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