Asterisk - The Open Source Telephony Project  18.5.0
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_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 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.

Referenced by ast_stun_request(), and stun_msg2str().

◆ 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.

Referenced by ast_stun_handle_packet(), ast_stun_request(), and stun_msg2str().

◆ STUN_BINDRESP

#define STUN_BINDRESP   0x0101

Definition at line 102 of file stun.c.

Referenced by ast_stun_handle_packet(), ast_stun_request(), and stun_msg2str().

◆ STUN_CHANGE_REQUEST

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 113 of file stun.c.

Referenced by stun_attr2str().

◆ STUN_CHANGED_ADDRESS

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 115 of file stun.c.

Referenced by stun_attr2str().

◆ STUN_ERROR_CODE

#define STUN_ERROR_CODE   0x0009

Definition at line 119 of file stun.c.

Referenced by stun_attr2str().

◆ 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.

Referenced by ast_stun_handle_packet(), stun_attr2str(), and stun_get_mapped().

◆ STUN_MESSAGE_INTEGRITY

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 118 of file stun.c.

Referenced by stun_attr2str().

◆ STUN_PASSWORD

#define STUN_PASSWORD   0x0007

Definition at line 117 of file stun.c.

Referenced by stun_attr2str(), and stun_process_attr().

◆ STUN_REFLECTED_FROM

#define STUN_REFLECTED_FROM   0x000b

Definition at line 121 of file stun.c.

Referenced by stun_attr2str().

◆ STUN_RESPONSE_ADDRESS

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 112 of file stun.c.

Referenced by stun_attr2str().

◆ STUN_SECERR

#define STUN_SECERR   0x0112

Definition at line 106 of file stun.c.

Referenced by stun_msg2str().

◆ STUN_SECREQ

#define STUN_SECREQ   0x0002

Definition at line 104 of file stun.c.

Referenced by stun_msg2str().

◆ STUN_SECRESP

#define STUN_SECRESP   0x0102

Definition at line 105 of file stun.c.

Referenced by stun_msg2str().

◆ STUN_SOURCE_ADDRESS

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 114 of file stun.c.

Referenced by stun_attr2str().

◆ STUN_UNKNOWN_ATTRIBUTES

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 120 of file stun.c.

Referenced by stun_attr2str().

◆ STUN_USERNAME

#define STUN_USERNAME   0x0006

Definition at line 116 of file stun.c.

Referenced by ast_stun_handle_packet(), ast_stun_request(), stun_attr2str(), and stun_process_attr().

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 220 of file stun.c.

References stun_addr::addr, stun_addr::family, stun_addr::port, and stun_addr::unused.

Referenced by ast_stun_handle_packet().

221 {
222  int size = sizeof(**attr) + 8;
223  struct stun_addr *addr;
224  if (*left > size) {
225  (*attr)->attr = htons(attrval);
226  (*attr)->len = htons(8);
227  addr = (struct stun_addr *)((*attr)->value);
228  addr->unused = 0;
229  addr->family = 0x01;
230  addr->port = sin->sin_port;
231  addr->addr = sin->sin_addr.s_addr;
232  (*attr) = (struct stun_attr *)((*attr)->value + 8);
233  *len += size;
234  *left -= size;
235  }
236 }
unsigned char unused
Definition: stun.c:88
Definition: stun.c:78
unsigned int addr
Definition: stun.c:91
Definition: stun.c:87
unsigned char family
Definition: stun.c:89
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
unsigned short port
Definition: stun.c:90

◆ 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 203 of file stun.c.

Referenced by ast_stun_handle_packet(), and ast_stun_request().

204 {
205  int str_length = strlen(s);
206  int attr_length = str_length + ((~(str_length - 1)) & 0x3);
207  int size = sizeof(**attr) + attr_length;
208  if (*left > size) {
209  (*attr)->attr = htons(attrval);
210  (*attr)->len = htons(attr_length);
211  memcpy((*attr)->value, s, str_length);
212  memset((*attr)->value + str_length, 0, attr_length - str_length);
213  (*attr) = (struct stun_attr *)((*attr)->value + attr_length);
214  *len += size;
215  *left -= size;
216  }
217 }
Definition: stun.c:78
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

