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