Merge branch 'ipsec' into tizen
[platform/upstream/connman.git] / src / rtnl.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-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.h"
44
45 #ifndef ARPHDR_PHONET_PIPE
46 #define ARPHDR_PHONET_PIPE (821)
47 #endif
48
49 #if defined TIZEN_EXT
50 #ifndef ARPHDR_RMNET
51 #define ARPHDR_RMNET (530)
52 #endif
53 #endif
54
55 #define print(arg...) do { if (0) connman_info(arg); } while (0)
56 //#define print(arg...) connman_info(arg)
57
58 struct watch_data {
59         unsigned int id;
60         int index;
61         connman_rtnl_link_cb_t newlink;
62         void *user_data;
63 };
64
65 static GSList *watch_list = NULL;
66 static unsigned int watch_id = 0;
67
68 static GSList *update_list = NULL;
69 static guint update_interval = G_MAXUINT;
70 static guint update_timeout = 0;
71
72 struct interface_data {
73         int index;
74         char *ident;
75         enum connman_service_type service_type;
76         enum connman_device_type device_type;
77 };
78
79 static GHashTable *interface_list = NULL;
80
81 static void free_interface(gpointer data)
82 {
83         struct interface_data *interface = data;
84
85         __connman_technology_remove_interface(interface->service_type,
86                         interface->index, interface->ident);
87
88         g_free(interface->ident);
89         g_free(interface);
90 }
91
92 static bool ether_blacklisted(const char *name)
93 {
94         if (!name)
95                 return true;
96
97         if (__connman_device_isfiltered(name))
98                 return true;
99
100         return false;
101 }
102
103 #if !defined TIZEN_EXT
104 static bool wext_interface(char *ifname)
105 {
106         struct iwreq wrq;
107         int fd, err;
108
109         fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
110         if (fd < 0)
111                 return false;
112
113         memset(&wrq, 0, sizeof(wrq));
114         strncpy(wrq.ifr_name, ifname, sizeof(wrq.ifr_name) - 1);
115
116         err = ioctl(fd, SIOCGIWNAME, &wrq);
117
118         close(fd);
119
120         if (err < 0)
121                 return false;
122
123         return true;
124 }
125 #endif
126
127 #if defined TIZEN_EXT
128 static bool __connman_rtnl_is_cellular_device(const char *name)
129 {
130         char **pattern;
131         char **cellular_interfaces;
132
133         cellular_interfaces =
134                         connman_setting_get_string_list(
135                                         "NetworkCellularInterfaceList");
136         if (!cellular_interfaces)
137                 return false;
138
139         for (pattern = cellular_interfaces; *pattern; pattern++) {
140                 if (g_str_has_prefix(name, *pattern)) {
141                         DBG("Cellular interface: %s", name);
142                         return true;
143                 }
144         }
145
146         return false;
147 }
148 #endif
149
150 static void read_uevent(struct interface_data *interface)
151 {
152         char *filename, *name, line[128];
153         bool found_devtype;
154         FILE *f;
155
156         name = connman_inet_ifname(interface->index);
157
158 #if defined TIZEN_EXT
159         if (__connman_rtnl_is_cellular_device(name)) {
160                 interface->service_type = CONNMAN_SERVICE_TYPE_CELLULAR;
161                 interface->device_type = CONNMAN_DEVICE_TYPE_CELLULAR;
162                 return;
163         }
164 #endif
165
166         if (ether_blacklisted(name)) {
167                 interface->service_type = CONNMAN_SERVICE_TYPE_UNKNOWN;
168                 interface->device_type = CONNMAN_DEVICE_TYPE_UNKNOWN;
169         } else {
170                 interface->service_type = CONNMAN_SERVICE_TYPE_ETHERNET;
171                 interface->device_type = CONNMAN_DEVICE_TYPE_ETHERNET;
172         }
173
174         filename = g_strdup_printf("/sys/class/net/%s/uevent", name);
175
176         f = fopen(filename, "re");
177
178         g_free(filename);
179
180         if (!f) {
181                 interface->service_type = CONNMAN_SERVICE_TYPE_UNKNOWN;
182                 interface->device_type = CONNMAN_DEVICE_TYPE_UNKNOWN;
183                 goto out;
184         }
185
186         found_devtype = false;
187         while (fgets(line, sizeof(line), f)) {
188                 char *pos;
189
190                 pos = strchr(line, '\n');
191                 if (!pos)
192                         continue;
193                 pos[0] = '\0';
194
195                 if (strncmp(line, "DEVTYPE=", 8) != 0)
196                         continue;
197
198                 found_devtype = true;
199
200                 if (strcmp(line + 8, "wlan") == 0) {
201                         interface->service_type = CONNMAN_SERVICE_TYPE_WIFI;
202                         interface->device_type = CONNMAN_DEVICE_TYPE_WIFI;
203                 } else if (strcmp(line + 8, "wwan") == 0) {
204                         interface->service_type = CONNMAN_SERVICE_TYPE_CELLULAR;
205                         interface->device_type = CONNMAN_DEVICE_TYPE_CELLULAR;
206                 } else if (strcmp(line + 8, "bluetooth") == 0) {
207                         interface->service_type = CONNMAN_SERVICE_TYPE_BLUETOOTH;
208                         interface->device_type = CONNMAN_DEVICE_TYPE_BLUETOOTH;
209                 } else if (strcmp(line + 8, "gadget") == 0) {
210                         interface->service_type = CONNMAN_SERVICE_TYPE_GADGET;
211                         interface->device_type = CONNMAN_DEVICE_TYPE_GADGET;
212                 } else if (strcmp(line + 8, "vlan") == 0) {
213                         interface->service_type = CONNMAN_SERVICE_TYPE_ETHERNET;
214                         interface->device_type = CONNMAN_DEVICE_TYPE_ETHERNET;
215
216                 } else {
217                         interface->service_type = CONNMAN_SERVICE_TYPE_UNKNOWN;
218                         interface->device_type = CONNMAN_DEVICE_TYPE_UNKNOWN;
219                 }
220         }
221
222         fclose(f);
223
224         if (found_devtype)
225                 goto out;
226
227 #if !defined TIZEN_EXT
228         /* TIZEN does not use old wext interface */
229         /* We haven't got a DEVTYPE, let's check if it's a wireless device */
230         if (wext_interface(name)) {
231                 interface->service_type = CONNMAN_SERVICE_TYPE_WIFI;
232                 interface->device_type = CONNMAN_DEVICE_TYPE_WIFI;
233
234                 connman_error("%s runs an unsupported 802.11 driver", name);
235         }
236 #endif
237
238 out:
239         g_free(name);
240 }
241
242 enum connman_device_type __connman_rtnl_get_device_type(int index)
243 {
244         struct interface_data *interface;
245
246         interface = g_hash_table_lookup(interface_list,
247                                         GINT_TO_POINTER(index));
248         if (!interface)
249                 return CONNMAN_DEVICE_TYPE_UNKNOWN;
250
251         return interface->device_type;
252 }
253
254 /**
255  * connman_rtnl_add_newlink_watch:
256  * @index: network device index
257  * @callback: callback function
258  * @user_data: callback data;
259  *
260  * Add a new RTNL watch for newlink events
261  *
262  * Returns: %0 on failure and a unique id on success
263  */
264 unsigned int connman_rtnl_add_newlink_watch(int index,
265                         connman_rtnl_link_cb_t callback, void *user_data)
266 {
267         struct watch_data *watch;
268
269         watch = g_try_new0(struct watch_data, 1);
270         if (!watch)
271                 return 0;
272
273         watch->id = ++watch_id;
274         watch->index = index;
275
276         watch->newlink = callback;
277         watch->user_data = user_data;
278
279         watch_list = g_slist_prepend(watch_list, watch);
280
281         DBG("id %d", watch->id);
282
283         if (callback) {
284                 unsigned int flags = __connman_ipconfig_get_flags_from_index(index);
285
286                 if (flags > 0)
287                         callback(flags, 0, user_data);
288         }
289
290         return watch->id;
291 }
292
293 /**
294  * connman_rtnl_remove_watch:
295  * @id: watch identifier
296  *
297  * Remove the RTNL watch for the identifier
298  */
299 void connman_rtnl_remove_watch(unsigned int id)
300 {
301         GSList *list;
302
303         DBG("id %d", id);
304
305         if (id == 0)
306                 return;
307
308         for (list = watch_list; list; list = list->next) {
309                 struct watch_data *watch = list->data;
310
311                 if (watch->id  == id) {
312                         watch_list = g_slist_remove(watch_list, watch);
313                         g_free(watch);
314                         break;
315                 }
316         }
317 }
318
319 static void trigger_rtnl(int index, void *user_data)
320 {
321         struct connman_rtnl *rtnl = user_data;
322
323         if (rtnl->newlink) {
324                 unsigned short type = __connman_ipconfig_get_type_from_index(index);
325                 unsigned int flags = __connman_ipconfig_get_flags_from_index(index);
326
327                 rtnl->newlink(type, index, flags, 0);
328         }
329
330         if (rtnl->newgateway) {
331                 const char *gateway =
332                         __connman_ipconfig_get_gateway_from_index(index,
333                                         CONNMAN_IPCONFIG_TYPE_ALL);
334
335                 if (gateway)
336                         rtnl->newgateway(index, gateway);
337         }
338 }
339
340 static GSList *rtnl_list = NULL;
341
342 static gint compare_priority(gconstpointer a, gconstpointer b)
343 {
344         const struct connman_rtnl *rtnl1 = a;
345         const struct connman_rtnl *rtnl2 = b;
346
347         return rtnl2->priority - rtnl1->priority;
348 }
349
350 /**
351  * connman_rtnl_register:
352  * @rtnl: RTNL module
353  *
354  * Register a new RTNL module
355  *
356  * Returns: %0 on success
357  */
358 int connman_rtnl_register(struct connman_rtnl *rtnl)
359 {
360         DBG("rtnl %p name %s", rtnl, rtnl->name);
361
362         rtnl_list = g_slist_insert_sorted(rtnl_list, rtnl,
363                                                         compare_priority);
364
365         __connman_ipconfig_foreach(trigger_rtnl, rtnl);
366
367         return 0;
368 }
369
370 /**
371  * connman_rtnl_unregister:
372  * @rtnl: RTNL module
373  *
374  * Remove a previously registered RTNL module
375  */
376 void connman_rtnl_unregister(struct connman_rtnl *rtnl)
377 {
378         DBG("rtnl %p name %s", rtnl, rtnl->name);
379
380         rtnl_list = g_slist_remove(rtnl_list, rtnl);
381 }
382
383 static const char *operstate2str(unsigned char operstate)
384 {
385         switch (operstate) {
386         case IF_OPER_UNKNOWN:
387                 return "UNKNOWN";
388         case IF_OPER_NOTPRESENT:
389                 return "NOT-PRESENT";
390         case IF_OPER_DOWN:
391                 return "DOWN";
392         case IF_OPER_LOWERLAYERDOWN:
393                 return "LOWER-LAYER-DOWN";
394         case IF_OPER_TESTING:
395                 return "TESTING";
396         case IF_OPER_DORMANT:
397                 return "DORMANT";
398         case IF_OPER_UP:
399                 return "UP";
400         }
401
402         return "";
403 }
404
405 static bool extract_link(struct ifinfomsg *msg, int bytes,
406                                 struct ether_addr *address, const char **ifname,
407                                 unsigned int *mtu, unsigned char *operstate,
408                                 struct rtnl_link_stats *stats)
409 {
410         struct rtattr *attr;
411
412         for (attr = IFLA_RTA(msg); RTA_OK(attr, bytes);
413                                         attr = RTA_NEXT(attr, bytes)) {
414                 switch (attr->rta_type) {
415                 case IFLA_ADDRESS:
416                         if (address)
417                                 memcpy(address, RTA_DATA(attr), ETH_ALEN);
418                         break;
419                 case IFLA_IFNAME:
420                         if (ifname)
421                                 *ifname = RTA_DATA(attr);
422                         break;
423                 case IFLA_MTU:
424                         if (mtu)
425                                 *mtu = *((unsigned int *) RTA_DATA(attr));
426                         break;
427                 case IFLA_STATS:
428                         if (stats)
429                                 memcpy(stats, RTA_DATA(attr),
430                                         sizeof(struct rtnl_link_stats));
431                         break;
432                 case IFLA_OPERSTATE:
433                         if (operstate)
434                                 *operstate = *((unsigned char *) RTA_DATA(attr));
435                         break;
436                 case IFLA_LINKMODE:
437                         break;
438                 case IFLA_WIRELESS:
439                         return false;
440                 }
441         }
442
443         return true;
444 }
445
446 static void process_newlink(unsigned short type, int index, unsigned flags,
447                         unsigned change, struct ifinfomsg *msg, int bytes)
448 {
449         struct ether_addr address = {{ 0, 0, 0, 0, 0, 0 }};
450         struct rtnl_link_stats stats;
451         unsigned char operstate = 0xff;
452         struct interface_data *interface;
453         const char *ifname = NULL;
454         unsigned int mtu = 0;
455         char ident[13], str[18];
456         GSList *list;
457
458         memset(&stats, 0, sizeof(stats));
459         if (!extract_link(msg, bytes, &address, &ifname, &mtu, &operstate, &stats))
460                 return;
461
462 #if defined TIZEN_EXT
463         /* Do not accept Wi-Fi P2P interface */
464         if (g_strrstr(ifname, "p2p") != NULL) {
465                 DBG("Newlink event for Wi-Fi P2P interface ignored");
466                 return;
467         }
468 #endif
469
470         snprintf(ident, 13, "%02x%02x%02x%02x%02x%02x",
471                                                 address.ether_addr_octet[0],
472                                                 address.ether_addr_octet[1],
473                                                 address.ether_addr_octet[2],
474                                                 address.ether_addr_octet[3],
475                                                 address.ether_addr_octet[4],
476                                                 address.ether_addr_octet[5]);
477
478         snprintf(str, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
479                                                 address.ether_addr_octet[0],
480                                                 address.ether_addr_octet[1],
481                                                 address.ether_addr_octet[2],
482                                                 address.ether_addr_octet[3],
483                                                 address.ether_addr_octet[4],
484                                                 address.ether_addr_octet[5]);
485
486         if (flags & IFF_SLAVE) {
487                 connman_info("%s {newlink} ignoring slave, index %d address %s",
488                                                 ifname, index, str);
489                 return;
490         }
491
492 #ifdef TIZEN_EXT
493         if (TIZEN_TV_EXT && g_strcmp0(ident, "eeeeeeeeeeee") == 0) {
494                 DBG("Newlink event with Dummy MAC. Ignored!");
495                 return;
496         }
497 #endif
498
499         switch (type) {
500         case ARPHRD_ETHER:
501         case ARPHRD_LOOPBACK:
502         case ARPHDR_PHONET_PIPE:
503         case ARPHRD_PPP:
504         case ARPHRD_NONE:
505 #if defined TIZEN_EXT
506 /*
507  * Description: ARPHDR_RMNET for QC modem using QMI
508  */
509         case ARPHDR_RMNET:
510 #endif
511                 __connman_ipconfig_newlink(index, type, flags,
512                                                         str, mtu, &stats);
513                 break;
514         }
515
516         connman_info("%s {newlink} index %d address %s mtu %u",
517                                         ifname, index, str, mtu);
518
519         if (operstate != 0xff)
520                 connman_info("%s {newlink} index %d operstate %u <%s>",
521                                                 ifname, index, operstate,
522                                                 operstate2str(operstate));
523
524         interface = g_hash_table_lookup(interface_list, GINT_TO_POINTER(index));
525         if (!interface) {
526                 interface = g_new0(struct interface_data, 1);
527                 interface->index = index;
528                 interface->ident = g_strdup(ident);
529
530                 g_hash_table_insert(interface_list,
531                                         GINT_TO_POINTER(index), interface);
532
533                 if (type == ARPHRD_ETHER)
534                         read_uevent(interface);
535 #if defined TIZEN_EXT
536                 if (type == ARPHRD_PPP || type == ARPHDR_RMNET)
537                         read_uevent(interface);
538
539         } else if (g_strcmp0(interface->ident, ident) != 0) {
540                 /* If an original address is built-in physical device,
541                  * it's hardly get an address at a initial creation
542                  */
543                 __connman_technology_remove_interface(interface->service_type,
544                                 interface->index, interface->ident);
545
546                 g_free(interface->ident);
547                 interface->ident = g_strdup(ident);
548
549                 __connman_technology_add_interface(interface->service_type,
550                                 interface->index, interface->ident);
551
552                 interface = NULL;
553 #endif
554         } else
555                 interface = NULL;
556
557         for (list = rtnl_list; list; list = list->next) {
558                 struct connman_rtnl *rtnl = list->data;
559
560                 if (rtnl->newlink)
561                         rtnl->newlink(type, index, flags, change);
562         }
563
564         /*
565          * The interface needs to be added after the newlink call.
566          * The newlink will create the technology when needed and
567          * __connman_technology_add_interface() expects the
568          * technology to be there already.
569          */
570         if (interface)
571                 __connman_technology_add_interface(interface->service_type,
572                         interface->index, interface->ident);
573
574         for (list = watch_list; list; list = list->next) {
575                 struct watch_data *watch = list->data;
576
577                 if (watch->index != index)
578                         continue;
579
580                 if (watch->newlink)
581                         watch->newlink(flags, change, watch->user_data);
582         }
583 }
584
585 static void process_dellink(unsigned short type, int index, unsigned flags,
586                         unsigned change, struct ifinfomsg *msg, int bytes)
587 {
588         struct rtnl_link_stats stats;
589         unsigned char operstate = 0xff;
590         const char *ifname = NULL;
591         GSList *list;
592
593         memset(&stats, 0, sizeof(stats));
594         if (!extract_link(msg, bytes, NULL, &ifname, NULL, &operstate, &stats))
595                 return;
596
597         if (operstate != 0xff)
598                 connman_info("%s {dellink} index %d operstate %u <%s>",
599                                                 ifname, index, operstate,
600                                                 operstate2str(operstate));
601
602         for (list = rtnl_list; list; list = list->next) {
603                 struct connman_rtnl *rtnl = list->data;
604
605                 if (rtnl->dellink)
606                         rtnl->dellink(type, index, flags, change);
607         }
608
609         switch (type) {
610         case ARPHRD_ETHER:
611         case ARPHRD_LOOPBACK:
612         case ARPHDR_PHONET_PIPE:
613         case ARPHRD_PPP:
614         case ARPHRD_NONE:
615 #if defined TIZEN_EXT
616         /*
617          * Description: SLP requires ARPHRD_PPP for PPP type device
618          *              ARPHDR_RMNET for QC modem using QMI
619          */
620         case ARPHDR_RMNET:
621 #endif
622                 __connman_ipconfig_dellink(index, &stats);
623                 break;
624         }
625
626         g_hash_table_remove(interface_list, GINT_TO_POINTER(index));
627 }
628
629 static void extract_ipv4_addr(struct ifaddrmsg *msg, int bytes,
630                                                 const char **label,
631                                                 struct in_addr *local,
632                                                 struct in_addr *address,
633                                                 struct in_addr *broadcast)
634 {
635         struct rtattr *attr;
636
637         for (attr = IFA_RTA(msg); RTA_OK(attr, bytes);
638                                         attr = RTA_NEXT(attr, bytes)) {
639                 switch (attr->rta_type) {
640                 case IFA_ADDRESS:
641                         if (address)
642                                 *address = *((struct in_addr *) RTA_DATA(attr));
643                         break;
644                 case IFA_LOCAL:
645                         if (local)
646                                 *local = *((struct in_addr *) RTA_DATA(attr));
647                         break;
648                 case IFA_BROADCAST:
649                         if (broadcast)
650                                 *broadcast = *((struct in_addr *) RTA_DATA(attr));
651                         break;
652                 case IFA_LABEL:
653                         if (label)
654                                 *label = RTA_DATA(attr);
655                         break;
656                 }
657         }
658 }
659
660 static void extract_ipv6_addr(struct ifaddrmsg *msg, int bytes,
661                                                 struct in6_addr *addr,
662                                                 struct in6_addr *local)
663 {
664         struct rtattr *attr;
665
666         for (attr = IFA_RTA(msg); RTA_OK(attr, bytes);
667                                         attr = RTA_NEXT(attr, bytes)) {
668                 switch (attr->rta_type) {
669                 case IFA_ADDRESS:
670                         if (addr)
671                                 *addr = *((struct in6_addr *) RTA_DATA(attr));
672                         break;
673                 case IFA_LOCAL:
674                         if (local)
675                                 *local = *((struct in6_addr *) RTA_DATA(attr));
676                         break;
677                 }
678         }
679 }
680
681 static void process_newaddr(unsigned char family, unsigned char prefixlen,
682                                 int index, struct ifaddrmsg *msg, int bytes)
683 {
684         struct in_addr ipv4_addr = { INADDR_ANY };
685         struct in6_addr ipv6_address, ipv6_local;
686         const char *label = NULL;
687         void *src;
688         char ip_string[INET6_ADDRSTRLEN];
689
690         if (family == AF_INET) {
691
692                 extract_ipv4_addr(msg, bytes, &label, &ipv4_addr, NULL, NULL);
693                 src = &ipv4_addr;
694         } else if (family == AF_INET6) {
695                 extract_ipv6_addr(msg, bytes, &ipv6_address, &ipv6_local);
696                 if (IN6_IS_ADDR_LINKLOCAL(&ipv6_address))
697                         return;
698
699                 src = &ipv6_address;
700         } else {
701                 return;
702         }
703
704         if (!inet_ntop(family, src, ip_string, INET6_ADDRSTRLEN))
705                 return;
706
707         if (__connman_ipconfig_newaddr(index, family, label,
708                                         prefixlen, ip_string) >= 0) {
709                 if (family == AF_INET6) {
710                         /*
711                          * Re-create RDNSS configured servers if there
712                          * are any for this interface. This is done
713                          * because we might have now properly
714                          * configured interface with proper
715                          * autoconfigured address.
716                          */
717                         __connman_resolver_redo_servers(index);
718                 }
719         }
720 }
721
722 static void process_deladdr(unsigned char family, unsigned char prefixlen,
723                                 int index, struct ifaddrmsg *msg, int bytes)
724 {
725         struct in_addr ipv4_addr = { INADDR_ANY };
726         struct in6_addr ipv6_address, ipv6_local;
727         const char *label = NULL;
728         void *src;
729         char ip_string[INET6_ADDRSTRLEN];
730
731         if (family == AF_INET) {
732                 extract_ipv4_addr(msg, bytes, &label, &ipv4_addr, NULL, NULL);
733                 src = &ipv4_addr;
734         } else if (family == AF_INET6) {
735                 extract_ipv6_addr(msg, bytes, &ipv6_address, &ipv6_local);
736                 if (IN6_IS_ADDR_LINKLOCAL(&ipv6_address))
737                         return;
738
739                 src = &ipv6_address;
740         } else {
741                 return;
742         }
743
744         if (!inet_ntop(family, src, ip_string, INET6_ADDRSTRLEN))
745                 return;
746
747         __connman_ipconfig_deladdr(index, family, label,
748                                         prefixlen, ip_string);
749 }
750
751 static void extract_ipv4_route(struct rtmsg *msg, int bytes, int *index,
752                                                 struct in_addr *dst,
753                                                 struct in_addr *gateway)
754 {
755         struct rtattr *attr;
756
757         for (attr = RTM_RTA(msg); RTA_OK(attr, bytes);
758                                         attr = RTA_NEXT(attr, bytes)) {
759                 switch (attr->rta_type) {
760                 case RTA_DST:
761                         if (dst)
762                                 *dst = *((struct in_addr *) RTA_DATA(attr));
763                         break;
764                 case RTA_GATEWAY:
765                         if (gateway)
766                                 *gateway = *((struct in_addr *) RTA_DATA(attr));
767                         break;
768                 case RTA_OIF:
769                         if (index)
770                                 *index = *((int *) RTA_DATA(attr));
771                         break;
772                 }
773         }
774 }
775
776 static void extract_ipv6_route(struct rtmsg *msg, int bytes, int *index,
777                                                 struct in6_addr *dst,
778                                                 struct in6_addr *gateway)
779 {
780         struct rtattr *attr;
781
782         for (attr = RTM_RTA(msg); RTA_OK(attr, bytes);
783                                         attr = RTA_NEXT(attr, bytes)) {
784                 switch (attr->rta_type) {
785                 case RTA_DST:
786                         if (dst)
787                                 *dst = *((struct in6_addr *) RTA_DATA(attr));
788                         break;
789                 case RTA_GATEWAY:
790                         if (gateway)
791                                 *gateway =
792                                         *((struct in6_addr *) RTA_DATA(attr));
793                         break;
794                 case RTA_OIF:
795                         if (index)
796                                 *index = *((int *) RTA_DATA(attr));
797                         break;
798                 }
799         }
800 }
801
802 static void process_newroute(unsigned char family, unsigned char scope,
803                                                 struct rtmsg *msg, int bytes)
804 {
805         GSList *list;
806         char dststr[INET6_ADDRSTRLEN], gatewaystr[INET6_ADDRSTRLEN];
807         int index = -1;
808
809         if (family == AF_INET) {
810                 struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY };
811
812                 extract_ipv4_route(msg, bytes, &index, &dst, &gateway);
813
814                 inet_ntop(family, &dst, dststr, sizeof(dststr));
815                 inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr));
816
817                 __connman_ipconfig_newroute(index, family, scope, dststr,
818                                                                 gatewaystr);
819
820                 /* skip host specific routes */
821                 if (scope != RT_SCOPE_UNIVERSE &&
822                         !(scope == RT_SCOPE_LINK && dst.s_addr == INADDR_ANY))
823                         return;
824
825                 if (dst.s_addr != INADDR_ANY)
826                         return;
827
828         } else if (family == AF_INET6) {
829                 struct in6_addr dst = IN6ADDR_ANY_INIT,
830                                 gateway = IN6ADDR_ANY_INIT;
831
832                 extract_ipv6_route(msg, bytes, &index, &dst, &gateway);
833
834                 inet_ntop(family, &dst, dststr, sizeof(dststr));
835                 inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr));
836
837                 __connman_ipconfig_newroute(index, family, scope, dststr,
838                                                                 gatewaystr);
839
840                 /* skip host specific routes */
841                 if (scope != RT_SCOPE_UNIVERSE &&
842                         !(scope == RT_SCOPE_LINK &&
843                                 IN6_IS_ADDR_UNSPECIFIED(&dst)))
844                         return;
845
846                 if (!IN6_IS_ADDR_UNSPECIFIED(&dst))
847                         return;
848         } else
849                 return;
850
851         for (list = rtnl_list; list; list = list->next) {
852                 struct connman_rtnl *rtnl = list->data;
853
854                 if (rtnl->newgateway)
855                         rtnl->newgateway(index, gatewaystr);
856         }
857 }
858
859 static void process_delroute(unsigned char family, unsigned char scope,
860                                                 struct rtmsg *msg, int bytes)
861 {
862         GSList *list;
863         char dststr[INET6_ADDRSTRLEN], gatewaystr[INET6_ADDRSTRLEN];
864         int index = -1;
865
866         if (family == AF_INET) {
867                 struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY };
868
869                 extract_ipv4_route(msg, bytes, &index, &dst, &gateway);
870
871                 inet_ntop(family, &dst, dststr, sizeof(dststr));
872                 inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr));
873
874                 __connman_ipconfig_delroute(index, family, scope, dststr,
875                                                                 gatewaystr);
876
877                 /* skip host specific routes */
878                 if (scope != RT_SCOPE_UNIVERSE &&
879                         !(scope == RT_SCOPE_LINK && dst.s_addr == INADDR_ANY))
880                         return;
881
882                 if (dst.s_addr != INADDR_ANY)
883                         return;
884
885         }  else if (family == AF_INET6) {
886                 struct in6_addr dst = IN6ADDR_ANY_INIT,
887                                 gateway = IN6ADDR_ANY_INIT;
888
889                 extract_ipv6_route(msg, bytes, &index, &dst, &gateway);
890
891                 inet_ntop(family, &dst, dststr, sizeof(dststr));
892                 inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr));
893
894                 __connman_ipconfig_delroute(index, family, scope, dststr,
895                                                 gatewaystr);
896
897                 /* skip host specific routes */
898                 if (scope != RT_SCOPE_UNIVERSE &&
899                         !(scope == RT_SCOPE_LINK &&
900                                 IN6_IS_ADDR_UNSPECIFIED(&dst)))
901                         return;
902
903                 if (!IN6_IS_ADDR_UNSPECIFIED(&dst))
904                         return;
905         } else
906                 return;
907
908         for (list = rtnl_list; list; list = list->next) {
909                 struct connman_rtnl *rtnl = list->data;
910
911                 if (rtnl->delgateway)
912                         rtnl->delgateway(index, gatewaystr);
913         }
914 }
915
916 static inline void print_ether(struct rtattr *attr, const char *name)
917 {
918         int len = (int) RTA_PAYLOAD(attr);
919
920         if (len == ETH_ALEN) {
921                 struct ether_addr eth;
922                 memcpy(&eth, RTA_DATA(attr), ETH_ALEN);
923                 print("  attr %s (len %d) %s\n", name, len, ether_ntoa(&eth));
924         } else
925                 print("  attr %s (len %d)\n", name, len);
926 }
927
928 static inline void print_inet(struct rtattr *attr, const char *name,
929                                                         unsigned char family)
930 {
931         int len = (int) RTA_PAYLOAD(attr);
932
933         if (family == AF_INET && len == sizeof(struct in_addr)) {
934                 struct in_addr addr;
935                 addr = *((struct in_addr *) RTA_DATA(attr));
936                 print("  attr %s (len %d) %s\n", name, len, inet_ntoa(addr));
937         } else
938                 print("  attr %s (len %d)\n", name, len);
939 }
940
941 static inline void print_string(struct rtattr *attr, const char *name)
942 {
943         print("  attr %s (len %d) %s\n", name, (int) RTA_PAYLOAD(attr),
944                                                 (char *) RTA_DATA(attr));
945 }
946
947 static inline void print_byte(struct rtattr *attr, const char *name)
948 {
949         print("  attr %s (len %d) 0x%02x\n", name, (int) RTA_PAYLOAD(attr),
950                                         *((unsigned char *) RTA_DATA(attr)));
951 }
952
953 static inline void print_integer(struct rtattr *attr, const char *name)
954 {
955         print("  attr %s (len %d) %d\n", name, (int) RTA_PAYLOAD(attr),
956                                                 *((int *) RTA_DATA(attr)));
957 }
958
959 static inline void print_attr(struct rtattr *attr, const char *name)
960 {
961         int len = (int) RTA_PAYLOAD(attr);
962
963         if (name && len > 0)
964                 print("  attr %s (len %d)\n", name, len);
965         else
966                 print("  attr %d (len %d)\n", attr->rta_type, len);
967 }
968
969 static void rtnl_link(struct nlmsghdr *hdr)
970 {
971         struct ifinfomsg *msg;
972         struct rtattr *attr;
973         int bytes;
974
975         msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
976         bytes = IFLA_PAYLOAD(hdr);
977
978         print("ifi_index %d ifi_flags 0x%04x", msg->ifi_index, msg->ifi_flags);
979
980         for (attr = IFLA_RTA(msg); RTA_OK(attr, bytes);
981                                         attr = RTA_NEXT(attr, bytes)) {
982                 switch (attr->rta_type) {
983                 case IFLA_ADDRESS:
984                         print_ether(attr, "address");
985                         break;
986                 case IFLA_BROADCAST:
987                         print_ether(attr, "broadcast");
988                         break;
989                 case IFLA_IFNAME:
990                         print_string(attr, "ifname");
991                         break;
992                 case IFLA_MTU:
993                         print_integer(attr, "mtu");
994                         break;
995                 case IFLA_LINK:
996                         print_attr(attr, "link");
997                         break;
998                 case IFLA_QDISC:
999                         print_attr(attr, "qdisc");
1000                         break;
1001                 case IFLA_STATS:
1002                         print_attr(attr, "stats");
1003                         break;
1004                 case IFLA_COST:
1005                         print_attr(attr, "cost");
1006                         break;
1007                 case IFLA_PRIORITY:
1008                         print_attr(attr, "priority");
1009                         break;
1010                 case IFLA_MASTER:
1011                         print_attr(attr, "master");
1012                         break;
1013                 case IFLA_WIRELESS:
1014                         print_attr(attr, "wireless");
1015                         break;
1016                 case IFLA_PROTINFO:
1017                         print_attr(attr, "protinfo");
1018                         break;
1019                 case IFLA_TXQLEN:
1020                         print_integer(attr, "txqlen");
1021                         break;
1022                 case IFLA_MAP:
1023                         print_attr(attr, "map");
1024                         break;
1025                 case IFLA_WEIGHT:
1026                         print_attr(attr, "weight");
1027                         break;
1028                 case IFLA_OPERSTATE:
1029                         print_byte(attr, "operstate");
1030                         break;
1031                 case IFLA_LINKMODE:
1032                         print_byte(attr, "linkmode");
1033                         break;
1034                 default:
1035                         print_attr(attr, NULL);
1036                         break;
1037                 }
1038         }
1039 }
1040
1041 static void rtnl_newlink(struct nlmsghdr *hdr)
1042 {
1043         struct ifinfomsg *msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
1044
1045         rtnl_link(hdr);
1046
1047         if (hdr->nlmsg_type == IFLA_WIRELESS)
1048                 connman_warn_once("Obsolete WEXT WiFi driver detected");
1049
1050         process_newlink(msg->ifi_type, msg->ifi_index, msg->ifi_flags,
1051                                 msg->ifi_change, msg, IFA_PAYLOAD(hdr));
1052 }
1053
1054 static void rtnl_dellink(struct nlmsghdr *hdr)
1055 {
1056         struct ifinfomsg *msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
1057
1058         rtnl_link(hdr);
1059
1060         process_dellink(msg->ifi_type, msg->ifi_index, msg->ifi_flags,
1061                                 msg->ifi_change, msg, IFA_PAYLOAD(hdr));
1062 }
1063
1064 static void rtnl_addr(struct nlmsghdr *hdr)
1065 {
1066         struct ifaddrmsg *msg;
1067         struct rtattr *attr;
1068         int bytes;
1069
1070         msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
1071         bytes = IFA_PAYLOAD(hdr);
1072
1073         print("ifa_family %d ifa_index %d", msg->ifa_family, msg->ifa_index);
1074
1075         for (attr = IFA_RTA(msg); RTA_OK(attr, bytes);
1076                                         attr = RTA_NEXT(attr, bytes)) {
1077                 switch (attr->rta_type) {
1078                 case IFA_ADDRESS:
1079                         print_inet(attr, "address", msg->ifa_family);
1080                         break;
1081                 case IFA_LOCAL:
1082                         print_inet(attr, "local", msg->ifa_family);
1083                         break;
1084                 case IFA_LABEL:
1085                         print_string(attr, "label");
1086                         break;
1087                 case IFA_BROADCAST:
1088                         print_inet(attr, "broadcast", msg->ifa_family);
1089                         break;
1090                 case IFA_ANYCAST:
1091                         print_attr(attr, "anycast");
1092                         break;
1093                 case IFA_CACHEINFO:
1094                         print_attr(attr, "cacheinfo");
1095                         break;
1096                 case IFA_MULTICAST:
1097                         print_attr(attr, "multicast");
1098                         break;
1099                 default:
1100                         print_attr(attr, NULL);
1101                         break;
1102                 }
1103         }
1104 }
1105
1106 static void rtnl_newaddr(struct nlmsghdr *hdr)
1107 {
1108         struct ifaddrmsg *msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
1109
1110         rtnl_addr(hdr);
1111
1112         process_newaddr(msg->ifa_family, msg->ifa_prefixlen, msg->ifa_index,
1113                                                 msg, IFA_PAYLOAD(hdr));
1114 }
1115
1116 static void rtnl_deladdr(struct nlmsghdr *hdr)
1117 {
1118         struct ifaddrmsg *msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
1119
1120         rtnl_addr(hdr);
1121
1122         process_deladdr(msg->ifa_family, msg->ifa_prefixlen, msg->ifa_index,
1123                                                 msg, IFA_PAYLOAD(hdr));
1124 }
1125
1126 static void rtnl_route(struct nlmsghdr *hdr)
1127 {
1128         struct rtmsg *msg;
1129         struct rtattr *attr;
1130         int bytes;
1131
1132         msg = (struct rtmsg *) NLMSG_DATA(hdr);
1133         bytes = RTM_PAYLOAD(hdr);
1134
1135         print("rtm_family %d rtm_table %d rtm_protocol %d",
1136                         msg->rtm_family, msg->rtm_table, msg->rtm_protocol);
1137         print("rtm_scope %d rtm_type %d rtm_flags 0x%04x",
1138                                 msg->rtm_scope, msg->rtm_type, msg->rtm_flags);
1139
1140         for (attr = RTM_RTA(msg); RTA_OK(attr, bytes);
1141                                         attr = RTA_NEXT(attr, bytes)) {
1142                 switch (attr->rta_type) {
1143                 case RTA_DST:
1144                         print_inet(attr, "dst", msg->rtm_family);
1145                         break;
1146                 case RTA_SRC:
1147                         print_inet(attr, "src", msg->rtm_family);
1148                         break;
1149                 case RTA_IIF:
1150                         print_string(attr, "iif");
1151                         break;
1152                 case RTA_OIF:
1153                         print_integer(attr, "oif");
1154                         break;
1155                 case RTA_GATEWAY:
1156                         print_inet(attr, "gateway", msg->rtm_family);
1157                         break;
1158                 case RTA_PRIORITY:
1159                         print_attr(attr, "priority");
1160                         break;
1161                 case RTA_PREFSRC:
1162                         print_inet(attr, "prefsrc", msg->rtm_family);
1163                         break;
1164                 case RTA_METRICS:
1165                         print_attr(attr, "metrics");
1166                         break;
1167                 case RTA_TABLE:
1168                         print_integer(attr, "table");
1169                         break;
1170                 default:
1171                         print_attr(attr, NULL);
1172                         break;
1173                 }
1174         }
1175 }
1176
1177 static bool is_route_rtmsg(struct rtmsg *msg)
1178 {
1179         if (msg->rtm_flags & RTM_F_CLONED)
1180                 return false;
1181
1182         if (msg->rtm_table != RT_TABLE_MAIN)
1183                 return false;
1184
1185         if (msg->rtm_protocol != RTPROT_BOOT &&
1186                         msg->rtm_protocol != RTPROT_KERNEL)
1187                 return false;
1188
1189         if (msg->rtm_type != RTN_UNICAST)
1190                 return false;
1191
1192         return true;
1193 }
1194
1195 static void rtnl_newroute(struct nlmsghdr *hdr)
1196 {
1197         struct rtmsg *msg = (struct rtmsg *) NLMSG_DATA(hdr);
1198
1199         rtnl_route(hdr);
1200
1201         if (is_route_rtmsg(msg))
1202                 process_newroute(msg->rtm_family, msg->rtm_scope,
1203                                                 msg, RTM_PAYLOAD(hdr));
1204 }
1205
1206 static void rtnl_delroute(struct nlmsghdr *hdr)
1207 {
1208         struct rtmsg *msg = (struct rtmsg *) NLMSG_DATA(hdr);
1209
1210         rtnl_route(hdr);
1211
1212         if (is_route_rtmsg(msg))
1213                 process_delroute(msg->rtm_family, msg->rtm_scope,
1214                                                 msg, RTM_PAYLOAD(hdr));
1215 }
1216
1217 static void *rtnl_nd_opt_rdnss(struct nd_opt_hdr *opt, guint32 *lifetime,
1218                                int *nr_servers)
1219 {
1220         guint32 *optint = (void *)opt;
1221
1222         if (opt->nd_opt_len < 3)
1223                 return NULL;
1224
1225         if (*lifetime > ntohl(optint[1]))
1226                 *lifetime = ntohl(optint[1]);
1227
1228         /* nd_opt_len is in units of 8 bytes. The header is 1 unit (8 bytes)
1229            and each address is another 2 units (16 bytes).
1230            So the number of addresses (given rounding) is nd_opt_len/2 */
1231         *nr_servers = opt->nd_opt_len / 2;
1232
1233         /* And they start 8 bytes into the packet, or two guint32s in. */
1234         return optint + 2;
1235 }
1236
1237 static const char **rtnl_nd_opt_dnssl(struct nd_opt_hdr *opt, guint32 *lifetime)
1238 {
1239         const char **domains = NULL;
1240         guint32 *optint = (void *)opt;
1241         unsigned char *optc = (void *)&optint[2];
1242         int data_len = (opt->nd_opt_len * 8) - 8;
1243         int nr_domains = 0;
1244         int i, tmp;
1245
1246         if (*lifetime > ntohl(optint[1]))
1247                 *lifetime = ntohl(optint[1]);
1248
1249         /* Turn it into normal strings by converting the length bytes into '.',
1250            and count how many search domains there are while we're at it. */
1251         i = 0;
1252         while (i < data_len) {
1253                 if (optc[i] > 0x3f) {
1254                         DBG("DNSSL contains compressed elements in violation of RFC6106");
1255                         return NULL;
1256                 }
1257
1258                 if (optc[i] == 0) {
1259                         nr_domains++;
1260                         i++;
1261                         /* Check for double zero */
1262                         if (i < data_len && optc[i] == 0)
1263                                 break;
1264                         continue;
1265                 }
1266
1267                 tmp = i;
1268                 i += optc[i] + 1;
1269
1270                 if (i >= data_len) {
1271                         DBG("DNSSL data overflows option length");
1272                         return NULL;
1273                 }
1274
1275                 optc[tmp] = '.';
1276         }
1277
1278         domains = g_try_new0(const char *, nr_domains + 1);
1279         if (!domains)
1280                 return NULL;
1281
1282         /* Now point to the normal strings, missing out the leading '.' that
1283            each of them will have now. */
1284         for (i = 0; i < nr_domains; i++) {
1285                 domains[i] = (char *)optc + 1;
1286                 optc += strlen((char *)optc) + 1;
1287         }
1288
1289         return domains;
1290 }
1291
1292 static void rtnl_newnduseropt(struct nlmsghdr *hdr)
1293 {
1294         struct nduseroptmsg *msg = (struct nduseroptmsg *) NLMSG_DATA(hdr);
1295         struct nd_opt_hdr *opt;
1296         guint32 lifetime = -1;
1297         const char **domains = NULL;
1298         struct in6_addr *servers = NULL;
1299         int i, nr_servers = 0;
1300         int msglen = msg->nduseropt_opts_len;
1301         int index;
1302
1303         DBG("family %d index %d len %d type %d code %d",
1304                 msg->nduseropt_family, msg->nduseropt_ifindex,
1305                 msg->nduseropt_opts_len, msg->nduseropt_icmp_type,
1306                 msg->nduseropt_icmp_code);
1307
1308         if (msg->nduseropt_family != AF_INET6 ||
1309                         msg->nduseropt_icmp_type != ND_ROUTER_ADVERT ||
1310                         msg->nduseropt_icmp_code != 0)
1311                 return;
1312
1313         index = msg->nduseropt_ifindex;
1314         if (index < 0)
1315                 return;
1316
1317 #if defined TIZEN_EXT
1318         struct connman_service *service;
1319         enum connman_dnsconfig_method ipv6_dns_method;
1320         char *ifname;
1321
1322         service = __connman_service_lookup_from_index(index);
1323         if (!service || !(__connman_service_index_is_default(index))) {
1324                 DBG("Invalid service, index: %d\n", index);
1325                 return;
1326         }
1327
1328         DBG("service: %p index: %d\n", service, index);
1329
1330         ifname = connman_inet_ifname(index);
1331         if (ifname == NULL) {
1332                 DBG("Interface is NULL, return");
1333                 return;
1334         }
1335
1336         ipv6_dns_method = connman_service_get_ipv6_dns_method(service);
1337         if (ipv6_dns_method != CONNMAN_DNSCONFIG_METHOD_DHCP) {
1338                 DBG("IPv6 DNS method is not Auto ignore RA!!! [DNS method: %d]", ipv6_dns_method);
1339                 g_free(ifname);
1340                 return;
1341         }
1342         g_free(ifname);
1343 #endif
1344
1345         for (opt = (void *)&msg[1];
1346                         msglen > 0;
1347                         msglen -= opt->nd_opt_len * 8,
1348                         opt = ((void *)opt) + opt->nd_opt_len*8) {
1349
1350                 DBG("remaining %d nd opt type %d len %d\n",
1351                         msglen, opt->nd_opt_type, opt->nd_opt_len);
1352
1353                 if (opt->nd_opt_type == 25) { /* ND_OPT_RDNSS */
1354                         char buf[40];
1355
1356                         servers = rtnl_nd_opt_rdnss(opt, &lifetime,
1357                                         &nr_servers);
1358                         for (i = 0; i < nr_servers; i++) {
1359                                 if (!inet_ntop(AF_INET6, servers + i, buf,
1360                                                         sizeof(buf)))
1361                                         continue;
1362
1363 #if defined TIZEN_EXT
1364                                 __connman_service_nameserver_remove(service,
1365                                                 buf, false,
1366                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1367                                 __connman_service_nameserver_append(service,
1368                                                 buf, false,
1369                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1370 #endif
1371                                 connman_resolver_append_lifetime(index,
1372                                                 NULL, buf, lifetime);
1373                         }
1374                 } else if (opt->nd_opt_type == 31) { /* ND_OPT_DNSSL */
1375                         g_free(domains);
1376
1377                         domains = rtnl_nd_opt_dnssl(opt, &lifetime);
1378                         for (i = 0; domains && domains[i]; i++)
1379                                 connman_resolver_append_lifetime(index,
1380                                                 domains[i], NULL, lifetime);
1381                 }
1382         }
1383
1384         g_free(domains);
1385 }
1386
1387 static const char *type2string(uint16_t type)
1388 {
1389         switch (type) {
1390         case NLMSG_NOOP:
1391                 return "NOOP";
1392         case NLMSG_ERROR:
1393                 return "ERROR";
1394         case NLMSG_DONE:
1395                 return "DONE";
1396         case NLMSG_OVERRUN:
1397                 return "OVERRUN";
1398         case RTM_GETLINK:
1399                 return "GETLINK";
1400         case RTM_NEWLINK:
1401                 return "NEWLINK";
1402         case RTM_DELLINK:
1403                 return "DELLINK";
1404         case RTM_GETADDR:
1405                 return "GETADDR";
1406         case RTM_NEWADDR:
1407                 return "NEWADDR";
1408         case RTM_DELADDR:
1409                 return "DELADDR";
1410         case RTM_GETROUTE:
1411                 return "GETROUTE";
1412         case RTM_NEWROUTE:
1413                 return "NEWROUTE";
1414         case RTM_DELROUTE:
1415                 return "DELROUTE";
1416         case RTM_NEWNDUSEROPT:
1417                 return "NEWNDUSEROPT";
1418         default:
1419                 return "UNKNOWN";
1420         }
1421 }
1422
1423 static GIOChannel *channel = NULL;
1424 static guint channel_watch = 0;
1425
1426 struct rtnl_request {
1427         struct nlmsghdr hdr;
1428         struct rtgenmsg msg;
1429 };
1430 #define RTNL_REQUEST_SIZE  (sizeof(struct nlmsghdr) + sizeof(struct rtgenmsg))
1431
1432 static GSList *request_list = NULL;
1433 static guint32 request_seq = 0;
1434
1435 static struct rtnl_request *find_request(guint32 seq)
1436 {
1437         GSList *list;
1438
1439         for (list = request_list; list; list = list->next) {
1440                 struct rtnl_request *req = list->data;
1441
1442                 if (req->hdr.nlmsg_seq == seq)
1443                         return req;
1444         }
1445
1446         return NULL;
1447 }
1448
1449 static int send_request(struct rtnl_request *req)
1450 {
1451         struct sockaddr_nl addr;
1452         int sk;
1453
1454         DBG("%s len %d type %d flags 0x%04x seq %d",
1455                                 type2string(req->hdr.nlmsg_type),
1456                                 req->hdr.nlmsg_len, req->hdr.nlmsg_type,
1457                                 req->hdr.nlmsg_flags, req->hdr.nlmsg_seq);
1458
1459         sk = g_io_channel_unix_get_fd(channel);
1460
1461         memset(&addr, 0, sizeof(addr));
1462         addr.nl_family = AF_NETLINK;
1463
1464         return sendto(sk, req, req->hdr.nlmsg_len, 0,
1465                                 (struct sockaddr *) &addr, sizeof(addr));
1466 }
1467
1468 static int queue_request(struct rtnl_request *req)
1469 {
1470         request_list = g_slist_append(request_list, req);
1471
1472         if (g_slist_length(request_list) > 1)
1473                 return 0;
1474
1475         return send_request(req);
1476 }
1477
1478 static int process_response(guint32 seq)
1479 {
1480         struct rtnl_request *req;
1481
1482         DBG("seq %d", seq);
1483
1484         req = find_request(seq);
1485         if (req) {
1486                 request_list = g_slist_remove(request_list, req);
1487                 g_free(req);
1488         }
1489
1490         req = g_slist_nth_data(request_list, 0);
1491         if (!req)
1492                 return 0;
1493
1494         return send_request(req);
1495 }
1496
1497 static void rtnl_message(void *buf, size_t len)
1498 {
1499         DBG("buf %p len %zd", buf, len);
1500
1501         while (len > 0) {
1502                 struct nlmsghdr *hdr = buf;
1503                 struct nlmsgerr *err;
1504
1505                 if (!NLMSG_OK(hdr, len))
1506                         break;
1507
1508                 DBG("%s len %d type %d flags 0x%04x seq %d pid %d",
1509                                         type2string(hdr->nlmsg_type),
1510                                         hdr->nlmsg_len, hdr->nlmsg_type,
1511                                         hdr->nlmsg_flags, hdr->nlmsg_seq,
1512                                         hdr->nlmsg_pid);
1513
1514                 switch (hdr->nlmsg_type) {
1515                 case NLMSG_NOOP:
1516                 case NLMSG_OVERRUN:
1517                         return;
1518                 case NLMSG_DONE:
1519                         process_response(hdr->nlmsg_seq);
1520                         return;
1521                 case NLMSG_ERROR:
1522                         err = NLMSG_DATA(hdr);
1523                         DBG("error %d (%s)", -err->error,
1524                                                 strerror(-err->error));
1525                         return;
1526                 case RTM_NEWLINK:
1527                         rtnl_newlink(hdr);
1528                         break;
1529                 case RTM_DELLINK:
1530                         rtnl_dellink(hdr);
1531                         break;
1532                 case RTM_NEWADDR:
1533                         rtnl_newaddr(hdr);
1534                         break;
1535                 case RTM_DELADDR:
1536                         rtnl_deladdr(hdr);
1537                         break;
1538                 case RTM_NEWROUTE:
1539                         rtnl_newroute(hdr);
1540                         break;
1541                 case RTM_DELROUTE:
1542                         rtnl_delroute(hdr);
1543                         break;
1544                 case RTM_NEWNDUSEROPT:
1545                         rtnl_newnduseropt(hdr);
1546                         break;
1547                 }
1548
1549                 len -= hdr->nlmsg_len;
1550                 buf += hdr->nlmsg_len;
1551         }
1552 }
1553
1554 static gboolean netlink_event(GIOChannel *chan, GIOCondition cond, gpointer data)
1555 {
1556         unsigned char buf[4096];
1557         struct sockaddr_nl nladdr;
1558         socklen_t addr_len = sizeof(nladdr);
1559         ssize_t status;
1560         int fd;
1561
1562         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
1563                 return FALSE;
1564
1565         memset(buf, 0, sizeof(buf));
1566         memset(&nladdr, 0, sizeof(nladdr));
1567
1568         fd = g_io_channel_unix_get_fd(chan);
1569
1570         status = recvfrom(fd, buf, sizeof(buf), 0,
1571                        (struct sockaddr *) &nladdr, &addr_len);
1572         if (status < 0) {
1573                 if (errno == EINTR || errno == EAGAIN)
1574                         return TRUE;
1575
1576                 return FALSE;
1577         }
1578
1579         if (status == 0)
1580                 return FALSE;
1581
1582         if (nladdr.nl_pid != 0) { /* not sent by kernel, ignore */
1583                 DBG("Received msg from %u, ignoring it", nladdr.nl_pid);
1584                 return TRUE;
1585         }
1586
1587         rtnl_message(buf, status);
1588
1589         return TRUE;
1590 }
1591
1592 static int send_getlink(void)
1593 {
1594         struct rtnl_request *req;
1595
1596         DBG("");
1597
1598         req = g_try_malloc0(RTNL_REQUEST_SIZE);
1599         if (!req)
1600                 return -ENOMEM;
1601
1602         req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
1603         req->hdr.nlmsg_type = RTM_GETLINK;
1604         req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1605         req->hdr.nlmsg_pid = 0;
1606         req->hdr.nlmsg_seq = request_seq++;
1607         req->msg.rtgen_family = AF_INET;
1608
1609         return queue_request(req);
1610 }
1611
1612 static int send_getaddr(void)
1613 {
1614         struct rtnl_request *req;
1615
1616         DBG("");
1617
1618         req = g_try_malloc0(RTNL_REQUEST_SIZE);
1619         if (!req)
1620                 return -ENOMEM;
1621
1622         req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
1623         req->hdr.nlmsg_type = RTM_GETADDR;
1624         req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1625         req->hdr.nlmsg_pid = 0;
1626         req->hdr.nlmsg_seq = request_seq++;
1627         req->msg.rtgen_family = AF_INET;
1628
1629         return queue_request(req);
1630 }
1631
1632 static int send_getroute(void)
1633 {
1634         struct rtnl_request *req;
1635
1636         DBG("");
1637
1638         req = g_try_malloc0(RTNL_REQUEST_SIZE);
1639         if (!req)
1640                 return -ENOMEM;
1641
1642         req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
1643         req->hdr.nlmsg_type = RTM_GETROUTE;
1644         req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1645         req->hdr.nlmsg_pid = 0;
1646         req->hdr.nlmsg_seq = request_seq++;
1647         req->msg.rtgen_family = AF_INET;
1648
1649         return queue_request(req);
1650 }
1651
1652 static gboolean update_timeout_cb(gpointer user_data)
1653 {
1654         __connman_rtnl_request_update();
1655
1656         return TRUE;
1657 }
1658
1659 static void update_interval_callback(guint min)
1660 {
1661         if (update_timeout > 0)
1662                 g_source_remove(update_timeout);
1663
1664         if (min < G_MAXUINT) {
1665                 update_interval = min;
1666                 update_timeout = g_timeout_add_seconds(update_interval,
1667                                                 update_timeout_cb, NULL);
1668         } else {
1669                 update_timeout = 0;
1670                 update_interval = G_MAXUINT;
1671         }
1672 }
1673
1674 static gint compare_interval(gconstpointer a, gconstpointer b)
1675 {
1676         guint val_a = GPOINTER_TO_UINT(a);
1677         guint val_b = GPOINTER_TO_UINT(b);
1678
1679         return val_a - val_b;
1680 }
1681
1682 unsigned int __connman_rtnl_update_interval_add(unsigned int interval)
1683 {
1684         guint min;
1685
1686         if (interval == 0)
1687                 return 0;
1688
1689         update_list = g_slist_insert_sorted(update_list,
1690                         GUINT_TO_POINTER(interval), compare_interval);
1691
1692         min = GPOINTER_TO_UINT(g_slist_nth_data(update_list, 0));
1693         if (min < update_interval) {
1694                 update_interval_callback(min);
1695                 __connman_rtnl_request_update();
1696         }
1697
1698         return update_interval;
1699 }
1700
1701 unsigned int __connman_rtnl_update_interval_remove(unsigned int interval)
1702 {
1703         guint min = G_MAXUINT;
1704
1705         if (interval == 0)
1706                 return 0;
1707
1708         update_list = g_slist_remove(update_list, GINT_TO_POINTER(interval));
1709
1710         if (update_list)
1711                 min = GPOINTER_TO_UINT(g_slist_nth_data(update_list, 0));
1712
1713         if (min > update_interval)
1714                 update_interval_callback(min);
1715
1716         return min;
1717 }
1718
1719 int __connman_rtnl_request_update(void)
1720 {
1721         return send_getlink();
1722 }
1723
1724 int __connman_rtnl_init(void)
1725 {
1726         struct sockaddr_nl addr;
1727         int sk;
1728
1729         DBG("");
1730
1731         interface_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1732                                                         NULL, free_interface);
1733
1734         sk = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_ROUTE);
1735         if (sk < 0)
1736                 return -1;
1737
1738         memset(&addr, 0, sizeof(addr));
1739         addr.nl_family = AF_NETLINK;
1740         addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE |
1741                                 RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE |
1742                                 (1<<(RTNLGRP_ND_USEROPT-1));
1743
1744         if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1745                 close(sk);
1746                 return -1;
1747         }
1748
1749         channel = g_io_channel_unix_new(sk);
1750         g_io_channel_set_close_on_unref(channel, TRUE);
1751
1752         g_io_channel_set_encoding(channel, NULL, NULL);
1753         g_io_channel_set_buffered(channel, FALSE);
1754
1755         channel_watch = g_io_add_watch(channel,
1756                                 G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
1757                                 netlink_event, NULL);
1758
1759         return 0;
1760 }
1761
1762 void __connman_rtnl_start(void)
1763 {
1764         DBG("");
1765
1766         send_getlink();
1767         send_getaddr();
1768         send_getroute();
1769 }
1770
1771 void __connman_rtnl_cleanup(void)
1772 {
1773         GSList *list;
1774
1775         DBG("");
1776
1777         for (list = watch_list; list; list = list->next) {
1778                 struct watch_data *watch = list->data;
1779
1780                 DBG("removing watch %d", watch->id);
1781
1782                 g_free(watch);
1783                 list->data = NULL;
1784         }
1785
1786         g_slist_free(watch_list);
1787         watch_list = NULL;
1788
1789         g_slist_free(update_list);
1790         update_list = NULL;
1791
1792         for (list = request_list; list; list = list->next) {
1793                 struct rtnl_request *req = list->data;
1794
1795                 DBG("%s len %d type %d flags 0x%04x seq %d",
1796                                 type2string(req->hdr.nlmsg_type),
1797                                 req->hdr.nlmsg_len, req->hdr.nlmsg_type,
1798                                 req->hdr.nlmsg_flags, req->hdr.nlmsg_seq);
1799
1800                 g_free(req);
1801                 list->data = NULL;
1802         }
1803
1804         g_slist_free(request_list);
1805         request_list = NULL;
1806
1807         if (channel_watch) {
1808                 g_source_remove(channel_watch);
1809                 channel_watch = 0;
1810         }
1811
1812         g_io_channel_shutdown(channel, TRUE, NULL);
1813         g_io_channel_unref(channel);
1814
1815         channel = NULL;
1816
1817         g_hash_table_destroy(interface_list);
1818 }