Sat Mar 10 01:55:48 2012

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

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

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

#define STUN_BINDRESP   0x0101

Definition at line 100 of file stun.c.

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

#define STUN_CHANGE_REQUEST   0x0003

Definition at line 111 of file stun.c.

Referenced by stun_attr2str().

#define STUN_CHANGED_ADDRESS   0x0005

Definition at line 113 of file stun.c.

Referenced by stun_attr2str().

#define STUN_ERROR_CODE   0x0009

Definition at line 117 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 109 of file stun.c.

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

#define STUN_MESSAGE_INTEGRITY   0x0008

Definition at line 116 of file stun.c.

Referenced by stun_attr2str().

#define STUN_PASSWORD   0x0007

Definition at line 115 of file stun.c.

Referenced by stun_attr2str(), and stun_process_attr().

#define STUN_REFLECTED_FROM   0x000b

Definition at line 119 of file stun.c.

Referenced by stun_attr2str().

#define STUN_RESPONSE_ADDRESS   0x0002

Definition at line 110 of file stun.c.

Referenced by stun_attr2str().

#define STUN_SECERR   0x0112

Definition at line 104 of file stun.c.

Referenced by stun_msg2str().

#define STUN_SECREQ   0x0002

Definition at line 102 of file stun.c.

Referenced by stun_msg2str().

#define STUN_SECRESP   0x0102

Definition at line 103 of file stun.c.

Referenced by stun_msg2str().

#define STUN_SOURCE_ADDRESS   0x0004

Definition at line 112 of file stun.c.

Referenced by stun_attr2str().

#define STUN_UNKNOWN_ATTRIBUTES   0x000a

Definition at line 118 of file stun.c.

Referenced by stun_attr2str().

#define STUN_USERNAME   0x0006

Definition at line 114 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 212 of file stun.c.

References stun_addr::addr.

Referenced by ast_stun_handle_packet().

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

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

Referenced by ast_stun_handle_packet(), and ast_stun_request().

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

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 260 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_header::msglen, stun_header::msgtype, stun_attr2str(), STUN_BINDREQ, STUN_BINDRESP, STUN_MAPPED_ADDRESS, stun_msg2str(), stun_process_attr(), stun_send(), and STUN_USERNAME.

Referenced by ast_rtp_read(), and ast_stun_request().

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

void ast_stun_init ( void   ) 

Initialize the STUN system in Asterisk.

Provided by stun.c

Definition at line 499 of file stun.c.

References ast_cli_register_multiple(), and cli_stun.

Referenced by main().

00500 {
00501    ast_cli_register_multiple(cli_stun, sizeof(cli_stun) / sizeof(struct ast_cli_entry));
00502 }

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

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

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

Definition at line 466 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.

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

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

helper function to print attribute names

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

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

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

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

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

Definition at line 247 of file stun.c.

Referenced by ast_stun_request().

00248 {
00249    return memcmp(left, right, sizeof(*left));
00250 }

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

helper function to print message names

Definition at line 122 of file stun.c.

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

Referenced by ast_stun_handle_packet().

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

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

Definition at line 177 of file stun.c.

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

Referenced by ast_stun_handle_packet().

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

static void stun_req_id ( struct stun_header req  )  [static]

helper function to generate a random request id

Definition at line 253 of file stun.c.

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

Referenced by ast_stun_request().

00254 {
00255    int x;
00256    for (x = 0; x < 4; x++)
00257       req->id.id[x] = ast_random();
00258 }

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

wrapper to send an STUN message

Definition at line 231 of file stun.c.

References stun_header::msglen.

Referenced by ast_stun_handle_packet(), and ast_stun_request().

00232 {
00233    return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0,
00234             (struct sockaddr *)dst, sizeof(*dst));
00235 }


Variable Documentation

struct ast_cli_entry cli_stun[] [static]

Initial value:

 {
   { .handler =  handle_cli_stun_set_debug , .summary =  "Enable/Disable STUN debugging" ,__VA_ARGS__ },
}

Definition at line 494 of file stun.c.

Referenced by ast_stun_init().

int stundebug [static]

Are we debugging stun?

Definition at line 39 of file stun.c.


Generated on Sat Mar 10 01:55:49 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7