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