◆ ast_debug_category_stun_id()

uintmax_t ast_debug_category_stun_id ( void  )

Definition at line 522 of file stun.c.

References debug_category_stun_id.

523 {
524  return debug_category_stun_id;
525 }
static uintmax_t debug_category_stun_id
Definition: stun.c:520

◆ ast_debug_category_stun_packet_id()

uintmax_t ast_debug_category_stun_packet_id ( void  )

Definition at line 529 of file stun.c.

References debug_category_stun_packet_id.

530 {
532 }
static uintmax_t debug_category_stun_packet_id
Definition: stun.c:527

◆ 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 268 of file stun.c.

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, stun_attr::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().

269 {
270  struct stun_header *hdr = (struct stun_header *)data;
271  struct stun_attr *attr;
272  struct stun_state st;
273  int ret = AST_STUN_IGNORE;
274  int x;
275 
276  /* On entry, 'len' is the length of the udp payload. After the
277  * initial checks it becomes the size of unprocessed options,
278  * while 'data' is advanced accordingly.
279  */
280  if (len < sizeof(struct stun_header)) {
281  ast_debug_stun(1, "Runt STUN packet (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header));
282  return -1;
283  }
284  len -= sizeof(struct stun_header);
285  data += sizeof(struct stun_header);
286  x = ntohs(hdr->msglen); /* len as advertised in the message */
288  ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), (unsigned)ntohs(hdr->msgtype), x);
289  if (x > len) {
290  ast_debug_stun(1, "Scrambled STUN packet length (got %d, expecting %d)\n", x, (int)len);
291  } else
292  len = x;
293  memset(&st, 0, sizeof(st));
294  while (len) {
295  if (len < sizeof(struct stun_attr)) {
296  ast_debug_stun(1, "Runt Attribute (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr));
297  break;
298  }
299  attr = (struct stun_attr *)data;
300  /* compute total attribute length */
301  x = ntohs(attr->len) + sizeof(struct stun_attr);
302  if (x > len) {
303  ast_debug_stun(1, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (int)len);
304  break;
305  }
306  if (stun_cb)
307  stun_cb(attr, arg);
308  if (stun_process_attr(&st, attr)) {
309  ast_debug_stun(1, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), (unsigned)ntohs(attr->attr));
310  break;
311  }
312  /* Clear attribute id: in case previous entry was a string,
313  * this will act as the terminator for the string.
314  */
315  attr->attr = 0;
316  data += x;
317  len -= x;
318  }
319  /* Null terminate any string.
320  * XXX NOTE, we write past the size of the buffer passed by the
321  * caller, so this is potentially dangerous. The only thing that
322  * saves us is that usually we read the incoming message in a
323  * much larger buffer in the struct ast_rtp
324  */
325  *data = '\0';
326 
327  /* Now prepare to generate a reply, which at the moment is done
328  * only for properly formed (len == 0) STUN_BINDREQ messages.
329  */
330  if (len == 0) {
331  unsigned char respdata[1024];
332  struct stun_header *resp = (struct stun_header *)respdata;
333  int resplen = 0; /* len excluding header */
334  int respleft = sizeof(respdata) - sizeof(struct stun_header);
335  char combined[33];
336 
337  resp->id = hdr->id;
338  resp->msgtype = 0;
339  resp->msglen = 0;
340  attr = (struct stun_attr *)resp->ies;
341  switch (ntohs(hdr->msgtype)) {
342  case STUN_BINDREQ:
344  ast_verbose("STUN Bind Request, username: %s\n",
345  st.username ? st.username : "<none>");
346  if (st.username) {
347  append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft);
348  snprintf(combined, sizeof(combined), "%16s%16s", st.username + 16, st.username);
349  } else {
350  combined[0] = '\0';
351  }
352 
353  append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft);
354  resp->msglen = htons(resplen);
355  resp->msgtype = htons(STUN_BINDRESP);
356  stun_send(s, src, resp);
357  ast_stun_request(s, src, combined, NULL);
358  ret = AST_STUN_ACCEPT;
359  break;
360  default:
362  ast_verbose("Dunno what to do with STUN message %04x (%s)\n", (unsigned)ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype)));
363  }
364  }
365  return ret;
366 }
unsigned short msglen
Definition: stun.c:73
static const char * stun_msg2str(int msg)
helper function to print message names
Definition: stun.c:124
#define STUN_BINDRESP
Definition: stun.c:102
unsigned short msgtype
Definition: stun.c:72
#define STUN_MAPPED_ADDRESS
Basic attribute types in stun messages. Messages can also contain custom attributes (codes above 0x7f...
Definition: stun.c:111
Definition: stun.c:78
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2207
#define ast_debug_stun_packet_is_allowed
Definition: stun.h:57
#define NULL
Definition: resample.c:96
int ast_stun_request(int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer)
Generic STUN request.
Definition: stun.c:384
#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:220
#define ast_debug_stun(sublevel,...)
Log debug level STUN information.
Definition: stun.h:53
stun_trans_id id
Definition: stun.c:74
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define STUN_BINDREQ
STUN message types &#39;BIND&#39; refers to transactions used to determine the externally visible addresses...
Definition: stun.c:101
here we store credentials extracted from a message
Definition: stun.c:174
static int stun_process_attr(struct stun_state *state, struct stun_attr *attr)
Definition: stun.c:179
unsigned char ies[0]
Definition: stun.c:75
unsigned short attr
Definition: stun.c:79
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:203
unsigned short len
Definition: stun.c:80
static int stun_send(int s, struct sockaddr_in *dst, struct stun_header *resp)
wrapper to send an STUN message
Definition: stun.c:239
static const char * stun_attr2str(int msg)
helper function to print attribute names
Definition: stun.c:144

◆ ast_stun_init()

void ast_stun_init ( void  )

Initialize the STUN system in Asterisk.

Provided by stun.c

Definition at line 543 of file stun.c.

References ast_cli_register_multiple, ast_debug_category_register(), AST_LOG_CATEGORY_STUN, AST_LOG_CATEGORY_STUN_PACKET, ast_register_cleanup(), and stun_shutdown().

Referenced by asterisk_daemon().

544 {
545  ast_cli_register_multiple(cli_stun, sizeof(cli_stun) / sizeof(struct ast_cli_entry));
547 
550 }
static void stun_shutdown(void)
Definition: stun.c:534
descriptor for a cli entry.
Definition: cli.h:171
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static uintmax_t debug_category_stun_packet_id
Definition: stun.c:527
static struct ast_cli_entry cli_stun[]
Definition: stun.c:516
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
static uintmax_t debug_category_stun_id
Definition: stun.c:520
#define AST_LOG_CATEGORY_STUN
Definition: stun.h:37
uintmax_t ast_debug_category_register(const char *name)
Register a debug level logger category.
#define AST_LOG_CATEGORY_STUN_PACKET
Definition: stun.h:39

◆ 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 384 of file stun.c.

References append_attr_string(), ast_debug_stun, ast_poll, ast_remaining_ms(), ast_stun_handle_packet(), ast_tvnow(), stun_attr::attr, errno, 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_req_id(), stun_send(), and STUN_USERNAME.

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

386 {
387  struct stun_header *req;
388  struct stun_header *rsp;
389  unsigned char req_buf[1024];
390  unsigned char rsp_buf[1024];
391  int reqlen, reqleft;
392  struct stun_attr *attr;
393  int res = -1;
394  int retry;
395 
396  if (answer) {
397  /* Always clear answer in case the request fails. */
398  memset(answer, 0, sizeof(struct sockaddr_in));
399  }
400 
401  /* Create STUN bind request */
402  req = (struct stun_header *) req_buf;
403  stun_req_id(req);
404  reqlen = 0;
405  reqleft = sizeof(req_buf) - sizeof(struct stun_header);
406  attr = (struct stun_attr *) req->ies;
407  if (username) {
408  append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft);
409  }
410  req->msglen = htons(reqlen);
411  req->msgtype = htons(STUN_BINDREQ);
412 
413  for (retry = 0; retry++ < 3;) { /* XXX make retries configurable */
414  /* send request, possibly wait for reply */
415  struct sockaddr_in src;
416  socklen_t srclen;
417  struct timeval start;
418 
419  /* Send STUN message. */
420  res = stun_send(s, dst, req);
421  if (res < 0) {
422  ast_debug_stun(1, "stun_send try %d failed: %s\n", retry, strerror(errno));
423  break;
424  }
425  if (!answer) {
426  /* Successful send since we don't care about any response. */
427  res = 0;
428  break;
429  }
430 
431  start = ast_tvnow();
432 try_again:
433  /* Wait for response. */
434  {
435  struct pollfd pfds = { .fd = s, .events = POLLIN };
436  int ms;
437 
438  ms = ast_remaining_ms(start, 3000);
439  if (ms <= 0) {
440  /* No response, timeout */
441  res = 1;
442  continue;
443  }
444  res = ast_poll(&pfds, 1, ms);
445  if (res < 0) {
446  /* Error */
447  continue;
448  }
449  if (!res) {
450  /* No response, timeout */
451  res = 1;
452  continue;
453  }
454  }
455 
456  /* Read STUN response. */
457  memset(&src, 0, sizeof(src));
458  srclen = sizeof(src);
459  /* XXX pass sizeof(rsp_buf) - 1 in the size, because stun_handle_packet might
460  * write past the end of the buffer.
461  */
462  res = recvfrom(s, rsp_buf, sizeof(rsp_buf) - 1,
463  0, (struct sockaddr *) &src, &srclen);
464  if (res < 0) {
465  ast_debug_stun(1, "recvfrom try %d failed: %s\n", retry, strerror(errno));
466  break;
467  }
468 
469  /* Process the STUN response. */
470  rsp = (struct stun_header *) rsp_buf;
471  if (ast_stun_handle_packet(s, &src, rsp_buf, res, stun_get_mapped, answer)
472  || (rsp->msgtype != htons(STUN_BINDRESP)
473  && rsp->msgtype != htons(STUN_BINDERR))
474  || stun_id_cmp(&req->id, &rsp->id)) {
475  /* Bad STUN packet, not right type, or transaction ID did not match. */
476  memset(answer, 0, sizeof(struct sockaddr_in));
477 
478  /* Was not a resonse to our request. */
479  goto try_again;
480  }
481  /* Success. answer contains the external address if available. */
482  res = 0;
483  break;
484  }
485  return res;
486 }
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:268
unsigned short msglen
Definition: stun.c:73
#define STUN_BINDRESP
Definition: stun.c:102
unsigned short msgtype
Definition: stun.c:72
Definition: stun.c:78
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define STUN_USERNAME
Definition: stun.c:116
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:372
static void stun_req_id(struct stun_header *req)
helper function to generate a random request id
Definition: stun.c:261
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
static int answer(void *data)
Definition: chan_pjsip.c:682
#define ast_debug_stun(sublevel,...)
Log debug level STUN information.
Definition: stun.h:53
stun_trans_id id
Definition: stun.c:74
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: main/utils.c:2033
#define STUN_BINDREQ
STUN message types &#39;BIND&#39; refers to transactions used to determine the externally visible addresses...
Definition: stun.c:101
int errno
static int stun_id_cmp(stun_trans_id *left, stun_trans_id *right)
Definition: stun.c:255
unsigned char ies[0]
Definition: stun.c:75
unsigned short attr
Definition: stun.c:79
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:203
#define STUN_BINDERR
Definition: stun.c:103
static int stun_send(int s, struct sockaddr_in *dst, struct stun_header *resp)
wrapper to send an STUN message
Definition: stun.c:239

