1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright 2011 Red Hat, Inc.
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.
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.
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/>.
25 #include "gnetworkmonitornetlink.h"
26 #include "gcredentials.h"
27 #include "ginetaddressmask.h"
28 #include "ginitable.h"
29 #include "giomodule-priv.h"
31 #include "glib/gstdio.h"
32 #include "gnetworkingprivate.h"
33 #include "gnetworkmonitor.h"
35 #include "gunixcredentialsmessage.h"
37 /* must come at the end to pick system includes from
38 * gnetworkingprivate.h */
39 #include <linux/netlink.h>
40 #include <linux/rtnetlink.h>
42 static void g_network_monitor_netlink_iface_init (GNetworkMonitorInterface
*iface
);
43 static void g_network_monitor_netlink_initable_iface_init (GInitableIface
*iface
);
45 struct _GNetworkMonitorNetlinkPrivate
48 GSource
*source
, *dump_source
;
50 GPtrArray
*dump_networks
;
53 static gboolean
read_netlink_messages (GSocket
*socket
,
54 GIOCondition condition
,
56 static gboolean
request_dump (GNetworkMonitorNetlink
*nl
,
59 #define g_network_monitor_netlink_get_type _g_network_monitor_netlink_get_type
60 G_DEFINE_TYPE_WITH_CODE (GNetworkMonitorNetlink
, g_network_monitor_netlink
, G_TYPE_NETWORK_MONITOR_BASE
,
61 G_ADD_PRIVATE (GNetworkMonitorNetlink
)
62 G_IMPLEMENT_INTERFACE (G_TYPE_NETWORK_MONITOR
,
63 g_network_monitor_netlink_iface_init
)
64 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE
,
65 g_network_monitor_netlink_initable_iface_init
)
66 _g_io_modules_ensure_extension_points_registered ();
67 g_io_extension_point_implement (G_NETWORK_MONITOR_EXTENSION_POINT_NAME
,
73 g_network_monitor_netlink_init (GNetworkMonitorNetlink
*nl
)
75 nl
->priv
= g_network_monitor_netlink_get_instance_private (nl
);
80 g_network_monitor_netlink_initable_init (GInitable
*initable
,
81 GCancellable
*cancellable
,
84 GNetworkMonitorNetlink
*nl
= G_NETWORK_MONITOR_NETLINK (initable
);
86 struct sockaddr_nl snl
;
88 /* We create the socket the old-school way because sockaddr_netlink
89 * can't be represented as a GSocketAddress
91 sockfd
= g_socket (PF_NETLINK
, SOCK_RAW
, NETLINK_ROUTE
, NULL
);
95 g_set_error (error
, G_IO_ERROR
, g_io_error_from_errno (errsv
),
96 _("Could not create network monitor: %s"),
101 snl
.nl_family
= AF_NETLINK
;
102 snl
.nl_pid
= snl
.nl_pad
= 0;
103 snl
.nl_groups
= RTMGRP_IPV4_ROUTE
| RTMGRP_IPV6_ROUTE
;
104 if (bind (sockfd
, (struct sockaddr
*)&snl
, sizeof (snl
)) != 0)
107 g_set_error (error
, G_IO_ERROR
, g_io_error_from_errno (errsv
),
108 _("Could not create network monitor: %s"),
110 (void) g_close (sockfd
, NULL
);
114 nl
->priv
->sock
= g_socket_new_from_fd (sockfd
, error
);
117 g_prefix_error (error
, "%s", _("Could not create network monitor: "));
118 (void) g_close (sockfd
, NULL
);
122 if (!g_socket_set_option (nl
->priv
->sock
, SOL_SOCKET
, SO_PASSCRED
,
126 g_set_error (error
, G_IO_ERROR
, g_io_error_from_errno (errsv
),
127 _("Could not create network monitor: %s"),
132 /* Request the current state */
133 if (!request_dump (nl
, error
))
136 /* And read responses; since we haven't yet marked the socket
137 * non-blocking, each call will block until a message is received.
139 while (nl
->priv
->dump_networks
)
141 if (!read_netlink_messages (NULL
, G_IO_IN
, nl
))
145 g_socket_set_blocking (nl
->priv
->sock
, FALSE
);
146 nl
->priv
->source
= g_socket_create_source (nl
->priv
->sock
, G_IO_IN
, NULL
);
147 g_source_set_callback (nl
->priv
->source
,
148 (GSourceFunc
) read_netlink_messages
, nl
, NULL
);
149 g_source_attach (nl
->priv
->source
,
150 g_main_context_get_thread_default ());
156 request_dump (GNetworkMonitorNetlink
*nl
,
160 struct rtgenmsg
*gen
;
161 gchar buf
[NLMSG_SPACE (sizeof (*gen
))];
163 memset (buf
, 0, sizeof (buf
));
164 n
= (struct nlmsghdr
*) buf
;
165 n
->nlmsg_len
= NLMSG_LENGTH (sizeof (*gen
));
166 n
->nlmsg_type
= RTM_GETROUTE
;
167 n
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_DUMP
;
169 gen
= NLMSG_DATA (n
);
170 gen
->rtgen_family
= AF_UNSPEC
;
172 if (g_socket_send (nl
->priv
->sock
, buf
, sizeof (buf
),
175 g_prefix_error (error
, "%s", _("Could not get network status: "));
179 nl
->priv
->dump_networks
= g_ptr_array_new_with_free_func (g_object_unref
);
184 timeout_request_dump (gpointer user_data
)
186 GNetworkMonitorNetlink
*nl
= user_data
;
188 g_source_destroy (nl
->priv
->dump_source
);
189 g_source_unref (nl
->priv
->dump_source
);
190 nl
->priv
->dump_source
= NULL
;
192 request_dump (nl
, NULL
);
198 queue_request_dump (GNetworkMonitorNetlink
*nl
)
200 if (nl
->priv
->dump_networks
)
203 if (nl
->priv
->dump_source
)
205 g_source_destroy (nl
->priv
->dump_source
);
206 g_source_unref (nl
->priv
->dump_source
);
209 nl
->priv
->dump_source
= g_timeout_source_new (1000);
210 g_source_set_callback (nl
->priv
->dump_source
,
211 (GSourceFunc
) timeout_request_dump
, nl
, NULL
);
212 g_source_attach (nl
->priv
->dump_source
,
213 g_main_context_get_thread_default ());
217 add_network (GNetworkMonitorNetlink
*nl
,
218 GSocketFamily family
,
222 GInetAddress
*dest_addr
;
223 GInetAddressMask
*network
;
226 dest_addr
= g_inet_address_new_from_bytes (dest
, family
);
228 dest_addr
= g_inet_address_new_any (family
);
229 network
= g_inet_address_mask_new (dest_addr
, dest_len
, NULL
);
230 g_object_unref (dest_addr
);
231 g_return_if_fail (network
!= NULL
);
233 if (nl
->priv
->dump_networks
)
234 g_ptr_array_add (nl
->priv
->dump_networks
, network
);
237 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (nl
), network
);
238 g_object_unref (network
);
243 remove_network (GNetworkMonitorNetlink
*nl
,
244 GSocketFamily family
,
248 GInetAddress
*dest_addr
;
249 GInetAddressMask
*network
;
252 dest_addr
= g_inet_address_new_from_bytes (dest
, family
);
254 dest_addr
= g_inet_address_new_any (family
);
255 network
= g_inet_address_mask_new (dest_addr
, dest_len
, NULL
);
256 g_object_unref (dest_addr
);
257 g_return_if_fail (network
!= NULL
);
259 if (nl
->priv
->dump_networks
)
261 GInetAddressMask
**dump_networks
= (GInetAddressMask
**)nl
->priv
->dump_networks
->pdata
;
264 for (i
= 0; i
< nl
->priv
->dump_networks
->len
; i
++)
266 if (g_inet_address_mask_equal (network
, dump_networks
[i
]))
267 g_ptr_array_remove_index_fast (nl
->priv
->dump_networks
, i
--);
269 g_object_unref (network
);
273 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (nl
), network
);
274 g_object_unref (network
);
279 finish_dump (GNetworkMonitorNetlink
*nl
)
281 g_network_monitor_base_set_networks (G_NETWORK_MONITOR_BASE (nl
),
282 (GInetAddressMask
**)nl
->priv
->dump_networks
->pdata
,
283 nl
->priv
->dump_networks
->len
);
284 g_ptr_array_free (nl
->priv
->dump_networks
, TRUE
);
285 nl
->priv
->dump_networks
= NULL
;
289 read_netlink_messages (GSocket
*socket
,
290 GIOCondition condition
,
293 GNetworkMonitorNetlink
*nl
= user_data
;
297 GError
*error
= NULL
;
298 GSocketAddress
*addr
= NULL
;
299 struct nlmsghdr
*msg
;
302 struct sockaddr_nl source_sockaddr
;
304 guint8
*dest
, *gateway
, *oif
;
305 gboolean retval
= TRUE
;
310 flags
= MSG_PEEK
| MSG_TRUNC
;
311 len
= g_socket_receive_message (nl
->priv
->sock
, NULL
, &iv
, 1,
312 NULL
, NULL
, &flags
, NULL
, &error
);
315 g_warning ("Error on netlink socket: %s", error
->message
);
316 g_error_free (error
);
317 if (nl
->priv
->dump_networks
)
322 iv
.buffer
= g_malloc (len
);
324 len
= g_socket_receive_message (nl
->priv
->sock
, &addr
, &iv
, 1,
325 NULL
, NULL
, NULL
, NULL
, &error
);
328 g_warning ("Error on netlink socket: %s", error
->message
);
329 g_clear_object (&addr
);
330 g_error_free (error
);
331 if (nl
->priv
->dump_networks
)
336 if (!g_socket_address_to_native (addr
, &source_sockaddr
, sizeof (source_sockaddr
), &error
))
338 g_warning ("Error on netlink socket: %s", error
->message
);
339 g_clear_object (&addr
);
340 g_error_free (error
);
341 if (nl
->priv
->dump_networks
)
346 /* If the sender port id is 0 (not fakeable) then the message is from the kernel */
347 if (source_sockaddr
.nl_pid
!= 0)
350 msg
= (struct nlmsghdr
*) iv
.buffer
;
351 for (; len
> 0; msg
= NLMSG_NEXT (msg
, len
))
353 if (!NLMSG_OK (msg
, (size_t) len
))
355 g_warning ("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 UNALIGNED_IN6_IS_ADDR_MC_LINKLOCAL (dest
))
400 if (msg
->nlmsg_type
== RTM_NEWROUTE
)
401 add_network (nl
, rtmsg
->rtm_family
, rtmsg
->rtm_dst_len
, dest
);
403 remove_network (nl
, rtmsg
->rtm_family
, rtmsg
->rtm_dst_len
, dest
);
404 queue_request_dump (nl
);
414 struct nlmsgerr
*e
= NLMSG_DATA (msg
);
416 g_warning ("netlink error: %s", g_strerror (-e
->error
));
422 g_warning ("unexpected netlink message %d", msg
->nlmsg_type
);
430 g_clear_object (&addr
);
432 if (!retval
&& nl
->priv
->dump_networks
)
438 g_network_monitor_netlink_finalize (GObject
*object
)
440 GNetworkMonitorNetlink
*nl
= G_NETWORK_MONITOR_NETLINK (object
);
444 g_socket_close (nl
->priv
->sock
, NULL
);
445 g_object_unref (nl
->priv
->sock
);
448 if (nl
->priv
->source
)
450 g_source_destroy (nl
->priv
->source
);
451 g_source_unref (nl
->priv
->source
);
454 if (nl
->priv
->dump_source
)
456 g_source_destroy (nl
->priv
->dump_source
);
457 g_source_unref (nl
->priv
->dump_source
);
460 G_OBJECT_CLASS (g_network_monitor_netlink_parent_class
)->finalize (object
);
464 g_network_monitor_netlink_class_init (GNetworkMonitorNetlinkClass
*nl_class
)
466 GObjectClass
*gobject_class
= G_OBJECT_CLASS (nl_class
);
468 gobject_class
->finalize
= g_network_monitor_netlink_finalize
;
472 g_network_monitor_netlink_iface_init (GNetworkMonitorInterface
*monitor_iface
)
477 g_network_monitor_netlink_initable_iface_init (GInitableIface
*iface
)
479 iface
->init
= g_network_monitor_netlink_initable_init
;