Tue Aug 20 16:35:16 2013

Asterisk developer's documentation


stun.c File Reference

STUN Support. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/stun.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/channel.h"

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

Defines

#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.
#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).
#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
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
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.
void ast_stun_init (void)
 Initialize the STUN system in Asterisk.
int ast_stun_request (int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer)
 Generic STUN request.
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
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.
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
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
static int stun_send (int s, struct sockaddr_in *dst, struct stun_header *resp)
 wrapper to send an STUN message
static void stun_shutdown (void)

Variables

static struct ast_cli_entry cli_stun []
static int stundebug

Detailed Description

STUN Support.

Author:
Mark Spencer <markster@digium.com>
Note:
STUN is defined in RFC 3489.

Definition in file stun.c.


Define Documentation

#define STUN_BINDERR   0x0111

Definition at line 105 of file stun.c.

Referenced by ast_stun_request(), and stun_msg2str().

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

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

#define STUN_BINDRESP   0x0101

Definition at line 104 of file stun.c.

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

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 115 of file stun.c.

Referenced by stun_attr2str().

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 117 of file stun.c.

Referenced by stun_attr2str().

#define STUN_ERROR_CODE   0x0009

Definition at line 121 of file stun.c.

Referenced by stun_attr2str().

#define STUN_MAPPED_ADDRESS   0x0001

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

Definition at line 113 of file stun.c.

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

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 120 of file stun.c.

Referenced by stun_attr2str().

#define STUN_PASSWORD   0x0007

Definition at line 119 of file stun.c.

Referenced by stun_attr2str(), and stun_process_attr().

#define STUN_REFLECTED_FROM   0x000b

Definition at line 123 of file stun.c.

Referenced by stun_attr2str().

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 114 of file stun.c.

Referenced by stun_attr2str().

#define STUN_SECERR   0x0112

Definition at line 108 of file stun.c.

Referenced by stun_msg2str().

#define STUN_SECREQ   0x0002

Definition at line 106 of file stun.c.

Referenced by stun_msg2str().

#define STUN_SECRESP   0x0102

Definition at line 107 of file stun.c.

Referenced by stun_msg2str().

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 116 of file stun.c.

Referenced by stun_attr2str().

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 122 of file stun.c.

Referenced by stun_attr2str().

#define STUN_USERNAME   0x0006

Definition at line 118 of file stun.c.

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


Function Documentation

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

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

Referenced by ast_stun_handle_packet().

00217 {
00218    int size = sizeof(**attr) + 8;
00219    struct stun_addr *addr;
00220    if (*left > size) {
00221       (*attr)->attr = htons(attrval);
00222       (*attr)->len = htons(8);
00223       addr = (struct stun_addr *)((*attr)->value);
00224       addr->unused = 0;
00225       addr->family = 0x01;
00226       addr->port = sin->sin_port;
00227       addr->addr = sin->sin_addr.s_addr;
00228       (*attr) = (struct stun_attr *)((*attr)->value + 8);
00229       *len += size;
00230       *left -= size;
00231    }
00232 }

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

Referenced by ast_stun_handle_packet(), and ast_stun_request().

00203 {
00204    int size = sizeof(**attr) + strlen(s);
00205    if (*left > size) {
00206       (*attr)->attr = htons(attrval);
00207       (*attr)->len = htons(strlen(s));
00208       memcpy((*attr)->value, s, strlen(s));
00209       (*attr) = (struct stun_attr *)((*attr)->value + strlen(s));
00210       *len += size;
00211       *left -= size;
00212    }
00213 }

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:
s Socket to send any response to.
src Address where packet came from.
data STUN packet buffer to process.
len Length of packet
stun_cb If not NULL, callback for each STUN attribute.
arg Arg 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_ACCEPT if responed to a STUN request
AST_STUN_IGNORE 
-1 on error

Definition at line 264 of file stun.c.

References append_attr_address(), append_attr_string(), ast_debug, AST_STUN_ACCEPT, AST_STUN_IGNORE, ast_verbose, stun_attr::attr, stun_header::id, stun_header::ies, stun_attr::len, stun_header::msglen, stun_header::msgtype, 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_rtp_read(), and ast_stun_request().

