Coverage Report

Created: 2026-07-25 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/glib/gio/gnetworkmonitornetlink.c
Line
Count
Source
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
#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTLBYNAME)
27
#include <sys/sysctl.h>
28
#endif
29
30
#include "gnetworkmonitornetlink.h"
31
#include "gcredentials.h"
32
#include "ginetaddress.h"
33
#include "ginetaddressmask.h"
34
#include "ginetsocketaddress.h"
35
#include "ginitable.h"
36
#include "giomodule-priv.h"
37
#include "gioerror.h"
38
#include "glibintl.h"
39
#include "glib/gstdio.h"
40
#include "gnetworkingprivate.h"
41
#include "gnetworkmonitor.h"
42
#include "gsocket.h"
43
#include "gsocketaddressenumerator.h"
44
#include "gsocketconnectable.h"
45
#include "gtask.h"
46
#include "gunixcredentialsmessage.h"
47
48
/* must come at the end to pick system includes from
49
 * gnetworkingprivate.h */
50
#ifdef HAVE_LINUX_NETLINK_H
51
#include <linux/netlink.h>
52
#include <linux/rtnetlink.h>
53
/* <linux/netlink.h> defines NETLINK_GET_STRICT_CHK but not its setsockopt
54
 * level SOL_NETLINK. */
55
#ifndef SOL_NETLINK
56
#define SOL_NETLINK 270
57
#endif
58
#endif
59
#if defined(HAVE_NETLINK_NETLINK_H) && defined(HAVE_NETLINK_NETLINK_ROUTE_H)
60
#include <netlink/netlink.h>
61
#include <netlink/netlink_route.h>
62
#endif
63
64
/* GNetworkMonitorNetlink is the default GNetworkMonitor on Linux when neither
65
 * NetworkManager nor systemd-networkd is in charge.
66
 *
67
 * The kernel routing table (FIB) can be enormous on routers and network-facing
68
 * servers (millions of routes), so this backend must never mirror or re-dump the
69
 * whole table. It deliberately ignores non-default routes:
70
 *
71
 *  - network-available is derived only from default routes. A single streaming
72
 *    dump at construction records just the default routes (every route with
73
 *    rtm_dst_len != 0 is skipped), and the set is then maintained incrementally
74
 *    from RTM_NEWROUTE/RTM_DELROUTE deltas. The table is re-dumped only to resync
75
 *    after an ENOBUFS overflow.
76
 *
77
 *  - can_reach() uses an on-demand per-destination RTM_GETROUTE lookup (the
78
 *    "ip route get" primitive), which is O(prefix length) and independent of the
79
 *    table size.
80
 *
81
 * If you change this code, keep it that way: never enumerate or cache the full
82
 * FIB. */
83
84
static GInitableIface *initable_parent_iface;
85
static void g_network_monitor_netlink_iface_init (GNetworkMonitorInterface *iface);
86
static void g_network_monitor_netlink_initable_iface_init (GInitableIface *iface);
87
88
struct _GNetworkMonitorNetlinkPrivate
89
{
90
  GSocket *query_sock;  /* (mutex query_lock) */
91
  guint    query_seq;  /* (mutex query_lock) */
92
  GMutex   query_lock;
93
94
  GMainContext *context;
95
96
  /* Availability tracking from the kernel routing table. These members are set
97
   * up only by setup_monitor(), which runs solely for the plain
98
   * GNetworkMonitorNetlink type. Subclasses (NetworkManager, systemd) source
99
   * availability elsewhere (e.g. D-Bus) and inherit only can_reach(), so for
100
   * them these stay NULL/empty: any code touching them must handle that. */
101
  GSocket *monitor_sock;  /* (nullable) */
102
  GSource *source;  /* (nullable) */
103
  GSource *dump_source;  /* (nullable) */
104
  gboolean dumping;
105
  GHashTable *ipv4_defaults;  /* (element-type utf8) (owned) (nullable) */
106
  GHashTable *ipv6_defaults;  /* (element-type utf8) (owned) (nullable) */
107
  GHashTable *dump_ipv4_defaults;  /* (element-type utf8) (owned) (nullable) */
108
  GHashTable *dump_ipv6_defaults;  /* (element-type utf8) (owned) (nullable) */
109
  GInetAddressMask *ipv4_default_mask;  /* (nullable) */
110
  GInetAddressMask *ipv6_default_mask;  /* (nullable) */
111
};
112
113
static gboolean read_netlink_messages (GNetworkMonitorNetlink  *nl,
114
                                       GError                 **error);
115
static gboolean read_netlink_messages_callback (GSocket             *socket,
116
                                                GIOCondition         condition,
117
                                                gpointer             user_data);
118
static gboolean request_dump (GNetworkMonitorNetlink  *nl,
119
                              GError                 **error);
120
121
#define g_network_monitor_netlink_get_type _g_network_monitor_netlink_get_type
122
0
G_DEFINE_TYPE_WITH_CODE (GNetworkMonitorNetlink, g_network_monitor_netlink, G_TYPE_NETWORK_MONITOR_BASE,
123
0
                         G_ADD_PRIVATE (GNetworkMonitorNetlink)
124
0
                         G_IMPLEMENT_INTERFACE (G_TYPE_NETWORK_MONITOR,
125
0
                                                g_network_monitor_netlink_iface_init)
126
0
                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
127
0
                                                g_network_monitor_netlink_initable_iface_init)
128
0
                         _g_io_modules_ensure_extension_points_registered ();
