(root)/
glib-2.79.0/
gio/
ginetsocketaddress.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  #include <glib.h>
      26  #include <string.h>
      27  
      28  #include "ginetsocketaddress.h"
      29  #include "ginetaddress.h"
      30  #include "gnetworkingprivate.h"
      31  #include "gsocketconnectable.h"
      32  #include "gioerror.h"
      33  #include "glibintl.h"
      34  
      35  
      36  /**
      37   * GInetSocketAddress:
      38   *
      39   * An IPv4 or IPv6 socket address. That is, the combination of a
      40   * [class@Gio.InetAddress] and a port number.
      41   *
      42   * In UNIX terms, `GInetSocketAddress` corresponds to a
      43   * [`struct sockaddr_in` or `struct sockaddr_in6`](man:sockaddr(3type)).
      44   */
      45  
      46  struct _GInetSocketAddressPrivate
      47  {
      48    GInetAddress *address;
      49    guint16       port;
      50    guint32       flowinfo;
      51    guint32       scope_id;
      52  };
      53  
      54  static void   g_inet_socket_address_connectable_iface_init (GSocketConnectableIface *iface);
      55  static gchar *g_inet_socket_address_connectable_to_string  (GSocketConnectable      *connectable);
      56  
      57  G_DEFINE_TYPE_WITH_CODE (GInetSocketAddress, g_inet_socket_address, G_TYPE_SOCKET_ADDRESS,
      58                           G_ADD_PRIVATE (GInetSocketAddress)
      59                           G_IMPLEMENT_INTERFACE (G_TYPE_SOCKET_CONNECTABLE,
      60                                                  g_inet_socket_address_connectable_iface_init))
      61  
      62  enum {
      63    PROP_0,
      64    PROP_ADDRESS,
      65    PROP_PORT,
      66    PROP_FLOWINFO,
      67    PROP_SCOPE_ID
      68  };
      69  
      70  static void
      71  g_inet_socket_address_dispose (GObject *object)
      72  {
      73    GInetSocketAddress *address = G_INET_SOCKET_ADDRESS (object);
      74  
      75    g_clear_object (&(address->priv->address));
      76  
      77    G_OBJECT_CLASS (g_inet_socket_address_parent_class)->dispose (object);
      78  }
      79  
      80  static void
      81  g_inet_socket_address_get_property (GObject    *object,
      82                                      guint       prop_id,
      83                                      GValue     *value,
      84                                      GParamSpec *pspec)
      85  {
      86    GInetSocketAddress *address = G_INET_SOCKET_ADDRESS (object);
      87  
      88    switch (prop_id)
      89      {
      90        case PROP_ADDRESS:
      91          g_value_set_object (value, address->priv->address);
      92          break;
      93  
      94        case PROP_PORT:
      95          g_value_set_uint (value, address->priv->port);
      96          break;
      97  
      98        case PROP_FLOWINFO:
      99  	g_return_if_fail (g_inet_address_get_family (address->priv->address) == G_SOCKET_FAMILY_IPV6);
     100          g_value_set_uint (value, address->priv->flowinfo);
     101          break;
     102  
     103        case PROP_SCOPE_ID:
     104  	g_return_if_fail (g_inet_address_get_family (address->priv->address) == G_SOCKET_FAMILY_IPV6);
     105          g_value_set_uint (value, address->priv->scope_id);
     106          break;
     107  
     108        default:
     109          G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     110      }
     111  }
     112  
     113  static void
     114  g_inet_socket_address_set_property (GObject      *object,
     115                                      guint         prop_id,
     116                                      const GValue *value,
     117                                      GParamSpec   *pspec)
     118  {
     119    GInetSocketAddress *address = G_INET_SOCKET_ADDRESS (object);
     120  
     121    switch (prop_id)
     122      {
     123        case PROP_ADDRESS:
     124          address->priv->address = g_object_ref (g_value_get_object (value));
     125          break;
     126  
     127        case PROP_PORT:
     128          address->priv->port = (guint16) g_value_get_uint (value);
     129          break;
     130  
     131        case PROP_FLOWINFO:
     132  	/* We can't test that address->priv->address is IPv6 here,
     133  	 * since this property might get set before PROP_ADDRESS.
     134  	 */
     135          address->priv->flowinfo = g_value_get_uint (value);
     136          break;
     137  
     138        case PROP_SCOPE_ID:
     139          address->priv->scope_id = g_value_get_uint (value);
     140          break;
     141  
     142        default:
     143          G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     144      }
     145  }
     146  
     147  static GSocketFamily
     148  g_inet_socket_address_get_family (GSocketAddress *address)
     149  {
     150    GInetSocketAddress *addr;
     151  
     152    g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), 0);
     153  
     154    addr = G_INET_SOCKET_ADDRESS (address);
     155  
     156    return g_inet_address_get_family (addr->priv->address);
     157  }
     158  
     159  static gssize
     160  g_inet_socket_address_get_native_size (GSocketAddress *address)
     161  {
     162    GInetSocketAddress *addr;
     163    GSocketFamily family;
     164  
     165    g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), 0);
     166  
     167    addr = G_INET_SOCKET_ADDRESS (address);
     168    family = g_inet_address_get_family (addr->priv->address);
     169  
     170    if (family == AF_INET)
     171      return sizeof (struct sockaddr_in);
     172    else if (family == AF_INET6)
     173      return sizeof (struct sockaddr_in6);
     174    else
     175      return -1;
     176  }
     177  
     178  static gboolean
     179  g_inet_socket_address_to_native (GSocketAddress  *address,
     180                                   gpointer         dest,
     181  				 gsize            destlen,
     182  				 GError         **error)
     183  {
     184    GInetSocketAddress *addr;
     185    GSocketFamily family;
     186  
     187    g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), FALSE);
     188  
     189    addr = G_INET_SOCKET_ADDRESS (address);
     190    family = g_inet_address_get_family (addr->priv->address);
     191  
     192    if (family == AF_INET)
     193      {
     194        struct sockaddr_in *sock = (struct sockaddr_in *) dest;
     195  
     196        if (destlen < sizeof (*sock))
     197  	{
     198  	  g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE,
     199  			       _("Not enough space for socket address"));
     200  	  return FALSE;
     201  	}
     202  
     203        sock->sin_family = AF_INET;
     204        sock->sin_port = g_htons (addr->priv->port);
     205        memcpy (&(sock->sin_addr.s_addr), g_inet_address_to_bytes (addr->priv->address), sizeof (sock->sin_addr));
     206        memset (sock->sin_zero, 0, sizeof (sock->sin_zero));
     207        return TRUE;
     208      }
     209    else if (family == AF_INET6)
     210      {
     211        struct sockaddr_in6 *sock = (struct sockaddr_in6 *) dest;
     212  
     213        if (destlen < sizeof (*sock))
     214  	{
     215  	  g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE,
     216  			       _("Not enough space for socket address"));
     217  	  return FALSE;
     218  	}
     219  
     220        memset (sock, 0, sizeof (*sock));
     221        sock->sin6_family = AF_INET6;
     222        sock->sin6_port = g_htons (addr->priv->port);
     223        sock->sin6_flowinfo = addr->priv->flowinfo;
     224        sock->sin6_scope_id = addr->priv->scope_id;
     225        memcpy (&(sock->sin6_addr.s6_addr), g_inet_address_to_bytes (addr->priv->address), sizeof (sock->sin6_addr));
     226        return TRUE;
     227      }
     228    else
     229      {
     230        g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
     231  			   _("Unsupported socket address"));
     232        return FALSE;
     233      }
     234  }
     235  
     236  static void
     237  g_inet_socket_address_class_init (GInetSocketAddressClass *klass)
     238  {
     239    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     240    GSocketAddressClass *gsocketaddress_class = G_SOCKET_ADDRESS_CLASS (klass);
     241  
     242    gobject_class->dispose = g_inet_socket_address_dispose;
     243    gobject_class->set_property = g_inet_socket_address_set_property;
     244    gobject_class->get_property = g_inet_socket_address_get_property;
     245  
     246    gsocketaddress_class->get_family = g_inet_socket_address_get_family;
     247    gsocketaddress_class->to_native = g_inet_socket_address_to_native;
     248    gsocketaddress_class->get_native_size = g_inet_socket_address_get_native_size;
     249  
     250    /**
     251     * GInetSocketAddress:address:
     252     *
     253     * The address.
     254     *
     255     * Since: 2.22
     256     */
     257    g_object_class_install_property (gobject_class, PROP_ADDRESS,
     258                                     g_param_spec_object ("address", NULL, NULL,
     259                                                          G_TYPE_INET_ADDRESS,
     260                                                          G_PARAM_CONSTRUCT_ONLY |
     261                                                          G_PARAM_READWRITE |
     262                                                          G_PARAM_STATIC_STRINGS));
     263  
     264    /**
     265     * GInetSocketAddress:port:
     266     *
     267     * The port.
     268     *
     269     * Since: 2.22
     270     */
     271    g_object_class_install_property (gobject_class, PROP_PORT,
     272                                     g_param_spec_uint ("port", NULL, NULL,
     273                                                        0,
     274                                                        65535,
     275                                                        0,
     276                                                        G_PARAM_CONSTRUCT_ONLY |
     277                                                        G_PARAM_READWRITE |
     278                                                        G_PARAM_STATIC_STRINGS));
     279  
     280    /**
     281     * GInetSocketAddress:flowinfo:
     282     *
     283     * The `sin6_flowinfo` field, for IPv6 addresses.
     284     *
     285     * Since: 2.32
     286     */
     287    g_object_class_install_property (gobject_class, PROP_FLOWINFO,
     288                                     g_param_spec_uint ("flowinfo", NULL, NULL,
     289                                                        0,
     290                                                        G_MAXUINT32,
     291                                                        0,
     292                                                        G_PARAM_CONSTRUCT_ONLY |
     293                                                        G_PARAM_READWRITE |
     294                                                        G_PARAM_STATIC_STRINGS));
     295  
     296    /**
     297     * GInetSocketAddress:scope-id:
     298     *
     299     * The `sin6_scope_id` field, for IPv6 addresses.
     300     *
     301     * Since: 2.32
     302     */
     303    g_object_class_install_property (gobject_class, PROP_SCOPE_ID,
     304                                     g_param_spec_uint ("scope-id", NULL, NULL,
     305                                                        0,
     306                                                        G_MAXUINT32,
     307                                                        0,
     308                                                        G_PARAM_CONSTRUCT_ONLY |
     309                                                        G_PARAM_READWRITE |
     310                                                        G_PARAM_STATIC_STRINGS));
     311  }
     312  
     313  static void
     314  g_inet_socket_address_connectable_iface_init (GSocketConnectableIface *iface)
     315  {
     316    GSocketConnectableIface *parent_iface = g_type_interface_peek_parent (iface);
     317  
     318    iface->enumerate = parent_iface->enumerate;
     319    iface->proxy_enumerate = parent_iface->proxy_enumerate;
     320    iface->to_string = g_inet_socket_address_connectable_to_string;
     321  }
     322  
     323  static gchar *
     324  g_inet_socket_address_connectable_to_string (GSocketConnectable *connectable)
     325  {
     326    GInetSocketAddress *sa;
     327    GInetAddress *a;
     328    gchar *a_string;
     329    GString *out;
     330    guint16 port;
     331  
     332    sa = G_INET_SOCKET_ADDRESS (connectable);
     333    a = g_inet_socket_address_get_address (sa);
     334    out = g_string_new ("");
     335  
     336    /* Address. */
     337    a_string = g_inet_address_to_string (a);
     338    g_string_append (out, a_string);
     339    g_free (a_string);
     340  
     341    /* Scope ID (IPv6 only). */
     342    if (g_inet_address_get_family (a) == G_SOCKET_FAMILY_IPV6 &&
     343        g_inet_socket_address_get_scope_id (sa) != 0)
     344      {
     345        g_string_append_printf (out, "%%%u",
     346                                g_inet_socket_address_get_scope_id (sa));
     347      }
     348  
     349    /* Port. */
     350    port = g_inet_socket_address_get_port (sa);
     351    if (port != 0)
     352      {
     353        /* Disambiguate ports from IPv6 addresses using square brackets. */
     354        if (g_inet_address_get_family (a) == G_SOCKET_FAMILY_IPV6)
     355          {
     356            g_string_prepend (out, "[");
     357            g_string_append (out, "]");
     358          }
     359  
     360        g_string_append_printf (out, ":%u", port);
     361      }
     362  
     363    return g_string_free (out, FALSE);
     364  }
     365  
     366  static void
     367  g_inet_socket_address_init (GInetSocketAddress *address)
     368  {
     369    address->priv = g_inet_socket_address_get_instance_private (address);
     370  }
     371  
     372  /**
     373   * g_inet_socket_address_new:
     374   * @address: a #GInetAddress
     375   * @port: a port number
     376   *
     377   * Creates a new #GInetSocketAddress for @address and @port.
     378   *
     379   * Returns: a new #GInetSocketAddress
     380   *
     381   * Since: 2.22
     382   */
     383  GSocketAddress *
     384  g_inet_socket_address_new (GInetAddress *address,
     385                             guint16       port)
     386  {
     387    return g_object_new (G_TYPE_INET_SOCKET_ADDRESS,
     388  		       "address", address,
     389  		       "port", port,
     390  		       NULL);
     391  }
     392  
     393  /**
     394   * g_inet_socket_address_new_from_string:
     395   * @address: the string form of an IP address
     396   * @port: a port number
     397   *
     398   * Creates a new #GInetSocketAddress for @address and @port.
     399   *
     400   * If @address is an IPv6 address, it can also contain a scope ID
     401   * (separated from the address by a `%`).
     402   *
     403   * Returns: (nullable) (transfer full): a new #GInetSocketAddress,
     404   * or %NULL if @address cannot be parsed.
     405   *
     406   * Since: 2.40
     407   */
     408  GSocketAddress *
     409  g_inet_socket_address_new_from_string (const char *address,
     410                                         guint       port)
     411  {
     412    static struct addrinfo *hints, hints_struct;
     413    GSocketAddress *saddr;
     414    GInetAddress *iaddr;
     415    struct addrinfo *res;
     416    gint status;
     417  
     418    if (strchr (address, ':'))
     419      {
     420        /* IPv6 address (or it's invalid). We use getaddrinfo() because
     421         * it will handle parsing a scope_id as well.
     422         */
     423  
     424        if (G_UNLIKELY (g_once_init_enter_pointer (&hints)))
     425          {
     426            hints_struct.ai_family = AF_UNSPEC;
     427            hints_struct.ai_socktype = SOCK_STREAM;
     428            hints_struct.ai_protocol = 0;
     429            hints_struct.ai_flags = AI_NUMERICHOST;
     430            g_once_init_leave_pointer (&hints, &hints_struct);
     431          }
     432  
     433        status = getaddrinfo (address, NULL, hints, &res);
     434        if (status != 0)
     435          return NULL;
     436  
     437        if (res->ai_family == AF_INET6 &&
     438            res->ai_addrlen == sizeof (struct sockaddr_in6))
     439          {
     440            ((struct sockaddr_in6 *)res->ai_addr)->sin6_port = g_htons (port);
     441            saddr = g_socket_address_new_from_native (res->ai_addr, res->ai_addrlen);
     442          }
     443        else
     444          saddr = NULL;
     445  
     446        freeaddrinfo (res);
     447      }
     448    else
     449      {
     450        /* IPv4 (or invalid). We don't want to use getaddrinfo() here,
     451         * because it accepts the stupid "IPv4 numbers-and-dots
     452         * notation" addresses that are never used for anything except
     453         * phishing. Since we don't have to worry about scope IDs for
     454         * IPv4, we can just use g_inet_address_new_from_string().
     455         */
     456        iaddr = g_inet_address_new_from_string (address);
     457        if (!iaddr)
     458          return NULL;
     459  
     460        g_warn_if_fail (g_inet_address_get_family (iaddr) == G_SOCKET_FAMILY_IPV4);
     461  
     462        saddr = g_inet_socket_address_new (iaddr, port);
     463        g_object_unref (iaddr);
     464      }
     465  
     466    return saddr;
     467  }
     468  
     469  /**
     470   * g_inet_socket_address_get_address:
     471   * @address: a #GInetSocketAddress
     472   *
     473   * Gets @address's #GInetAddress.
     474   *
     475   * Returns: (transfer none): the #GInetAddress for @address, which must be
     476   * g_object_ref()'d if it will be stored
     477   *
     478   * Since: 2.22
     479   */
     480  GInetAddress *
     481  g_inet_socket_address_get_address (GInetSocketAddress *address)
     482  {
     483    g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), NULL);
     484  
     485    return address->priv->address;
     486  }
     487  
     488  /**
     489   * g_inet_socket_address_get_port:
     490   * @address: a #GInetSocketAddress
     491   *
     492   * Gets @address's port.
     493   *
     494   * Returns: the port for @address
     495   *
     496   * Since: 2.22
     497   */
     498  guint16
     499  g_inet_socket_address_get_port (GInetSocketAddress *address)
     500  {
     501    g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), 0);
     502  
     503    return address->priv->port;
     504  }
     505  
     506  
     507  /**
     508   * g_inet_socket_address_get_flowinfo:
     509   * @address: a %G_SOCKET_FAMILY_IPV6 #GInetSocketAddress
     510   *
     511   * Gets the `sin6_flowinfo` field from @address,
     512   * which must be an IPv6 address.
     513   *
     514   * Returns: the flowinfo field
     515   *
     516   * Since: 2.32
     517   */
     518  guint32
     519  g_inet_socket_address_get_flowinfo (GInetSocketAddress *address)
     520  {
     521    g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), 0);
     522    g_return_val_if_fail (g_inet_address_get_family (address->priv->address) == G_SOCKET_FAMILY_IPV6, 0);
     523  
     524    return address->priv->flowinfo;
     525  }
     526  
     527  /**
     528   * g_inet_socket_address_get_scope_id:
     529   * @address: a %G_SOCKET_FAMILY_IPV6 #GInetAddress
     530   *
     531   * Gets the `sin6_scope_id` field from @address,
     532   * which must be an IPv6 address.
     533   *
     534   * Returns: the scope id field
     535   *
     536   * Since: 2.32
     537   */
     538  guint32
     539  g_inet_socket_address_get_scope_id (GInetSocketAddress *address)
     540  {
     541    g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), 0);
     542    g_return_val_if_fail (g_inet_address_get_family (address->priv->address) == G_SOCKET_FAMILY_IPV6, 0);
     543  
     544    return address->priv->scope_id;
     545  }