(root)/
glib-2.79.0/
gio/
gnetworkmonitornetlink.c
       1  /* GIO - GLib Input, Output and Streaming Library
       2   *
       3   * Copyright 2011 Red Hat, Inc.
       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  
      21  #include "config.h"
      22  
      23  #include <errno.h>
      24  #include <string.h>
      25  #include <unistd.h>
      26  
      27  #include "gnetworkmonitornetlink.h"
      28  #include "gcredentials.h"
      29  #include "ginetaddressmask.h"
      30  #include "ginitable.h"
      31  #include "giomodule-priv.h"
      32  #include "glibintl.h"
      33  #include "glib/gstdio.h"
      34  #include "gnetworkingprivate.h"
      35  #include "gnetworkmonitor.h"
      36  #include "gsocket.h"
      37  #include "gunixcredentialsmessage.h"
      38  
      39  /* must come at the end to pick system includes from
      40   * gnetworkingprivate.h */
      41  #include <linux/netlink.h>
      42  #include <linux/rtnetlink.h>
      43  
      44  static GInitableIface *initable_parent_iface;
      45  static void g_network_monitor_netlink_iface_init (GNetworkMonitorInterface *iface);
      46  static void g_network_monitor_netlink_initable_iface_init (GInitableIface *iface);
      47  
      48  struct _GNetworkMonitorNetlinkPrivate
      49  {
      50    GSocket *sock;
      51    GSource *source, *dump_source;
      52    GMainContext *context;
      53  
      54    GPtrArray *dump_networks;
      55  };
      56  
      57  static gboolean read_netlink_messages (GNetworkMonitorNetlink  *nl,
      58                                         GError                 **error);
      59  static gboolean read_netlink_messages_callback (GSocket             *socket,
      60                                                  GIOCondition         condition,
      61                                                  gpointer             user_data);
      62  static gboolean request_dump (GNetworkMonitorNetlink  *nl,
      63                                GError                 **error);
      64  
      65  #define g_network_monitor_netlink_get_type _g_network_monitor_netlink_get_type
      66  G_DEFINE_TYPE_WITH_CODE (GNetworkMonitorNetlink, g_network_monitor_netlink, G_TYPE_NETWORK_MONITOR_BASE,
      67                           G_ADD_PRIVATE (GNetworkMonitorNetlink)
      68                           G_IMPLEMENT_INTERFACE (G_TYPE_NETWORK_MONITOR,
      69                                                  g_network_monitor_netlink_iface_init)
      70                           G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
      71                                                  g_network_monitor_netlink_initable_iface_init)
      72                           _g_io_modules_ensure_extension_points_registered ();
      73                           g_io_extension_point_implement (G_NETWORK_MONITOR_EXTENSION_POINT_NAME,
      74                                                           g_define_type_id,
      75                                                           "netlink",
      76                                                           20))
      77  
      78  static void
      79  g_network_monitor_netlink_init (GNetworkMonitorNetlink *nl)
      80  {
      81    nl->priv = g_network_monitor_netlink_get_instance_private (nl);
      82  }
      83  
      84  static gboolean
      85  g_network_monitor_netlink_initable_init (GInitable     *initable,
      86                                           GCancellable  *cancellable,
      87                                           GError       **error)
      88  {
      89    GNetworkMonitorNetlink *nl = G_NETWORK_MONITOR_NETLINK (initable);
      90    gint sockfd;
      91    struct sockaddr_nl snl;
      92  
      93    /* We create the socket the old-school way because sockaddr_netlink
      94     * can't be represented as a GSocketAddress
      95     */
      96    sockfd = g_socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE, NULL);
      97    if (sockfd == -1)
      98      {
      99        int errsv = errno;
     100        g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
     101                     _("Could not create network monitor: %s"),
     102                     g_strerror (errsv));
     103        return FALSE;
     104      }
     105  
     106    snl.nl_family = AF_NETLINK;
     107    snl.nl_pid = snl.nl_pad = 0;
     108    snl.nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE;
     109    if (bind (sockfd, (struct sockaddr *)&snl, sizeof (snl)) != 0)
     110      {
     111        int errsv = errno;
     112        g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
     113                     _("Could not create network monitor: %s"),
     114                     g_strerror (errsv));
     115        (void) g_close (sockfd, NULL);
     116        return FALSE;
     117      }
     118  
     119    nl->priv->sock = g_socket_new_from_fd (sockfd, error);
     120    if (!nl->priv->sock)
     121      {
     122        g_prefix_error (error, "%s", _("Could not create network monitor: "));
     123        (void) g_close (sockfd, NULL);
     124        return FALSE;
     125      }
     126  
     127    if (!g_socket_set_option (nl->priv->sock, SOL_SOCKET, SO_PASSCRED,
     128  			    TRUE, NULL))
     129      {
     130        int errsv = errno;
     131        g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
     132                     _("Could not create network monitor: %s"),
     133                     g_strerror (errsv));
     134        return FALSE;
     135      }
     136  
     137    /* Request the current state */
     138    if (!request_dump (nl, error))
     139      return FALSE;
     140  
     141    /* And read responses; since we haven't yet marked the socket
     142     * non-blocking, each call will block until a message is received.
     143     */
     144    while (nl->priv->dump_networks)
     145      {
     146        GError *local_error = NULL;
     147        if (!read_netlink_messages (nl, &local_error))
     148          {
     149            g_warning ("%s", local_error->message);
     150            g_clear_error (&local_error);
     151            break;
     152          }
     153      }
     154  
     155    g_socket_set_blocking (nl->priv->sock, FALSE);
     156    nl->priv->context = g_main_context_ref_thread_default ();
     157    nl->priv->source = g_socket_create_source (nl->priv->sock, G_IO_IN, NULL);
     158    g_source_set_callback (nl->priv->source,
     159                           (GSourceFunc) read_netlink_messages_callback, nl, NULL);
     160    g_source_attach (nl->priv->source, nl->priv->context);
     161  
     162    return initable_parent_iface->init (initable, cancellable, error);
     163  }
     164  
     165  static gboolean
     166  request_dump (GNetworkMonitorNetlink  *nl,
     167                GError                 **error)
     168  {
     169    struct nlmsghdr *n;
     170    struct rtgenmsg *gen;
     171    gchar buf[NLMSG_SPACE (sizeof (*gen))];
     172  
     173    memset (buf, 0, sizeof (buf));
     174    n = (struct nlmsghdr*) buf;
     175    n->nlmsg_len = NLMSG_LENGTH (sizeof (*gen));
     176    n->nlmsg_type = RTM_GETROUTE;
     177    n->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
     178    n->nlmsg_pid = 0;
     179    gen = NLMSG_DATA (n);
     180    gen->rtgen_family = AF_UNSPEC;
     181  
     182    if (g_socket_send (nl->priv->sock, buf, sizeof (buf),
     183                       NULL, error) < 0)
     184      {
     185        g_prefix_error (error, "%s", _("Could not get network status: "));
     186        return FALSE;
     187      }
     188  
     189    nl->priv->dump_networks = g_ptr_array_new_with_free_func (g_object_unref);
     190    return TRUE;
     191  }
     192  
     193  static gboolean
     194  timeout_request_dump (gpointer user_data)
     195  {
     196    GNetworkMonitorNetlink *nl = user_data;
     197  
     198    g_source_destroy (nl->priv->dump_source);
     199    g_source_unref (nl->priv->dump_source);
     200    nl->priv->dump_source = NULL;
     201  
     202    request_dump (nl, NULL);
     203  
     204    return FALSE;
     205  }
     206  
     207  static void
     208  queue_request_dump (GNetworkMonitorNetlink *nl)
     209  {
     210    if (nl->priv->dump_networks)
     211      return;
     212  
     213    if (nl->priv->dump_source)
     214      {
     215        g_source_destroy (nl->priv->dump_source);
     216        g_source_unref (nl->priv->dump_source);
     217      }
     218  
     219    nl->priv->dump_source = g_timeout_source_new_seconds (1);
     220    g_source_set_callback (nl->priv->dump_source,
     221                           (GSourceFunc) timeout_request_dump, nl, NULL);
     222    g_source_attach (nl->priv->dump_source, nl->priv->context);
     223  }
     224  
     225  static GInetAddressMask *
     226  create_inet_address_mask (GSocketFamily  family,
     227                            const guint8  *dest,
     228                            gsize          dest_len)
     229  {
     230    GInetAddress *dest_addr;
     231    GInetAddressMask *network;
     232  
     233    if (dest)
     234      dest_addr = g_inet_address_new_from_bytes (dest, family);
     235    else
     236      dest_addr = g_inet_address_new_any (family);
     237    network = g_inet_address_mask_new (dest_addr, dest_len, NULL);
     238    g_object_unref (dest_addr);
     239  
     240    return network;
     241  }
     242  
     243  static void
     244  add_network (GNetworkMonitorNetlink *nl,
     245               GSocketFamily           family,
     246               const guint8           *dest,
     247               gsize                   dest_len)
     248  {
     249    GInetAddressMask *network = create_inet_address_mask (family, dest, dest_len);
     250    g_return_if_fail (network != NULL);
     251  
     252    if (nl->priv->dump_networks)
     253      g_ptr_array_add (nl->priv->dump_networks, g_object_ref (network));
     254    else
     255      g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (nl), network);
     256  
     257    g_object_unref (network);
     258  }
     259  
     260  static void
     261  remove_network (GNetworkMonitorNetlink *nl,
     262                  GSocketFamily           family,
     263                  const guint8           *dest,
     264                  gsize                   dest_len)
     265  {
     266    GInetAddressMask *network = create_inet_address_mask (family, dest, dest_len);
     267    g_return_if_fail (network != NULL);
     268  
     269    if (nl->priv->dump_networks)
     270      {
     271        GInetAddressMask **dump_networks = (GInetAddressMask **)nl->priv->dump_networks->pdata;
     272        guint i;
     273  
     274        for (i = 0; i < nl->priv->dump_networks->len; i++)
     275          {
     276            if (g_inet_address_mask_equal (network, dump_networks[i]))
     277              g_ptr_array_remove_index_fast (nl->priv->dump_networks, i--);
     278          }
     279      }
     280    else
     281      {
     282        g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (nl), network);
     283      }
     284  
     285    g_object_unref (network);
     286  }
     287  
     288  static void
     289  finish_dump (GNetworkMonitorNetlink *nl)
     290  {
     291    g_network_monitor_base_set_networks (G_NETWORK_MONITOR_BASE (nl),
     292                                         (GInetAddressMask **)nl->priv->dump_networks->pdata,
     293                                         nl->priv->dump_networks->len);
     294    g_ptr_array_free (nl->priv->dump_networks, TRUE);
     295    nl->priv->dump_networks = NULL;
     296  }
     297  
     298  static gboolean
     299  read_netlink_messages (GNetworkMonitorNetlink  *nl,
     300                         GError                 **error)
     301  {
     302    GInputVector iv;
     303    gssize len;
     304    gint flags;
     305    GError *local_error = NULL;
     306    GSocketAddress *addr = NULL;
     307    struct nlmsghdr *msg;
     308    struct rtmsg *rtmsg;
     309    struct rtattr *attr;
     310    struct sockaddr_nl source_sockaddr;
     311    gsize attrlen;
     312    guint8 *dest, *gateway, *oif;
     313    gboolean retval = TRUE;
     314  
     315    iv.buffer = NULL;
     316    iv.size = 0;
     317  
     318    flags = MSG_PEEK | MSG_TRUNC;
     319    len = g_socket_receive_message (nl->priv->sock, NULL, &iv, 1,
     320                                    NULL, NULL, &flags, NULL, &local_error);
     321    if (len < 0)
     322      {
     323        retval = FALSE;
     324        goto done;
     325      }
     326  
     327    iv.buffer = g_malloc (len);
     328    iv.size = len;
     329    len = g_socket_receive_message (nl->priv->sock, &addr, &iv, 1,
     330                                    NULL, NULL, NULL, NULL, &local_error);
     331    if (len < 0)
     332      {
     333        retval = FALSE;
     334        goto done;
     335      }
     336  
     337    if (!g_socket_address_to_native (addr, &source_sockaddr, sizeof (source_sockaddr), &local_error))
     338      {
     339        retval = FALSE;
     340        goto done;
     341      }
     342  
     343    /* If the sender port id is 0 (not fakeable) then the message is from the kernel */
     344    if (source_sockaddr.nl_pid != 0)
     345      goto done;
     346  
     347    msg = (struct nlmsghdr *) iv.buffer;
     348    for (; len > 0; msg = NLMSG_NEXT (msg, len))
     349      {
     350        if (!NLMSG_OK (msg, (size_t) len))
     351          {
     352            g_set_error_literal (&local_error,
     353                                 G_IO_ERROR,
     354                                 G_IO_ERROR_PARTIAL_INPUT,
     355                                 "netlink message was truncated; shouldn't happen...");
     356            retval = FALSE;
     357            goto done;
     358          }
     359  
     360        switch (msg->nlmsg_type)
     361          {
     362          case RTM_NEWROUTE:
     363          case RTM_DELROUTE:
     364            rtmsg = NLMSG_DATA (msg);
     365  
     366            if (rtmsg->rtm_family != AF_INET && rtmsg->rtm_family != AF_INET6)
     367              continue;
     368            if (rtmsg->rtm_type == RTN_UNREACHABLE)
     369              continue;
     370  
     371            attrlen = NLMSG_PAYLOAD (msg, sizeof (struct rtmsg));
     372            attr = RTM_RTA (rtmsg);
     373            dest = gateway = oif = NULL;
     374            while (RTA_OK (attr, attrlen))
     375              {
     376                if (attr->rta_type == RTA_DST)
     377                  dest = RTA_DATA (attr);
     378                else if (attr->rta_type == RTA_GATEWAY)
     379                  gateway = RTA_DATA (attr);
     380                else if (attr->rta_type == RTA_OIF)
     381                  oif = RTA_DATA (attr);
     382                attr = RTA_NEXT (attr, attrlen);
     383              }
     384  
     385            if (dest || gateway || oif)
     386              {
     387                /* Unless we're processing the results of a dump, ignore
     388                 * IPv6 link-local multicast routes, which are added and
     389                 * removed all the time for some reason.
     390                 */
     391  #define UNALIGNED_IN6_IS_ADDR_MC_LINKLOCAL(a)           \
     392                ((a[0] == 0xff) && ((a[1] & 0xf) == 0x2))
     393  
     394                if (!nl->priv->dump_networks &&
     395                    rtmsg->rtm_family == AF_INET6 &&
     396                    rtmsg->rtm_dst_len != 0 &&
     397                    (dest && UNALIGNED_IN6_IS_ADDR_MC_LINKLOCAL (dest)))
     398                  continue;
     399  
     400                if (msg->nlmsg_type == RTM_NEWROUTE)
     401                  add_network (nl, rtmsg->rtm_family, dest, rtmsg->rtm_dst_len);
     402                else
     403                  remove_network (nl, rtmsg->rtm_family, dest, rtmsg->rtm_dst_len);
     404                queue_request_dump (nl);
     405              }
     406            break;
     407  
     408          case NLMSG_DONE:
     409            finish_dump (nl);
     410            goto done;
     411  
     412          case NLMSG_ERROR:
     413            {
     414              struct nlmsgerr *e = NLMSG_DATA (msg);
     415  
     416              g_set_error (&local_error,
     417                           G_IO_ERROR,
     418                           g_io_error_from_errno (-e->error),
     419                           "netlink error: %s",
     420                           g_strerror (-e->error));
     421            }
     422            retval = FALSE;
     423            goto done;
     424  
     425          default:
     426            g_set_error (&local_error,
     427                         G_IO_ERROR,
     428                         G_IO_ERROR_INVALID_DATA,
     429                         "unexpected netlink message %d",
     430                         msg->nlmsg_type);
     431            retval = FALSE;
     432            goto done;
     433          }
     434      }
     435  
     436   done:
     437    g_free (iv.buffer);
     438    g_clear_object (&addr);
     439  
     440    if (!retval && nl->priv->dump_networks)
     441      finish_dump (nl);
     442  
     443    if (local_error)
     444      g_propagate_prefixed_error (error, local_error, "Error on netlink socket: ");
     445  
     446    return retval;
     447  }
     448  
     449  static void
     450  g_network_monitor_netlink_finalize (GObject *object)
     451  {
     452    GNetworkMonitorNetlink *nl = G_NETWORK_MONITOR_NETLINK (object);
     453  
     454    if (nl->priv->source)
     455      {
     456        g_source_destroy (nl->priv->source);
     457        g_source_unref (nl->priv->source);
     458      }
     459  
     460    if (nl->priv->dump_source)
     461      {
     462        g_source_destroy (nl->priv->dump_source);
     463        g_source_unref (nl->priv->dump_source);
     464      }
     465  
     466    if (nl->priv->sock)
     467      {
     468        g_socket_close (nl->priv->sock, NULL);
     469        g_object_unref (nl->priv->sock);
     470      }
     471  
     472    g_clear_pointer (&nl->priv->context, g_main_context_unref);
     473    g_clear_pointer (&nl->priv->dump_networks, g_ptr_array_unref);
     474  
     475    G_OBJECT_CLASS (g_network_monitor_netlink_parent_class)->finalize (object);
     476  }
     477  
     478  static gboolean
     479  read_netlink_messages_callback (GSocket      *socket,
     480                                  GIOCondition  condition,
     481                                  gpointer      user_data)
     482  {
     483    GError *error = NULL;
     484    GNetworkMonitorNetlink *nl = G_NETWORK_MONITOR_NETLINK (user_data);
     485  
     486    if (!read_netlink_messages (nl, &error))
     487      {
     488        g_warning ("Error reading netlink message: %s", error->message);
     489        g_clear_error (&error);
     490        return FALSE;
     491      }
     492  
     493    return TRUE;
     494  }
     495  
     496  static void
     497  g_network_monitor_netlink_class_init (GNetworkMonitorNetlinkClass *nl_class)
     498  {
     499    GObjectClass *gobject_class = G_OBJECT_CLASS (nl_class);
     500  
     501    gobject_class->finalize = g_network_monitor_netlink_finalize;
     502  }
     503  
     504  static void
     505  g_network_monitor_netlink_iface_init (GNetworkMonitorInterface *monitor_iface)
     506  {
     507  }
     508  
     509  static void
     510  g_network_monitor_netlink_initable_iface_init (GInitableIface *iface)
     511  {
     512    initable_parent_iface = g_type_interface_peek_parent (iface);
     513  
     514    iface->init = g_network_monitor_netlink_initable_init;
     515  }