319 lines
12 KiB
C
319 lines
12 KiB
C
/*
|
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
|
* Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
|
|
*
|
|
* Version: MPL 1.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Anthony Minessale II <anthm@freeswitch.org>
|
|
* Portions created by the Initial Developer are Copyright (C)
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Anthony Minessale II <anthm@freeswitch.org>
|
|
*
|
|
*
|
|
* switch_stun.h STUN (Simple Traversal of UDP over NAT)
|
|
*
|
|
*/
|
|
/*!
|
|
\defgroup stun1 STUN code
|
|
\ingroup core1
|
|
\{
|
|
*/
|
|
#ifndef FREESWITCH_STUN_PARSER_H
|
|
#define FREESWITCH_STUN_PARSER_H
|
|
|
|
SWITCH_BEGIN_EXTERN_C
|
|
#define SWITCH_STUN_DEFAULT_PORT 3478
|
|
#define SWITCH_STUN_PACKET_MIN_LEN 20
|
|
#define SWITCH_STUN_ATTRIBUTE_MIN_LEN 8
|
|
typedef enum {
|
|
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
|
|
} 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 */
|
|
SWITCH_STUN_ATTR_CHANGE_REQUEST = 0x0003, /* UInt32 */
|
|
SWITCH_STUN_ATTR_SOURCE_ADDRESS = 0x0004, /* Address */
|
|
SWITCH_STUN_ATTR_CHANGED_ADDRESS = 0x0005, /* Address */
|
|
SWITCH_STUN_ATTR_USERNAME = 0x0006, /* ByteString, multiple of 4 bytes */
|
|
SWITCH_STUN_ATTR_PASSWORD = 0x0007, /* ByteString, multiple of 4 bytes */
|
|
SWITCH_STUN_ATTR_MESSAGE_INTEGRITY = 0x0008, /* ByteString, 20 bytes */
|
|
SWITCH_STUN_ATTR_ERROR_CODE = 0x0009, /* ErrorCode */
|
|
SWITCH_STUN_ATTR_UNKNOWN_ATTRIBUTES = 0x000a, /* UInt16List */
|
|
SWITCH_STUN_ATTR_REFLECTED_FROM = 0x000b, /* Address */
|
|
SWITCH_STUN_ATTR_TRANSPORT_PREFERENCES = 0x000c, /* TransportPrefs */
|
|
SWITCH_STUN_ATTR_LIFETIME = 0x000d, /* UInt32 */
|
|
SWITCH_STUN_ATTR_ALTERNATE_SERVER = 0x000e, /* Address */
|
|
SWITCH_STUN_ATTR_MAGIC_COOKIE = 0x000f, /* ByteString, 4 bytes */
|
|
SWITCH_STUN_ATTR_BANDWIDTH = 0x0010, /* UInt32 */
|
|
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_XOR_MAPPED_ADDRESS = 0x0020, /* Address */
|
|
|
|
/* ice crap */
|
|
|
|
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
|
|
|
|
} switch_stun_attribute_t;
|
|
|
|
typedef enum {
|
|
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
|
|
} switch_stun_error_t;
|
|
|
|
typedef enum {
|
|
SWITCH_STUN_TYPE_PACKET_TYPE,
|
|
SWITCH_STUN_TYPE_ATTRIBUTE,
|
|
SWITCH_STUN_TYPE_ERROR
|
|
} switch_stun_type_t;
|
|
|
|
typedef struct {
|
|
uint16_t type;
|
|
uint16_t length;
|
|
uint32_t cookie;
|
|
char id[12];
|
|
} switch_stun_packet_header_t;
|
|
|
|
typedef struct {
|
|
uint16_t type;
|
|
uint16_t length;
|
|
char value[];
|
|
} switch_stun_packet_attribute_t;
|
|
|
|
typedef struct {
|
|
switch_stun_packet_header_t header;
|
|
uint8_t first_attribute[];
|
|
} switch_stun_packet_t;
|
|
|
|
typedef struct {
|
|
uint8_t wasted;
|
|
uint8_t family;
|
|
uint16_t port;
|
|
uint32_t address;
|
|
} switch_stun_ip_t;
|
|
|
|
#if SWITCH_BYTE_ORDER == __BIG_ENDIAN
|
|
|
|
typedef struct {
|
|
unsigned padding:21;
|
|
unsigned code:3;
|
|
unsigned number:8;
|
|
char reason[764];
|
|
} switch_stun_error_code_t;
|
|
|
|
#else
|
|
|
|
typedef struct {
|
|
unsigned number:8;
|
|
unsigned code:3;
|
|
unsigned padding:21;
|
|
char reason[764];
|
|
} switch_stun_error_code_t;
|
|
|
|
#endif
|
|
|
|
|
|
/*!
|
|
\brief Writes random characters into a buffer
|
|
\param buf the buffer
|
|
\param len the length of the data
|
|
\param set the set of chars to use (NULL for auto)
|
|
*/
|
|
SWITCH_DECLARE(void) switch_stun_random_string(char *buf, uint16_t len, char *set);
|
|
|
|
/*!
|
|
\brief Prepare a raw packet for parsing
|
|
\param buf the raw data
|
|
\param len the length of the data
|
|
\return a stun packet pointer to buf to use as an access point
|
|
*/
|
|
SWITCH_DECLARE(switch_stun_packet_t *) switch_stun_packet_parse(uint8_t *buf, uint32_t len);
|
|
|
|
/*!
|
|
\brief Obtain a printable string form of a given value
|
|
\param type the type of message
|
|
\param value the value to look up
|
|
\return a sring version of value
|
|
*/
|
|
SWITCH_DECLARE(const char *) switch_stun_value_to_name(int32_t type, uint32_t value);
|
|
|
|
SWITCH_DECLARE(char *) switch_stun_host_lookup(const char *host, switch_memory_pool_t *pool);
|
|
|
|
/*!
|
|
\brief Extract a mapped address (IP:PORT) from a packet attribute
|
|
\param attribute the attribute from which to extract
|
|
\param ipstr a buffer to write the string representation of the ip
|
|
\param port the port
|
|
\return true or false
|
|
*/
|
|
SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_get_mapped_address(switch_stun_packet_attribute_t *attribute, char *ipstr, switch_size_t iplen, uint16_t *port);
|
|
SWITCH_DECLARE(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);
|
|
|
|
|
|
/*!
|
|
\brief Extract a username from a packet attribute
|
|
\param attribute the attribute from which to extract
|
|
\param username a buffer to write the string representation of the username
|
|
\param len the maximum size of the username buffer
|
|
\return a pointer to the username or NULL
|
|
*/
|
|
SWITCH_DECLARE(char *) switch_stun_packet_attribute_get_username(switch_stun_packet_attribute_t *attribute, char *username, uint16_t len);
|
|
|
|
|
|
/*!
|
|
\brief Prepare a new outbound packet of a certian type and id
|
|
\param id id to use (NULL for an auto generated id)
|
|
\param type the stun packet type
|
|
\param buf a pointer to data to use for the packet
|
|
\return a pointer to a ready-to-use stun packet
|
|
*/
|
|
SWITCH_DECLARE(switch_stun_packet_t *) switch_stun_packet_build_header(switch_stun_message_t type, char *id, uint8_t *buf);
|
|
|
|
/*!
|
|
\brief Add a username packet attribute
|
|
\param packet the packet to add the attribute to
|
|
\param username the string representation of the username
|
|
\param ulen the length of the username
|
|
\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);
|
|
SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_software(switch_stun_packet_t *packet, char *software, uint16_t ulen);
|
|
|
|
/*!
|
|
\brief Add a binded address packet attribute
|
|
\param packet the packet to add the attribute to
|
|
\param ipstr the string representation of the ip
|
|
\param port the port of the mapped address
|
|
\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, int family);
|
|
SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_xor_binded_address(switch_stun_packet_t *packet, char *ipstr, uint16_t port, int family);
|
|
SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_integrity(switch_stun_packet_t *packet, const char *pass);
|
|
SWITCH_DECLARE(uint32_t) switch_crc32_8bytes(const void* data, size_t length);
|
|
SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_fingerprint(switch_stun_packet_t *packet);
|
|
SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_use_candidate(switch_stun_packet_t *packet);
|
|
SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_controlling(switch_stun_packet_t *packet);
|
|
SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_controlled(switch_stun_packet_t *packet);
|
|
SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_priority(switch_stun_packet_t *packet, uint32_t priority);
|
|
|
|
/*!
|
|
\brief Perform a stun lookup
|
|
\param ip the local ip to use (replaced with stun results)
|
|
\param port the local port to use (replaced with stun results)
|
|
\param stunip the ip of the stun server
|
|
\param stunport the port of the stun server
|
|
\param err a pointer to describe errors
|
|
\param pool the memory pool to use
|
|
\return SUCCESS or FAIL
|
|
*/
|
|
SWITCH_DECLARE(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);
|
|
|
|
/*!
|
|
\brief Perform a stun ip lookup
|
|
\param external_ip replaced with stun results
|
|
\param sourceip stun:, host: or an ip
|
|
\param external_pool the memory pool to use
|
|
\return SUCCESS or FAIL
|
|
*/
|
|
SWITCH_DECLARE(switch_status_t) switch_stun_ip_lookup(char **external_ip, const char *sourceip, switch_memory_pool_t *external_pool);
|
|
|
|
|
|
/*!
|
|
\brief Obtain the padded length of an attribute's value
|
|
\param attribute the attribute
|
|
\return the padded size in bytes
|
|
*/
|
|
#define switch_stun_attribute_padded_length(attribute) (int16_t)((attribute->length & 0x3) ? 0x4 + (attribute->length & ~0x3) : attribute->length)
|
|
#define switch_stun_attribute_padded_length_hbo(attribute) (int16_t)((ntohs(attribute->length) & 0x3) ? 0x4 + (ntohs(attribute->length) & ~0x3) : ntohs(attribute->length))
|
|
|
|
|
|
/*!
|
|
\brief set a switch_stun_packet_attribute_t pointer to point at the first attribute in a packet
|
|
\param packet the packet in question
|
|
\param attribute the pointer to set up
|
|
*/
|
|
#define switch_stun_packet_first_attribute(packet, attribute) attribute = (switch_stun_packet_attribute_t *)(&packet->first_attribute);
|
|
|
|
/*!
|
|
\brief Increment an attribute pointer to the next attribute in it's packet
|
|
\param attribute the pointer to increment
|
|
\param end pointer to the end of the buffer
|
|
\return true or false depending on if there are any more attributes
|
|
*/
|
|
|
|
#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))
|
|
|
|
#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))
|
|
|
|
/*!
|
|
\brief Obtain the correct length in bytes of a stun packet
|
|
\param packet the packet in question
|
|
\return the size in bytes (host order) of the entire packet
|
|
*/
|
|
#define switch_stun_packet_length(packet) ntohs(packet->header.length) + (sizeof(switch_stun_packet_header_t))
|
|
///\}
|
|
|
|
SWITCH_END_EXTERN_C
|
|
#endif
|
|
/* For Emacs:
|
|
* Local Variables:
|
|
* mode:c
|
|
* indent-tabs-mode:t
|
|
* tab-width:4
|
|
* c-basic-offset:4
|
|
* End:
|
|
* For VIM:
|
|
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
|
*/
|