◆ 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 488 of file stun.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, 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, ast_cli_args::fd, NULL, and ast_cli_entry::usage.

489 {
490  switch (cmd) {
491  case CLI_INIT:
492  e->command = "stun set debug {on|off}";
493  e->usage =
494  "Usage: stun set debug {on|off}\n"
495  " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
496  " debugging\n";
497  return NULL;
498  case CLI_GENERATE:
499  return NULL;
500  }
501 
502  if (a->argc != e->args)
503  return CLI_SHOWUSAGE;
504 
505  if (!strncasecmp(a->argv[e->args-1], "on", 2))
507  else if (!strncasecmp(a->argv[e->args-1], "off", 3))
509  else
510  return CLI_SHOWUSAGE;
511 
512  ast_cli(a->fd, "STUN Debugging %s\n", ast_debug_stun_packet_is_allowed ? "Enabled" : "Disabled");
513  return CLI_SUCCESS;
514 }
int ast_debug_category_set_sublevel(const char *name, int sublevel)
Set the debug category&#39;s sublevel.
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define ast_debug_stun_packet_is_allowed
Definition: stun.h:57
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int args
This gets set in ast_cli_register()
Definition: cli.h:185
const int fd
Definition: cli.h:159
const char *const * argv
Definition: cli.h:161
#define AST_LOG_CATEGORY_DISABLED
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
#define AST_LOG_CATEGORY_ENABLED
#define AST_LOG_CATEGORY_STUN_PACKET
Definition: stun.h:39

