69typedef struct {
unsigned int id[4]; } __attribute__((packed))
stun_trans_id;
76} __attribute__((packed));
82} __attribute__((packed));
92} __attribute__((packed));
101#define STUN_BINDREQ 0x0001
102#define STUN_BINDRESP 0x0101
103#define STUN_BINDERR 0x0111
104#define STUN_SECREQ 0x0002
105#define STUN_SECRESP 0x0102
106#define STUN_SECERR 0x0112
111#define STUN_MAPPED_ADDRESS 0x0001
112#define STUN_RESPONSE_ADDRESS 0x0002
113#define STUN_CHANGE_REQUEST 0x0003
114#define STUN_SOURCE_ADDRESS 0x0004
115#define STUN_CHANGED_ADDRESS 0x0005
116#define STUN_USERNAME 0x0006
117#define STUN_PASSWORD 0x0007
118#define STUN_MESSAGE_INTEGRITY 0x0008
119#define STUN_ERROR_CODE 0x0009
120#define STUN_UNKNOWN_ATTRIBUTES 0x000a
121#define STUN_REFLECTED_FROM 0x000b
123#define STUN_MAX_RETRIES 3
130 return "Binding Request";
132 return "Binding Response";
134 return "Binding Error Response";
136 return "Shared Secret Request";
138 return "Shared Secret Response";
140 return "Shared Secret Error Response";
142 return "Non-RFC3489 Message";
150 return "Mapped Address";
152 return "Response Address";
154 return "Change Request";
156 return "Source Address";
158 return "Changed Address";
164 return "Message Integrity";
168 return "Unknown Attributes";
170 return "Reflected From";
172 return "Non-RFC3489 Attribute";
184 ast_verbose(
"Found STUN Attribute %s (%04x), length %d\n",
187 switch (ntohs(attr->
attr)) {
189 state->username = (
const char *) (attr->
value);
192 state->password = (
const char *) (attr->
value);
196 ast_verbose(
"Ignoring STUN attribute %s (%04x), length %d\n",
207 int str_length = strlen(s);
208 int attr_length = str_length + ((~(str_length - 1)) & 0x3);
209 int size =
sizeof(**attr) + attr_length;
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);
224 int size =
sizeof(**attr) + 8;
227 (*attr)->attr = htons(attrval);
228 (*attr)->len = htons(8);
232 addr->port = sin->sin_port;
233 addr->addr = sin->sin_addr.s_addr;
234 (*attr) = (
struct stun_attr *)((*attr)->value + 8);
242 char *stun_destination =
"";
248 "Attempt %d to send STUN request %stimed out.\n",
253 "Attempt %d to send STUN request %stimed out. "
254 "Check that the server address is correct and reachable.\n",
266 return sendto(s, resp, ntohs(resp->
msglen) +
sizeof(*resp), 0,
267 (
struct sockaddr *)dst,
sizeof(*dst));
282 return memcmp(left, right,
sizeof(*left));
289 for (x = 0; x < 4; x++)
315 ast_debug_stun(1,
"Scrambled STUN packet length (got %d, expecting %d)\n", x, (
int)
len);
318 memset(&st, 0,
sizeof(st));
328 ast_debug_stun(1,
"Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (
int)
len);
356 unsigned char respdata[1024];
359 int respleft =
sizeof(respdata) -
sizeof(
struct stun_header);
378 snprintf(combined, 17,
"%16s", st.
username + 16);
379 snprintf(combined + 16, 17,
"%16s", st.
username);
385 resp->
msglen = htons(resplen);
406 struct sockaddr_in *sa = (
struct sockaddr_in *)arg;
410 sa->sin_port = addr->
port;
411 sa->sin_addr.s_addr = addr->
addr;
416 const char *username,
struct sockaddr_in *
answer)
420 unsigned char req_buf[1024];
421 unsigned char rsp_buf[1024];
429 memset(
answer, 0,
sizeof(
struct sockaddr_in));
436 reqleft =
sizeof(req_buf) -
sizeof(
struct stun_header);
441 req->
msglen = htons(reqlen);
446 struct sockaddr_in src;
448 struct timeval start;
466 struct pollfd pfds = { .fd = s, .events = POLLIN };
490 memset(&src, 0,
sizeof(src));
491 srclen =
sizeof(src);
495 res = recvfrom(s, rsp_buf,
sizeof(rsp_buf) - 1,
496 0, (
struct sockaddr *) &src, &srclen);
509 memset(
answer, 0,
sizeof(
struct sockaddr_in));
525 e->
command =
"stun set debug {on|off}";
527 "Usage: stun set debug {on|off}\n"
528 " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
535 if (
a->argc != e->
args)
538 if (!strncasecmp(
a->argv[e->
args-1],
"on", 2))
540 else if (!strncasecmp(
a->argv[e->
args-1],
"off", 3))
Prototypes for public functions only of internal interest,.
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
static int answer(void *data)
General Asterisk PBX channel definitions.
Standard Command Line Interface.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
void ast_verbose(const char *fmt,...)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Support for logging to various files, console and syslog Configuration in file logger....
#define AST_LOG_CATEGORY_DISABLED
uintmax_t ast_debug_category_register(const char *name)
Register a debug level logger category.
#define AST_LOG_CATEGORY_ENABLED
int ast_debug_category_unregister(const char *name)
Un-register a debug level logger category.
int ast_debug_category_set_sublevel(const char *name, int sublevel)
Set the debug category's sublevel.
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
#define ast_poll(a, b, c)
descriptor for a cli entry.
int args
This gets set in ast_cli_register()
here we store credentials extracted from a message
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...
#define STUN_RESPONSE_ADDRESS
static void stun_shutdown(void)
static uintmax_t debug_category_stun_id
static const char * stun_msg2str(int msg)
helper function to print message names
uintmax_t ast_debug_category_stun_id(void)
static void handle_stun_timeout(int retry, struct sockaddr_in *dst)
#define STUN_CHANGED_ADDRESS
int ast_stun_request(int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer)
Generic STUN request.
void ast_stun_init(void)
Initialize the STUN system in Asterisk.
#define STUN_MAPPED_ADDRESS
Basic attribute types in stun messages. Messages can also contain custom attributes (codes above 0x7f...
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.
#define STUN_REFLECTED_FROM
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 int stun_id_cmp(stun_trans_id *left, stun_trans_id *right)
static char * handle_cli_stun_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define STUN_SOURCE_ADDRESS
static uintmax_t debug_category_stun_packet_id
static const char * stun_attr2str(int msg)
helper function to print attribute names
#define STUN_BINDREQ
STUN message types 'BIND' refers to transactions used to determine the externally visible addresses....
uintmax_t ast_debug_category_stun_packet_id(void)
static int stun_process_attr(struct stun_state *state, struct stun_attr *attr)
static struct ast_cli_entry cli_stun[]
#define STUN_UNKNOWN_ATTRIBUTES
static void stun_req_id(struct stun_header *req)
helper function to generate a random request id
#define STUN_MESSAGE_INTEGRITY
static int stun_send(int s, struct sockaddr_in *dst, struct stun_header *resp)
wrapper to send an STUN message
#define STUN_CHANGE_REQUEST
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
#define ast_debug_stun(sublevel,...)
Log debug level STUN information.
#define AST_LOG_CATEGORY_STUN_PACKET
int() stun_cb_f(struct stun_attr *attr, void *arg)
callback type to be invoked on stun responses.
#define ast_debug_stun_packet_is_allowed
#define AST_LOG_CATEGORY_STUN
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
long int ast_random(void)