STUN code
[Core Library]

Collaboration diagram for STUN code:

Data Structures

struct  switch_stun_packet_header_t
struct  switch_stun_packet_attribute_t
struct  switch_stun_packet_t
struct  switch_stun_ip_t

Defines

#define SWITCH_STUN_DEFAULT_PORT   3478
#define SWITCH_STUN_PACKET_MIN_LEN   20
#define SWITCH_STUN_ATTRIBUTE_MIN_LEN   8
#define switch_stun_attribute_padded_length(attribute)   ((uint16_t)(attribute->length + (sizeof(uint32_t)-1)) & ~sizeof(uint32_t))
 Obtain the padded length of an attribute's value.
#define switch_stun_packet_first_attribute(packet, attribute)   attribute = (switch_stun_packet_attribute_t *)(&packet->first_attribute);
 set a switch_stun_packet_attribute_t pointer to point at the first attribute in a packet
#define switch_stun_packet_next_attribute(attribute, end)   (attribute && (attribute = (switch_stun_packet_attribute_t *) (attribute->value + switch_stun_attribute_padded_length(attribute))) && ((void *)attribute < end) && attribute->length && ((void *)(attribute + switch_stun_attribute_padded_length(attribute)) < end))
 Increment an attribute pointer to the next attribute in it's packet.
#define switch_stun_packet_length(packet)   ntohs(packet->header.length) + (sizeof(switch_stun_packet_header_t))
 Obtain the correct length in bytes of a stun packet.

Enumerations

enum  switch_stun_message_t {
  SWITCH_STUN_BINDING_REQUEST = 0x0001, SWITCH_STUN_BINDING_RESPONSE = 0x0101, SWITCH_STUN_BINDING_ERROR_RESPONSE = 0x0111, SWITCH_STUN_SHARED_SECRET_REQUEST = 0x0002,
  SWITCH_STUN_SHARED_SECRET_RESPONSE = 0x0102, SWITCH_STUN_SHARED_SECRET_ERROR_RESPONSE = 0x0112, SWITCH_STUN_ALLOCATE_REQUEST = 0x0003, SWITCH_STUN_ALLOCATE_RESPONSE = 0x0103,
  SWITCH_STUN_ALLOCATE_ERROR_RESPONSE = 0x0113, SWITCH_STUN_SEND_REQUEST = 0x0004, SWITCH_STUN_SEND_RESPONSE = 0x0104, SWITCH_STUN_SEND_ERROR_RESPONSE = 0x0114,
  SWITCH_STUN_DATA_INDICATION = 0x0115
}
enum  switch_stun_attribute_t {
  SWITCH_STUN_ATTR_MAPPED_ADDRESS = 0x0001, SWITCH_STUN_ATTR_RESPONSE_ADDRESS = 0x0002, SWITCH_STUN_ATTR_CHANGE_REQUEST = 0x0003, SWITCH_STUN_ATTR_SOURCE_ADDRESS = 0x0004,
  SWITCH_STUN_ATTR_CHANGED_ADDRESS = 0x0005, SWITCH_STUN_ATTR_USERNAME = 0x0006, SWITCH_STUN_ATTR_PASSWORD = 0x0007, SWITCH_STUN_ATTR_MESSAGE_INTEGRITY = 0x0008,
  SWITCH_STUN_ATTR_ERROR_CODE = 0x0009, SWITCH_STUN_ATTR_UNKNOWN_ATTRIBUTES = 0x000a, SWITCH_STUN_ATTR_REFLECTED_FROM = 0x000b, SWITCH_STUN_ATTR_TRANSPORT_PREFERENCES = 0x000c,
  SWITCH_STUN_ATTR_LIFETIME = 0x000d, SWITCH_STUN_ATTR_ALTERNATE_SERVER = 0x000e, SWITCH_STUN_ATTR_MAGIC_COOKIE = 0x000f, SWITCH_STUN_ATTR_BANDWIDTH = 0x0010,
  SWITCH_STUN_ATTR_DESTINATION_ADDRESS = 0x0011, SWITCH_STUN_ATTR_SOURCE_ADDRESS2 = 0x0012, SWITCH_STUN_ATTR_DATA = 0x0013, SWITCH_STUN_ATTR_OPTIONS = 0x8001
}
enum  switch_stun_error_t {
  SWITCH_STUN_ERROR_BAD_REQUEST = 400, SWITCH_STUN_ERROR_UNAUTHORIZED = 401, SWITCH_STUN_ERROR_UNKNOWN_ATTRIBUTE = 420, SWITCH_STUN_ERROR_STALE_CREDENTIALS = 430,
  SWITCH_STUN_ERROR_INTEGRITY_CHECK_FAILURE = 431, SWITCH_STUN_ERROR_MISSING_USERNAME = 432, SWITCH_STUN_ERROR_USE_TLS = 433, SWITCH_STUN_ERROR_SERVER_ERROR = 500,
  SWITCH_STUN_ERROR_GLOBAL_FAILURE = 600
}
enum  switch_stun_type_t { SWITCH_STUN_TYPE_PACKET_TYPE, SWITCH_STUN_TYPE_ATTRIBUTE, SWITCH_STUN_TYPE_ERROR }

Functions

void switch_stun_random_string (char *buf, uint16_t len, char *set)
 Writes random characters into a buffer.
