stupid WLM 2009 CRC32 typo workaround (ugly, I know...)
[sipe-libnice.git] / agent / address.c
blobc4553be05c76aec159d90bc30314d3cfc6d58b3d
1 /*
2 * This file is part of the Nice GLib ICE library.
4 * (C) 2006, 2007 Collabora Ltd.
5 * Contact: Dafydd Harries
6 * (C) 2006, 2007 Nokia Corporation. All rights reserved.
7 * Contact: Kai Vehmanen
9 * The contents of this file are subject to the Mozilla Public License Version
10 * 1.1 (the "License"); you may not use this file except in compliance with
11 * the License. You may obtain a copy of the License at
12 * http://www.mozilla.org/MPL/
14 * Software distributed under the License is distributed on an "AS IS" basis,
15 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
16 * for the specific language governing rights and limitations under the
17 * License.
19 * The Original Code is the Nice GLib ICE library.
21 * The Initial Developers of the Original Code are Collabora Ltd and Nokia
22 * Corporation. All Rights Reserved.
24 * Contributors:
25 * Dafydd Harries, Collabora Ltd.
26 * Kai Vehmanen, Nokia
28 * Alternatively, the contents of this file may be used under the terms of the
29 * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
30 * case the provisions of LGPL are applicable instead of those above. If you
31 * wish to allow use of your version of this file only under the terms of the
32 * LGPL and not to allow others to use your version of this file under the
33 * MPL, indicate your decision by deleting the provisions above and replace
34 * them with the notice and other provisions required by the LGPL. If you do
35 * not delete the provisions above, a recipient may use your version of this
36 * file under either the MPL or the LGPL.
38 #ifdef HAVE_CONFIG_H
39 # include "config.h"
40 #else
41 #define NICEAPI_EXPORT
42 #endif
44 #include <string.h>
46 #include "address.h"
48 #ifdef G_OS_WIN32
49 #define inet_pton inet_pton_win32
50 #define inet_ntop inet_ntop_win32
53 static const char *
54 inet_ntop_win32 (int af, const void *src, char *dst, socklen_t cnt)
56 if (af == AF_INET) {
57 struct sockaddr_in in;
58 memset(&in, 0, sizeof(in));
59 in.sin_family = AF_INET;
60 memcpy(&in.sin_addr, src, sizeof(struct in_addr));
61 getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in),
62 dst, cnt, NULL, 0, NI_NUMERICHOST);
63 return dst;
64 } else if (af == AF_INET6) {
65 struct sockaddr_in6 in;
66 memset(&in, 0, sizeof(in));
67 in.sin6_family = AF_INET6;
68 memcpy(&in.sin6_addr, src, sizeof(struct in_addr6));
69 getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6),
70 dst, cnt, NULL, 0, NI_NUMERICHOST);
71 return dst;
73 return NULL;
76 static int
77 inet_pton_win32(int af, const char *src, void *dst)
79 struct addrinfo hints, *res, *ressave;
81 memset(&hints, 0, sizeof(struct addrinfo));
82 hints.ai_family = af;
84 if (getaddrinfo(src, NULL, &hints, &res) != 0) {
85 return 0;
88 ressave = res;
90 while (res) {
91 if( res->ai_addr->sa_family == AF_INET) {
92 memcpy(dst, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
93 res->ai_addrlen);
94 res = res->ai_next;
95 } else if(res->ai_addr->sa_family == AF_INET6) {
96 memcpy(dst, &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr,
97 res->ai_addrlen);
98 res = res->ai_next;
102 freeaddrinfo(ressave);
103 return 1;
106 #endif
110 NICEAPI_EXPORT void
111 nice_address_init (NiceAddress *addr)
113 addr->s.addr.sa_family = AF_UNSPEC;
114 memset (&addr->s, 0, sizeof(addr->s));
117 NICEAPI_EXPORT NiceAddress *
118 nice_address_new (void)
120 NiceAddress *addr = g_slice_new0 (NiceAddress);
121 nice_address_init (addr);
122 return addr;
126 NICEAPI_EXPORT void
127 nice_address_set_ipv4 (NiceAddress *addr, guint32 addr_ipv4)
129 addr->s.ip4.sin_family = AF_INET;
130 #ifdef HAVE_SA_LEN
131 addr->s.ip4.sin_len = sizeof (addr->sa.ip4);
132 #endif
133 addr->s.ip4.sin_addr.s_addr = addr_ipv4 ? htonl (addr_ipv4) : INADDR_ANY;
134 addr->s.ip4.sin_port = 0;
138 NICEAPI_EXPORT void
139 nice_address_set_ipv6 (NiceAddress *addr, const guchar *addr_ipv6)
141 addr->s.ip6.sin6_family = AF_INET6;
142 #ifdef HAVE_SA_LEN
143 addr->s.ip6.sin6_len = sizeof (addr->sa.ip6);
144 #endif
145 memcpy (addr->s.ip6.sin6_addr.s6_addr, addr_ipv6, 16);
146 addr->s.ip6.sin6_port = addr->s.ip6.sin6_scope_id = 0;
150 NICEAPI_EXPORT void
151 nice_address_set_port (NiceAddress *addr, guint port)
153 g_assert (addr);
155 switch (addr->s.addr.sa_family)
157 case AF_INET:
158 addr->s.ip4.sin_port = htons (port);
159 break;
160 case AF_INET6:
161 addr->s.ip6.sin6_port = htons (port);
162 break;
163 default:
164 g_return_if_reached ();
169 guint
170 nice_address_get_port (const NiceAddress *addr)
172 if (!addr)
173 return 0;
175 switch (addr->s.addr.sa_family)
177 case AF_INET:
178 return ntohs (addr->s.ip4.sin_port);
179 case AF_INET6:
180 return ntohs (addr->s.ip6.sin6_port);
183 g_return_val_if_reached (0);
188 * address_set_from_string ()
190 * Returns FALSE on error.
192 NICEAPI_EXPORT gboolean
193 nice_address_set_from_string (NiceAddress *addr, const gchar *str)
195 union
197 struct in_addr ipv4;
198 struct in6_addr ipv6;
199 } a;
201 if (inet_pton (AF_INET, str, &a.ipv4) > 0)
202 nice_address_set_ipv4 (addr, ntohl (a.ipv4.s_addr));
203 else if (inet_pton (AF_INET6, str, &a.ipv6) > 0)
204 nice_address_set_ipv6 (addr, a.ipv6.s6_addr);
205 else
206 return FALSE; /* Invalid address */
208 return TRUE;
213 * Sets address to match socket address struct 'sin'.
215 NICEAPI_EXPORT void
216 nice_address_set_from_sockaddr (NiceAddress *addr,
217 const struct sockaddr *sa)
219 switch (sa->sa_family)
221 case AF_INET:
222 memcpy(&addr->s.ip4, sa, sizeof (addr->s.ip4));
223 break;
224 case AF_INET6:
225 memcpy(&addr->s.ip6, sa, sizeof (addr->s.ip6));
226 break;
227 default:
228 g_return_if_reached ();
234 * Copies NiceAddress to socket address struct 'sin'.
236 NICEAPI_EXPORT void
237 nice_address_copy_to_sockaddr (const NiceAddress *addr,
238 struct sockaddr *sa)
240 struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
241 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
243 g_assert (sa);
245 switch (addr->s.addr.sa_family)
247 case AF_INET:
248 memcpy (sin4, &addr->s.ip4, sizeof (*sin4));
249 break;
250 case AF_INET6:
251 memcpy (sin6, &addr->s.ip6, sizeof (*sin6));
252 break;
253 default:
254 g_return_if_reached ();
258 NICEAPI_EXPORT void
259 nice_address_to_string (const NiceAddress *addr, gchar *dst)
261 const gchar *ret = NULL;
263 switch (addr->s.addr.sa_family) {
264 case AF_INET:
265 ret = inet_ntop (AF_INET, &addr->s.ip4.sin_addr, dst, INET_ADDRSTRLEN);
266 break;
267 case AF_INET6:
268 ret = inet_ntop (AF_INET6, &addr->s.ip6.sin6_addr, dst,
269 INET6_ADDRSTRLEN);
270 break;
271 default:
272 g_return_if_reached ();
277 NICEAPI_EXPORT gboolean
278 nice_address_equal (const NiceAddress *a, const NiceAddress *b)
280 if (a->s.addr.sa_family != b->s.addr.sa_family)
281 return FALSE;
283 switch (a->s.addr.sa_family)
285 case AF_INET:
286 return (a->s.ip4.sin_addr.s_addr == b->s.ip4.sin_addr.s_addr)
287 && (a->s.ip4.sin_port == b->s.ip4.sin_port);
289 case AF_INET6:
290 return IN6_ARE_ADDR_EQUAL (&a->s.ip6.sin6_addr, &b->s.ip6.sin6_addr)
291 && (a->s.ip6.sin6_port == b->s.ip6.sin6_port)
292 && (a->s.ip6.sin6_scope_id == b->s.ip6.sin6_scope_id);
295 g_return_val_if_reached (FALSE);
299 NICEAPI_EXPORT NiceAddress *
300 nice_address_dup (const NiceAddress *a)
302 NiceAddress *dup = g_slice_new0 (NiceAddress);
304 *dup = *a;
305 return dup;
309 NICEAPI_EXPORT void
310 nice_address_free (NiceAddress *addr)
312 g_slice_free (NiceAddress, addr);
316 /* "private" in the sense of "not routable on the Internet" */
317 static gboolean
318 ipv4_address_is_private (guint32 addr)
320 addr = ntohl (addr);
322 /* http://tools.ietf.org/html/rfc3330 */
323 return (
324 /* 10.0.0.0/8 */
325 ((addr & 0xff000000) == 0x0a000000) ||
326 /* 172.16.0.0/12 */
327 ((addr & 0xfff00000) == 0xac100000) ||
328 /* 192.168.0.0/16 */
329 ((addr & 0xffff0000) == 0xc0a80000) ||
330 /* 127.0.0.0/8 */
331 ((addr & 0xff000000) == 0x7f000000));
335 static gboolean
336 ipv6_address_is_private (const guchar *addr)
338 return (
339 /* fe80::/10 */
340 ((addr[0] == 0xfe) && ((addr[1] & 0xc) == 0x80)) ||
341 /* fc00::/7 */
342 ((addr[0] & 0xfe) == 0xfc) ||
343 /* ::1 loopback */
344 ((memcmp (addr, "\x00\x00\x00\x00"
345 "\x00\x00\x00\x00"
346 "\x00\x00\x00\x00"
347 "\x00\x00\x00\x01", 16) == 0)));
351 NICEAPI_EXPORT gboolean
352 nice_address_is_private (const NiceAddress *a)
354 switch (a->s.addr.sa_family)
356 case AF_INET:
357 return ipv4_address_is_private (a->s.ip4.sin_addr.s_addr);
358 case AF_INET6:
359 return ipv6_address_is_private (a->s.ip6.sin6_addr.s6_addr);
362 g_return_val_if_reached (FALSE);
366 NICEAPI_EXPORT gboolean
367 nice_address_is_valid (const NiceAddress *a)
369 switch (a->s.addr.sa_family)
371 case AF_INET:
372 case AF_INET6:
373 return TRUE;
374 default:
375 return FALSE;