Asterisk - The Open Source Telephony Project GIT-master-a358458
stun.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 1999 - 2008, Digium, Inc.
5 *
6 * Mark Spencer <markster@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*!
20 * \file
21 *
22 * \brief STUN Support
23 *
24 * \author Mark Spencer <markster@digium.com>
25 *
26 * \note STUN is defined in RFC 3489.
27 */
28
29/*** MODULEINFO
30 <support_level>core</support_level>
31 ***/
32
33#include "asterisk.h"
34
35#include "asterisk/logger.h"
37#include "asterisk/_private.h"
38#include "asterisk/stun.h"
39#include "asterisk/cli.h"
40#include "asterisk/utils.h"
41#include "asterisk/channel.h"
42
43/*!
44 * \brief STUN support code
45 *
46 * This code provides some support for doing STUN transactions.
47 * Eventually it should be moved elsewhere as other protocols
48 * than RTP can benefit from it - e.g. SIP.
49 * STUN is described in RFC3489 and it is based on the exchange
50 * of UDP packets between a client and one or more servers to
51 * determine the externally visible address (and port) of the client
52 * once it has gone through the NAT boxes that connect it to the
53 * outside.
54 * The simplest request packet is just the header defined in
55 * struct stun_header, and from the response we may just look at
56 * one attribute, STUN_MAPPED_ADDRESS, that we find in the response.
57 * By doing more transactions with different server addresses we
58 * may determine more about the behaviour of the NAT boxes, of
59 * course - the details are in the RFC.
60 *
61 * All STUN packets start with a simple header made of a type,
62 * length (excluding the header) and a 16-byte random transaction id.
63 * Following the header we may have zero or more attributes, each
64 * structured as a type, length and a value (whose format depends
65 * on the type, but often contains addresses).
66 * Of course all fields are in network format.
67 */
68
69typedef struct { unsigned int id[4]; } __attribute__((packed)) stun_trans_id;
70
72 unsigned short msgtype;
73 unsigned short msglen;
75 unsigned char ies[0];
76} __attribute__((packed));
77
78struct stun_attr {
79 unsigned short attr;
80 unsigned short len;
81 unsigned char value[0];
82} __attribute__((packed));
83
84/*
85 * The format normally used for addresses carried by STUN messages.
86 */
87struct stun_addr {
88 unsigned char unused;
89 unsigned char family;
90 unsigned short port;
91 unsigned int addr;
92} __attribute__((packed));
93
94/*! \brief STUN message types
95 * 'BIND' refers to transactions used to determine the externally
96 * visible addresses. 'SEC' refers to transactions used to establish
97 * a session key for subsequent requests.
98 * 'SEC' functionality is not supported here.
99 */
100
101#define STUN_BINDREQ 0x0001
102#define STUN_BINDRESP 0x0101
103#define STUN_BINDERR 0x0111
104#define STUN_SECREQ 0x0002
105#define STUN_SECRESP 0x0102
106#define STUN_SECERR 0x0112
107
108/*! \brief Basic attribute types in stun messages.
109 * Messages can also contain custom attributes (codes above 0x7fff)
110 */
111#define STUN_MAPPED_ADDRESS 0x0001
112#define STUN_RESPONSE_ADDRESS 0x0002
113#define STUN_CHANGE_REQUEST 0x0003
114#define STUN_SOURCE_ADDRESS 0x0004
115#define STUN_CHANGED_ADDRESS 0x0005
116#define STUN_USERNAME 0x0006
117#define STUN_PASSWORD 0x0007
118#define STUN_MESSAGE_INTEGRITY 0x0008
119#define STUN_ERROR_CODE 0x0009
120#define STUN_UNKNOWN_ATTRIBUTES 0x000a
121#define STUN_REFLECTED_FROM 0x000b
122
123#define STUN_MAX_RETRIES 3
124
125/*! \brief helper function to print message names */
126static const char *stun_msg2str(int msg)
127{
128 switch (msg) {
129 case STUN_BINDREQ:
130 return "Binding Request";
131 case STUN_BINDRESP:
132 return "Binding Response";
133 case STUN_BINDERR:
134 return "Binding Error Response";
135 case STUN_SECREQ:
136 return "Shared Secret Request";
137 case STUN_SECRESP:
138 return "Shared Secret Response";
139 case STUN_SECERR:
140 return "Shared Secret Error Response";
141 }
142 return "Non-RFC3489 Message";
143}
144
145/*! \brief helper function to print attribute names */
146static const char *stun_attr2str(int msg)
147{
148 switch (msg) {
150 return "Mapped Address";
152 return "Response Address";
154 return "Change Request";
156 return "Source Address";
158 return "Changed Address";
159 case STUN_USERNAME:
160 return "Username";
161 case STUN_PASSWORD:
162 return "Password";
164 return "Message Integrity";
165 case STUN_ERROR_CODE:
166 return "Error Code";
168 return "Unknown Attributes";
170 return "Reflected From";
171 }
172 return "Non-RFC3489 Attribute";
173}
174
175/*! \brief here we store credentials extracted from a message */
177 const char *username;
178 const char *password;
179};
180
181static int stun_process_attr(struct stun_state *state, struct stun_attr *attr)
182{
184 ast_verbose("Found STUN Attribute %s (%04x), length %d\n",
185 stun_attr2str(ntohs(attr->attr)), (unsigned)ntohs(attr->attr), ntohs(attr->len));
186 }
187 switch (ntohs(attr->attr)) {
188 case STUN_USERNAME:
189 state->username = (const char *) (attr->value);
190 break;
191 case STUN_PASSWORD:
192 state->password = (const char *) (attr->value);
193 break;
194 default:
196 ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n",
197 stun_attr2str(ntohs(attr->attr)), (unsigned)ntohs(attr->attr), ntohs(attr->len));
198 }
199 }
200
201 return 0;
202}
203
204/*! \brief append a string to an STUN message */
205static void append_attr_string(struct stun_attr **attr, int attrval, const char *s, int *len, int *left)
206{
207 int str_length = strlen(s);
208 int attr_length = str_length + ((~(str_length - 1)) & 0x3);
209 int size = sizeof(**attr) + attr_length;
210 if (*left > size) {
211 (*attr)->attr = htons(attrval);
212 (*attr)->len = htons(attr_length);
213 memcpy((*attr)->value, s, str_length);
214 memset((*attr)->value + str_length, 0, attr_length - str_length);
215 (*attr) = (struct stun_attr *)((*attr)->value + attr_length);
216 *len += size;
217 *left -= size;
218 }
219}
220
221/*! \brief append an address to an STUN message */
222static void append_attr_address(struct stun_attr **attr, int attrval, struct sockaddr_in *sin, int *len, int *left)
223{
224 int size = sizeof(**attr) + 8;
225 struct stun_addr *addr;
226 if (*left > size) {
227 (*attr)->attr = htons(attrval);
228 (*attr)->len = htons(8);
229 addr = (struct stun_addr *)((*attr)->value);
230 addr->unused = 0;
231 addr->family = 0x01;
232 addr->port = sin->sin_port;
233 addr->addr = sin->sin_addr.s_addr;
234 (*attr) = (struct stun_attr *)((*attr)->value + 8);
235 *len += size;
236 *left -= size;
237 }
238}
239
240static void handle_stun_timeout(int retry, struct sockaddr_in *dst)
241{
242 char *stun_destination = "";
243 if (dst) {
244 ast_asprintf(&stun_destination, "to '%s' ", ast_inet_ntoa(dst->sin_addr));
245 }
246 if (retry < STUN_MAX_RETRIES) {
248 "Attempt %d to send STUN request %stimed out.\n",
249 retry,
250 stun_destination);
251 } else {
253 "Attempt %d to send STUN request %stimed out. "
254 "Check that the server address is correct and reachable.\n",
255 retry,
256 stun_destination);
257 }
258 if (dst) {
259 ast_free(stun_destination);
260 }
261}
262
263/*! \brief wrapper to send an STUN message */
264static int stun_send(int s, struct sockaddr_in *dst, struct stun_header *resp)
265{
266 return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0,
267 (struct sockaddr *)dst, sizeof(*dst));
268}
269
270/*!
271 * \internal
272 * \brief Compare the STUN transaction IDs.
273 *
274 * \param left Transaction ID.
275 * \param right Transaction ID.
276 *
277 * \retval 0 if match.
278 * \retval non-zero if not match.
279 */
280static int stun_id_cmp(stun_trans_id *left, stun_trans_id *right)
281{
282 return memcmp(left, right, sizeof(*left));
283}
284
285/*! \brief helper function to generate a random request id */
286static void stun_req_id(struct stun_header *req)
287{
288 int x;
289 for (x = 0; x < 4; x++)
290 req->id.id[x] = ast_random();
291}
292
293int ast_stun_handle_packet(int s, struct sockaddr_in *src, unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
294{
295 struct stun_header *hdr = (struct stun_header *)data;
296 struct stun_attr *attr;
297 struct stun_state st;
298 int ret = AST_STUN_IGNORE;
299 int x;
300
301 /* On entry, 'len' is the length of the udp payload. After the
302 * initial checks it becomes the size of unprocessed options,
303 * while 'data' is advanced accordingly.
304 */
305 if (len < sizeof(struct stun_header)) {
306 ast_debug_stun(1, "Runt STUN packet (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header));
307 return -1;
308 }
309 len -= sizeof(struct stun_header);
310 data += sizeof(struct stun_header);
311 x = ntohs(hdr->msglen); /* len as advertised in the message */
313 ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), (unsigned)ntohs(hdr->msgtype), x);
314 if (x > len) {
315 ast_debug_stun(1, "Scrambled STUN packet length (got %d, expecting %d)\n", x, (int)len);
316 } else
317 len = x;
318 memset(&st, 0, sizeof(st));
319 while (len) {
320 if (len < sizeof(struct stun_attr)) {
321 ast_debug_stun(1, "Runt Attribute (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr));
322 break;
323 }
324 attr = (struct stun_attr *)data;
325 /* compute total attribute length */
326 x = ntohs(attr->len) + sizeof(struct stun_attr);
327 if (x > len) {
328 ast_debug_stun(1, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (int)len);
329 break;
330 }
331 if (stun_cb)
332 stun_cb(attr, arg);
333 if (stun_process_attr(&st, attr)) {
334 ast_debug_stun(1, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), (unsigned)ntohs(attr->attr));
335 break;
336 }
337 /* Clear attribute id: in case previous entry was a string,
338 * this will act as the terminator for the string.
339 */
340 attr->attr = 0;
341 data += x;
342 len -= x;
343 }
344 /* Null terminate any string.
345 * XXX NOTE, we write past the size of the buffer passed by the
346 * caller, so this is potentially dangerous. The only thing that
347 * saves us is that usually we read the incoming message in a
348 * much larger buffer in the struct ast_rtp
349 */
350 *data = '\0';
351
352 /* Now prepare to generate a reply, which at the moment is done
353 * only for properly formed (len == 0) STUN_BINDREQ messages.
354 */
355 if (len == 0) {
356 unsigned char respdata[1024];
357 struct stun_header *resp = (struct stun_header *)respdata;
358 int resplen = 0; /* len excluding header */
359 int respleft = sizeof(respdata) - sizeof(struct stun_header);
360 char combined[33];
361
362 resp->id = hdr->id;
363 resp->msgtype = 0;
364 resp->msglen = 0;
365 attr = (struct stun_attr *)resp->ies;
366 switch (ntohs(hdr->msgtype)) {
367 case STUN_BINDREQ:
369 ast_verbose("STUN Bind Request, username: %s\n",
370 st.username ? st.username : "<none>");
371 if (st.username) {
372 append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft);
373 /*
374 * For Google Voice, the stun username is made up of the local
375 * and remote usernames, each being fixed at 16 bytes. We have
376 * to swap the two at this point.
377 */
378 snprintf(combined, 17, "%16s", st.username + 16);
379 snprintf(combined + 16, 17, "%16s", st.username);
380 } else {
381 combined[0] = '\0';
382 }
383
384 append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft);
385 resp->msglen = htons(resplen);
386 resp->msgtype = htons(STUN_BINDRESP);
387 stun_send(s, src, resp);
388 ast_stun_request(s, src, combined, NULL);
389 ret = AST_STUN_ACCEPT;
390 break;
391 default:
393 ast_verbose("Dunno what to do with STUN message %04x (%s)\n", (unsigned)ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype)));
394 }
395 }
396 return ret;
397}
398
399/*! \brief Extract the STUN_MAPPED_ADDRESS from the stun response.
400 * This is used as a callback for stun_handle_response
401 * when called from ast_stun_request.
402 */
403static int stun_get_mapped(struct stun_attr *attr, void *arg)
404{
405 struct stun_addr *addr = (struct stun_addr *)(attr + 1);
406 struct sockaddr_in *sa = (struct sockaddr_in *)arg;
407
408 if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8)
409 return 1; /* not us. */
410 sa->sin_port = addr->port;
411 sa->sin_addr.s_addr = addr->addr;
412 return 0;
413}
414
415int ast_stun_request(int s, struct sockaddr_in *dst,
416 const char *username, struct sockaddr_in *answer)
417{
418 struct stun_header *req;
419 struct stun_header *rsp;
420 unsigned char req_buf[1024];
421 unsigned char rsp_buf[1024];
422 int reqlen, reqleft;
423 struct stun_attr *attr;
424 int res = -1;
425 int retry;
426
427 if (answer) {
428 /* Always clear answer in case the request fails. */
429 memset(answer, 0, sizeof(struct sockaddr_in));
430 }
431
432 /* Create STUN bind request */
433 req = (struct stun_header *) req_buf;
434 stun_req_id(req);
435 reqlen = 0;
436 reqleft = sizeof(req_buf) - sizeof(struct stun_header);
437 attr = (struct stun_attr *) req->ies;
438 if (username) {
439 append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft);
440 }
441 req->msglen = htons(reqlen);
442 req->msgtype = htons(STUN_BINDREQ);
443
444 for (retry = 0; retry++ < STUN_MAX_RETRIES;) { /* XXX make retries configurable */
445 /* send request, possibly wait for reply */
446 struct sockaddr_in src;
447 socklen_t srclen;
448 struct timeval start;
449
450 /* Send STUN message. */
451 res = stun_send(s, dst, req);
452 if (res < 0) {
453 ast_debug_stun(1, "stun_send try %d failed: %s\n", retry, strerror(errno));
454 break;
455 }
456 if (!answer) {
457 /* Successful send since we don't care about any response. */
458 res = 0;
459 break;
460 }
461
462 start = ast_tvnow();
463try_again:
464 /* Wait for response. */
465 {
466 struct pollfd pfds = { .fd = s, .events = POLLIN };
467 int ms;
468
469 ms = ast_remaining_ms(start, 3000);
470 if (ms <= 0) {
471 /* No response, timeout */
472 handle_stun_timeout(retry, dst);
473 res = 1;
474 continue;
475 }
476 res = ast_poll(&pfds, 1, ms);
477 if (res < 0) {
478 /* Error */
479 continue;
480 }
481 if (!res) {
482 /* No response, timeout */
483 handle_stun_timeout(retry, dst);
484 res = 1;
485 continue;
486 }
487 }
488
489 /* Read STUN response. */
490 memset(&src, 0, sizeof(src));
491 srclen = sizeof(src);
492 /* XXX pass sizeof(rsp_buf) - 1 in the size, because stun_handle_packet might
493 * write past the end of the buffer.
494 */
495 res = recvfrom(s, rsp_buf, sizeof(rsp_buf) - 1,
496 0, (struct sockaddr *) &src, &srclen);
497 if (res < 0) {
498 ast_debug_stun(1, "recvfrom try %d failed: %s\n", retry, strerror(errno));
499 break;
500 }
501
502 /* Process the STUN response. */
503 rsp = (struct stun_header *) rsp_buf;
504 if (ast_stun_handle_packet(s, &src, rsp_buf, res, stun_get_mapped, answer)
505 || (rsp->msgtype != htons(STUN_BINDRESP)
506 && rsp->msgtype != htons(STUN_BINDERR))
507 || stun_id_cmp(&req->id, &rsp->id)) {
508 /* Bad STUN packet, not right type, or transaction ID did not match. */
509 memset(answer, 0, sizeof(struct sockaddr_in));
510
511 /* Was not a resonse to our request. */
512 goto try_again;
513 }
514 /* Success. answer contains the external address if available. */
515 res = 0;
516 break;
517 }
518 return res;
519}
520
521static char *handle_cli_stun_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
522{
523 switch (cmd) {
524 case CLI_INIT:
525 e->command = "stun set debug {on|off}";
526 e->usage =
527 "Usage: stun set debug {on|off}\n"
528 " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
529 " debugging\n";
530 return NULL;
531 case CLI_GENERATE:
532 return NULL;
533 }
534
535 if (a->argc != e->args)
536 return CLI_SHOWUSAGE;
537
538 if (!strncasecmp(a->argv[e->args-1], "on", 2))
540 else if (!strncasecmp(a->argv[e->args-1], "off", 3))
542 else
543 return CLI_SHOWUSAGE;
544
545 ast_cli(a->fd, "STUN Debugging %s\n", ast_debug_stun_packet_is_allowed ? "Enabled" : "Disabled");
546 return CLI_SUCCESS;
547}
548
549static struct ast_cli_entry cli_stun[] = {
550 AST_CLI_DEFINE(handle_cli_stun_set_debug, "Enable/Disable STUN debugging"),
551};
552
553static uintmax_t debug_category_stun_id;
554
556{
558}
559
561
563{
565}
566
567static void stun_shutdown(void)
568{
570
573}
574
575/*! \brief Initialize the STUN system in Asterisk */
577{
578 ast_cli_register_multiple(cli_stun, sizeof(cli_stun) / sizeof(struct ast_cli_entry));
581
582 /*
583 * Normnally a core module should call ast_register_cleanup
584 * which doesn't run if any module fails to unload. This
585 * prevents resources being pulled out from under a running
586 * module and ppossibly causing a segfault. In this case however,
587 * the only thing we're cleaning up is the cli command and
588 * the registers of the debug categories.
589 */
591
592}
Prototypes for public functions only of internal interest,.
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
Definition: clicompat.c:13
#define ast_free(a)
Definition: astmm.h:180
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define ast_log
Definition: astobj2.c:42
static int answer(void *data)
Definition: chan_pjsip.c:683
General Asterisk PBX channel definitions.
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2206
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Support for logging to various files, console and syslog Configuration in file logger....
#define LOG_NOTICE
#define LOG_WARNING
#define AST_LOG_CATEGORY_DISABLED
uintmax_t ast_debug_category_register(const char *name)
Register a debug level logger category.
#define AST_LOG_CATEGORY_ENABLED
int ast_debug_category_unregister(const char *name)
Un-register a debug level logger category.
int ast_debug_category_set_sublevel(const char *name, int sublevel)
Set the debug category's sublevel.
int errno
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: utils.c:928
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
#define NULL
Definition: resample.c:96
descriptor for a cli entry.
Definition: cli.h:171
int args
This gets set in ast_cli_register()
Definition: cli.h:185
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
Definition: stun.c:87
unsigned char family
Definition: stun.c:89
unsigned int addr
Definition: stun.c:91
unsigned short port
Definition: stun.c:90
unsigned char unused
Definition: stun.c:88
Definition: stun.c:78
unsigned short len
Definition: stun.c:80
unsigned short attr
Definition: stun.c:79
unsigned char value[0]
Definition: stun.c:81
unsigned char ies[0]
Definition: stun.c:75
unsigned short msgtype
Definition: stun.c:72
unsigned short msglen
Definition: stun.c:73
stun_trans_id id
Definition: stun.c:74
here we store credentials extracted from a message
Definition: stun.c:176
const char * password
Definition: stun.c:178
const char * username
Definition: stun.c:177
STUN support code.
Definition: stun.c:69
unsigned int id[4]
Definition: stun.c:69
static int stun_get_mapped(struct stun_attr *attr, void *arg)
Extract the STUN_MAPPED_ADDRESS from the stun response. This is used as a callback for stun_handle_re...
Definition: stun.c:403
#define STUN_MAX_RETRIES
Definition: stun.c:123
#define STUN_RESPONSE_ADDRESS
Definition: stun.c:112
static void stun_shutdown(void)
Definition: stun.c:567
static uintmax_t debug_category_stun_id
Definition: stun.c:553
static const char * stun_msg2str(int msg)
helper function to print message names
Definition: stun.c:126
uintmax_t ast_debug_category_stun_id(void)
Definition: stun.c:555
static void handle_stun_timeout(int retry, struct sockaddr_in *dst)
Definition: stun.c:240
#define STUN_CHANGED_ADDRESS
Definition: stun.c:115
#define STUN_BINDRESP
Definition: stun.c:102
#define STUN_PASSWORD
Definition: stun.c:117
#define STUN_SECERR
Definition: stun.c:106
int ast_stun_request(int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer)
Generic STUN request.
Definition: stun.c:415
void ast_stun_init(void)
Initialize the STUN system in Asterisk.
Definition: stun.c:576
#define STUN_MAPPED_ADDRESS
Basic attribute types in stun messages. Messages can also contain custom attributes (codes above 0x7f...
Definition: stun.c:111
int ast_stun_handle_packet(int s, struct sockaddr_in *src, unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
handle an incoming STUN message.
Definition: stun.c:293
#define STUN_SECRESP
Definition: stun.c:105
#define STUN_REFLECTED_FROM
Definition: stun.c:121
#define STUN_ERROR_CODE
Definition: stun.c:119
#define STUN_USERNAME
Definition: stun.c:116
static void append_attr_address(struct stun_attr **attr, int attrval, struct sockaddr_in *sin, int *len, int *left)
append an address to an STUN message
Definition: stun.c:222
static int stun_id_cmp(stun_trans_id *left, stun_trans_id *right)
Definition: stun.c:280
static char * handle_cli_stun_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: stun.c:521
#define STUN_SOURCE_ADDRESS
Definition: stun.c:114
#define STUN_SECREQ
Definition: stun.c:104
#define STUN_BINDERR
Definition: stun.c:103
static uintmax_t debug_category_stun_packet_id
Definition: stun.c:560
static const char * stun_attr2str(int msg)
helper function to print attribute names
Definition: stun.c:146
#define STUN_BINDREQ
STUN message types 'BIND' refers to transactions used to determine the externally visible addresses....
Definition: stun.c:101
uintmax_t ast_debug_category_stun_packet_id(void)
Definition: stun.c:562
static int stun_process_attr(struct stun_state *state, struct stun_attr *attr)
Definition: stun.c:181
static struct ast_cli_entry cli_stun[]
Definition: stun.c:549
#define STUN_UNKNOWN_ATTRIBUTES
Definition: stun.c:120
static void stun_req_id(struct stun_header *req)
helper function to generate a random request id
Definition: stun.c:286
#define STUN_MESSAGE_INTEGRITY
Definition: stun.c:118
static int stun_send(int s, struct sockaddr_in *dst, struct stun_header *resp)
wrapper to send an STUN message
Definition: stun.c:264
#define STUN_CHANGE_REQUEST
Definition: stun.c:113
static void append_attr_string(struct stun_attr **attr, int attrval, const char *s, int *len, int *left)
append a string to an STUN message
Definition: stun.c:205
STUN support.
#define ast_debug_stun(sublevel,...)
Log debug level STUN information.
Definition: stun.h:54
#define AST_LOG_CATEGORY_STUN_PACKET
Definition: stun.h:40
int() stun_cb_f(struct stun_attr *attr, void *arg)
callback type to be invoked on stun responses.
Definition: stun.h:95
@ AST_STUN_ACCEPT
Definition: stun.h:65
@ AST_STUN_IGNORE
Definition: stun.h:64
#define ast_debug_stun_packet_is_allowed
Definition: stun.h:58
#define AST_LOG_CATEGORY_STUN
Definition: stun.h:38
static struct test_val a
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:2281
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
Utility functions.
long int ast_random(void)
Definition: utils.c:2312