Asterisk - The Open Source Telephony Project GIT-master-7e7a603
Data Structures | Macros | Functions | Variables
stun.c File Reference

STUN Support. More...

#include "asterisk.h"
#include "asterisk/logger.h"
#include "asterisk/logger_category.h"
#include "asterisk/_private.h"
#include "asterisk/stun.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/channel.h"
Include dependency graph for stun.c:

Go to the source code of this file.

Data Structures

struct  stun_addr
 
struct  stun_attr
 
struct  stun_header
 
struct  stun_state
 here we store credentials extracted from a message More...
 
struct  stun_trans_id
 STUN support code. More...
 

Macros

#define STUN_BINDERR   0x0111
 
#define STUN_BINDREQ   0x0001
 STUN message types 'BIND' refers to transactions used to determine the externally visible addresses. 'SEC' refers to transactions used to establish a session key for subsequent requests. 'SEC' functionality is not supported here. More...
 
#define STUN_BINDRESP   0x0101
 
#define STUN_CHANGE_REQUEST   0x0003
 
#define STUN_CHANGED_ADDRESS   0x0005
 
#define STUN_ERROR_CODE   0x0009
 
#define STUN_MAPPED_ADDRESS   0x0001
 Basic attribute types in stun messages. Messages can also contain custom attributes (codes above 0x7fff) More...
 
#define STUN_MAX_RETRIES   3
 
#define STUN_MESSAGE_INTEGRITY   0x0008
 
#define STUN_PASSWORD   0x0007
 
#define STUN_REFLECTED_FROM   0x000b
 
#define STUN_RESPONSE_ADDRESS   0x0002
 
#define STUN_SECERR   0x0112
 
#define STUN_SECREQ   0x0002
 
#define STUN_SECRESP   0x0102
 
#define STUN_SOURCE_ADDRESS   0x0004
 
#define STUN_UNKNOWN_ATTRIBUTES   0x000a
 
#define STUN_USERNAME   0x0006
 

Functions

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 More...
 
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 More...
 
uintmax_t ast_debug_category_stun_id (void)
 
uintmax_t ast_debug_category_stun_packet_id (void)
 
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. More...
 
void ast_stun_init (void)
 Initialize the STUN system in Asterisk. More...
 
int ast_stun_request (int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer)
 Generic STUN request. More...
 
static char * handle_cli_stun_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static void handle_stun_timeout (int retry, struct sockaddr_in *dst)
 
static const char * stun_attr2str (int msg)
 helper function to print attribute names More...
 
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_response when called from ast_stun_request. More...
 
static int stun_id_cmp (stun_trans_id *left, stun_trans_id *right)
 
static const char * stun_msg2str (int msg)
 helper function to print message names More...
 
static int stun_process_attr (struct stun_state *state, struct stun_attr *attr)
 
static void stun_req_id (struct stun_header *req)
 helper function to generate a random request id More...
 
static int stun_send (int s, struct sockaddr_in *dst, struct stun_header *resp)
 wrapper to send an STUN message More...
 
static void stun_shutdown (void)
 

Variables

static struct ast_cli_entry cli_stun []
 
static uintmax_t debug_category_stun_id
 
static uintmax_t debug_category_stun_packet_id
 

Detailed Description

STUN Support.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Note
STUN is defined in RFC 3489.

Definition in file stun.c.

Macro Definition Documentation

◆ STUN_BINDERR

#define STUN_BINDERR   0x0111

Definition at line 103 of file stun.c.

◆ STUN_BINDREQ

#define STUN_BINDREQ   0x0001

STUN message types 'BIND' refers to transactions used to determine the externally visible addresses. 'SEC' refers to transactions used to establish a session key for subsequent requests. 'SEC' functionality is not supported here.

Definition at line 101 of file stun.c.

◆ STUN_BINDRESP

#define STUN_BINDRESP   0x0101

Definition at line 102 of file stun.c.

◆ STUN_CHANGE_REQUEST

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 113 of file stun.c.

◆ STUN_CHANGED_ADDRESS

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 115 of file stun.c.

◆ STUN_ERROR_CODE

#define STUN_ERROR_CODE   0x0009

Definition at line 119 of file stun.c.

◆ STUN_MAPPED_ADDRESS

#define STUN_MAPPED_ADDRESS   0x0001

Basic attribute types in stun messages. Messages can also contain custom attributes (codes above 0x7fff)

Definition at line 111 of file stun.c.

◆ STUN_MAX_RETRIES

#define STUN_MAX_RETRIES   3

Definition at line 123 of file stun.c.