◆ stun_attr2str()

static const char* stun_attr2str ( int  msg)
static

helper function to print attribute names

Definition at line 144 of file stun.c.

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().

145 {
146  switch (msg) {
147  case STUN_MAPPED_ADDRESS:
148  return "Mapped Address";
150  return "Response Address";
151  case STUN_CHANGE_REQUEST:
152  return "Change Request";
153  case STUN_SOURCE_ADDRESS:
154  return "Source Address";
156  return "Changed Address";
157  case STUN_USERNAME:
158  return "Username";
159  case STUN_PASSWORD:
160  return "Password";
162  return "Message Integrity";
163  case STUN_ERROR_CODE:
164  return "Error Code";
166  return "Unknown Attributes";
167  case STUN_REFLECTED_FROM:
168  return "Reflected From";
169  }
170  return "Non-RFC3489 Attribute";
171 }
#define STUN_PASSWORD
Definition: stun.c:117
#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_CHANGE_REQUEST
Definition: stun.c:113
#define STUN_MESSAGE_INTEGRITY
Definition: stun.c:118
#define STUN_USERNAME
Definition: stun.c:116
#define STUN_CHANGED_ADDRESS
Definition: stun.c:115
#define STUN_REFLECTED_FROM
Definition: stun.c:121
#define STUN_RESPONSE_ADDRESS
Definition: stun.c:112
#define STUN_ERROR_CODE
Definition: stun.c:119
#define STUN_SOURCE_ADDRESS
Definition: stun.c:114
#define STUN_UNKNOWN_ATTRIBUTES
Definition: stun.c:120

