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