6ddfd83252526d7f874f62478c2be8144074d3d0
[platform/upstream/connman.git] / vpn / vpn-rtnl.c
1 /*
2  *
3  *  ConnMan VPN daemon
4  *
5  *  Copyright (C) 2012-2013  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <sys/socket.h>
31 #include <sys/ioctl.h>
32 #include <arpa/inet.h>
33 #include <netinet/ether.h>
34 #include <netinet/icmp6.h>
35 #include <net/if_arp.h>
36 #include <linux/if.h>
37 #include <linux/netlink.h>
38 #include <linux/rtnetlink.h>
39 #include <linux/wireless.h>
40
41 #include <glib.h>
42
43 #include <connman/log.h>
44
45 #include "vpn.h"
46
47 #include "vpn-rtnl.h"
48
49 #ifndef ARPHDR_PHONET_PIPE
50 #define ARPHDR_PHONET_PIPE (821)
51 #endif
52
53 #define print(arg...) do { if (0) connman_info(arg); } while (0)
54 #define debug(arg...) do { if (0) DBG(arg); } while (0)
55
56 struct watch_data {
57         unsigned int id;
58         int index;
59         vpn_rtnl_link_cb_t newlink;
60         void *user_data;
61 };
62
63 static GSList *watch_list = NULL;
64 static unsigned int watch_id = 0;
65
66 static GSList *update_list = NULL;
67 static guint update_interval = G_MAXUINT;
68 static guint update_timeout = 0;
69
70 struct interface_data {
71         int index;
72         char *ident;
73 };
74
75 static GHashTable *interface_list = NULL;
76
77 static void free_interface(gpointer data)
78 {
79         struct interface_data *interface = data;
80
81         g_free(interface->ident);
82         g_free(interface);
83 }
84
85 /**
86  * vpn_rtnl_add_newlink_watch:
87  * @index: network device index
88  * @callback: callback function
89  * @user_data: callback data;
90  *
91  * Add a new RTNL watch for newlink events
92  *
93  * Returns: %0 on failure and a unique id on success
94  */
95 unsigned int vpn_rtnl_add_newlink_watch(int index,
96                         vpn_rtnl_link_cb_t callback, void *user_data)
97 {
98         struct watch_data *watch;
99
100         watch = g_try_new0(struct watch_data, 1);
101         if (!watch)
102                 return 0;
103
104         watch->id = ++watch_id;
105         watch->index = index;
106
107         watch->newlink = callback;
108         watch->user_data = user_data;
109
110         watch_list = g_slist_prepend(watch_list, watch);
111
112         DBG("id %d", watch->id);
113
114         if (callback) {
115                 unsigned int flags = __vpn_ipconfig_get_flags_from_index(index);
116
117                 if (flags > 0)
118                         callback(flags, 0, user_data);
119         }
120
121         return watch->id;
122 }
123
124 /**
125  * vpn_rtnl_remove_watch:
126  * @id: watch identifier
127  *
128  * Remove the RTNL watch for the identifier
129  */
130 void vpn_rtnl_remove_watch(unsigned int id)
131 {
132         GSList *list;
133
134         DBG("id %d", id);
135
136         if (id == 0)
137                 return;
138
139         for (list = watch_list; list; list = list->next) {
140                 struct watch_data *watch = list->data;
141
142                 if (watch->id  == id) {
143                         watch_list = g_slist_remove(watch_list, watch);
144                         g_free(watch);
145                         break;
146                 }
147         }
148 }
149
150 static void trigger_rtnl(int index, void *user_data)
151 {
152         struct vpn_rtnl *rtnl = user_data;
153
154         if (rtnl->newlink) {
155                 unsigned short type = __vpn_ipconfig_get_type_from_index(index);
156                 unsigned int flags = __vpn_ipconfig_get_flags_from_index(index);
157
158                 rtnl->newlink(type, index, flags, 0);
159         }
160 }
161
162 static GSList *rtnl_list = NULL;
163
164 static gint compare_priority(gconstpointer a, gconstpointer b)
165 {
166         const struct vpn_rtnl *rtnl1 = a;
167         const struct vpn_rtnl *rtnl2 = b;
168
169         return rtnl2->priority - rtnl1->priority;
170 }
171
172 /**
173  * vpn_rtnl_register:
174  * @rtnl: RTNL module
175  *
176  * Register a new RTNL module
177  *
178  * Returns: %0 on success
179  */
180 int vpn_rtnl_register(struct vpn_rtnl *rtnl)
181 {
182         DBG("rtnl %p name %s", rtnl, rtnl->name);
183
184         rtnl_list = g_slist_insert_sorted(rtnl_list, rtnl,
185                                                         compare_priority);
186
187         __vpn_ipconfig_foreach(trigger_rtnl, rtnl);
188
189         return 0;
190 }
191
192 /**
193  * vpn_rtnl_unregister:
194  * @rtnl: RTNL module
195  *
196  * Remove a previously registered RTNL module
197  */
198 void vpn_rtnl_unregister(struct vpn_rtnl *rtnl)
199 {
200         DBG("rtnl %p name %s", rtnl, rtnl->name);
201
202         rtnl_list = g_slist_remove(rtnl_list, rtnl);
203 }
204
205 static const char *operstate2str(unsigned char operstate)
206 {
207         switch (operstate) {
208         case IF_OPER_UNKNOWN:
209                 return "UNKNOWN";
210         case IF_OPER_NOTPRESENT:
211                 return "NOT-PRESENT";
212         case IF_OPER_DOWN:
213                 return "DOWN";
214         case IF_OPER_LOWERLAYERDOWN:
215                 return "LOWER-LAYER-DOWN";
216         case IF_OPER_TESTING:
217                 return "TESTING";
218         case IF_OPER_DORMANT:
219                 return "DORMANT";
220         case IF_OPER_UP:
221                 return "UP";
222         }
223
224         return "";
225 }
226
227 static void extract_link(struct ifinfomsg *msg, int bytes,
228                                 struct ether_addr *address, const char **ifname,
229                                 unsigned int *mtu, unsigned char *operstate,
230                                                 struct rtnl_link_stats *stats)
231 {
232         struct rtattr *attr;
233
234         for (attr = IFLA_RTA(msg); RTA_OK(attr, bytes);
235                                         attr = RTA_NEXT(attr, bytes)) {
236                 switch (attr->rta_type) {
237                 case IFLA_ADDRESS:
238                         if (address)
239                                 memcpy(address, RTA_DATA(attr), ETH_ALEN);
240                         break;
241                 case IFLA_IFNAME:
242                         if (ifname)
243                                 *ifname = RTA_DATA(attr);
244                         break;
245                 case IFLA_MTU:
246                         if (mtu)
247                                 *mtu = *((unsigned int *) RTA_DATA(attr));
248                         break;
249                 case IFLA_STATS:
250                         if (stats)
251                                 memcpy(stats, RTA_DATA(attr),
252                                         sizeof(struct rtnl_link_stats));
253                         break;
254                 case IFLA_OPERSTATE:
255                         if (operstate)
256                                 *operstate = *((unsigned char *) RTA_DATA(attr));
257                         break;
258                 case IFLA_LINKMODE:
259                         break;
260                 }
261         }
262 }
263
264 static void process_newlink(unsigned short type, int index, unsigned flags,
265                         unsigned change, struct ifinfomsg *msg, int bytes)
266 {
267         struct ether_addr address = {{ 0, 0, 0, 0, 0, 0 }};
268         struct ether_addr compare = {{ 0, 0, 0, 0, 0, 0 }};
269         struct rtnl_link_stats stats;
270         unsigned char operstate = 0xff;
271         struct interface_data *interface;
272         const char *ifname = NULL;
273         unsigned int mtu = 0;
274         char ident[13], str[18];
275         GSList *list;
276
277         memset(&stats, 0, sizeof(stats));
278         extract_link(msg, bytes, &address, &ifname, &mtu, &operstate, &stats);
279
280         snprintf(ident, 13, "%02x%02x%02x%02x%02x%02x",
281                                                 address.ether_addr_octet[0],
282                                                 address.ether_addr_octet[1],
283                                                 address.ether_addr_octet[2],
284                                                 address.ether_addr_octet[3],
285                                                 address.ether_addr_octet[4],
286                                                 address.ether_addr_octet[5]);
287
288         snprintf(str, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
289                                                 address.ether_addr_octet[0],
290                                                 address.ether_addr_octet[1],
291                                                 address.ether_addr_octet[2],
292                                                 address.ether_addr_octet[3],
293                                                 address.ether_addr_octet[4],
294                                                 address.ether_addr_octet[5]);
295
296         switch (type) {
297         case ARPHRD_ETHER:
298         case ARPHRD_LOOPBACK:
299         case ARPHDR_PHONET_PIPE:
300         case ARPHRD_NONE:
301                 __vpn_ipconfig_newlink(index, type, flags,
302                                                         str, mtu, &stats);
303                 break;
304         }
305
306         if (memcmp(&address, &compare, ETH_ALEN) != 0)
307                 connman_info("%s {newlink} index %d address %s mtu %u",
308                                                 ifname, index, str, mtu);
309
310         if (operstate != 0xff)
311                 connman_info("%s {newlink} index %d operstate %u <%s>",
312                                                 ifname, index, operstate,
313                                                 operstate2str(operstate));
314
315         interface = g_hash_table_lookup(interface_list, GINT_TO_POINTER(index));
316         if (!interface) {
317                 interface = g_new0(struct interface_data, 1);
318                 interface->index = index;
319                 interface->ident = g_strdup(ident);
320
321                 g_hash_table_insert(interface_list,
322                                         GINT_TO_POINTER(index), interface);
323         }
324
325         for (list = rtnl_list; list; list = list->next) {
326                 struct vpn_rtnl *rtnl = list->data;
327
328                 if (rtnl->newlink)
329                         rtnl->newlink(type, index, flags, change);
330         }
331
332         for (list = watch_list; list; list = list->next) {
333                 struct watch_data *watch = list->data;
334
335                 if (watch->index != index)
336                         continue;
337
338                 if (watch->newlink)
339                         watch->newlink(flags, change, watch->user_data);
340         }
341 }
342
343 static void process_dellink(unsigned short type, int index, unsigned flags,
344                         unsigned change, struct ifinfomsg *msg, int bytes)
345 {
346         struct rtnl_link_stats stats;
347         unsigned char operstate = 0xff;
348         const char *ifname = NULL;
349         GSList *list;
350
351         memset(&stats, 0, sizeof(stats));
352         extract_link(msg, bytes, NULL, &ifname, NULL, &operstate, &stats);
353
354         if (operstate != 0xff)
355                 connman_info("%s {dellink} index %d operstate %u <%s>",
356                                                 ifname, index, operstate,
357                                                 operstate2str(operstate));
358
359         for (list = rtnl_list; list; list = list->next) {
360                 struct vpn_rtnl *rtnl = list->data;
361
362                 if (rtnl->dellink)
363                         rtnl->dellink(type, index, flags, change);
364         }
365
366         switch (type) {
367         case ARPHRD_ETHER:
368         case ARPHRD_LOOPBACK:
369         case ARPHRD_NONE:
370                 __vpn_ipconfig_dellink(index, &stats);
371                 break;
372         }
373
374         g_hash_table_remove(interface_list, GINT_TO_POINTER(index));
375 }
376
377 static void extract_ipv4_route(struct rtmsg *msg, int bytes, int *index,
378                                                 struct in_addr *dst,
379                                                 struct in_addr *gateway)
380 {
381         struct rtattr *attr;
382
383         for (attr = RTM_RTA(msg); RTA_OK(attr, bytes);
384                                         attr = RTA_NEXT(attr, bytes)) {
385                 switch (attr->rta_type) {
386                 case RTA_DST:
387                         if (dst)
388                                 *dst = *((struct in_addr *) RTA_DATA(attr));
389                         break;
390                 case RTA_GATEWAY:
391                         if (gateway)
392                                 *gateway = *((struct in_addr *) RTA_DATA(attr));
393                         break;
394                 case RTA_OIF:
395                         if (index)
396                                 *index = *((int *) RTA_DATA(attr));
397                         break;
398                 }
399         }
400 }
401
402 static void extract_ipv6_route(struct rtmsg *msg, int bytes, int *index,
403                                                 struct in6_addr *dst,
404                                                 struct in6_addr *gateway)
405 {
406         struct rtattr *attr;
407
408         for (attr = RTM_RTA(msg); RTA_OK(attr, bytes);
409                                         attr = RTA_NEXT(attr, bytes)) {
410                 switch (attr->rta_type) {
411                 case RTA_DST:
412                         if (dst)
413                                 *dst = *((struct in6_addr *) RTA_DATA(attr));
414                         break;
415                 case RTA_GATEWAY:
416                         if (gateway)
417                                 *gateway =
418                                         *((struct in6_addr *) RTA_DATA(attr));
419                         break;
420                 case RTA_OIF:
421                         if (index)
422                                 *index = *((int *) RTA_DATA(attr));
423                         break;
424                 }
425         }
426 }
427
428 static void process_newroute(unsigned char family, unsigned char scope,
429                                                 struct rtmsg *msg, int bytes)
430 {
431         GSList *list;
432         char dststr[INET6_ADDRSTRLEN], gatewaystr[INET6_ADDRSTRLEN];
433         int index = -1;
434
435         if (family == AF_INET) {
436                 struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY };
437
438                 extract_ipv4_route(msg, bytes, &index, &dst, &gateway);
439
440                 inet_ntop(family, &dst, dststr, sizeof(dststr));
441                 inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr));
442
443                 /* skip host specific routes */
444                 if (scope != RT_SCOPE_UNIVERSE &&
445                         !(scope == RT_SCOPE_LINK && dst.s_addr == INADDR_ANY))
446                         return;
447
448                 if (dst.s_addr != INADDR_ANY)
449                         return;
450
451         } else if (family == AF_INET6) {
452                 struct in6_addr dst = IN6ADDR_ANY_INIT,
453                                 gateway = IN6ADDR_ANY_INIT;
454
455                 extract_ipv6_route(msg, bytes, &index, &dst, &gateway);
456
457                 inet_ntop(family, &dst, dststr, sizeof(dststr));
458                 inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr));
459
460                 /* skip host specific routes */
461                 if (scope != RT_SCOPE_UNIVERSE &&
462                         !(scope == RT_SCOPE_LINK &&
463                                 IN6_IS_ADDR_UNSPECIFIED(&dst)))
464                         return;
465
466                 if (!IN6_IS_ADDR_UNSPECIFIED(&dst))
467                         return;
468         } else
469                 return;
470
471         for (list = rtnl_list; list; list = list->next) {
472                 struct vpn_rtnl *rtnl = list->data;
473
474                 if (rtnl->newgateway)
475                         rtnl->newgateway(index, gatewaystr);
476         }
477 }
478
479 static void process_delroute(unsigned char family, unsigned char scope,
480                                                 struct rtmsg *msg, int bytes)
481 {
482         GSList *list;
483         char dststr[INET6_ADDRSTRLEN], gatewaystr[INET6_ADDRSTRLEN];
484         int index = -1;
485
486         if (family == AF_INET) {
487                 struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY };
488
489                 extract_ipv4_route(msg, bytes, &index, &dst, &gateway);
490
491                 inet_ntop(family, &dst, dststr, sizeof(dststr));
492                 inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr));
493
494                 /* skip host specific routes */
495                 if (scope != RT_SCOPE_UNIVERSE &&
496                         !(scope == RT_SCOPE_LINK && dst.s_addr == INADDR_ANY))
497                         return;
498
499                 if (dst.s_addr != INADDR_ANY)
500                         return;
501
502         }  else if (family == AF_INET6) {
503                 struct in6_addr dst = IN6ADDR_ANY_INIT,
504                                 gateway = IN6ADDR_ANY_INIT;
505
506                 extract_ipv6_route(msg, bytes, &index, &dst, &gateway);
507
508                 inet_ntop(family, &dst, dststr, sizeof(dststr));
509                 inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr));
510
511                 /* skip host specific routes */
512                 if (scope != RT_SCOPE_UNIVERSE &&
513                         !(scope == RT_SCOPE_LINK &&
514                                 IN6_IS_ADDR_UNSPECIFIED(&dst)))
515                         return;
516
517                 if (!IN6_IS_ADDR_UNSPECIFIED(&dst))
518                         return;
519         } else
520                 return;
521
522         for (list = rtnl_list; list; list = list->next) {
523                 struct vpn_rtnl *rtnl = list->data;
524
525                 if (rtnl->delgateway)
526                         rtnl->delgateway(index, gatewaystr);
527         }
528 }
529
530 static inline void print_ether(struct rtattr *attr, const char *name)
531 {
532         int len = (int) RTA_PAYLOAD(attr);
533
534         if (len == ETH_ALEN) {
535                 struct ether_addr eth;
536                 memcpy(&eth, RTA_DATA(attr), ETH_ALEN);
537                 print("  attr %s (len %d) %s\n", name, len, ether_ntoa(&eth));
538         } else
539                 print("  attr %s (len %d)\n", name, len);
540 }
541
542 static inline void print_inet(struct rtattr *attr, const char *name,
543                                                         unsigned char family)
544 {
545         int len = (int) RTA_PAYLOAD(attr);
546
547         if (family == AF_INET && len == sizeof(struct in_addr)) {
548                 struct in_addr addr;
549                 addr = *((struct in_addr *) RTA_DATA(attr));
550                 print("  attr %s (len %d) %s\n", name, len, inet_ntoa(addr));
551         } else
552                 print("  attr %s (len %d)\n", name, len);
553 }
554
555 static inline void print_string(struct rtattr *attr, const char *name)
556 {
557         print("  attr %s (len %d) %s\n", name, (int) RTA_PAYLOAD(attr),
558                                                 (char *) RTA_DATA(attr));
559 }
560
561 static inline void print_byte(struct rtattr *attr, const char *name)
562 {
563         print("  attr %s (len %d) 0x%02x\n", name, (int) RTA_PAYLOAD(attr),
564                                         *((unsigned char *) RTA_DATA(attr)));
565 }
566
567 static inline void print_integer(struct rtattr *attr, const char *name)
568 {
569         print("  attr %s (len %d) %d\n", name, (int) RTA_PAYLOAD(attr),
570                                                 *((int *) RTA_DATA(attr)));
571 }
572
573 static inline void print_attr(struct rtattr *attr, const char *name)
574 {
575         int len = (int) RTA_PAYLOAD(attr);
576
577         if (name && len > 0)
578                 print("  attr %s (len %d)\n", name, len);
579         else
580                 print("  attr %d (len %d)\n", attr->rta_type, len);
581 }
582
583 static void rtnl_link(struct nlmsghdr *hdr)
584 {
585         struct ifinfomsg *msg;
586         struct rtattr *attr;
587         int bytes;
588
589         msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
590         bytes = IFLA_PAYLOAD(hdr);
591
592         print("ifi_index %d ifi_flags 0x%04x", msg->ifi_index, msg->ifi_flags);
593
594         for (attr = IFLA_RTA(msg); RTA_OK(attr, bytes);
595                                         attr = RTA_NEXT(attr, bytes)) {
596                 switch (attr->rta_type) {
597                 case IFLA_ADDRESS:
598                         print_ether(attr, "address");
599                         break;
600                 case IFLA_BROADCAST:
601                         print_ether(attr, "broadcast");
602                         break;
603                 case IFLA_IFNAME:
604                         print_string(attr, "ifname");
605                         break;
606                 case IFLA_MTU:
607                         print_integer(attr, "mtu");
608                         break;
609                 case IFLA_LINK:
610                         print_attr(attr, "link");
611                         break;
612                 case IFLA_QDISC:
613                         print_attr(attr, "qdisc");
614                         break;
615                 case IFLA_STATS:
616                         print_attr(attr, "stats");
617                         break;
618                 case IFLA_COST:
619                         print_attr(attr, "cost");
620                         break;
621                 case IFLA_PRIORITY:
622                         print_attr(attr, "priority");
623                         break;
624                 case IFLA_MASTER:
625                         print_attr(attr, "master");
626                         break;
627                 case IFLA_WIRELESS:
628                         print_attr(attr, "wireless");
629                         break;
630                 case IFLA_PROTINFO:
631                         print_attr(attr, "protinfo");
632                         break;
633                 case IFLA_TXQLEN:
634                         print_integer(attr, "txqlen");
635                         break;
636                 case IFLA_MAP:
637                         print_attr(attr, "map");
638                         break;
639                 case IFLA_WEIGHT:
640                         print_attr(attr, "weight");
641                         break;
642                 case IFLA_OPERSTATE:
643                         print_byte(attr, "operstate");
644                         break;
645                 case IFLA_LINKMODE:
646                         print_byte(attr, "linkmode");
647                         break;
648                 default:
649                         print_attr(attr, NULL);
650                         break;
651                 }
652         }
653 }
654
655 static void rtnl_newlink(struct nlmsghdr *hdr)
656 {
657         struct ifinfomsg *msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
658
659         rtnl_link(hdr);
660
661         process_newlink(msg->ifi_type, msg->ifi_index, msg->ifi_flags,
662                                 msg->ifi_change, msg, IFA_PAYLOAD(hdr));
663 }
664
665 static void rtnl_dellink(struct nlmsghdr *hdr)
666 {
667         struct ifinfomsg *msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
668
669         rtnl_link(hdr);
670
671         process_dellink(msg->ifi_type, msg->ifi_index, msg->ifi_flags,
672                                 msg->ifi_change, msg, IFA_PAYLOAD(hdr));
673 }
674
675 static void rtnl_route(struct nlmsghdr *hdr)
676 {
677         struct rtmsg *msg;
678         struct rtattr *attr;
679         int bytes;
680
681         msg = (struct rtmsg *) NLMSG_DATA(hdr);
682         bytes = RTM_PAYLOAD(hdr);
683
684         print("rtm_family %d rtm_table %d rtm_protocol %d",
685                         msg->rtm_family, msg->rtm_table, msg->rtm_protocol);
686         print("rtm_scope %d rtm_type %d rtm_flags 0x%04x",
687                                 msg->rtm_scope, msg->rtm_type, msg->rtm_flags);
688
689         for (attr = RTM_RTA(msg); RTA_OK(attr, bytes);
690                                         attr = RTA_NEXT(attr, bytes)) {
691                 switch (attr->rta_type) {
692                 case RTA_DST:
693                         print_inet(attr, "dst", msg->rtm_family);
694                         break;
695                 case RTA_SRC:
696                         print_inet(attr, "src", msg->rtm_family);
697                         break;
698                 case RTA_IIF:
699                         print_string(attr, "iif");
700                         break;
701                 case RTA_OIF:
702                         print_integer(attr, "oif");
703                         break;
704                 case RTA_GATEWAY:
705                         print_inet(attr, "gateway", msg->rtm_family);
706                         break;
707                 case RTA_PRIORITY:
708                         print_attr(attr, "priority");
709                         break;
710                 case RTA_PREFSRC:
711                         print_inet(attr, "prefsrc", msg->rtm_family);
712                         break;
713                 case RTA_METRICS:
714                         print_attr(attr, "metrics");
715                         break;
716                 case RTA_TABLE:
717                         print_integer(attr, "table");
718                         break;
719                 default:
720                         print_attr(attr, NULL);
721                         break;
722                 }
723         }
724 }
725
726 static bool is_route_rtmsg(struct rtmsg *msg)
727 {
728
729         if (msg->rtm_table != RT_TABLE_MAIN)
730                 return false;
731
732         if (msg->rtm_protocol != RTPROT_BOOT &&
733                         msg->rtm_protocol != RTPROT_KERNEL)
734                 return false;
735
736         if (msg->rtm_type != RTN_UNICAST)
737                 return false;
738
739         return true;
740 }
741
742 static void rtnl_newroute(struct nlmsghdr *hdr)
743 {
744         struct rtmsg *msg = (struct rtmsg *) NLMSG_DATA(hdr);
745
746         rtnl_route(hdr);
747
748         if (is_route_rtmsg(msg))
749                 process_newroute(msg->rtm_family, msg->rtm_scope,
750                                                 msg, RTM_PAYLOAD(hdr));
751 }
752
753 static void rtnl_delroute(struct nlmsghdr *hdr)
754 {
755         struct rtmsg *msg = (struct rtmsg *) NLMSG_DATA(hdr);
756
757         rtnl_route(hdr);
758
759         if (is_route_rtmsg(msg))
760                 process_delroute(msg->rtm_family, msg->rtm_scope,
761                                                 msg, RTM_PAYLOAD(hdr));
762 }
763
764 static const char *type2string(uint16_t type)
765 {
766         switch (type) {
767         case NLMSG_NOOP:
768                 return "NOOP";
769         case NLMSG_ERROR:
770                 return "ERROR";
771         case NLMSG_DONE:
772                 return "DONE";
773         case NLMSG_OVERRUN:
774                 return "OVERRUN";
775         case RTM_GETLINK:
776                 return "GETLINK";
777         case RTM_NEWLINK:
778                 return "NEWLINK";
779         case RTM_DELLINK:
780                 return "DELLINK";
781         case RTM_NEWADDR:
782                 return "NEWADDR";
783         case RTM_DELADDR:
784                 return "DELADDR";
785         case RTM_GETROUTE:
786                 return "GETROUTE";
787         case RTM_NEWROUTE:
788                 return "NEWROUTE";
789         case RTM_DELROUTE:
790                 return "DELROUTE";
791         case RTM_NEWNDUSEROPT:
792                 return "NEWNDUSEROPT";
793         default:
794                 return "UNKNOWN";
795         }
796 }
797
798 static GIOChannel *channel = NULL;
799
800 struct rtnl_request {
801         struct nlmsghdr hdr;
802         struct rtgenmsg msg;
803 };
804 #define RTNL_REQUEST_SIZE  (sizeof(struct nlmsghdr) + sizeof(struct rtgenmsg))
805
806 static GSList *request_list = NULL;
807 static guint32 request_seq = 0;
808
809 static struct rtnl_request *find_request(guint32 seq)
810 {
811         GSList *list;
812
813         for (list = request_list; list; list = list->next) {
814                 struct rtnl_request *req = list->data;
815
816                 if (req->hdr.nlmsg_seq == seq)
817                         return req;
818         }
819
820         return NULL;
821 }
822
823 static int send_request(struct rtnl_request *req)
824 {
825         struct sockaddr_nl addr;
826         int sk;
827
828         debug("%s len %d type %d flags 0x%04x seq %d",
829                                 type2string(req->hdr.nlmsg_type),
830                                 req->hdr.nlmsg_len, req->hdr.nlmsg_type,
831                                 req->hdr.nlmsg_flags, req->hdr.nlmsg_seq);
832
833         sk = g_io_channel_unix_get_fd(channel);
834
835         memset(&addr, 0, sizeof(addr));
836         addr.nl_family = AF_NETLINK;
837
838         return sendto(sk, req, req->hdr.nlmsg_len, 0,
839                                 (struct sockaddr *) &addr, sizeof(addr));
840 }
841
842 static int queue_request(struct rtnl_request *req)
843 {
844         request_list = g_slist_append(request_list, req);
845
846         if (g_slist_length(request_list) > 1)
847                 return 0;
848
849         return send_request(req);
850 }
851
852 static int process_response(guint32 seq)
853 {
854         struct rtnl_request *req;
855
856         debug("seq %d", seq);
857
858         req = find_request(seq);
859         if (req) {
860                 request_list = g_slist_remove(request_list, req);
861                 g_free(req);
862         }
863
864         req = g_slist_nth_data(request_list, 0);
865         if (!req)
866                 return 0;
867
868         return send_request(req);
869 }
870
871 static void rtnl_message(void *buf, size_t len)
872 {
873         debug("buf %p len %zd", buf, len);
874
875         while (len > 0) {
876                 struct nlmsghdr *hdr = buf;
877                 struct nlmsgerr *err;
878
879                 if (!NLMSG_OK(hdr, len))
880                         break;
881
882                 debug("%s len %u type %u flags 0x%04x seq %u pid %u",
883                                         type2string(hdr->nlmsg_type),
884                                         hdr->nlmsg_len, hdr->nlmsg_type,
885                                         hdr->nlmsg_flags, hdr->nlmsg_seq,
886                                         hdr->nlmsg_pid);
887
888                 switch (hdr->nlmsg_type) {
889                 case NLMSG_NOOP:
890                 case NLMSG_OVERRUN:
891                         return;
892                 case NLMSG_DONE:
893                         process_response(hdr->nlmsg_seq);
894                         return;
895                 case NLMSG_ERROR:
896                         err = NLMSG_DATA(hdr);
897                         DBG("error %d (%s)", -err->error,
898                                                 strerror(-err->error));
899                         return;
900                 case RTM_NEWLINK:
901                         rtnl_newlink(hdr);
902                         break;
903                 case RTM_DELLINK:
904                         rtnl_dellink(hdr);
905                         break;
906                 case RTM_NEWADDR:
907                         break;
908                 case RTM_DELADDR:
909                         break;
910                 case RTM_NEWROUTE:
911                         rtnl_newroute(hdr);
912                         break;
913                 case RTM_DELROUTE:
914                         rtnl_delroute(hdr);
915                         break;
916                 }
917
918                 len -= hdr->nlmsg_len;
919                 buf += hdr->nlmsg_len;
920         }
921 }
922
923 static gboolean netlink_event(GIOChannel *chan, GIOCondition cond, gpointer data)
924 {
925         unsigned char buf[4096];
926         struct sockaddr_nl nladdr;
927         socklen_t addr_len = sizeof(nladdr);
928         ssize_t status;
929         int fd;
930
931         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
932                 return FALSE;
933
934         memset(buf, 0, sizeof(buf));
935         memset(&nladdr, 0, sizeof(nladdr));
936
937         fd = g_io_channel_unix_get_fd(chan);
938
939         status = recvfrom(fd, buf, sizeof(buf), 0,
940                        (struct sockaddr *) &nladdr, &addr_len);
941         if (status < 0) {
942                 if (errno == EINTR || errno == EAGAIN)
943                         return TRUE;
944
945                 return FALSE;
946         }
947
948         if (status == 0)
949                 return FALSE;
950
951         if (nladdr.nl_pid != 0) { /* not sent by kernel, ignore */
952                 DBG("Received msg from %u, ignoring it", nladdr.nl_pid);
953                 return TRUE;
954         }
955
956         rtnl_message(buf, status);
957
958         return TRUE;
959 }
960
961 static int send_getlink(void)
962 {
963         struct rtnl_request *req;
964
965         debug("");
966
967         req = g_try_malloc0(RTNL_REQUEST_SIZE);
968         if (!req)
969                 return -ENOMEM;
970
971         req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
972         req->hdr.nlmsg_type = RTM_GETLINK;
973         req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
974         req->hdr.nlmsg_pid = 0;
975         req->hdr.nlmsg_seq = request_seq++;
976         req->msg.rtgen_family = AF_INET;
977
978         return queue_request(req);
979 }
980
981 static int send_getaddr(void)
982 {
983         struct rtnl_request *req;
984
985         debug("");
986
987         req = g_try_malloc0(RTNL_REQUEST_SIZE);
988         if (!req)
989                 return -ENOMEM;
990
991         req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
992         req->hdr.nlmsg_type = RTM_GETADDR;
993         req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
994         req->hdr.nlmsg_pid = 0;
995         req->hdr.nlmsg_seq = request_seq++;
996         req->msg.rtgen_family = AF_INET;
997
998         return queue_request(req);
999 }
1000
1001 static int send_getroute(void)
1002 {
1003         struct rtnl_request *req;
1004
1005         debug("");
1006
1007         req = g_try_malloc0(RTNL_REQUEST_SIZE);
1008         if (!req)
1009                 return -ENOMEM;
1010
1011         req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
1012         req->hdr.nlmsg_type = RTM_GETROUTE;
1013         req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1014         req->hdr.nlmsg_pid = 0;
1015         req->hdr.nlmsg_seq = request_seq++;
1016         req->msg.rtgen_family = AF_INET;
1017
1018         return queue_request(req);
1019 }
1020
1021 static gboolean update_timeout_cb(gpointer user_data)
1022 {
1023         __vpn_rtnl_request_update();
1024
1025         return TRUE;
1026 }
1027
1028 static void update_interval_callback(guint min)
1029 {
1030         if (update_timeout > 0)
1031                 g_source_remove(update_timeout);
1032
1033         if (min < G_MAXUINT) {
1034                 update_interval = min;
1035                 update_timeout = g_timeout_add_seconds(update_interval,
1036                                                 update_timeout_cb, NULL);
1037         } else {
1038                 update_timeout = 0;
1039                 update_interval = G_MAXUINT;
1040         }
1041 }
1042
1043 static gint compare_interval(gconstpointer a, gconstpointer b)
1044 {
1045         guint val_a = GPOINTER_TO_UINT(a);
1046         guint val_b = GPOINTER_TO_UINT(b);
1047
1048         return val_a - val_b;
1049 }
1050
1051 unsigned int __vpn_rtnl_update_interval_add(unsigned int interval)
1052 {
1053         guint min;
1054
1055         if (interval == 0)
1056                 return 0;
1057
1058         update_list = g_slist_insert_sorted(update_list,
1059                         GUINT_TO_POINTER(interval), compare_interval);
1060
1061         min = GPOINTER_TO_UINT(g_slist_nth_data(update_list, 0));
1062         if (min < update_interval) {
1063                 update_interval_callback(min);
1064                 __vpn_rtnl_request_update();
1065         }
1066
1067         return update_interval;
1068 }
1069
1070 unsigned int __vpn_rtnl_update_interval_remove(unsigned int interval)
1071 {
1072         guint min = G_MAXUINT;
1073
1074         if (interval == 0)
1075                 return 0;
1076
1077         update_list = g_slist_remove(update_list, GINT_TO_POINTER(interval));
1078
1079         if (update_list)
1080                 min = GPOINTER_TO_UINT(g_slist_nth_data(update_list, 0));
1081
1082         if (min > update_interval)
1083                 update_interval_callback(min);
1084
1085         return min;
1086 }
1087
1088 int __vpn_rtnl_request_update(void)
1089 {
1090         return send_getlink();
1091 }
1092
1093 int __vpn_rtnl_init(void)
1094 {
1095         struct sockaddr_nl addr;
1096         int sk;
1097
1098         DBG("");
1099
1100         interface_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1101                                                         NULL, free_interface);
1102
1103         sk = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_ROUTE);
1104         if (sk < 0)
1105                 return -1;
1106
1107         memset(&addr, 0, sizeof(addr));
1108         addr.nl_family = AF_NETLINK;
1109         addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE |
1110                                 RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE |
1111                                 (1<<(RTNLGRP_ND_USEROPT-1));
1112
1113         if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1114                 close(sk);
1115                 return -1;
1116         }
1117
1118         channel = g_io_channel_unix_new(sk);
1119         g_io_channel_set_close_on_unref(channel, TRUE);
1120
1121         g_io_channel_set_encoding(channel, NULL, NULL);
1122         g_io_channel_set_buffered(channel, FALSE);
1123
1124         g_io_add_watch(channel, G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
1125                                                         netlink_event, NULL);
1126
1127         return 0;
1128 }
1129
1130 void __vpn_rtnl_start(void)
1131 {
1132         DBG("");
1133
1134         send_getlink();
1135         send_getaddr();
1136         send_getroute();
1137 }
1138
1139 void __vpn_rtnl_cleanup(void)
1140 {
1141         GSList *list;
1142
1143         DBG("");
1144
1145         for (list = watch_list; list; list = list->next) {
1146                 struct watch_data *watch = list->data;
1147
1148                 DBG("removing watch %d", watch->id);
1149
1150                 g_free(watch);
1151                 list->data = NULL;
1152         }
1153
1154         g_slist_free(watch_list);
1155         watch_list = NULL;
1156
1157         g_slist_free(update_list);
1158         update_list = NULL;
1159
1160         for (list = request_list; list; list = list->next) {
1161                 struct rtnl_request *req = list->data;
1162
1163                 debug("%s len %d type %d flags 0x%04x seq %d",
1164                                 type2string(req->hdr.nlmsg_type),
1165                                 req->hdr.nlmsg_len, req->hdr.nlmsg_type,
1166                                 req->hdr.nlmsg_flags, req->hdr.nlmsg_seq);
1167
1168                 g_free(req);
1169                 list->data = NULL;
1170         }
1171
1172         g_slist_free(request_list);
1173         request_list = NULL;
1174
1175         g_io_channel_shutdown(channel, TRUE, NULL);
1176         g_io_channel_unref(channel);
1177
1178         channel = NULL;
1179
1180         g_hash_table_destroy(interface_list);
1181 }