00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "asterisk.h"
00034
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 377883 $")
00036
00037 #include "asterisk/_private.h"
00038 #include "asterisk/stun.h"
00039 #include "asterisk/cli.h"
00040 #include "asterisk/utils.h"
00041 #include "asterisk/channel.h"
00042
00043 static int stundebug;
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 typedef struct { unsigned int id[4]; } __attribute__((packed)) stun_trans_id;
00072
00073 struct stun_header {
00074 unsigned short msgtype;
00075 unsigned short msglen;
00076 stun_trans_id id;
00077 unsigned char ies[0];
00078 } __attribute__((packed));
00079
00080 struct stun_attr {
00081 unsigned short attr;
00082 unsigned short len;
00083 unsigned char value[0];
00084 } __attribute__((packed));
00085
00086
00087
00088
00089 struct stun_addr {
00090 unsigned char unused;
00091 unsigned char family;
00092 unsigned short port;
00093 unsigned int addr;
00094 } __attribute__((packed));
00095
00096
00097
00098
00099
00100
00101
00102
00103 #define STUN_BINDREQ 0x0001
00104 #define STUN_BINDRESP 0x0101
00105 #define STUN_BINDERR 0x0111
00106 #define STUN_SECREQ 0x0002
00107 #define STUN_SECRESP 0x0102
00108 #define STUN_SECERR 0x0112
00109
00110
00111
00112
00113 #define STUN_MAPPED_ADDRESS 0x0001
00114 #define STUN_RESPONSE_ADDRESS 0x0002
00115 #define STUN_CHANGE_REQUEST 0x0003
00116 #define STUN_SOURCE_ADDRESS 0x0004
00117 #define STUN_CHANGED_ADDRESS 0x0005
00118 #define STUN_USERNAME 0x0006
00119 #define STUN_PASSWORD 0x0007
00120 #define STUN_MESSAGE_INTEGRITY 0x0008
00121 #define STUN_ERROR_CODE 0x0009
00122 #define STUN_UNKNOWN_ATTRIBUTES 0x000a
00123 #define STUN_REFLECTED_FROM 0x000b
00124
00125
00126 static const char *stun_msg2str(int msg)
00127 {
00128 switch (msg) {
00129 case STUN_BINDREQ:
00130 return "Binding Request";
00131 case STUN_BINDRESP:
00132 return "Binding Response";
00133 case STUN_BINDERR:
00134 return "Binding Error Response";
00135 case STUN_SECREQ:
00136 return "Shared Secret Request";
00137 case STUN_SECRESP:
00138 return "Shared Secret Response";
00139 case STUN_SECERR:
00140 return "Shared Secret Error Response";
00141 }
00142 return "Non-RFC3489 Message";
00143 }
00144
00145
00146 static const char *stun_attr2str(int msg)
00147 {
00148 switch (msg) {
00149 case STUN_MAPPED_ADDRESS:
00150 return "Mapped Address";
00151 case STUN_RESPONSE_ADDRESS:
00152 return "Response Address";
00153 case STUN_CHANGE_REQUEST:
00154 return "Change Request";
00155 case STUN_SOURCE_ADDRESS:
00156 return "Source Address";
00157 case STUN_CHANGED_ADDRESS:
00158 return "Changed Address";
00159 case STUN_USERNAME:
00160 return "Username";
00161 case STUN_PASSWORD:
00162 return "Password";
00163 case STUN_MESSAGE_INTEGRITY:
00164 return "Message Integrity";
00165 case STUN_ERROR_CODE:
00166 return "Error Code";
00167 case STUN_UNKNOWN_ATTRIBUTES:
00168 return "Unknown Attributes";
00169 case STUN_REFLECTED_FROM:
00170 return "Reflected From";
00171 }
00172 return "Non-RFC3489 Attribute";
00173 }
00174
00175
00176 struct stun_state {
00177 const char *username;
00178 const char *password;
00179 };
00180
00181 static int stun_process_attr(struct stun_state *state, struct stun_attr *attr)
00182 {
00183 if (stundebug)
00184 ast_verbose("Found STUN Attribute %s (%04x), length %d\n",
00185 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
00186 switch (ntohs(attr->attr)) {
00187 case STUN_USERNAME:
00188 state->username = (const char *) (attr->value);
00189 break;
00190 case STUN_PASSWORD:
00191 state->password = (const char *) (attr->value);
00192 break;
00193 default:
00194 if (stundebug)
00195 ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n",
00196 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
00197 }
00198 return 0;
00199 }
00200
00201
00202 static void append_attr_string(struct stun_attr **attr, int attrval, const char *s, int *len, int *left)
00203 {
00204 int size = sizeof(**attr) + strlen(s);
00205 if (*left > size) {
00206 (*attr)->attr = htons(attrval);
00207 (*attr)->len = htons(strlen(s));
00208 memcpy((*attr)->value, s, strlen(s));
00209 (*attr) = (struct stun_attr *)((*attr)->value + strlen(s));
00210 *len += size;
00211 *left -= size;
00212 }
00213 }
00214
00215
00216 static void append_attr_address(struct stun_attr **attr, int attrval, struct sockaddr_in *sin, int *len, int *left)
00217 {
00218 int size = sizeof(**attr) + 8;
00219 struct stun_addr *addr;
00220 if (*left > size) {
00221 (*attr)->attr = htons(attrval);
00222 (*attr)->len = htons(8);
00223 addr = (struct stun_addr *)((*attr)->value);
00224 addr->unused = 0;
00225 addr->family = 0x01;
00226 addr->port = sin->sin_port;
00227 addr->addr = sin->sin_addr.s_addr;
00228 (*attr) = (struct stun_attr *)((*attr)->value + 8);
00229 *len += size;
00230 *left -= size;
00231 }
00232 }
00233
00234
00235 static int stun_send(int s, struct sockaddr_in *dst, struct stun_header *resp)
00236 {
00237 return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0,
00238 (struct sockaddr *)dst, sizeof(*dst));
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 static int stun_id_cmp(stun_trans_id *left, stun_trans_id *right)
00252 {
00253 return memcmp(left, right, sizeof(*left));
00254 }
00255
00256
00257 static void stun_req_id(struct stun_header *req)
00258 {
00259 int x;
00260 for (x = 0; x < 4; x++)
00261 req->id.id[x] = ast_random();
00262 }
00263
00264 int ast_stun_handle_packet(int s, struct sockaddr_in *src, unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
00265 {
00266 struct stun_header *hdr = (struct stun_header *)data;
00267 struct stun_attr *attr;
00268 struct stun_state st;
00269 int ret = AST_STUN_IGNORE;
00270 int x;
00271
00272
00273
00274
00275
00276 if (len < sizeof(struct stun_header)) {
00277 ast_debug(1, "Runt STUN packet (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header));
00278 return -1;
00279 }
00280 len -= sizeof(struct stun_header);
00281 data += sizeof(struct stun_header);
00282 x = ntohs(hdr->msglen);
00283 if (stundebug)
00284 ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), x);
00285 if (x > len) {
00286 ast_debug(1, "Scrambled STUN packet length (got %d, expecting %d)\n", x, (int)len);
00287 } else
00288 len = x;
00289 memset(&st, 0, sizeof(st));
00290 while (len) {
00291 if (len < sizeof(struct stun_attr)) {
00292 ast_debug(1, "Runt Attribute (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr));
00293 break;
00294 }
00295 attr = (struct stun_attr *)data;
00296
00297 x = ntohs(attr->len) + sizeof(struct stun_attr);
00298 if (x > len) {
00299 ast_debug(1, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (int)len);
00300 break;
00301 }
00302 if (stun_cb)
00303 stun_cb(attr, arg);
00304 if (stun_process_attr(&st, attr)) {
00305 ast_debug(1, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr));
00306 break;
00307 }
00308
00309
00310
00311 attr->attr = 0;
00312 data += x;
00313 len -= x;
00314 }
00315
00316
00317
00318
00319
00320
00321 *data = '\0';
00322
00323
00324
00325
00326 if (len == 0) {
00327 unsigned char respdata[1024];
00328 struct stun_header *resp = (struct stun_header *)respdata;
00329 int resplen = 0;
00330 int respleft = sizeof(respdata) - sizeof(struct stun_header);
00331 char combined[33];
00332
00333 resp->id = hdr->id;
00334 resp->msgtype = 0;
00335 resp->msglen = 0;
00336 attr = (struct stun_attr *)resp->ies;
00337 switch (ntohs(hdr->msgtype)) {
00338 case STUN_BINDREQ:
00339 if (stundebug)
00340 ast_verbose("STUN Bind Request, username: %s\n",
00341 st.username ? st.username : "<none>");
00342 if (st.username) {
00343 append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft);
00344 snprintf(combined, sizeof(combined), "%16s%16s", st.username + 16, st.username);
00345 }
00346
00347 append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft);
00348 resp->msglen = htons(resplen);
00349 resp->msgtype = htons(STUN_BINDRESP);
00350 stun_send(s, src, resp);
00351 ast_stun_request(s, src, combined, NULL);
00352 ret = AST_STUN_ACCEPT;
00353 break;
00354 default:
00355 if (stundebug)
00356 ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype)));
00357 }
00358 }
00359 return ret;
00360 }
00361
00362
00363
00364
00365
00366 static int stun_get_mapped(struct stun_attr *attr, void *arg)
00367 {
00368 struct stun_addr *addr = (struct stun_addr *)(attr + 1);
00369 struct sockaddr_in *sa = (struct sockaddr_in *)arg;
00370
00371 if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8)
00372 return 1;
00373 sa->sin_port = addr->port;
00374 sa->sin_addr.s_addr = addr->addr;
00375 return 0;
00376 }
00377
00378 int ast_stun_request(int s, struct sockaddr_in *dst,
00379 const char *username, struct sockaddr_in *answer)
00380 {
00381 struct stun_header *req;
00382 struct stun_header *rsp;
00383 unsigned char req_buf[1024];
00384 unsigned char rsp_buf[1024];
00385 int reqlen, reqleft;
00386 struct stun_attr *attr;
00387 int res = -1;
00388 int retry;
00389
00390 if (answer) {
00391
00392 memset(answer, 0, sizeof(struct sockaddr_in));
00393 }
00394
00395
00396 req = (struct stun_header *) req_buf;
00397 stun_req_id(req);
00398 reqlen = 0;
00399 reqleft = sizeof(req_buf) - sizeof(struct stun_header);
00400 req->msgtype = 0;
00401 req->msglen = 0;
00402 attr = (struct stun_attr *) req->ies;
00403 if (username) {
00404 append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft);
00405 }
00406 req->msglen = htons(reqlen);
00407 req->msgtype = htons(STUN_BINDREQ);
00408
00409 for (retry = 0; retry++ < 3;) {
00410
00411 struct sockaddr_in src;
00412 socklen_t srclen;
00413
00414
00415 res = stun_send(s, dst, req);
00416 if (res < 0) {
00417 ast_debug(1, "stun_send try %d failed: %s\n", retry, strerror(errno));
00418 break;
00419 }
00420 if (!answer) {
00421
00422 res = 0;
00423 break;
00424 }
00425
00426 try_again:
00427
00428 {
00429 struct pollfd pfds = { .fd = s, .events = POLLIN };
00430
00431 res = ast_poll(&pfds, 1, 3000);
00432 if (res < 0) {
00433
00434 continue;
00435 }
00436 if (!res) {
00437
00438 res = 1;
00439 continue;
00440 }
00441 }
00442
00443
00444 memset(&src, 0, sizeof(src));
00445 srclen = sizeof(src);
00446
00447
00448
00449 res = recvfrom(s, rsp_buf, sizeof(rsp_buf) - 1,
00450 0, (struct sockaddr *) &src, &srclen);
00451 if (res < 0) {
00452 ast_debug(1, "recvfrom try %d failed: %s\n", retry, strerror(errno));
00453 break;
00454 }
00455
00456
00457 rsp = (struct stun_header *) rsp_buf;
00458 if (ast_stun_handle_packet(s, &src, rsp_buf, res, stun_get_mapped, answer)
00459 || (rsp->msgtype != htons(STUN_BINDRESP)
00460 && rsp->msgtype != htons(STUN_BINDERR))
00461 || stun_id_cmp(&req->id, &rsp->id)) {
00462
00463 memset(answer, 0, sizeof(struct sockaddr_in));
00464
00465
00466 goto try_again;
00467 }
00468
00469 res = 0;
00470 break;
00471 }
00472 return res;
00473 }
00474
00475 static char *handle_cli_stun_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00476 {
00477 switch (cmd) {
00478 case CLI_INIT:
00479 e->command = "stun set debug {on|off}";
00480 e->usage =
00481 "Usage: stun set debug {on|off}\n"
00482 " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
00483 " debugging\n";
00484 return NULL;
00485 case CLI_GENERATE:
00486 return NULL;
00487 }
00488
00489 if (a->argc != e->args)
00490 return CLI_SHOWUSAGE;
00491
00492 if (!strncasecmp(a->argv[e->args-1], "on", 2))
00493 stundebug = 1;
00494 else if (!strncasecmp(a->argv[e->args-1], "off", 3))
00495 stundebug = 0;
00496 else
00497 return CLI_SHOWUSAGE;
00498
00499 ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
00500 return CLI_SUCCESS;
00501 }
00502
00503 static struct ast_cli_entry cli_stun[] = {
00504 AST_CLI_DEFINE(handle_cli_stun_set_debug, "Enable/Disable STUN debugging"),
00505 };
00506
00507 static void stun_shutdown(void)
00508 {
00509 ast_cli_unregister_multiple(cli_stun, sizeof(cli_stun) / sizeof(struct ast_cli_entry));
00510 }
00511
00512
00513 void ast_stun_init(void)
00514 {
00515 ast_cli_register_multiple(cli_stun, sizeof(cli_stun) / sizeof(struct ast_cli_entry));
00516 ast_register_atexit(stun_shutdown);
00517 }