1 /* 2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application 3 * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org> 4 * 5 * Version: MPL 1.1 6 * 7 * The contents of this file are subject to the Mozilla Public License Version 8 * 1.1 (the "License"); you may not use this file except in compliance with 9 * the License. You may obtain a copy of the License at 10 * http://www.mozilla.org/MPL/ 11 * 12 * Software distributed under the License is distributed on an "AS IS" basis, 13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 14 * for the specific language governing rights and limitations under the 15 * License. 16 * 17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application 18 * 19 * The Initial Developer of the Original Code is 20 * Anthony Minessale II <anthm@freeswitch.org> 21 * Portions created by the Initial Developer are Copyright (C) 22 * the Initial Developer. All Rights Reserved. 23 * 24 * Contributor(s): 25 * 26 * Anthony Minessale II <anthm@freeswitch.org> 27 * 28 * 29 * switch_stun.h STUN (Simple Traversal of UDP over NAT) 30 * 31 */ 32 /*! 33 \defgroup stun1 STUN code 34 \ingroup core1 35 \{ 36 */ 37 #ifndef FREESWITCH_STUN_PARSER_H 38 #define FREESWITCH_STUN_PARSER_H 39 40 SWITCH_BEGIN_EXTERN_C 41 #define SWITCH_STUN_DEFAULT_PORT 3478 42 #define SWITCH_STUN_PACKET_MIN_LEN 20 43 #define SWITCH_STUN_ATTRIBUTE_MIN_LEN 8 44 typedef enum { 45 SWITCH_STUN_BINDING_REQUEST = 0x0001, 46 SWITCH_STUN_BINDING_RESPONSE = 0x0101, 47 SWITCH_STUN_BINDING_ERROR_RESPONSE = 0x0111, 48 SWITCH_STUN_SHARED_SECRET_REQUEST = 0x0002, 49 SWITCH_STUN_SHARED_SECRET_RESPONSE = 0x0102, 50 SWITCH_STUN_SHARED_SECRET_ERROR_RESPONSE = 0x0112, 51 SWITCH_STUN_ALLOCATE_REQUEST = 0x0003, 52 SWITCH_STUN_ALLOCATE_RESPONSE = 0x0103, 53 SWITCH_STUN_ALLOCATE_ERROR_RESPONSE = 0x0113, 54 SWITCH_STUN_SEND_REQUEST = 0x0004, 55 SWITCH_STUN_SEND_RESPONSE = 0x0104, 56 SWITCH_STUN_SEND_ERROR_RESPONSE = 0x0114, 57 SWITCH_STUN_DATA_INDICATION = 0x0115 58 } switch_stun_message_t; 59 60 #define STUN_MAGIC_COOKIE 0x2112A442 61 62 typedef enum { 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 87 SWITCH_STUN_ATTR_PRIORITY = 0x0024, 88 SWITCH_STUN_ATTR_USE_CAND = 0x0025, 89 SWITCH_STUN_ATTR_PADDING = 0x0026, 90 SWITCH_STUN_ATTR_RESP_PORT = 0x0027, 91 SWITCH_STUN_ATTR_SOFTWARE = 0x8022, 92 SWITCH_STUN_ATTR_ALT_SERVER = 0x8023, 93 SWITCH_STUN_ATTR_FINGERPRINT = 0x8028, 94 SWITCH_STUN_ATTR_CONTROLLED = 0x8029, 95 SWITCH_STUN_ATTR_CONTROLLING = 0x802a, 96 SWITCH_STUN_ATTR_RESP_ORIGIN = 0x802b, 97 SWITCH_STUN_ATTR_OTHER_ADDR = 0x802c 98 99 } switch_stun_attribute_t; 100 101 typedef enum { 102 SWITCH_STUN_ERROR_BAD_REQUEST = 400, 103 SWITCH_STUN_ERROR_UNAUTHORIZED = 401, 104 SWITCH_STUN_ERROR_UNKNOWN_ATTRIBUTE = 420, 105 SWITCH_STUN_ERROR_STALE_CREDENTIALS = 430, 106 SWITCH_STUN_ERROR_INTEGRITY_CHECK_FAILURE = 431, 107 SWITCH_STUN_ERROR_MISSING_USERNAME = 432, 108 SWITCH_STUN_ERROR_USE_TLS = 433, 109 SWITCH_STUN_ERROR_SERVER_ERROR = 500, 110 SWITCH_STUN_ERROR_GLOBAL_FAILURE = 600 111 } switch_stun_error_t; 112 113 typedef enum { 114 SWITCH_STUN_TYPE_PACKET_TYPE, 115 SWITCH_STUN_TYPE_ATTRIBUTE, 116 SWITCH_STUN_TYPE_ERROR 117 } switch_stun_type_t; 118 119 typedef struct { 120 uint16_t type; 121 uint16_t length; 122 uint32_t cookie; 123 char id[12]; 124 } switch_stun_packet_header_t; 125 126 typedef struct { 127 uint16_t type; 128 uint16_t length; 129 char value[]; 130 } switch_stun_packet_attribute_t; 131 132 typedef struct { 133 switch_stun_packet_header_t header; 134 uint8_t first_attribute[]; 135 } switch_stun_packet_t; 136 137 typedef struct { 138 uint8_t wasted; 139 uint8_t family; 140 uint16_t port; 141 uint32_t address; 142 } switch_stun_ip_t; 143 144 #if SWITCH_BYTE_ORDER == __BIG_ENDIAN 145 146 typedef struct { 147 unsigned padding:21; 148 unsigned code:3; 149 unsigned number:8; 150 char reason[764]; 151 } switch_stun_error_code_t; 152 153 #else 154 155 typedef struct { 156 unsigned number:8; 157 unsigned code:3; 158 unsigned padding:21; 159 char reason[764]; 160 } switch_stun_error_code_t; 161 162 #endif 163 164 165 /*! 166 \brief Writes random characters into a buffer 167 \param buf the buffer 168 \param len the length of the data 169 \param set the set of chars to use (NULL for auto) 170 */ 171 SWITCH_DECLARE(void) switch_stun_random_string(char *buf, uint16_t len, char *set); 172 173 /*! 174 \brief Prepare a raw packet for parsing 175 \param buf the raw data 176 \param len the length of the data 177 \return a stun packet pointer to buf to use as an access point 178 */ 179 SWITCH_DECLARE(switch_stun_packet_t *) switch_stun_packet_parse(uint8_t *buf, uint32_t len); 180 181 /*! 182 \brief Obtain a printable string form of a given value 183 \param type the type of message 184 \param value the value to look up 185 \return a sring version of value 186 */ 187 SWITCH_DECLARE(const char *) switch_stun_value_to_name(int32_t type, uint32_t value); 188 189 SWITCH_DECLARE(char *) switch_stun_host_lookup(const char *host, switch_memory_pool_t *pool); 190 191 /*! 192 \brief Extract a mapped address (IP:PORT) from a packet attribute 193 \param attribute the attribute from which to extract 194 \param ipstr a buffer to write the string representation of the ip 195 \param port the port 196 \return true or false 197 */ 198 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); 199 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); 200 201 202 /*! 203 \brief Extract a username from a packet attribute 204 \param attribute the attribute from which to extract 205 \param username a buffer to write the string representation of the username 206 \param len the maximum size of the username buffer 207 \return a pointer to the username or NULL 208 */ 209 SWITCH_DECLARE(char *) switch_stun_packet_attribute_get_username(switch_stun_packet_attribute_t *attribute, char *username, uint16_t len); 210 211 212 /*! 213 \brief Prepare a new outbound packet of a certian type and id 214 \param id id to use (NULL for an auto generated id) 215 \param type the stun packet type 216 \param buf a pointer to data to use for the packet 217 \return a pointer to a ready-to-use stun packet 218 */ 219 SWITCH_DECLARE(switch_stun_packet_t *) switch_stun_packet_build_header(switch_stun_message_t type, char *id, uint8_t *buf); 220 221 /*! 222 \brief Add a username packet attribute 223 \param packet the packet to add the attribute to 224 \param username the string representation of the username 225 \param ulen the length of the username 226 \return true or false 227 */ 228 SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_username(switch_stun_packet_t *packet, char *username, uint16_t ulen); 229 SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_password(switch_stun_packet_t *packet, char *password, uint16_t ulen); 230 SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_software(switch_stun_packet_t *packet, char *software, uint16_t ulen); 231 232 /*! 233 \brief Add a binded address packet attribute 234 \param packet the packet to add the attribute to 235 \param ipstr the string representation of the ip 236 \param port the port of the mapped address 237 \return true or false 238 */ 239 SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_binded_address(switch_stun_packet_t *packet, char *ipstr, uint16_t port, int family); 240 SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_xor_binded_address(switch_stun_packet_t *packet, char *ipstr, uint16_t port, int family); 241 SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_integrity(switch_stun_packet_t *packet, const char *pass); 242 SWITCH_DECLARE(uint32_t) switch_crc32_8bytes(const void* data, size_t length); 243 SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_fingerprint(switch_stun_packet_t *packet); 244 SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_use_candidate(switch_stun_packet_t *packet); 245 SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_controlling(switch_stun_packet_t *packet); 246 SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_controlled(switch_stun_packet_t *packet); 247 SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_priority(switch_stun_packet_t *packet, uint32_t priority); 248 249 /*! 250 \brief Perform a stun lookup 251 \param ip the local ip to use (replaced with stun results) 252 \param port the local port to use (replaced with stun results) 253 \param stunip the ip of the stun server 254 \param stunport the port of the stun server 255 \param err a pointer to describe errors 256 \param pool the memory pool to use 257 \return SUCCESS or FAIL 258 */ 259 SWITCH_DECLARE(switch_status_t) switch_stun_lookup(char **ip, 260 switch_port_t *port, char *stunip, switch_port_t stunport, char **err, switch_memory_pool_t *pool); 261 262 /*! 263 \brief Perform a stun ip lookup 264 \param external_ip replaced with stun results 265 \param sourceip stun:, host: or an ip 266 \param external_pool the memory pool to use 267 \return SUCCESS or FAIL 268 */ 269 SWITCH_DECLARE(switch_status_t) switch_stun_ip_lookup(char **external_ip, const char *sourceip, switch_memory_pool_t *external_pool); 270 271 272 /*! 273 \brief Obtain the padded length of an attribute's value 274 \param attribute the attribute 275 \return the padded size in bytes 276 */ 277 #define switch_stun_attribute_padded_length(attribute) (int16_t)((attribute->length & 0x3) ? 0x4 + (attribute->length & ~0x3) : attribute->length) 278 #define switch_stun_attribute_padded_length_hbo(attribute) (int16_t)((ntohs(attribute->length) & 0x3) ? 0x4 + (ntohs(attribute->length) & ~0x3) : ntohs(attribute->length)) 279 280 281 /*! 282 \brief set a switch_stun_packet_attribute_t pointer to point at the first attribute in a packet 283 \param packet the packet in question 284 \param attribute the pointer to set up 285 */ 286 #define switch_stun_packet_first_attribute(packet, attribute) attribute = (switch_stun_packet_attribute_t *)(&packet->first_attribute); 287 288 /*! 289 \brief Increment an attribute pointer to the next attribute in it's packet 290 \param attribute the pointer to increment 291 \param end pointer to the end of the buffer 292 \return true or false depending on if there are any more attributes 293 */ 294 295 #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)) 296 297 #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)) 298 299 /*! 300 \brief Obtain the correct length in bytes of a stun packet 301 \param packet the packet in question 302 \return the size in bytes (host order) of the entire packet 303 */ 304 #define switch_stun_packet_length(packet) ntohs(packet->header.length) + (sizeof(switch_stun_packet_header_t)) 305 ///\} 306 307 SWITCH_END_EXTERN_C 308 #endif 309 /* For Emacs: 310 * Local Variables: 311 * mode:c 312 * indent-tabs-mode:t 313 * tab-width:4 314 * c-basic-offset:4 315 * End: 316 * For VIM: 317 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 318 */ 319