00265 {
00266    struct stun_header *hdr = (struct stun_header *)data;
00267    struct stun_attr *attr;
00268    struct stun_state st;
00269    int ret = AST_STUN_IGNORE;
00270    int x;
00271 
00272    /* On entry, 'len' is the length of the udp payload. After the
00273     * initial checks it becomes the size of unprocessed options,
00274     * while 'data' is advanced accordingly.
00275     */
00276    if (len < sizeof(struct stun_header)) {
00277       ast_debug(1, "Runt STUN packet (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header));
00278       return -1;
00279    }
00280    len -= sizeof(struct stun_header);
00281    data += sizeof(struct stun_header);
00282    x = ntohs(hdr->msglen); /* len as advertised in the message */
00283    if (stundebug)
00284       ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), x);
00285    if (x > len) {
00286       ast_debug(1, "Scrambled STUN packet length (got %d, expecting %d)\n", x, (int)len);
00287    } else
00288       len = x;
00289    memset(&st, 0, sizeof(st));
00290    while (len) {
00291       if (len < sizeof(struct stun_attr)) {
00292          ast_debug(1, "Runt Attribute (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr));
00293          break;
00294       }
00295       attr = (struct stun_attr *)data;
00296       /* compute total attribute length */
00297       x = ntohs(attr->len) + sizeof(struct stun_attr);
00298       if (x > len) {
00299          ast_debug(1, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (int)len);
00300          break;
00301       }
00302       if (stun_cb)
00303          stun_cb(attr, arg);
00304       if (stun_process_attr(&st, attr)) {
00305          ast_debug(1, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr));
00306          break;
00307       }
00308       /* Clear attribute id: in case previous entry was a string,
00309        * this will act as the terminator for the string.
00310        */
00311       attr->attr = 0;
00312       data += x;
00313       len -= x;
00314    }
00315    /* Null terminate any string.
00316     * XXX NOTE, we write past the size of the buffer passed by the
00317     * caller, so this is potentially dangerous. The only thing that
00318     * saves us is that usually we read the incoming message in a
00319     * much larger buffer in the struct ast_rtp
00320     */
00321    *data = '\0';
00322 
00323    /* Now prepare to generate a reply, which at the moment is done
00324     * only for properly formed (len == 0) STUN_BINDREQ messages.
00325     */
00326    if (len == 0) {
00327       unsigned char respdata[1024];
00328       struct stun_header *resp = (struct stun_header *)respdata;
00329       int resplen = 0;  /* len excluding header */
00330       int respleft = sizeof(respdata) - sizeof(struct stun_header);
00331 
00332       resp->id = hdr->id;
00333       resp->msgtype = 0;
00334       resp->msglen = 0;
00335       attr = (struct stun_attr *)resp->ies;
00336       switch (ntohs(hdr->msgtype)) {
00337       case STUN_BINDREQ:
00338          if (stundebug)
00339             ast_verbose("STUN Bind Request, username: %s\n",
00340                    st.username ? st.username : "<none>");
00341          if (st.username)
00342             append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft);
00343          append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft);
00344          resp->msglen = htons(resplen);
00345          resp->msgtype = htons(STUN_BINDRESP);
00346          stun_send(s, src, resp);
00347          ret = AST_STUN_ACCEPT;
00348          break;
00349       default:
00350          if (stundebug)
00351             ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype)));
00352       }
00353    }
00354    return ret;
00355 }

void ast_stun_init ( void   ) 

Initialize the STUN system in Asterisk.

Provided by stun.c

Definition at line 508 of file stun.c.

References ast_cli_register_multiple(), ast_register_atexit(), and stun_shutdown().

Referenced by main().

00509 {
00510    ast_cli_register_multiple(cli_stun, sizeof(cli_stun) / sizeof(struct ast_cli_entry));
00511    ast_register_atexit(stun_shutdown);
00512 }

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

Generic STUN request.

Parameters:
s The socket used to send the request.
dst If non null, the address of the STUN server. Only needed if the socket is not bound or connected.
username If non null, add the username in the request.
answer If 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:
0 on success.
<0 on error.
>0 on timeout.

Definition at line 373 of file stun.c.

References append_attr_string(), ast_debug, ast_poll, ast_stun_handle_packet(), stun_attr::attr, errno, stun_header::id, stun_header::ies, 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(), gtalk_update_externip(), and stun_monitor_request().

