coverity: fix possible buffer overrun with turn and IPv6. Use sockaddr_storage
[sipe-libnice.git] / agent / address.c
blob374ca6aee1d4c2d3fc4dfa4d83363a12e88a49cd
1 /*
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
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 * Youness Alaoui, Collabora Ltd.
27 * Kai Vehmanen, Nokia
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.
39 #ifdef HAVE_CONFIG_H
40 # include "config.h"
41 #else
42 #define NICEAPI_EXPORT
43 #endif
45 #include <string.h>
47 #include "address.h"
49 #ifdef G_OS_WIN32
50 #define inet_pton inet_pton_win32
51 #define inet_ntop inet_ntop_win32
54 static const char *
55 inet_ntop_win32 (int af, const void *src, char *dst, socklen_t cnt)
57 if (af == AF_INET) {
58 struct sockaddr_in in;
59 memset(&in, 0, sizeof(in));
60 in.sin_family = AF_INET;
61 memcpy(&in.sin_addr, src, sizeof(struct in_addr));
62 getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in),
63 dst, cnt, NULL, 0, NI_NUMERICHOST);
64 return dst;
65 } else if (af == AF_INET6) {
66 struct sockaddr_in6 in;
67 memset(&in, 0, sizeof(in));
68 in.sin6_family = AF_INET6;
69 memcpy(&in.sin6_addr, src, sizeof(struct in_addr6));
70 getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6),
71 dst, cnt, NULL, 0, NI_NUMERICHOST);
72 return dst;
74 return NULL;
77 static int
78 inet_pton_win32(int af, const char *src, void *dst)
80 struct addrinfo hints, *res, *ressave;
82 memset(&hints, 0, sizeof(struct addrinfo));
83 hints.ai_family = af;
85 if (getaddrinfo(src, NULL, &hints, &res) != 0) {
86 return 0;
89 ressave = res;
91 while (res) {
92 if( res->ai_addr->sa_family == AF_INET) {
93 memcpy(dst, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
94 res->ai_addrlen);
95 res = res->ai_next;
96 } else if(res->ai_addr->sa_family == AF_INET6) {
97 memcpy(dst, &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr,
98 res->ai_addrlen);
99 res = res->ai_next;
103 freeaddrinfo(ressave);
104 return 1;
107 #endif
111 NICEAPI_EXPORT void
112 nice_address_init (NiceAddress *addr)
114 addr->s.addr.sa_family = AF_UNSPEC;
115 memset (&addr->s, 0, sizeof(addr->s));
118 NICEAPI_EXPORT NiceAddress *
119 nice_address_new (void)
121 NiceAddress *addr = g_slice_new0 (NiceAddress);
122 nice_address_init (addr);
123 return addr;
127 NICEAPI_EXPORT void
128 nice_address_set_ipv4 (NiceAddress *addr, guint32 addr_ipv4)
130 addr->s.ip4.sin_family = AF_INET;
131 #ifdef HAVE_SA_LEN
132 addr->s.ip4.sin_len = sizeof (addr->sa.ip4);
133 #endif
134 addr->s.ip4.sin_addr.s_addr = addr_ipv4 ? htonl (addr_ipv4) : INADDR_ANY;
135 addr->s.ip4.sin_port = 0;
139 NICEAPI_EXPORT void
140 nice_address_set_ipv6 (NiceAddress *addr, const guchar *addr_ipv6)
142 addr->s.ip6.sin6_family = AF_INET6;
143 #ifdef HAVE_SA_LEN
144 addr->s.ip6.sin6_len = sizeof (addr->sa.ip6);
145 #endif
146 memcpy (addr->s.ip6.sin6_addr.s6_addr, addr_ipv6, 16);
147 addr->s.ip6.sin6_port = addr->s.ip6.sin6_scope_id = 0;
151 NICEAPI_EXPORT void
152 nice_address_set_port (NiceAddress *addr, guint port)
154 g_assert (addr);
156 switch (addr->s.addr.sa_family)
158 case AF_INET:
159 addr->s.ip4.sin_port = htons (port);
160 break;
161 case AF_INET6:
162 addr->s.ip6.sin6_port = htons (port);
163 break;
164 default:
165 g_return_if_reached ();
170 guint
171 nice_address_get_port (const NiceAddress *addr)
173 if (!addr)
174 return 0;
176 switch (addr->s.addr.sa_family)
178 case AF_INET:
179 return ntohs (addr->s.ip4.sin_port);
180 case AF_INET6:
181 return ntohs (addr->s.ip6.sin6_port);
184 g_return_val_if_reached (0);
188 NICEAPI_EXPORT gboolean
189 nice_address_set_from_string (NiceAddress *addr, const gchar *str)
191 union
193 struct in_addr ipv4;
194 struct in6_addr ipv6;
195 } a;
197 if (inet_pton (AF_INET, str, &a.ipv4) > 0)
198 nice_address_set_ipv4 (addr, ntohl (a.ipv4.s_addr));
199 else if (inet_pton (AF_INET6, str, &a.ipv6) > 0)
200 nice_address_set_ipv6 (addr, a.ipv6.s6_addr);
201 else
202 return FALSE; /* Invalid address */
204 return TRUE;
208 NICEAPI_EXPORT void
209 nice_address_set_from_sockaddr (NiceAddress *addr,
210 const struct sockaddr *sa)
212 switch (sa->sa_family)
214 case AF_INET:
215 memcpy(&addr->s.ip4, sa, sizeof (addr->s.ip4));
216 break;
217 case AF_INET6:
218 memcpy(&addr->s.ip6, sa, sizeof (addr->s.ip6));
219 break;
220 default:
221 g_return_if_reached ();
226 NICEAPI_EXPORT void
227 nice_address_copy_to_sockaddr (const NiceAddress *addr,
228 struct sockaddr *sa)
230 struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
231 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
233 g_assert (sa);
235 switch (addr->s.addr.sa_family)
237 case AF_INET:
238 memcpy (sin4, &addr->s.ip4, sizeof (*sin4));
239 break;
240 case AF_INET6:
241 memcpy (sin6, &addr->s.ip6, sizeof (*sin6));
242 break;
243 default:
244 g_return_if_reached ();
248 NICEAPI_EXPORT void
249 nice_address_to_string (const NiceAddress *addr, gchar *dst)
251 switch (addr->s.addr.sa_family) {
252 case AF_INET:
253 inet_ntop (AF_INET, &addr->s.ip4.sin_addr, dst, INET_ADDRSTRLEN);
254 break;
255 case AF_INET6:
256 inet_ntop (AF_INET6, &addr->s.ip6.sin6_addr, dst, INET6_ADDRSTRLEN);
257 break;
258 default:
259 g_return_if_reached ();
264 NICEAPI_EXPORT gboolean
265 nice_address_equal (const NiceAddress *a, const NiceAddress *b)
267 if (a->s.addr.sa_family != b->s.addr.sa_family)
268 return FALSE;
270 switch (a->s.addr.sa_family)
272 case AF_INET:
273 return (a->s.ip4.sin_addr.s_addr == b->s.ip4.sin_addr.s_addr)
274 && (a->s.ip4.sin_port == b->s.ip4.sin_port);
276 case AF_INET6:
277 return IN6_ARE_ADDR_EQUAL (&a->s.ip6.sin6_addr, &b->s.ip6.sin6_addr)
278 && (a->s.ip6.sin6_port == b->s.ip6.sin6_port)
279 && (a->s.ip6.sin6_scope_id == b->s.ip6.sin6_scope_id);
282 g_return_val_if_reached (FALSE);
286 NICEAPI_EXPORT NiceAddress *
287 nice_address_dup (const NiceAddress *a)
289 NiceAddress *dup = g_slice_new0 (NiceAddress);
291 *dup = *a;
292 return dup;
296 NICEAPI_EXPORT void
297 nice_address_free (NiceAddress *addr)
299 g_slice_free (NiceAddress, addr);
303 /* "private" in the sense of "not routable on the Internet" */
304 static gboolean
305 ipv4_address_is_private (guint32 addr)
307 addr = ntohl (addr);
309 /* http://tools.ietf.org/html/rfc3330 */
310 return (
311 /* 10.0.0.0/8 */
312 ((addr & 0xff000000) == 0x0a000000) ||
313 /* 172.16.0.0/12 */
314 ((addr & 0xfff00000) == 0xac100000) ||
315 /* 192.168.0.0/16 */
316 ((addr & 0xffff0000) == 0xc0a80000) ||
317 /* 127.0.0.0/8 */
318 ((addr & 0xff000000) == 0x7f000000));
322 static gboolean
323 ipv6_address_is_private (const guchar *addr)
325 return (
326 /* fe80::/10 */
327 ((addr[0] == 0xfe) && ((addr[1] & 0xc) == 0x80)) ||
328 /* fc00::/7 */
329 ((addr[0] & 0xfe) == 0xfc) ||
330 /* ::1 loopback */
331 ((memcmp (addr, "\x00\x00\x00\x00"
332 "\x00\x00\x00\x00"
333 "\x00\x00\x00\x00"
334 "\x00\x00\x00\x01", 16) == 0)));
338 NICEAPI_EXPORT gboolean
339 nice_address_is_private (const NiceAddress *a)
341 switch (a->s.addr.sa_family)
343 case AF_INET:
344 return ipv4_address_is_private (a->s.ip4.sin_addr.s_addr);
345 case AF_INET6:
346 return ipv6_address_is_private (a->s.ip6.sin6_addr.s6_addr);
349 g_return_val_if_reached (FALSE);
353 NICEAPI_EXPORT gboolean
354 nice_address_is_valid (const NiceAddress *a)
356 switch (a->s.addr.sa_family)
358 case AF_INET:
359 case AF_INET6:
360 return TRUE;
361 default:
362 return FALSE;