1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright (C) 2008 Christian Kellner, Samuel Cormier-Iijima
5 * SPDX-License-Identifier: LGPL-2.1-or-later
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 * Authors: Christian Kellner <gicmo@gnome.org>
21 * Samuel Cormier-Iijima <sciyoshi@gmail.com>
30 #include "ginetaddress.h"
32 #include "gioenumtypes.h"
34 #include "gnetworkingprivate.h"
36 struct _GInetAddressPrivate
50 * `GInetAddress` represents an IPv4 or IPv6 internet address. Use
51 * [method@Gio.Resolver.lookup_by_name] or
52 * [method@Gio.Resolver.lookup_by_name_async] to look up the `GInetAddress` for
53 * a hostname. Use [method@Gio.Resolver.lookup_by_address] or
54 * [method@Gio.Resolver.lookup_by_address_async] to look up the hostname for a
57 * To actually connect to a remote host, you will need a
58 * [class@Gio.InetSocketAddress] (which includes a `GInetAddress` as well as a
62 G_DEFINE_TYPE_WITH_CODE (GInetAddress, g_inet_address, G_TYPE_OBJECT,
63 G_ADD_PRIVATE (GInetAddress)
64 g_networking_init ();)
77 PROP_IS_MC_LINK_LOCAL,
78 PROP_IS_MC_NODE_LOCAL,
80 PROP_IS_MC_SITE_LOCAL,
84 g_inet_address_set_property (GObject *object,
89 GInetAddress *address = G_INET_ADDRESS (object);
94 address->priv->family = g_value_get_enum (value);
99 memcpy (&address->priv->addr, g_value_get_pointer (value),
100 address->priv->family == AF_INET ?
101 sizeof (address->priv->addr.ipv4) :
102 sizeof (address->priv->addr.ipv6));
104 g_assert (address->priv->family == AF_INET);
105 memcpy (&address->priv->addr, g_value_get_pointer (value),
106 sizeof (address->priv->addr.ipv4));
111 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
118 g_inet_address_get_property (GObject *object,
123 GInetAddress *address = G_INET_ADDRESS (object);
128 g_value_set_enum (value, address->priv->family);
132 g_value_set_pointer (value, &address->priv->addr);
136 g_value_set_boolean (value, g_inet_address_get_is_any (address));
139 case PROP_IS_LOOPBACK:
140 g_value_set_boolean (value, g_inet_address_get_is_loopback (address));
143 case PROP_IS_LINK_LOCAL:
144 g_value_set_boolean (value, g_inet_address_get_is_link_local (address));
147 case PROP_IS_SITE_LOCAL:
148 g_value_set_boolean (value, g_inet_address_get_is_site_local (address));
151 case PROP_IS_MULTICAST:
152 g_value_set_boolean (value, g_inet_address_get_is_multicast (address));
155 case PROP_IS_MC_GLOBAL:
156 g_value_set_boolean (value, g_inet_address_get_is_mc_global (address));
159 case PROP_IS_MC_LINK_LOCAL:
160 g_value_set_boolean (value, g_inet_address_get_is_mc_link_local (address));
163 case PROP_IS_MC_NODE_LOCAL:
164 g_value_set_boolean (value, g_inet_address_get_is_mc_node_local (address));
167 case PROP_IS_MC_ORG_LOCAL:
168 g_value_set_boolean (value, g_inet_address_get_is_mc_org_local (address));
171 case PROP_IS_MC_SITE_LOCAL:
172 g_value_set_boolean (value, g_inet_address_get_is_mc_site_local (address));
176 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
181 g_inet_address_class_init (GInetAddressClass *klass)
183 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
185 gobject_class->set_property = g_inet_address_set_property;
186 gobject_class->get_property = g_inet_address_get_property;
189 * GInetAddress:family:
191 * The address family (IPv4 or IPv6).
195 g_object_class_install_property (gobject_class, PROP_FAMILY,
196 g_param_spec_enum ("family", NULL, NULL,
197 G_TYPE_SOCKET_FAMILY,
198 G_SOCKET_FAMILY_INVALID,
200 G_PARAM_CONSTRUCT_ONLY |
201 G_PARAM_STATIC_STRINGS));
204 * GInetAddress:bytes:
206 * The raw address data.
210 g_object_class_install_property (gobject_class, PROP_BYTES,
211 g_param_spec_pointer ("bytes", NULL, NULL,
213 G_PARAM_CONSTRUCT_ONLY |
214 G_PARAM_STATIC_STRINGS));
217 * GInetAddress:is-any:
219 * Whether this is the "any" address for its family.
220 * See g_inet_address_get_is_any().
224 g_object_class_install_property (gobject_class, PROP_IS_ANY,
225 g_param_spec_boolean ("is-any", NULL, NULL,
228 G_PARAM_STATIC_STRINGS));
231 * GInetAddress:is-link-local:
233 * Whether this is a link-local address.
234 * See g_inet_address_get_is_link_local().
238 g_object_class_install_property (gobject_class, PROP_IS_LINK_LOCAL,
239 g_param_spec_boolean ("is-link-local", NULL, NULL,
242 G_PARAM_STATIC_STRINGS));
245 * GInetAddress:is-loopback:
247 * Whether this is the loopback address for its family.
248 * See g_inet_address_get_is_loopback().
252 g_object_class_install_property (gobject_class, PROP_IS_LOOPBACK,
253 g_param_spec_boolean ("is-loopback", NULL, NULL,
256 G_PARAM_STATIC_STRINGS));
259 * GInetAddress:is-site-local:
261 * Whether this is a site-local address.
262 * See g_inet_address_get_is_loopback().
266 g_object_class_install_property (gobject_class, PROP_IS_SITE_LOCAL,
267 g_param_spec_boolean ("is-site-local", NULL, NULL,
270 G_PARAM_STATIC_STRINGS));
273 * GInetAddress:is-multicast:
275 * Whether this is a multicast address.
276 * See g_inet_address_get_is_multicast().
280 g_object_class_install_property (gobject_class, PROP_IS_MULTICAST,
281 g_param_spec_boolean ("is-multicast", NULL, NULL,
284 G_PARAM_STATIC_STRINGS));
287 * GInetAddress:is-mc-global:
289 * Whether this is a global multicast address.
290 * See g_inet_address_get_is_mc_global().
294 g_object_class_install_property (gobject_class, PROP_IS_MC_GLOBAL,
295 g_param_spec_boolean ("is-mc-global", NULL, NULL,
298 G_PARAM_STATIC_STRINGS));
302 * GInetAddress:is-mc-link-local:
304 * Whether this is a link-local multicast address.
305 * See g_inet_address_get_is_mc_link_local().
309 g_object_class_install_property (gobject_class, PROP_IS_MC_LINK_LOCAL,
310 g_param_spec_boolean ("is-mc-link-local", NULL, NULL,
313 G_PARAM_STATIC_STRINGS));
316 * GInetAddress:is-mc-node-local:
318 * Whether this is a node-local multicast address.
319 * See g_inet_address_get_is_mc_node_local().
323 g_object_class_install_property (gobject_class, PROP_IS_MC_NODE_LOCAL,
324 g_param_spec_boolean ("is-mc-node-local", NULL, NULL,
327 G_PARAM_STATIC_STRINGS));
330 * GInetAddress:is-mc-org-local:
332 * Whether this is an organization-local multicast address.
333 * See g_inet_address_get_is_mc_org_local().
337 g_object_class_install_property (gobject_class, PROP_IS_MC_ORG_LOCAL,
338 g_param_spec_boolean ("is-mc-org-local", NULL, NULL,
341 G_PARAM_STATIC_STRINGS));
344 * GInetAddress:is-mc-site-local:
346 * Whether this is a site-local multicast address.
347 * See g_inet_address_get_is_mc_site_local().
351 g_object_class_install_property (gobject_class, PROP_IS_MC_SITE_LOCAL,
352 g_param_spec_boolean ("is-mc-site-local", NULL, NULL,
355 G_PARAM_STATIC_STRINGS));
359 g_inet_address_init (GInetAddress *address)
361 address->priv = g_inet_address_get_instance_private (address);
365 * g_inet_address_new_from_string:
366 * @string: a string representation of an IP address
368 * Parses @string as an IP address and creates a new #GInetAddress.
370 * Returns: (nullable) (transfer full): a new #GInetAddress corresponding
371 * to @string, or %NULL if @string could not be parsed.
372 * Free the returned object with g_object_unref().
377 g_inet_address_new_from_string (const gchar *string)
379 struct in_addr in_addr;
381 struct in6_addr in6_addr;
384 g_return_val_if_fail (string != NULL, NULL);
386 /* If this GInetAddress is the first networking-related object to be
387 * created, then we won't have called g_networking_init() yet at
390 g_networking_init ();
392 if (inet_pton (AF_INET, string, &in_addr) > 0)
393 return g_inet_address_new_from_bytes ((guint8 *)&in_addr, AF_INET);
395 else if (inet_pton (AF_INET6, string, &in6_addr) > 0)
396 return g_inet_address_new_from_bytes ((guint8 *)&in6_addr, AF_INET6);
402 #define G_INET_ADDRESS_FAMILY_IS_VALID(family) ((family) == AF_INET || (family) == AF_INET6)
405 * g_inet_address_new_from_bytes:
406 * @bytes: (array) (element-type guint8): raw address data
407 * @family: the address family of @bytes
409 * Creates a new #GInetAddress from the given @family and @bytes.
410 * @bytes should be 4 bytes for %G_SOCKET_FAMILY_IPV4 and 16 bytes for
411 * %G_SOCKET_FAMILY_IPV6.
413 * Returns: a new #GInetAddress corresponding to @family and @bytes.
414 * Free the returned object with g_object_unref().
419 g_inet_address_new_from_bytes (const guint8 *bytes,
420 GSocketFamily family)
422 g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
424 return g_object_new (G_TYPE_INET_ADDRESS,
431 * g_inet_address_new_loopback:
432 * @family: the address family
434 * Creates a #GInetAddress for the loopback address for @family.
436 * Returns: a new #GInetAddress corresponding to the loopback address
438 * Free the returned object with g_object_unref().
443 g_inet_address_new_loopback (GSocketFamily family)
445 g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
447 if (family == AF_INET)
449 guint8 addr[4] = {127, 0, 0, 1};
451 return g_inet_address_new_from_bytes (addr, family);
455 return g_inet_address_new_from_bytes (in6addr_loopback.s6_addr, family);
457 g_assert_not_reached ();
462 * g_inet_address_new_any:
463 * @family: the address family
465 * Creates a #GInetAddress for the "any" address (unassigned/"don't
466 * care") for @family.
468 * Returns: a new #GInetAddress corresponding to the "any" address
470 * Free the returned object with g_object_unref().
475 g_inet_address_new_any (GSocketFamily family)
477 g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
479 if (family == AF_INET)
481 guint8 addr[4] = {0, 0, 0, 0};
483 return g_inet_address_new_from_bytes (addr, family);
487 return g_inet_address_new_from_bytes (in6addr_any.s6_addr, family);
489 g_assert_not_reached ();
495 * g_inet_address_to_string:
496 * @address: a #GInetAddress
498 * Converts @address to string form.
500 * Returns: a representation of @address as a string, which should be
506 g_inet_address_to_string (GInetAddress *address)
508 gchar buffer[INET6_ADDRSTRLEN];
510 g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
512 if (address->priv->family == AF_INET)
514 inet_ntop (AF_INET, &address->priv->addr.ipv4, buffer, sizeof (buffer));
515 return g_strdup (buffer);
520 inet_ntop (AF_INET6, &address->priv->addr.ipv6, buffer, sizeof (buffer));
521 return g_strdup (buffer);
523 g_assert_not_reached ();
529 * g_inet_address_to_bytes: (skip)
530 * @address: a #GInetAddress
532 * Gets the raw binary address data from @address.
534 * Returns: a pointer to an internal array of the bytes in @address,
535 * which should not be modified, stored, or freed. The size of this
536 * array can be gotten with g_inet_address_get_native_size().
541 g_inet_address_to_bytes (GInetAddress *address)
543 g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
545 return (guint8 *)&address->priv->addr;
549 * g_inet_address_get_native_size:
550 * @address: a #GInetAddress
552 * Gets the size of the native raw binary address for @address. This
553 * is the size of the data that you get from g_inet_address_to_bytes().
555 * Returns: the number of bytes used for the native version of @address.
560 g_inet_address_get_native_size (GInetAddress *address)
562 if (address->priv->family == AF_INET)
563 return sizeof (address->priv->addr.ipv4);
565 return sizeof (address->priv->addr.ipv6);
567 g_assert_not_reached ();
572 * g_inet_address_get_family:
573 * @address: a #GInetAddress
575 * Gets @address's family
577 * Returns: @address's family
582 g_inet_address_get_family (GInetAddress *address)
584 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
586 return address->priv->family;
590 * g_inet_address_get_is_any:
591 * @address: a #GInetAddress
593 * Tests whether @address is the "any" address for its family.
595 * Returns: %TRUE if @address is the "any" address for its family.
600 g_inet_address_get_is_any (GInetAddress *address)
602 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
604 if (address->priv->family == AF_INET)
606 guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
608 return addr4 == INADDR_ANY;
612 return IN6_IS_ADDR_UNSPECIFIED (&address->priv->addr.ipv6);
614 g_assert_not_reached ();
619 * g_inet_address_get_is_loopback:
620 * @address: a #GInetAddress
622 * Tests whether @address is the loopback address for its family.
624 * Returns: %TRUE if @address is the loopback address for its family.
629 g_inet_address_get_is_loopback (GInetAddress *address)
631 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
633 if (address->priv->family == AF_INET)
635 guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
638 return ((addr4 & 0xff000000) == 0x7f000000);
642 return IN6_IS_ADDR_LOOPBACK (&address->priv->addr.ipv6);
644 g_assert_not_reached ();
649 * g_inet_address_get_is_link_local:
650 * @address: a #GInetAddress
652 * Tests whether @address is a link-local address (that is, if it
653 * identifies a host on a local network that is not connected to the
656 * Returns: %TRUE if @address is a link-local address.
661 g_inet_address_get_is_link_local (GInetAddress *address)
663 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
665 if (address->priv->family == AF_INET)
667 guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
670 return ((addr4 & 0xffff0000) == 0xa9fe0000);
674 return IN6_IS_ADDR_LINKLOCAL (&address->priv->addr.ipv6);
676 g_assert_not_reached ();
681 * g_inet_address_get_is_site_local:
682 * @address: a #GInetAddress
684 * Tests whether @address is a site-local address such as 10.0.0.1
685 * (that is, the address identifies a host on a local network that can
686 * not be reached directly from the Internet, but which may have
687 * outgoing Internet connectivity via a NAT or firewall).
689 * Returns: %TRUE if @address is a site-local address.
694 g_inet_address_get_is_site_local (GInetAddress *address)
696 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
698 if (address->priv->family == AF_INET)
700 guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
702 /* 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 */
703 return ((addr4 & 0xff000000) == 0x0a000000 ||
704 (addr4 & 0xfff00000) == 0xac100000 ||
705 (addr4 & 0xffff0000) == 0xc0a80000);
709 return IN6_IS_ADDR_SITELOCAL (&address->priv->addr.ipv6);
711 g_assert_not_reached ();
716 * g_inet_address_get_is_multicast:
717 * @address: a #GInetAddress
719 * Tests whether @address is a multicast address.
721 * Returns: %TRUE if @address is a multicast address.
726 g_inet_address_get_is_multicast (GInetAddress *address)
728 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
730 if (address->priv->family == AF_INET)
732 guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
734 return IN_MULTICAST (addr4);
738 return IN6_IS_ADDR_MULTICAST (&address->priv->addr.ipv6);
740 g_assert_not_reached ();
745 * g_inet_address_get_is_mc_global:
746 * @address: a #GInetAddress
748 * Tests whether @address is a global multicast address.
750 * Returns: %TRUE if @address is a global multicast address.
755 g_inet_address_get_is_mc_global (GInetAddress *address)
757 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
759 if (address->priv->family == AF_INET)
763 return IN6_IS_ADDR_MC_GLOBAL (&address->priv->addr.ipv6);
765 g_assert_not_reached ();
770 * g_inet_address_get_is_mc_link_local:
771 * @address: a #GInetAddress
773 * Tests whether @address is a link-local multicast address.
775 * Returns: %TRUE if @address is a link-local multicast address.
780 g_inet_address_get_is_mc_link_local (GInetAddress *address)
782 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
784 if (address->priv->family == AF_INET)
788 return IN6_IS_ADDR_MC_LINKLOCAL (&address->priv->addr.ipv6);
790 g_assert_not_reached ();
795 * g_inet_address_get_is_mc_node_local:
796 * @address: a #GInetAddress
798 * Tests whether @address is a node-local multicast address.
800 * Returns: %TRUE if @address is a node-local multicast address.
805 g_inet_address_get_is_mc_node_local (GInetAddress *address)
807 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
809 if (address->priv->family == AF_INET)
813 return IN6_IS_ADDR_MC_NODELOCAL (&address->priv->addr.ipv6);
815 g_assert_not_reached ();
820 * g_inet_address_get_is_mc_org_local:
821 * @address: a #GInetAddress
823 * Tests whether @address is an organization-local multicast address.
825 * Returns: %TRUE if @address is an organization-local multicast address.
830 g_inet_address_get_is_mc_org_local (GInetAddress *address)
832 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
834 if (address->priv->family == AF_INET)
838 return IN6_IS_ADDR_MC_ORGLOCAL (&address->priv->addr.ipv6);
840 g_assert_not_reached ();
845 * g_inet_address_get_is_mc_site_local:
846 * @address: a #GInetAddress
848 * Tests whether @address is a site-local multicast address.
850 * Returns: %TRUE if @address is a site-local multicast address.
855 g_inet_address_get_is_mc_site_local (GInetAddress *address)
857 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
859 if (address->priv->family == AF_INET)
863 return IN6_IS_ADDR_MC_SITELOCAL (&address->priv->addr.ipv6);
865 g_assert_not_reached ();
870 * g_inet_address_equal:
871 * @address: A #GInetAddress.
872 * @other_address: Another #GInetAddress.
874 * Checks if two #GInetAddress instances are equal, e.g. the same address.
876 * Returns: %TRUE if @address and @other_address are equal, %FALSE otherwise.
881 g_inet_address_equal (GInetAddress *address,
882 GInetAddress *other_address)
884 g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
885 g_return_val_if_fail (G_IS_INET_ADDRESS (other_address), FALSE);
887 if (g_inet_address_get_family (address) != g_inet_address_get_family (other_address))
890 if (memcmp (g_inet_address_to_bytes (address),
891 g_inet_address_to_bytes (other_address),
892 g_inet_address_get_native_size (address)) != 0)