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: 413586 $")
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)), (unsigned)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)), (unsigned)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)), (unsigned)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)), (unsigned)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
00332 resp->id = hdr->id;
00333 resp->msgtype = 0;
00334 resp->msglen = 0;
00335 attr = (struct stun_attr *)resp->ies;
00336 switch (ntohs(hdr->msgtype)) {
00337 case STUN_BINDREQ:
00338 if (stundebug)
00339 ast_verbose("STUN Bind Request, username: %s\n",
00340 st.username ? st.username : "<none>");
00341 if (st.username)
00342 append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft);
00343 append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft);
00344 resp->msglen = htons(resplen);
00345 resp->msgtype = htons(STUN_BINDRESP);
00346 stun_send(s, src, resp);
00347 ret = AST_STUN_ACCEPT;
00348 break;
00349 default:
00350 if (stundebug)
00351 ast_verbose("Dunno what to do with STUN message %04x (%s)\n", (unsigned)ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype)));
00352 }
00353 }
00354 return ret;
00355 }
00356
00357
00358
00359
00360
00361 static int stun_get_mapped(struct stun_attr *attr, void *arg)
00362 {
00363 struct stun_addr *addr = (struct stun_addr *)(attr + 1);
00364 struct sockaddr_in *sa = (struct sockaddr_in *)arg;
00365
00366 if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8)
00367 return 1;
00368 sa->sin_port = addr->port;
00369 sa->sin_addr.s_addr = addr->addr;
00370 return 0;
00371 }
00372
00373 int ast_stun_request(int s, struct sockaddr_in *dst,
00374 const char *username, struct sockaddr_in *answer)
00375 {
00376 struct stun_header *req;
00377 struct stun_header *rsp;
00378 unsigned char req_buf[1024];
00379 unsigned char rsp_buf[1024];
00380 int reqlen, reqleft;
00381 struct stun_attr *attr;
00382 int res = -1;
00383 int retry;
00384
00385 if (answer) {
00386
00387 memset(answer, 0, sizeof(struct sockaddr_in));
00388 }
00389
00390
00391 req = (struct stun_header *) req_buf;
00392 stun_req_id(req);
00393 reqlen = 0;
00394 reqleft = sizeof(req_buf) - sizeof(struct stun_header);
00395 req->msgtype = 0;
00396 req->msglen = 0;
00397 attr = (struct stun_attr *) req->ies;
00398 if (username) {
00399 append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft);
00400 }
00401 req->msglen = htons(reqlen);
00402 req->msgtype = htons(STUN_BINDREQ);
00403
00404 for (retry = 0; retry++ < 3;) {
00405
00406 struct sockaddr_in src;
00407 socklen_t srclen;
00408
00409
00410 res = stun_send(s, dst, req);
00411 if (res < 0) {
00412 ast_debug(1, "stun_send try %d failed: %s\n", retry, strerror(errno));
00413 break;
00414 }
00415 if (!answer) {
00416
00417 res = 0;
00418 break;
00419 }
00420
00421 try_again:
00422
00423 {
00424 struct pollfd pfds = { .fd = s, .events = POLLIN };
00425
00426 res = ast_poll(&pfds, 1, 3000);
00427 if (res < 0) {
00428
00429 continue;
00430 }
00431 if (!res) {
00432
00433 res = 1;
00434 continue;
00435 }
00436 }
00437
00438
00439 memset(&src, 0, sizeof(src));
00440 srclen = sizeof(src);
00441
00442
00443
00444 res = recvfrom(s, rsp_buf, sizeof(rsp_buf) - 1,
00445 0, (struct sockaddr *) &src, &srclen);
00446 if (res < 0) {
00447 ast_debug(1, "recvfrom try %d failed: %s\n", retry, strerror(errno));
00448 break;
00449 }
00450
00451
00452 rsp = (struct stun_header *) rsp_buf;
00453 if (ast_stun_handle_packet(s, &src, rsp_buf, res, stun_get_mapped, answer)
00454 || (rsp->msgtype != htons(STUN_BINDRESP)
00455 && rsp->msgtype != htons(STUN_BINDERR))
00456 || stun_id_cmp(&req->id, &rsp->id)) {
00457
00458 memset(answer, 0, sizeof(struct sockaddr_in));
00459
00460
00461 goto try_again;
00462 }
00463
00464 res = 0;
00465 break;
00466 }
00467 return res;
00468 }
00469
00470 static char *handle_cli_stun_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00471 {
00472 switch (cmd) {
00473 case CLI_INIT:
00474 e->command = "stun set debug {on|off}";
00475 e->usage =
00476 "Usage: stun set debug {on|off}\n"
00477 " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
00478 " debugging\n";
00479 return NULL;
00480 case CLI_GENERATE:
00481 return NULL;
00482 }
00483
00484 if (a->argc != e->args)
00485 return CLI_SHOWUSAGE;
00486
00487 if (!strncasecmp(a->argv[e->args-1], "on", 2))
00488 stundebug = 1;
00489 else if (!strncasecmp(a->argv[e->args-1], "off", 3))
00490 stundebug = 0;
00491 else
00492 return CLI_SHOWUSAGE;
00493
00494 ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
00495 return CLI_SUCCESS;
00496 }
00497
00498 static struct ast_cli_entry cli_stun[] = {
00499 AST_CLI_DEFINE(handle_cli_stun_set_debug, "Enable/Disable STUN debugging"),
00500 };
00501
00502 static void stun_shutdown(void)
00503 {
00504 ast_cli_unregister_multiple(cli_stun, sizeof(cli_stun) / sizeof(struct ast_cli_entry));
00505 }
00506
00507
00508 void ast_stun_init(void)
00509 {
00510 ast_cli_register_multiple(cli_stun, sizeof(cli_stun) / sizeof(struct ast_cli_entry));
00511 ast_register_atexit(stun_shutdown);
00512 }