1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright 2011 Red Hat, Inc.
5 * SPDX-License-Identifier: LGPL-2.1-or-later
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
27 #include "gnetworkmonitornetlink.h"
28 #include "gcredentials.h"
29 #include "ginetaddressmask.h"
30 #include "ginitable.h"
31 #include "giomodule-priv.h"
33 #include "glib/gstdio.h"
34 #include "gnetworkingprivate.h"
35 #include "gnetworkmonitor.h"
37 #include "gunixcredentialsmessage.h"
39 /* must come at the end to pick system includes from
40 * gnetworkingprivate.h */
41 #include <linux/netlink.h>
42 #include <linux/rtnetlink.h>
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);
48 struct _GNetworkMonitorNetlinkPrivate
51 GSource *source, *dump_source;
52 GMainContext *context;
54 GPtrArray *dump_networks;
57 static gboolean read_netlink_messages (GNetworkMonitorNetlink *nl,
59 static gboolean read_netlink_messages_callback (GSocket *socket,
60 GIOCondition condition,
62 static gboolean request_dump (GNetworkMonitorNetlink *nl,
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,
79 g_network_monitor_netlink_init (GNetworkMonitorNetlink *nl)
81 nl->priv = g_network_monitor_netlink_get_instance_private (nl);
85 g_network_monitor_netlink_initable_init (GInitable *initable,
86 GCancellable *cancellable,
89 GNetworkMonitorNetlink *nl = G_NETWORK_MONITOR_NETLINK (initable);
91 struct sockaddr_nl snl;
93 /* We create the socket the old-school way because sockaddr_netlink
94 * can't be represented as a GSocketAddress
96 sockfd = g_socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE, NULL);
100 g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
101 _("Could not create network monitor: %s"),
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)
112 g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
113 _("Could not create network monitor: %s"),
115 (void) g_close (sockfd, NULL);
119 nl->priv->sock = g_socket_new_from_fd (sockfd, error);
122 g_prefix_error (error, "%s", _("Could not create network monitor: "));
123 (void) g_close (sockfd, NULL);
127 if (!g_socket_set_option (nl->priv->sock, SOL_SOCKET, SO_PASSCRED,
131 g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
132 _("Could not create network monitor: %s"),
137 /* Request the current state */
138 if (!request_dump (nl, error))
141 /* And read responses; since we haven't yet marked the socket
142 * non-blocking, each call will block until a message is received.
144 while (nl->priv->dump_networks)
146 GError *local_error = NULL;
147 if (!read_netlink_messages (nl, &local_error))
149 g_warning ("%s", local_error->message);
150 g_clear_error (&local_error);
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);
162 return initable_parent_iface->init (initable, cancellable, error);
166 request_dump (GNetworkMonitorNetlink *nl,
170 struct rtgenmsg *gen;
171 gchar buf[NLMSG_SPACE (sizeof (*gen))];
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;
179 gen = NLMSG_DATA (n);
180 gen->rtgen_family = AF_UNSPEC;
182 if (g_socket_send (nl->priv->sock, buf, sizeof (buf),
185 g_prefix_error (error, "%s", _("Could not get network status: "));
189 nl->priv->dump_networks = g_ptr_array_new_with_free_func (g_object_unref);
194 timeout_request_dump (gpointer user_data)
196 GNetworkMonitorNetlink *nl = user_data;
198 g_source_destroy (nl->priv->dump_source);
199 g_source_unref (nl->priv->dump_source);
200 nl->priv->dump_source = NULL;
202 request_dump (nl, NULL);
208 queue_request_dump (GNetworkMonitorNetlink *nl)
210 if (nl->priv->dump_networks)
213 if (nl->priv->dump_source)
215 g_source_destroy (nl->priv->dump_source);
216 g_source_unref (nl->priv->dump_source);
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);
225 static GInetAddressMask *
226 create_inet_address_mask (GSocketFamily family,
230 GInetAddress *dest_addr;
231 GInetAddressMask *network;
234 dest_addr = g_inet_address_new_from_bytes (dest, family);
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);
244 add_network (GNetworkMonitorNetlink *nl,
245 GSocketFamily family,
249 GInetAddressMask *network = create_inet_address_mask (family, dest, dest_len);
250 g_return_if_fail (network != NULL);
252 if (nl->priv->dump_networks)
253 g_ptr_array_add (nl->priv->dump_networks, g_object_ref (network));
255 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (nl), network);
257 g_object_unref (network);
261 remove_network (GNetworkMonitorNetlink *nl,
262 GSocketFamily family,
266 GInetAddressMask *network = create_inet_address_mask (family, dest, dest_len);
267 g_return_if_fail (network != NULL);
269 if (nl->priv->dump_networks)
271 GInetAddressMask **dump_networks = (GInetAddressMask **)nl->priv->dump_networks->pdata;
274 for (i = 0; i < nl->priv->dump_networks->len; i++)
276 if (g_inet_address_mask_equal (network, dump_networks[i]))
277 g_ptr_array_remove_index_fast (nl->priv->dump_networks, i--);
282 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (nl), network);
285 g_object_unref (network);
289 finish_dump (GNetworkMonitorNetlink *nl)
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;
299 read_netlink_messages (GNetworkMonitorNetlink *nl,
305 GError *local_error = NULL;
306 GSocketAddress *addr = NULL;
307 struct nlmsghdr *msg;
310 struct sockaddr_nl source_sockaddr;
312 guint8 *dest, *gateway, *oif;
313 gboolean retval = TRUE;
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);
327 iv.buffer = g_malloc (len);
329 len = g_socket_receive_message (nl->priv->sock, &addr, &iv, 1,
330 NULL, NULL, NULL, NULL, &local_error);
337 if (!g_socket_address_to_native (addr, &source_sockaddr, sizeof (source_sockaddr), &local_error))
343 /* If the sender port id is 0 (not fakeable) then the message is from the kernel */
344 if (source_sockaddr.nl_pid != 0)
347 msg = (struct nlmsghdr *) iv.buffer;
348 for (; len > 0; msg = NLMSG_NEXT (msg, len))
350 if (!NLMSG_OK (msg, (size_t) len))
352 g_set_error_literal (&local_error,
354 G_IO_ERROR_PARTIAL_INPUT,
355 "netlink message was truncated; shouldn't happen...");
360 switch (msg->nlmsg_type)
364 rtmsg = NLMSG_DATA (msg);
366 if (rtmsg->rtm_family != AF_INET && rtmsg->rtm_family != AF_INET6)
368 if (rtmsg->rtm_type == RTN_UNREACHABLE)
371 attrlen = NLMSG_PAYLOAD (msg, sizeof (struct rtmsg));
372 attr = RTM_RTA (rtmsg);
373 dest = gateway = oif = NULL;
374 while (RTA_OK (attr, attrlen))
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);
385 if (dest || gateway || oif)
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.
391 #define UNALIGNED_IN6_IS_ADDR_MC_LINKLOCAL(a) \
392 ((a[0] == 0xff) && ((a[1] & 0xf) == 0x2))
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)))
400 if (msg->nlmsg_type == RTM_NEWROUTE)
401 add_network (nl, rtmsg->rtm_family, dest, rtmsg->rtm_dst_len);
403 remove_network (nl, rtmsg->rtm_family, dest, rtmsg->rtm_dst_len);
404 queue_request_dump (nl);
414 struct nlmsgerr *e = NLMSG_DATA (msg);
416 g_set_error (&local_error,
418 g_io_error_from_errno (-e->error),
420 g_strerror (-e->error));
426 g_set_error (&local_error,
428 G_IO_ERROR_INVALID_DATA,
429 "unexpected netlink message %d",
438 g_clear_object (&addr);
440 if (!retval && nl->priv->dump_networks)
444 g_propagate_prefixed_error (error, local_error, "Error on netlink socket: ");
450 g_network_monitor_netlink_finalize (GObject *object)
452 GNetworkMonitorNetlink *nl = G_NETWORK_MONITOR_NETLINK (object);
454 if (nl->priv->source)
456 g_source_destroy (nl->priv->source);
457 g_source_unref (nl->priv->source);
460 if (nl->priv->dump_source)
462 g_source_destroy (nl->priv->dump_source);
463 g_source_unref (nl->priv->dump_source);
468 g_socket_close (nl->priv->sock, NULL);
469 g_object_unref (nl->priv->sock);
472 g_clear_pointer (&nl->priv->context, g_main_context_unref);
473 g_clear_pointer (&nl->priv->dump_networks, g_ptr_array_unref);
475 G_OBJECT_CLASS (g_network_monitor_netlink_parent_class)->finalize (object);
479 read_netlink_messages_callback (GSocket *socket,
480 GIOCondition condition,
483 GError *error = NULL;
484 GNetworkMonitorNetlink *nl = G_NETWORK_MONITOR_NETLINK (user_data);
486 if (!read_netlink_messages (nl, &error))
488 g_warning ("Error reading netlink message: %s", error->message);
489 g_clear_error (&error);
497 g_network_monitor_netlink_class_init (GNetworkMonitorNetlinkClass *nl_class)
499 GObjectClass *gobject_class = G_OBJECT_CLASS (nl_class);
501 gobject_class->finalize = g_network_monitor_netlink_finalize;
505 g_network_monitor_netlink_iface_init (GNetworkMonitorInterface *monitor_iface)
510 g_network_monitor_netlink_initable_iface_init (GInitableIface *iface)
512 initable_parent_iface = g_type_interface_peek_parent (iface);
514 iface->init = g_network_monitor_netlink_initable_init;