switch_stun_packet_tswitch_stun_packet_parse (uint8_t *buf, uint32_t len)
 Prepare a raw packet for parsing.
const char * switch_stun_value_to_name (int32_t type, uint32_t value)
 Obtain a printable string form of a given value.
char * switch_stun_host_lookup (const char *host, switch_memory_pool_t *pool)
uint8_t switch_stun_packet_attribute_get_mapped_address (switch_stun_packet_attribute_t *attribute, char *ipstr, uint16_t *port)
 Extract a mapped address (IP:PORT) from a packet attribute.
char * switch_stun_packet_attribute_get_username (switch_stun_packet_attribute_t *attribute, char *username, uint16_t len)
 Extract a username from a packet attribute.
switch_stun_packet_tswitch_stun_packet_build_header (switch_stun_message_t type, char *id, uint8_t *buf)
 Prepare a new outbound packet of a certian type and id.
uint8_t switch_stun_packet_attribute_add_username (switch_stun_packet_t *packet, char *username, uint16_t ulen)
 Add a username packet attribute.
uint8_t switch_stun_packet_attribute_add_binded_address (switch_stun_packet_t *packet, char *ipstr, uint16_t port)
 Add a binded address packet attribute.
switch_status_t switch_stun_lookup (char **ip, switch_port_t *port, char *stunip, switch_port_t stunport, char **err, switch_memory_pool_t *pool)
 Perform a stun lookup.


Define Documentation

#define SWITCH_STUN_ATTRIBUTE_MIN_LEN   8

Definition at line 43 of file switch_stun.h.

Referenced by switch_stun_packet_parse().

#define switch_stun_attribute_padded_length ( attribute   )     ((uint16_t)(attribute->length + (sizeof(uint32_t)-1)) & ~sizeof(uint32_t))

Obtain the padded length of an attribute's value.

Parameters:
attribute the attribute
Returns:
the padded size in bytes

Definition at line 218 of file switch_stun.h.

Referenced by switch_stun_packet_parse().

#define SWITCH_STUN_DEFAULT_PORT   3478

Definition at line 41 of file switch_stun.h.

#define switch_stun_packet_first_attribute ( packet,
attribute   )     attribute = (switch_stun_packet_attribute_t *)(&packet->first_attribute);

set a switch_stun_packet_attribute_t pointer to point at the first attribute in a packet

Parameters:
packet the packet in question
attribute the pointer to set up

Definition at line 225 of file switch_stun.h.

Referenced by handle_ice(), switch_stun_lookup(), and switch_stun_packet_parse().

#define switch_stun_packet_length ( packet   )     ntohs(packet->header.length) + (sizeof(switch_stun_packet_header_t))

Obtain the correct length in bytes of a stun packet.

Parameters:
packet the packet in question
Returns:
the size in bytes (host order) of the entire packet

Definition at line 240 of file switch_stun.h.

Referenced by do_stun_ping(), handle_ice(), ice_out(), and switch_stun_lookup().

#define SWITCH_STUN_PACKET_MIN_LEN   20

Definition at line 42 of file switch_stun.h.

Referenced by switch_stun_packet_parse().

#define switch_stun_packet_next_attribute ( attribute,
end   )     (attribute && (attribute = (switch_stun_packet_attribute_t *) (attribute->value + switch_stun_attribute_padded_length(attribute))) && ((void *)attribute < end) && attribute->length && ((void *)(attribute + switch_stun_attribute_padded_length(attribute)) < end))

Increment an attribute pointer to the next attribute in it's packet.

Parameters:
attribute the pointer to increment
end pointer to the end of the buffer
Returns:
true or false depending on if there are any more attributes

Definition at line 233 of file switch_stun.h.

Referenced by handle_ice(), switch_stun_lookup(), and switch_stun_packet_parse().


Enumeration Type Documentation

enum switch_stun_attribute_t

Enumerator:
SWITCH_STUN_ATTR_MAPPED_ADDRESS 
SWITCH_STUN_ATTR_RESPONSE_ADDRESS 
SWITCH_STUN_ATTR_CHANGE_REQUEST 
SWITCH_STUN_ATTR_SOURCE_ADDRESS 
SWITCH_STUN_ATTR_CHANGED_ADDRESS 
SWITCH_STUN_ATTR_USERNAME 
SWITCH_STUN_ATTR_PASSWORD 
SWITCH_STUN_ATTR_MESSAGE_INTEGRITY 
SWITCH_STUN_ATTR_ERROR_CODE 
SWITCH_STUN_ATTR_UNKNOWN_ATTRIBUTES 
SWITCH_STUN_ATTR_REFLECTED_FROM 
SWITCH_STUN_ATTR_TRANSPORT_PREFERENCES 
SWITCH_STUN_ATTR_LIFETIME 
SWITCH_STUN_ATTR_ALTERNATE_SERVER 
SWITCH_STUN_ATTR_MAGIC_COOKIE 
SWITCH_STUN_ATTR_BANDWIDTH 
SWITCH_STUN_ATTR_DESTINATION_ADDRESS 
SWITCH_STUN_ATTR_SOURCE_ADDRESS2 
SWITCH_STUN_ATTR_DATA 
SWITCH_STUN_ATTR_OPTIONS 

Definition at line 60 of file switch_stun.h.

