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