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