◆ 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 372 of file stun.c.

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

Referenced by ast_stun_request().

373 {
374  struct stun_addr *addr = (struct stun_addr *)(attr + 1);
375  struct sockaddr_in *sa = (struct sockaddr_in *)arg;
376 
377  if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8)
378  return 1; /* not us. */
379  sa->sin_port = addr->port;
380  sa->sin_addr.s_addr = addr->addr;
381  return 0;
382 }
#define STUN_MAPPED_ADDRESS
Basic attribute types in stun messages. Messages can also contain custom attributes (codes above 0x7f...
Definition: stun.c:111
unsigned int addr
Definition: stun.c:91
Definition: stun.c:87
unsigned short attr
Definition: stun.c:79
unsigned short len
Definition: stun.c:80
unsigned short port
Definition: stun.c:90

◆ stun_id_cmp()

static int stun_id_cmp ( stun_trans_id left,
stun_trans_id right 
)
static

Definition at line 255 of file stun.c.

Referenced by ast_stun_request().

256 {
257  return memcmp(left, right, sizeof(*left));
258 }

◆ stun_msg2str()

static const char* stun_msg2str ( int  msg)
static

helper function to print message names

Definition at line 124 of file stun.c.

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

Referenced by ast_stun_handle_packet().

125 {
126  switch (msg) {
127  case STUN_BINDREQ:
128  return "Binding Request";
129  case STUN_BINDRESP:
130  return "Binding Response";
131  case STUN_BINDERR:
132  return "Binding Error Response";
133  case STUN_SECREQ:
134  return "Shared Secret Request";
135  case STUN_SECRESP:
136  return "Shared Secret Response";
137  case STUN_SECERR:
138  return "Shared Secret Error Response";
139  }
140  return "Non-RFC3489 Message";
141 }
#define STUN_BINDRESP
Definition: stun.c:102
#define STUN_BINDREQ
STUN message types &#39;BIND&#39; refers to transactions used to determine the externally visible addresses...
Definition: stun.c:101
#define STUN_SECERR
Definition: stun.c:106
#define STUN_BINDERR
Definition: stun.c:103
#define STUN_SECRESP
Definition: stun.c:105
#define STUN_SECREQ
Definition: stun.c:104

◆ stun_process_attr()

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

Definition at line 179 of file stun.c.

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

Referenced by ast_stun_handle_packet().

180 {
182  ast_verbose("Found STUN Attribute %s (%04x), length %d\n",
183  stun_attr2str(ntohs(attr->attr)), (unsigned)ntohs(attr->attr), ntohs(attr->len));
184  }
185  switch (ntohs(attr->attr)) {
186  case STUN_USERNAME:
187  state->username = (const char *) (attr->value);
188  break;
189  case STUN_PASSWORD:
190  state->password = (const char *) (attr->value);
191  break;
192  default:
194  ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n",
195  stun_attr2str(ntohs(attr->attr)), (unsigned)ntohs(attr->attr), ntohs(attr->len));
196  }
197  }
198 
199  return 0;
200 }
#define STUN_PASSWORD
Definition: stun.c:117
const char * username
Definition: stun.c:175
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2207
#define ast_debug_stun_packet_is_allowed
Definition: stun.h:57
#define STUN_USERNAME
Definition: stun.c:116
const char * password
Definition: stun.c:176
unsigned short attr
Definition: stun.c:79
unsigned short len
Definition: stun.c:80
unsigned char value[0]
Definition: stun.c:81
static const char * stun_attr2str(int msg)
helper function to print attribute names
Definition: stun.c:144

