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