00375 {
00376    struct stun_header *req;
00377    struct stun_header *rsp;
00378    unsigned char req_buf[1024];
00379    unsigned char rsp_buf[1024];
00380    int reqlen, reqleft;
00381    struct stun_attr *attr;
00382    int res = -1;
00383    int retry;
00384 
00385    if (answer) {
00386       /* Always clear answer in case the request fails. */
00387       memset(answer, 0, sizeof(struct sockaddr_in));
00388    }
00389 
00390    /* Create STUN bind request */
00391    req = (struct stun_header *) req_buf;
00392    stun_req_id(req);
00393    reqlen = 0;
00394    reqleft = sizeof(req_buf) - sizeof(struct stun_header);
00395    req->msgtype = 0;
00396    req->msglen = 0;
00397    attr = (struct stun_attr *) req->ies;
00398    if (username) {
00399       append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft);
00400    }
00401    req->msglen = htons(reqlen);
00402    req->msgtype = htons(STUN_BINDREQ);
00403 
00404    for (retry = 0; retry++ < 3;) {  /* XXX make retries configurable */
00405       /* send request, possibly wait for reply */
00406       struct sockaddr_in src;
00407       socklen_t srclen;
00408 
00409       /* Send STUN message. */
00410       res = stun_send(s, dst, req);
00411       if (res < 0) {
00412          ast_debug(1, "stun_send try %d failed: %s\n", retry, strerror(errno));
00413          break;
00414       }
00415       if (!answer) {
00416          /* Successful send since we don't care about any response. */
00417          res = 0;
00418          break;
00419       }
00420 
00421 try_again:
00422       /* Wait for response. */
00423       {
00424          struct pollfd pfds = { .fd = s, .events = POLLIN };
00425 
00426          res = ast_poll(&pfds, 1, 3000);
00427          if (res < 0) {
00428             /* Error */
00429             continue;
00430          }
00431          if (!res) {
00432             /* No response, timeout */
00433             res = 1;
00434             continue;
00435          }
00436       }
00437 
00438       /* Read STUN response. */
00439       memset(&src, 0, sizeof(src));
00440       srclen = sizeof(src);
00441       /* XXX pass sizeof(rsp_buf) - 1 in the size, because stun_handle_packet might
00442        * write past the end of the buffer.
00443        */
00444       res = recvfrom(s, rsp_buf, sizeof(rsp_buf) - 1,
00445          0, (struct sockaddr *) &src, &srclen);
00446       if (res < 0) {
00447          ast_debug(1, "recvfrom try %d failed: %s\n", retry, strerror(errno));
00448          break;
00449       }
00450 
00451       /* Process the STUN response. */
00452       rsp = (struct stun_header *) rsp_buf;
00453       if (ast_stun_handle_packet(s, &src, rsp_buf, res, stun_get_mapped, answer)
00454          || (rsp->msgtype != htons(STUN_BINDRESP)
00455             && rsp->msgtype != htons(STUN_BINDERR))
00456          || stun_id_cmp(&req->id, &rsp->id)) {
00457          /* Bad STUN packet, not right type, or transaction ID did not match. */
00458          memset(answer, 0, sizeof(struct sockaddr_in));
00459 
00460          /* Was not a resonse to our request. */
00461          goto try_again;
00462       }
00463       /* Success.  answer contains the external address if available. */
00464       res = 0;
00465       break;
00466    }
00467    return res;
00468 }

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

Definition at line 470 of file stun.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

00471 {
00472    switch (cmd) {
00473    case CLI_INIT:
00474       e->command = "stun set debug {on|off}";
00475       e->usage =
00476          "Usage: stun set debug {on|off}\n"
00477          "       Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
00478          "       debugging\n";
00479       return NULL;
00480    case CLI_GENERATE:
00481       return NULL;
00482    }
00483 
00484    if (a->argc != e->args)
00485       return CLI_SHOWUSAGE;
00486 
00487    if (!strncasecmp(a->argv[e->args-1], "on", 2))
00488       stundebug = 1;
00489    else if (!strncasecmp(a->argv[e->args-1], "off", 3))
00490       stundebug = 0;
00491    else
00492       return CLI_SHOWUSAGE;
00493 
00494    ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
00495    return CLI_SUCCESS;
00496 }

static const char* stun_attr2str ( int  msg  )  [static]