◆ STUN_MESSAGE_INTEGRITY

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 118 of file stun.c.

◆ STUN_PASSWORD

#define STUN_PASSWORD   0x0007

Definition at line 117 of file stun.c.

◆ STUN_REFLECTED_FROM

#define STUN_REFLECTED_FROM   0x000b

Definition at line 121 of file stun.c.

◆ STUN_RESPONSE_ADDRESS

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 112 of file stun.c.

◆ STUN_SECERR

#define STUN_SECERR   0x0112

Definition at line 106 of file stun.c.

◆ STUN_SECREQ

#define STUN_SECREQ   0x0002

Definition at line 104 of file stun.c.

◆ STUN_SECRESP

#define STUN_SECRESP   0x0102

Definition at line 105 of file stun.c.

◆ STUN_SOURCE_ADDRESS

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 114 of file stun.c.

◆ STUN_UNKNOWN_ATTRIBUTES

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 120 of file stun.c.

◆ STUN_USERNAME

#define STUN_USERNAME   0x0006

Definition at line 116 of file stun.c.

Function Documentation

◆ append_attr_address()

static void append_attr_address ( struct stun_attr **  attr,
int  attrval,
struct sockaddr_in *  sin,
int *  len,
int *  left 
)
static

append an address to an STUN message

Definition at line 222 of file stun.c.

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}
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Definition: stun.c:87
unsigned int addr
Definition: stun.c:91
Definition: stun.c:78

References stun_addr::addr, and len().

Referenced by ast_stun_handle_packet().

◆ append_attr_string()

static void append_attr_string ( struct stun_attr **  attr,
int  attrval,
const char *  s,
int *  len,
int *  left 
)
static

append a string to an STUN message

Definition at line 205 of file stun.c.

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}

References len().

Referenced by ast_stun_handle_packet(), and ast_stun_request().

◆ ast_debug_category_stun_id()

uintmax_t ast_debug_category_stun_id ( void  )

Definition at line 555 of file stun.c.

556{
558}
static uintmax_t debug_category_stun_id
Definition: stun.c:553

References debug_category_stun_id.

◆ ast_debug_category_stun_packet_id()

uintmax_t ast_debug_category_stun_packet_id ( void  )

Definition at line 562 of file stun.c.

563{
565}
static uintmax_t debug_category_stun_packet_id
Definition: stun.c:560

References debug_category_stun_packet_id.

◆ ast_stun_handle_packet()

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.

Parameters
sSocket to send any response to.
srcAddress where packet came from.
dataSTUN packet buffer to process.
lenLength of packet
stun_cbIf not NULL, callback for each STUN attribute.
argArg to pass to callback.

Do some basic sanity checks on packet size and content, try to extract a bit of information, and possibly reply. At the moment this only processes BIND requests, and returns the externally visible address of the request. If a callback is specified, invoke it with the attribute.

Return values
AST_STUN_ACCEPTif responed to a STUN request
AST_STUN_IGNORE
-1on error

Definition at line 293 of file stun.c.

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}
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2206
#define NULL
Definition: resample.c:96
unsigned short attr
Definition: stun.c:79
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
static const char * stun_msg2str(int msg)
helper function to print message names
Definition: stun.c:126
#define STUN_BINDRESP
Definition: stun.c:102
int ast_stun_request(int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer)
Generic STUN request.
Definition: stun.c:415
#define STUN_MAPPED_ADDRESS
Basic attribute types in stun messages. Messages can also contain custom attributes (codes above 0x7f...
Definition: stun.c:111
#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 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
static int stun_process_attr(struct stun_state *state, struct stun_attr *attr)
Definition: stun.c:181
static int stun_send(int s, struct sockaddr_in *dst, struct stun_header *resp)
wrapper to send an STUN message
Definition: stun.c:264
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
#define ast_debug_stun(sublevel,...)
Log debug level STUN information.
Definition: stun.h:54
@ 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

References append_attr_address(), append_attr_string(), ast_debug_stun, ast_debug_stun_packet_is_allowed, AST_STUN_ACCEPT, AST_STUN_IGNORE, ast_stun_request(), ast_verbose(), stun_attr::attr, stun_header::id, stun_header::ies, len(), stun_header::msglen, stun_header::msgtype, NULL, stun_attr2str(), STUN_BINDREQ, STUN_BINDRESP, STUN_MAPPED_ADDRESS, stun_msg2str(), stun_process_attr(), stun_send(), STUN_USERNAME, and stun_state::username.

Referenced by ast_rtcp_read(), ast_rtp_read(), and ast_stun_request().

◆ ast_stun_init()

void ast_stun_init ( void  )

Initialize the STUN system in Asterisk.

Provided by stun.c

Definition at line 576 of file stun.c.

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}
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
Definition: clicompat.c:13
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
uintmax_t ast_debug_category_register(const char *name)
Register a debug level logger category.
descriptor for a cli entry.
Definition: cli.h:171
static void stun_shutdown(void)
Definition: stun.c:567
static struct ast_cli_entry cli_stun[]
Definition: stun.c:549
#define AST_LOG_CATEGORY_STUN_PACKET
Definition: stun.h:40
#define AST_LOG_CATEGORY_STUN
Definition: stun.h:38

