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