37 #include "asterisk/_private.h"
71 typedef struct {
unsigned int id[4]; } __attribute__((packed))
stun_trans_id;
78 } __attribute__((packed));
84 } __attribute__((packed));
94 } __attribute__((packed));
103 #define STUN_BINDREQ 0x0001
104 #define STUN_BINDRESP 0x0101
105 #define STUN_BINDERR 0x0111
106 #define STUN_SECREQ 0x0002
107 #define STUN_SECRESP 0x0102
108 #define STUN_SECERR 0x0112
113 #define STUN_MAPPED_ADDRESS 0x0001
114 #define STUN_RESPONSE_ADDRESS 0x0002
115 #define STUN_CHANGE_REQUEST 0x0003
116 #define STUN_SOURCE_ADDRESS 0x0004
117 #define STUN_CHANGED_ADDRESS 0x0005
118 #define STUN_USERNAME 0x0006
119 #define STUN_PASSWORD 0x0007
120 #define STUN_MESSAGE_INTEGRITY 0x0008
121 #define STUN_ERROR_CODE 0x0009
122 #define STUN_UNKNOWN_ATTRIBUTES 0x000a
123 #define STUN_REFLECTED_FROM 0x000b
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",
186 switch (ntohs(attr->
attr)) {
195 ast_verbose(
"Ignoring STUN attribute %s (%04x), length %d\n",
204 int size =
sizeof(**attr) + strlen(s);
206 (*attr)->attr = htons(attrval);
207 (*attr)->len = htons(strlen(s));
208 memcpy((*attr)->value, s, strlen(s));
209 (*attr) = (
struct stun_attr *)((*attr)->value + strlen(s));
218 int size =
sizeof(**attr) + 8;
221 (*attr)->attr = htons(attrval);
222 (*attr)->len = htons(8);
223 addr = (
struct stun_addr *)((*attr)->value);
226 addr->
port = sin->sin_port;
227 addr->
addr = sin->sin_addr.s_addr;
228 (*attr) = (
struct stun_attr *)((*attr)->value + 8);
237 return sendto(s, resp, ntohs(resp->
msglen) +
sizeof(*resp), 0,
238 (
struct sockaddr *)dst,
sizeof(*dst));
253 return memcmp(left, right,
sizeof(*left));
260 for (x = 0; x < 4; x++)
277 ast_debug(1,
"Runt STUN packet (only %d, wanting at least %d)\n", (
int) len, (
int)
sizeof(
struct stun_header));
286 ast_debug(1,
"Scrambled STUN packet length (got %d, expecting %d)\n", x, (
int)len);
289 memset(&st, 0,
sizeof(st));
292 ast_debug(1,
"Runt Attribute (got %d, expecting %d)\n", (
int)len, (
int)
sizeof(
struct stun_attr));
299 ast_debug(1,
"Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (
int)len);
327 unsigned char respdata[1024];
330 int respleft =
sizeof(respdata) -
sizeof(
struct stun_header);
344 resp->
msglen = htons(resplen);
364 struct sockaddr_in *sa = (
struct sockaddr_in *)arg;
368 sa->sin_port = addr->
port;
369 sa->sin_addr.s_addr = addr->
addr;
374 const char *username,
struct sockaddr_in *answer)
378 unsigned char req_buf[1024];
379 unsigned char rsp_buf[1024];
387 memset(answer, 0,
sizeof(
struct sockaddr_in));
394 reqleft =
sizeof(req_buf) -
sizeof(
struct stun_header);
401 req->
msglen = htons(reqlen);
404 for (retry = 0; retry++ < 3;) {
406 struct sockaddr_in src;
412 ast_debug(1,
"stun_send try %d failed: %s\n", retry, strerror(
errno));
424 struct pollfd pfds = { .fd = s, .events = POLLIN };
439 memset(&src, 0,
sizeof(src));
440 srclen =
sizeof(src);
444 res = recvfrom(s, rsp_buf,
sizeof(rsp_buf) - 1,
445 0, (
struct sockaddr *) &src, &srclen);
447 ast_debug(1,
"recvfrom try %d failed: %s\n", retry, strerror(
errno));
458 memset(answer, 0,
sizeof(
struct sockaddr_in));
474 e->
command =
"stun set debug {on|off}";
476 "Usage: stun set debug {on|off}\n"
477 " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
487 if (!strncasecmp(a->
argv[e->
args-1],
"on", 2))
489 else if (!strncasecmp(a->
argv[e->
args-1],
"off", 3))
494 ast_cli(a->
fd,
"STUN Debugging %s\n", stundebug ?
"Enabled" :
"Disabled");
#define AST_CLI_DEFINE(fn, txt,...)
Asterisk main include file. File version handling, generic pbx functions.
static const char * stun_msg2str(int msg)
helper function to print message names
static void stun_shutdown(void)
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define STUN_MAPPED_ADDRESS
Basic attribute types in stun messages. Messages can also contain custom attributes (codes above 0x7f...
descriptor for a cli entry.
#define STUN_CHANGE_REQUEST
void ast_verbose(const char *fmt,...)
#define STUN_MESSAGE_INTEGRITY
void ast_cli(int fd, const char *fmt,...)
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.
static struct ast_cli_entry cli_stun[]
int args
This gets set in ast_cli_register()
int( stun_cb_f)(struct stun_attr *attr, void *arg)
callback type to be invoked on stun responses.
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 ast_debug(level,...)
Log a DEBUG message.
General Asterisk PBX channel definitions.
static void stun_req_id(struct stun_header *req)
helper function to generate a random request id
int ast_stun_request(int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer)
Generic STUN request.
#define ast_poll(a, b, c)
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
long int ast_random(void)
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
#define STUN_CHANGED_ADDRESS
void ast_stun_init(void)
Initialize the STUN system in Asterisk.
#define STUN_REFLECTED_FROM
#define STUN_RESPONSE_ADDRESS
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define STUN_BINDREQ
STUN message types 'BIND' refers to transactions used to determine the externally visible addresses...
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)
here we store credentials extracted from a message
if(yyss+yystacksize-1<=yyssp)
static int stun_process_attr(struct stun_state *state, struct stun_attr *attr)
Standard Command Line Interface.
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
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
static int stun_send(int s, struct sockaddr_in *dst, struct stun_header *resp)
wrapper to send an STUN message
#define STUN_SOURCE_ADDRESS
#define STUN_UNKNOWN_ATTRIBUTES
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
static const char * stun_attr2str(int msg)
helper function to print attribute names