129
0
                         g_io_extension_point_implement (G_NETWORK_MONITOR_EXTENSION_POINT_NAME,
130
0
                                                         g_define_type_id,
131
0
                                                         "netlink",
132
0
                                                         20))
133
0
134
0
static void
135
0
g_network_monitor_netlink_init (GNetworkMonitorNetlink *nl)
136
0
{
137
0
  nl->priv = g_network_monitor_netlink_get_instance_private (nl);
138
0
}
139
140
/* Create a NETLINK_ROUTE socket bound to the given multicast groups (0 for a
141
 * request/response socket that is not interested in unsolicited events). */
142
static GSocket *
143
create_netlink_socket (guint32   groups,
144
                       GError  **error)
145
0
{
146
0
  gint sockfd;
147
0
  struct sockaddr_nl snl;
148
0
  GSocket *sock;
149
0
  const int rcvbuf = 1024 * 1024;
150
151
  /* We create the socket the old-school way because sockaddr_netlink
152
   * can't be represented as a GSocketAddress
153
   */
154
0
  sockfd = g_socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE, NULL);
155
0
  if (sockfd == -1)
156
0
    {
157
0
      int errsv = errno;
158
0
      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
159
0
                   _("Could not create network monitor: %s"),
160
0
                   g_strerror (errsv));
161
0
      return NULL;
162
0
    }
163
164
  /* A host running dynamic routing protocols such as BGP can generate many
165
   * route events in a short time; a larger buffer reduces ENOBUFS overflows
166
   * that force running the full route enumeration again. */
167
0
  if (setsockopt (sockfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof (rcvbuf)) != 0)
168
0
    g_debug ("Could not enlarge netlink receive buffer: %s", g_strerror (errno));
169
170
0
  snl.nl_family = AF_NETLINK;
171
0
  snl.nl_pid = snl.nl_pad = 0;
172
0
  snl.nl_groups = groups;
173
0
  if (bind (sockfd, (struct sockaddr *)&snl, sizeof (snl)) != 0)
174
0
    {
175
0
      int errsv = errno;
176
0
      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
177
0
                   _("Could not create network monitor: %s"),
178
0
                   g_strerror (errsv));
179
0
      (void) g_close (sockfd, NULL);
180
0
      return NULL;
181
0
    }
182
183
0
  sock = g_socket_new_from_fd (sockfd, error);
184
0
  if (!sock)
185
0
    {
186
0
      g_prefix_error (error, "%s", _("Could not create network monitor: "));
187
0
      (void) g_close (sockfd, NULL);
188
0
      return NULL;
189
0
    }
190
191
0
  return sock;
192
0
}
193
194
static gboolean
195
setup_monitor (GNetworkMonitorNetlink  *nl,
196
               GError                 **error)
197
0
{
198
0
  nl->priv->monitor_sock = create_netlink_socket (RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE,
199
0
                                                  error);
200
0
  if (!nl->priv->monitor_sock)
201
0
    return FALSE;
202
203
0
#ifdef SO_PASSCRED
204
0
  if (!g_socket_set_option (nl->priv->monitor_sock, SOL_SOCKET, SO_PASSCRED,
205
0
                            TRUE, NULL))
206
0
    {
207
0
      int errsv = errno;
208
0
      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
209
0
                   _("Could not create network monitor: %s"),
210
0
                   g_strerror (errsv));
211
0
      return FALSE;
212
0
    }
213
0
#endif
214
215
0
  nl->priv->ipv4_defaults = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
216
0
  nl->priv->ipv6_defaults = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
217
218
  /* Request the current state to find existing default routes */
219
0
  if (!request_dump (nl, error))
220
0
    return FALSE;
221
222
  /* And read responses; since we haven't yet marked the socket
223
   * non-blocking, each call will block until a message is received.
224
   */
225
0
  while (nl->priv->dumping)
226
0
    {
227
0
      GError *local_error = NULL;
228
0
      if (!read_netlink_messages (nl, &local_error))
229
0
        {
230
0
          g_warning ("%s", local_error->message);
231
0
          g_clear_error (&local_error);
232
0
          break;
233
0
        }
234
0
    }
235
236
0
  g_socket_set_blocking (nl->priv->monitor_sock, FALSE);
237
0
  nl->priv->source = g_socket_create_source (nl->priv->monitor_sock, G_IO_IN, NULL);
238
0
  g_source_set_callback (nl->priv->source,
239
0
                         (GSourceFunc) read_netlink_messages_callback, nl, NULL);
240
0
  g_source_attach (nl->priv->source, nl->priv->context);
241
242
0
  return TRUE;
243
0
}
244
245
static gboolean
246
g_network_monitor_netlink_initable_init (GInitable     *initable,
247
                                         GCancellable  *cancellable,
248
                                         GError       **error)
249
0
{
250
0
  GNetworkMonitorNetlink *nl = G_NETWORK_MONITOR_NETLINK (initable);
251
252
0
  g_mutex_init (&nl->priv->query_lock);
253
0
  nl->priv->context = g_main_context_ref_thread_default ();
254
255
  /* A socket for on-demand per-destination route lookups, used by can_reach()
256
   * for this backend and every subclass. */
257
0
  nl->priv->query_sock = create_netlink_socket (0, error);
258
0
  if (!nl->priv->query_sock)
259
0
    return FALSE;
260
261
  /* Availability tracking is set up only for the plain netlink type; see the
262
   * GNetworkMonitorNetlinkPrivate definition. Subclasses inherit can_reach(). */
263
0
  if (G_OBJECT_TYPE (nl) == G_TYPE_NETWORK_MONITOR_NETLINK &&
264
0
      !setup_monitor (nl, error))
265
0
    return FALSE;
266
267
0
  return initable_parent_iface->init (initable, cancellable, error);
268
0
}
269
270
static gboolean
271
request_dump (GNetworkMonitorNetlink  *nl,
272
              GError                 **error)
