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