2
* This file is part of the Nice GLib ICE library.
4
* (C) 2007 Nokia Corporation. All rights reserved.
5
* Contact: Rémi Denis-Courmont
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/
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
17
* The Original Code is the Nice GLib ICE library.
19
* The Initial Developers of the Original Code are Collabora Ltd and Nokia
20
* Corporation. All Rights Reserved.
23
* Rémi Denis-Courmont, Nokia
25
* Alternatively, the contents of this file may be used under the terms of the
26
* the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
27
* case the provisions of LGPL are applicable instead of those above. If you
28
* wish to allow use of your version of this file only under the terms of the
29
* LGPL and not to allow others to use your version of this file under the
30
* MPL, indicate your decision by deleting the provisions above and replace
31
* them with the notice and other provisions required by the LGPL. If you do
32
* not delete the provisions above, a recipient may use your version of this
33
* file under either the MPL or the LGPL.
49
#define EAFNOSUPPORT -4
56
/** Compares two socket addresses
57
* @return 0 if the addresses are equal, non-zero otherwise
59
int sockaddrcmp (const struct sockaddr *a, const struct sockaddr *b)
63
res = a->sa_family - b->sa_family;
71
const struct sockaddr_in *a4 = (const struct sockaddr_in *)a;
72
const struct sockaddr_in *b4 = (const struct sockaddr_in *)b;
73
res = memcmp (&a4->sin_addr, &b4->sin_addr, 4);
75
res = memcmp (&a4->sin_port, &b4->sin_port, 2);
81
const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *)a;
82
const struct sockaddr_in6 *b6 = (const struct sockaddr_in6 *)b;
83
res = memcmp (&a6->sin6_addr, &b6->sin6_addr, 16);
85
res = a6->sin6_scope_id - b6->sin6_scope_id;
87
res = memcmp (&a6->sin6_port, &b6->sin6_port, 2);
97
bool stun_optional (uint16_t t)
99
return (t >> 15) == 1;
104
* @return complement to the next multiple of 4.
106
size_t stun_padding (size_t l)
108
return (4 - (l & 3)) & 3;
113
* Rounds up an integer to the next multiple of 4.
115
size_t stun_align (size_t l)
122
* Reads a word from a non-aligned buffer.
123
* @return host byte order word value.
125
uint16_t stun_getw (const uint8_t *ptr)
127
return ((ptr)[0] << 8) | ptr[1];
133
/* * @param msg valid STUN message */
134
/* * @return true if there is at least one unknown mandatory attribute. */
136
/* bool stun_has_unknown (const void *msg) */
138
/* uint16_t dummy; */
139
/* return stun_find_unknown (msg, &dummy, 1); */
142
static int debug_enabled = 1;
144
void stun_debug_enable (void) {
147
void stun_debug_disable (void) {
151
void stun_debug (const char *fmt, ...)
156
vfprintf (stderr, fmt, ap);
161
void stun_debug_bytes (const void *data, size_t len)
166
for (i = 0; i < len; i++)
167
stun_debug ("%02x", ((const unsigned char *)data)[i]);
170
int stun_xor_address (const StunMessage *msg,
171
struct sockaddr *addr, socklen_t addrlen,
172
uint32_t magic_cookie)
174
switch (addr->sa_family)
178
struct sockaddr_in *ip4 = (struct sockaddr_in *)addr;
179
if ((size_t) addrlen < sizeof (*ip4))
182
ip4->sin_port ^= htons (magic_cookie >> 16);
183
ip4->sin_addr.s_addr ^= htonl (magic_cookie);
189
struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)addr;
192
if ((size_t) addrlen < sizeof (*ip6))
195
ip6->sin6_port ^= htons (magic_cookie >> 16);
196
for (i = 0; i < 16; i++)
197
ip6->sin6_addr.s6_addr[i] ^= msg->buffer[4 + i];
205
* Compares the length and content of an attribute.
207
* @param msg valid STUN message buffer
208
* @param type STUN attribute type (host byte order)
209
* @param data pointer to value to compare with
210
* @param len byte length of the value
211
* @return 0 in case of match, ENOENT if attribute was not found,
212
* EINVAL if it did not match (different length, or same length but
215
int stun_memcmp (const StunMessage *msg, stun_attr_type_t type,
216
const void *data, size_t len)
219
const void *ptr = stun_message_find (msg, type, &alen);
223
if ((len != alen) || memcmp (ptr, data, len))
230
* Compares the content of an attribute with a string.
231
* @param msg valid STUN message buffer
232
* @param type STUN attribute type (host byte order)
233
* @param str string to compare with
234
* @return 0 in case of match, ENOENT if attribute was not found,
235
* EINVAL if it did not match
237
int stun_strcmp (const StunMessage *msg, stun_attr_type_t type, const char *str)
239
return stun_memcmp (msg, type, str, strlen (str));
243
void *stun_setw (uint8_t *ptr, uint16_t value)
246
*ptr++ = value & 0xff;
251
void stun_set_type (uint8_t *h, stun_class_t c, stun_method_t m)
253
/* assert (c < 4); */
254
/* assert (m < (1 << 12)); */
256
h[0] = (c >> 1) | ((m >> 6) & 0x3e);
257
h[1] = ((c << 4) & 0x10) | ((m << 1) & 0xe0) | (m & 0x0f);
259
/* assert (stun_getw (h) < (1 << 14)); */
260
/* assert (stun_get_class (h) == c); */
261
/* assert (stun_get_method (h) == m); */
266
* @param code host-byte order error code
267
* @return a static pointer to a nul-terminated error message string.
269
const char *stun_strerror (stun_error_t code)
277
{ STUN_ERROR_TRY_ALTERNATE, "Try alternate server" },
278
{ STUN_ERROR_BAD_REQUEST, "Bad request" },
279
{ STUN_ERROR_UNAUTHORIZED, "Authorization required" },
280
{ STUN_ERROR_UNKNOWN_ATTRIBUTE, "Unknown attribute" },
282
{ STUN_STALE_CREDENTIALS, "Authentication expired" },
283
{ STUN_INTEGRITY_CHECK_FAILURE, "Incorrect username/password" },
284
{ STUN_MISSING_USERNAME, "Username required" },
285
{ STUN_USE_TLS, "Secure connection required" },
286
{ STUN_MISSING_REALM, "Authentication domain required" },
287
{ STUN_MISSING_NONCE, "Authentication token missing" },
288
{ STUN_UNKNOWN_USERNAME, "Unknown user name" },
290
{ STUN_ERROR_NO_BINDING, "Session expired" },
291
{ STUN_ERROR_STALE_NONCE, "Authentication token expired" },
292
{ STUN_ERROR_ACT_DST_ALREADY, "Changing remote peer forbidden" },
293
{ STUN_ERROR_UNSUPP_TRANSPORT, "Unknown transport protocol" },
294
{ STUN_ERROR_INVALID_IP, "Address unavailable" },
295
{ STUN_ERROR_INVALID_PORT, "Port unavailable" },
296
{ STUN_ERROR_OP_TCP_ONLY, "Invalid operation" },
297
{ STUN_ERROR_CONN_ALREADY, "Connection already established" },
298
{ STUN_ERROR_ALLOC_OVER_QUOTA, "Quota reached" },
299
{ STUN_ERROR_ROLE_CONFLICT, "Role conflict" },
300
{ STUN_ERROR_SERVER_ERROR, "Temporary server error" },
301
{ STUN_ERROR_SERVER_CAPACITY, "Temporary server congestion" },
303
const char *str = "Unknown error";
306
for (i = 0; i < (sizeof (tab) / sizeof (tab[0])); i++)
308
if (tab[i].code == code)
315
/* Maximum allowed error message length */
316
// assert (strlen (str) < 128);