273
0
{
274
0
  struct nlmsghdr *n;
275
0
  struct rtmsg *rtm;
276
0
  gchar buf[NLMSG_SPACE (sizeof (*rtm))];
277
278
0
#ifdef NETLINK_GET_STRICT_CHK
279
  /* Strict checking with rtm_flags == 0 lets the kernel dump faster by
280
   * skipping unnecessary data, e.g. the route-cache exceptions. */
281
0
  {
282
0
    const int strict = 1;
283
0
    if (setsockopt (g_socket_get_fd (nl->priv->monitor_sock), SOL_NETLINK,
284
0
                    NETLINK_GET_STRICT_CHK, &strict, sizeof (strict)) != 0)
285
0
      g_debug ("Could not set NETLINK_GET_STRICT_CHK: %s", g_strerror (errno));
286
0
  }
287
0
#endif
288
289
0
  memset (buf, 0, sizeof (buf));
290
0
  n = (struct nlmsghdr*) buf;
291
0
  n->nlmsg_len = NLMSG_LENGTH (sizeof (*rtm));
292
0
  n->nlmsg_type = RTM_GETROUTE;
293
0
  n->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
294
0
  n->nlmsg_pid = 0;
295
0
  rtm = NLMSG_DATA (n);
296
0
  rtm->rtm_family = AF_UNSPEC;
297
  /* Keep this request minimal: a strict dump requires the selector fields to
298
   * stay zero, and extra attributes can also hurt dump performance. */
299
300
0
  if (g_socket_send (nl->priv->monitor_sock, buf, sizeof (buf),
301
0
                     NULL, error) < 0)
302
0
    {
303
0
      g_prefix_error (error, "%s", _("Could not get network status: "));
304
0
      return FALSE;
305
0
    }
306
307
0
  nl->priv->dumping = TRUE;
308
0
  nl->priv->dump_ipv4_defaults = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
309
0
  nl->priv->dump_ipv6_defaults = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
310
0
  return TRUE;
311
0
}
312
313
static gboolean
314
timeout_request_dump (gpointer user_data)
315
0
{
316
0
  GNetworkMonitorNetlink *nl = user_data;
317
318
0
  g_source_destroy (nl->priv->dump_source);
319
0
  g_source_unref (nl->priv->dump_source);
320
0
  nl->priv->dump_source = NULL;
321
322
0
  request_dump (nl, NULL);
323
324
0
  return FALSE;
325
0
}
326
327
/* Schedule a full re-dump to rebuild default-route state after the monitor
328
 * socket overflows (ENOBUFS). Normal default-route changes are tracked
329
 * incrementally and do not trigger a dump. */
330
static void
331
queue_request_dump (GNetworkMonitorNetlink *nl)
332
0
{
333
0
  if (nl->priv->dumping)
334
0
    return;
335
336
0
  if (nl->priv->dump_source)
337
0
    {
338
0
      g_source_destroy (nl->priv->dump_source);
339
0
      g_source_unref (nl->priv->dump_source);
340
0
    }
341
342
0
  nl->priv->dump_source = g_timeout_source_new_seconds (1);
343
0
  g_source_set_callback (nl->priv->dump_source,
344
0
                         (GSourceFunc) timeout_request_dump, nl, NULL);
345
0
  g_source_attach (nl->priv->dump_source, nl->priv->context);
346
0
}
347
348
static GInetAddressMask *
349
default_route_mask (GNetworkMonitorNetlink *nl,
350
                    int                     family)
351
0
{
352
0
  GInetAddressMask **maskp;
353
0
  GSocketFamily socket_family;
354
355
0
  if (family == AF_INET)
356
0
    {
357
0
      maskp = &nl->priv->ipv4_default_mask;
358
0
      socket_family = G_SOCKET_FAMILY_IPV4;
359
0
    }
360
0
  else if (family == AF_INET6)
361
0
    {
362
0
      maskp = &nl->priv->ipv6_default_mask;
363
0
      socket_family = G_SOCKET_FAMILY_IPV6;
364
0
    }
365
0
  else
366
0
    {
367
0
      g_assert_not_reached ();
368
0
    }
369
370
0
  if (*maskp == NULL)
371
0
    {
372
0
      GInetAddress *any = g_inet_address_new_any (socket_family);
373
0
      *maskp = g_inet_address_mask_new (any, 0, NULL);
374
0
      g_object_unref (any);
375
0
    }
376
377
0
  return *maskp;
378
0
}
379
380
/* Reflect presence of a default route for @family into the base monitor's
381
 * network set, which drives the network-available property. */
382
static void
383
update_default_route_available (GNetworkMonitorNetlink *nl,
384
                                int                     family,
385
                                gboolean                available)
386
0
{
387
0
  GInetAddressMask *mask = default_route_mask (nl, family);
388
389
0
  if (mask == NULL)
390
0
    return;
391
392
0
  if (available)
393
0
    g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (nl), mask);
394
0
  else
395
0
    g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (nl), mask);
396
0
}
397
398
static void
399
add_default_route (GNetworkMonitorNetlink *nl,
400
                   int                     family,
401
                   gchar                  *stolen_key /* (transfer full) */)
