69 typedef 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 128 return "Binding Request";
130 return "Binding Response";
132 return "Binding Error Response";
134 return "Shared Secret Request";
136 return "Shared Secret Response";
138 return "Shared Secret Error Response";
140 return "Non-RFC3489 Message";
148 return "Mapped Address";
150 return "Response Address";
152 return "Change Request";
154 return "Source Address";
156 return "Changed Address";
162 return "Message Integrity";
166 return "Unknown Attributes";
168 return "Reflected From";
170 return "Non-RFC3489 Attribute";
182 ast_verbose(
"Found STUN Attribute %s (%04x), length %d\n",
185 switch (ntohs(attr->
attr)) {
194 ast_verbose(
"Ignoring STUN attribute %s (%04x), length %d\n",
205 int str_length = strlen(s);
206 int attr_length = str_length + ((~(str_length - 1)) & 0x3);
207 int size =
sizeof(**attr) + attr_length;
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);
222 int size =
sizeof(**attr) + 8;
225 (*attr)->attr = htons(attrval);
226 (*attr)->len = htons(8);
227 addr = (
struct stun_addr *)((*attr)->value);
230 addr->
port = sin->sin_port;
231 addr->
addr = sin->sin_addr.s_addr;
232 (*attr) = (
struct stun_attr *)((*attr)->value + 8);
241 return sendto(s, resp, ntohs(resp->
msglen) +
sizeof(*resp), 0,
242 (
struct sockaddr *)dst,
sizeof(*dst));
257 return memcmp(left, right,
sizeof(*left));
264 for (x = 0; x < 4; x++)
290 ast_debug_stun(1,
"Scrambled STUN packet length (got %d, expecting %d)\n", x, (
int)len);
293 memset(&st, 0,
sizeof(st));
303 ast_debug_stun(1,
"Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (
int)len);
331 unsigned char respdata[1024];
334 int respleft =
sizeof(respdata) -
sizeof(
struct stun_header);
348 snprintf(combined,
sizeof(combined),
"%16s%16s", st.
username + 16, st.
username);
354 resp->
msglen = htons(resplen);
375 struct sockaddr_in *sa = (
struct sockaddr_in *)arg;
379 sa->sin_port = addr->
port;
380 sa->sin_addr.s_addr = addr->
addr;
385 const char *username,
struct sockaddr_in *
answer)
389 unsigned char req_buf[1024];
390 unsigned char rsp_buf[1024];
398 memset(answer, 0,
sizeof(
struct sockaddr_in));
405 reqleft =
sizeof(req_buf) -
sizeof(
struct stun_header);
410 req->
msglen = htons(reqlen);
413 for (retry = 0; retry++ < 3;) {
415 struct sockaddr_in src;
417 struct timeval start;
435 struct pollfd pfds = { .fd = s, .events = POLLIN };
457 memset(&src, 0,
sizeof(src));
458 srclen =
sizeof(src);
462 res = recvfrom(s, rsp_buf,
sizeof(rsp_buf) - 1,
463 0, (
struct sockaddr *) &src, &srclen);
476 memset(answer, 0,
sizeof(
struct sockaddr_in));
492 e->
command =
"stun set debug {on|off}";
494 "Usage: stun set debug {on|off}\n" 495 " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n" 505 if (!strncasecmp(a->
argv[e->
args-1],
"on", 2))
507 else if (!strncasecmp(a->
argv[e->
args-1],
"off", 3))
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 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...
int ast_debug_category_set_sublevel(const char *name, int sublevel)
Set the debug category's sublevel.
descriptor for a cli entry.
#define STUN_CHANGE_REQUEST
#define ast_cli_register_multiple(e, len)
Register multiple commands.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define STUN_MESSAGE_INTEGRITY
void ast_verbose(const char *fmt,...)
#define ast_debug_stun_packet_is_allowed
static uintmax_t debug_category_stun_packet_id
void ast_cli(int fd, const char *fmt,...)
int ast_stun_request(int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer)
Generic STUN request.
static struct ast_cli_entry cli_stun[]
int args
This gets set in ast_cli_register()
void ast_stun_init(void)
Initialize the STUN system in Asterisk.
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...
General Asterisk PBX channel definitions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
static void stun_req_id(struct stun_header *req)
helper function to generate a random request id
#define ast_poll(a, b, c)
uintmax_t ast_debug_category_stun_packet_id(void)
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
static int answer(void *data)
#define STUN_CHANGED_ADDRESS
static uintmax_t debug_category_stun_id
#define ast_debug_stun(sublevel,...)
Log debug level STUN information.
#define AST_LOG_CATEGORY_DISABLED
#define STUN_REFLECTED_FROM
#define STUN_RESPONSE_ADDRESS
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
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
uintmax_t ast_debug_category_stun_id(void)
Prototypes for public functions only of internal interest,.
int() stun_cb_f(struct stun_attr *attr, void *arg)
callback type to be invoked on stun responses.
static int stun_process_attr(struct stun_state *state, struct stun_attr *attr)
Support for logging to various files, console and syslog Configuration in file logger.conf.
int ast_debug_category_unregister(const char *name)
Un-register a debug level logger category.
Standard Command Line Interface.
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_LOG_CATEGORY_STUN
uintmax_t ast_debug_category_register(const char *name)
Register a debug level logger category.
#define AST_LOG_CATEGORY_ENABLED
#define AST_LOG_CATEGORY_STUN_PACKET
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
static const char * stun_attr2str(int msg)
helper function to print attribute names