0f3ba0fe4d0d8c2508bee110692455609d3387d9
[platform/upstream/connman.git] / src / rtnl.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <sys/socket.h>
30 #include <arpa/inet.h>
31 #include <netinet/ether.h>
32 #include <net/if_arp.h>
33 #include <linux/if.h>
34 #include <linux/netlink.h>
35 #include <linux/rtnetlink.h>
36
37 #include <glib.h>
38
39 #include "connman.h"
40
41 #define print(arg...) do { } while (0)
42 //#define print(arg...) connman_info(arg)
43
44 struct watch_data {
45         unsigned int id;
46         int index;
47         connman_rtnl_operstate_cb_t operstate;
48         connman_rtnl_link_cb_t newlink;
49         void *user_data;
50 };
51
52 static GSList *watch_list = NULL;
53 static unsigned int watch_id = 0;
54
55 static GSList *update_list = NULL;
56 static guint update_interval = G_MAXUINT;
57 static guint update_timeout = 0;
58
59 struct interface_data {
60         int index;
61         char *name;
62         enum connman_service_type type;
63 };
64
65 static GHashTable *interface_list = NULL;
66
67 static void free_interface(gpointer data)
68 {
69         struct interface_data *interface = data;
70
71         __connman_technology_remove_interface(interface->type,
72                                         interface->index, interface->name);
73
74         g_free(interface->name);
75         g_free(interface);
76 }
77
78 static connman_bool_t ether_blacklisted(const char *name)
79 {
80         if (name == NULL)
81                 return TRUE;
82
83         /* virtual interface from VMware */
84         if (g_str_has_prefix(name, "vmnet") == TRUE)
85                 return TRUE;
86
87         /* virtual interface from VirtualBox */
88         if (g_str_has_prefix(name, "vboxnet") == TRUE)
89                 return TRUE;
90
91         return FALSE;
92 }
93
94 static void read_uevent(struct interface_data *interface)
95 {
96         char *filename, line[128];
97         FILE *f;
98
99         filename = g_strdup_printf("/sys/class/net/%s/uevent",
100                                                 interface->name);
101
102         f = fopen(filename, "re");
103         if (f == NULL)
104                 return;
105
106         while (fgets(line, sizeof(line), f)) {
107                 char *pos;
108
109                 pos = strchr(line, '\n');
110                 if (pos == NULL)
111                         continue;
112                 pos[0] = '\0';
113
114                 if (strncmp(line, "DEVTYPE=", 8) != 0)
115                         continue;
116
117                 if (strcmp(line + 8, "wlan") == 0)
118                         interface->type = CONNMAN_SERVICE_TYPE_WIFI;
119                 else if (strcmp(line + 8, "wwan") == 0)
120                         interface->type = CONNMAN_SERVICE_TYPE_CELLULAR;
121                 else if (strcmp(line + 8, "bluetooth") == 0)
122                         interface->type = CONNMAN_SERVICE_TYPE_BLUETOOTH;
123                 else if (strcmp(line + 8, "wimax") == 0)
124                         interface->type = CONNMAN_SERVICE_TYPE_WIMAX;
125         }
126
127         fclose(f);
128 }
129
130 /**
131  * connman_rtnl_add_operstate_watch:
132  * @index: network device index
133  * @callback: callback function
134  * @user_data: callback data;
135  *
136  * Add a new RTNL watch for operation state events
137  *
138  * Returns: %0 on failure and a unique id on success
139  */
140 unsigned int connman_rtnl_add_operstate_watch(int index,
141                         connman_rtnl_operstate_cb_t callback, void *user_data)
142 {
143         struct watch_data *watch;
144
145         watch = g_try_new0(struct watch_data, 1);
146         if (watch == NULL)
147                 return 0;
148
149         watch->id = ++watch_id;
150         watch->index = index;
151
152         watch->operstate = callback;
153         watch->user_data = user_data;
154
155         watch_list = g_slist_prepend(watch_list, watch);
156
157         DBG("id %d", watch->id);
158
159         if (callback) {
160                 unsigned char operstate = 0;
161
162                 if (operstate > 0)
163                         callback(operstate, user_data);
164         }
165
166         return watch->id;
167 }
168
169 /**
170  * connman_rtnl_add_newlink_watch:
171  * @index: network device index
172  * @callback: callback function
173  * @user_data: callback data;
174  *
175  * Add a new RTNL watch for newlink events
176  *
177  * Returns: %0 on failure and a unique id on success
178  */
179 unsigned int connman_rtnl_add_newlink_watch(int index,
180                         connman_rtnl_link_cb_t callback, void *user_data)
181 {
182         struct watch_data *watch;
183
184         watch = g_try_new0(struct watch_data, 1);
185         if (watch == NULL)
186                 return 0;
187
188         watch->id = ++watch_id;
189         watch->index = index;
190
191         watch->newlink = callback;
192         watch->user_data = user_data;
193
194         watch_list = g_slist_prepend(watch_list, watch);
195
196         DBG("id %d", watch->id);
197
198         if (callback) {
199                 unsigned int flags = __connman_ipconfig_get_flags(index);
200
201                 if (flags > 0)
202                         callback(flags, 0, user_data);
203         }
204
205         return watch->id;
206 }
207
208 /**
209  * connman_rtnl_remove_watch:
210  * @id: watch identifier
211  *
212  * Remove the RTNL watch for the identifier
213  */
214 void connman_rtnl_remove_watch(unsigned int id)
215 {
216         GSList *list;
217
218         DBG("id %d", id);
219
220         if (id == 0)
221                 return;
222
223         for (list = watch_list; list; list = list->next) {
224                 struct watch_data *watch = list->data;
225
226                 if (watch->id  == id) {
227                         watch_list = g_slist_remove(watch_list, watch);
228                         g_free(watch);
229                         break;
230                 }
231         }
232 }
233
234 static void trigger_rtnl(int index, void *user_data)
235 {
236         struct connman_rtnl *rtnl = user_data;
237
238         if (rtnl->newlink) {
239                 unsigned short type = __connman_ipconfig_get_type(index);
240                 unsigned int flags = __connman_ipconfig_get_flags(index);
241
242                 rtnl->newlink(type, index, flags, 0);
243         }
244
245         if (rtnl->newgateway) {
246                 const char *gateway = __connman_ipconfig_get_gateway(index);
247
248                 if (gateway != NULL)
249                         rtnl->newgateway(index, gateway);
250         }
251 }
252
253 static GSList *rtnl_list = NULL;
254
255 static gint compare_priority(gconstpointer a, gconstpointer b)
256 {
257         const struct connman_rtnl *rtnl1 = a;
258         const struct connman_rtnl *rtnl2 = b;
259
260         return rtnl2->priority - rtnl1->priority;
261 }
262
263 /**
264  * connman_rtnl_register:
265  * @rtnl: RTNL module
266  *
267  * Register a new RTNL module
268  *
269  * Returns: %0 on success
270  */
271 int connman_rtnl_register(struct connman_rtnl *rtnl)
272 {
273         DBG("rtnl %p name %s", rtnl, rtnl->name);
274
275         rtnl_list = g_slist_insert_sorted(rtnl_list, rtnl,
276                                                         compare_priority);
277
278         __connman_ipconfig_foreach(trigger_rtnl, rtnl);
279
280         return 0;
281 }
282
283 /**
284  * connman_rtnl_unregister:
285  * @rtnl: RTNL module
286  *
287  * Remove a previously registered RTNL module
288  */
289 void connman_rtnl_unregister(struct connman_rtnl *rtnl)
290 {
291         DBG("rtnl %p name %s", rtnl, rtnl->name);
292
293         rtnl_list = g_slist_remove(rtnl_list, rtnl);
294 }
295
296 static const char *operstate2str(unsigned char operstate)
297 {
298         switch (operstate) {
299         case IF_OPER_UNKNOWN:
300                 return "UNKNOWN";
301         case IF_OPER_NOTPRESENT:
302                 return "NOT-PRESENT";
303         case IF_OPER_DOWN:
304                 return "DOWN";
305         case IF_OPER_LOWERLAYERDOWN:
306                 return "LOWER-LAYER-DOWN";
307         case IF_OPER_TESTING:
308                 return "TESTING";
309         case IF_OPER_DORMANT:
310                 return "DORMANT";
311         case IF_OPER_UP:
312                 return "UP";
313         }
314
315         return "";
316 }
317
318 static void extract_link(struct ifinfomsg *msg, int bytes,
319                                 struct ether_addr *address, const char **ifname,
320                                 unsigned int *mtu, unsigned char *operstate,
321                                                 struct rtnl_link_stats *stats)
322 {
323         struct rtattr *attr;
324
325         for (attr = IFLA_RTA(msg); RTA_OK(attr, bytes);
326                                         attr = RTA_NEXT(attr, bytes)) {
327                 switch (attr->rta_type) {
328                 case IFLA_ADDRESS:
329                         if (address != NULL)
330                                 memcpy(address, RTA_DATA(attr), ETH_ALEN);
331                         break;
332                 case IFLA_IFNAME:
333                         if (ifname != NULL)
334                                 *ifname = RTA_DATA(attr);
335                         break;
336                 case IFLA_MTU:
337                         if (mtu != NULL)
338                                 *mtu = *((unsigned int *) RTA_DATA(attr));
339                         break;
340                 case IFLA_STATS:
341                         if (stats != NULL)
342                                 memcpy(stats, RTA_DATA(attr),
343                                         sizeof(struct rtnl_link_stats));
344                         break;
345                 case IFLA_OPERSTATE:
346                         if (operstate != NULL)
347                                 *operstate = *((unsigned char *) RTA_DATA(attr));
348                         break;
349                 case IFLA_LINKMODE:
350                         break;
351                 }
352         }
353 }
354
355 static void process_newlink(unsigned short type, int index, unsigned flags,
356                         unsigned change, struct ifinfomsg *msg, int bytes)
357 {
358         struct ether_addr address = {{ 0, 0, 0, 0, 0, 0 }};
359         struct ether_addr compare = {{ 0, 0, 0, 0, 0, 0 }};
360         struct rtnl_link_stats stats;
361         unsigned char operstate = 0xff;
362         const char *ifname = NULL;
363         unsigned int mtu = 0;
364         char str[18];
365         GSList *list;
366
367         memset(&stats, 0, sizeof(stats));
368         extract_link(msg, bytes, &address, &ifname, &mtu, &operstate, &stats);
369
370         snprintf(str, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
371                                                 address.ether_addr_octet[0],
372                                                 address.ether_addr_octet[1],
373                                                 address.ether_addr_octet[2],
374                                                 address.ether_addr_octet[3],
375                                                 address.ether_addr_octet[4],
376                                                 address.ether_addr_octet[5]);
377
378         switch (type) {
379         case ARPHRD_ETHER:
380         case ARPHRD_LOOPBACK:
381         case ARPHRD_NONE:
382                 __connman_ipconfig_newlink(index, type, flags,
383                                                         str, mtu, &stats);
384                 break;
385         }
386
387         if (memcmp(&address, &compare, ETH_ALEN) != 0)
388                 connman_info("%s {newlink} index %d address %s mtu %u",
389                                                 ifname, index, str, mtu);
390
391         if (operstate != 0xff)
392                 connman_info("%s {newlink} index %d operstate %u <%s>",
393                                                 ifname, index, operstate,
394                                                 operstate2str(operstate));
395
396         if (g_hash_table_lookup(interface_list,
397                                         GINT_TO_POINTER(index)) == NULL) {
398                 struct interface_data *interface;
399
400                 interface = g_new0(struct interface_data, 1);
401                 interface->index = index;
402                 interface->name = g_strdup(ifname);
403
404                 g_hash_table_insert(interface_list,
405                                         GINT_TO_POINTER(index), interface);
406
407                 read_uevent(interface);
408
409                 if (interface->type == CONNMAN_SERVICE_TYPE_UNKNOWN &&
410                                         type == ARPHRD_ETHER &&
411                                         ether_blacklisted(ifname) == FALSE)
412                         interface->type = CONNMAN_SERVICE_TYPE_ETHERNET;
413
414                 __connman_technology_add_interface(interface->type,
415                                         interface->index, interface->name);
416         }
417
418         for (list = rtnl_list; list; list = list->next) {
419                 struct connman_rtnl *rtnl = list->data;
420
421                 if (rtnl->newlink)
422                         rtnl->newlink(type, index, flags, change);
423         }
424
425         for (list = watch_list; list; list = list->next) {
426                 struct watch_data *watch = list->data;
427
428                 if (watch->index != index)
429                         continue;
430
431                 if (operstate != 0xff && watch->operstate)
432                         watch->operstate(operstate, watch->user_data);
433
434                 if (watch->newlink)
435                         watch->newlink(flags, change, watch->user_data);
436         }
437 }
438
439 static void process_dellink(unsigned short type, int index, unsigned flags,
440                         unsigned change, struct ifinfomsg *msg, int bytes)
441 {
442         struct rtnl_link_stats stats;
443         unsigned char operstate = 0xff;
444         const char *ifname = NULL;
445         GSList *list;
446
447         memset(&stats, 0, sizeof(stats));
448         extract_link(msg, bytes, NULL, &ifname, NULL, &operstate, &stats);
449
450         if (operstate != 0xff)
451                 connman_info("%s {dellink} index %d operstate %u <%s>",
452                                                 ifname, index, operstate,
453                                                 operstate2str(operstate));
454
455         for (list = watch_list; list; list = list->next) {
456                 struct watch_data *watch = list->data;
457
458                 if (watch->index != index)
459                         continue;
460
461                 if (operstate != 0xff && watch->operstate)
462                         watch->operstate(operstate, watch->user_data);
463         }
464
465         for (list = rtnl_list; list; list = list->next) {
466                 struct connman_rtnl *rtnl = list->data;
467
468                 if (rtnl->dellink)
469                         rtnl->dellink(type, index, flags, change);
470         }
471
472         switch (type) {
473         case ARPHRD_ETHER:
474         case ARPHRD_LOOPBACK:
475         case ARPHRD_NONE:
476                 __connman_ipconfig_dellink(index, &stats);
477                 break;
478         }
479
480         g_hash_table_remove(interface_list, GINT_TO_POINTER(index));
481 }
482
483 static void extract_addr(struct ifaddrmsg *msg, int bytes,
484                                                 const char **label,
485                                                 struct in_addr *local,
486                                                 struct in_addr *address,
487                                                 struct in_addr *broadcast)
488 {
489         struct rtattr *attr;
490
491         for (attr = IFA_RTA(msg); RTA_OK(attr, bytes);
492                                         attr = RTA_NEXT(attr, bytes)) {
493                 switch (attr->rta_type) {
494                 case IFA_ADDRESS:
495                         if (address != NULL)
496                                 *address = *((struct in_addr *) RTA_DATA(attr));
497                         break;
498                 case IFA_LOCAL:
499                         if (local != NULL)
500                                 *local = *((struct in_addr *) RTA_DATA(attr));
501                         break;
502                 case IFA_BROADCAST:
503                         if (broadcast != NULL)
504                                 *broadcast = *((struct in_addr *) RTA_DATA(attr));
505                         break;
506                 case IFA_LABEL:
507                         if (label != NULL)
508                                 *label = RTA_DATA(attr);
509                         break;
510                 }
511         }
512 }
513
514 static void process_newaddr(unsigned char family, unsigned char prefixlen,
515                                 int index, struct ifaddrmsg *msg, int bytes)
516 {
517         struct in_addr address = { INADDR_ANY };
518         const char *label = NULL;
519
520         if (family != AF_INET)
521                 return;
522
523         extract_addr(msg, bytes, &label, &address, NULL, NULL);
524
525         __connman_ipconfig_newaddr(index, label,
526                                         prefixlen, inet_ntoa(address));
527 }
528
529 static void process_deladdr(unsigned char family, unsigned char prefixlen,
530                                 int index, struct ifaddrmsg *msg, int bytes)
531 {
532         struct in_addr address = { INADDR_ANY };
533         const char *label = NULL;
534
535         if (family != AF_INET)
536                 return;
537
538         extract_addr(msg, bytes, &label, &address, NULL, NULL);
539
540         __connman_ipconfig_deladdr(index, label,
541                                         prefixlen, inet_ntoa(address));
542 }
543
544 static void extract_route(struct rtmsg *msg, int bytes, int *index,
545                                                 struct in_addr *dst,
546                                                 struct in_addr *gateway)
547 {
548         struct rtattr *attr;
549
550         for (attr = RTM_RTA(msg); RTA_OK(attr, bytes);
551                                         attr = RTA_NEXT(attr, bytes)) {
552                 switch (attr->rta_type) {
553                 case RTA_DST:
554                         if (dst != NULL)
555                                 *dst = *((struct in_addr *) RTA_DATA(attr));
556                         break;
557                 case RTA_GATEWAY:
558                         if (gateway != NULL)
559                                 *gateway = *((struct in_addr *) RTA_DATA(attr));
560                         break;
561                 case RTA_OIF:
562                         if (index != NULL)
563                                 *index = *((int *) RTA_DATA(attr));
564                         break;
565                 }
566         }
567 }
568
569 static void process_newroute(unsigned char family, unsigned char scope,
570                                                 struct rtmsg *msg, int bytes)
571 {
572         GSList *list;
573         struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY };
574         char dststr[16], gatewaystr[16];
575         int index = -1;
576
577         if (family != AF_INET)
578                 return;
579
580         extract_route(msg, bytes, &index, &dst, &gateway);
581
582         inet_ntop(family, &dst, dststr, sizeof(dststr));
583         inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr));
584
585         __connman_ipconfig_newroute(index, scope, dststr, gatewaystr);
586
587         /* skip host specific routes */
588         if (scope != RT_SCOPE_UNIVERSE &&
589                         !(scope == RT_SCOPE_LINK && dst.s_addr == INADDR_ANY))
590                 return;
591
592         if (dst.s_addr != INADDR_ANY)
593                 return;
594
595         for (list = rtnl_list; list; list = list->next) {
596                 struct connman_rtnl *rtnl = list->data;
597
598                 if (rtnl->newgateway)
599                         rtnl->newgateway(index, gatewaystr);
600         }
601 }
602
603 static void process_delroute(unsigned char family, unsigned char scope,
604                                                 struct rtmsg *msg, int bytes)
605 {
606         GSList *list;
607         struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY };
608         char dststr[16], gatewaystr[16];
609         int index = -1;
610
611         if (family != AF_INET)
612                 return;
613
614         extract_route(msg, bytes, &index, &dst, &gateway);
615
616         inet_ntop(family, &dst, dststr, sizeof(dststr));
617         inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr));
618
619         __connman_ipconfig_delroute(index, scope, dststr, gatewaystr);
620
621         /* skip host specific routes */
622         if (scope != RT_SCOPE_UNIVERSE &&
623                         !(scope == RT_SCOPE_LINK && dst.s_addr == INADDR_ANY))
624                 return;
625
626         if (dst.s_addr != INADDR_ANY)
627                 return;
628
629         for (list = rtnl_list; list; list = list->next) {
630                 struct connman_rtnl *rtnl = list->data;
631
632                 if (rtnl->delgateway)
633                         rtnl->delgateway(index, gatewaystr);
634         }
635 }
636
637 static inline void print_ether(struct rtattr *attr, const char *name)
638 {
639         int len = (int) RTA_PAYLOAD(attr);
640
641         if (len == ETH_ALEN) {
642                 struct ether_addr eth;
643                 memcpy(&eth, RTA_DATA(attr), ETH_ALEN);
644                 print("  attr %s (len %d) %s\n", name, len, ether_ntoa(&eth));
645         } else
646                 print("  attr %s (len %d)\n", name, len);
647 }
648
649 static inline void print_inet(struct rtattr *attr, const char *name,
650                                                         unsigned char family)
651 {
652         int len = (int) RTA_PAYLOAD(attr);
653
654         if (family == AF_INET && len == sizeof(struct in_addr)) {
655                 struct in_addr addr;
656                 addr = *((struct in_addr *) RTA_DATA(attr));
657                 print("  attr %s (len %d) %s\n", name, len, inet_ntoa(addr));
658         } else
659                 print("  attr %s (len %d)\n", name, len);
660 }
661
662 static inline void print_string(struct rtattr *attr, const char *name)
663 {
664         print("  attr %s (len %d) %s\n", name, (int) RTA_PAYLOAD(attr),
665                                                 (char *) RTA_DATA(attr));
666 }
667
668 static inline void print_byte(struct rtattr *attr, const char *name)
669 {
670         print("  attr %s (len %d) 0x%02x\n", name, (int) RTA_PAYLOAD(attr),
671                                         *((unsigned char *) RTA_DATA(attr)));
672 }
673
674 static inline void print_integer(struct rtattr *attr, const char *name)
675 {
676         print("  attr %s (len %d) %d\n", name, (int) RTA_PAYLOAD(attr),
677                                                 *((int *) RTA_DATA(attr)));
678 }
679
680 static inline void print_attr(struct rtattr *attr, const char *name)
681 {
682         int len = (int) RTA_PAYLOAD(attr);
683
684         if (name && len > 0)
685                 print("  attr %s (len %d)\n", name, len);
686         else
687                 print("  attr %d (len %d)\n", attr->rta_type, len);
688 }
689
690 static void rtnl_link(struct nlmsghdr *hdr)
691 {
692         struct ifinfomsg *msg;
693         struct rtattr *attr;
694         int bytes;
695
696         msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
697         bytes = IFLA_PAYLOAD(hdr);
698
699         print("ifi_index %d ifi_flags 0x%04x", msg->ifi_index, msg->ifi_flags);
700
701         for (attr = IFLA_RTA(msg); RTA_OK(attr, bytes);
702                                         attr = RTA_NEXT(attr, bytes)) {
703                 switch (attr->rta_type) {
704                 case IFLA_ADDRESS:
705                         print_ether(attr, "address");
706                         break;
707                 case IFLA_BROADCAST:
708                         print_ether(attr, "broadcast");
709                         break;
710                 case IFLA_IFNAME:
711                         print_string(attr, "ifname");
712                         break;
713                 case IFLA_MTU:
714                         print_integer(attr, "mtu");
715                         break;
716                 case IFLA_LINK:
717                         print_attr(attr, "link");
718                         break;
719                 case IFLA_QDISC:
720                         print_attr(attr, "qdisc");
721                         break;
722                 case IFLA_STATS:
723                         print_attr(attr, "stats");
724                         break;
725                 case IFLA_COST:
726                         print_attr(attr, "cost");
727                         break;
728                 case IFLA_PRIORITY:
729                         print_attr(attr, "priority");
730                         break;
731                 case IFLA_MASTER:
732                         print_attr(attr, "master");
733                         break;
734                 case IFLA_WIRELESS:
735                         print_attr(attr, "wireless");
736                         break;
737                 case IFLA_PROTINFO:
738                         print_attr(attr, "protinfo");
739                         break;
740                 case IFLA_TXQLEN:
741                         print_integer(attr, "txqlen");
742                         break;
743                 case IFLA_MAP:
744                         print_attr(attr, "map");
745                         break;
746                 case IFLA_WEIGHT:
747                         print_attr(attr, "weight");
748                         break;
749                 case IFLA_OPERSTATE:
750                         print_byte(attr, "operstate");
751                         break;
752                 case IFLA_LINKMODE:
753                         print_byte(attr, "linkmode");
754                         break;
755                 default:
756                         print_attr(attr, NULL);
757                         break;
758                 }
759         }
760 }
761
762 static void rtnl_newlink(struct nlmsghdr *hdr)
763 {
764         struct ifinfomsg *msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
765
766         rtnl_link(hdr);
767
768         process_newlink(msg->ifi_type, msg->ifi_index, msg->ifi_flags,
769                                 msg->ifi_change, msg, IFA_PAYLOAD(hdr));
770 }
771
772 static void rtnl_dellink(struct nlmsghdr *hdr)
773 {
774         struct ifinfomsg *msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
775
776         rtnl_link(hdr);
777
778         process_dellink(msg->ifi_type, msg->ifi_index, msg->ifi_flags,
779                                 msg->ifi_change, msg, IFA_PAYLOAD(hdr));
780 }
781
782 static void rtnl_addr(struct nlmsghdr *hdr)
783 {
784         struct ifaddrmsg *msg;
785         struct rtattr *attr;
786         int bytes;
787
788         msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
789         bytes = IFA_PAYLOAD(hdr);
790
791         print("ifa_family %d ifa_index %d", msg->ifa_family, msg->ifa_index);
792
793         for (attr = IFA_RTA(msg); RTA_OK(attr, bytes);
794                                         attr = RTA_NEXT(attr, bytes)) {
795                 switch (attr->rta_type) {
796                 case IFA_ADDRESS:
797                         print_inet(attr, "address", msg->ifa_family);
798                         break;
799                 case IFA_LOCAL:
800                         print_inet(attr, "local", msg->ifa_family);
801                         break;
802                 case IFA_LABEL:
803                         print_string(attr, "label");
804                         break;
805                 case IFA_BROADCAST:
806                         print_inet(attr, "broadcast", msg->ifa_family);
807                         break;
808                 case IFA_ANYCAST:
809                         print_attr(attr, "anycast");
810                         break;
811                 case IFA_CACHEINFO:
812                         print_attr(attr, "cacheinfo");
813                         break;
814                 case IFA_MULTICAST:
815                         print_attr(attr, "multicast");
816                         break;
817                 default:
818                         print_attr(attr, NULL);
819                         break;
820                 }
821         }
822 }
823
824 static void rtnl_newaddr(struct nlmsghdr *hdr)
825 {
826         struct ifaddrmsg *msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
827
828         rtnl_addr(hdr);
829
830         process_newaddr(msg->ifa_family, msg->ifa_prefixlen, msg->ifa_index,
831                                                 msg, IFA_PAYLOAD(hdr));
832 }
833
834 static void rtnl_deladdr(struct nlmsghdr *hdr)
835 {
836         struct ifaddrmsg *msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
837
838         rtnl_addr(hdr);
839
840         process_deladdr(msg->ifa_family, msg->ifa_prefixlen, msg->ifa_index,
841                                                 msg, IFA_PAYLOAD(hdr));
842 }
843
844 static void rtnl_route(struct nlmsghdr *hdr)
845 {
846         struct rtmsg *msg;
847         struct rtattr *attr;
848         int bytes;
849
850         msg = (struct rtmsg *) NLMSG_DATA(hdr);
851         bytes = RTM_PAYLOAD(hdr);
852
853         print("rtm_family %d rtm_table %d rtm_protocol %d",
854                         msg->rtm_family, msg->rtm_table, msg->rtm_protocol);
855         print("rtm_scope %d rtm_type %d rtm_flags 0x%04x",
856                                 msg->rtm_scope, msg->rtm_type, msg->rtm_flags);
857
858         for (attr = RTM_RTA(msg); RTA_OK(attr, bytes);
859                                         attr = RTA_NEXT(attr, bytes)) {
860                 switch (attr->rta_type) {
861                 case RTA_DST:
862                         print_inet(attr, "dst", msg->rtm_family);
863                         break;
864                 case RTA_SRC:
865                         print_inet(attr, "src", msg->rtm_family);
866                         break;
867                 case RTA_IIF:
868                         print_string(attr, "iif");
869                         break;
870                 case RTA_OIF:
871                         print_integer(attr, "oif");
872                         break;
873                 case RTA_GATEWAY:
874                         print_inet(attr, "gateway", msg->rtm_family);
875                         break;
876                 case RTA_PRIORITY:
877                         print_attr(attr, "priority");
878                         break;
879                 case RTA_PREFSRC:
880                         print_inet(attr, "prefsrc", msg->rtm_family);
881                         break;
882                 case RTA_METRICS:
883                         print_attr(attr, "metrics");
884                         break;
885                 case RTA_TABLE:
886                         print_integer(attr, "table");
887                         break;
888                 default:
889                         print_attr(attr, NULL);
890                         break;
891                 }
892         }
893 }
894
895 static connman_bool_t is_route_rtmsg(struct rtmsg *msg)
896 {
897
898         if (msg->rtm_table != RT_TABLE_MAIN)
899                 return FALSE;
900
901         if (msg->rtm_protocol != RTPROT_BOOT &&
902                         msg->rtm_protocol != RTPROT_KERNEL)
903                 return FALSE;
904
905         if (msg->rtm_type != RTN_UNICAST)
906                 return FALSE;
907
908         return TRUE;
909 }
910
911 static void rtnl_newroute(struct nlmsghdr *hdr)
912 {
913         struct rtmsg *msg = (struct rtmsg *) NLMSG_DATA(hdr);
914
915         rtnl_route(hdr);
916
917         if (is_route_rtmsg(msg))
918                 process_newroute(msg->rtm_family, msg->rtm_scope,
919                                                 msg, RTM_PAYLOAD(hdr));
920 }
921
922 static void rtnl_delroute(struct nlmsghdr *hdr)
923 {
924         struct rtmsg *msg = (struct rtmsg *) NLMSG_DATA(hdr);
925
926         rtnl_route(hdr);
927
928         if (is_route_rtmsg(msg))
929                 process_delroute(msg->rtm_family, msg->rtm_scope,
930                                                 msg, RTM_PAYLOAD(hdr));
931 }
932
933 static const char *type2string(uint16_t type)
934 {
935         switch (type) {
936         case NLMSG_NOOP:
937                 return "NOOP";
938         case NLMSG_ERROR:
939                 return "ERROR";
940         case NLMSG_DONE:
941                 return "DONE";
942         case NLMSG_OVERRUN:
943                 return "OVERRUN";
944         case RTM_GETLINK:
945                 return "GETLINK";
946         case RTM_NEWLINK:
947                 return "NEWLINK";
948         case RTM_DELLINK:
949                 return "DELLINK";
950         case RTM_NEWADDR:
951                 return "NEWADDR";
952         case RTM_DELADDR:
953                 return "DELADDR";
954         case RTM_GETROUTE:
955                 return "GETROUTE";
956         case RTM_NEWROUTE:
957                 return "NEWROUTE";
958         case RTM_DELROUTE:
959                 return "DELROUTE";
960         default:
961                 return "UNKNOWN";
962         }
963 }
964
965 static GIOChannel *channel = NULL;
966
967 struct rtnl_request {
968         struct nlmsghdr hdr;
969         struct rtgenmsg msg;
970 };
971 #define RTNL_REQUEST_SIZE  (sizeof(struct nlmsghdr) + sizeof(struct rtgenmsg))
972
973 static GSList *request_list = NULL;
974 static guint32 request_seq = 0;
975
976 static struct rtnl_request *find_request(guint32 seq)
977 {
978         GSList *list;
979
980         for (list = request_list; list; list = list->next) {
981                 struct rtnl_request *req = list->data;
982
983                 if (req->hdr.nlmsg_seq == seq)
984                         return req;
985         }
986
987         return NULL;
988 }
989
990 static int send_request(struct rtnl_request *req)
991 {
992         struct sockaddr_nl addr;
993         int sk;
994
995         DBG("%s len %d type %d flags 0x%04x seq %d",
996                                 type2string(req->hdr.nlmsg_type),
997                                 req->hdr.nlmsg_len, req->hdr.nlmsg_type,
998                                 req->hdr.nlmsg_flags, req->hdr.nlmsg_seq);
999
1000         sk = g_io_channel_unix_get_fd(channel);
1001
1002         memset(&addr, 0, sizeof(addr));
1003         addr.nl_family = AF_NETLINK;
1004
1005         return sendto(sk, req, req->hdr.nlmsg_len, 0,
1006                                 (struct sockaddr *) &addr, sizeof(addr));
1007 }
1008
1009 static int queue_request(struct rtnl_request *req)
1010 {
1011         request_list = g_slist_append(request_list, req);
1012
1013         if (g_slist_length(request_list) > 1)
1014                 return 0;
1015
1016         return send_request(req);
1017 }
1018
1019 static int process_response(guint32 seq)
1020 {
1021         struct rtnl_request *req;
1022
1023         DBG("seq %d", seq);
1024
1025         req = find_request(seq);
1026         if (req != NULL) {
1027                 request_list = g_slist_remove(request_list, req);
1028                 g_free(req);
1029         }
1030
1031         req = g_slist_nth_data(request_list, 0);
1032         if (req == NULL)
1033                 return 0;
1034
1035         return send_request(req);
1036 }
1037
1038 static void rtnl_message(void *buf, size_t len)
1039 {
1040         DBG("buf %p len %zd", buf, len);
1041
1042         while (len > 0) {
1043                 struct nlmsghdr *hdr = buf;
1044                 struct nlmsgerr *err;
1045
1046                 if (!NLMSG_OK(hdr, len))
1047                         break;
1048
1049                 DBG("%s len %d type %d flags 0x%04x seq %d",
1050                                         type2string(hdr->nlmsg_type),
1051                                         hdr->nlmsg_len, hdr->nlmsg_type,
1052                                         hdr->nlmsg_flags, hdr->nlmsg_seq);
1053
1054                 switch (hdr->nlmsg_type) {
1055                 case NLMSG_NOOP:
1056                 case NLMSG_OVERRUN:
1057                         return;
1058                 case NLMSG_DONE:
1059                         process_response(hdr->nlmsg_seq);
1060                         return;
1061                 case NLMSG_ERROR:
1062                         err = NLMSG_DATA(hdr);
1063                         DBG("error %d (%s)", -err->error,
1064                                                 strerror(-err->error));
1065                         return;
1066                 case RTM_NEWLINK:
1067                         rtnl_newlink(hdr);
1068                         break;
1069                 case RTM_DELLINK:
1070                         rtnl_dellink(hdr);
1071                         break;
1072                 case RTM_NEWADDR:
1073                         rtnl_newaddr(hdr);
1074                         break;
1075                 case RTM_DELADDR:
1076                         rtnl_deladdr(hdr);
1077                         break;
1078                 case RTM_NEWROUTE:
1079                         rtnl_newroute(hdr);
1080                         break;
1081                 case RTM_DELROUTE:
1082                         rtnl_delroute(hdr);
1083                         break;
1084                 }
1085
1086                 len -= hdr->nlmsg_len;
1087                 buf += hdr->nlmsg_len;
1088         }
1089 }
1090
1091 static gboolean netlink_event(GIOChannel *chan,
1092                                 GIOCondition cond, gpointer data)
1093 {
1094         unsigned char buf[4096];
1095         gsize len;
1096         GIOError err;
1097
1098         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
1099                 return FALSE;
1100
1101         memset(buf, 0, sizeof(buf));
1102
1103         err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len);
1104         if (err) {
1105                 if (err == G_IO_ERROR_AGAIN)
1106                         return TRUE;
1107                 return FALSE;
1108         }
1109
1110         rtnl_message(buf, len);
1111
1112         return TRUE;
1113 }
1114
1115 static int send_getlink(void)
1116 {
1117         struct rtnl_request *req;
1118
1119         DBG("");
1120
1121         req = g_try_malloc0(RTNL_REQUEST_SIZE);
1122         if (req == NULL)
1123                 return -ENOMEM;
1124
1125         req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
1126         req->hdr.nlmsg_type = RTM_GETLINK;
1127         req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1128         req->hdr.nlmsg_pid = 0;
1129         req->hdr.nlmsg_seq = request_seq++;
1130         req->msg.rtgen_family = AF_INET;
1131
1132         return queue_request(req);
1133 }
1134
1135 static int send_getaddr(void)
1136 {
1137         struct rtnl_request *req;
1138
1139         DBG("");
1140
1141         req = g_try_malloc0(RTNL_REQUEST_SIZE);
1142         if (req == NULL)
1143                 return -ENOMEM;
1144
1145         req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
1146         req->hdr.nlmsg_type = RTM_GETADDR;
1147         req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1148         req->hdr.nlmsg_pid = 0;
1149         req->hdr.nlmsg_seq = request_seq++;
1150         req->msg.rtgen_family = AF_INET;
1151
1152         return queue_request(req);
1153 }
1154
1155 static int send_getroute(void)
1156 {
1157         struct rtnl_request *req;
1158
1159         DBG("");
1160
1161         req = g_try_malloc0(RTNL_REQUEST_SIZE);
1162         if (req == NULL)
1163                 return -ENOMEM;
1164
1165         req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
1166         req->hdr.nlmsg_type = RTM_GETROUTE;
1167         req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1168         req->hdr.nlmsg_pid = 0;
1169         req->hdr.nlmsg_seq = request_seq++;
1170         req->msg.rtgen_family = AF_INET;
1171
1172         return queue_request(req);
1173 }
1174
1175 static gboolean update_timeout_cb(gpointer user_data)
1176 {
1177         __connman_rtnl_request_update();
1178
1179         return TRUE;
1180 }
1181
1182 static void update_interval_callback(guint min)
1183 {
1184         if (update_timeout > 0)
1185                 g_source_remove(update_timeout);
1186
1187         if (min < G_MAXUINT) {
1188                 update_interval = min;
1189                 update_timeout = g_timeout_add_seconds(update_interval,
1190                                                 update_timeout_cb, NULL);
1191         } else {
1192                 update_timeout = 0;
1193                 update_interval = G_MAXUINT;
1194         }
1195 }
1196
1197 static gint compare_interval(gconstpointer a, gconstpointer b)
1198 {
1199         guint val_a = GPOINTER_TO_UINT(a);
1200         guint val_b = GPOINTER_TO_UINT(b);
1201
1202         return val_a - val_b;
1203 }
1204
1205 unsigned int __connman_rtnl_update_interval_add(unsigned int interval)
1206 {
1207         guint min;
1208
1209         if (interval == 0)
1210                 return 0;
1211
1212         update_list = g_slist_insert_sorted(update_list,
1213                         GUINT_TO_POINTER(interval), compare_interval);
1214
1215         min = GPOINTER_TO_UINT(g_slist_nth_data(update_list, 0));
1216         if (min < update_interval) {
1217                 update_interval_callback(min);
1218                 __connman_rtnl_request_update();
1219         }
1220
1221         return update_interval;
1222 }
1223
1224 unsigned int __connman_rtnl_update_interval_remove(unsigned int interval)
1225 {
1226         guint min = G_MAXUINT;
1227
1228         if (interval == 0)
1229                 return 0;
1230
1231         update_list = g_slist_remove(update_list, GINT_TO_POINTER(interval));
1232
1233         if (update_list != NULL)
1234                 min = GPOINTER_TO_UINT(g_slist_nth_data(update_list, 0));
1235
1236         if (min > update_interval)
1237                 update_interval_callback(min);
1238
1239         return min;
1240 }
1241
1242 int __connman_rtnl_request_update(void)
1243 {
1244         return send_getlink();
1245 }
1246
1247 int __connman_rtnl_init(void)
1248 {
1249         struct sockaddr_nl addr;
1250         int sk;
1251
1252         DBG("");
1253
1254         interface_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1255                                                         NULL, free_interface);
1256
1257         sk = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
1258         if (sk < 0)
1259                 return -1;
1260
1261         memset(&addr, 0, sizeof(addr));
1262         addr.nl_family = AF_NETLINK;
1263         addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE;
1264
1265         if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1266                 close(sk);
1267                 return -1;
1268         }
1269
1270         channel = g_io_channel_unix_new(sk);
1271         g_io_channel_set_close_on_unref(channel, TRUE);
1272
1273         g_io_add_watch(channel, G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
1274                                                         netlink_event, NULL);
1275
1276         return 0;
1277 }
1278
1279 void __connman_rtnl_start(void)
1280 {
1281         DBG("");
1282
1283         send_getlink();
1284         send_getaddr();
1285         send_getroute();
1286 }
1287
1288 void __connman_rtnl_cleanup(void)
1289 {
1290         GSList *list;
1291
1292         DBG("");
1293
1294         for (list = watch_list; list; list = list->next) {
1295                 struct watch_data *watch = list->data;
1296
1297                 DBG("removing watch %d", watch->id);
1298
1299                 g_free(watch);
1300                 list->data = NULL;
1301         }
1302
1303         g_slist_free(watch_list);
1304         watch_list = NULL;
1305
1306         g_slist_free(update_list);
1307         update_list = NULL;
1308
1309         for (list = request_list; list; list = list->next) {
1310                 struct rtnl_request *req = list->data;
1311
1312                 DBG("%s len %d type %d flags 0x%04x seq %d",
1313                                 type2string(req->hdr.nlmsg_type),
1314                                 req->hdr.nlmsg_len, req->hdr.nlmsg_type,
1315                                 req->hdr.nlmsg_flags, req->hdr.nlmsg_seq);
1316
1317                 g_free(req);
1318                 list->data = NULL;
1319         }
1320
1321         g_slist_free(request_list);
1322         request_list = NULL;
1323
1324         g_io_channel_shutdown(channel, TRUE, NULL);
1325         g_io_channel_unref(channel);
1326
1327         channel = NULL;
1328
1329         g_hash_table_destroy(interface_list);
1330 }