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