00060              {
00061         SWITCH_STUN_ATTR_MAPPED_ADDRESS = 0x0001,       /* Address */
00062         SWITCH_STUN_ATTR_RESPONSE_ADDRESS = 0x0002,     /* Address */
00063         SWITCH_STUN_ATTR_CHANGE_REQUEST = 0x0003,       /* UInt32 */
00064         SWITCH_STUN_ATTR_SOURCE_ADDRESS = 0x0004,       /* Address */
00065         SWITCH_STUN_ATTR_CHANGED_ADDRESS = 0x0005,      /* Address */
00066         SWITCH_STUN_ATTR_USERNAME = 0x0006,     /* ByteString, multiple of 4 bytes */
00067         SWITCH_STUN_ATTR_PASSWORD = 0x0007,     /* ByteString, multiple of 4 bytes */
00068         SWITCH_STUN_ATTR_MESSAGE_INTEGRITY = 0x0008,    /* ByteString, 20 bytes */
00069         SWITCH_STUN_ATTR_ERROR_CODE = 0x0009,   /* ErrorCode */
00070         SWITCH_STUN_ATTR_UNKNOWN_ATTRIBUTES = 0x000a,   /* UInt16List */
00071         SWITCH_STUN_ATTR_REFLECTED_FROM = 0x000b,       /* Address */
00072         SWITCH_STUN_ATTR_TRANSPORT_PREFERENCES = 0x000c,        /* TransportPrefs */
00073         SWITCH_STUN_ATTR_LIFETIME = 0x000d,     /* UInt32 */
00074         SWITCH_STUN_ATTR_ALTERNATE_SERVER = 0x000e,     /* Address */
00075         SWITCH_STUN_ATTR_MAGIC_COOKIE = 0x000f, /* ByteString, 4 bytes */
00076         SWITCH_STUN_ATTR_BANDWIDTH = 0x0010,    /* UInt32 */
00077         SWITCH_STUN_ATTR_DESTINATION_ADDRESS = 0x0011,  /* Address */
00078         SWITCH_STUN_ATTR_SOURCE_ADDRESS2 = 0x0012,      /* Address */
00079         SWITCH_STUN_ATTR_DATA = 0x0013, /* ByteString */
00080         SWITCH_STUN_ATTR_OPTIONS = 0x8001       /* UInt32 */
00081 } switch_stun_attribute_t;

enum switch_stun_error_t

Enumerator:
SWITCH_STUN_ERROR_BAD_REQUEST 
SWITCH_STUN_ERROR_UNAUTHORIZED 
SWITCH_STUN_ERROR_UNKNOWN_ATTRIBUTE 
SWITCH_STUN_ERROR_STALE_CREDENTIALS 
SWITCH_STUN_ERROR_INTEGRITY_CHECK_FAILURE 
SWITCH_STUN_ERROR_MISSING_USERNAME 
SWITCH_STUN_ERROR_USE_TLS 
SWITCH_STUN_ERROR_SERVER_ERROR 
SWITCH_STUN_ERROR_GLOBAL_FAILURE 

Definition at line 83 of file switch_stun.h.

enum switch_stun_message_t

Enumerator:
SWITCH_STUN_BINDING_REQUEST 
SWITCH_STUN_BINDING_RESPONSE 
SWITCH_STUN_BINDING_ERROR_RESPONSE 
SWITCH_STUN_SHARED_SECRET_REQUEST 
SWITCH_STUN_SHARED_SECRET_RESPONSE 
SWITCH_STUN_SHARED_SECRET_ERROR_RESPONSE 
SWITCH_STUN_ALLOCATE_REQUEST 
SWITCH_STUN_ALLOCATE_RESPONSE 
SWITCH_STUN_ALLOCATE_ERROR_RESPONSE 
SWITCH_STUN_SEND_REQUEST 
SWITCH_STUN_SEND_RESPONSE 
SWITCH_STUN_SEND_ERROR_RESPONSE 
SWITCH_STUN_DATA_INDICATION 

Definition at line 44 of file switch_stun.h.

enum switch_stun_type_t

Enumerator:
SWITCH_STUN_TYPE_PACKET_TYPE 
SWITCH_STUN_TYPE_ATTRIBUTE 
SWITCH_STUN_TYPE_ERROR 

Definition at line 95 of file switch_stun.h.


Function Documentation

char* switch_stun_host_lookup ( const char *  host,
switch_memory_pool_t pool 
)

Definition at line 429 of file switch_stun.c.

References buf, switch_core_strdup, switch_get_addr(), switch_sockaddr_info_get(), switch_str_nil, and SWITCH_UNSPEC.

00430 {
00431         switch_sockaddr_t *addr = NULL;
00432         char buf[30];
00433 
00434         switch_sockaddr_info_get(&addr, host, SWITCH_UNSPEC, 0, 0, pool);
00435         return switch_core_strdup(pool, switch_str_nil(switch_get_addr(buf, sizeof(buf), addr)));
00436 
00437 }

switch_status_t switch_stun_lookup ( char **  ip,
switch_port_t port,
char *  stunip,
switch_port_t  stunport,
char **  err,
switch_memory_pool_t pool 
)

Perform a stun lookup.