402
0
{
403
0
  GHashTable *set;
404
405
0
  if (nl->priv->dumping)
406
0
    set = (family == AF_INET) ? nl->priv->dump_ipv4_defaults : nl->priv->dump_ipv6_defaults;
407
0
  else
408
0
    set = (family == AF_INET) ? nl->priv->ipv4_defaults : nl->priv->ipv6_defaults;
409
410
0
  if (!nl->priv->dumping && g_hash_table_size (set) == 0)
411
0
    update_default_route_available (nl, family, TRUE);
412
413
0
  g_hash_table_add (set, g_steal_pointer (&stolen_key));
414
0
}
415
416
static void
417
remove_default_route (GNetworkMonitorNetlink *nl,
418
                      int                     family,
419
                      const gchar            *key)
420
0
{
421
0
  GHashTable *set;
422
423
  /* An RTM_DELROUTE is always a multicast event and can interleave with a
424
   * (re-)dump, so this may run while dumping; update the live set, which
425
   * finish_dump() then reconciles against the freshly dumped set. */
426
0
  set = (family == AF_INET) ? nl->priv->ipv4_defaults : nl->priv->ipv6_defaults;
427
428
0
  if (g_hash_table_remove (set, key) &&
429
0
      g_hash_table_size (set) == 0)
430
0
    update_default_route_available (nl, family, FALSE);
431
0
}
432
433
static void
434
finish_dump (GNetworkMonitorNetlink *nl)
435
0
{
436
0
  int families[2] = { AF_INET, AF_INET6 };
437
0
  size_t i;
438
439
  /* Reconcile the freshly-dumped default routes with the live state, emitting
440
   * an availability change only when the per-family presence actually flips. */
441
0
  for (i = 0; i < G_N_ELEMENTS (families); i++)
442
0
    {
443
0
      int family = families[i];
444
0
      GHashTable **livep = (family == AF_INET) ? &nl->priv->ipv4_defaults : &nl->priv->ipv6_defaults;
445
0
      GHashTable **dumpp = (family == AF_INET) ? &nl->priv->dump_ipv4_defaults : &nl->priv->dump_ipv6_defaults;
446
0
      gboolean was_available = g_hash_table_size (*livep) > 0;
447
0
      gboolean now_available = g_hash_table_size (*dumpp) > 0;
448
449
0
      g_hash_table_unref (*livep);
450
0
      *livep = g_steal_pointer (dumpp);
451
452
0
      if (was_available != now_available)
453
0
        update_default_route_available (nl, family, now_available);
454
0
    }
455
456
0
  nl->priv->dumping = FALSE;
457
458
  /* FreeBSD features "jailing" functionality, which can be approximated to
459
   * Linux namespaces. A jail may or may not share the host's network stack,
460
   * which includes routing tables.
461
   * When jail runs in non-vnet mode and has a shared stack with the host,
462
   * the kernel prevents jailed processes from getting full view on a routing
463
   * table. This makes GNetworkManager believe that we're offline and return
464
   * FALSE for the "available" property.
465
   * To workaround this problem, do the same thing as GNetworkMonitorBase -
466
   * add a fake network of 0 length.
467
   */
468
#ifdef __FreeBSD__
469
  gboolean is_jailed = FALSE;
470
  gsize len = sizeof (is_jailed);
471
472
  if (sysctlbyname ("security.jail.jailed", &is_jailed, &len, NULL, 0) != 0)
473
    return;
474
475
  if (!is_jailed)
476
    return;
477
478
  if (is_jailed && !g_network_monitor_get_network_available (G_NETWORK_MONITOR (nl)))
479
    {
480
      GInetAddressMask *network;
481
      network = g_inet_address_mask_new_from_string ("0.0.0.0/0", NULL);
482
      g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (nl), network);
483
      g_object_unref (network);
484
    }
485
#endif
486
0
}
487
488
/* A route whose type does not actually deliver packets to the destination
489
 * (unreachable, blackhole, prohibit, throw) does not count as reachable. */
490
static gboolean
491
route_type_is_reachable (unsigned char rtm_type)
492
0
{
493
0
  return (rtm_type != RTN_UNREACHABLE &&
494
0
          rtm_type != RTN_BLACKHOLE &&
495
0
          rtm_type != RTN_PROHIBIT &&
496
0
          rtm_type != RTN_THROW);
497
0
}
498
499
/* Sane upper bound on a single netlink datagram before g_malloc(): a route-get
500
 * reply is one message (<= NLMSG_GOODSIZE, < 8 KiB), while a dump datagram packs
501
 * many messages and is hard-capped by the kernel at SKB_WITH_OVERHEAD(32768)
502
 * (~32 KiB, see netlink_recvmsg()). 64 KiB leaves headroom over both. */
503
0
#define NETLINK_MESSAGE_MAX_SIZE (64 * 1024)
504
505
static gboolean
506
read_netlink_messages (GNetworkMonitorNetlink  *nl,
507
                       GError                 **error)