References ast_cli_register_multiple, ast_debug_category_register(), AST_LOG_CATEGORY_STUN, AST_LOG_CATEGORY_STUN_PACKET, ast_register_atexit(), cli_stun, debug_category_stun_id, debug_category_stun_packet_id, and stun_shutdown().

Referenced by asterisk_daemon().

◆ ast_stun_request()

int ast_stun_request ( int  s,
struct sockaddr_in *  dst,
const char *  username,
struct sockaddr_in *  answer 
)

Generic STUN request.

Parameters
sThe socket used to send the request.
dstIf non null, the address of the STUN server. Only needed if the socket is not bound or connected.
usernameIf non null, add the username in the request.
answerIf non null, the function waits for a response and puts here the externally visible address.

Send a generic STUN request to the server specified, possibly waiting for a reply and filling the answer parameter with the externally visible address. Note that in this case the request will be blocking.

Note
The interface may change slightly in the future.
Return values
0on success.
<0on error.
>0on timeout.

Definition at line 415 of file stun.c.

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}
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
static int answer(void *data)
Definition: chan_pjsip.c:683
int errno
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
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
static void handle_stun_timeout(int retry, struct sockaddr_in *dst)
Definition: stun.c:240
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
static int stun_id_cmp(stun_trans_id *left, stun_trans_id *right)
Definition: stun.c:280
#define STUN_BINDERR
Definition: stun.c:103
static void stun_req_id(struct stun_header *req)
helper function to generate a random request id
Definition: stun.c:286
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

References answer(), append_attr_string(), ast_debug_stun, ast_poll, ast_remaining_ms(), ast_stun_handle_packet(), ast_tvnow(), stun_attr::attr, errno, handle_stun_timeout(), stun_header::id, stun_header::ies, if(), stun_header::msglen, stun_header::msgtype, STUN_BINDERR, STUN_BINDREQ, STUN_BINDRESP, stun_get_mapped(), stun_id_cmp(), STUN_MAX_RETRIES, stun_req_id(), stun_send(), and STUN_USERNAME.

Referenced by ast_rtp_stun_request(), ast_stun_handle_packet(), and stun_monitor_request().

◆ handle_cli_stun_set_debug()

static char * handle_cli_stun_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 521 of file stun.c.

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}
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
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_LOG_CATEGORY_DISABLED
#define AST_LOG_CATEGORY_ENABLED
int ast_debug_category_set_sublevel(const char *name, int sublevel)
Set the debug category's sublevel.
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
static struct test_val a

References a, ast_cli_entry::args, ast_cli(), ast_debug_category_set_sublevel(), ast_debug_stun_packet_is_allowed, AST_LOG_CATEGORY_DISABLED, AST_LOG_CATEGORY_ENABLED, AST_LOG_CATEGORY_STUN_PACKET, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, and ast_cli_entry::usage.

◆ handle_stun_timeout()

static void handle_stun_timeout ( int  retry,
struct sockaddr_in *  dst 
)
static

Definition at line 240 of file stun.c.

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}
#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
#define LOG_NOTICE
#define LOG_WARNING
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: utils.c:928

References ast_asprintf, ast_free, ast_inet_ntoa(), ast_log, LOG_NOTICE, LOG_WARNING, and STUN_MAX_RETRIES.

Referenced by ast_stun_request().

◆ stun_attr2str()

static const char * stun_attr2str ( int  msg)
static

helper function to print attribute names

Definition at line 146 of file stun.c.

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}
#define STUN_RESPONSE_ADDRESS
Definition: stun.c:112
#define STUN_CHANGED_ADDRESS
Definition: stun.c:115
#define STUN_PASSWORD
Definition: stun.c:117
#define STUN_REFLECTED_FROM
Definition: stun.c:121
#define STUN_ERROR_CODE
Definition: stun.c:119
#define STUN_SOURCE_ADDRESS
Definition: stun.c:114
#define STUN_UNKNOWN_ATTRIBUTES
Definition: stun.c:120
#define STUN_MESSAGE_INTEGRITY
Definition: stun.c:118
#define STUN_CHANGE_REQUEST
Definition: stun.c:113

