add GNetworkMonitor, for... monitoring the network
[platform/upstream/glib.git] / gio / gnetworkmonitornetlink.c
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 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, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include "config.h"
22
23 #include <errno.h>
24 #include <unistd.h>
25 #include <linux/netlink.h>
26 #include <linux/rtnetlink.h>
27
28 #include "gnetworkmonitornetlink.h"
29 #include "gcredentials.h"
30 #include "ginetaddressmask.h"
31 #include "ginitable.h"
32 #include "giomodule-priv.h"
33 #include "glibintl.h"
34 #include "gnetworkingprivate.h"
35 #include "gnetworkmonitor.h"
36 #include "gsocket.h"
37 #include "gunixcredentialsmessage.h"
38
39 static void g_network_monitor_netlink_iface_init (GNetworkMonitorInterface *iface);
40 static void g_network_monitor_netlink_initable_iface_init (GInitableIface *iface);
41
42 #define g_network_monitor_netlink_get_type _g_network_monitor_netlink_get_type
43 G_DEFINE_TYPE_WITH_CODE (GNetworkMonitorNetlink, g_network_monitor_netlink, G_TYPE_NETWORK_MONITOR_BASE,
44                          G_IMPLEMENT_INTERFACE (G_TYPE_NETWORK_MONITOR,
45                                                 g_network_monitor_netlink_iface_init)
46                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
47                                                 g_network_monitor_netlink_initable_iface_init)
48                          _g_io_modules_ensure_extension_points_registered ();
49                          g_io_extension_point_implement (G_NETWORK_MONITOR_EXTENSION_POINT_NAME,
50                                                          g_define_type_id,
51                                                          "netlink",
52                                                          20))
53
54 struct _GNetworkMonitorNetlinkPrivate
55 {
56   GSocket *sock;
57   GSource *source, *dump_source;
58
59   GPtrArray *dump_networks;
60 };
61
62 static gboolean read_netlink_messages (GSocket             *socket,
63                                        GIOCondition         condition,
64                                        gpointer             user_data);
65 static gboolean request_dump (GNetworkMonitorNetlink  *nl,
66                               GError                 **error);
67
68 static void
69 g_network_monitor_netlink_init (GNetworkMonitorNetlink *nl)
70 {
71   nl->priv = G_TYPE_INSTANCE_GET_PRIVATE (nl,
72                                           G_TYPE_NETWORK_MONITOR_NETLINK,
73                                           GNetworkMonitorNetlinkPrivate);
74 }
75
76
77 static gboolean
78 g_network_monitor_netlink_initable_init (GInitable     *initable,
79                                          GCancellable  *cancellable,
80                                          GError       **error)
81 {
82   GNetworkMonitorNetlink *nl = G_NETWORK_MONITOR_NETLINK (initable);
83   gint sockfd, val;
84   struct sockaddr_nl snl;
85
86   /* We create the socket the old-school way because sockaddr_netlink
87    * can't be represented as a GSocketAddress
88    */
89   sockfd = socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
90   if (sockfd == -1)
91     {
92       int errsv = errno;
93       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
94                    _("Could not create netlink socket: %s"),
95                    g_strerror (errno));
96       return FALSE;
97     }
98
99   snl.nl_family = AF_NETLINK;
100   snl.nl_pid = snl.nl_pad = 0;
101   snl.nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE;
102   if (bind (sockfd, (struct sockaddr *)&snl, sizeof (snl)) != 0)
103     {
104       int errsv = errno;
105       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
106                    _("Could not bind netlink socket: %s"),
107                    g_strerror (errno));
108       close (sockfd);
109       return FALSE;
110     }
111
112   val = 1;
113   if (setsockopt (sockfd, SOL_SOCKET, SO_PASSCRED, &val, sizeof (val)) != 0)
114     {
115       int errsv = errno;
116       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
117                    _("Could not set options on netlink socket: %s"),
118                    g_strerror (errno));
119       close (sockfd);
120       return FALSE;
121     }
122
123   nl->priv->sock = g_socket_new_from_fd (sockfd, error);
124   if (error)
125     {
126       g_prefix_error (error, "%s", _("Could not wrap netlink socket: "));
127       close (sockfd);
128       return FALSE;
129     }
130
131   /* Request the current state */
132   if (!request_dump (nl, error))
133     return FALSE;
134
135   /* And read responses; since we haven't yet marked the socket
136    * non-blocking, each call will block until a message is received.
137    */
138   while (nl->priv->dump_networks)
139     {
140       if (!read_netlink_messages (NULL, G_IO_IN, nl))
141         break;
142     }
143
144   g_socket_set_blocking (nl->priv->sock, FALSE);
145   nl->priv->source = g_socket_create_source (nl->priv->sock, G_IO_IN, NULL);
146   g_source_set_callback (nl->priv->source,
147                          (GSourceFunc) read_netlink_messages, nl, NULL);
148   g_source_attach (nl->priv->source,
149                    g_main_context_get_thread_default ());
150
151   return TRUE;
152 }
153
154 static gboolean
155 request_dump (GNetworkMonitorNetlink  *nl,
156               GError                 **error)
157 {
158   struct nlmsghdr *n;
159   struct rtgenmsg *gen;
160   gchar buf[NLMSG_SPACE (sizeof (*gen))];
161
162   memset (buf, 0, sizeof (buf));
163   n = (struct nlmsghdr*) buf;
164   n->nlmsg_len = NLMSG_LENGTH (sizeof (*gen));
165   n->nlmsg_type = RTM_GETROUTE;
166   n->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
167   n->nlmsg_pid = 0;
168   gen = NLMSG_DATA (n);
169   gen->rtgen_family = AF_UNSPEC;
170
171   if (g_socket_send (nl->priv->sock, buf, sizeof (buf),
172                      NULL, error) < 0)
173     {
174       g_prefix_error (error, "%s", _("Could not send netlink request: "));
175       return FALSE;
176     }
177
178   nl->priv->dump_networks = g_ptr_array_new_with_free_func (g_object_unref);
179   return TRUE;
180 }
181
182 static gboolean
183 timeout_request_dump (gpointer user_data)
184 {
185   GNetworkMonitorNetlink *nl = user_data;
186
187   g_source_destroy (nl->priv->dump_source);
188   g_source_unref (nl->priv->dump_source);
189   nl->priv->dump_source = NULL;
190
191   request_dump (nl, NULL);
192
193   return FALSE;
194 }
195
196 static void
197 queue_request_dump (GNetworkMonitorNetlink *nl)
198 {
199   if (nl->priv->dump_networks)
200     return;
201
202   if (nl->priv->dump_source)
203     {
204       g_source_destroy (nl->priv->dump_source);
205       g_source_unref (nl->priv->dump_source);
206     }
207
208   nl->priv->dump_source = g_timeout_source_new (1000);
209   g_source_set_callback (nl->priv->dump_source,
210                          (GSourceFunc) timeout_request_dump, nl, NULL);
211   g_source_attach (nl->priv->dump_source,
212                    g_main_context_get_thread_default ());
213 }
214
215 static void
216 add_network (GNetworkMonitorNetlink *nl,
217              GSocketFamily           family,
218              gint                    dest_len,
219              guint8                 *dest,
220              guint8                 *gateway)
221 {
222   GInetAddress *dest_addr;
223   GInetAddressMask *network;
224
225   if (dest)
226     dest_addr = g_inet_address_new_from_bytes (dest, family);
227   else
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);
232
233   if (nl->priv->dump_networks)
234     g_ptr_array_add (nl->priv->dump_networks, network);
235   else
236     {
237       g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (nl), network);
238       g_object_unref (network);
239     }
240 }
241
242 static void
243 remove_network (GNetworkMonitorNetlink *nl,
244                 GSocketFamily           family,
245                 gint                    dest_len,
246                 guint8                 *dest,
247                 guint8                 *gateway)
248 {
249   GInetAddress *dest_addr;
250   GInetAddressMask *network;
251
252   if (dest)
253     dest_addr = g_inet_address_new_from_bytes (dest, family);
254   else
255     dest_addr = g_inet_address_new_any (family);
256   network = g_inet_address_mask_new (dest_addr, dest_len, NULL);
257   g_object_unref (dest_addr);
258   g_return_if_fail (network != NULL);
259
260   if (nl->priv->dump_networks)
261     {
262       GInetAddressMask **dump_networks = (GInetAddressMask **)nl->priv->dump_networks->pdata;
263       int i;
264
265       for (i = 0; i < nl->priv->dump_networks->len; i++)
266         {
267           if (g_inet_address_mask_equal (network, dump_networks[i]))
268             g_ptr_array_remove_index_fast (nl->priv->dump_networks, i--);
269         }
270       g_object_unref (network);
271     }
272   else
273     {       
274       g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (nl), network);
275       g_object_unref (network);
276     }
277 }
278
279 static void
280 finish_dump (GNetworkMonitorNetlink *nl)
281 {
282   g_network_monitor_base_set_networks (G_NETWORK_MONITOR_BASE (nl),
283                                        (GInetAddressMask **)nl->priv->dump_networks->pdata,
284                                        nl->priv->dump_networks->len);
285   g_ptr_array_free (nl->priv->dump_networks, FALSE);
286   nl->priv->dump_networks = NULL;
287 }
288
289 static gboolean
290 read_netlink_messages (GSocket      *socket,
291                        GIOCondition  condition,
292                        gpointer      user_data)
293 {
294   GNetworkMonitorNetlink *nl = user_data;
295   GInputVector iv;
296   gsize len;
297   GSocketControlMessage **cmsgs = NULL;
298   gint num_cmsgs = 0, i, flags;
299   GError *error = NULL;
300   GCredentials *creds;
301   uid_t sender;
302   struct nlmsghdr *msg;
303   struct rtmsg *rtmsg;
304   struct rtattr *attr;
305   gsize attrlen;
306   guint8 *dest, *gateway;
307   gboolean retval = TRUE;
308
309   iv.buffer = NULL;
310   iv.size = 0;
311
312   flags = MSG_PEEK | MSG_TRUNC;
313   len = g_socket_receive_message (nl->priv->sock, NULL, &iv, 1,
314                                   NULL, NULL, &flags, NULL, &error);
315   if (len < 0)
316     {
317       g_warning ("Error on netlink socket: %s", error->message);
318       g_error_free (error);
319       if (nl->priv->dump_networks)
320         finish_dump (nl);
321       return FALSE;
322     }
323
324   iv.buffer = g_malloc (len);
325   iv.size = len;
326   len = g_socket_receive_message (nl->priv->sock, NULL, &iv, 1,
327                                   &cmsgs, &num_cmsgs, NULL, NULL, &error);
328   if (len < 0)
329     {
330       g_warning ("Error on netlink socket: %s", error->message);
331       g_error_free (error);
332       if (nl->priv->dump_networks)
333         finish_dump (nl);
334       return FALSE;
335     }
336
337   if (num_cmsgs != 1 || !G_IS_UNIX_CREDENTIALS_MESSAGE (cmsgs[0]))
338     goto done;
339
340   creds = g_unix_credentials_message_get_credentials (G_UNIX_CREDENTIALS_MESSAGE (cmsgs[0]));
341   sender = g_credentials_get_unix_user (creds, NULL);
342   if (sender != 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_warning ("netlink message was truncated; shouldn't happen...");
351           retval = FALSE;
352           goto done;
353         }
354
355       switch (msg->nlmsg_type)
356         {
357         case RTM_NEWROUTE:
358         case RTM_DELROUTE:
359           rtmsg = NLMSG_DATA (msg);
360
361           if (rtmsg->rtm_family != AF_INET && rtmsg->rtm_family != AF_INET6)
362             continue;
363           if (rtmsg->rtm_type == RTN_UNREACHABLE)
364             continue;
365
366           attrlen = NLMSG_PAYLOAD (msg, sizeof (struct rtmsg));
367           attr = RTM_RTA (rtmsg);
368           dest = gateway = NULL;
369           while (RTA_OK (attr, attrlen))
370             {
371               if (attr->rta_type == RTA_DST)
372                 dest = RTA_DATA (attr);
373               else if (attr->rta_type == RTA_GATEWAY)
374                 gateway = RTA_DATA (attr);
375               attr = RTA_NEXT (attr, attrlen);
376             }
377
378           if (dest || gateway)
379             {
380               if (msg->nlmsg_type == RTM_NEWROUTE)
381                 add_network (nl, rtmsg->rtm_family, rtmsg->rtm_dst_len, dest, gateway);
382               else
383                 remove_network (nl, rtmsg->rtm_family, rtmsg->rtm_dst_len, dest, gateway);
384               queue_request_dump (nl);
385             }
386           break;
387
388         case NLMSG_DONE:
389           finish_dump (nl);
390           goto done;
391
392         case NLMSG_ERROR:
393           {
394             struct nlmsgerr *e = NLMSG_DATA (msg);
395
396             g_warning ("netlink error: %s", g_strerror (-e->error));
397           }
398           retval = FALSE;
399           goto done;
400
401         default:
402           g_warning ("unexpected netlink message %d", msg->nlmsg_type);
403           retval = FALSE;
404           goto done;
405         }
406     }
407
408  done:
409   for (i = 0; i < num_cmsgs; i++)
410     g_object_unref (cmsgs[i]);
411   g_free (cmsgs);
412
413   g_free (iv.buffer);
414
415   if (!retval && nl->priv->dump_networks)
416     finish_dump (nl);
417   return retval;
418 }
419
420 static void
421 g_network_monitor_netlink_finalize (GObject *object)
422 {
423   GNetworkMonitorNetlink *nl = G_NETWORK_MONITOR_NETLINK (object);
424
425   if (nl->priv->sock)
426     {
427       g_socket_close (nl->priv->sock, NULL);
428       g_object_unref (nl->priv->sock);
429     }
430
431   if (nl->priv->source)
432     {
433       g_source_destroy (nl->priv->source);
434       g_source_unref (nl->priv->source);
435     }
436
437   if (nl->priv->dump_source)
438     {
439       g_source_destroy (nl->priv->dump_source);
440       g_source_unref (nl->priv->dump_source);
441     }
442
443   G_OBJECT_CLASS (g_network_monitor_netlink_parent_class)->finalize (object);
444 }
445
446 static void
447 g_network_monitor_netlink_class_init (GNetworkMonitorNetlinkClass *nl_class)
448 {
449   GObjectClass *gobject_class = G_OBJECT_CLASS (nl_class);
450
451   g_type_class_add_private (nl_class, sizeof (GNetworkMonitorNetlinkPrivate));
452
453   gobject_class->finalize  = g_network_monitor_netlink_finalize;
454 }
455
456 static void
457 g_network_monitor_netlink_iface_init (GNetworkMonitorInterface *monitor_iface)
458 {
459 }
460
461 static void
462 g_network_monitor_netlink_initable_iface_init (GInitableIface *iface)
463 {
464   iface->init = g_network_monitor_netlink_initable_init;
465 }