508
0
{
509
0
  GInputVector iv;
510
0
  gssize len;
511
0
  gint flags;
512
0
  GError *local_error = NULL;
513
0
  GSocketAddress *addr = NULL;
514
0
  struct nlmsghdr *msg;
515
0
  struct rtmsg *rtmsg;
516
0
  struct rtattr *attr;
517
0
  struct sockaddr_nl source_sockaddr;
518
0
  gsize attrlen;
519
0
  guint32 table, metric, oif;
520
0
  gboolean have_nexthop;
521
522
  /* The kernel is aware of the read buffer size, so a larger buffer lets it
523
   * deliver more data per datagram. */
524
0
  iv.buffer = g_malloc (NETLINK_MESSAGE_MAX_SIZE);
525
0
  iv.size = NETLINK_MESSAGE_MAX_SIZE;
526
0
  flags = 0;
527
0
  len = g_socket_receive_message (nl->priv->monitor_sock, &addr, &iv, 1,
528
0
                                  NULL, NULL, &flags, NULL, &local_error);
529
0
  if (len < 0)
530
0
    goto done;
531
0
  if (len == 0 || (flags & MSG_TRUNC))
532
0
    {
533
0
      g_set_error_literal (&local_error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
534
0
                           "netlink message length is invalid");
535
0
      goto done;
536
0
    }
537
538
0
  if (!g_socket_address_to_native (addr, &source_sockaddr, sizeof (source_sockaddr), &local_error))
539
0
    goto done;
540
541
  /* If the sender port id is 0 (not fakeable) then the message is from the kernel */
542
0
  if (source_sockaddr.nl_pid != 0)
543
0
    goto done;
544
545
0
  msg = (struct nlmsghdr *) iv.buffer;
546
0
  for (; len > 0; msg = NLMSG_NEXT (msg, len))
547
0
    {
548
0
      if (!NLMSG_OK (msg, (size_t) len))
549
0
        {
550
0
          g_set_error_literal (&local_error,
551
0
                               G_IO_ERROR,
552
0
                               G_IO_ERROR_PARTIAL_INPUT,
553
0
                               "netlink message was truncated; shouldn't happen...");
554
0
          goto done;
555
0
        }
556
557
0
      switch (msg->nlmsg_type)
558
0
        {
559
0
        case RTM_NEWROUTE:
560
0
        case RTM_DELROUTE:
561
0
          rtmsg = NLMSG_DATA (msg);
562
563
0
          if (rtmsg->rtm_family != AF_INET && rtmsg->rtm_family != AF_INET6)
564
0
            continue;
565
          /* Only default routes (0-length prefix) affect network-available. */
566
0
          if (rtmsg->rtm_dst_len != 0)
567
0
            continue;
568
0
          if (!route_type_is_reachable (rtmsg->rtm_type))
569
0
            continue;
570
571
0
          table = rtmsg->rtm_table;
572
0
          metric = 0;
573
0
          oif = 0;
574
0
          have_nexthop = FALSE;
575
576
0
          attrlen = NLMSG_PAYLOAD (msg, sizeof (struct rtmsg));
577
0
          attr = RTM_RTA (rtmsg);
578
0
          while (RTA_OK (attr, attrlen))
579
0
            {
580
0
              if (attr->rta_type == RTA_GATEWAY)
581
0
                have_nexthop = TRUE;
582
0
              else if (attr->rta_type == RTA_OIF)
583
0
                {
584
0
                  oif = *(guint32 *) RTA_DATA (attr);
585
0
                  have_nexthop = TRUE;
586
0
                }
587
0
              else if (attr->rta_type == RTA_PRIORITY)
588
0
                metric = *(guint32 *) RTA_DATA (attr);
589
0
              else if (attr->rta_type == RTA_TABLE)
590
0
                table = *(guint32 *) RTA_DATA (attr);
591
0
              else if (attr->rta_type == RTA_MULTIPATH)
592
0
                have_nexthop = TRUE;
593
0
              attr = RTA_NEXT (attr, attrlen);
594
0
            }
595
596
          /* A default route reaches a nexthop: a gateway, an output interface,
597
           * or a set of multipath nexthops. */
598
0
          if (have_nexthop)
599
0
            {
600
              /* Key by attributes that survive "ip route replace" (which emits
601
               * RTM_NEWROUTE with no matching RTM_DELROUTE), so the set tracks
602
               * distinct default routes without drifting. */
603
0
              gchar *key = g_strdup_printf ("%u:%u:%u", table, metric, oif);
604
605
0
              if (msg->nlmsg_type == RTM_NEWROUTE)
606
0
                add_default_route (nl, rtmsg->rtm_family, g_steal_pointer (&key));
607
0
              else
608
0
                remove_default_route (nl, rtmsg->rtm_family, key);
609
0
              g_free (key);
610
0
            }
611
0
          break;
612
613
0
        case NLMSG_DONE:
614
0
          finish_dump (nl);
615
0
          goto done;
616
617
0
        case NLMSG_ERROR:
618
0
          {
619
0
            struct nlmsgerr *e = NLMSG_DATA (msg);
620
621
            /* ENOBUFS means the socket buffer overflowed and we may have missed
622
             * default-route changes; resync by re-dumping. */
623
0
            if (e->error == -ENOBUFS)
624
0
              {
625
0
                queue_request_dump (nl);
626
0
                goto done;
627
0
              }
628
629
0
            g_set_error (&local_error,
630
0
                         G_IO_ERROR,
631
0
                         g_io_error_from_errno (-e->error),
632
0
                         "netlink error: %s",
633
0
                         g_strerror (-e->error));
634
0
          }
635
0
          goto done;
636
637
0
        default:
638
0
          g_set_error (&local_error,
639
0
                       G_IO_ERROR,
640
0
                       G_IO_ERROR_INVALID_DATA,
641
0
                       "unexpected netlink message %d",
642
0
                       msg->nlmsg_type);
643
0
          goto done;
644
0
        }
645
0
    }
646
647
0
 done:
648
0
  g_free (iv.buffer);
649
0
  g_clear_object (&addr);
650
651
0
  if (local_error != NULL && nl->priv->dumping)
652
0
    finish_dump (nl);
653
654
0
  if (local_error != NULL)
655
0
    {
656
0
      g_propagate_prefixed_error (error, local_error, "Error on netlink socket: ");
657
0
      return FALSE;
658
0
    }
659
0
  else
660
0
    {
661
0
      return TRUE;
662
0
    }
663
0
}
664
665
static gboolean
666
read_netlink_messages_callback (GSocket      *socket,
667
                                GIOCondition  condition,
668
                                gpointer      user_data)
