Use helper for checking rtnl message validity
[platform/upstream/connman.git] / src / rtnl.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <sys/socket.h>
30 #include <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 connman_bool_t is_route_rtmsg(struct rtmsg *msg)
787 {
788
789         if (msg->rtm_table != RT_TABLE_MAIN)
790                 return FALSE;
791
792         if (msg->rtm_protocol != RTPROT_BOOT &&
793                         msg->rtm_protocol != RTPROT_KERNEL)
794                 return FALSE;
795
796         if (msg->rtm_type != RTN_UNICAST)
797                 return FALSE;
798
799         return TRUE;
800 }
801
802 static void rtnl_newroute(struct nlmsghdr *hdr)
803 {
804         struct rtmsg *msg = (struct rtmsg *) NLMSG_DATA(hdr);
805
806         rtnl_route(hdr);
807
808         if (is_route_rtmsg(msg))
809                 process_newroute(msg->rtm_family, msg->rtm_scope,
810                                                 msg, RTM_PAYLOAD(hdr));
811 }
812
813 static void rtnl_delroute(struct nlmsghdr *hdr)
814 {
815         struct rtmsg *msg = (struct rtmsg *) NLMSG_DATA(hdr);
816
817         rtnl_route(hdr);
818
819         if (is_route_rtmsg(msg))
820                 process_delroute(msg->rtm_family, msg->rtm_scope,
821                                                 msg, RTM_PAYLOAD(hdr));
822 }
823
824 static const char *type2string(uint16_t type)
825 {
826         switch (type) {
827         case NLMSG_NOOP:
828                 return "NOOP";
829         case NLMSG_ERROR:
830                 return "ERROR";
831         case NLMSG_DONE:
832                 return "DONE";
833         case NLMSG_OVERRUN:
834                 return "OVERRUN";
835         case RTM_GETLINK:
836                 return "GETLINK";
837         case RTM_NEWLINK:
838                 return "NEWLINK";
839         case RTM_DELLINK:
840                 return "DELLINK";
841         case RTM_NEWADDR:
842                 return "NEWADDR";
843         case RTM_DELADDR:
844                 return "DELADDR";
845         case RTM_GETROUTE:
846                 return "GETROUTE";
847         case RTM_NEWROUTE:
848                 return "NEWROUTE";
849         case RTM_DELROUTE:
850                 return "DELROUTE";
851         default:
852                 return "UNKNOWN";
853         }
854 }
855
856 static GIOChannel *channel = NULL;
857
858 struct rtnl_request {
859         struct nlmsghdr hdr;
860         struct rtgenmsg msg;
861 };
862 #define RTNL_REQUEST_SIZE  (sizeof(struct nlmsghdr) + sizeof(struct rtgenmsg))
863
864 static GSList *request_list = NULL;
865 static guint32 request_seq = 0;
866
867 static struct rtnl_request *find_request(guint32 seq)
868 {
869         GSList *list;
870
871         for (list = request_list; list; list = list->next) {
872                 struct rtnl_request *req = list->data;
873
874                 if (req->hdr.nlmsg_seq == seq)
875                         return req;
876         }
877
878         return NULL;
879 }
880
881 static int send_request(struct rtnl_request *req)
882 {
883         struct sockaddr_nl addr;
884         int sk;
885
886         DBG("%s len %d type %d flags 0x%04x seq %d",
887                                 type2string(req->hdr.nlmsg_type),
888                                 req->hdr.nlmsg_len, req->hdr.nlmsg_type,
889                                 req->hdr.nlmsg_flags, req->hdr.nlmsg_seq);
890
891         sk = g_io_channel_unix_get_fd(channel);
892
893         memset(&addr, 0, sizeof(addr));
894         addr.nl_family = AF_NETLINK;
895
896         return sendto(sk, req, req->hdr.nlmsg_len, 0,
897                                 (struct sockaddr *) &addr, sizeof(addr));
898 }
899
900 static int queue_request(struct rtnl_request *req)
901 {
902         request_list = g_slist_append(request_list, req);
903
904         if (g_slist_length(request_list) > 1)
905                 return 0;
906
907         return send_request(req);
908 }
909
910 static int process_response(guint32 seq)
911 {
912         struct rtnl_request *req;
913
914         DBG("seq %d", seq);
915
916         req = find_request(seq);
917         if (req != NULL) {
918                 request_list = g_slist_remove(request_list, req);
919                 g_free(req);
920         }
921
922         req = g_slist_nth_data(request_list, 0);
923         if (req == NULL)
924                 return 0;
925
926         return send_request(req);
927 }
928
929 static void rtnl_message(void *buf, size_t len)
930 {
931         DBG("buf %p len %zd", buf, len);
932
933         while (len > 0) {
934                 struct nlmsghdr *hdr = buf;
935                 struct nlmsgerr *err;
936
937                 if (!NLMSG_OK(hdr, len))
938                         break;
939
940                 DBG("%s len %d type %d flags 0x%04x seq %d",
941                                         type2string(hdr->nlmsg_type),
942                                         hdr->nlmsg_len, hdr->nlmsg_type,
943                                         hdr->nlmsg_flags, hdr->nlmsg_seq);
944
945                 switch (hdr->nlmsg_type) {
946                 case NLMSG_NOOP:
947                 case NLMSG_OVERRUN:
948                         return;
949                 case NLMSG_DONE:
950                         process_response(hdr->nlmsg_seq);
951                         return;
952                 case NLMSG_ERROR:
953                         err = NLMSG_DATA(hdr);
954                         DBG("error %d (%s)", -err->error,
955                                                 strerror(-err->error));
956                         return;
957                 case RTM_NEWLINK:
958                         rtnl_newlink(hdr);
959                         break;
960                 case RTM_DELLINK:
961                         rtnl_dellink(hdr);
962                         break;
963                 case RTM_NEWADDR:
964                         rtnl_newaddr(hdr);
965                         break;
966                 case RTM_DELADDR:
967                         rtnl_deladdr(hdr);
968                         break;
969                 case RTM_NEWROUTE:
970                         rtnl_newroute(hdr);
971                         break;
972                 case RTM_DELROUTE:
973                         rtnl_delroute(hdr);
974                         break;
975                 }
976
977                 len -= hdr->nlmsg_len;
978                 buf += hdr->nlmsg_len;
979         }
980 }
981
982 static gboolean netlink_event(GIOChannel *chan,
983                                 GIOCondition cond, gpointer data)
984 {
985         unsigned char buf[4096];
986         gsize len;
987         GIOError err;
988
989         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
990                 return FALSE;
991
992         memset(buf, 0, sizeof(buf));
993
994         err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len);
995         if (err) {
996                 if (err == G_IO_ERROR_AGAIN)
997                         return TRUE;
998                 return FALSE;
999         }
1000
1001         rtnl_message(buf, len);
1002
1003         return TRUE;
1004 }
1005
1006 static int send_getlink(void)
1007 {
1008         struct rtnl_request *req;
1009
1010         DBG("");
1011
1012         req = g_try_malloc0(RTNL_REQUEST_SIZE);
1013         if (req == NULL)
1014                 return -ENOMEM;
1015
1016         req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
1017         req->hdr.nlmsg_type = RTM_GETLINK;
1018         req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1019         req->hdr.nlmsg_pid = 0;
1020         req->hdr.nlmsg_seq = request_seq++;
1021         req->msg.rtgen_family = AF_INET;
1022
1023         return queue_request(req);
1024 }
1025
1026 static int send_getaddr(void)
1027 {
1028         struct rtnl_request *req;
1029
1030         DBG("");
1031
1032         req = g_try_malloc0(RTNL_REQUEST_SIZE);
1033         if (req == NULL)
1034                 return -ENOMEM;
1035
1036         req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
1037         req->hdr.nlmsg_type = RTM_GETADDR;
1038         req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1039         req->hdr.nlmsg_pid = 0;
1040         req->hdr.nlmsg_seq = request_seq++;
1041         req->msg.rtgen_family = AF_INET;
1042
1043         return queue_request(req);
1044 }
1045
1046 static int send_getroute(void)
1047 {
1048         struct rtnl_request *req;
1049
1050         DBG("");
1051
1052         req = g_try_malloc0(RTNL_REQUEST_SIZE);
1053         if (req == NULL)
1054                 return -ENOMEM;
1055
1056         req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
1057         req->hdr.nlmsg_type = RTM_GETROUTE;
1058         req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1059         req->hdr.nlmsg_pid = 0;
1060         req->hdr.nlmsg_seq = request_seq++;
1061         req->msg.rtgen_family = AF_INET;
1062
1063         return queue_request(req);
1064 }
1065
1066 int __connman_rtnl_request_update(void)
1067 {
1068         return send_getlink();
1069 }
1070
1071 int __connman_rtnl_init(void)
1072 {
1073         struct sockaddr_nl addr;
1074         int sk;
1075
1076         DBG("");
1077
1078         sk = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
1079         if (sk < 0)
1080                 return -1;
1081
1082         memset(&addr, 0, sizeof(addr));
1083         addr.nl_family = AF_NETLINK;
1084         addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE;
1085
1086         if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1087                 close(sk);
1088                 return -1;
1089         }
1090
1091         channel = g_io_channel_unix_new(sk);
1092         g_io_channel_set_close_on_unref(channel, TRUE);
1093
1094         g_io_add_watch(channel, G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
1095                                                         netlink_event, NULL);
1096
1097         return 0;
1098 }
1099
1100 void __connman_rtnl_start(void)
1101 {
1102         DBG("");
1103
1104         send_getlink();
1105         send_getaddr();
1106         send_getroute();
1107 }
1108
1109 void __connman_rtnl_cleanup(void)
1110 {
1111         GSList *list;
1112
1113         DBG("");
1114
1115         for (list = watch_list; list; list = list->next) {
1116                 struct watch_data *watch = list->data;
1117
1118                 DBG("removing watch %d", watch->id);
1119
1120                 g_free(watch);
1121                 list->data = NULL;
1122         }
1123
1124         g_slist_free(watch_list);
1125         watch_list = NULL;
1126
1127         for (list = request_list; list; list = list->next) {
1128                 struct rtnl_request *req = list->data;
1129
1130                 DBG("%s len %d type %d flags 0x%04x seq %d",
1131                                 type2string(req->hdr.nlmsg_type),
1132                                 req->hdr.nlmsg_len, req->hdr.nlmsg_type,
1133                                 req->hdr.nlmsg_flags, req->hdr.nlmsg_seq);
1134
1135                 g_free(req);
1136                 list->data = NULL;
1137         }
1138
1139         g_slist_free(request_list);
1140         request_list = NULL;
1141
1142         g_io_channel_shutdown(channel, TRUE, NULL);
1143         g_io_channel_unref(channel);
1144
1145         channel = NULL;
1146 }