Parameters:
ip the local ip to use (replaced with stun results)
port the local port to use (replaced with stun results)
stunip the ip of the stun server
stunport the port of the stun server
err a pointer to describe errors
pool the memory pool to use
Returns:
SUCCESS or FAIL

Definition at line 439 of file switch_stun.c.

References switch_stun_ip_t::address, buf, switch_assert, switch_cond_next(), switch_core_strdup, switch_micro_time_now(), SWITCH_SHUTDOWN_READWRITE, SWITCH_SO_NONBLOCK, switch_sockaddr_info_get(), switch_socket_bind(), switch_socket_close(), switch_socket_create(), switch_socket_opt_set(), switch_socket_recvfrom(), switch_socket_sendto(), switch_socket_shutdown(), SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, SWITCH_STATUS_TIMEOUT, SWITCH_STUN_ATTR_MAPPED_ADDRESS, SWITCH_STUN_ATTR_USERNAME, SWITCH_STUN_BINDING_REQUEST, SWITCH_STUN_BINDING_RESPONSE, switch_stun_packet_attribute_add_username(), switch_stun_packet_attribute_get_mapped_address(), switch_stun_packet_attribute_get_username(), switch_stun_packet_build_header(), switch_stun_packet_first_attribute, switch_stun_packet_length, switch_stun_packet_next_attribute, switch_stun_packet_parse(), switch_stun_random_string(), SWITCH_UNSPEC, TRUE, switch_stun_packet_attribute_t::type, and switch_stun_packet_attribute_t::value.

00441 {
00442         switch_sockaddr_t *local_addr = NULL, *remote_addr = NULL, *from_addr = NULL;
00443         switch_socket_t *sock = NULL;
00444         uint8_t buf[260] = { 0 };
00445         uint8_t *start = buf;
00446         void *end_buf;
00447         switch_stun_packet_t *packet;
00448         switch_stun_packet_attribute_t *attr;
00449         switch_size_t bytes = 0;
00450         char username[33] = { 0 };
00451         char rip[16] = { 0 };
00452         uint16_t rport = 0;
00453         switch_time_t started = 0;
00454         unsigned int elapsed = 0;
00455         int funny = 0;
00456         int size = sizeof(buf);
00457 
00458         switch_assert(err);
00459 
00460         if (*err && !strcmp(*err, "funny")) {
00461                 funny = 1;
00462         }
00463 
00464         *err = "Success";
00465 
00466         switch_sockaddr_info_get(&from_addr, NULL, SWITCH_UNSPEC, 0, 0, pool);
00467 
00468         if (switch_sockaddr_info_get(&local_addr, *ip, SWITCH_UNSPEC, *port, 0, pool) != SWITCH_STATUS_SUCCESS) {
00469                 *err = "Local Address Error!";
00470                 return SWITCH_STATUS_FALSE;
00471         }
00472 
00473         if (switch_sockaddr_info_get(&remote_addr, stunip, SWITCH_UNSPEC, stunport, 0, pool) != SWITCH_STATUS_SUCCESS) {
00474                 *err = "Remote Address Error!";
00475                 return SWITCH_STATUS_FALSE;
00476         }
00477 
00478         if (switch_socket_create(&sock, AF_INET, SOCK_DGRAM, 0, pool) != SWITCH_STATUS_SUCCESS) {
00479                 *err = "Socket Error!";
00480                 return SWITCH_STATUS_FALSE;
00481         }
00482 
00483         if (switch_socket_bind(sock, local_addr) != SWITCH_STATUS_SUCCESS) {
00484                 *err = "Bind Error!";
00485                 return SWITCH_STATUS_FALSE;
00486         }
00487 
00488         if (funny) {
00489                 *start++ = 0;
00490                 *start++ = 0;
00491                 *start++ = 0x22;
00492                 *start++ = 0x22;
00493         }
00494 
00495         switch_socket_opt_set(sock, SWITCH_SO_NONBLOCK, TRUE);
00496         packet = switch_stun_packet_build_header(SWITCH_STUN_BINDING_REQUEST, NULL, start);
00497         switch_stun_random_string(username, 32, NULL);
00498         switch_stun_packet_attribute_add_username(packet, username, 32);
00499         bytes = switch_stun_packet_length(packet);
00500 
00501         if (funny) {
00502                 packet = (switch_stun_packet_t *) buf;
00503                 bytes += 4;
00504                 buf[bytes++] = 0;
00505                 buf[bytes++] = 0;
00506                 buf[bytes++] = 0;
00507                 buf[bytes++] = 0;
00508         }
00509 
00510         switch_socket_sendto(sock, remote_addr, 0, (void *) packet, &bytes);
00511         started = switch_micro_time_now();
00512 
00513         *ip = NULL;
00514         *port = 0;
00515 
00516 
00517         for (;;) {
00518                 bytes = sizeof(buf);
00519                 if (switch_socket_recvfrom(from_addr, sock, 0, (char *) &buf, &bytes) == SWITCH_STATUS_SUCCESS && bytes > 0) {
00520                         break;
00521                 }
00522 
00523                 if ((elapsed = (unsigned int) ((switch_micro_time_now() - started) / 1000)) > 5000) {
00524                         *err = "Timeout";
00525                         switch_socket_shutdown(sock, SWITCH_SHUTDOWN_READWRITE);
00526                         switch_socket_close(sock);
00527                         return SWITCH_STATUS_TIMEOUT;
00528                 }
00529                 switch_cond_next();
00530         }
00531         switch_socket_close(sock);
00532 
00533         if (funny) {
00534                 size -= 4;
00535         }
00536 
00537         packet = switch_stun_packet_parse(start, size);
00538         if (!packet) {
00539                 *err = "Invalid STUN/ICE packet";
00540                 return SWITCH_STATUS_FALSE;
00541         }
00542         end_buf = buf + ((sizeof(buf) > packet->header.length) ? packet->header.length : sizeof(buf));
00543 
00544         switch_stun_packet_first_attribute(packet, attr);
00545         do {
00546                 switch (attr->type) {
00547                 case SWITCH_STUN_ATTR_MAPPED_ADDRESS:
00548                         if (attr->type) {
00549                                 if (funny) {
00550                                         switch_stun_ip_t *tmp = (switch_stun_ip_t *) attr->value;
00551                                         tmp->address ^= ntohl(0xabcdabcd);
00552                                 }
00553                                 switch_stun_packet_attribute_get_mapped_address(attr, rip, &rport);
00554                         }
00555                         break;
00556                 case SWITCH_STUN_ATTR_USERNAME:
00557                         if (attr->type) {
00558                                 switch_stun_packet_attribute_get_username(attr, username, 32);
00559                         }
00560                         break;
00561                 }
00562         } while (switch_stun_packet_next_attribute(attr, end_buf));
00563 
00564         if (packet->header.type == SWITCH_STUN_BINDING_RESPONSE) {
00565                 *ip = switch_core_strdup(pool, rip);
00566                 *port = rport;
00567                 return SWITCH_STATUS_SUCCESS;
00568         } else {
00569                 *err = "Invalid Reply";
00570         }
00571 
00572         return SWITCH_STATUS_FALSE;
00573 }

