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