nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /* GIO - GLib Input, Output and Streaming Library
2 *
3 * Copyright (C) 2008 Christian Kellner, Samuel Cormier-Iijima
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 *
18 * Authors: Christian Kellner <gicmo@gnome.org>
19 * Samuel Cormier-Iijima <sciyoshi@gmail.com>
20 */
21  
22 #include <config.h>
23  
24 #include <string.h>
25  
26 #include <glib.h>
27  
28 #include "ginetaddress.h"
29 #include "gioenums.h"
30 #include "gioenumtypes.h"
31 #include "glibintl.h"
32 #include "gnetworkingprivate.h"
33  
34 #ifdef G_OS_WIN32
35 /* Ensure Windows XP runtime compatibility, while using
36 * inet_pton() and inet_ntop() if available
37 */
38 #include "gwin32networking.h"
39 #endif
40  
41 struct _GInetAddressPrivate
42 {
43 GSocketFamily family;
44 union {
45 struct in_addr ipv4;
46 struct in6_addr ipv6;
47 } addr;
48 };
49  
50 /**
51 * SECTION:ginetaddress
52 * @short_description: An IPv4/IPv6 address
53 * @include: gio/gio.h
54 *
55 * #GInetAddress represents an IPv4 or IPv6 internet address. Use
56 * g_resolver_lookup_by_name() or g_resolver_lookup_by_name_async() to
57 * look up the #GInetAddress for a hostname. Use
58 * g_resolver_lookup_by_address() or
59 * g_resolver_lookup_by_address_async() to look up the hostname for a
60 * #GInetAddress.
61 *
62 * To actually connect to a remote host, you will need a
63 * #GInetSocketAddress (which includes a #GInetAddress as well as a
64 * port number).
65 */
66  
67 /**
68 * GInetAddress:
69 *
70 * An IPv4 or IPv6 internet address.
71 */
72  
73 G_DEFINE_TYPE_WITH_CODE (GInetAddress, g_inet_address, G_TYPE_OBJECT,
74 G_ADD_PRIVATE (GInetAddress)
75 g_networking_init ();)
76  
77 enum
78 {
79 PROP_0,
80 PROP_FAMILY,
81 PROP_BYTES,
82 PROP_IS_ANY,
83 PROP_IS_LOOPBACK,
84 PROP_IS_LINK_LOCAL,
85 PROP_IS_SITE_LOCAL,
86 PROP_IS_MULTICAST,
87 PROP_IS_MC_GLOBAL,
88 PROP_IS_MC_LINK_LOCAL,
89 PROP_IS_MC_NODE_LOCAL,
90 PROP_IS_MC_ORG_LOCAL,
91 PROP_IS_MC_SITE_LOCAL,
92 };
93  
94 static void
95 g_inet_address_set_property (GObject *object,
96 guint prop_id,
97 const GValue *value,
98 GParamSpec *pspec)
99 {
100 GInetAddress *address = G_INET_ADDRESS (object);
101  
102 switch (prop_id)
103 {
104 case PROP_FAMILY:
105 address->priv->family = g_value_get_enum (value);
106 break;
107  
108 case PROP_BYTES:
109 memcpy (&address->priv->addr, g_value_get_pointer (value),
110 address->priv->family == AF_INET ?
111 sizeof (address->priv->addr.ipv4) :
112 sizeof (address->priv->addr.ipv6));
113 break;
114  
115 default:
116 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
117 break;
118 }
119  
120 }
121  
122 static void
123 g_inet_address_get_property (GObject *object,
124 guint prop_id,
125 GValue *value,
126 GParamSpec *pspec)
127 {
128 GInetAddress *address = G_INET_ADDRESS (object);
129  
130 switch (prop_id)
131 {
132 case PROP_FAMILY:
133 g_value_set_enum (value, address->priv->family);
134 break;
135  
136 case PROP_BYTES:
137 g_value_set_pointer (value, &address->priv->addr);
138 break;
139  
140 case PROP_IS_ANY:
141 g_value_set_boolean (value, g_inet_address_get_is_any (address));
142 break;
143  
144 case PROP_IS_LOOPBACK:
145 g_value_set_boolean (value, g_inet_address_get_is_loopback (address));
146 break;
147  
148 case PROP_IS_LINK_LOCAL:
149 g_value_set_boolean (value, g_inet_address_get_is_link_local (address));
150 break;
151  
152 case PROP_IS_SITE_LOCAL:
153 g_value_set_boolean (value, g_inet_address_get_is_site_local (address));
154 break;
155  
156 case PROP_IS_MULTICAST:
157 g_value_set_boolean (value, g_inet_address_get_is_multicast (address));
158 break;
159  
160 case PROP_IS_MC_GLOBAL:
161 g_value_set_boolean (value, g_inet_address_get_is_mc_global (address));
162 break;
163  
164 case PROP_IS_MC_LINK_LOCAL:
165 g_value_set_boolean (value, g_inet_address_get_is_mc_link_local (address));
166 break;
167  
168 case PROP_IS_MC_NODE_LOCAL:
169 g_value_set_boolean (value, g_inet_address_get_is_mc_node_local (address));
170 break;
171  
172 case PROP_IS_MC_ORG_LOCAL:
173 g_value_set_boolean (value, g_inet_address_get_is_mc_org_local (address));
174 break;
175  
176 case PROP_IS_MC_SITE_LOCAL:
177 g_value_set_boolean (value, g_inet_address_get_is_mc_site_local (address));
178 break;
179  
180 default:
181 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
182 }
183 }
184  
185 static void
186 g_inet_address_class_init (GInetAddressClass *klass)
187 {
188 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
189  
190 gobject_class->set_property = g_inet_address_set_property;
191 gobject_class->get_property = g_inet_address_get_property;
192  
193 g_object_class_install_property (gobject_class, PROP_FAMILY,
194 g_param_spec_enum ("family",
195 P_("Address family"),
196 P_("The address family (IPv4 or IPv6)"),
197 G_TYPE_SOCKET_FAMILY,
198 G_SOCKET_FAMILY_INVALID,
199 G_PARAM_READWRITE |
200 G_PARAM_CONSTRUCT_ONLY |
201 G_PARAM_STATIC_STRINGS));
202  
203 g_object_class_install_property (gobject_class, PROP_BYTES,
204 g_param_spec_pointer ("bytes",
205 P_("Bytes"),
206 P_("The raw address data"),
207 G_PARAM_READWRITE |
208 G_PARAM_CONSTRUCT_ONLY |
209 G_PARAM_STATIC_STRINGS));
210  
211 /**
212 * GInetAddress:is-any:
213 *
214 * Whether this is the "any" address for its family.
215 * See g_inet_address_get_is_any().
216 *
217 * Since: 2.22
218 */
219 g_object_class_install_property (gobject_class, PROP_IS_ANY,
220 g_param_spec_boolean ("is-any",
221 P_("Is any"),
222 P_("Whether this is the \"any\" address for its family"),
223 FALSE,
224 G_PARAM_READABLE |
225 G_PARAM_STATIC_STRINGS));
226  
227 /**
228 * GInetAddress:is-link-local:
229 *
230 * Whether this is a link-local address.
231 * See g_inet_address_get_is_link_local().
232 *
233 * Since: 2.22
234 */
235 g_object_class_install_property (gobject_class, PROP_IS_LINK_LOCAL,
236 g_param_spec_boolean ("is-link-local",
237 P_("Is link-local"),
238 P_("Whether this is a link-local address"),
239 FALSE,
240 G_PARAM_READABLE |
241 G_PARAM_STATIC_STRINGS));
242  
243 /**
244 * GInetAddress:is-loopback:
245 *
246 * Whether this is the loopback address for its family.
247 * See g_inet_address_get_is_loopback().
248 *
249 * Since: 2.22
250 */
251 g_object_class_install_property (gobject_class, PROP_IS_LOOPBACK,
252 g_param_spec_boolean ("is-loopback",
253 P_("Is loopback"),
254 P_("Whether this is the loopback address for its family"),
255 FALSE,
256 G_PARAM_READABLE |
257 G_PARAM_STATIC_STRINGS));
258  
259 /**
260 * GInetAddress:is-site-local:
261 *
262 * Whether this is a site-local address.
263 * See g_inet_address_get_is_loopback().
264 *
265 * Since: 2.22
266 */
267 g_object_class_install_property (gobject_class, PROP_IS_SITE_LOCAL,
268 g_param_spec_boolean ("is-site-local",
269 P_("Is site-local"),
270 P_("Whether this is a site-local address"),
271 FALSE,
272 G_PARAM_READABLE |
273 G_PARAM_STATIC_STRINGS));
274  
275 /**
276 * GInetAddress:is-multicast:
277 *
278 * Whether this is a multicast address.
279 * See g_inet_address_get_is_multicast().
280 *
281 * Since: 2.22
282 */
283 g_object_class_install_property (gobject_class, PROP_IS_MULTICAST,
284 g_param_spec_boolean ("is-multicast",
285 P_("Is multicast"),
286 P_("Whether this is a multicast address"),
287 FALSE,
288 G_PARAM_READABLE |
289 G_PARAM_STATIC_STRINGS));
290  
291 /**
292 * GInetAddress:is-mc-global:
293 *
294 * Whether this is a global multicast address.
295 * See g_inet_address_get_is_mc_global().
296 *
297 * Since: 2.22
298 */
299 g_object_class_install_property (gobject_class, PROP_IS_MC_GLOBAL,
300 g_param_spec_boolean ("is-mc-global",
301 P_("Is multicast global"),
302 P_("Whether this is a global multicast address"),
303 FALSE,
304 G_PARAM_READABLE |
305 G_PARAM_STATIC_STRINGS));
306  
307  
308 /**
309 * GInetAddress:is-mc-link-local:
310 *
311 * Whether this is a link-local multicast address.
312 * See g_inet_address_get_is_mc_link_local().
313 *
314 * Since: 2.22
315 */
316 g_object_class_install_property (gobject_class, PROP_IS_MC_LINK_LOCAL,
317 g_param_spec_boolean ("is-mc-link-local",
318 P_("Is multicast link-local"),
319 P_("Whether this is a link-local multicast address"),
320 FALSE,
321 G_PARAM_READABLE |
322 G_PARAM_STATIC_STRINGS));
323  
324 /**
325 * GInetAddress:is-mc-node-local:
326 *
327 * Whether this is a node-local multicast address.
328 * See g_inet_address_get_is_mc_node_local().
329 *
330 * Since: 2.22
331 */
332 g_object_class_install_property (gobject_class, PROP_IS_MC_NODE_LOCAL,
333 g_param_spec_boolean ("is-mc-node-local",
334 P_("Is multicast node-local"),
335 P_("Whether this is a node-local multicast address"),
336 FALSE,
337 G_PARAM_READABLE |
338 G_PARAM_STATIC_STRINGS));
339  
340 /**
341 * GInetAddress:is-mc-org-local:
342 *
343 * Whether this is an organization-local multicast address.
344 * See g_inet_address_get_is_mc_org_local().
345 *
346 * Since: 2.22
347 */
348 g_object_class_install_property (gobject_class, PROP_IS_MC_ORG_LOCAL,
349 g_param_spec_boolean ("is-mc-org-local",
350 P_("Is multicast org-local"),
351 P_("Whether this is an organization-local multicast address"),
352 FALSE,
353 G_PARAM_READABLE |
354 G_PARAM_STATIC_STRINGS));
355  
356 /**
357 * GInetAddress:is-mc-site-local:
358 *
359 * Whether this is a site-local multicast address.
360 * See g_inet_address_get_is_mc_site_local().
361 *
362 * Since: 2.22
363 */
364 g_object_class_install_property (gobject_class, PROP_IS_MC_SITE_LOCAL,
365 g_param_spec_boolean ("is-mc-site-local",
366 P_("Is multicast site-local"),
367 P_("Whether this is a site-local multicast address"),
368 FALSE,
369 G_PARAM_READABLE |
370 G_PARAM_STATIC_STRINGS));
371 }
372  
373 static void
374 g_inet_address_init (GInetAddress *address)
375 {
376 address->priv = g_inet_address_get_instance_private (address);
377 }
378  
379 /* These are provided so that we can use inet_pton() and inet_ntop() on Windows
380 * if they are available (i.e. Vista and later), and use the existing code path
381 * on Windows XP/Server 2003. We can drop this portion when we drop support for
382 * XP/Server 2003.
383 */
384 #if defined(G_OS_WIN32) && _WIN32_WINNT < 0x0600
385 static gint
386 inet_pton (gint family,
387 const gchar *addr_string,
388 gpointer addr)
389 {
390 /* For Vista/Server 2008 and later, there is native inet_pton() in Winsock2 */
391 if (ws2funcs.pInetPton != NULL)
392 return ws2funcs.pInetPton (family, addr_string, addr);
393 else
394 {
395 /* Fallback codepath for XP/Server 2003 */
396 struct sockaddr_storage sa;
397 struct sockaddr_in *sin = (struct sockaddr_in *)&sa;
398 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa;
399 gint len = sizeof (sa);
400  
401 if (family != AF_INET && family != AF_INET6)
402 {
403 WSASetLastError (WSAEAFNOSUPPORT);
404 return -1;
405 }
406  
407 /* WSAStringToAddress() will accept various not-an-IP-address
408 * strings like "127.0.0.1:80", "[1234::5678]:80", "127.1", etc.
409 */
410 if (!g_hostname_is_ip_address (addr_string))
411 return 0;
412  
413 if (WSAStringToAddress ((LPTSTR) addr_string, family, NULL, (LPSOCKADDR) &sa, &len) != 0)
414 return 0;
415  
416 if (family == AF_INET)
417 *(IN_ADDR *)addr = sin->sin_addr;
418 else
419 *(IN6_ADDR *)addr = sin6->sin6_addr;
420  
421 return 1;
422 }
423 }
424  
425 static const gchar *
426 inet_ntop (gint family,
427 const gpointer addr,
428 gchar *addr_str,
429 socklen_t size)
430 {
431 /* On Vista/Server 2008 and later, there is native inet_ntop() in Winsock2 */
432 if (ws2funcs.pInetNtop != NULL)
433 return ws2funcs.pInetNtop (family, addr, addr_str, size);
434 else
435 {
436 /* Fallback codepath for XP/Server 2003 */
437 DWORD buflen = size, addrlen;
438 struct sockaddr_storage sa;
439 struct sockaddr_in *sin = (struct sockaddr_in *)&sa;
440 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa;
441  
442 memset (&sa, 0, sizeof (sa));
443 sa.ss_family = family;
444 if (sa.ss_family == AF_INET)
445 {
446 struct in_addr *addrv4 = (struct in_addr *) addr;
447  
448 addrlen = sizeof (*sin);
449 memcpy (&sin->sin_addr, addrv4, sizeof (sin->sin_addr));
450 }
451 else if (sa.ss_family == AF_INET6)
452 {
453 struct in6_addr *addrv6 = (struct in6_addr *) addr;
454  
455 addrlen = sizeof (*sin6);
456 memcpy (&sin6->sin6_addr, addrv6, sizeof (sin6->sin6_addr));
457 }
458 else
459 {
460 WSASetLastError (WSAEAFNOSUPPORT);
461 return NULL;
462 }
463 if (WSAAddressToString ((LPSOCKADDR) &sa, addrlen, NULL, addr_str, &buflen) == 0)
464 return addr_str;
465 else
466 return NULL;
467 }
468 }
469 #endif
470  
471 /**
472 * g_inet_address_new_from_string:
473 * @string: a string representation of an IP address
474 *
475 * Parses @string as an IP address and creates a new #GInetAddress.
476 *
477 * Returns: a new #GInetAddress corresponding to @string, or %NULL if
478 * @string could not be parsed.
479 * Free the returned object with g_object_unref().
480 *
481 * Since: 2.22
482 */
483 GInetAddress *
484 g_inet_address_new_from_string (const gchar *string)
485 {
486 struct in_addr in_addr;
487 struct in6_addr in6_addr;
488  
489 g_return_val_if_fail (string != NULL, NULL);
490  
491 /* If this GInetAddress is the first networking-related object to be
492 * created, then we won't have called g_networking_init() yet at
493 * this point.
494 */
495 g_networking_init ();
496  
497 if (inet_pton (AF_INET, string, &in_addr) > 0)
498 return g_inet_address_new_from_bytes ((guint8 *)&in_addr, AF_INET);
499 else if (inet_pton (AF_INET6, string, &in6_addr) > 0)
500 return g_inet_address_new_from_bytes ((guint8 *)&in6_addr, AF_INET6);
501  
502 return NULL;
503 }
504  
505 #define G_INET_ADDRESS_FAMILY_IS_VALID(family) ((family) == AF_INET || (family) == AF_INET6)
506  
507 /**
508 * g_inet_address_new_from_bytes:
509 * @bytes: (array) (element-type guint8): raw address data
510 * @family: the address family of @bytes
511 *
512 * Creates a new #GInetAddress from the given @family and @bytes.
513 * @bytes should be 4 bytes for %G_SOCKET_FAMILY_IPV4 and 16 bytes for
514 * %G_SOCKET_FAMILY_IPV6.
515 *
516 * Returns: a new #GInetAddress corresponding to @family and @bytes.
517 * Free the returned object with g_object_unref().
518 *
519 * Since: 2.22
520 */
521 GInetAddress *
522 g_inet_address_new_from_bytes (const guint8 *bytes,
523 GSocketFamily family)
524 {
525 g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
526  
527 return g_object_new (G_TYPE_INET_ADDRESS,
528 "family", family,
529 "bytes", bytes,
530 NULL);
531 }
532  
533 /**
534 * g_inet_address_new_loopback:
535 * @family: the address family
536 *
537 * Creates a #GInetAddress for the loopback address for @family.
538 *
539 * Returns: a new #GInetAddress corresponding to the loopback address
540 * for @family.
541 * Free the returned object with g_object_unref().
542 *
543 * Since: 2.22
544 */
545 GInetAddress *
546 g_inet_address_new_loopback (GSocketFamily family)
547 {
548 g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
549  
550 if (family == AF_INET)
551 {
552 guint8 addr[4] = {127, 0, 0, 1};
553  
554 return g_inet_address_new_from_bytes (addr, family);
555 }
556 else
557 return g_inet_address_new_from_bytes (in6addr_loopback.s6_addr, family);
558 }
559  
560 /**
561 * g_inet_address_new_any:
562 * @family: the address family
563 *
564 * Creates a #GInetAddress for the "any" address (unassigned/"don't
565 * care") for @family.
566 *
567 * Returns: a new #GInetAddress corresponding to the "any" address
568 * for @family.
569 * Free the returned object with g_object_unref().
570 *
571 * Since: 2.22
572 */
573 GInetAddress *
574 g_inet_address_new_any (GSocketFamily family)
575 {
576 g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
577  
578 if (family == AF_INET)
579 {
580 guint8 addr[4] = {0, 0, 0, 0};
581  
582 return g_inet_address_new_from_bytes (addr, family);
583 }
584 else
585 return g_inet_address_new_from_bytes (in6addr_any.s6_addr, family);
586 }
587  
588  
589 /**
590 * g_inet_address_to_string:
591 * @address: a #GInetAddress
592 *
593 * Converts @address to string form.
594 *
595 * Returns: a representation of @address as a string, which should be
596 * freed after use.
597 *
598 * Since: 2.22
599 */
600 gchar *
601 g_inet_address_to_string (GInetAddress *address)
602 {
603 gchar buffer[INET6_ADDRSTRLEN];
604  
605 g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
606  
607 if (address->priv->family == AF_INET)
608 inet_ntop (AF_INET, &address->priv->addr.ipv4, buffer, sizeof (buffer));
609 else
610 inet_ntop (AF_INET6, &address->priv->addr.ipv6, buffer, sizeof (buffer));
611  
612 return g_strdup (buffer);
613 }
614  
615 /**
616 * g_inet_address_to_bytes: (skip)
617 * @address: a #GInetAddress
618 *
619 * Gets the raw binary address data from @address.
620 *
621 * Returns: a pointer to an internal array of the bytes in @address,
622 * which should not be modified, stored, or freed. The size of this
623 * array can be gotten with g_inet_address_get_native_size().
624 *
625 * Since: 2.22
626 */
627 const guint8 *
628 g_inet_address_to_bytes (GInetAddress *address)
629 {
630 g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
631  
632 return (guint8 *)&address->priv->addr;
633 }
634  
635 /**
636 * g_inet_address_get_native_size:
637 * @address: a #GInetAddress
638 *
639 * Gets the size of the native raw binary address for @address. This
640 * is the size of the data that you get from g_inet_address_to_bytes().
641 *
642 * Returns: the number of bytes used for the native version of @address.
643 *
644 * Since: 2.22
645 */
646 gsize
647 g_inet_address_get_native_size (GInetAddress *address)
648 {
649 if (address->priv->family == AF_INET)
650 return sizeof (address->priv->addr.ipv4);
651 return sizeof (address->priv->addr.ipv6);
652 }
653  
654 /**
655 * g_inet_address_get_family:
656 * @address: a #GInetAddress
657 *
658 * Gets @address's family
659 *
660 * Returns: @address's family
661 *
662 * Since: 2.22
663 */
664 GSocketFamily
665 g_inet_address_get_family (GInetAddress *address)
666 {
667 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
668  
669 return address->priv->family;
670 }
671  
672 /**
673 * g_inet_address_get_is_any:
674 * @address: a #GInetAddress
675 *
676 * Tests whether @address is the "any" address for its family.
677 *
678 * Returns: %TRUE if @address is the "any" address for its family.
679 *
680 * Since: 2.22
681 */
682 gboolean
683 g_inet_address_get_is_any (GInetAddress *address)
684 {
685 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
686  
687 if (address->priv->family == AF_INET)
688 {
689 guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
690  
691 return addr4 == INADDR_ANY;
692 }
693 else
694 return IN6_IS_ADDR_UNSPECIFIED (&address->priv->addr.ipv6);
695 }
696  
697 /**
698 * g_inet_address_get_is_loopback:
699 * @address: a #GInetAddress
700 *
701 * Tests whether @address is the loopback address for its family.
702 *
703 * Returns: %TRUE if @address is the loopback address for its family.
704 *
705 * Since: 2.22
706 */
707 gboolean
708 g_inet_address_get_is_loopback (GInetAddress *address)
709 {
710 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
711  
712 if (address->priv->family == AF_INET)
713 {
714 guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
715  
716 /* 127.0.0.0/8 */
717 return ((addr4 & 0xff000000) == 0x7f000000);
718 }
719 else
720 return IN6_IS_ADDR_LOOPBACK (&address->priv->addr.ipv6);
721 }
722  
723 /**
724 * g_inet_address_get_is_link_local:
725 * @address: a #GInetAddress
726 *
727 * Tests whether @address is a link-local address (that is, if it
728 * identifies a host on a local network that is not connected to the
729 * Internet).
730 *
731 * Returns: %TRUE if @address is a link-local address.
732 *
733 * Since: 2.22
734 */
735 gboolean
736 g_inet_address_get_is_link_local (GInetAddress *address)
737 {
738 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
739  
740 if (address->priv->family == AF_INET)
741 {
742 guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
743  
744 /* 169.254.0.0/16 */
745 return ((addr4 & 0xffff0000) == 0xa9fe0000);
746 }
747 else
748 return IN6_IS_ADDR_LINKLOCAL (&address->priv->addr.ipv6);
749 }
750  
751 /**
752 * g_inet_address_get_is_site_local:
753 * @address: a #GInetAddress
754 *
755 * Tests whether @address is a site-local address such as 10.0.0.1
756 * (that is, the address identifies a host on a local network that can
757 * not be reached directly from the Internet, but which may have
758 * outgoing Internet connectivity via a NAT or firewall).
759 *
760 * Returns: %TRUE if @address is a site-local address.
761 *
762 * Since: 2.22
763 */
764 gboolean
765 g_inet_address_get_is_site_local (GInetAddress *address)
766 {
767 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
768  
769 if (address->priv->family == AF_INET)
770 {
771 guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
772  
773 /* 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 */
774 return ((addr4 & 0xff000000) == 0x0a000000 ||
775 (addr4 & 0xfff00000) == 0xac100000 ||
776 (addr4 & 0xffff0000) == 0xc0a80000);
777 }
778 else
779 return IN6_IS_ADDR_SITELOCAL (&address->priv->addr.ipv6);
780 }
781  
782 /**
783 * g_inet_address_get_is_multicast:
784 * @address: a #GInetAddress
785 *
786 * Tests whether @address is a multicast address.
787 *
788 * Returns: %TRUE if @address is a multicast address.
789 *
790 * Since: 2.22
791 */
792 gboolean
793 g_inet_address_get_is_multicast (GInetAddress *address)
794 {
795 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
796  
797 if (address->priv->family == AF_INET)
798 {
799 guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
800  
801 return IN_MULTICAST (addr4);
802 }
803 else
804 return IN6_IS_ADDR_MULTICAST (&address->priv->addr.ipv6);
805 }
806  
807 /**
808 * g_inet_address_get_is_mc_global:
809 * @address: a #GInetAddress
810 *
811 * Tests whether @address is a global multicast address.
812 *
813 * Returns: %TRUE if @address is a global multicast address.
814 *
815 * Since: 2.22
816 */
817 gboolean
818 g_inet_address_get_is_mc_global (GInetAddress *address)
819 {
820 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
821  
822 if (address->priv->family == AF_INET)
823 return FALSE;
824 else
825 return IN6_IS_ADDR_MC_GLOBAL (&address->priv->addr.ipv6);
826 }
827  
828 /**
829 * g_inet_address_get_is_mc_link_local:
830 * @address: a #GInetAddress
831 *
832 * Tests whether @address is a link-local multicast address.
833 *
834 * Returns: %TRUE if @address is a link-local multicast address.
835 *
836 * Since: 2.22
837 */
838 gboolean
839 g_inet_address_get_is_mc_link_local (GInetAddress *address)
840 {
841 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
842  
843 if (address->priv->family == AF_INET)
844 return FALSE;
845 else
846 return IN6_IS_ADDR_MC_LINKLOCAL (&address->priv->addr.ipv6);
847 }
848  
849 /**
850 * g_inet_address_get_is_mc_node_local:
851 * @address: a #GInetAddress
852 *
853 * Tests whether @address is a node-local multicast address.
854 *
855 * Returns: %TRUE if @address is a node-local multicast address.
856 *
857 * Since: 2.22
858 */
859 gboolean
860 g_inet_address_get_is_mc_node_local (GInetAddress *address)
861 {
862 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
863  
864 if (address->priv->family == AF_INET)
865 return FALSE;
866 else
867 return IN6_IS_ADDR_MC_NODELOCAL (&address->priv->addr.ipv6);
868 }
869  
870 /**
871 * g_inet_address_get_is_mc_org_local:
872 * @address: a #GInetAddress
873 *
874 * Tests whether @address is an organization-local multicast address.
875 *
876 * Returns: %TRUE if @address is an organization-local multicast address.
877 *
878 * Since: 2.22
879 */
880 gboolean
881 g_inet_address_get_is_mc_org_local (GInetAddress *address)
882 {
883 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
884  
885 if (address->priv->family == AF_INET)
886 return FALSE;
887 else
888 return IN6_IS_ADDR_MC_ORGLOCAL (&address->priv->addr.ipv6);
889 }
890  
891 /**
892 * g_inet_address_get_is_mc_site_local:
893 * @address: a #GInetAddress
894 *
895 * Tests whether @address is a site-local multicast address.
896 *
897 * Returns: %TRUE if @address is a site-local multicast address.
898 *
899 * Since: 2.22
900 */
901 gboolean
902 g_inet_address_get_is_mc_site_local (GInetAddress *address)
903 {
904 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
905  
906 if (address->priv->family == AF_INET)
907 return FALSE;
908 else
909 return IN6_IS_ADDR_MC_SITELOCAL (&address->priv->addr.ipv6);
910 }
911  
912 /**
913 * g_inet_address_equal:
914 * @address: A #GInetAddress.
915 * @other_address: Another #GInetAddress.
916 *
917 * Checks if two #GInetAddress instances are equal, e.g. the same address.
918 *
919 * Returns: %TRUE if @address and @other_address are equal, %FALSE otherwise.
920 *
921 * Since: 2.30
922 */
923 gboolean
924 g_inet_address_equal (GInetAddress *address,
925 GInetAddress *other_address)
926 {
927 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
928 g_return_val_if_fail (G_IS_INET_ADDRESS (other_address), FALSE);
929  
930 if (g_inet_address_get_family (address) != g_inet_address_get_family (other_address))
931 return FALSE;
932  
933 if (memcmp (g_inet_address_to_bytes (address),
934 g_inet_address_to_bytes (other_address),
935 g_inet_address_get_native_size (address)) != 0)
936 return FALSE;
937  
938 return TRUE;
939 }