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