Change LGPL-2.1+ to LGPL-2.1-or-later
[platform/upstream/glib.git] / 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 }