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