uint8_t switch_stun_packet_attribute_add_binded_address ( switch_stun_packet_t packet,
char *  ipstr,
uint16_t  port 
)

Add a binded address packet attribute.

Parameters:
packet the packet to add the attribute to
ipstr the string representation of the ip
port the port of the mapped address
Returns:
true or false

Definition at line 380 of file switch_stun.c.

References switch_stun_ip_t::address, switch_stun_ip_t::family, switch_stun_packet_attribute_t::length, switch_stun_ip_t::port, SWITCH_STUN_ATTR_MAPPED_ADDRESS, switch_stun_packet_attribute_t::type, and switch_stun_packet_attribute_t::value.

Referenced by handle_ice().

00381 {
00382         switch_stun_packet_attribute_t *attribute;
00383         switch_stun_ip_t *ip;
00384         uint8_t *i, x;
00385         char *p = ipstr;
00386 
00387         attribute = (switch_stun_packet_attribute_t *) ((uint8_t *) & packet->first_attribute + ntohs(packet->header.length));
00388         attribute->type = htons(SWITCH_STUN_ATTR_MAPPED_ADDRESS);
00389         attribute->length = htons(8);
00390         ip = (switch_stun_ip_t *) attribute->value;
00391 
00392         ip->port = htons(port);
00393         ip->family = 1;
00394         i = (uint8_t *) & ip->address;
00395 
00396         for (x = 0; x < 4; x++) {
00397                 i[x] = (uint8_t) atoi(p);
00398                 if ((p = strchr(p, '.'))) {
00399                         p++;
00400                 } else {
00401                         break;
00402                 }
00403         }
00404 
00405         packet->header.length += htons(sizeof(switch_stun_packet_attribute_t)) + attribute->length;
00406         return 1;
00407 }

uint8_t switch_stun_packet_attribute_add_username ( switch_stun_packet_t packet,
char *  username,
uint16_t  ulen 
)

Add a username packet attribute.

Parameters:
packet the packet to add the attribute to
username the string representation of the username
ulen the length of the username
Returns:
true or false

Definition at line 409 of file switch_stun.c.

References switch_stun_packet_attribute_t::length, SWITCH_STUN_ATTR_USERNAME, switch_stun_random_string(), switch_stun_packet_attribute_t::type, and switch_stun_packet_attribute_t::value.

Referenced by handle_ice(), ice_out(), and switch_stun_lookup().

00410 {
00411         switch_stun_packet_attribute_t *attribute;
00412 
00413         if (ulen % 4 != 0) {
00414                 return 0;
00415         }
00416         attribute = (switch_stun_packet_attribute_t *) ((uint8_t *) & packet->first_attribute + ntohs(packet->header.length));
00417         attribute->type = htons(SWITCH_STUN_ATTR_USERNAME);
00418         attribute->length = htons(ulen);
00419         if (username) {
00420                 memcpy(attribute->value, username, ulen);
00421         } else {
00422                 switch_stun_random_string(attribute->value, ulen, NULL);
00423         }
00424 
00425         packet->header.length += htons(sizeof(switch_stun_packet_attribute_t)) + attribute->length;
00426         return 1;
00427 }

uint8_t switch_stun_packet_attribute_get_mapped_address ( switch_stun_packet_attribute_t attribute,
char *  ipstr,
uint16_t *  port 
)

Extract a mapped address (IP:PORT) from a packet attribute.

