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