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