Parameters:
attribute the attribute from which to extract
ipstr a buffer to write the string representation of the ip
port the port
Returns:
true or false

Definition at line 337 of file switch_stun.c.

References switch_stun_ip_t::address, and switch_stun_ip_t::port.

Referenced by handle_ice(), and switch_stun_lookup().

00338 {
00339         switch_stun_ip_t *ip;
00340         uint8_t x, *i;
00341         char *p = ipstr;
00342 
00343         ip = (switch_stun_ip_t *) attribute->value;
00344         i = (uint8_t *) & ip->address;
00345         *ipstr = 0;
00346         for (x = 0; x < 4; x++) {
00347                 sprintf(p, "%u%s", i[x], x == 3 ? "" : ".");
00348                 p = ipstr + strlen(ipstr);
00349         }
00350         *port = ip->port;
00351         return 1;
00352 }

char* switch_stun_packet_attribute_get_username ( switch_stun_packet_attribute_t attribute,
char *  username,
uint16_t  len 
)

Extract a username from a packet attribute.

Parameters:
attribute the attribute from which to extract
username a buffer to write the string representation of the username
len the maximum size of the username buffer
Returns:
a pointer to the username or NULL

Definition at line 354 of file switch_stun.c.

Referenced by handle_ice(), and switch_stun_lookup().

00355 {
00356         uint16_t cpylen;
00357 
00358         cpylen = attribute->length < len ? attribute->length : len;
00359         return memcpy(username, attribute->value, cpylen);
00360 }

switch_stun_packet_t* switch_stun_packet_build_header ( switch_stun_message_t  type,
char *  id,
uint8_t *  buf 
)

Prepare a new outbound packet of a certian type and id.

Parameters:
id id to use (NULL for an auto generated id)
type the stun packet type
buf a pointer to data to use for the packet
Returns:
a pointer to a ready-to-use stun packet

Definition at line 362 of file switch_stun.c.

References switch_stun_packet_header_t::id, switch_stun_packet_header_t::length, switch_stun_random_string(), and switch_stun_packet_header_t::type.

Referenced by do_stun_ping(), handle_ice(), ice_out(), and switch_stun_lookup().

00363 {
00364         switch_stun_packet_header_t *header;
00365 
00366 
00367         header = (switch_stun_packet_header_t *) buf;
00368         header->type = htons(type);
00369         header->length = 0;
00370 
00371         if (id) {
00372                 memcpy(header->id, id, 16);
00373         } else {
00374                 switch_stun_random_string(header->id, 16, NULL);
00375         }
00376 
00377         return (switch_stun_packet_t *) buf;
00378 }

switch_stun_packet_t* switch_stun_packet_parse ( uint8_t *  buf,
uint32_t  len 
)

Prepare a raw packet for parsing.

Parameters:
buf the raw data
len the length of the data
Returns:
a stun packet pointer to buf to use as an access point

Definition at line 115 of file switch_stun.c.

References switch_stun_ip_t::family, switch_stun_packet_t::header, switch_stun_packet_header_t::length, switch_stun_packet_attribute_t::length, switch_stun_ip_t::port, SWITCH_STUN_ALLOCATE_ERROR_RESPONSE, SWITCH_STUN_ALLOCATE_REQUEST, SWITCH_STUN_ALLOCATE_RESPONSE, SWITCH_STUN_ATTR_ALTERNATE_SERVER, SWITCH_STUN_ATTR_BANDWIDTH, SWITCH_STUN_ATTR_CHANGE_REQUEST, SWITCH_STUN_ATTR_CHANGED_ADDRESS, SWITCH_STUN_ATTR_DATA, SWITCH_STUN_ATTR_DESTINATION_ADDRESS, SWITCH_STUN_ATTR_ERROR_CODE, SWITCH_STUN_ATTR_LIFETIME, SWITCH_STUN_ATTR_MAGIC_COOKIE, SWITCH_STUN_ATTR_MAPPED_ADDRESS, SWITCH_STUN_ATTR_MESSAGE_INTEGRITY, SWITCH_STUN_ATTR_OPTIONS, SWITCH_STUN_ATTR_PASSWORD, SWITCH_STUN_ATTR_REFLECTED_FROM, SWITCH_STUN_ATTR_RESPONSE_ADDRESS, SWITCH_STUN_ATTR_SOURCE_ADDRESS, SWITCH_STUN_ATTR_SOURCE_ADDRESS2, SWITCH_STUN_ATTR_TRANSPORT_PREFERENCES, SWITCH_STUN_ATTR_UNKNOWN_ATTRIBUTES, SWITCH_STUN_ATTR_USERNAME, SWITCH_STUN_ATTRIBUTE_MIN_LEN, switch_stun_attribute_padded_length, SWITCH_STUN_BINDING_ERROR_RESPONSE, SWITCH_STUN_BINDING_REQUEST, SWITCH_STUN_BINDING_RESPONSE, SWITCH_STUN_DATA_INDICATION, switch_stun_packet_first_attribute, SWITCH_STUN_PACKET_MIN_LEN, switch_stun_packet_next_attribute, SWITCH_STUN_SEND_ERROR_RESPONSE, SWITCH_STUN_SEND_REQUEST, SWITCH_STUN_SEND_RESPONSE, SWITCH_STUN_SHARED_SECRET_ERROR_RESPONSE, SWITCH_STUN_SHARED_SECRET_REQUEST, SWITCH_STUN_SHARED_SECRET_RESPONSE, switch_stun_packet_header_t::type, switch_stun_packet_attribute_t::type, and switch_stun_packet_attribute_t::value.

