FreeSWITCH API Documentation  1.7.0
Data Structures | Macros | Enumerations | Functions
STUN code
+ 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
 
struct  switch_stun_error_code_t
 

Macros

#define SWITCH_STUN_DEFAULT_PORT   3478
 
#define SWITCH_STUN_PACKET_MIN_LEN   20
 
#define SWITCH_STUN_ATTRIBUTE_MIN_LEN   8
 
#define STUN_MAGIC_COOKIE   0x2112A442
 
#define switch_stun_attribute_padded_length(attribute)   (int16_t)((attribute->length & 0x3) ? 0x4 + (attribute->length & ~0x3) : attribute->length)
 Obtain the padded length of an attribute's value. More...
 
#define switch_stun_attribute_padded_length_hbo(attribute)   (int16_t)((ntohs(attribute->length) & 0x3) ? 0x4 + (ntohs(attribute->length) & ~0x3) : ntohs(attribute->length))
 
#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 More...
 
#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->type && (((switch_byte_t *)attribute + switch_stun_attribute_padded_length(attribute)) < (switch_byte_t *)end))
 Increment an attribute pointer to the next attribute in it's packet. More...
 
#define switch_stun_packet_next_attribute_hbo(attribute, end)   (attribute && (attribute = (switch_stun_packet_attribute_t *) (attribute->value + switch_stun_attribute_padded_length_hbo(attribute))) && ((void *)attribute < end) && attribute->type && (((switch_byte_t *)attribute + switch_stun_attribute_padded_length_hbo(attribute)) < (switch_byte_t *)end))
 
#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. More...
 

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,
  SWITCH_STUN_ATTR_XOR_MAPPED_ADDRESS = 0x0020, SWITCH_STUN_ATTR_PRIORITY = 0x0024, SWITCH_STUN_ATTR_USE_CAND = 0x0025, SWITCH_STUN_ATTR_PADDING = 0x0026,
  SWITCH_STUN_ATTR_RESP_PORT = 0x0027, SWITCH_STUN_ATTR_SOFTWARE = 0x8022, SWITCH_STUN_ATTR_ALT_SERVER = 0x8023, SWITCH_STUN_ATTR_FINGERPRINT = 0x8028,
  SWITCH_STUN_ATTR_CONTROLLED = 0x8029, SWITCH_STUN_ATTR_CONTROLLING = 0x802a, SWITCH_STUN_ATTR_RESP_ORIGIN = 0x802b, SWITCH_STUN_ATTR_OTHER_ADDR = 0x802c
}
 
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. More...
 
switch_stun_packet_tswitch_stun_packet_parse (uint8_t *buf, uint32_t len)
 Prepare a raw packet for parsing. More...
 
const char * switch_stun_value_to_name (int32_t type, uint32_t value)
 Obtain a printable string form of a given value. More...
 
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, switch_size_t iplen, uint16_t *port)
 Extract a mapped address (IP:PORT) from a packet attribute. More...
 
uint8_t switch_stun_packet_attribute_get_xor_mapped_address (switch_stun_packet_attribute_t *attribute, switch_stun_packet_header_t *header, char *ipstr, switch_size_t iplen, uint16_t *port)
 
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. More...
 
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. More...
 
uint8_t switch_stun_packet_attribute_add_username (switch_stun_packet_t *packet, char *username, uint16_t ulen)
 Add a username packet attribute. More...
 
uint8_t switch_stun_packet_attribute_add_password (switch_stun_packet_t *packet, char *password, uint16_t ulen)
 
uint8_t switch_stun_packet_attribute_add_software (switch_stun_packet_t *packet, char *software, uint16_t ulen)
 
uint8_t switch_stun_packet_attribute_add_binded_address (switch_stun_packet_t *packet, char *ipstr, uint16_t port, int family)
 Add a binded address packet attribute. More...
 
uint8_t switch_stun_packet_attribute_add_xor_binded_address (switch_stun_packet_t *packet, char *ipstr, uint16_t port, int family)
 
uint8_t switch_stun_packet_attribute_add_integrity (switch_stun_packet_t *packet, const char *pass)
 
uint32_t switch_crc32_8bytes (const void *data, size_t length)
 
uint8_t switch_stun_packet_attribute_add_fingerprint (switch_stun_packet_t *packet)
 
uint8_t switch_stun_packet_attribute_add_use_candidate (switch_stun_packet_t *packet)
 
uint8_t switch_stun_packet_attribute_add_controlling (switch_stun_packet_t *packet)
 
uint8_t switch_stun_packet_attribute_add_controlled (switch_stun_packet_t *packet)
 
uint8_t switch_stun_packet_attribute_add_priority (switch_stun_packet_t *packet, uint32_t priority)
 
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. More...
 

Detailed Description

Macro Definition Documentation

#define STUN_MAGIC_COOKIE   0x2112A442
#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)    (int16_t)((attribute->length & 0x3) ? 0x4 + (attribute->length & ~0x3) : attribute->length)

Obtain the padded length of an attribute's value.

Parameters
attributethe attribute
Returns
the padded size in bytes

Definition at line 268 of file switch_stun.h.

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

#define switch_stun_attribute_padded_length_hbo (   attribute)    (int16_t)((ntohs(attribute->length) & 0x3) ? 0x4 + (ntohs(attribute->length) & ~0x3) : ntohs(attribute->length))

Definition at line 269 of file switch_stun.h.

#define SWITCH_STUN_DEFAULT_PORT   3478

Definition at line 41 of file switch_stun.h.

Referenced by switch_core_media_ext_address_lookup().

#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
packetthe packet in question
attributethe pointer to set up

Definition at line 277 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
packetthe packet in question
Returns
the size in bytes (host order) of the entire packet

Definition at line 295 of file switch_stun.h.

Referenced by 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->type && (((switch_byte_t *)attribute + switch_stun_attribute_padded_length(attribute)) < (switch_byte_t *)end))

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

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

Definition at line 286 of file switch_stun.h.

Referenced by handle_ice(), and switch_stun_lookup().

