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