Referenced by handle_ice(), and switch_stun_lookup().

00116 {
00117         switch_stun_packet_t *packet;
00118         switch_stun_packet_attribute_t *attr;
00119         uint32_t bytes_left = len;
00120         void *end_buf = buf + len;
00121 
00122         if (len < SWITCH_STUN_PACKET_MIN_LEN) {
00123                 return NULL;
00124         }
00125 
00126         packet = (switch_stun_packet_t *) buf;
00127         packet->header.type = ntohs(packet->header.type);
00128         packet->header.length = ntohs(packet->header.length);
00129         bytes_left -= packet->header.length + 20;
00130 
00131         /*
00132          * Check packet type (RFC3489(bis?) values)
00133          */
00134         switch (packet->header.type) {
00135         case SWITCH_STUN_BINDING_REQUEST:
00136         case SWITCH_STUN_BINDING_RESPONSE:
00137         case SWITCH_STUN_BINDING_ERROR_RESPONSE:
00138         case SWITCH_STUN_SHARED_SECRET_REQUEST:
00139         case SWITCH_STUN_SHARED_SECRET_RESPONSE:
00140         case SWITCH_STUN_SHARED_SECRET_ERROR_RESPONSE:
00141         case SWITCH_STUN_ALLOCATE_REQUEST:
00142         case SWITCH_STUN_ALLOCATE_RESPONSE:
00143         case SWITCH_STUN_ALLOCATE_ERROR_RESPONSE:
00144         case SWITCH_STUN_SEND_REQUEST:
00145         case SWITCH_STUN_SEND_RESPONSE:
00146         case SWITCH_STUN_SEND_ERROR_RESPONSE:
00147         case SWITCH_STUN_DATA_INDICATION:
00148                 /* Valid */
00149                 break;
00150 
00151         default:
00152                 /* Invalid value */
00153                 return NULL;
00154         }
00155 
00156         /*
00157          * Check for length overflow
00158          */
00159         if (bytes_left <= 0) {
00160                 /* Invalid */
00161                 return NULL;
00162         }
00163 
00164         /*
00165          * No payload?
00166          */
00167         if (packet->header.length == 0) {
00168                 /* Invalid?! */
00169                 return NULL;
00170         }
00171 
00172         /* check if we have enough bytes left for an attribute */
00173         if (bytes_left < SWITCH_STUN_ATTRIBUTE_MIN_LEN) {
00174                 return NULL;
00175         }
00176 
00177         switch_stun_packet_first_attribute(packet, attr);
00178         do {
00179                 attr->length = ntohs(attr->length);
00180                 attr->type = ntohs(attr->type);
00181                 bytes_left -= 4;                /* attribute header consumed */
00182 
00183                 if (!attr->length || switch_stun_attribute_padded_length(attr) > bytes_left) {
00184                         /*
00185                          * Note we simply don't "break" here out of the loop anymore because
00186                          * we don't want the upper layers to have to deal with attributes without a value
00187                          * (or worse: invalid length)
00188                          */
00189                         return NULL;
00190                 }
00191 
00192                 /*
00193                  * Handle STUN attributes
00194                  */
00195                 switch (attr->type) {
00196                 case SWITCH_STUN_ATTR_MAPPED_ADDRESS:   /* Address, we only care about this one, but parse the others too */
00197                 case SWITCH_STUN_ATTR_RESPONSE_ADDRESS:
00198                 case SWITCH_STUN_ATTR_SOURCE_ADDRESS:
00199                 case SWITCH_STUN_ATTR_CHANGED_ADDRESS:
00200                 case SWITCH_STUN_ATTR_REFLECTED_FROM:
00201                 case SWITCH_STUN_ATTR_ALTERNATE_SERVER:
00202                 case SWITCH_STUN_ATTR_DESTINATION_ADDRESS:
00203                 case SWITCH_STUN_ATTR_SOURCE_ADDRESS2:
00204                         {
00205                                 switch_stun_ip_t *ip;
00206                                 uint32_t addr_length = 0;
00207                                 ip = (switch_stun_ip_t *) attr->value;
00208 
00209                                 switch (ip->family) {
00210                                 case 0x01:              /* IPv4 */
00211                                         addr_length = 4;
00212                                         break;
00213 
00214                                 case 0x02:              /* IPv6 */
00215                                         addr_length = 16;
00216                                         break;
00217 
00218                                 default:                /* Invalid */
00219                                         return NULL;
00220                                 }
00221 
00222                                 /* attribute payload length must be == address length + size of other payload fields (family...) */
00223                                 if (attr->length != addr_length + 4) {
00224                                         /* Invalid */
00225                                         return NULL;
00226                                 }
00227 
00228                                 ip->port = ntohs(ip->port);
00229                         }
00230                         break;
00231 
00232                 case SWITCH_STUN_ATTR_CHANGE_REQUEST:   /* UInt32 */
00233                 case SWITCH_STUN_ATTR_LIFETIME:
00234                 case SWITCH_STUN_ATTR_BANDWIDTH:
00235                 case SWITCH_STUN_ATTR_OPTIONS:
00236                         {
00237                                 uint32_t *val = (uint32_t *) attr->value;
00238 
00239                                 if (attr->length != sizeof(uint32_t)) {
00240                                         /* Invalid */
00241                                         return NULL;
00242                                 }
00243 
00244                                 *val = ntohl(*val);     /* should we do this here? */
00245                         }
00246                         break;
00247 
00248                 case SWITCH_STUN_ATTR_USERNAME: /* ByteString, multiple of 4 bytes */
00249                 case SWITCH_STUN_ATTR_PASSWORD: /* ByteString, multiple of 4 bytes */
00250                         if (attr->length % 4 != 0) {
00251                                 /* Invalid */
00252                                 return NULL;
00253                         }
00254                         break;
00255 
00256                 case SWITCH_STUN_ATTR_DATA:     /* ByteString */
00257                 case SWITCH_STUN_ATTR_ERROR_CODE:       /* ErrorCode */
00258                 case SWITCH_STUN_ATTR_TRANSPORT_PREFERENCES:    /* TransportPrefs */
00259                         /*
00260                          * No length checking here, since we already checked against the padded length
00261                          * before
00262                          */
00263                         break;
00264 
00265                 case SWITCH_STUN_ATTR_MESSAGE_INTEGRITY:        /* ByteString, 20 bytes */
00266                         if (attr->length != 20) {
00267                                 /* Invalid */
00268                                 return NULL;
00269                         }
00270                         break;
00271 
00272                 case SWITCH_STUN_ATTR_MAGIC_COOKIE:     /* ByteString, 4 bytes */
00273                         if (attr->length != 4) {
00274                                 /* Invalid */
00275                                 return NULL;
00276                         }
00277                         break;
00278 
00279                 case SWITCH_STUN_ATTR_UNKNOWN_ATTRIBUTES:       /* UInt16List (= multiple of 2 bytes) */
00280                         if (attr->length % 2 != 0) {
00281                                 return NULL;
00282                         }
00283                         break;
00284 
00285                 default:
00286                         /* Mandatory attribute range? => invalid */
00287                         if (attr->type <= 0x7FFF) {
00288                                 return NULL;
00289                         }
00290                         break;
00291                 }
00292                 bytes_left -= switch_stun_attribute_padded_length(attr);        /* attribute value consumed, substract padded length */
00293 
00294         } while (bytes_left >= SWITCH_STUN_ATTRIBUTE_MIN_LEN && switch_stun_packet_next_attribute(attr, end_buf));
00295 
00296         if ((uint32_t) (packet->header.length + 20) > (uint32_t) (len - bytes_left)) {
00297                 /*
00298                  * the packet length is longer than the length of all attributes?
00299                  * for now simply decrease the packet size
00300                  */
00301                 packet->header.length = (uint16_t) ((len - bytes_left) - 20);
00302         }
00303 
00304         return packet;
00305 }

