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