669
0
{
670
0
  GError *error = NULL;
671
0
  GNetworkMonitorNetlink *nl = G_NETWORK_MONITOR_NETLINK (user_data);
672
673
0
  if (!read_netlink_messages (nl, &error))
674
0
    {
675
0
      g_warning ("Error reading netlink message: %s", error->message);
676
0
      g_clear_error (&error);
677
0
      return FALSE;
678
0
    }
679
680
0
  return TRUE;
681
0
}
682
683
/* Map a GSocketFamily to its AF_* address family constant. */
684
static int
685
socket_family_to_af_family (GSocketFamily socket_family)
686
0
{
687
0
  switch (socket_family)
688
0
    {
689
0
    case G_SOCKET_FAMILY_IPV4:
690
0
      return AF_INET;
691
0
    case G_SOCKET_FAMILY_IPV6:
692
0
      return AF_INET6;
693
0
    default:
694
0
      g_assert_not_reached ();
695
0
    }
696
0
}
697
698
/* Map a kernel route-lookup errno to the GIOError reported by can_reach(). */
699
static GIOErrorEnum
700
route_get_error_from_errno (int err)
701
0
{
702
0
  switch (err)
703
0
    {
704
0
    case ENETUNREACH:
705
0
    case ENETDOWN:
706
0
      return G_IO_ERROR_NETWORK_UNREACHABLE;
707
0
    case EHOSTUNREACH:
708
0
    case EHOSTDOWN:
709
0
    case EACCES:
710
0
      return G_IO_ERROR_HOST_UNREACHABLE;
711
0
    default:
712
0
      return g_io_error_from_errno (err);
713
0
    }
714
0
}
715
716
/* Perform a single per-destination route lookup ("ip route get"). Returns TRUE
717
 * if @addr is reachable, otherwise FALSE with @error set. The error is usually
718
 * G_IO_ERROR_HOST_UNREACHABLE or G_IO_ERROR_NETWORK_UNREACHABLE, but any other
719
 * GIOError that route_get_error_from_errno() maps from the kernel's errno is
720
 * possible. Blocking, and safe to call from a worker thread. */
721
static gboolean
722
route_get (GNetworkMonitorNetlink  *nl,
723
           GInetAddress            *addr,
724
           GCancellable            *cancellable,
725
           GError                 **error)