helper function to print attribute names

Definition at line 146 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().

00147 {
00148    switch (msg) {
00149    case STUN_MAPPED_ADDRESS:
00150       return "Mapped Address";
00151    case STUN_RESPONSE_ADDRESS:
00152       return "Response Address";
00153    case STUN_CHANGE_REQUEST:
00154       return "Change Request";
00155    case STUN_SOURCE_ADDRESS:
00156       return "Source Address";
00157    case STUN_CHANGED_ADDRESS:
00158       return "Changed Address";
00159    case STUN_USERNAME:
00160       return "Username";
00161    case STUN_PASSWORD:
00162       return "Password";
00163    case STUN_MESSAGE_INTEGRITY:
00164       return "Message Integrity";
00165    case STUN_ERROR_CODE:
00166       return "Error Code";
00167    case STUN_UNKNOWN_ATTRIBUTES:
00168       return "Unknown Attributes";
00169    case STUN_REFLECTED_FROM:
00170       return "Reflected From";
00171    }
00172    return "Non-RFC3489 Attribute";
00173 }

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

00362 {
00363    struct stun_addr *addr = (struct stun_addr *)(attr + 1);
00364    struct sockaddr_in *sa = (struct sockaddr_in *)arg;
00365 
00366    if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8)
00367       return 1;   /* not us. */
00368    sa->sin_port = addr->port;
00369    sa->sin_addr.s_addr = addr->addr;
00370    return 0;
00371 }

static int stun_id_cmp ( stun_trans_id left,
stun_trans_id right 
) [static]

Definition at line 251 of file stun.c.

Referenced by ast_stun_request().

00252 {
00253    return memcmp(left, right, sizeof(*left));
00254 }

static const char* stun_msg2str ( int  msg  )  [static]

helper function to print message names

Definition at line 126 of file stun.c.

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

Referenced by ast_stun_handle_packet().

00127 {
00128    switch (msg) {
00129    case STUN_BINDREQ:
00130       return "Binding Request";
00131    case STUN_BINDRESP:
00132       return "Binding Response";
00133    case STUN_BINDERR:
00134       return "Binding Error Response";
00135    case STUN_SECREQ:
00136       return "Shared Secret Request";
00137    case STUN_SECRESP:
00138       return "Shared Secret Response";
00139    case STUN_SECERR:
00140       return "Shared Secret Error Response";
00141    }
00142    return "Non-RFC3489 Message";
00143 }

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

Definition at line 181 of file stun.c.

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

00182 {
00183    if (stundebug)
00184       ast_verbose("Found STUN Attribute %s (%04x), length %d\n",
00185              stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
00186    switch (ntohs(attr->attr)) {
00187    case STUN_USERNAME:
00188       state->username = (const char *) (attr->value);
00189       break;
00190    case STUN_PASSWORD:
00191       state->password = (const char *) (attr->value);
00192       break;
00193    default:
00194       if (stundebug)
00195          ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n",
00196                 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
00197    }
00198    return 0;
00199 }

static void stun_req_id ( struct stun_header req  )  [static]

helper function to generate a random request id

Definition at line 257 of file stun.c.

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

Referenced by ast_stun_request().

00258 {
00259    int x;
00260    for (x = 0; x < 4; x++)
00261       req->id.id[x] = ast_random();
00262 }

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

wrapper to send an STUN message

Definition at line 235 of file stun.c.

References stun_header::msglen.

Referenced by ast_stun_handle_packet(), and ast_stun_request().

00236 {
00237    return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0,
00238             (struct sockaddr *)dst, sizeof(*dst));
00239 }

static void stun_shutdown ( void   )  [static]

Definition at line 502 of file stun.c.

References ast_cli_unregister_multiple().

Referenced by ast_stun_init().

00503 {
00504    ast_cli_unregister_multiple(cli_stun, sizeof(cli_stun) / sizeof(struct ast_cli_entry));
00505 }


Variable Documentation

struct ast_cli_entry cli_stun[] [static]
Initial value:
 {
   AST_CLI_DEFINE(handle_cli_stun_set_debug, "Enable/Disable STUN debugging"),
}

Definition at line 498 of file stun.c.

int stundebug [static]

Are we debugging stun?

Definition at line 43 of file stun.c.


Generated on 20 Aug 2013 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1