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