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