Imported Upstream version 0.1.17
[platform/upstream/libnice.git] / agent / address.c
1 /*
2  * This file is part of the Nice GLib ICE library.
3  *
4  * (C) 2006-2009 Collabora Ltd.
5  *  Contact: Youness Alaoui
6  * (C) 2006-2009 Nokia Corporation. All rights reserved.
7  *  Contact: Kai Vehmanen
8  *
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/
13  *
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.
18  *
19  * The Original Code is the Nice GLib ICE library.
20  *
21  * The Initial Developers of the Original Code are Collabora Ltd and Nokia
22  * Corporation. All Rights Reserved.
23  *
24  * Contributors:
25  *   Dafydd Harries, Collabora Ltd.
26  *   Youness Alaoui, Collabora Ltd.
27  *   Kai Vehmanen, Nokia
28  *
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.
38  */
39 #ifdef HAVE_CONFIG_H
40 # include "config.h"
41 #else
42 #define NICEAPI_EXPORT
43 #endif
44
45 #include <string.h>
46
47 #ifdef HAVE_NETDB_H
48 #include <netdb.h>
49 #endif
50
51 #include "address.h"
52
53 #ifdef G_OS_WIN32
54 #define inet_ntop inet_ntop_win32
55
56 /* Defined in recent versions of mingw:
57  * https://github.com/mirror/mingw-w64/commit/0f4899473c4ba2e34fa447b1931a04e38c1f105e
58  */
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)
62 #endif
63
64
65 static const char *
66 inet_ntop_win32 (int af, const void *src, char *dst, socklen_t cnt)
67 {
68   if (af == AF_INET) {
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);
75     return dst;
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);
83     return dst;
84   }
85   return NULL;
86 }
87
88 #endif
89
90
91
92 NICEAPI_EXPORT void
93 nice_address_init (NiceAddress *addr)
94 {
95   addr->s.addr.sa_family = AF_UNSPEC;
96   memset (&addr->s, 0, sizeof(addr->s));
97 }
98
99 NICEAPI_EXPORT NiceAddress *
100 nice_address_new (void)
101 {
102   NiceAddress *addr = g_slice_new0 (NiceAddress);
103   nice_address_init (addr);
104   return addr;
105 }
106
107
108 NICEAPI_EXPORT void
109 nice_address_set_ipv4 (NiceAddress *addr, guint32 addr_ipv4)
110 {
111   addr->s.ip4.sin_family = AF_INET;
112 #ifdef HAVE_SA_LEN
113   addr->s.ip4.sin_len = sizeof (addr->sa.ip4);
114 #endif
115   addr->s.ip4.sin_addr.s_addr = addr_ipv4 ? htonl (addr_ipv4) : INADDR_ANY;
116   addr->s.ip4.sin_port = 0;
117 }
118
119
120 NICEAPI_EXPORT void
121 nice_address_set_ipv6 (NiceAddress *addr, const guchar *addr_ipv6)
122 {
123   addr->s.ip6.sin6_family = AF_INET6;
124 #ifdef HAVE_SA_LEN
125   addr->s.ip6.sin6_len = sizeof (addr->sa.ip6);
126 #endif
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;
130 }
131
132
133 NICEAPI_EXPORT void
134 nice_address_set_port (NiceAddress *addr, guint port)
135 {
136   g_assert (addr);
137
138   switch (addr->s.addr.sa_family)
139     {
140     case AF_INET:
141       addr->s.ip4.sin_port = htons (port);
142       break;
143     case AF_INET6:
144       addr->s.ip6.sin6_port = htons (port);
145       break;
146     default:
147       g_return_if_reached ();
148     }
149 }
150
151
152 guint
153 nice_address_get_port (const NiceAddress *addr)
154 {
155   if (!addr)
156           return 0;
157
158   switch (addr->s.addr.sa_family)
159     {
160     case AF_INET:
161       return ntohs (addr->s.ip4.sin_port);
162     case AF_INET6:
163       return ntohs (addr->s.ip6.sin6_port);
164     default:
165       g_return_val_if_reached (0);
166     }
167 }
168
169
170 NICEAPI_EXPORT gboolean
171 nice_address_set_from_string (NiceAddress *addr, const gchar *str)
172 {
173   struct addrinfo hints;
174   struct addrinfo *res;
175
176   memset (&hints, 0, sizeof (hints));
177
178   /* AI_NUMERICHOST prevents getaddrinfo() from doing DNS resolution. */
179   hints.ai_family = AF_UNSPEC;
180   hints.ai_flags = AI_NUMERICHOST;
181
182   if (getaddrinfo (str, NULL, &hints, &res) != 0)
183     return FALSE;  /* invalid address */
184
185   nice_address_set_from_sockaddr (addr, res->ai_addr);
186
187   freeaddrinfo (res);
188
189   return TRUE;
190 }
191
192
193 NICEAPI_EXPORT void
194 nice_address_set_from_sockaddr (NiceAddress *addr,
195                                 const struct sockaddr *sa)
196 {
197   switch (sa->sa_family)
198     {
199     case AF_INET:
200       memcpy(&addr->s.ip4, sa, sizeof (addr->s.ip4));
201       break;
202     case AF_INET6:
203       memcpy(&addr->s.ip6, sa, sizeof (addr->s.ip6));
204       break;
205     default:
206       g_return_if_reached ();
207     }
208 }
209
210
211 NICEAPI_EXPORT void
212 nice_address_copy_to_sockaddr (const NiceAddress *addr,
213                                struct sockaddr *_sa)
214 {
215   union {
216     struct sockaddr *addr;
217     struct sockaddr_in *in;
218     struct sockaddr_in6 *in6;
219   } sa;
220
221   sa.addr = _sa;
222
223   g_assert (_sa);
224
225   switch (addr->s.addr.sa_family)
226     {
227     case AF_INET:
228       memcpy (sa.in, &addr->s.ip4, sizeof (*sa.in));
229       break;
230     case AF_INET6:
231       memcpy (sa.in6, &addr->s.ip6, sizeof (*sa.in6));
232       break;
233     default:
234       g_return_if_reached ();
235     }
236 }
237
238 NICEAPI_EXPORT void
239 nice_address_to_string (const NiceAddress *addr, gchar *dst)
240 {
241   switch (addr->s.addr.sa_family) {
242     case AF_INET:
243       inet_ntop (AF_INET, &addr->s.ip4.sin_addr, dst, INET_ADDRSTRLEN);
244       break;
245     case AF_INET6:
246       inet_ntop (AF_INET6, &addr->s.ip6.sin6_addr, dst, INET6_ADDRSTRLEN);
247       break;
248     default:
249       g_return_if_reached ();
250   }
251 }
252
253
254 NICEAPI_EXPORT gboolean
255 nice_address_equal (const NiceAddress *a, const NiceAddress *b)
256 {
257   if (a->s.addr.sa_family != b->s.addr.sa_family)
258     return FALSE;
259
260   switch (a->s.addr.sa_family)
261     {
262     case AF_INET:
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);
265
266     case AF_INET6:
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));
271
272     default:
273       g_return_val_if_reached (FALSE);
274     }
275 }
276
277
278 NICEAPI_EXPORT NiceAddress *
279 nice_address_dup (const NiceAddress *a)
280 {
281   NiceAddress *dup = g_slice_new0 (NiceAddress);
282
283   *dup = *a;
284   return dup;
285 }
286
287
288 NICEAPI_EXPORT void
289 nice_address_free (NiceAddress *addr)
290 {
291   g_slice_free (NiceAddress, addr);
292 }
293
294
295 /* "private" in the sense of "not routable on the Internet" */
296 static gboolean
297 ipv4_address_is_private (guint32 addr)
298 {
299   addr = ntohl (addr);
300
301   /* http://tools.ietf.org/html/rfc3330 
302    * https://tools.ietf.org/html/rfc3927
303    */
304   return (
305       /* 10.0.0.0/8 */
306       ((addr & 0xff000000) == 0x0a000000) ||
307       /* 172.16.0.0 - 172.31.255.255  = 172.16.0.0/12 */
308       ((addr & 0xfff00000) == 0xac100000) ||
309       /* 192.168.0.0/16 */
310       ((addr & 0xffff0000) == 0xc0a80000) ||
311       /* 169.254.x.x/16  (for APIPA) */
312       ((addr & 0xffff0000) == 0xa9fe0000) ||
313       /* 127.0.0.0/8 */
314       ((addr & 0xff000000) == 0x7f000000));
315 }
316
317
318 static gboolean
319 ipv6_address_is_private (const guchar *addr)
320 {
321   return (
322       /* fe80::/10 (link local addresses, needs scope) */
323       ((addr[0] == 0xfe) && ((addr[1] & 0xc0) == 0x80)) ||
324       /* fd00::/8 (official private IP block) */
325       (addr[0] == 0xfd) ||
326       /* fc00::/7 (those are ULA) */
327       ((addr[0] & 0xfe) == 0xfc) ||
328       /* ::1 loopback */
329       ((memcmp (addr, "\x00\x00\x00\x00"
330                 "\x00\x00\x00\x00"
331                 "\x00\x00\x00\x00"
332                 "\x00\x00\x00\x01", 16) == 0))); 
333 }
334
335
336 NICEAPI_EXPORT gboolean
337 nice_address_is_private (const NiceAddress *a)
338 {
339   switch (a->s.addr.sa_family)
340     {
341     case AF_INET:
342       return ipv4_address_is_private (a->s.ip4.sin_addr.s_addr);
343     case AF_INET6:
344       return ipv6_address_is_private (a->s.ip6.sin6_addr.s6_addr);
345     default:
346       g_return_val_if_reached (FALSE);
347     }
348 }
349
350
351 NICEAPI_EXPORT gboolean
352 nice_address_is_valid (const NiceAddress *a)
353 {
354  switch (a->s.addr.sa_family)
355     {
356     case AF_INET:
357     case AF_INET6:
358       return TRUE;
359     default:
360       return FALSE;
361     }
362 }
363
364 NICEAPI_EXPORT int
365 nice_address_ip_version (const NiceAddress *addr)
366 {
367  switch (addr->s.addr.sa_family)
368     {
369     case AF_INET:
370       return 4;
371     case AF_INET6:
372       return 6;
373     default:
374       return 0;
375     }
376 }
377
378 NICEAPI_EXPORT gboolean
379 nice_address_equal_no_port (const NiceAddress *a, const NiceAddress *b)
380 {
381   if (a->s.addr.sa_family != b->s.addr.sa_family)
382     return FALSE;
383
384   switch (a->s.addr.sa_family)
385     {
386     case AF_INET:
387       return (a->s.ip4.sin_addr.s_addr == b->s.ip4.sin_addr.s_addr);
388
389     case AF_INET6:
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));
393
394     default:
395       g_return_val_if_reached (FALSE);
396     }
397 }