#define switch_stun_packet_next_attribute_hbo (   attribute,
  end 
)    (attribute && (attribute = (switch_stun_packet_attribute_t *) (attribute->value + switch_stun_attribute_padded_length_hbo(attribute))) && ((void *)attribute < end) && attribute->type && (((switch_byte_t *)attribute + switch_stun_attribute_padded_length_hbo(attribute)) < (switch_byte_t *)end))

Definition at line 288 of file switch_stun.h.

Enumeration Type Documentation

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 
SWITCH_STUN_ATTR_XOR_MAPPED_ADDRESS 
SWITCH_STUN_ATTR_PRIORITY 
SWITCH_STUN_ATTR_USE_CAND 
SWITCH_STUN_ATTR_PADDING 
SWITCH_STUN_ATTR_RESP_PORT 
SWITCH_STUN_ATTR_SOFTWARE 
SWITCH_STUN_ATTR_ALT_SERVER 
SWITCH_STUN_ATTR_FINGERPRINT 
SWITCH_STUN_ATTR_CONTROLLED 
SWITCH_STUN_ATTR_CONTROLLING 
SWITCH_STUN_ATTR_RESP_ORIGIN 
SWITCH_STUN_ATTR_OTHER_ADDR 

Definition at line 62 of file switch_stun.h.