void switch_stun_random_string ( char *  buf,
uint16_t  len,
char *  set 
)

Writes random characters into a buffer.

Parameters:
buf the buffer
len the length of the data
set the set of chars to use (NULL for auto)

Definition at line 96 of file switch_stun.c.

Referenced by switch_core_set_serial(), switch_rtp_get_random(), switch_stun_lookup(), switch_stun_packet_attribute_add_username(), and switch_stun_packet_build_header().

00097 {
00098         char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
00099         int max;
00100         uint16_t x;
00101 
00102         if (!set) {
00103                 set = chars;
00104         }
00105 
00106         max = (int) strlen(set);
00107 
00108         for (x = 0; x < len; x++) {
00109                 int j = (int) (max * 1.0 * rand() / (RAND_MAX + 1.0));
00110                 buf[x] = set[j];
00111         }
00112 }

const char* switch_stun_value_to_name ( int32_t  type,
uint32_t  value 
)

Obtain a printable string form of a given value.

Parameters:
type the type of message
value the value to look up
Returns:
a sring version of value

Definition at line 307 of file switch_stun.c.

References ATTR_TYPES, ERROR_TYPES, value_mapping::name, PACKET_TYPES, SWITCH_STUN_TYPE_ATTRIBUTE, SWITCH_STUN_TYPE_ERROR, SWITCH_STUN_TYPE_PACKET_TYPE, and value_mapping::value.

00308 {
00309         uint32_t x = 0;
00310         const struct value_mapping *map = NULL;
00311         switch (type) {
00312         case SWITCH_STUN_TYPE_PACKET_TYPE:
00313                 map = PACKET_TYPES;
00314                 break;
00315         case SWITCH_STUN_TYPE_ATTRIBUTE:
00316                 map = ATTR_TYPES;
00317                 break;
00318         case SWITCH_STUN_TYPE_ERROR:
00319                 map = ERROR_TYPES;
00320                 break;
00321         default:
00322                 map = NULL;
00323                 break;
00324         }
00325 
00326         if (map) {
00327                 for (x = 0; map[x].value; x++) {
00328                         if (map[x].value == value) {
00329                                 return map[x].name;
00330                         }
00331                 }
00332         }
00333 
00334         return "INVALID";
00335 }


Generated on Wed May 16 04:00:20 2012 for FreeSWITCH API Documentation by  doxygen 1.4.7