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