• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.1 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
g_inet_address_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)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
g_inet_address_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)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
g_inet_address_class_init(GInetAddressClass * klass)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
g_inet_address_init(GInetAddress * address)374 g_inet_address_init (GInetAddress *address)
375 {
376   address->priv = g_inet_address_get_instance_private (address);
377 }
378 
379 /**
380  * g_inet_address_new_from_string:
381  * @string: a string representation of an IP address
382  *
383  * Parses @string as an IP address and creates a new #GInetAddress.
384  *
385  * Returns: a new #GInetAddress corresponding to @string, or %NULL if
386  * @string could not be parsed.
387  *     Free the returned object with g_object_unref().
388  *
389  * Since: 2.22
390  */
391 GInetAddress *
g_inet_address_new_from_string(const gchar * string)392 g_inet_address_new_from_string (const gchar *string)
393 {
394   struct in_addr in_addr;
395   struct in6_addr in6_addr;
396 
397   g_return_val_if_fail (string != NULL, NULL);
398 
399   /* If this GInetAddress is the first networking-related object to be
400    * created, then we won't have called g_networking_init() yet at
401    * this point.
402    */
403   g_networking_init ();
404 
405   if (inet_pton (AF_INET, string, &in_addr) > 0)
406     return g_inet_address_new_from_bytes ((guint8 *)&in_addr, AF_INET);
407   else if (inet_pton (AF_INET6, string, &in6_addr) > 0)
408     return g_inet_address_new_from_bytes ((guint8 *)&in6_addr, AF_INET6);
409 
410   return NULL;
411 }
412 
413 #define G_INET_ADDRESS_FAMILY_IS_VALID(family) ((family) == AF_INET || (family) == AF_INET6)
414 
415 /**
416  * g_inet_address_new_from_bytes:
417  * @bytes: (array) (element-type guint8): raw address data
418  * @family: the address family of @bytes
419  *
420  * Creates a new #GInetAddress from the given @family and @bytes.
421  * @bytes should be 4 bytes for %G_SOCKET_FAMILY_IPV4 and 16 bytes for
422  * %G_SOCKET_FAMILY_IPV6.
423  *
424  * Returns: a new #GInetAddress corresponding to @family and @bytes.
425  *     Free the returned object with g_object_unref().
426  *
427  * Since: 2.22
428  */
429 GInetAddress *
g_inet_address_new_from_bytes(const guint8 * bytes,GSocketFamily family)430 g_inet_address_new_from_bytes (const guint8         *bytes,
431 			       GSocketFamily  family)
432 {
433   g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
434 
435   return g_object_new (G_TYPE_INET_ADDRESS,
436 		       "family", family,
437 		       "bytes", bytes,
438 		       NULL);
439 }
440 
441 /**
442  * g_inet_address_new_loopback:
443  * @family: the address family
444  *
445  * Creates a #GInetAddress for the loopback address for @family.
446  *
447  * Returns: a new #GInetAddress corresponding to the loopback address
448  * for @family.
449  *     Free the returned object with g_object_unref().
450  *
451  * Since: 2.22
452  */
453 GInetAddress *
g_inet_address_new_loopback(GSocketFamily family)454 g_inet_address_new_loopback (GSocketFamily family)
455 {
456   g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
457 
458   if (family == AF_INET)
459     {
460       guint8 addr[4] = {127, 0, 0, 1};
461 
462       return g_inet_address_new_from_bytes (addr, family);
463     }
464   else
465     return g_inet_address_new_from_bytes (in6addr_loopback.s6_addr, family);
466 }
467 
468 /**
469  * g_inet_address_new_any:
470  * @family: the address family
471  *
472  * Creates a #GInetAddress for the "any" address (unassigned/"don't
473  * care") for @family.
474  *
475  * Returns: a new #GInetAddress corresponding to the "any" address
476  * for @family.
477  *     Free the returned object with g_object_unref().
478  *
479  * Since: 2.22
480  */
481 GInetAddress *
g_inet_address_new_any(GSocketFamily family)482 g_inet_address_new_any (GSocketFamily family)
483 {
484   g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
485 
486   if (family == AF_INET)
487     {
488       guint8 addr[4] = {0, 0, 0, 0};
489 
490       return g_inet_address_new_from_bytes (addr, family);
491     }
492   else
493     return g_inet_address_new_from_bytes (in6addr_any.s6_addr, family);
494 }
495 
496 
497 /**
498  * g_inet_address_to_string:
499  * @address: a #GInetAddress
500  *
501  * Converts @address to string form.
502  *
503  * Returns: a representation of @address as a string, which should be
504  * freed after use.
505  *
506  * Since: 2.22
507  */
508 gchar *
g_inet_address_to_string(GInetAddress * address)509 g_inet_address_to_string (GInetAddress *address)
510 {
511   gchar buffer[INET6_ADDRSTRLEN];
512 
513   g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
514 
515   if (address->priv->family == AF_INET)
516     inet_ntop (AF_INET, &address->priv->addr.ipv4, buffer, sizeof (buffer));
517   else
518     inet_ntop (AF_INET6, &address->priv->addr.ipv6, buffer, sizeof (buffer));
519 
520   return g_strdup (buffer);
521 }
522 
523 /**
524  * g_inet_address_to_bytes: (skip)
525  * @address: a #GInetAddress
526  *
527  * Gets the raw binary address data from @address.
528  *
529  * Returns: a pointer to an internal array of the bytes in @address,
530  * which should not be modified, stored, or freed. The size of this
531  * array can be gotten with g_inet_address_get_native_size().
532  *
533  * Since: 2.22
534  */
535 const guint8 *
g_inet_address_to_bytes(GInetAddress * address)536 g_inet_address_to_bytes (GInetAddress *address)
537 {
538   g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
539 
540   return (guint8 *)&address->priv->addr;
541 }
542 
543 /**
544  * g_inet_address_get_native_size:
545  * @address: a #GInetAddress
546  *
547  * Gets the size of the native raw binary address for @address. This
548  * is the size of the data that you get from g_inet_address_to_bytes().
549  *
550  * Returns: the number of bytes used for the native version of @address.
551  *
552  * Since: 2.22
553  */
554 gsize
g_inet_address_get_native_size(GInetAddress * address)555 g_inet_address_get_native_size (GInetAddress *address)
556 {
557   if (address->priv->family == AF_INET)
558     return sizeof (address->priv->addr.ipv4);
559   return sizeof (address->priv->addr.ipv6);
560 }
561 
562 /**
563  * g_inet_address_get_family:
564  * @address: a #GInetAddress
565  *
566  * Gets @address's family
567  *
568  * Returns: @address's family
569  *
570  * Since: 2.22
571  */
572 GSocketFamily
g_inet_address_get_family(GInetAddress * address)573 g_inet_address_get_family (GInetAddress *address)
574 {
575   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
576 
577   return address->priv->family;
578 }
579 
580 /**
581  * g_inet_address_get_is_any:
582  * @address: a #GInetAddress
583  *
584  * Tests whether @address is the "any" address for its family.
585  *
586  * Returns: %TRUE if @address is the "any" address for its family.
587  *
588  * Since: 2.22
589  */
590 gboolean
g_inet_address_get_is_any(GInetAddress * address)591 g_inet_address_get_is_any (GInetAddress *address)
592 {
593   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
594 
595   if (address->priv->family == AF_INET)
596     {
597       guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
598 
599       return addr4 == INADDR_ANY;
600     }
601   else
602     return IN6_IS_ADDR_UNSPECIFIED (&address->priv->addr.ipv6);
603 }
604 
605 /**
606  * g_inet_address_get_is_loopback:
607  * @address: a #GInetAddress
608  *
609  * Tests whether @address is the loopback address for its family.
610  *
611  * Returns: %TRUE if @address is the loopback address for its family.
612  *
613  * Since: 2.22
614  */
615 gboolean
g_inet_address_get_is_loopback(GInetAddress * address)616 g_inet_address_get_is_loopback (GInetAddress *address)
617 {
618   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
619 
620   if (address->priv->family == AF_INET)
621     {
622       guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
623 
624       /* 127.0.0.0/8 */
625       return ((addr4 & 0xff000000) == 0x7f000000);
626     }
627   else
628     return IN6_IS_ADDR_LOOPBACK (&address->priv->addr.ipv6);
629 }
630 
631 /**
632  * g_inet_address_get_is_link_local:
633  * @address: a #GInetAddress
634  *
635  * Tests whether @address is a link-local address (that is, if it
636  * identifies a host on a local network that is not connected to the
637  * Internet).
638  *
639  * Returns: %TRUE if @address is a link-local address.
640  *
641  * Since: 2.22
642  */
643 gboolean
g_inet_address_get_is_link_local(GInetAddress * address)644 g_inet_address_get_is_link_local (GInetAddress *address)
645 {
646   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
647 
648   if (address->priv->family == AF_INET)
649     {
650       guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
651 
652       /* 169.254.0.0/16 */
653       return ((addr4 & 0xffff0000) == 0xa9fe0000);
654     }
655   else
656     return IN6_IS_ADDR_LINKLOCAL (&address->priv->addr.ipv6);
657 }
658 
659 /**
660  * g_inet_address_get_is_site_local:
661  * @address: a #GInetAddress
662  *
663  * Tests whether @address is a site-local address such as 10.0.0.1
664  * (that is, the address identifies a host on a local network that can
665  * not be reached directly from the Internet, but which may have
666  * outgoing Internet connectivity via a NAT or firewall).
667  *
668  * Returns: %TRUE if @address is a site-local address.
669  *
670  * Since: 2.22
671  */
672 gboolean
g_inet_address_get_is_site_local(GInetAddress * address)673 g_inet_address_get_is_site_local (GInetAddress *address)
674 {
675   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
676 
677   if (address->priv->family == AF_INET)
678     {
679       guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
680 
681       /* 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 */
682       return ((addr4 & 0xff000000) == 0x0a000000 ||
683 	      (addr4 & 0xfff00000) == 0xac100000 ||
684 	      (addr4 & 0xffff0000) == 0xc0a80000);
685     }
686   else
687     return IN6_IS_ADDR_SITELOCAL (&address->priv->addr.ipv6);
688 }
689 
690 /**
691  * g_inet_address_get_is_multicast:
692  * @address: a #GInetAddress
693  *
694  * Tests whether @address is a multicast address.
695  *
696  * Returns: %TRUE if @address is a multicast address.
697  *
698  * Since: 2.22
699  */
700 gboolean
g_inet_address_get_is_multicast(GInetAddress * address)701 g_inet_address_get_is_multicast (GInetAddress *address)
702 {
703   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
704 
705   if (address->priv->family == AF_INET)
706     {
707       guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
708 
709       return IN_MULTICAST (addr4);
710     }
711   else
712     return IN6_IS_ADDR_MULTICAST (&address->priv->addr.ipv6);
713 }
714 
715 /**
716  * g_inet_address_get_is_mc_global:
717  * @address: a #GInetAddress
718  *
719  * Tests whether @address is a global multicast address.
720  *
721  * Returns: %TRUE if @address is a global multicast address.
722  *
723  * Since: 2.22
724  */
725 gboolean
g_inet_address_get_is_mc_global(GInetAddress * address)726 g_inet_address_get_is_mc_global (GInetAddress *address)
727 {
728   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
729 
730   if (address->priv->family == AF_INET)
731     return FALSE;
732   else
733     return IN6_IS_ADDR_MC_GLOBAL (&address->priv->addr.ipv6);
734 }
735 
736 /**
737  * g_inet_address_get_is_mc_link_local:
738  * @address: a #GInetAddress
739  *
740  * Tests whether @address is a link-local multicast address.
741  *
742  * Returns: %TRUE if @address is a link-local multicast address.
743  *
744  * Since: 2.22
745  */
746 gboolean
g_inet_address_get_is_mc_link_local(GInetAddress * address)747 g_inet_address_get_is_mc_link_local (GInetAddress *address)
748 {
749   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
750 
751   if (address->priv->family == AF_INET)
752     return FALSE;
753   else
754     return IN6_IS_ADDR_MC_LINKLOCAL (&address->priv->addr.ipv6);
755 }
756 
757 /**
758  * g_inet_address_get_is_mc_node_local:
759  * @address: a #GInetAddress
760  *
761  * Tests whether @address is a node-local multicast address.
762  *
763  * Returns: %TRUE if @address is a node-local multicast address.
764  *
765  * Since: 2.22
766  */
767 gboolean
g_inet_address_get_is_mc_node_local(GInetAddress * address)768 g_inet_address_get_is_mc_node_local (GInetAddress *address)
769 {
770   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
771 
772   if (address->priv->family == AF_INET)
773     return FALSE;
774   else
775     return IN6_IS_ADDR_MC_NODELOCAL (&address->priv->addr.ipv6);
776 }
777 
778 /**
779  * g_inet_address_get_is_mc_org_local:
780  * @address: a #GInetAddress
781  *
782  * Tests whether @address is an organization-local multicast address.
783  *
784  * Returns: %TRUE if @address is an organization-local multicast address.
785  *
786  * Since: 2.22
787  */
788 gboolean
g_inet_address_get_is_mc_org_local(GInetAddress * address)789 g_inet_address_get_is_mc_org_local  (GInetAddress *address)
790 {
791   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
792 
793   if (address->priv->family == AF_INET)
794     return FALSE;
795   else
796     return IN6_IS_ADDR_MC_ORGLOCAL (&address->priv->addr.ipv6);
797 }
798 
799 /**
800  * g_inet_address_get_is_mc_site_local:
801  * @address: a #GInetAddress
802  *
803  * Tests whether @address is a site-local multicast address.
804  *
805  * Returns: %TRUE if @address is a site-local multicast address.
806  *
807  * Since: 2.22
808  */
809 gboolean
g_inet_address_get_is_mc_site_local(GInetAddress * address)810 g_inet_address_get_is_mc_site_local (GInetAddress *address)
811 {
812   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
813 
814   if (address->priv->family == AF_INET)
815     return FALSE;
816   else
817     return IN6_IS_ADDR_MC_SITELOCAL (&address->priv->addr.ipv6);
818 }
819 
820 /**
821  * g_inet_address_equal:
822  * @address: A #GInetAddress.
823  * @other_address: Another #GInetAddress.
824  *
825  * Checks if two #GInetAddress instances are equal, e.g. the same address.
826  *
827  * Returns: %TRUE if @address and @other_address are equal, %FALSE otherwise.
828  *
829  * Since: 2.30
830  */
831 gboolean
g_inet_address_equal(GInetAddress * address,GInetAddress * other_address)832 g_inet_address_equal (GInetAddress *address,
833                       GInetAddress *other_address)
834 {
835   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
836   g_return_val_if_fail (G_IS_INET_ADDRESS (other_address), FALSE);
837 
838   if (g_inet_address_get_family (address) != g_inet_address_get_family (other_address))
839     return FALSE;
840 
841   if (memcmp (g_inet_address_to_bytes (address),
842               g_inet_address_to_bytes (other_address),
843               g_inet_address_get_native_size (address)) != 0)
844     return FALSE;
845 
846   return TRUE;
847 }
848