◆ stun_req_id()

static void stun_req_id ( struct stun_header req)
static

helper function to generate a random request id

Definition at line 261 of file stun.c.

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

Referenced by ast_stun_request().

262 {
263  int x;
264  for (x = 0; x < 4; x++)
265  req->id.id[x] = ast_random();
266 }
unsigned int id[4]
Definition: stun.c:69
long int ast_random(void)
Definition: main/utils.c:2064
stun_trans_id id
Definition: stun.c:74

◆ 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 239 of file stun.c.

References stun_header::msglen.

Referenced by ast_stun_handle_packet(), and ast_stun_request().

240 {
241  return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0,
242  (struct sockaddr *)dst, sizeof(*dst));
243 }
unsigned short msglen
Definition: stun.c:73

◆ stun_shutdown()

static void stun_shutdown ( void  )
static

Definition at line 534 of file stun.c.

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

Referenced by ast_stun_init().

535 {
536  ast_cli_unregister_multiple(cli_stun, sizeof(cli_stun) / sizeof(struct ast_cli_entry));
537 
540 }
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
descriptor for a cli entry.
Definition: cli.h:171
static struct ast_cli_entry cli_stun[]
Definition: stun.c:516
int ast_debug_category_unregister(const char *name)
Un-register a debug level logger category.
#define AST_LOG_CATEGORY_STUN
Definition: stun.h:37
#define AST_LOG_CATEGORY_STUN_PACKET
Definition: stun.h:39

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:488

Definition at line 516 of file stun.c.

◆ debug_category_stun_id

uintmax_t debug_category_stun_id
static

Definition at line 520 of file stun.c.

Referenced by ast_debug_category_stun_id().

◆ debug_category_stun_packet_id

uintmax_t debug_category_stun_packet_id
static

Definition at line 527 of file stun.c.

Referenced by ast_debug_category_stun_packet_id().