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