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