Fix PASSED_TO_PROC_AFTER_FREE.EX
[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 #define RTNL_REQUEST_SIZE (NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(struct rtgenmsg)))
801
802 static GSList *request_list = NULL;
803 static guint32 request_seq = 0;
804
805 static struct nlmsghdr *find_request(guint32 seq)
806 {
807         GSList *list;
808
809         for (list = request_list; list; list = list->next) {
810                 struct nlmsghdr *hdr = list->data;
811
812                 if (hdr->nlmsg_seq == seq)
813                         return hdr;
814         }
815
816         return NULL;
817 }
818
819 static int send_request(struct nlmsghdr *hdr)
820 {
821         struct sockaddr_nl addr;
822         int sk;
823
824         debug("%s len %d type %d flags 0x%04x seq %d",
825                                 type2string(hdr->nlmsg_type),
826                                 hdr->nlmsg_len, hdr->nlmsg_type,
827                                 hdr->nlmsg_flags, hdr->nlmsg_seq);
828
829         sk = g_io_channel_unix_get_fd(channel);
830
831         memset(&addr, 0, sizeof(addr));
832         addr.nl_family = AF_NETLINK;
833
834         return sendto(sk, hdr, hdr->nlmsg_len, 0,
835                                 (struct sockaddr *) &addr, sizeof(addr));
836 }
837
838 static int queue_request(struct nlmsghdr *hdr)
839 {
840         request_list = g_slist_append(request_list, hdr);
841
842         if (g_slist_length(request_list) > 1)
843                 return 0;
844
845         return send_request(hdr);
846 }
847
848 static int process_response(guint32 seq)
849 {
850         struct nlmsghdr *hdr;
851
852         debug("seq %d", seq);
853
854         hdr = find_request(seq);
855         if (hdr) {
856                 request_list = g_slist_remove(request_list, hdr);
857                 g_free(hdr);
858         }
859
860         hdr = g_slist_nth_data(request_list, 0);
861         if (!hdr)
862                 return 0;
863
864         return send_request(hdr);
865 }
866
867 static void rtnl_message(void *buf, size_t len)
868 {
869         debug("buf %p len %zd", buf, len);
870
871         while (len > 0) {
872                 struct nlmsghdr *hdr = buf;
873                 struct nlmsgerr *err;
874
875                 if (!NLMSG_OK(hdr, len))
876                         break;
877
878                 debug("%s len %u type %u flags 0x%04x seq %u pid %u",
879                                         type2string(hdr->nlmsg_type),
880                                         hdr->nlmsg_len, hdr->nlmsg_type,
881                                         hdr->nlmsg_flags, hdr->nlmsg_seq,
882                                         hdr->nlmsg_pid);
883
884                 switch (hdr->nlmsg_type) {
885                 case NLMSG_NOOP:
886                 case NLMSG_OVERRUN:
887                         return;
888                 case NLMSG_DONE:
889                         process_response(hdr->nlmsg_seq);
890                         return;
891                 case NLMSG_ERROR:
892                         err = NLMSG_DATA(hdr);
893                         DBG("error %d (%s)", -err->error,
894                                                 strerror(-err->error));
895                         return;
896                 case RTM_NEWLINK:
897                         rtnl_newlink(hdr);
898                         break;
899                 case RTM_DELLINK:
900                         rtnl_dellink(hdr);
901                         break;
902                 case RTM_NEWADDR:
903                         break;
904                 case RTM_DELADDR:
905                         break;
906                 case RTM_NEWROUTE:
907                         rtnl_newroute(hdr);
908                         break;
909                 case RTM_DELROUTE:
910                         rtnl_delroute(hdr);
911                         break;
912                 }
913
914                 len -= hdr->nlmsg_len;
915                 buf += hdr->nlmsg_len;
916         }
917 }
918
919 static gboolean netlink_event(GIOChannel *chan, GIOCondition cond, gpointer data)
920 {
921         unsigned char buf[4096];
922         struct sockaddr_nl nladdr;
923         socklen_t addr_len = sizeof(nladdr);
924         ssize_t status;
925         int fd;
926
927         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
928                 return FALSE;
929
930         memset(buf, 0, sizeof(buf));
931         memset(&nladdr, 0, sizeof(nladdr));
932
933         fd = g_io_channel_unix_get_fd(chan);
934
935         status = recvfrom(fd, buf, sizeof(buf), 0,
936                        (struct sockaddr *) &nladdr, &addr_len);
937         if (status < 0) {
938                 if (errno == EINTR || errno == EAGAIN)
939                         return TRUE;
940
941                 return FALSE;
942         }
943
944         if (status == 0)
945                 return FALSE;
946
947         if (nladdr.nl_pid != 0) { /* not sent by kernel, ignore */
948                 DBG("Received msg from %u, ignoring it", nladdr.nl_pid);
949                 return TRUE;
950         }
951
952         rtnl_message(buf, status);
953
954         return TRUE;
955 }
956
957 static int send_getlink(void)
958 {
959         struct nlmsghdr *hdr;
960         struct rtgenmsg *msg;
961
962         debug("");
963
964         hdr = g_malloc0(RTNL_REQUEST_SIZE);
965
966         hdr->nlmsg_len = RTNL_REQUEST_SIZE;
967         hdr->nlmsg_type = RTM_GETLINK;
968         hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
969         hdr->nlmsg_pid = 0;
970         hdr->nlmsg_seq = request_seq++;
971
972         msg = (struct rtgenmsg *) NLMSG_DATA(hdr);
973         msg->rtgen_family = AF_INET;
974
975         return queue_request(hdr);
976 }
977
978 static int send_getaddr(void)
979 {
980         struct nlmsghdr *hdr;
981         struct rtgenmsg *msg;
982
983         debug("");
984
985         hdr = g_malloc0(RTNL_REQUEST_SIZE);
986
987         hdr->nlmsg_len = RTNL_REQUEST_SIZE;
988         hdr->nlmsg_type = RTM_GETADDR;
989         hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
990         hdr->nlmsg_pid = 0;
991         hdr->nlmsg_seq = request_seq++;
992
993         msg = (struct rtgenmsg *) NLMSG_DATA(hdr);
994         msg->rtgen_family = AF_INET;
995
996         return queue_request(hdr);
997 }
998
999 static int send_getroute(void)
1000 {
1001         struct nlmsghdr *hdr;
1002         struct rtgenmsg *msg;
1003
1004         debug("");
1005
1006         hdr = g_malloc0(RTNL_REQUEST_SIZE);
1007
1008         hdr->nlmsg_len = RTNL_REQUEST_SIZE;
1009         hdr->nlmsg_type = RTM_GETROUTE;
1010         hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1011         hdr->nlmsg_pid = 0;
1012         hdr->nlmsg_seq = request_seq++;
1013
1014         msg = (struct rtgenmsg *) NLMSG_DATA(hdr);
1015         msg->rtgen_family = AF_INET;
1016
1017         return queue_request(hdr);
1018 }
1019
1020 static gboolean update_timeout_cb(gpointer user_data)
1021 {
1022         __vpn_rtnl_request_update();
1023
1024         return TRUE;
1025 }
1026
1027 static void update_interval_callback(guint min)
1028 {
1029         if (update_timeout > 0)
1030                 g_source_remove(update_timeout);
1031
1032         if (min < G_MAXUINT) {
1033                 update_interval = min;
1034                 update_timeout = g_timeout_add_seconds(update_interval,
1035                                                 update_timeout_cb, NULL);
1036         } else {
1037                 update_timeout = 0;
1038                 update_interval = G_MAXUINT;
1039         }
1040 }
1041
1042 static gint compare_interval(gconstpointer a, gconstpointer b)
1043 {
1044         guint val_a = GPOINTER_TO_UINT(a);
1045         guint val_b = GPOINTER_TO_UINT(b);
1046
1047         return val_a - val_b;
1048 }
1049
1050 unsigned int __vpn_rtnl_update_interval_add(unsigned int interval)
1051 {
1052         guint min;
1053
1054         if (interval == 0)
1055                 return 0;
1056
1057         update_list = g_slist_insert_sorted(update_list,
1058                         GUINT_TO_POINTER(interval), compare_interval);
1059
1060         min = GPOINTER_TO_UINT(g_slist_nth_data(update_list, 0));
1061         if (min < update_interval) {
1062                 update_interval_callback(min);
1063                 __vpn_rtnl_request_update();
1064         }
1065
1066         return update_interval;
1067 }
1068
1069 unsigned int __vpn_rtnl_update_interval_remove(unsigned int interval)
1070 {
1071         guint min = G_MAXUINT;
1072
1073         if (interval == 0)
1074                 return 0;
1075
1076         update_list = g_slist_remove(update_list, GINT_TO_POINTER(interval));
1077
1078         if (update_list)
1079                 min = GPOINTER_TO_UINT(g_slist_nth_data(update_list, 0));
1080
1081         if (min > update_interval)
1082                 update_interval_callback(min);
1083
1084         return min;
1085 }
1086
1087 int __vpn_rtnl_request_update(void)
1088 {
1089         return send_getlink();
1090 }
1091
1092 int __vpn_rtnl_init(void)
1093 {
1094         struct sockaddr_nl addr;
1095         int sk;
1096
1097         DBG("");
1098
1099         interface_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1100                                                         NULL, free_interface);
1101
1102         sk = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_ROUTE);
1103         if (sk < 0)
1104                 return -1;
1105
1106         memset(&addr, 0, sizeof(addr));
1107         addr.nl_family = AF_NETLINK;
1108         addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE |
1109                                 RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE |
1110                                 (1<<(RTNLGRP_ND_USEROPT-1));
1111
1112         if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1113                 close(sk);
1114                 return -1;
1115         }
1116
1117         channel = g_io_channel_unix_new(sk);
1118         g_io_channel_set_close_on_unref(channel, TRUE);
1119
1120         g_io_channel_set_encoding(channel, NULL, NULL);
1121         g_io_channel_set_buffered(channel, FALSE);
1122
1123         g_io_add_watch(channel, G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
1124                                                         netlink_event, NULL);
1125
1126         return 0;
1127 }
1128
1129 void __vpn_rtnl_start(void)
1130 {
1131         DBG("");
1132
1133         send_getlink();
1134         send_getaddr();
1135         send_getroute();
1136 }
1137
1138 void __vpn_rtnl_cleanup(void)
1139 {
1140         GSList *list;
1141
1142         DBG("");
1143
1144         for (list = watch_list; list; list = list->next) {
1145                 struct watch_data *watch = list->data;
1146
1147                 DBG("removing watch %d", watch->id);
1148
1149                 g_free(watch);
1150                 list->data = NULL;
1151         }
1152
1153         g_slist_free(watch_list);
1154         watch_list = NULL;
1155
1156         g_slist_free(update_list);
1157         update_list = NULL;
1158
1159         for (list = request_list; list; list = list->next) {
1160                 struct nlmsghdr *hdr = list->data;
1161
1162                 debug("%s len %d type %d flags 0x%04x seq %d",
1163                                 type2string(hdr->nlmsg_type),
1164                                 hdr->nlmsg_len, hdr->nlmsg_type,
1165                                 hdr->nlmsg_flags, hdr->nlmsg_seq);
1166
1167                 g_free(hdr);
1168                 list->data = NULL;
1169         }
1170
1171         g_slist_free(request_list);
1172         request_list = NULL;
1173
1174         g_io_channel_shutdown(channel, TRUE, NULL);
1175         g_io_channel_unref(channel);
1176
1177         channel = NULL;
1178
1179         g_hash_table_destroy(interface_list);
1180 }