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
34struct _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
68G_DEFINE_TYPE_WITH_CODE (GInetAddress, g_inet_address, G_TYPE_OBJECT,
69 G_ADD_PRIVATE (GInetAddress)
70 g_networking_init ();)
71
72enum
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
89static void
90g_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 (dest: &address->priv->addr, src: g_value_get_pointer (value),
106 n: 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
123static void
124g_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, v_enum: address->priv->family);
135 break;
136
137 case PROP_BYTES:
138 g_value_set_pointer (value, v_pointer: &address->priv->addr);
139 break;
140
141 case PROP_IS_ANY:
142 g_value_set_boolean (value, v_boolean: g_inet_address_get_is_any (address));
143 break;
144
145 case PROP_IS_LOOPBACK:
146 g_value_set_boolean (value, v_boolean: g_inet_address_get_is_loopback (address));
147 break;
148
149 case PROP_IS_LINK_LOCAL:
150 g_value_set_boolean (value, v_boolean: g_inet_address_get_is_link_local (address));
151 break;
152
153 case PROP_IS_SITE_LOCAL:
154 g_value_set_boolean (value, v_boolean: g_inet_address_get_is_site_local (address));
155 break;
156
157 case PROP_IS_MULTICAST:
158 g_value_set_boolean (value, v_boolean: g_inet_address_get_is_multicast (address));
159 break;
160
161 case PROP_IS_MC_GLOBAL:
162 g_value_set_boolean (value, v_boolean: g_inet_address_get_is_mc_global (address));
163 break;
164
165 case PROP_IS_MC_LINK_LOCAL:
166 g_value_set_boolean (value, v_boolean: 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, v_boolean: 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, v_boolean: 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, v_boolean: 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
186static void
187g_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 (oclass: gobject_class, property_id: PROP_FAMILY,
195 pspec: g_param_spec_enum (name: "family",
196 P_("Address family"),
197 P_("The address family (IPv4 or IPv6)"),
198 enum_type: G_TYPE_SOCKET_FAMILY,
199 default_value: G_SOCKET_FAMILY_INVALID,
200 flags: G_PARAM_READWRITE |
201 G_PARAM_CONSTRUCT_ONLY |
202 G_PARAM_STATIC_STRINGS));
203
204 g_object_class_install_property (oclass: gobject_class, property_id: PROP_BYTES,
205 pspec: g_param_spec_pointer (name: "bytes",
206 P_("Bytes"),
207 P_("The raw address data"),
208 flags: 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 (oclass: gobject_class, property_id: PROP_IS_ANY,
221 pspec: g_param_spec_boolean (name: "is-any",
222 P_("Is any"),
223 P_("Whether this is the \"any\" address for its family"),
224 FALSE,
225 flags: 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 (oclass: gobject_class, property_id: PROP_IS_LINK_LOCAL,
237 pspec: g_param_spec_boolean (name: "is-link-local",
238 P_("Is link-local"),
239 P_("Whether this is a link-local address"),
240 FALSE,
241 flags: 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 (oclass: gobject_class, property_id: PROP_IS_LOOPBACK,
253 pspec: g_param_spec_boolean (name: "is-loopback",
254 P_("Is loopback"),
255 P_("Whether this is the loopback address for its family"),
256 FALSE,
257 flags: 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 (oclass: gobject_class, property_id: PROP_IS_SITE_LOCAL,
269 pspec: g_param_spec_boolean (name: "is-site-local",
270 P_("Is site-local"),
271 P_("Whether this is a site-local address"),
272 FALSE,
273 flags: 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 (oclass: gobject_class, property_id: PROP_IS_MULTICAST,
285 pspec: g_param_spec_boolean (name: "is-multicast",
286 P_("Is multicast"),
287 P_("Whether this is a multicast address"),
288 FALSE,
289 flags: 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 (oclass: gobject_class, property_id: PROP_IS_MC_GLOBAL,
301 pspec: g_param_spec_boolean (name: "is-mc-global",
302 P_("Is multicast global"),
303 P_("Whether this is a global multicast address"),
304 FALSE,
305 flags: 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 (oclass: gobject_class, property_id: PROP_IS_MC_LINK_LOCAL,
318 pspec: g_param_spec_boolean (name: "is-mc-link-local",
319 P_("Is multicast link-local"),
320 P_("Whether this is a link-local multicast address"),
321 FALSE,
322 flags: 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 (oclass: gobject_class, property_id: PROP_IS_MC_NODE_LOCAL,
334 pspec: g_param_spec_boolean (name: "is-mc-node-local",
335 P_("Is multicast node-local"),
336 P_("Whether this is a node-local multicast address"),
337 FALSE,
338 flags: 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 (oclass: gobject_class, property_id: PROP_IS_MC_ORG_LOCAL,
350 pspec: g_param_spec_boolean (name: "is-mc-org-local",
351 P_("Is multicast org-local"),
352 P_("Whether this is an organization-local multicast address"),
353 FALSE,
354 flags: 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 (oclass: gobject_class, property_id: PROP_IS_MC_SITE_LOCAL,
366 pspec: g_param_spec_boolean (name: "is-mc-site-local",
367 P_("Is multicast site-local"),
368 P_("Whether this is a site-local multicast address"),
369 FALSE,
370 flags: G_PARAM_READABLE |
371 G_PARAM_STATIC_STRINGS));
372}
373
374static void
375g_inet_address_init (GInetAddress *address)
376{
377 address->priv = g_inet_address_get_instance_private (self: 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 */
392GInetAddress *
393g_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, cp: string, buf: &in_addr) > 0)
409 return g_inet_address_new_from_bytes (bytes: (guint8 *)&in_addr, AF_INET);
410#ifdef HAVE_IPV6
411 else if (inet_pton (AF_INET6, cp: string, buf: &in6_addr) > 0)
412 return g_inet_address_new_from_bytes (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 */
434GInetAddress *
435g_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 first_property_name: "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 */
458GInetAddress *
459g_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 (bytes: addr, family);
468 }
469 else
470#ifdef HAVE_IPV6
471 return g_inet_address_new_from_bytes (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 */
490GInetAddress *
491g_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 (bytes: addr, family);
500 }
501 else
502#ifdef HAVE_IPV6
503 return g_inet_address_new_from_bytes (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 */
521gchar *
522g_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, cp: &address->priv->addr.ipv4, buf: buffer, len: sizeof (buffer));
531 return g_strdup (str: buffer);
532 }
533 else
534 {
535#ifdef HAVE_IPV6
536 inet_ntop (AF_INET6, cp: &address->priv->addr.ipv6, buf: buffer, len: sizeof (buffer));
537 return g_strdup (str: 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 */
556const guint8 *
557g_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 */
575gsize
576g_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 */
597GSocketFamily
598g_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 */
615gboolean
616g_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 */
644gboolean
645g_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 */
676gboolean
677g_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 */
709gboolean
710g_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 */
741gboolean
742g_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 */
770gboolean
771g_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 */
795gboolean
796g_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 */
820gboolean
821g_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 */
845gboolean
846g_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 */
870gboolean
871g_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 */
896gboolean
897g_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 (address: other_address))
904 return FALSE;
905
906 if (memcmp (s1: g_inet_address_to_bytes (address),
907 s2: g_inet_address_to_bytes (address: other_address),
908 n: g_inet_address_get_native_size (address)) != 0)
909 return FALSE;
910
911 return TRUE;
912}
913

source code of gtk/subprojects/glib/gio/ginetaddress.c