Track link address and MTU settings
[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                                 const char **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                                 *address = RTA_DATA(attr);
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         const char *address = NULL;
286         const char *ifname = NULL;
287         unsigned int mtu = 0;
288         unsigned char operstate = 0xff;
289         GSList *list;
290
291         extract_link(msg, bytes, &address, &ifname, &mtu, &operstate);
292
293         switch (type) {
294         case ARPHRD_ETHER:
295         case ARPHRD_LOOPBACK:
296         case ARPHRD_NONE:
297                 __connman_ipconfig_newlink(index, type, flags, address, mtu);
298                 break;
299         }
300
301         if (address != NULL && strlen(address) > 0)
302                 connman_info("%s {newlink} index %d address %s mtu %u",
303                                                 ifname, index, address, mtu);
304
305         if (operstate != 0xff)
306                 connman_info("%s {newlink} index %d operstate %u <%s>",
307                                                 ifname, index, operstate,
308                                                 operstate2str(operstate));
309
310         for (list = rtnl_list; list; list = list->next) {
311                 struct connman_rtnl *rtnl = list->data;
312
313                 if (rtnl->newlink)
314                         rtnl->newlink(type, index, flags, change);
315         }
316
317         for (list = watch_list; list; list = list->next) {
318                 struct watch_data *watch = list->data;
319
320                 if (watch->index != index)
321                         continue;
322
323                 if (operstate != 0xff && watch->operstate)
324                         watch->operstate(operstate, watch->user_data);
325
326                 if (watch->newlink)
327                         watch->newlink(flags, change, watch->user_data);
328         }
329 }
330
331 static void process_dellink(unsigned short type, int index, unsigned flags,
332                         unsigned change, struct ifinfomsg *msg, int bytes)
333 {
334         const char *address = NULL;
335         const char *ifname = NULL;
336         unsigned int mtu = 0;
337         unsigned char operstate = 0xff;
338         GSList *list;
339
340         extract_link(msg, bytes, &address, &ifname, &mtu, &operstate);
341
342         if (operstate != 0xff)
343                 connman_info("%s {dellink} index %d operstate %u <%s>",
344                                                 ifname, index, operstate,
345                                                 operstate2str(operstate));
346
347         for (list = watch_list; list; list = list->next) {
348                 struct watch_data *watch = list->data;
349
350                 if (watch->index != index)
351                         continue;
352
353                 if (operstate != 0xff && watch->operstate)
354                         watch->operstate(operstate, watch->user_data);
355         }
356
357         for (list = rtnl_list; list; list = list->next) {
358                 struct connman_rtnl *rtnl = list->data;
359
360                 if (rtnl->dellink)
361                         rtnl->dellink(type, index, flags, change);
362         }
363
364         switch (type) {
365         case ARPHRD_ETHER:
366         case ARPHRD_LOOPBACK:
367         case ARPHRD_NONE:
368                 __connman_ipconfig_dellink(index);
369                 break;
370         }
371 }
372
373 static void extract_addr(struct ifaddrmsg *msg, int bytes,
374                                                 const char **label,
375                                                 struct in_addr *local,
376                                                 struct in_addr *address,
377                                                 struct in_addr *broadcast)
378 {
379         struct rtattr *attr;
380
381         for (attr = IFA_RTA(msg); RTA_OK(attr, bytes);
382                                         attr = RTA_NEXT(attr, bytes)) {
383                 switch (attr->rta_type) {
384                 case IFA_ADDRESS:
385                         if (address != NULL)
386                                 *address = *((struct in_addr *) RTA_DATA(attr));
387                         break;
388                 case IFA_LOCAL:
389                         if (local != NULL)
390                                 *local = *((struct in_addr *) RTA_DATA(attr));
391                         break;
392                 case IFA_BROADCAST:
393                         if (broadcast != NULL)
394                                 *broadcast = *((struct in_addr *) RTA_DATA(attr));
395                         break;
396                 case IFA_LABEL:
397                         if (label != NULL)
398                                 *label = RTA_DATA(attr);
399                         break;
400                 }
401         }
402 }
403
404 static void process_newaddr(unsigned char family, unsigned char prefixlen,
405                                 int index, struct ifaddrmsg *msg, int bytes)
406 {
407         struct in_addr address = { INADDR_ANY };
408         const char *label = NULL;
409
410         if (family != AF_INET)
411                 return;
412
413         extract_addr(msg, bytes, &label, &address, NULL, NULL);
414
415         __connman_ipconfig_newaddr(index, label,
416                                         prefixlen, inet_ntoa(address));
417 }
418
419 static void process_deladdr(unsigned char family, unsigned char prefixlen,
420                                 int index, struct ifaddrmsg *msg, int bytes)
421 {
422         struct in_addr address = { INADDR_ANY };
423         const char *label = NULL;
424
425         if (family != AF_INET)
426                 return;
427
428         extract_addr(msg, bytes, &label, &address, NULL, NULL);
429
430         __connman_ipconfig_deladdr(index, label,
431                                         prefixlen, inet_ntoa(address));
432 }
433
434 static void extract_route(struct rtmsg *msg, int bytes, int *index,
435                                                 struct in_addr *dst,
436                                                 struct in_addr *gateway)
437 {
438         struct rtattr *attr;
439
440         for (attr = RTM_RTA(msg); RTA_OK(attr, bytes);
441                                         attr = RTA_NEXT(attr, bytes)) {
442                 switch (attr->rta_type) {
443                 case RTA_DST:
444                         if (dst != NULL)
445                                 *dst = *((struct in_addr *) RTA_DATA(attr));
446                         break;
447                 case RTA_GATEWAY:
448                         if (gateway != NULL)
449                                 *gateway = *((struct in_addr *) RTA_DATA(attr));
450                         break;
451                 case RTA_OIF:
452                         if (index != NULL)
453                                 *index = *((int *) RTA_DATA(attr));
454                         break;
455                 }
456         }
457 }
458
459 static void process_newroute(unsigned char family, unsigned char scope,
460                                                 struct rtmsg *msg, int bytes)
461 {
462         GSList *list;
463         struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY };
464         char dststr[16], gatewaystr[16];
465         int index = -1;
466
467         if (family != AF_INET)
468                 return;
469
470         extract_route(msg, bytes, &index, &dst, &gateway);
471
472         inet_ntop(family, &dst, dststr, sizeof(dststr));
473         inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr));
474
475         __connman_ipconfig_newroute(index, scope, dststr, gatewaystr);
476
477         if (scope != RT_SCOPE_UNIVERSE || dst.s_addr != INADDR_ANY)
478                 return;
479
480         for (list = rtnl_list; list; list = list->next) {
481                 struct connman_rtnl *rtnl = list->data;
482
483                 if (rtnl->newgateway)
484                         rtnl->newgateway(index, gatewaystr);
485         }
486 }
487
488 static void process_delroute(unsigned char family, unsigned char scope,
489                                                 struct rtmsg *msg, int bytes)
490 {
491         GSList *list;
492         struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY };
493         char dststr[16], gatewaystr[16];
494         int index = -1;
495
496         if (family != AF_INET)
497                 return;
498
499         extract_route(msg, bytes, &index, &dst, &gateway);
500
501         inet_ntop(family, &dst, dststr, sizeof(dststr));
502         inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr));
503
504         __connman_ipconfig_delroute(index, scope, dststr, gatewaystr);
505
506         if (scope != RT_SCOPE_UNIVERSE || dst.s_addr != INADDR_ANY)
507                 return;
508
509         for (list = rtnl_list; list; list = list->next) {
510                 struct connman_rtnl *rtnl = list->data;
511
512                 if (rtnl->delgateway)
513                         rtnl->delgateway(index, gatewaystr);
514         }
515 }
516
517 static inline void print_ether(struct rtattr *attr, const char *name)
518 {
519         int len = (int) RTA_PAYLOAD(attr);
520
521         if (len == ETH_ALEN) {
522                 struct ether_addr eth;
523                 memcpy(&eth, RTA_DATA(attr), ETH_ALEN);
524                 print("  attr %s (len %d) %s\n", name, len, ether_ntoa(&eth));
525         } else
526                 print("  attr %s (len %d)\n", name, len);
527 }
528
529 static inline void print_inet(struct rtattr *attr, const char *name,
530                                                         unsigned char family)
531 {
532         int len = (int) RTA_PAYLOAD(attr);
533
534         if (family == AF_INET && len == sizeof(struct in_addr)) {
535                 struct in_addr addr;
536                 addr = *((struct in_addr *) RTA_DATA(attr));
537                 print("  attr %s (len %d) %s\n", name, len, inet_ntoa(addr));
538         } else
539                 print("  attr %s (len %d)\n", name, len);
540 }
541
542 static inline void print_string(struct rtattr *attr, const char *name)
543 {
544         print("  attr %s (len %d) %s\n", name, (int) RTA_PAYLOAD(attr),
545                                                 (char *) RTA_DATA(attr));
546 }
547
548 static inline void print_byte(struct rtattr *attr, const char *name)
549 {
550         print("  attr %s (len %d) 0x%02x\n", name, (int) RTA_PAYLOAD(attr),
551                                         *((unsigned char *) RTA_DATA(attr)));
552 }
553
554 static inline void print_integer(struct rtattr *attr, const char *name)
555 {
556         print("  attr %s (len %d) %d\n", name, (int) RTA_PAYLOAD(attr),
557                                                 *((int *) RTA_DATA(attr)));
558 }
559
560 static inline void print_attr(struct rtattr *attr, const char *name)
561 {
562         int len = (int) RTA_PAYLOAD(attr);
563
564         if (name && len > 0)
565                 print("  attr %s (len %d)\n", name, len);
566         else
567                 print("  attr %d (len %d)\n", attr->rta_type, len);
568 }
569
570 static void rtnl_link(struct nlmsghdr *hdr)
571 {
572         struct ifinfomsg *msg;
573         struct rtattr *attr;
574         int bytes;
575
576         msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
577         bytes = IFLA_PAYLOAD(hdr);
578
579         print("ifi_index %d ifi_flags 0x%04x", msg->ifi_index, msg->ifi_flags);
580
581         for (attr = IFLA_RTA(msg); RTA_OK(attr, bytes);
582                                         attr = RTA_NEXT(attr, bytes)) {
583                 switch (attr->rta_type) {
584                 case IFLA_ADDRESS:
585                         print_ether(attr, "address");
586                         break;
587                 case IFLA_BROADCAST:
588                         print_ether(attr, "broadcast");
589                         break;
590                 case IFLA_IFNAME:
591                         print_string(attr, "ifname");
592                         break;
593                 case IFLA_MTU:
594                         print_integer(attr, "mtu");
595                         break;
596                 case IFLA_LINK:
597                         print_attr(attr, "link");
598                         break;
599                 case IFLA_QDISC:
600                         print_attr(attr, "qdisc");
601                         break;
602                 case IFLA_STATS:
603                         print_attr(attr, "stats");
604                         break;
605                 case IFLA_COST:
606                         print_attr(attr, "cost");
607                         break;
608                 case IFLA_PRIORITY:
609                         print_attr(attr, "priority");
610                         break;
611                 case IFLA_MASTER:
612                         print_attr(attr, "master");
613                         break;
614                 case IFLA_WIRELESS:
615                         print_attr(attr, "wireless");
616                         break;
617                 case IFLA_PROTINFO:
618                         print_attr(attr, "protinfo");
619                         break;
620                 case IFLA_TXQLEN:
621                         print_integer(attr, "txqlen");
622                         break;
623                 case IFLA_MAP:
624                         print_attr(attr, "map");
625                         break;
626                 case IFLA_WEIGHT:
627                         print_attr(attr, "weight");
628                         break;
629                 case IFLA_OPERSTATE:
630                         print_byte(attr, "operstate");
631                         break;
632                 case IFLA_LINKMODE:
633                         print_byte(attr, "linkmode");
634                         break;
635                 default:
636                         print_attr(attr, NULL);
637                         break;
638                 }
639         }
640 }
641
642 static void rtnl_newlink(struct nlmsghdr *hdr)
643 {
644         struct ifinfomsg *msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
645
646         rtnl_link(hdr);
647
648         process_newlink(msg->ifi_type, msg->ifi_index, msg->ifi_flags,
649                                 msg->ifi_change, msg, IFA_PAYLOAD(hdr));
650 }
651
652 static void rtnl_dellink(struct nlmsghdr *hdr)
653 {
654         struct ifinfomsg *msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
655
656         rtnl_link(hdr);
657
658         process_dellink(msg->ifi_type, msg->ifi_index, msg->ifi_flags,
659                                 msg->ifi_change, msg, IFA_PAYLOAD(hdr));
660 }
661
662 static void rtnl_addr(struct nlmsghdr *hdr)
663 {
664         struct ifaddrmsg *msg;
665         struct rtattr *attr;
666         int bytes;
667
668         msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
669         bytes = IFA_PAYLOAD(hdr);
670
671         print("ifa_family %d ifa_index %d", msg->ifa_family, msg->ifa_index);
672
673         for (attr = IFA_RTA(msg); RTA_OK(attr, bytes);
674                                         attr = RTA_NEXT(attr, bytes)) {
675                 switch (attr->rta_type) {
676                 case IFA_ADDRESS:
677                         print_inet(attr, "address", msg->ifa_family);
678                         break;
679                 case IFA_LOCAL:
680                         print_inet(attr, "local", msg->ifa_family);
681                         break;
682                 case IFA_LABEL:
683                         print_string(attr, "label");
684                         break;
685                 case IFA_BROADCAST:
686                         print_inet(attr, "broadcast", msg->ifa_family);
687                         break;
688                 case IFA_ANYCAST:
689                         print_attr(attr, "anycast");
690                         break;
691                 case IFA_CACHEINFO:
692                         print_attr(attr, "cacheinfo");
693                         break;
694                 case IFA_MULTICAST:
695                         print_attr(attr, "multicast");
696                         break;
697                 default:
698                         print_attr(attr, NULL);
699                         break;
700                 }
701         }
702 }
703
704 static void rtnl_newaddr(struct nlmsghdr *hdr)
705 {
706         struct ifaddrmsg *msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
707
708         rtnl_addr(hdr);
709
710         process_newaddr(msg->ifa_family, msg->ifa_prefixlen, msg->ifa_index,
711                                                 msg, IFA_PAYLOAD(hdr));
712 }
713
714 static void rtnl_deladdr(struct nlmsghdr *hdr)
715 {
716         struct ifaddrmsg *msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
717
718         rtnl_addr(hdr);
719
720         process_deladdr(msg->ifa_family, msg->ifa_prefixlen, msg->ifa_index,
721                                                 msg, IFA_PAYLOAD(hdr));
722 }
723
724 static void rtnl_route(struct nlmsghdr *hdr)
725 {
726         struct rtmsg *msg;
727         struct rtattr *attr;
728         int bytes;
729
730         msg = (struct rtmsg *) NLMSG_DATA(hdr);
731         bytes = RTM_PAYLOAD(hdr);
732
733         print("rtm_family %d rtm_table %d rtm_protocol %d",
734                         msg->rtm_family, msg->rtm_table, msg->rtm_protocol);
735         print("rtm_scope %d rtm_type %d rtm_flags 0x%04x",
736                                 msg->rtm_scope, msg->rtm_type, msg->rtm_flags);
737
738         for (attr = RTM_RTA(msg); RTA_OK(attr, bytes);
739                                         attr = RTA_NEXT(attr, bytes)) {
740                 switch (attr->rta_type) {
741                 case RTA_DST:
742                         print_inet(attr, "dst", msg->rtm_family);
743                         break;
744                 case RTA_SRC:
745                         print_inet(attr, "src", msg->rtm_family);
746                         break;
747                 case RTA_IIF:
748                         print_string(attr, "iif");
749                         break;
750                 case RTA_OIF:
751                         print_integer(attr, "oif");
752                         break;
753                 case RTA_GATEWAY:
754                         print_inet(attr, "gateway", msg->rtm_family);
755                         break;
756                 case RTA_PRIORITY:
757                         print_attr(attr, "priority");
758                         break;
759                 case RTA_PREFSRC:
760                         print_inet(attr, "prefsrc", msg->rtm_family);
761                         break;
762                 case RTA_METRICS:
763                         print_attr(attr, "metrics");
764                         break;
765                 case RTA_TABLE:
766                         print_integer(attr, "table");
767                         break;
768                 default:
769                         print_attr(attr, NULL);
770                         break;
771                 }
772         }
773 }
774
775 static void rtnl_newroute(struct nlmsghdr *hdr)
776 {
777         struct rtmsg *msg = (struct rtmsg *) NLMSG_DATA(hdr);
778
779         rtnl_route(hdr);
780
781         if (msg->rtm_table == RT_TABLE_MAIN &&
782                                 msg->rtm_protocol == RTPROT_BOOT &&
783                                                 msg->rtm_type == RTN_UNICAST)
784                 process_newroute(msg->rtm_family, msg->rtm_scope,
785                                                 msg, RTM_PAYLOAD(hdr));
786 }
787
788 static void rtnl_delroute(struct nlmsghdr *hdr)
789 {
790         struct rtmsg *msg = (struct rtmsg *) NLMSG_DATA(hdr);
791
792         rtnl_route(hdr);
793
794         if (msg->rtm_table == RT_TABLE_MAIN &&
795                                 msg->rtm_protocol == RTPROT_BOOT &&
796                                                 msg->rtm_type == RTN_UNICAST)
797                 process_delroute(msg->rtm_family, msg->rtm_scope,
798                                                 msg, RTM_PAYLOAD(hdr));
799 }
800
801 static const char *type2string(uint16_t type)
802 {
803         switch (type) {
804         case NLMSG_NOOP:
805                 return "NOOP";
806         case NLMSG_ERROR:
807                 return "ERROR";
808         case NLMSG_DONE:
809                 return "DONE";
810         case NLMSG_OVERRUN:
811                 return "OVERRUN";
812         case RTM_GETLINK:
813                 return "GETLINK";
814         case RTM_NEWLINK:
815                 return "NEWLINK";
816         case RTM_DELLINK:
817                 return "DELLINK";
818         case RTM_NEWADDR:
819                 return "NEWADDR";
820         case RTM_DELADDR:
821                 return "DELADDR";
822         case RTM_GETROUTE:
823                 return "GETROUTE";
824         case RTM_NEWROUTE:
825                 return "NEWROUTE";
826         case RTM_DELROUTE:
827                 return "DELROUTE";
828         default:
829                 return "UNKNOWN";
830         }
831 }
832
833 static GIOChannel *channel = NULL;
834
835 struct rtnl_request {
836         struct nlmsghdr hdr;
837         struct rtgenmsg msg;
838 };
839 #define RTNL_REQUEST_SIZE  (sizeof(struct nlmsghdr) + sizeof(struct rtgenmsg))
840
841 static GSList *request_list = NULL;
842 static guint32 request_seq = 0;
843
844 static struct rtnl_request *find_request(guint32 seq)
845 {
846         GSList *list;
847
848         for (list = request_list; list; list = list->next) {
849                 struct rtnl_request *req = list->data;
850
851                 if (req->hdr.nlmsg_seq == seq)
852                         return req;
853         }
854
855         return NULL;
856 }
857
858 static int send_request(struct rtnl_request *req)
859 {
860         struct sockaddr_nl addr;
861         int sk;
862
863         DBG("%s len %d type %d flags 0x%04x seq %d",
864                                 type2string(req->hdr.nlmsg_type),
865                                 req->hdr.nlmsg_len, req->hdr.nlmsg_type,
866                                 req->hdr.nlmsg_flags, req->hdr.nlmsg_seq);
867
868         sk = g_io_channel_unix_get_fd(channel);
869
870         memset(&addr, 0, sizeof(addr));
871         addr.nl_family = AF_NETLINK;
872
873         return sendto(sk, req, req->hdr.nlmsg_len, 0,
874                                 (struct sockaddr *) &addr, sizeof(addr));
875 }
876
877 static int queue_request(struct rtnl_request *req)
878 {
879         request_list = g_slist_append(request_list, req);
880
881         if (g_slist_length(request_list) > 1)
882                 return 0;
883
884         return send_request(req);
885 }
886
887 static int process_response(guint32 seq)
888 {
889         struct rtnl_request *req;
890
891         DBG("seq %d", seq);
892
893         req = find_request(seq);
894         if (req != NULL) {
895                 request_list = g_slist_remove(request_list, req);
896                 g_free(req);
897         }
898
899         req = g_slist_nth_data(request_list, 0);
900         if (req == NULL)
901                 return 0;
902
903         return send_request(req);
904 }
905
906 static void rtnl_message(void *buf, size_t len)
907 {
908         DBG("buf %p len %zd", buf, len);
909
910         while (len > 0) {
911                 struct nlmsghdr *hdr = buf;
912                 struct nlmsgerr *err;
913
914                 if (!NLMSG_OK(hdr, len))
915                         break;
916
917                 DBG("%s len %d type %d flags 0x%04x seq %d",
918                                         type2string(hdr->nlmsg_type),
919                                         hdr->nlmsg_len, hdr->nlmsg_type,
920                                         hdr->nlmsg_flags, hdr->nlmsg_seq);
921
922                 switch (hdr->nlmsg_type) {
923                 case NLMSG_NOOP:
924                 case NLMSG_OVERRUN:
925                         return;
926                 case NLMSG_DONE:
927                         process_response(hdr->nlmsg_seq);
928                         return;
929                 case NLMSG_ERROR:
930                         err = NLMSG_DATA(hdr);
931                         DBG("error %d (%s)", -err->error,
932                                                 strerror(-err->error));
933                         return;
934                 case RTM_NEWLINK:
935                         rtnl_newlink(hdr);
936                         break;
937                 case RTM_DELLINK:
938                         rtnl_dellink(hdr);
939                         break;
940                 case RTM_NEWADDR:
941                         rtnl_newaddr(hdr);
942                         break;
943                 case RTM_DELADDR:
944                         rtnl_deladdr(hdr);
945                         break;
946                 case RTM_NEWROUTE:
947                         rtnl_newroute(hdr);
948                         break;
949                 case RTM_DELROUTE:
950                         rtnl_delroute(hdr);
951                         break;
952                 }
953
954                 len -= hdr->nlmsg_len;
955                 buf += hdr->nlmsg_len;
956         }
957 }
958
959 static gboolean netlink_event(GIOChannel *chan,
960                                 GIOCondition cond, gpointer data)
961 {
962         unsigned char buf[4096];
963         gsize len;
964         GIOError err;
965
966         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
967                 return FALSE;
968
969         memset(buf, 0, sizeof(buf));
970
971         err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len);
972         if (err) {
973                 if (err == G_IO_ERROR_AGAIN)
974                         return TRUE;
975                 return FALSE;
976         }
977
978         rtnl_message(buf, len);
979
980         return TRUE;
981 }
982
983 static int send_getlink(void)
984 {
985         struct rtnl_request *req;
986
987         DBG("");
988
989         req = g_try_malloc0(RTNL_REQUEST_SIZE);
990         if (req == NULL)
991                 return -ENOMEM;
992
993         req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
994         req->hdr.nlmsg_type = RTM_GETLINK;
995         req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
996         req->hdr.nlmsg_pid = 0;
997         req->hdr.nlmsg_seq = request_seq++;
998         req->msg.rtgen_family = AF_INET;
999
1000         return queue_request(req);
1001 }
1002
1003 static int send_getaddr(void)
1004 {
1005         struct rtnl_request *req;
1006
1007         DBG("");
1008
1009         req = g_try_malloc0(RTNL_REQUEST_SIZE);
1010         if (req == NULL)
1011                 return -ENOMEM;
1012
1013         req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
1014         req->hdr.nlmsg_type = RTM_GETADDR;
1015         req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1016         req->hdr.nlmsg_pid = 0;
1017         req->hdr.nlmsg_seq = request_seq++;
1018         req->msg.rtgen_family = AF_INET;
1019
1020         return queue_request(req);
1021 }
1022
1023 static int send_getroute(void)
1024 {
1025         struct rtnl_request *req;
1026
1027         DBG("");
1028
1029         req = g_try_malloc0(RTNL_REQUEST_SIZE);
1030         if (req == NULL)
1031                 return -ENOMEM;
1032
1033         req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
1034         req->hdr.nlmsg_type = RTM_GETROUTE;
1035         req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1036         req->hdr.nlmsg_pid = 0;
1037         req->hdr.nlmsg_seq = request_seq++;
1038         req->msg.rtgen_family = AF_INET;
1039
1040         return queue_request(req);
1041 }
1042
1043 int __connman_rtnl_init(void)
1044 {
1045         struct sockaddr_nl addr;
1046         int sk;
1047
1048         DBG("");
1049
1050         sk = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
1051         if (sk < 0)
1052                 return -1;
1053
1054         memset(&addr, 0, sizeof(addr));
1055         addr.nl_family = AF_NETLINK;
1056         addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE;
1057
1058         if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1059                 close(sk);
1060                 return -1;
1061         }
1062
1063         channel = g_io_channel_unix_new(sk);
1064         g_io_channel_set_close_on_unref(channel, TRUE);
1065
1066         g_io_add_watch(channel, G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
1067                                                         netlink_event, NULL);
1068
1069         return 0;
1070 }
1071
1072 void __connman_rtnl_start(void)
1073 {
1074         DBG("");
1075
1076         send_getlink();
1077         send_getaddr();
1078         send_getroute();
1079 }
1080
1081 void __connman_rtnl_cleanup(void)
1082 {
1083         GSList *list;
1084
1085         DBG("");
1086
1087         for (list = watch_list; list; list = list->next) {
1088                 struct watch_data *watch = list->data;
1089
1090                 DBG("removing watch %d", watch->id);
1091
1092                 g_free(watch);
1093                 list->data = NULL;
1094         }
1095
1096         g_slist_free(watch_list);
1097         watch_list = NULL;
1098
1099         for (list = request_list; list; list = list->next) {
1100                 struct rtnl_request *req = list->data;
1101
1102                 DBG("%s len %d type %d flags 0x%04x seq %d",
1103                                 type2string(req->hdr.nlmsg_type),
1104                                 req->hdr.nlmsg_len, req->hdr.nlmsg_type,
1105                                 req->hdr.nlmsg_flags, req->hdr.nlmsg_seq);
1106
1107                 g_free(req);
1108                 list->data = NULL;
1109         }
1110
1111         g_slist_free(request_list);
1112         request_list = NULL;
1113
1114         g_io_channel_shutdown(channel, TRUE, NULL);
1115         g_io_channel_unref(channel);
1116
1117         channel = NULL;
1118 }