726
0
{
727
0
  GSocketFamily socket_family = g_inet_address_get_family (addr);
728
0
  int family = socket_family_to_af_family (socket_family);
729
0
  gsize addrlen = g_inet_address_get_native_size (addr);
730
0
  const guint8 *addrbytes = g_inet_address_to_bytes (addr);
731
0
  struct {
732
0
    struct nlmsghdr n;
733
0
    struct rtmsg    r;
734
0
    gchar           buf[64];
735
0
  } req;
736
0
  struct nlmsghdr *msg;
737
0
  struct rtmsg *rtmsg;
738
0
  struct rtattr *rta;
739
0
  GInputVector iv = { NULL, 0 };
740
0
  struct sockaddr_nl source_sockaddr;
741
0
  GSocketAddress *src_addr = NULL;
742
0
  GError *local_error = NULL;
743
0
  gssize len;
744
0
  gint flags;
745
0
  guint seq;
746
0
  gboolean reachable = FALSE;
747
0
  gboolean got_reply = FALSE;
748
749
0
  memset (&req, 0, sizeof (req));
750
0
  req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
751
0
  req.n.nlmsg_type = RTM_GETROUTE;
752
0
  req.n.nlmsg_flags = NLM_F_REQUEST;
753
0
  req.r.rtm_family = family;
754
0
  req.r.rtm_dst_len = addrlen * 8;  /* this field is a CIDR length in bits */
755
756
  /* We want the kernel to resolve the route to @addr. RTM_F_FIB_MATCH
757
   * (Linux 4.11+) makes it return the matching FIB entry; without the flag the
758
   * kernel returns a per-destination cloned route instead, which still works
759
   * as we are currently interested in a route existence. */
760
0
#ifdef RTM_F_FIB_MATCH
761
0
  req.r.rtm_flags = RTM_F_FIB_MATCH;
762
0
#endif
763
764
0
  rta = (struct rtattr *) (((char *) &req) + NLMSG_ALIGN (req.n.nlmsg_len));
765
0
  rta->rta_type = RTA_DST;
766
0
  rta->rta_len = RTA_LENGTH (addrlen);
767
0
  g_assert ((char *) rta + rta->rta_len <= (char *) &req + sizeof (req));
768
0
  memcpy (RTA_DATA (rta), addrbytes, addrlen);
769
0
  req.n.nlmsg_len = NLMSG_ALIGN (req.n.nlmsg_len) + rta->rta_len;
770
771
0
  g_mutex_lock (&nl->priv->query_lock);
772
773
0
  seq = ++nl->priv->query_seq;
774
0
  req.n.nlmsg_seq = seq;
775
776
0
  if (g_socket_send (nl->priv->query_sock, (const gchar *) &req, req.n.nlmsg_len,
777
0
                     cancellable, &local_error) < 0)
778
0
    goto done;
779
780
0
  flags = MSG_PEEK | MSG_TRUNC;
781
0
  len = g_socket_receive_message (nl->priv->query_sock, NULL, &iv, 1,
782
0
                                  NULL, NULL, &flags, cancellable, &local_error);
783
0
  if (len < 0)
784
0
    goto done;
785
0
  if (len == 0 || len > NETLINK_MESSAGE_MAX_SIZE)
786
0
    {
787
0
      g_set_error_literal (&local_error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
788
0
                           "netlink route reply length is invalid");
789
0
      goto done;
790
0
    }
791
792
0
  iv.buffer = g_malloc (len);
793
0
  iv.size = len;
794
0
  len = g_socket_receive_message (nl->priv->query_sock, &src_addr, &iv, 1,
795
0
                                  NULL, NULL, NULL, cancellable, &local_error);
796
0
  if (len < 0)
797
0
    goto done;
798
799
  /* Only trust messages from the kernel (sender port id 0). */
800
0
  if (!g_socket_address_to_native (src_addr, &source_sockaddr, sizeof (source_sockaddr), &local_error))
801
0
    goto done;
802
0
  if (source_sockaddr.nl_pid != 0)
803
0
    goto done;
804
805
0
  msg = (struct nlmsghdr *) iv.buffer;
806
0
  for (; len > 0; msg = NLMSG_NEXT (msg, len))
807
0
    {
808
0
      if (!NLMSG_OK (msg, (size_t) len))
809
0
        break;
810
0
      if (msg->nlmsg_seq != seq)
811
0
        continue;
812
813
0
      if (msg->nlmsg_type == NLMSG_ERROR)
814
0
        {
815
0
          struct nlmsgerr *e = NLMSG_DATA (msg);
816
817
0
          got_reply = TRUE;
818
          /* error == 0 is a success acknowledgement, which the kernel never sends for our request. */
819
0
          if (e->error != 0)
820
0
            g_set_error_literal (&local_error, G_IO_ERROR,
821
0
                                 route_get_error_from_errno (-e->error),
822
0
                                 g_strerror (-e->error));
823
0
          break;
824
0
        }
825
0
      else if (msg->nlmsg_type == RTM_NEWROUTE)
826
0
        {
827
0
          rtmsg = NLMSG_DATA (msg);
828
0
          got_reply = TRUE;
829
0
          reachable = route_type_is_reachable (rtmsg->rtm_type);
830
0
          if (!reachable)
831
0
            g_set_error_literal (&local_error, G_IO_ERROR,
832
0
                                 G_IO_ERROR_HOST_UNREACHABLE,
833
0
                                 _("Host unreachable"));
834
0
          break;
835
0
        }
836
0
    }
837
838
0
 done:
839
0
  g_mutex_unlock (&nl->priv->query_lock);
840
841
0
  g_free (iv.buffer);
842
0
  g_clear_object (&src_addr);
843
844
0
  if (reachable)
845
0
    {
846
0
      g_assert (local_error == NULL);
847
0
      return TRUE;
848
0
    }
849
850
0
  if (local_error != NULL)
851
0
    g_propagate_error (error, g_steal_pointer (&local_error));
852
0
  else if (!got_reply)
853
0
    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_HOST_UNREACHABLE,
854
0
                         _("Host unreachable"));
855
0
  return FALSE;
856
0
}
857
858
static gboolean
859
g_network_monitor_netlink_can_reach (GNetworkMonitor     *monitor,
860
                                     GSocketConnectable  *connectable,
861
                                     GCancellable        *cancellable,
862
                                     GError             **error)
863
0
{
864
0
  GNetworkMonitorNetlink *nl = G_NETWORK_MONITOR_NETLINK (monitor);
865
0
  GSocketAddressEnumerator *enumerator;
866
0
  GSocketAddress *addr;
867
0
  GError *local_error = NULL;
868
869
0
  enumerator = g_socket_connectable_proxy_enumerate (connectable);
870
871
  /* Try each resolved address; the host is reachable if any of them is. A
872
   * failed route_get() is cleared so the next g_socket_address_enumerator_next()
873
   * sees a clean @local_error, except on cancellation, which we propagate. */
874
0
  while ((addr = g_socket_address_enumerator_next (enumerator, cancellable, &local_error)))
875
0
    {
876
0
      if (G_IS_INET_SOCKET_ADDRESS (addr))
877
0
        {
878
0
          GInetAddress *iaddr;
879
880
0
          iaddr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (addr));
881
0
          if (route_get (nl, iaddr, cancellable, &local_error))
882
0
            {
883
0
              g_object_unref (addr);
884
0
              g_object_unref (enumerator);
885
0
              return TRUE;
886
0
            }
887
888
0
          if (g_cancellable_is_cancelled (cancellable))
889
0
            {
890
0
              g_object_unref (addr);
891
0
              break;
892
0
            }
893
0
          g_clear_error (&local_error);
894
0
        }
895
896
0
      g_object_unref (addr);
897
0
    }
898
0
  g_object_unref (enumerator);
899
900
  /* An enumeration failure (DNS) or cancellation is reported as-is. */
901
0
  if (local_error != NULL)
