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