62  {
63  SWITCH_STUN_ATTR_MAPPED_ADDRESS = 0x0001, /* Address */
64  SWITCH_STUN_ATTR_RESPONSE_ADDRESS = 0x0002, /* Address */
65  SWITCH_STUN_ATTR_CHANGE_REQUEST = 0x0003, /* UInt32 */
66  SWITCH_STUN_ATTR_SOURCE_ADDRESS = 0x0004, /* Address */
67  SWITCH_STUN_ATTR_CHANGED_ADDRESS = 0x0005, /* Address */
68  SWITCH_STUN_ATTR_USERNAME = 0x0006, /* ByteString, multiple of 4 bytes */
69  SWITCH_STUN_ATTR_PASSWORD = 0x0007, /* ByteString, multiple of 4 bytes */
70  SWITCH_STUN_ATTR_MESSAGE_INTEGRITY = 0x0008, /* ByteString, 20 bytes */
71  SWITCH_STUN_ATTR_ERROR_CODE = 0x0009, /* ErrorCode */
72  SWITCH_STUN_ATTR_UNKNOWN_ATTRIBUTES = 0x000a, /* UInt16List */
73  SWITCH_STUN_ATTR_REFLECTED_FROM = 0x000b, /* Address */
74  SWITCH_STUN_ATTR_TRANSPORT_PREFERENCES = 0x000c, /* TransportPrefs */
75  SWITCH_STUN_ATTR_LIFETIME = 0x000d, /* UInt32 */
76  SWITCH_STUN_ATTR_ALTERNATE_SERVER = 0x000e, /* Address */
77  SWITCH_STUN_ATTR_MAGIC_COOKIE = 0x000f, /* ByteString, 4 bytes */
78  SWITCH_STUN_ATTR_BANDWIDTH = 0x0010, /* UInt32 */
79  SWITCH_STUN_ATTR_DESTINATION_ADDRESS = 0x0011, /* Address */
80  SWITCH_STUN_ATTR_SOURCE_ADDRESS2 = 0x0012, /* Address */
81  SWITCH_STUN_ATTR_DATA = 0x0013, /* ByteString */
82  SWITCH_STUN_ATTR_OPTIONS = 0x8001, /* UInt32 */
83  SWITCH_STUN_ATTR_XOR_MAPPED_ADDRESS = 0x0020, /* Address */
84 
85  /* ice crap */
86 
89  SWITCH_STUN_ATTR_PADDING = 0x0026,
98 
switch_stun_attribute_t
Definition: switch_stun.h:62
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 101 of file switch_stun.h.

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.

Enumerator
SWITCH_STUN_TYPE_PACKET_TYPE 
SWITCH_STUN_TYPE_ATTRIBUTE 
SWITCH_STUN_TYPE_ERROR 

Definition at line 113 of file switch_stun.h.

Function Documentation

uint32_t switch_crc32_8bytes ( const void *  data,
size_t  length 
)

Definition at line 1140 of file switch_stun.c.

References crc32Lookup.

Referenced by switch_stun_packet_attribute_add_fingerprint().

1141 {
1142  uint32_t *current = (uint32_t *) data;
1143  uint32_t previousCrc32 = 0;
1144  uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF
1145  uint8_t *currentChar;
1146 
1147  // process eight bytes at once
1148  while (length >= 8)
1149  {
1150  uint32_t one = *current++ ^ crc;
1151  uint32_t two = *current++;
1152  crc = crc32Lookup[7][ one & 0xFF] ^
1153  crc32Lookup[6][(one>> 8) & 0xFF] ^
1154  crc32Lookup[5][(one>>16) & 0xFF] ^
1155  crc32Lookup[4][ one>>24 ] ^
1156  crc32Lookup[3][ two & 0xFF] ^
1157  crc32Lookup[2][(two>> 8) & 0xFF] ^
1158  crc32Lookup[1][(two>>16) & 0xFF] ^
1159  crc32Lookup[0][ two>>24 ];
1160  length -= 8;
1161  }
1162 
1163  currentChar = (uint8_t*) current;
1164  // remaining 1 to 7 bytes (standard CRC table-based algorithm)
1165  while (length--)
1166  crc = (crc >> 8) ^ crc32Lookup[0][(crc & 0xFF) ^ *currentChar++];
1167 
1168  return ~crc; // same as crc ^ 0xFFFFFFFF
1169 }
const uint32_t crc32Lookup[8][256]
look-up table, already defined in line 18
Definition: switch_stun.c:849
char* switch_stun_host_lookup ( const char *  host,
switch_memory_pool_t pool 
)

Definition at line 688 of file switch_stun.c.

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

Referenced by switch_core_media_ext_address_lookup().

689 {
690  switch_sockaddr_t *addr = NULL;
691  char buf[30];
692 
693  switch_sockaddr_info_get(&addr, host, SWITCH_UNSPEC, 0, 0, pool);
694  return switch_core_strdup(pool, switch_str_nil(switch_get_addr(buf, sizeof(buf), addr)));
695 
696 }
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:729
switch_memory_pool_t * pool
switch_byte_t switch_byte_t * buf
struct apr_sockaddr_t switch_sockaddr_t
Definition: switch_apr.h:1029
#define switch_str_nil(s)
Make a null string a blank string instead.
Definition: switch_utils.h:903
#define SWITCH_UNSPEC
Definition: switch_apr.h:1022
const char * switch_get_addr(char *buf, switch_size_t len, switch_sockaddr_t *in)
Definition: switch_apr.c:894
switch_status_t switch_sockaddr_info_get(switch_sockaddr_t **sa, const char *hostname, int32_t family, switch_port_t port, int32_t flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:817
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
ipthe local ip to use (replaced with stun results)
portthe local port to use (replaced with stun results)
stunipthe ip of the stun server
stunportthe port of the stun server
erra pointer to describe errors
poolthe memory pool to use
Returns
SUCCESS or FAIL

Definition at line 698 of file switch_stun.c.

References switch_stun_ip_t::address, buf, switch_stun_packet_t::header, switch_stun_packet_header_t::length, 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_ATTR_XOR_MAPPED_ADDRESS, switch_stun_attribute_padded_length, 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_attribute_get_xor_mapped_address(), 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_header_t::type, switch_stun_packet_attribute_t::type, and switch_stun_packet_attribute_t::value.

Referenced by switch_core_media_ext_address_lookup().

700 {
701  switch_sockaddr_t *local_addr = NULL, *remote_addr = NULL, *from_addr = NULL;
702  switch_socket_t *sock = NULL;
703  uint8_t buf[260] = { 0 };
704  uint8_t *start = buf;
705  void *end_buf;
706  switch_stun_packet_t *packet;
708  switch_size_t bytes = 0;
709  char username[33] = { 0 };
710  char rip[50] = { 0 };
711  uint16_t rport = 0;
712  switch_time_t started = 0;
713  unsigned int elapsed = 0;
714  int funny = 0;
715  int size = sizeof(buf);
716  int xlen = sizeof(switch_stun_packet_header_t);
717 
718  switch_assert(err);
719 
720  if (*err && !strcmp(*err, "funny")) {
721  funny = 1;
722  }
723 
724  *err = "Success";
725 
726  switch_sockaddr_info_get(&from_addr, NULL, SWITCH_UNSPEC, 0, 0, pool);
727 
728  if (switch_sockaddr_info_get(&local_addr, *ip, SWITCH_UNSPEC, *port, 0, pool) != SWITCH_STATUS_SUCCESS) {
729  *err = "Local Address Error!";
730  return SWITCH_STATUS_FALSE;
731  }
732 
733  if (switch_sockaddr_info_get(&remote_addr, stunip, SWITCH_UNSPEC, stunport, 0, pool) != SWITCH_STATUS_SUCCESS) {
734  *err = "Remote Address Error!";
735  return SWITCH_STATUS_FALSE;
736  }
737 
738  if (switch_socket_create(&sock, AF_INET, SOCK_DGRAM, 0, pool) != SWITCH_STATUS_SUCCESS) {
739  *err = "Socket Error!";
740  return SWITCH_STATUS_FALSE;
741  }
742 
743  if (switch_socket_bind(sock, local_addr) != SWITCH_STATUS_SUCCESS) {
744  *err = "Bind Error!";
745  return SWITCH_STATUS_FALSE;
746  }
747 
748  if (funny) {
749  *start++ = 0;
750  *start++ = 0;
751  *start++ = 0x22;
752  *start++ = 0x22;
753  }
754 
757  switch_stun_random_string(username, 32, NULL);
758  switch_stun_packet_attribute_add_username(packet, username, 32);
759  bytes = switch_stun_packet_length(packet);
760 
761  if (funny) {
762  packet = (switch_stun_packet_t *) buf;
763  bytes += 4;
764  buf[bytes++] = 0;
765  buf[bytes++] = 0;
766  buf[bytes++] = 0;
767  buf[bytes++] = 0;
768  }
769 
770  switch_socket_sendto(sock, remote_addr, 0, (void *) packet, &bytes);
771  started = switch_micro_time_now();
772 
773  *ip = NULL;
774  *port = 0;
775 
776 
777  for (;;) {
778  bytes = sizeof(buf);
779  if (switch_socket_recvfrom(from_addr, sock, 0, (char *) &buf, &bytes) == SWITCH_STATUS_SUCCESS && bytes > 0) {
780  break;
781  }
782 
783  if ((elapsed = (unsigned int) ((switch_micro_time_now() - started) / 1000)) > 5000) {
784  *err = "Timeout";
786  switch_socket_close(sock);
787  return SWITCH_STATUS_TIMEOUT;
788  }
790  }
791  switch_socket_close(sock);
792 
793  if (funny) {
794  size -= 4;
795  }
796 
797  packet = switch_stun_packet_parse(start, size);
798  if (!packet) {
799  *err = "Invalid STUN/ICE packet";
800  return SWITCH_STATUS_FALSE;
801  }
802  end_buf = buf + ((sizeof(buf) > packet->header.length) ? packet->header.length : sizeof(buf));
803 
805  do {
806  switch (attr->type) {
808  if (attr->type) {
809  if (funny) {
810  switch_stun_ip_t *tmp = (switch_stun_ip_t *) attr->value;
811  tmp->address ^= ntohl(0xabcdabcd);
812  }
813  switch_stun_packet_attribute_get_mapped_address(attr, rip, sizeof(rip), &rport);
814  }
815  break;
817  if (attr->type) {
818  switch_stun_packet_attribute_get_xor_mapped_address(attr, &packet->header, rip, sizeof(rip), &rport);
819  }
820  break;
822  if (attr->type) {
823  switch_stun_packet_attribute_get_username(attr, username, 32);
824  }
825  break;
826  }
827 
828  if (!switch_stun_packet_next_attribute(attr, end_buf)) {
829  break;
830  }
831  xlen += 4 + switch_stun_attribute_padded_length(attr);
832  } while (xlen <= packet->header.length);
833 
834  if (packet->header.type == SWITCH_STUN_BINDING_RESPONSE) {
835  *ip = switch_core_strdup(pool, rip);
836  *port = rport;
837  return SWITCH_STATUS_SUCCESS;
838  } else {
839  *err = "Invalid Reply";
840  }
841 
842  return SWITCH_STATUS_FALSE;
843 }
switch_time_t switch_micro_time_now(void)
Get the current epoch time in microseconds.
Definition: switch_time.c:310
switch_status_t switch_socket_bind(switch_socket_t *sock, switch_sockaddr_t *sa)
Definition: switch_apr.c:719
uint32_t address
Definition: switch_stun.h:141
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:729
switch_memory_pool_t * pool
switch_status_t switch_socket_recvfrom(switch_sockaddr_t *from, switch_socket_t *sock, int32_t flags, char *buf, size_t *len)
Definition: switch_apr.c:936
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.
Definition: switch_stun.c:431
uint8_t switch_stun_packet_attribute_add_username(switch_stun_packet_t *packet, char *username, uint16_t ulen)
Add a username packet attribute.
Definition: switch_stun.c:616
int64_t switch_time_t
Definition: switch_apr.h:188
switch_byte_t switch_byte_t * buf
void switch_stun_random_string(char *buf, uint16_t len, char *set)
Writes random characters into a buffer.
Definition: switch_stun.c:125
switch_status_t switch_socket_sendto(switch_socket_t *sock, switch_sockaddr_t *where, int32_t flags, const char *buf, switch_size_t *len)
Definition: switch_apr.c:773
struct apr_sockaddr_t switch_sockaddr_t
Definition: switch_apr.h:1029
#define switch_stun_packet_first_attribute(packet, attribute)
set a switch_stun_packet_attribute_t pointer to point at the first attribute in a packet ...
Definition: switch_stun.h:277
#define switch_stun_attribute_padded_length(attribute)
Obtain the padded length of an attribute's value.
Definition: switch_stun.h:268
#define switch_stun_packet_length(packet)
Obtain the correct length in bytes of a stun packet.
Definition: switch_stun.h:295
switch_status_t switch_socket_opt_set(switch_socket_t *sock, int32_t opt, int32_t on)
Definition: switch_apr.c:823
uintptr_t switch_size_t
void switch_cond_next(void)
Definition: switch_time.c:638
switch_stun_packet_header_t header
Definition: switch_stun.h:133
#define switch_stun_packet_next_attribute(attribute, end)
Increment an attribute pointer to the next attribute in it's packet.
Definition: switch_stun.h:286
switch_status_t switch_socket_create(switch_socket_t **new_sock, int family, int type, int protocol, switch_memory_pool_t *pool)
Definition: switch_apr.c:704
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.
Definition: switch_stun.c:423
#define SWITCH_SO_NONBLOCK
Definition: switch_apr.h:994
switch_status_t switch_socket_close(switch_socket_t *sock)
Definition: switch_apr.c:714
#define SWITCH_UNSPEC
Definition: switch_apr.h:1022
switch_status_t switch_socket_shutdown(switch_socket_t *sock, switch_shutdown_how_e how)
Definition: switch_apr.c:709
uint8_t switch_stun_packet_attribute_get_xor_mapped_address(switch_stun_packet_attribute_t *attribute, switch_stun_packet_header_t *header, char *ipstr, switch_size_t iplen, uint16_t *port)
Definition: switch_stun.c:394
switch_stun_packet_t * switch_stun_packet_parse(uint8_t *buf, uint32_t len)
Prepare a raw packet for parsing.
Definition: switch_stun.c:144
#define TRUE
struct apr_socket_t switch_socket_t
Definition: switch_apr.h:1026
#define switch_assert(expr)
switch_status_t switch_sockaddr_info_get(switch_sockaddr_t **sa, const char *hostname, int32_t family, switch_port_t port, int32_t flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:817
uint8_t switch_stun_packet_attribute_get_mapped_address(switch_stun_packet_attribute_t *attribute, char *ipstr, switch_size_t iplen, uint16_t *port)
Extract a mapped address (IP:PORT) from a packet attribute.
Definition: switch_stun.c:377
uint8_t switch_stun_packet_attribute_add_binded_address ( switch_stun_packet_t packet,
char *  ipstr,
uint16_t  port,
int  family 
)

Add a binded address packet attribute.

Parameters
packetthe packet to add the attribute to
ipstrthe string representation of the ip
portthe port of the mapped address
Returns
true or false

Definition at line 451 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, STUN_MAGIC_COOKIE, SWITCH_STUN_ATTR_XOR_MAPPED_ADDRESS, switch_stun_packet_attribute_t::type, and switch_stun_packet_attribute_t::value.

452 {
454  switch_stun_ip_t *ip;
455 
456  attribute = (switch_stun_packet_attribute_t *) ((uint8_t *) & packet->first_attribute + ntohs(packet->header.length));
457  attribute->type = htons(SWITCH_STUN_ATTR_XOR_MAPPED_ADDRESS);
458 
459  if (family == AF_INET6) {
460  attribute->length = htons(20);
461  } else {
462  attribute->length = htons(8);
463  }
464 
465  ip = (switch_stun_ip_t *) attribute->value;
466 
467  ip->port = htons(port ^ (STUN_MAGIC_COOKIE >> 16));
468 
469  if (family == AF_INET6) {
470  ip->family = 2;
471  } else {
472  ip->family = 1;
473  }
474 
475  if (family == AF_INET6) {
476  inet_pton(AF_INET6, ipstr, (struct in6_addr *) &ip->address);
477  } else {
478  inet_pton(AF_INET, ipstr, (int *) &ip->address);
479  }
480 
481  packet->header.length += htons(sizeof(switch_stun_packet_attribute_t)) + attribute->length;
482  return 1;
483 }
#define STUN_MAGIC_COOKIE
Definition: switch_stun.h:60
uint32_t address
Definition: switch_stun.h:141
uint8_t first_attribute[]
Definition: switch_stun.h:134
switch_stun_packet_header_t header
Definition: switch_stun.h:133
uint8_t switch_stun_packet_attribute_add_controlled ( switch_stun_packet_t packet)

Definition at line 600 of file switch_stun.c.

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

Referenced by ice_out().

601 {
603  char buf[8];
604 
605  switch_stun_random_string(buf, 8, NULL);
606 
607  attribute = (switch_stun_packet_attribute_t *) ((uint8_t *) & packet->first_attribute + ntohs(packet->header.length));
608  attribute->type = htons(SWITCH_STUN_ATTR_CONTROLLED);
609  attribute->length = htons(8);
610  memcpy(attribute->value, buf, 8);
611  packet->header.length += htons(sizeof(switch_stun_packet_attribute_t)) + attribute->length;
612  return 1;
613 }
switch_byte_t switch_byte_t * buf
void switch_stun_random_string(char *buf, uint16_t len, char *set)
Writes random characters into a buffer.
Definition: switch_stun.c:125
uint8_t first_attribute[]
Definition: switch_stun.h:134
switch_stun_packet_header_t header
Definition: switch_stun.h:133
uint8_t switch_stun_packet_attribute_add_controlling ( switch_stun_packet_t packet)

Definition at line 585 of file switch_stun.c.

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

Referenced by ice_out().

586 {
588  char buf[8];
589 
590  switch_stun_random_string(buf, 8, NULL);
591 
592  attribute = (switch_stun_packet_attribute_t *) ((uint8_t *) & packet->first_attribute + ntohs(packet->header.length));
593  attribute->type = htons(SWITCH_STUN_ATTR_CONTROLLING);
594  attribute->length = htons(8);
595  memcpy(attribute->value, buf, 8);
596  packet->header.length += htons(sizeof(switch_stun_packet_attribute_t)) + attribute->length;
597  return 1;
598 }
switch_byte_t switch_byte_t * buf
void switch_stun_random_string(char *buf, uint16_t len, char *set)
Writes random characters into a buffer.
Definition: switch_stun.c:125
uint8_t first_attribute[]
Definition: switch_stun.h:134
switch_stun_packet_header_t header
Definition: switch_stun.h:133
uint8_t switch_stun_packet_attribute_add_fingerprint ( switch_stun_packet_t packet)

Definition at line 552 of file switch_stun.c.

References switch_stun_packet_attribute_t::length, switch_crc32_8bytes(), SWITCH_STUN_ATTR_FINGERPRINT, switch_stun_packet_attribute_t::type, and switch_stun_packet_attribute_t::value.

Referenced by handle_ice(), and ice_out().

553 {
555  uint32_t crc;
556  uint16_t xlen;
557 
558  attribute = (switch_stun_packet_attribute_t *) ((uint8_t *) & packet->first_attribute + ntohs(packet->header.length));
559  attribute->type = htons(SWITCH_STUN_ATTR_FINGERPRINT);
560  attribute->length = htons(4);
561 
562  xlen = ntohs(packet->header.length) + sizeof(switch_stun_packet_header_t);
563 
564  packet->header.length += htons(sizeof(switch_stun_packet_attribute_t)) + attribute->length;
565 
566  crc = htonl(switch_crc32_8bytes(packet, xlen) ^ 0x5354554e);
567 
568  memcpy(attribute->value, &crc, 4);
569 
570  return 1;
571 }
uint32_t switch_crc32_8bytes(const void *data, size_t length)
Definition: switch_stun.c:1140
uint8_t first_attribute[]
Definition: switch_stun.h:134
switch_stun_packet_header_t header
Definition: switch_stun.h:133
uint8_t switch_stun_packet_attribute_add_integrity ( switch_stun_packet_t packet,
const char *  pass 
)

Definition at line 535 of file switch_stun.c.

References switch_stun_packet_attribute_t::length, SWITCH_STUN_ATTR_MESSAGE_INTEGRITY, switch_stun_packet_attribute_t::type, and switch_stun_packet_attribute_t::value.

Referenced by handle_ice(), and ice_out().

536 {
538  uint16_t xlen;
539 
540  attribute = (switch_stun_packet_attribute_t *) ((uint8_t *) & packet->first_attribute + ntohs(packet->header.length));
541  attribute->type = htons(SWITCH_STUN_ATTR_MESSAGE_INTEGRITY);
542  attribute->length = htons(20);
543 
544  xlen = ntohs(packet->header.length) + sizeof(switch_stun_packet_header_t);
545  packet->header.length += htons(sizeof(switch_stun_packet_attribute_t)) + attribute->length;
546 
547  HMAC(EVP_sha1(), (unsigned char *)pass, (int)strlen(pass), (void *)packet, xlen, (void *)attribute->value, NULL);
548 
549  return 1;
550 }
uint8_t first_attribute[]
Definition: switch_stun.h:134
switch_stun_packet_header_t header
Definition: switch_stun.h:133
uint8_t switch_stun_packet_attribute_add_password ( switch_stun_packet_t packet,
char *  password,
uint16_t  ulen 
)

Definition at line 664 of file switch_stun.c.

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

665 {
667  int m = ulen % 4;
668  int padding = 0;
669 
670  if (m) {
671  padding = 4 - m;
672  }
673 
674  attribute = (switch_stun_packet_attribute_t *) ((uint8_t *) & packet->first_attribute + ntohs(packet->header.length));
675  attribute->type = htons(SWITCH_STUN_ATTR_PASSWORD);
676  attribute->length = htons(ulen);
677  if (password) {
678  memcpy(attribute->value, password, ulen);
679  } else {
680  switch_stun_random_string(attribute->value, ulen, NULL);
681  }
682 
683  packet->header.length += htons((u_short)(sizeof(switch_stun_packet_attribute_t) + padding)) + attribute->length;
684 
685  return 1;
686 }
void switch_stun_random_string(char *buf, uint16_t len, char *set)
Writes random characters into a buffer.
Definition: switch_stun.c:125
uint8_t first_attribute[]
Definition: switch_stun.h:134
switch_stun_packet_header_t header
Definition: switch_stun.h:133
uint8_t switch_stun_packet_attribute_add_priority ( switch_stun_packet_t packet,
uint32_t  priority 
)

Definition at line 521 of file switch_stun.c.

References switch_stun_packet_attribute_t::length, SWITCH_STUN_ATTR_PRIORITY, switch_stun_packet_attribute_t::type, and switch_stun_packet_attribute_t::value.

Referenced by ice_out().

522 {
524 
525  priority = htonl(priority);
526  attribute = (switch_stun_packet_attribute_t *) ((uint8_t *) & packet->first_attribute + ntohs(packet->header.length));
527  attribute->type = htons(SWITCH_STUN_ATTR_PRIORITY);
528  attribute->length = htons(4);
529  memcpy(attribute->value, &priority, 4);
530 
531  packet->header.length += htons(sizeof(switch_stun_packet_attribute_t)) + attribute->length;
532  return 1;
533 }
uint8_t first_attribute[]
Definition: switch_stun.h:134
switch_stun_packet_header_t header
Definition: switch_stun.h:133
uint8_t switch_stun_packet_attribute_add_software ( switch_stun_packet_t packet,
char *  software,
uint16_t  ulen 
)

Definition at line 640 of file switch_stun.c.

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

Referenced by ice_out().

641 {
643  int m = ulen % 4;
644  int padding = 0;
645 
646  if (m) {
647  padding = 4 - m;
648  }
649 
650  attribute = (switch_stun_packet_attribute_t *) ((uint8_t *) & packet->first_attribute + ntohs(packet->header.length));
651  attribute->type = htons(SWITCH_STUN_ATTR_SOFTWARE);
652  attribute->length = htons(ulen);
653  if (software) {
654  memcpy(attribute->value, software, ulen);
655  } else {
656  switch_stun_random_string(attribute->value, ulen, NULL);
657  }
658 
659  packet->header.length += htons((u_short)(sizeof(switch_stun_packet_attribute_t) + padding)) + attribute->length;
660 
661  return 1;
662 }
void switch_stun_random_string(char *buf, uint16_t len, char *set)
Writes random characters into a buffer.
Definition: switch_stun.c:125
uint8_t first_attribute[]
Definition: switch_stun.h:134
switch_stun_packet_header_t header
Definition: switch_stun.h:133
uint8_t switch_stun_packet_attribute_add_use_candidate ( switch_stun_packet_t packet)

Definition at line 574 of file switch_stun.c.

References switch_stun_packet_attribute_t::length, SWITCH_STUN_ATTR_USE_CAND, and switch_stun_packet_attribute_t::type.

Referenced by ice_out().

575 {
577 
578  attribute = (switch_stun_packet_attribute_t *) ((uint8_t *) & packet->first_attribute + ntohs(packet->header.length));
579  attribute->type = htons(SWITCH_STUN_ATTR_USE_CAND);
580  attribute->length = htons(0);
581  packet->header.length += htons(sizeof(switch_stun_packet_attribute_t)) + attribute->length;
582  return 1;
583 }
uint8_t first_attribute[]
Definition: switch_stun.h:134
switch_stun_packet_header_t header
Definition: switch_stun.h:133
uint8_t switch_stun_packet_attribute_add_username ( switch_stun_packet_t packet,
char *  username,
uint16_t  ulen 
)

Add a username packet attribute.

Parameters
packetthe packet to add the attribute to
usernamethe string representation of the username
ulenthe length of the username
Returns
true or false

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

617 {
619  int m = ulen % 4;
620  int padding = 0;
621 
622  if (m) {
623  padding = 4 - m;
624  }
625 
626  attribute = (switch_stun_packet_attribute_t *) ((uint8_t *) & packet->first_attribute + ntohs(packet->header.length));
627  attribute->type = htons(SWITCH_STUN_ATTR_USERNAME);
628  attribute->length = htons(ulen);
629  if (username) {
630  memcpy(attribute->value, username, ulen);
631  } else {
632  switch_stun_random_string(attribute->value, ulen, NULL);
633  }
634 
635  packet->header.length += htons((u_short)(sizeof(switch_stun_packet_attribute_t) + padding)) + attribute->length;
636 
637  return 1;
638 }
void switch_stun_random_string(char *buf, uint16_t len, char *set)
Writes random characters into a buffer.
Definition: switch_stun.c:125
uint8_t first_attribute[]
Definition: switch_stun.h:134
switch_stun_packet_header_t header
Definition: switch_stun.h:133
uint8_t switch_stun_packet_attribute_add_xor_binded_address ( switch_stun_packet_t packet,
char *  ipstr,
uint16_t  port,
int  family 
)

Definition at line 485 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, STUN_MAGIC_COOKIE, SWITCH_STUN_ATTR_XOR_MAPPED_ADDRESS, switch_stun_packet_attribute_t::type, v6_xor(), and switch_stun_packet_attribute_t::value.

Referenced by handle_ice().

486 {
488  switch_stun_ip_t *ip;
489 
490  attribute = (switch_stun_packet_attribute_t *) ((uint8_t *) & packet->first_attribute + ntohs(packet->header.length));
491  attribute->type = htons(SWITCH_STUN_ATTR_XOR_MAPPED_ADDRESS);
492 
493  if (family == AF_INET6) {
494  attribute->length = htons(20);
495  } else {
496  attribute->length = htons(8);
497  }
498 
499  ip = (switch_stun_ip_t *) attribute->value;
500 
501  ip->port = htons(port ^ (STUN_MAGIC_COOKIE >> 16));
502 
503  if (family == AF_INET6) {
504  ip->family = 2;
505  } else {
506  ip->family = 1;
507  }
508 
509  if (family == AF_INET6) {
510  inet_pton(AF_INET6, ipstr, (struct in6_addr *) &ip->address);
511  v6_xor((uint8_t *)&ip->address, (uint8_t *)packet->header.id);
512  } else {
513  inet_pton(AF_INET, ipstr, (int *) &ip->address);
514  ip->address = htonl(ntohl(ip->address) ^ STUN_MAGIC_COOKIE);
515  }
516 
517  packet->header.length += htons(sizeof(switch_stun_packet_attribute_t)) + attribute->length;
518  return 1;
519 }
#define STUN_MAGIC_COOKIE
Definition: switch_stun.h:60
uint32_t address
Definition: switch_stun.h:141
uint8_t first_attribute[]
Definition: switch_stun.h:134
switch_stun_packet_header_t header
Definition: switch_stun.h:133
static void v6_xor(uint8_t *addr, const uint8_t *transaction_id)
Definition: switch_stun.c:110
uint8_t switch_stun_packet_attribute_get_mapped_address ( switch_stun_packet_attribute_t attribute,
char *  ipstr,
switch_size_t  iplen,
uint16_t *  port 
)

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

Parameters
attributethe attribute from which to extract
ipstra buffer to write the string representation of the ip
portthe port
Returns
true or false

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

378 {
379  switch_stun_ip_t *ip;
380  uint8_t x, *i;
381  char *p = ipstr;
382 
383  ip = (switch_stun_ip_t *) attribute->value;
384  i = (uint8_t *) & ip->address;
385  *ipstr = 0;
386  for (x = 0; x < 4; x++) {
387  sprintf(p, "%u%s", i[x], x == 3 ? "" : ".");
388  p = ipstr + strlen(ipstr);
389  }
390  *port = ip->port;
391  return 1;
392 }
uint32_t address
Definition: switch_stun.h:141
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
attributethe attribute from which to extract
usernamea buffer to write the string representation of the username
lenthe maximum size of the username buffer
Returns
a pointer to the username or NULL

Definition at line 423 of file switch_stun.c.

Referenced by handle_ice(), and switch_stun_lookup().

424 {
425  uint16_t cpylen;
426 
427  cpylen = attribute->length < len ? attribute->length : len;
428  return memcpy(username, attribute->value, cpylen);
429 }
uint8_t switch_stun_packet_attribute_get_xor_mapped_address ( switch_stun_packet_attribute_t attribute,
switch_stun_packet_header_t header,
char *  ipstr,
switch_size_t  iplen,
uint16_t *  port 
)

Definition at line 394 of file switch_stun.c.

References switch_stun_ip_t::address, switch_stun_ip_t::family, if(), switch_stun_ip_t::port, and v6_xor().

Referenced by handle_ice(), and switch_stun_lookup().

395 {
396  switch_stun_ip_t *ip;
397  uint8_t x, *i;
398  char *p = ipstr;
399 
400  ip = (switch_stun_ip_t *) attribute->value;
401 
402  if (ip->family == 2) {
403  uint8_t *v6addr = (uint8_t *) &ip->address;
404  v6_xor(v6addr, (uint8_t *)header->id);
405  inet_ntop(AF_INET6, v6addr, ipstr, iplen);
406  } else {
407  ip->address ^= header->cookie;
408 
409  i = (uint8_t *) & ip->address;
410  *ipstr = 0;
411  for (x = 0; x < 4; x++) {
412  sprintf(p, "%u%s", i[x], x == 3 ? "" : ".");
413  p = ipstr + strlen(ipstr);
414  }
415  }
416 
417  ip->port ^= ntohl(header->cookie) >> 16;
418  *port = ip->port;
419 
420  return 1;
421 }
uint32_t address
Definition: switch_stun.h:141
if((uint32_t)(unpack->cur-unpack->buf) > unpack->buflen)
static void v6_xor(uint8_t *addr, const uint8_t *transaction_id)
Definition: switch_stun.c:110
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
idid to use (NULL for an auto generated id)
typethe stun packet type
bufa pointer to data to use for the packet
Returns
a pointer to a ready-to-use stun packet

Definition at line 431 of file switch_stun.c.

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

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

432 {
434 
435 
436  header = (switch_stun_packet_header_t *) buf;
437  header->type = htons(type);
438  header->length = 0;
439  header->cookie = htonl(STUN_MAGIC_COOKIE);
440 
441  if (id) {
442  memcpy(header->id, id, 12);
443  } else {
444  switch_stun_random_string(header->id, 12, NULL);
445  }
446 
447  return (switch_stun_packet_t *) buf;
448 }
#define STUN_MAGIC_COOKIE
Definition: switch_stun.h:60
switch_byte_t switch_byte_t * buf
void switch_stun_random_string(char *buf, uint16_t len, char *set)
Writes random characters into a buffer.
Definition: switch_stun.c:125
switch_stun_packet_t* switch_stun_packet_parse ( uint8_t *  buf,
uint32_t  len 
)

Prepare a raw packet for parsing.

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

Definition at line 144 of file switch_stun.c.

References switch_stun_ip_t::family, switch_stun_packet_t::header, if(), 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_PRIORITY, SWITCH_STUN_ATTR_REFLECTED_FROM, SWITCH_STUN_ATTR_RESPONSE_ADDRESS, SWITCH_STUN_ATTR_SOFTWARE, 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_ATTR_XOR_MAPPED_ADDRESS, 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_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().

145 {
146  switch_stun_packet_t *packet;
148  uint32_t bytes_left = len;
149  void *end_buf = buf + len;
150  int xlen = 0;
151 
152  if (len < SWITCH_STUN_PACKET_MIN_LEN) {
153  return NULL;
154  }
155 
156  packet = (switch_stun_packet_t *) buf;
157  packet->header.type = ntohs(packet->header.type);
158  packet->header.length = ntohs(packet->header.length);
159  if (packet->header.length > (bytes_left -= 20)) return NULL;
160 
161  /*
162  * Check packet type (RFC3489(bis?) values)
163  */
164  switch (packet->header.type) {
178  /* Valid */
179  break;
180 
181  default:
182  /* Invalid value */
183  return NULL;
184  }
185 
186  /*
187  * Check for length overflow
188  */
189  if (bytes_left <= 0) {
190  /* Invalid */
191  return NULL;
192  }
193 
194  /*
195  * No payload?
196  */
197  if (packet->header.length == 0) {
198  /* Invalid?! */
199  return NULL;
200  }
201 
202  /* check if we have enough bytes left for an attribute */
203  if (bytes_left < SWITCH_STUN_ATTRIBUTE_MIN_LEN) {
204  return NULL;
205  }
206 
208  do {
209  attr->length = ntohs(attr->length);
210  attr->type = ntohs(attr->type);
211  bytes_left -= 4; /* attribute header consumed */
212 
213  if (switch_stun_attribute_padded_length(attr) > (int)bytes_left) {
214  /*
215  * Note we simply don't "break" here out of the loop anymore because
216  * we don't want the upper layers to have to deal with attributes without a value
217  * (or worse: invalid length)
218  */
219  return NULL;
220  }
221 
222  /*
223  * Handle STUN attributes
224  */
225  switch (attr->type) {
226  case SWITCH_STUN_ATTR_MAPPED_ADDRESS: /* Address, we only care about this one, but parse the others too */
235  {
236  switch_stun_ip_t *ip = (switch_stun_ip_t *) attr->value;
237  ip->port = ntohs(ip->port);
238  }
239  break;
241  {
242  switch_stun_ip_t *ip;
243  uint32_t addr_length = 0;
244  ip = (switch_stun_ip_t *) attr->value;
245 
246  switch (ip->family) {
247  case 0x01: /* IPv4 */
248  addr_length = 4;
249  break;
250 
251  case 0x02: /* IPv6 */
252  addr_length = 16;
253  break;
254 
255  default: /* Invalid */
256  return NULL;
257  }
258 
259  /* attribute payload length must be == address length + size of other payload fields (family...) */
260  if (attr->length != addr_length + 4) {
261  /* Invalid */
262  return NULL;
263  }
264 
265  ip->port = ntohs(ip->port);
266  }
267  break;
268 
269  case SWITCH_STUN_ATTR_CHANGE_REQUEST: /* UInt32 */
273  {
274  uint32_t *val = (uint32_t *) attr->value;
275 
276  if (attr->length != sizeof(uint32_t)) {
277  /* Invalid */
278  return NULL;
279  }
280 
281  *val = ntohl(*val); /* should we do this here? */
282  }
283  break;
284  case SWITCH_STUN_ATTR_ERROR_CODE: /* ErrorCode */
285  {
286  uint32_t *u = (uint32_t *) attr->value;
287  *u = htonl(*u);
288  }
289  break;
290 
292  case SWITCH_STUN_ATTR_USERNAME: /* ByteString, multiple of 4 bytes */
293  case SWITCH_STUN_ATTR_PASSWORD: /* ByteString, multiple of 4 bytes */
294  case SWITCH_STUN_ATTR_DATA: /* ByteString */
295  case SWITCH_STUN_ATTR_TRANSPORT_PREFERENCES: /* TransportPrefs */
296  /*
297  * No length checking here, since we already checked against the padded length
298  * before
299  */
300  break;
301 
302  case SWITCH_STUN_ATTR_MESSAGE_INTEGRITY: /* ByteString, 20 bytes */
303  if (attr->length != 20) {
304  /* Invalid */
305  return NULL;
306  }
307  break;
308 
309  case SWITCH_STUN_ATTR_MAGIC_COOKIE: /* ByteString, 4 bytes */
310  if (attr->length != 4) {
311  /* Invalid */
312  return NULL;
313  }
314  break;
315 
316  case SWITCH_STUN_ATTR_UNKNOWN_ATTRIBUTES: /* UInt16List (= multiple of 2 bytes) */
317  if (attr->length % 2 != 0) {
318  return NULL;
319  }
320  break;
321 
322  default:
323  break;
324  }
325 
326  bytes_left -= switch_stun_attribute_padded_length(attr); /* attribute value consumed, substract padded length */
327  xlen += 4 + switch_stun_attribute_padded_length(attr);
328 
330  if ((void *)attr > end_buf) {
331  break;
332  }
333  } while (xlen < packet->header.length);
334 
335  if ((uint32_t) (packet->header.length + 20) > (uint32_t) (len - bytes_left)) {
336  /*
337  * the packet length is longer than the length of all attributes?
338  * for now simply decrease the packet size
339  */
340  packet->header.length = (uint16_t) ((len - bytes_left) - 20);
341  }
342 
343  return packet;
344 }
#define SWITCH_STUN_PACKET_MIN_LEN
Definition: switch_stun.h:42
if((uint32_t)(unpack->cur-unpack->buf) > unpack->buflen)
switch_byte_t switch_byte_t * buf
#define switch_stun_packet_first_attribute(packet, attribute)
set a switch_stun_packet_attribute_t pointer to point at the first attribute in a packet ...
Definition: switch_stun.h:277
#define switch_stun_attribute_padded_length(attribute)
Obtain the padded length of an attribute's value.
Definition: switch_stun.h:268
switch_stun_packet_header_t header
Definition: switch_stun.h:133
#define SWITCH_STUN_ATTRIBUTE_MIN_LEN
Definition: switch_stun.h:43
void switch_stun_random_string ( char *  buf,
uint16_t  len,
char *  set 
)

Writes random characters into a buffer.

Parameters
bufthe buffer
lenthe length of the data
setthe set of chars to use (NULL for auto)

Definition at line 125 of file switch_stun.c.

Referenced by gen_ice(), generate_m(), switch_core_media_gen_local_sdp(), switch_rtp_get_random(), switch_stun_lookup(), switch_stun_packet_attribute_add_controlled(), switch_stun_packet_attribute_add_controlling(), switch_stun_packet_attribute_add_password(), switch_stun_packet_attribute_add_software(), switch_stun_packet_attribute_add_username(), and switch_stun_packet_build_header().

126 {
127  char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
128  int max;
129  uint16_t x;
130 
131  if (!set) {
132  set = chars;
133  }
134 
135  max = (int) strlen(set);
136 
137  for (x = 0; x < len; x++) {
138  int j = (int) (max * 1.0 * rand() / (RAND_MAX + 1.0));
139  buf[x] = set[j];
140  }
141 }
switch_byte_t switch_byte_t * buf
const char* switch_stun_value_to_name ( int32_t  type,
uint32_t  value 
)

Obtain a printable string form of a given value.

Parameters
typethe type of message
valuethe value to look up
Returns
a sring version of value

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

Referenced by handle_ice().

348 {
349  uint32_t x = 0;
350  const struct value_mapping *map = NULL;
351  switch (type) {
353  map = PACKET_TYPES;
354  break;
356  map = ATTR_TYPES;
357  break;
359  map = ERROR_TYPES;
360  break;
361  default:
362  map = NULL;
363  break;
364  }
365 
366  if (map) {
367  for (x = 0; map[x].value; x++) {
368  if (map[x].value == value) {
369  return map[x].name;
370  }
371  }
372  }
373 
374  return "INVALID";
375 }
static const struct value_mapping ERROR_TYPES[]
Definition: switch_stun.c:97
const char * name
Definition: switch_stun.c:41
static const struct value_mapping PACKET_TYPES[]
Definition: switch_stun.c:44
static const struct value_mapping ATTR_TYPES[]
Definition: switch_stun.c:61
const uint32_t value
Definition: switch_stun.c:40