References STUN_CHANGE_REQUEST, STUN_CHANGED_ADDRESS, STUN_ERROR_CODE, STUN_MAPPED_ADDRESS, STUN_MESSAGE_INTEGRITY, STUN_PASSWORD, STUN_REFLECTED_FROM, STUN_RESPONSE_ADDRESS, STUN_SOURCE_ADDRESS, STUN_UNKNOWN_ATTRIBUTES, and STUN_USERNAME.

Referenced by ast_stun_handle_packet(), and stun_process_attr().

◆ stun_get_mapped()

static int stun_get_mapped ( struct stun_attr attr,
void *  arg 
)
static

Extract the STUN_MAPPED_ADDRESS from the stun response. This is used as a callback for stun_handle_response when called from ast_stun_request.

Definition at line 403 of file stun.c.

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}
unsigned short port
Definition: stun.c:90
unsigned short len
Definition: stun.c:80

References stun_addr::addr, stun_attr::attr, stun_attr::len, stun_addr::port, and STUN_MAPPED_ADDRESS.

Referenced by ast_stun_request().

◆ stun_id_cmp()

static int stun_id_cmp ( stun_trans_id left,
stun_trans_id right 
)
static

Definition at line 280 of file stun.c.

281{
282 return memcmp(left, right, sizeof(*left));
283}

Referenced by ast_stun_request().

◆ stun_msg2str()

static const char * stun_msg2str ( int  msg)
static

helper function to print message names

Definition at line 126 of file stun.c.

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}
#define STUN_SECERR
Definition: stun.c:106
#define STUN_SECRESP
Definition: stun.c:105
#define STUN_SECREQ
Definition: stun.c:104

References STUN_BINDERR, STUN_BINDREQ, STUN_BINDRESP, STUN_SECERR, STUN_SECREQ, and STUN_SECRESP.

Referenced by ast_stun_handle_packet().

◆ stun_process_attr()

static int stun_process_attr ( struct stun_state state,
struct stun_attr attr 
)
static

Definition at line 181 of file stun.c.

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}
unsigned char value[0]
Definition: stun.c:81

References ast_debug_stun_packet_is_allowed, ast_verbose(), stun_attr::attr, stun_attr::len, stun_attr2str(), STUN_PASSWORD, STUN_USERNAME, and stun_attr::value.

Referenced by ast_stun_handle_packet().

◆ stun_req_id()

static void stun_req_id ( struct stun_header req)
static

helper function to generate a random request id

Definition at line 286 of file stun.c.

287{
288 int x;
289 for (x = 0; x < 4; x++)
290 req->id.id[x] = ast_random();
291}
unsigned int id[4]
Definition: stun.c:69
long int ast_random(void)
Definition: utils.c:2312

References ast_random(), stun_trans_id::id, and stun_header::id.

Referenced by ast_stun_request().

◆ stun_send()

static int stun_send ( int  s,
struct sockaddr_in *  dst,
struct stun_header resp 
)
static

wrapper to send an STUN message

Definition at line 264 of file stun.c.

265{
266 return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0,
267 (struct sockaddr *)dst, sizeof(*dst));
268}

References stun_header::msglen.

Referenced by ast_stun_handle_packet(), and ast_stun_request().

◆ stun_shutdown()

static void stun_shutdown ( void  )
static

Definition at line 567 of file stun.c.

568{
570
573}
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
int ast_debug_category_unregister(const char *name)
Un-register a debug level logger category.

References ast_cli_unregister_multiple(), ast_debug_category_unregister(), AST_LOG_CATEGORY_STUN, AST_LOG_CATEGORY_STUN_PACKET, and cli_stun.

Referenced by ast_stun_init().

Variable Documentation

◆ cli_stun

struct ast_cli_entry cli_stun[]
static
Initial value:
= {
{ .handler = handle_cli_stun_set_debug , .summary = "Enable/Disable STUN debugging" ,},
}
static char * handle_cli_stun_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: stun.c:521

Definition at line 549 of file stun.c.

Referenced by ast_stun_init(), and stun_shutdown().

◆ debug_category_stun_id

uintmax_t debug_category_stun_id
static

Definition at line 553 of file stun.c.

Referenced by ast_debug_category_stun_id(), and ast_stun_init().

◆ debug_category_stun_packet_id

uintmax_t debug_category_stun_packet_id
static

Definition at line 560 of file stun.c.

Referenced by ast_debug_category_stun_packet_id(), and ast_stun_init().