2 * This file is part of the Nice GLib ICE library.
4 * (C) 2006-2009 Collabora Ltd.
5 * Contact: Youness Alaoui
6 * (C) 2006-2009 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
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.
25 * Dafydd Harries, Collabora Ltd.
26 * Youness Alaoui, Collabora Ltd.
29 * Alternatively, the contents of this file may be used under the terms of the
30 * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
31 * case the provisions of LGPL are applicable instead of those above. If you
32 * wish to allow use of your version of this file only under the terms of the
33 * LGPL and not to allow others to use your version of this file under the
34 * MPL, indicate your decision by deleting the provisions above and replace
35 * them with the notice and other provisions required by the LGPL. If you do
36 * not delete the provisions above, a recipient may use your version of this
37 * file under either the MPL or the LGPL.
42 #define NICEAPI_EXPORT
54 #define inet_ntop inet_ntop_win32
56 /* Defined in recent versions of mingw:
57 * https://github.com/mirror/mingw-w64/commit/0f4899473c4ba2e34fa447b1931a04e38c1f105e
59 #ifndef IN6_ARE_ADDR_EQUAL
60 #define IN6_ARE_ADDR_EQUAL(a, b) \
61 (memcmp ((const void *) (a), (const void *) (b), sizeof (struct in6_addr)) == 0)
66 inet_ntop_win32 (int af, const void *src, char *dst, socklen_t cnt)
69 struct sockaddr_in in;
70 memset(&in, 0, sizeof(in));
71 in.sin_family = AF_INET;
72 memcpy(&in.sin_addr, src, sizeof(struct in_addr));
73 getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in),
74 dst, cnt, NULL, 0, NI_NUMERICHOST);
76 } else if (af == AF_INET6) {
77 struct sockaddr_in6 in;
78 memset(&in, 0, sizeof(in));
79 in.sin6_family = AF_INET6;
80 memcpy(&in.sin6_addr, src, sizeof(struct in_addr6));
81 getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6),
82 dst, cnt, NULL, 0, NI_NUMERICHOST);
93 nice_address_init (NiceAddress *addr)
95 addr->s.addr.sa_family = AF_UNSPEC;
96 memset (&addr->s, 0, sizeof(addr->s));
99 NICEAPI_EXPORT NiceAddress *
100 nice_address_new (void)
102 NiceAddress *addr = g_slice_new0 (NiceAddress);
103 nice_address_init (addr);
109 nice_address_set_ipv4 (NiceAddress *addr, guint32 addr_ipv4)
111 addr->s.ip4.sin_family = AF_INET;
113 addr->s.ip4.sin_len = sizeof (addr->sa.ip4);
115 addr->s.ip4.sin_addr.s_addr = addr_ipv4 ? htonl (addr_ipv4) : INADDR_ANY;
116 addr->s.ip4.sin_port = 0;
121 nice_address_set_ipv6 (NiceAddress *addr, const guchar *addr_ipv6)
123 addr->s.ip6.sin6_family = AF_INET6;
125 addr->s.ip6.sin6_len = sizeof (addr->sa.ip6);
127 memcpy (addr->s.ip6.sin6_addr.s6_addr, addr_ipv6, 16);
128 addr->s.ip6.sin6_port = 0;
129 addr->s.ip6.sin6_scope_id = 0;
134 nice_address_set_port (NiceAddress *addr, guint port)
138 switch (addr->s.addr.sa_family)
141 addr->s.ip4.sin_port = htons (port);
144 addr->s.ip6.sin6_port = htons (port);
147 g_return_if_reached ();
153 nice_address_get_port (const NiceAddress *addr)
158 switch (addr->s.addr.sa_family)
161 return ntohs (addr->s.ip4.sin_port);
163 return ntohs (addr->s.ip6.sin6_port);
165 g_return_val_if_reached (0);
170 NICEAPI_EXPORT gboolean
171 nice_address_set_from_string (NiceAddress *addr, const gchar *str)
173 struct addrinfo hints;
174 struct addrinfo *res;
176 memset (&hints, 0, sizeof (hints));
178 /* AI_NUMERICHOST prevents getaddrinfo() from doing DNS resolution. */
179 hints.ai_family = AF_UNSPEC;
180 hints.ai_flags = AI_NUMERICHOST;
182 if (getaddrinfo (str, NULL, &hints, &res) != 0)
183 return FALSE; /* invalid address */
185 nice_address_set_from_sockaddr (addr, res->ai_addr);
194 nice_address_set_from_sockaddr (NiceAddress *addr,
195 const struct sockaddr *sa)
197 switch (sa->sa_family)
200 memcpy(&addr->s.ip4, sa, sizeof (addr->s.ip4));
203 memcpy(&addr->s.ip6, sa, sizeof (addr->s.ip6));
206 g_return_if_reached ();
212 nice_address_copy_to_sockaddr (const NiceAddress *addr,
213 struct sockaddr *_sa)
216 struct sockaddr *addr;
217 struct sockaddr_in *in;
218 struct sockaddr_in6 *in6;
225 switch (addr->s.addr.sa_family)
228 memcpy (sa.in, &addr->s.ip4, sizeof (*sa.in));
231 memcpy (sa.in6, &addr->s.ip6, sizeof (*sa.in6));
234 g_return_if_reached ();
239 nice_address_to_string (const NiceAddress *addr, gchar *dst)
241 switch (addr->s.addr.sa_family) {
243 inet_ntop (AF_INET, &addr->s.ip4.sin_addr, dst, INET_ADDRSTRLEN);
246 inet_ntop (AF_INET6, &addr->s.ip6.sin6_addr, dst, INET6_ADDRSTRLEN);
249 g_return_if_reached ();
254 NICEAPI_EXPORT gboolean
255 nice_address_equal (const NiceAddress *a, const NiceAddress *b)
257 if (a->s.addr.sa_family != b->s.addr.sa_family)
260 switch (a->s.addr.sa_family)
263 return (a->s.ip4.sin_addr.s_addr == b->s.ip4.sin_addr.s_addr)
264 && (a->s.ip4.sin_port == b->s.ip4.sin_port);
267 return IN6_ARE_ADDR_EQUAL (&a->s.ip6.sin6_addr, &b->s.ip6.sin6_addr)
268 && (a->s.ip6.sin6_port == b->s.ip6.sin6_port)
269 && (a->s.ip6.sin6_scope_id == 0 || b->s.ip6.sin6_scope_id == 0 ||
270 (a->s.ip6.sin6_scope_id == b->s.ip6.sin6_scope_id));
273 g_return_val_if_reached (FALSE);
278 NICEAPI_EXPORT NiceAddress *
279 nice_address_dup (const NiceAddress *a)
281 NiceAddress *dup = g_slice_new0 (NiceAddress);
289 nice_address_free (NiceAddress *addr)
291 g_slice_free (NiceAddress, addr);
295 /* "private" in the sense of "not routable on the Internet" */
297 ipv4_address_is_private (guint32 addr)
301 /* http://tools.ietf.org/html/rfc3330
302 * https://tools.ietf.org/html/rfc3927
306 ((addr & 0xff000000) == 0x0a000000) ||
307 /* 172.16.0.0 - 172.31.255.255 = 172.16.0.0/12 */
308 ((addr & 0xfff00000) == 0xac100000) ||
310 ((addr & 0xffff0000) == 0xc0a80000) ||
311 /* 169.254.x.x/16 (for APIPA) */
312 ((addr & 0xffff0000) == 0xa9fe0000) ||
314 ((addr & 0xff000000) == 0x7f000000));
319 ipv6_address_is_private (const guchar *addr)
322 /* fe80::/10 (link local addresses, needs scope) */
323 ((addr[0] == 0xfe) && ((addr[1] & 0xc0) == 0x80)) ||
324 /* fd00::/8 (official private IP block) */
326 /* fc00::/7 (those are ULA) */
327 ((addr[0] & 0xfe) == 0xfc) ||
329 ((memcmp (addr, "\x00\x00\x00\x00"
332 "\x00\x00\x00\x01", 16) == 0)));
336 NICEAPI_EXPORT gboolean
337 nice_address_is_private (const NiceAddress *a)
339 switch (a->s.addr.sa_family)
342 return ipv4_address_is_private (a->s.ip4.sin_addr.s_addr);
344 return ipv6_address_is_private (a->s.ip6.sin6_addr.s6_addr);
346 g_return_val_if_reached (FALSE);
351 NICEAPI_EXPORT gboolean
352 nice_address_is_valid (const NiceAddress *a)
354 switch (a->s.addr.sa_family)
365 nice_address_ip_version (const NiceAddress *addr)
367 switch (addr->s.addr.sa_family)
378 NICEAPI_EXPORT gboolean
379 nice_address_equal_no_port (const NiceAddress *a, const NiceAddress *b)
381 if (a->s.addr.sa_family != b->s.addr.sa_family)
384 switch (a->s.addr.sa_family)
387 return (a->s.ip4.sin_addr.s_addr == b->s.ip4.sin_addr.s_addr);
390 return IN6_ARE_ADDR_EQUAL (&a->s.ip6.sin6_addr, &b->s.ip6.sin6_addr)
391 && (a->s.ip6.sin6_scope_id == 0 || b->s.ip6.sin6_scope_id == 0 ||
392 (a->s.ip6.sin6_scope_id == b->s.ip6.sin6_scope_id));
395 g_return_val_if_reached (FALSE);