diff --git a/src/include/switch_stun.h b/src/include/switch_stun.h index 7159cf1f3b..fbf6b3270f 100644 --- a/src/include/switch_stun.h +++ b/src/include/switch_stun.h @@ -57,6 +57,8 @@ SWITCH_BEGIN_EXTERN_C SWITCH_STUN_DATA_INDICATION = 0x0115 } switch_stun_message_t; +#define STUN_MAGIC_COOKIE 0x2112A442 + typedef enum { SWITCH_STUN_ATTR_MAPPED_ADDRESS = 0x0001, /* Address */ SWITCH_STUN_ATTR_RESPONSE_ADDRESS = 0x0002, /* Address */ @@ -77,7 +79,8 @@ typedef enum { SWITCH_STUN_ATTR_DESTINATION_ADDRESS = 0x0011, /* Address */ SWITCH_STUN_ATTR_SOURCE_ADDRESS2 = 0x0012, /* Address */ SWITCH_STUN_ATTR_DATA = 0x0013, /* ByteString */ - SWITCH_STUN_ATTR_OPTIONS = 0x8001 /* UInt32 */ + SWITCH_STUN_ATTR_OPTIONS = 0x8001, /* UInt32 */ + SWITCH_STUN_ATTR_XOR_MAPPED_ADDRESS = 0x0020, /* Address */ } switch_stun_attribute_t; typedef enum { @@ -101,7 +104,8 @@ typedef enum { typedef struct { uint16_t type; uint16_t length; - char id[16]; + uint32_t cookie; + char id[12]; } switch_stun_packet_header_t; typedef struct { @@ -185,6 +189,7 @@ SWITCH_DECLARE(switch_stun_packet_t *) switch_stun_packet_build_header(switch_st \return true or false */ SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_username(switch_stun_packet_t *packet, char *username, uint16_t ulen); +SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_password(switch_stun_packet_t *packet, char *password, uint16_t ulen); /*! @@ -195,6 +200,7 @@ SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_username(switch_stun_pa \return true or false */ SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_binded_address(switch_stun_packet_t *packet, char *ipstr, uint16_t port); +SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_xor_binded_address(switch_stun_packet_t *packet, char *ipstr, uint16_t port); /*! \brief Perform a stun lookup diff --git a/src/switch_stun.c b/src/switch_stun.c index 30933fff6a..616cf27a37 100644 --- a/src/switch_stun.c +++ b/src/switch_stun.c @@ -186,7 +186,6 @@ SWITCH_DECLARE(switch_stun_packet_t *) switch_stun_packet_parse(uint8_t *buf, ui * we don't want the upper layers to have to deal with attributes without a value * (or worse: invalid length) */ - return NULL; } /* @@ -367,11 +366,12 @@ SWITCH_DECLARE(switch_stun_packet_t *) switch_stun_packet_build_header(switch_st header = (switch_stun_packet_header_t *) buf; header->type = htons(type); header->length = 0; + header->cookie = htonl(STUN_MAGIC_COOKIE); if (id) { - memcpy(header->id, id, 16); + memcpy(header->id, id, 12); } else { - switch_stun_random_string(header->id, 16, NULL); + switch_stun_random_string(header->id, 12, NULL); } return (switch_stun_packet_t *) buf; @@ -402,6 +402,38 @@ SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_binded_address(switch_s } } + packet->header.length += htons(sizeof(switch_stun_packet_attribute_t)) + attribute->length; + + return 1; +} + +SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_xor_binded_address(switch_stun_packet_t *packet, char *ipstr, uint16_t port) +{ + switch_stun_packet_attribute_t *attribute; + switch_stun_ip_t *ip; + uint8_t *i, x; + char *p = ipstr; + + attribute = (switch_stun_packet_attribute_t *) ((uint8_t *) & packet->first_attribute + ntohs(packet->header.length)); + attribute->type = htons(SWITCH_STUN_ATTR_XOR_MAPPED_ADDRESS); + attribute->length = htons(8); + ip = (switch_stun_ip_t *) attribute->value; + + ip->port = htons(port ^ (STUN_MAGIC_COOKIE >> 16)); + ip->family = 1; + i = (uint8_t *) & ip->address; + + for (x = 0; x < 4; x++) { + i[x] = (uint8_t) atoi(p); + if ((p = strchr(p, '.'))) { + p++; + } else { + break; + } + } + + ip->address = htonl(ntohl(ip->address) ^ STUN_MAGIC_COOKIE); + packet->header.length += htons(sizeof(switch_stun_packet_attribute_t)) + attribute->length; return 1; } @@ -426,6 +458,26 @@ SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_username(switch_stun_pa return 1; } +SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_password(switch_stun_packet_t *packet, char *password, uint16_t ulen) +{ + switch_stun_packet_attribute_t *attribute; + + if (ulen % 4 != 0) { + return 0; + } + attribute = (switch_stun_packet_attribute_t *) ((uint8_t *) & packet->first_attribute + ntohs(packet->header.length)); + attribute->type = htons(SWITCH_STUN_ATTR_PASSWORD); + attribute->length = htons(ulen); + if (password) { + memcpy(attribute->value, password, ulen); + } else { + switch_stun_random_string(attribute->value, ulen, NULL); + } + + packet->header.length += htons(sizeof(switch_stun_packet_attribute_t)) + attribute->length; + return 1; +} + SWITCH_DECLARE(char *) switch_stun_host_lookup(const char *host, switch_memory_pool_t *pool) { switch_sockaddr_t *addr = NULL;