902
0
    {
903
0
      g_propagate_error (error, g_steal_pointer (&local_error));
904
0
      return FALSE;
905
0
    }
906
907
  /* Reached when no address was routable (each route_get() error was cleared to
908
   * try the next one) or none were `GInetSocketAddress`es; either way report a
909
   * generic error, matching the base monitor. */
910
0
  g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_HOST_UNREACHABLE,
911
0
                       _("Host unreachable"));
912
0
  return FALSE;
913
0
}
914
915
static void
916
can_reach_thread (GTask        *task,
917
                  gpointer      source_object,
918
                  gpointer      task_data,
919
                  GCancellable *cancellable)
920
0
{
921
0
  GNetworkMonitor *monitor = G_NETWORK_MONITOR (source_object);
922
0
  GSocketConnectable *connectable = G_SOCKET_CONNECTABLE (task_data);
923
0
  GError *error = NULL;
924
925
0
  if (g_network_monitor_netlink_can_reach (monitor, connectable, cancellable, &error))
926
0
    g_task_return_boolean (task, TRUE);
927
0
  else
928
0
    g_task_return_error (task, g_steal_pointer (&error));
929
0
}
930
931
static void
932
g_network_monitor_netlink_can_reach_async (GNetworkMonitor     *monitor,
933
                                           GSocketConnectable  *connectable,
934
                                           GCancellable        *cancellable,
935
                                           GAsyncReadyCallback  callback,
936
                                           gpointer             user_data)
937
0
{
938
0
  GTask *task;
939
940
0
  task = g_task_new (monitor, cancellable, callback, user_data);
941
0
  g_task_set_source_tag (task, g_network_monitor_netlink_can_reach_async);
942
0
  g_task_set_static_name (task, "[gio] network monitor can_reach");
943
0
  g_task_set_task_data (task, g_object_ref (connectable), g_object_unref);
944
945
  /* A route lookup is a quick kernel round-trip, so the shared GTask thread
946
   * pool is fine here. */
947
0
  g_task_run_in_thread (task, can_reach_thread);
948
0
  g_object_unref (task);
949
0
}
950
951
static gboolean
952
g_network_monitor_netlink_can_reach_finish (GNetworkMonitor  *monitor,
953
                                            GAsyncResult     *result,
954
                                            GError          **error)
955
0
{
956
0
  g_return_val_if_fail (g_task_is_valid (result, monitor), FALSE);
957
958
0
  return g_task_propagate_boolean (G_TASK (result), error);
959
0
}
960
961
static void
962
g_network_monitor_netlink_finalize (GObject *object)
963
0
{
964
0
  GNetworkMonitorNetlink *nl = G_NETWORK_MONITOR_NETLINK (object);
965
966
0
  if (nl->priv->source)
967
0
    {
968
0
      g_source_destroy (nl->priv->source);
969
0
      g_source_unref (nl->priv->source);
970
0
    }
971
972
0
  if (nl->priv->dump_source)
973
0
    {
974
0
      g_source_destroy (nl->priv->dump_source);
975
0
      g_source_unref (nl->priv->dump_source);
976
0
    }
977
978
0
  if (nl->priv->query_sock)
979
0
    {
980
0
      g_socket_close (nl->priv->query_sock, NULL);
981
0
      g_object_unref (nl->priv->query_sock);
982
0
    }
983
984
0
  if (nl->priv->monitor_sock)
985
0
    {
986
0
      g_socket_close (nl->priv->monitor_sock, NULL);
987
0
      g_object_unref (nl->priv->monitor_sock);
988
0
    }
989
990
0
  g_mutex_clear (&nl->priv->query_lock);
991
992
0
  g_clear_pointer (&nl->priv->context, g_main_context_unref);
993
0
  g_clear_pointer (&nl->priv->ipv4_defaults, g_hash_table_unref);
994
0
  g_clear_pointer (&nl->priv->ipv6_defaults, g_hash_table_unref);
995
0
  g_clear_pointer (&nl->priv->dump_ipv4_defaults, g_hash_table_unref);
996
0
  g_clear_pointer (&nl->priv->dump_ipv6_defaults, g_hash_table_unref);
997
0
  g_clear_object (&nl->priv->ipv4_default_mask);
998
0
  g_clear_object (&nl->priv->ipv6_default_mask);
999
1000
0
  G_OBJECT_CLASS (g_network_monitor_netlink_parent_class)->finalize (object);
1001
0
}
1002
1003
static void
1004
g_network_monitor_netlink_class_init (GNetworkMonitorNetlinkClass *nl_class)
1005
0
{
1006
0
  GObjectClass *gobject_class = G_OBJECT_CLASS (nl_class);
1007
1008
0
  gobject_class->finalize = g_network_monitor_netlink_finalize;
1009
0
}
1010
1011
static void
1012
g_network_monitor_netlink_iface_init (GNetworkMonitorInterface *monitor_iface)
1013
0
{
1014
0
  monitor_iface->can_reach = g_network_monitor_netlink_can_reach;
1015
0
  monitor_iface->can_reach_async = g_network_monitor_netlink_can_reach_async;
1016
0
  monitor_iface->can_reach_finish = g_network_monitor_netlink_can_reach_finish;
1017
0
}
1018
1019
static void
1020
g_network_monitor_netlink_initable_iface_init (GInitableIface *iface)
1021
0
{
1022
0
  initable_parent_iface = g_type_interface_peek_parent (iface);
1023
1024
0
  iface->init = g_network_monitor_netlink_initable_init;
1025
0
}