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