inet: Fix file descriptor leak when comparing subnets
[platform/upstream/connman.git] / src / inet.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
6  *  Copyright (C) 2003-2005  Go-Core Project
7  *  Copyright (C) 2003-2006  Helsinki University of Technology
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License version 2 as
11  *  published by the Free Software Foundation.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #define _GNU_SOURCE
29 #include <stdio.h>
30 #include <errno.h>
31 #include <unistd.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/stat.h>
35 #include <sys/ioctl.h>
36 #include <sys/socket.h>
37 #include <linux/sockios.h>
38 #include <arpa/inet.h>
39 #include <net/route.h>
40 #include <net/ethernet.h>
41 #include <net/if.h>
42 #include <net/if_arp.h>
43 #include <netinet/icmp6.h>
44 #include <fcntl.h>
45 #include <linux/if_tun.h>
46
47 #include "connman.h"
48
49 #define NLMSG_TAIL(nmsg)                                \
50         ((struct rtattr *) (((uint8_t*) (nmsg)) +       \
51         NLMSG_ALIGN((nmsg)->nlmsg_len)))
52
53 static int add_rtattr(struct nlmsghdr *n, size_t max_length, int type,
54                                 const void *data, size_t data_length)
55 {
56         size_t length;
57         struct rtattr *rta;
58
59         length = RTA_LENGTH(data_length);
60
61         if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(length) > max_length)
62                 return -E2BIG;
63
64         rta = NLMSG_TAIL(n);
65         rta->rta_type = type;
66         rta->rta_len = length;
67         memcpy(RTA_DATA(rta), data, data_length);
68         n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(length);
69
70         return 0;
71 }
72
73 int __connman_inet_modify_address(int cmd, int flags,
74                                 int index, int family,
75                                 const char *address,
76                                 const char *peer,
77                                 unsigned char prefixlen,
78                                 const char *broadcast)
79 {
80         uint8_t request[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
81                         NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
82                         RTA_LENGTH(sizeof(struct in6_addr)) +
83                         RTA_LENGTH(sizeof(struct in6_addr))];
84
85         struct nlmsghdr *header;
86         struct sockaddr_nl nl_addr;
87         struct ifaddrmsg *ifaddrmsg;
88         struct in6_addr ipv6_addr;
89         struct in_addr ipv4_addr, ipv4_dest, ipv4_bcast;
90         int sk, err;
91
92         DBG("cmd %#x flags %#x index %d family %d address %s peer %s "
93                 "prefixlen %hhu broadcast %s", cmd, flags, index, family,
94                 address, peer, prefixlen, broadcast);
95
96         if (address == NULL)
97                 return -EINVAL;
98
99         if (family != AF_INET && family != AF_INET6)
100                 return -EINVAL;
101
102         memset(&request, 0, sizeof(request));
103
104         header = (struct nlmsghdr *)request;
105         header->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
106         header->nlmsg_type = cmd;
107         header->nlmsg_flags = NLM_F_REQUEST | flags;
108         header->nlmsg_seq = 1;
109
110         ifaddrmsg = NLMSG_DATA(header);
111         ifaddrmsg->ifa_family = family;
112         ifaddrmsg->ifa_prefixlen = prefixlen;
113         ifaddrmsg->ifa_flags = IFA_F_PERMANENT;
114         ifaddrmsg->ifa_scope = RT_SCOPE_UNIVERSE;
115         ifaddrmsg->ifa_index = index;
116
117         if (family == AF_INET) {
118                 if (inet_pton(AF_INET, address, &ipv4_addr) < 1)
119                         return -1;
120
121                 if (broadcast != NULL)
122                         inet_pton(AF_INET, broadcast, &ipv4_bcast);
123                 else
124                         ipv4_bcast.s_addr = ipv4_addr.s_addr |
125                                 htonl(0xfffffffflu >> prefixlen);
126
127                 if (peer != NULL) {
128                         if (inet_pton(AF_INET, peer, &ipv4_dest) < 1)
129                                 return -1;
130
131                         if ((err = add_rtattr(header, sizeof(request),
132                                         IFA_ADDRESS,
133                                         &ipv4_dest, sizeof(ipv4_dest))) < 0)
134                         return err;
135                 }
136
137                 if ((err = add_rtattr(header, sizeof(request), IFA_LOCAL,
138                                 &ipv4_addr, sizeof(ipv4_addr))) < 0)
139                         return err;
140
141                 if ((err = add_rtattr(header, sizeof(request), IFA_BROADCAST,
142                                 &ipv4_bcast, sizeof(ipv4_bcast))) < 0)
143                         return err;
144
145         } else if (family == AF_INET6) {
146                 if (inet_pton(AF_INET6, address, &ipv6_addr) < 1)
147                         return -1;
148
149                 if ((err = add_rtattr(header, sizeof(request), IFA_LOCAL,
150                                 &ipv6_addr, sizeof(ipv6_addr))) < 0)
151                         return err;
152         }
153
154         sk = socket(AF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_ROUTE);
155         if (sk < 0)
156                 return -errno;
157
158         memset(&nl_addr, 0, sizeof(nl_addr));
159         nl_addr.nl_family = AF_NETLINK;
160
161         if ((err = sendto(sk, request, header->nlmsg_len, 0,
162                         (struct sockaddr *) &nl_addr, sizeof(nl_addr))) < 0)
163                 goto done;
164
165         err = 0;
166
167 done:
168         close(sk);
169
170         return err;
171 }
172
173 int connman_inet_ifindex(const char *name)
174 {
175         struct ifreq ifr;
176         int sk, err;
177
178         if (name == NULL)
179                 return -1;
180
181         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
182         if (sk < 0)
183                 return -1;
184
185         memset(&ifr, 0, sizeof(ifr));
186         strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
187
188         err = ioctl(sk, SIOCGIFINDEX, &ifr);
189
190         close(sk);
191
192         if (err < 0)
193                 return -1;
194
195         return ifr.ifr_ifindex;
196 }
197
198 char *connman_inet_ifname(int index)
199 {
200         struct ifreq ifr;
201         int sk, err;
202
203         if (index < 0)
204                 return NULL;
205
206         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
207         if (sk < 0)
208                 return NULL;
209
210         memset(&ifr, 0, sizeof(ifr));
211         ifr.ifr_ifindex = index;
212
213         err = ioctl(sk, SIOCGIFNAME, &ifr);
214
215         close(sk);
216
217         if (err < 0)
218                 return NULL;
219
220         return strdup(ifr.ifr_name);
221 }
222
223 short int connman_inet_ifflags(int index)
224 {
225         struct ifreq ifr;
226         int sk, err;
227
228         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
229         if (sk < 0)
230                 return -errno;
231
232         memset(&ifr, 0, sizeof(ifr));
233         ifr.ifr_ifindex = index;
234
235         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
236                 err = -errno;
237                 goto done;
238         }
239
240         if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
241                 err = -errno;
242                 goto done;
243         }
244
245         err = ifr.ifr_flags;
246
247 done:
248         close(sk);
249
250         return err;
251 }
252
253 int connman_inet_ifup(int index)
254 {
255         struct ifreq ifr;
256         int sk, err;
257
258         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
259         if (sk < 0)
260                 return -errno;
261
262         memset(&ifr, 0, sizeof(ifr));
263         ifr.ifr_ifindex = index;
264
265         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
266                 err = -errno;
267                 goto done;
268         }
269
270         if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
271                 err = -errno;
272                 goto done;
273         }
274
275         if (ifr.ifr_flags & IFF_UP) {
276                 err = -EALREADY;
277                 goto done;
278         }
279
280         ifr.ifr_flags |= IFF_UP;
281
282         if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0) {
283                 err = -errno;
284                 goto done;
285         }
286
287         err = 0;
288
289 done:
290         close(sk);
291
292         return err;
293 }
294
295 int connman_inet_ifdown(int index)
296 {
297         struct ifreq ifr;
298         int sk, err;
299
300         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
301         if (sk < 0)
302                 return -errno;
303
304         memset(&ifr, 0, sizeof(ifr));
305         ifr.ifr_ifindex = index;
306
307         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
308                 err = -errno;
309                 goto done;
310         }
311
312         if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
313                 err = -errno;
314                 goto done;
315         }
316
317         if (!(ifr.ifr_flags & IFF_UP)) {
318                 err = -EALREADY;
319                 goto done;
320         }
321
322         ifr.ifr_flags &= ~IFF_UP;
323
324         if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0)
325                 err = -errno;
326         else
327                 err = 0;
328
329 done:
330         close(sk);
331
332         return err;
333 }
334
335 static char *index2addr(int index)
336 {
337         struct ifreq ifr;
338         struct ether_addr eth;
339         char *str;
340         int sk, err;
341
342         if (index < 0)
343                 return NULL;
344
345         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
346         if (sk < 0)
347                 return NULL;
348
349         memset(&ifr, 0, sizeof(ifr));
350         ifr.ifr_ifindex = index;
351
352         err = ioctl(sk, SIOCGIFNAME, &ifr);
353
354         if (err == 0)
355                 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
356
357         close(sk);
358
359         if (err < 0)
360                 return NULL;
361
362         str = malloc(18);
363         if (!str)
364                 return NULL;
365
366         memcpy(&eth, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
367         snprintf(str, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
368                                                 eth.ether_addr_octet[0],
369                                                 eth.ether_addr_octet[1],
370                                                 eth.ether_addr_octet[2],
371                                                 eth.ether_addr_octet[3],
372                                                 eth.ether_addr_octet[4],
373                                                 eth.ether_addr_octet[5]);
374
375         return str;
376 }
377
378 static char *index2ident(int index, const char *prefix)
379 {
380         struct ifreq ifr;
381         struct ether_addr eth;
382         char *str;
383         int sk, err, len;
384
385         if (index < 0)
386                 return NULL;
387
388         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
389         if (sk < 0)
390                 return NULL;
391
392         memset(&ifr, 0, sizeof(ifr));
393         ifr.ifr_ifindex = index;
394
395         err = ioctl(sk, SIOCGIFNAME, &ifr);
396
397         if (err == 0)
398                 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
399
400         close(sk);
401
402         if (err < 0)
403                 return NULL;
404
405         len = prefix ? strlen(prefix) + 18 : 18;
406
407         str = malloc(len);
408         if (!str)
409                 return NULL;
410
411         memcpy(&eth, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
412         snprintf(str, len, "%s%02x%02x%02x%02x%02x%02x",
413                                                 prefix ? prefix : "",
414                                                 eth.ether_addr_octet[0],
415                                                 eth.ether_addr_octet[1],
416                                                 eth.ether_addr_octet[2],
417                                                 eth.ether_addr_octet[3],
418                                                 eth.ether_addr_octet[4],
419                                                 eth.ether_addr_octet[5]);
420
421         return str;
422 }
423
424 connman_bool_t connman_inet_is_cfg80211(int index)
425 {
426         connman_bool_t result = FALSE;
427         char phy80211_path[PATH_MAX];
428         struct stat st;
429         struct ifreq ifr;
430         int sk;
431
432         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
433         if (sk < 0)
434                 return FALSE;
435
436         memset(&ifr, 0, sizeof(ifr));
437         ifr.ifr_ifindex = index;
438
439         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0)
440                 goto done;
441
442         snprintf(phy80211_path, PATH_MAX,
443                                 "/sys/class/net/%s/phy80211", ifr.ifr_name);
444
445         if (stat(phy80211_path, &st) == 0 && (st.st_mode & S_IFDIR))
446                 result = TRUE;
447
448 done:
449         close(sk);
450
451         return result;
452 }
453
454 struct connman_device *connman_inet_create_device(int index)
455 {
456         enum connman_device_type type;
457         struct connman_device *device;
458         char *devname, *ident = NULL;
459         char *addr = NULL, *name = NULL;
460
461         if (index < 0)
462                 return NULL;
463
464         devname = connman_inet_ifname(index);
465         if (devname == NULL)
466                 return NULL;
467
468         if (__connman_device_isfiltered(devname) == TRUE) {
469                 connman_info("Ignoring interface %s (filtered)", devname);
470                 free(devname);
471                 return NULL;
472         }
473
474         type = __connman_rtnl_get_device_type(index);
475
476         switch (type) {
477         case CONNMAN_DEVICE_TYPE_UNKNOWN:
478                 connman_info("Ignoring interface %s (type unknown)", devname);
479                 free(devname);
480                 return NULL;
481         case CONNMAN_DEVICE_TYPE_ETHERNET:
482         case CONNMAN_DEVICE_TYPE_GADGET:
483         case CONNMAN_DEVICE_TYPE_WIFI:
484         case CONNMAN_DEVICE_TYPE_WIMAX:
485                 name = index2ident(index, "");
486                 addr = index2addr(index);
487                 break;
488         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
489         case CONNMAN_DEVICE_TYPE_CELLULAR:
490         case CONNMAN_DEVICE_TYPE_GPS:
491         case CONNMAN_DEVICE_TYPE_VENDOR:
492                 name = strdup(devname);
493                 break;
494         }
495
496         device = connman_device_create(name, type);
497         if (device == NULL)
498                 goto done;
499
500         switch (type) {
501         case CONNMAN_DEVICE_TYPE_UNKNOWN:
502         case CONNMAN_DEVICE_TYPE_VENDOR:
503         case CONNMAN_DEVICE_TYPE_GPS:
504                 break;
505         case CONNMAN_DEVICE_TYPE_ETHERNET:
506         case CONNMAN_DEVICE_TYPE_GADGET:
507                 ident = index2ident(index, NULL);
508                 break;
509         case CONNMAN_DEVICE_TYPE_WIFI:
510         case CONNMAN_DEVICE_TYPE_WIMAX:
511                 ident = index2ident(index, NULL);
512                 break;
513         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
514                 break;
515         case CONNMAN_DEVICE_TYPE_CELLULAR:
516                 ident = index2ident(index, NULL);
517                 break;
518         }
519
520         connman_device_set_index(device, index);
521         connman_device_set_interface(device, devname);
522
523         if (ident != NULL) {
524                 connman_device_set_ident(device, ident);
525                 free(ident);
526         }
527
528         connman_device_set_string(device, "Address", addr);
529
530 done:
531         free(devname);
532         free(name);
533         free(addr);
534
535         return device;
536 }
537
538 struct in6_ifreq {
539         struct in6_addr ifr6_addr;
540         __u32 ifr6_prefixlen;
541         unsigned int ifr6_ifindex;
542 };
543
544 int connman_inet_set_ipv6_address(int index,
545                 struct connman_ipaddress *ipaddress)
546 {
547         int err;
548         unsigned char prefix_len;
549         const char *address;
550
551         if (ipaddress->local == NULL)
552                 return 0;
553
554         prefix_len = ipaddress->prefixlen;
555         address = ipaddress->local;
556
557         DBG("index %d address %s prefix_len %d", index, address, prefix_len);
558
559         err = __connman_inet_modify_address(RTM_NEWADDR,
560                                 NLM_F_REPLACE | NLM_F_ACK, index, AF_INET6,
561                                 address, NULL, prefix_len, NULL);
562         if (err < 0) {
563                 connman_error("%s: %s", __func__, strerror(-err));
564                 return err;
565         }
566
567         return 0;
568 }
569
570 int connman_inet_set_address(int index, struct connman_ipaddress *ipaddress)
571 {
572         int err;
573         unsigned char prefix_len;
574         const char *address, *broadcast, *peer;
575
576         if (ipaddress->local == NULL)
577                 return -1;
578
579         prefix_len = ipaddress->prefixlen;
580         address = ipaddress->local;
581         broadcast = ipaddress->broadcast;
582         peer = ipaddress->peer;
583
584         DBG("index %d address %s prefix_len %d", index, address, prefix_len);
585
586         err = __connman_inet_modify_address(RTM_NEWADDR,
587                                 NLM_F_REPLACE | NLM_F_ACK, index, AF_INET,
588                                 address, peer, prefix_len, broadcast);
589         if (err < 0) {
590                 connman_error("%s: %s", __func__, strerror(-err));
591                 return err;
592         }
593
594         return 0;
595 }
596
597 int connman_inet_clear_ipv6_address(int index, const char *address,
598                                                         int prefix_len)
599 {
600         int err;
601
602         DBG("index %d address %s prefix_len %d", index, address, prefix_len);
603
604         err = __connman_inet_modify_address(RTM_DELADDR, 0, index, AF_INET6,
605                                 address, NULL, prefix_len, NULL);
606         if (err < 0) {
607                 connman_error("%s: %s", __func__, strerror(-err));
608                 return err;
609         }
610
611         return 0;
612 }
613
614 int connman_inet_clear_address(int index, struct connman_ipaddress *ipaddress)
615 {
616         int err;
617         unsigned char prefix_len;
618         const char *address, *broadcast, *peer;
619
620         prefix_len = ipaddress->prefixlen;
621         address = ipaddress->local;
622         broadcast = ipaddress->broadcast;
623         peer = ipaddress->peer;
624
625         DBG("index %d address %s prefix_len %d", index, address, prefix_len);
626
627         err = __connman_inet_modify_address(RTM_DELADDR, 0, index, AF_INET,
628                                 address, peer, prefix_len, broadcast);
629         if (err < 0) {
630                 connman_error("%s: %s", __func__, strerror(-err));
631                 return err;
632         }
633
634         return 0;
635 }
636
637 int connman_inet_add_host_route(int index, const char *host,
638                                 const char *gateway)
639 {
640         return connman_inet_add_network_route(index, host, gateway, NULL);
641 }
642
643 int connman_inet_del_host_route(int index, const char *host)
644 {
645         return connman_inet_del_network_route(index, host);
646 }
647
648 int connman_inet_add_network_route(int index, const char *host,
649                                         const char *gateway,
650                                         const char *netmask)
651 {
652         struct ifreq ifr;
653         struct rtentry rt;
654         struct sockaddr_in addr;
655         int sk, err;
656
657         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
658         if (sk < 0)
659                 return -1;
660
661         memset(&ifr, 0, sizeof(ifr));
662         ifr.ifr_ifindex = index;
663
664         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
665                 close(sk);
666                 return -1;
667         }
668
669         DBG("ifname %s", ifr.ifr_name);
670
671         memset(&rt, 0, sizeof(rt));
672         rt.rt_flags = RTF_UP;
673         if (gateway != NULL)
674                 rt.rt_flags |= RTF_GATEWAY;
675         if (netmask == NULL)
676                 rt.rt_flags |= RTF_HOST;
677
678         memset(&addr, 0, sizeof(addr));
679         addr.sin_family = AF_INET;
680         addr.sin_addr.s_addr = inet_addr(host);
681         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
682
683         memset(&addr, 0, sizeof(addr));
684         addr.sin_family = AF_INET;
685         if (gateway != NULL)
686                 addr.sin_addr.s_addr = inet_addr(gateway);
687         else
688                 addr.sin_addr.s_addr = INADDR_ANY;
689         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
690
691         memset(&addr, 0, sizeof(addr));
692         addr.sin_family = AF_INET;
693         addr.sin_addr.s_addr = INADDR_ANY;
694         if (netmask != NULL)
695                 addr.sin_addr.s_addr = inet_addr(netmask);
696         else
697                 addr.sin_addr.s_addr = INADDR_ANY;
698         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
699
700         rt.rt_dev = ifr.ifr_name;
701
702         err = ioctl(sk, SIOCADDRT, &rt);
703         if (err < 0)
704                 connman_error("Adding host route failed (%s)",
705                                                         strerror(errno));
706
707         close(sk);
708
709         return err;
710 }
711
712 int connman_inet_del_network_route(int index, const char *host)
713 {
714         struct ifreq ifr;
715         struct rtentry rt;
716         struct sockaddr_in addr;
717         int sk, err;
718
719         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
720         if (sk < 0)
721                 return -1;
722
723         memset(&ifr, 0, sizeof(ifr));
724         ifr.ifr_ifindex = index;
725
726         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
727                 close(sk);
728                 return -1;
729         }
730
731         DBG("ifname %s", ifr.ifr_name);
732
733         memset(&rt, 0, sizeof(rt));
734         rt.rt_flags = RTF_UP | RTF_HOST;
735
736         memset(&addr, 0, sizeof(addr));
737         addr.sin_family = AF_INET;
738         addr.sin_addr.s_addr = inet_addr(host);
739         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
740
741         rt.rt_dev = ifr.ifr_name;
742
743         err = ioctl(sk, SIOCDELRT, &rt);
744         if (err < 0)
745                 connman_error("Deleting host route failed (%s)",
746                                                         strerror(errno));
747
748         close(sk);
749
750         return err;
751 }
752
753 int connman_inet_del_ipv6_network_route(int index, const char *host,
754                                                 unsigned char prefix_len)
755 {
756         struct in6_rtmsg rt;
757         int sk, err;
758
759         DBG("index %d host %s", index, host);
760
761         if (host == NULL)
762                 return -EINVAL;
763
764         memset(&rt, 0, sizeof(rt));
765
766         rt.rtmsg_dst_len = prefix_len;
767
768         err = inet_pton(AF_INET6, host, &rt.rtmsg_dst);
769         if (err < 0)
770                 goto out;
771
772         rt.rtmsg_flags = RTF_UP | RTF_HOST;
773
774         rt.rtmsg_metric = 1;
775         rt.rtmsg_ifindex = index;
776
777         sk = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
778         if (sk < 0) {
779                 err = -1;
780                 goto out;
781         }
782
783         err = ioctl(sk, SIOCDELRT, &rt);
784         close(sk);
785 out:
786         if (err < 0)
787                 connman_error("Del IPv6 host route error (%s)",
788                                                 strerror(errno));
789
790         return err;
791 }
792
793 int connman_inet_del_ipv6_host_route(int index, const char *host)
794 {
795         return connman_inet_del_ipv6_network_route(index, host, 128);
796 }
797
798 int connman_inet_add_ipv6_network_route(int index, const char *host,
799                                         const char *gateway,
800                                         unsigned char prefix_len)
801 {
802         struct in6_rtmsg rt;
803         int sk, err;
804
805         DBG("index %d host %s gateway %s", index, host, gateway);
806
807         if (host == NULL)
808                 return -EINVAL;
809
810         memset(&rt, 0, sizeof(rt));
811
812         rt.rtmsg_dst_len = prefix_len;
813
814         err = inet_pton(AF_INET6, host, &rt.rtmsg_dst);
815         if (err < 0)
816                 goto out;
817
818         rt.rtmsg_flags = RTF_UP | RTF_HOST;
819
820         if (gateway != NULL) {
821                 rt.rtmsg_flags |= RTF_GATEWAY;
822                 inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway);
823         }
824
825         rt.rtmsg_metric = 1;
826         rt.rtmsg_ifindex = index;
827
828         sk = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
829         if (sk < 0) {
830                 err = -1;
831                 goto out;
832         }
833
834         err = ioctl(sk, SIOCADDRT, &rt);
835         close(sk);
836 out:
837         if (err < 0)
838                 connman_error("Set IPv6 host route error (%s)",
839                                                 strerror(errno));
840
841         return err;
842 }
843
844 int connman_inet_add_ipv6_host_route(int index, const char *host,
845                                         const char *gateway)
846 {
847         return connman_inet_add_ipv6_network_route(index, host, gateway, 128);
848 }
849
850 int connman_inet_set_ipv6_gateway_address(int index, const char *gateway)
851 {
852         struct in6_rtmsg rt;
853         int sk, err;
854
855         DBG("index %d, gateway %s", index, gateway);
856
857         if (gateway == NULL)
858                 return -EINVAL;
859
860         memset(&rt, 0, sizeof(rt));
861
862         err = inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway);
863         if (err < 0)
864                 goto out;
865
866         rt.rtmsg_flags = RTF_UP | RTF_GATEWAY;
867         rt.rtmsg_metric = 1;
868         rt.rtmsg_dst_len = 0;
869         rt.rtmsg_ifindex = index;
870
871         sk = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
872         if (sk < 0) {
873                 err = -1;
874                 goto out;
875         }
876
877         err = ioctl(sk, SIOCADDRT, &rt);
878         close(sk);
879 out:
880         if (err < 0)
881                 connman_error("Set default IPv6 gateway error (%s)",
882                                                 strerror(errno));
883
884         return err;
885 }
886
887 int connman_inet_clear_ipv6_gateway_address(int index, const char *gateway)
888 {
889         struct in6_rtmsg rt;
890         int sk, err;
891
892         DBG("index %d, gateway %s", index, gateway);
893
894         if (gateway == NULL)
895                 return -EINVAL;
896
897         memset(&rt, 0, sizeof(rt));
898
899         err = inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway);
900         if (err < 0)
901                 goto out;
902
903         rt.rtmsg_flags = RTF_UP | RTF_GATEWAY;
904         rt.rtmsg_metric = 1;
905         rt.rtmsg_dst_len = 0;
906         rt.rtmsg_ifindex = index;
907
908         sk = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
909         if (sk < 0) {
910                 err = -1;
911                 goto out;
912         }
913
914         err = ioctl(sk, SIOCDELRT, &rt);
915         close(sk);
916 out:
917         if (err < 0)
918                 connman_error("Clear default IPv6 gateway error (%s)",
919                                                 strerror(errno));
920
921         return err;
922 }
923
924 int connman_inet_set_gateway_address(int index, const char *gateway)
925 {
926         struct ifreq ifr;
927         struct rtentry rt;
928         struct sockaddr_in addr;
929         int sk, err;
930
931         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
932         if (sk < 0)
933                 return -1;
934
935         memset(&ifr, 0, sizeof(ifr));
936         ifr.ifr_ifindex = index;
937
938         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
939                 close(sk);
940                 return -1;
941         }
942
943         DBG("ifname %s", ifr.ifr_name);
944
945         memset(&rt, 0, sizeof(rt));
946         rt.rt_flags = RTF_UP | RTF_GATEWAY;
947
948         memset(&addr, 0, sizeof(addr));
949         addr.sin_family = AF_INET;
950         addr.sin_addr.s_addr = INADDR_ANY;
951         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
952
953         memset(&addr, 0, sizeof(addr));
954         addr.sin_family = AF_INET;
955         addr.sin_addr.s_addr = inet_addr(gateway);
956         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
957
958         memset(&addr, 0, sizeof(addr));
959         addr.sin_family = AF_INET;
960         addr.sin_addr.s_addr = INADDR_ANY;
961         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
962
963         err = ioctl(sk, SIOCADDRT, &rt);
964         if (err < 0)
965                 connman_error("Setting default gateway route failed (%s)",
966                                                         strerror(errno));
967
968         close(sk);
969
970         return err;
971 }
972
973 int connman_inet_set_gateway_interface(int index)
974 {
975         struct ifreq ifr;
976         struct rtentry rt;
977         struct sockaddr_in addr;
978         int sk, err;
979
980         DBG("");
981
982         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
983         if (sk < 0)
984                 return -1;
985
986         memset(&ifr, 0, sizeof(ifr));
987         ifr.ifr_ifindex = index;
988
989         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
990                 close(sk);
991                 return -1;
992         }
993
994         DBG("ifname %s", ifr.ifr_name);
995
996         memset(&rt, 0, sizeof(rt));
997         rt.rt_flags = RTF_UP;
998
999         memset(&addr, 0, sizeof(addr));
1000         addr.sin_family = AF_INET;
1001         addr.sin_addr.s_addr = INADDR_ANY;
1002
1003         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1004         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1005         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1006
1007         rt.rt_dev = ifr.ifr_name;
1008
1009         err = ioctl(sk, SIOCADDRT, &rt);
1010         if (err < 0)
1011                 connman_error("Setting default interface route failed (%s)",
1012                                                         strerror(errno));
1013         close(sk);
1014
1015         return err;
1016 }
1017
1018 int connman_inet_set_ipv6_gateway_interface(int index)
1019 {
1020         struct ifreq ifr;
1021         struct rtentry rt;
1022         struct sockaddr_in6 addr;
1023         const struct in6_addr any = IN6ADDR_ANY_INIT;
1024         int sk, err;
1025
1026         DBG("");
1027
1028         sk = socket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1029         if (sk < 0)
1030                 return -1;
1031
1032         memset(&ifr, 0, sizeof(ifr));
1033         ifr.ifr_ifindex = index;
1034
1035         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1036                 close(sk);
1037                 return -1;
1038         }
1039
1040         DBG("ifname %s", ifr.ifr_name);
1041
1042         memset(&rt, 0, sizeof(rt));
1043         rt.rt_flags = RTF_UP;
1044
1045         memset(&addr, 0, sizeof(addr));
1046         addr.sin6_family = AF_INET6;
1047         addr.sin6_addr = any;
1048
1049         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1050         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1051         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1052
1053         rt.rt_dev = ifr.ifr_name;
1054
1055         err = ioctl(sk, SIOCADDRT, &rt);
1056         if (err < 0)
1057                 connman_error("Setting default interface route failed (%s)",
1058                                                         strerror(errno));
1059         close(sk);
1060
1061         return err;
1062 }
1063
1064 int connman_inet_clear_gateway_address(int index, const char *gateway)
1065 {
1066         struct ifreq ifr;
1067         struct rtentry rt;
1068         struct sockaddr_in addr;
1069         int sk, err;
1070
1071         DBG("");
1072
1073         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1074         if (sk < 0)
1075                 return -1;
1076
1077         memset(&ifr, 0, sizeof(ifr));
1078         ifr.ifr_ifindex = index;
1079
1080         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1081                 close(sk);
1082                 return -1;
1083         }
1084
1085         DBG("ifname %s", ifr.ifr_name);
1086
1087         memset(&rt, 0, sizeof(rt));
1088         rt.rt_flags = RTF_UP | RTF_GATEWAY;
1089
1090         memset(&addr, 0, sizeof(addr));
1091         addr.sin_family = AF_INET;
1092         addr.sin_addr.s_addr = INADDR_ANY;
1093         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1094
1095         memset(&addr, 0, sizeof(addr));
1096         addr.sin_family = AF_INET;
1097         addr.sin_addr.s_addr = inet_addr(gateway);
1098         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1099
1100         memset(&addr, 0, sizeof(addr));
1101         addr.sin_family = AF_INET;
1102         addr.sin_addr.s_addr = INADDR_ANY;
1103         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1104
1105         err = ioctl(sk, SIOCDELRT, &rt);
1106         if (err < 0)
1107                 connman_error("Removing default gateway route failed (%s)",
1108                                                         strerror(errno));
1109
1110         close(sk);
1111
1112         return err;
1113 }
1114
1115 int connman_inet_clear_gateway_interface(int index)
1116 {
1117         struct ifreq ifr;
1118         struct rtentry rt;
1119         struct sockaddr_in addr;
1120         int sk, err;
1121
1122         DBG("");
1123
1124         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1125         if (sk < 0)
1126                 return -1;
1127
1128         memset(&ifr, 0, sizeof(ifr));
1129         ifr.ifr_ifindex = index;
1130
1131         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1132                 close(sk);
1133                 return -1;
1134         }
1135
1136         DBG("ifname %s", ifr.ifr_name);
1137
1138         memset(&rt, 0, sizeof(rt));
1139         rt.rt_flags = RTF_UP;
1140
1141         memset(&addr, 0, sizeof(addr));
1142         addr.sin_family = AF_INET;
1143         addr.sin_addr.s_addr = INADDR_ANY;
1144
1145         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1146         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1147         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1148
1149         rt.rt_dev = ifr.ifr_name;
1150
1151         err = ioctl(sk, SIOCDELRT, &rt);
1152         if (err < 0)
1153                 connman_error("Removing default interface route failed (%s)",
1154                                                         strerror(errno));
1155         close(sk);
1156
1157         return err;
1158 }
1159
1160 int connman_inet_clear_ipv6_gateway_interface(int index)
1161 {
1162         struct ifreq ifr;
1163         struct rtentry rt;
1164         struct sockaddr_in6 addr;
1165         const struct in6_addr any = IN6ADDR_ANY_INIT;
1166         int sk, err;
1167
1168         DBG("");
1169
1170         sk = socket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1171         if (sk < 0)
1172                 return -1;
1173
1174         memset(&ifr, 0, sizeof(ifr));
1175         ifr.ifr_ifindex = index;
1176
1177         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1178                 close(sk);
1179                 return -1;
1180         }
1181
1182         DBG("ifname %s", ifr.ifr_name);
1183
1184         memset(&rt, 0, sizeof(rt));
1185         rt.rt_flags = RTF_UP;
1186
1187         memset(&addr, 0, sizeof(addr));
1188         addr.sin6_family = AF_INET6;
1189         addr.sin6_addr = any;
1190
1191         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1192         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1193         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1194
1195         rt.rt_dev = ifr.ifr_name;
1196
1197         err = ioctl(sk, SIOCDELRT, &rt);
1198         if (err < 0)
1199                 connman_error("Removing default interface route failed (%s)",
1200                                                         strerror(errno));
1201         close(sk);
1202
1203         return err;
1204 }
1205
1206 connman_bool_t connman_inet_compare_subnet(int index, const char *host)
1207 {
1208         struct ifreq ifr;
1209         struct in_addr _host_addr;
1210         in_addr_t host_addr, netmask_addr, if_addr;
1211         struct sockaddr_in *netmask, *addr;
1212         int sk;
1213
1214         DBG("host %s", host);
1215
1216         if (host == NULL)
1217                 return FALSE;
1218
1219         if (inet_aton(host, &_host_addr) == 0)
1220                 return -1;
1221         host_addr = _host_addr.s_addr;
1222
1223         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1224         if (sk < 0)
1225                 return FALSE;
1226
1227         memset(&ifr, 0, sizeof(ifr));
1228         ifr.ifr_ifindex = index;
1229
1230         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1231                 close(sk);
1232                 return FALSE;
1233         }
1234
1235         if (ioctl(sk, SIOCGIFNETMASK, &ifr) < 0) {
1236                 close(sk);
1237                 return FALSE;
1238         }
1239
1240         netmask = (struct sockaddr_in *)&ifr.ifr_netmask;
1241         netmask_addr = netmask->sin_addr.s_addr;
1242
1243         if (ioctl(sk, SIOCGIFADDR, &ifr) < 0) {
1244                 close(sk);
1245                 return FALSE;
1246         }
1247
1248         close(sk);
1249
1250         addr = (struct sockaddr_in *)&ifr.ifr_addr;
1251         if_addr = addr->sin_addr.s_addr;
1252
1253         return ((if_addr & netmask_addr) == (host_addr & netmask_addr));
1254 }
1255
1256 int connman_inet_remove_from_bridge(int index, const char *bridge)
1257 {
1258         struct ifreq ifr;
1259         int sk, err;
1260
1261         if (bridge == NULL)
1262                 return -EINVAL;
1263
1264         sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
1265         if (sk < 0)
1266                 return sk;
1267
1268         memset(&ifr, 0, sizeof(ifr));
1269         strncpy(ifr.ifr_name, bridge, IFNAMSIZ - 1);
1270         ifr.ifr_ifindex = index;
1271
1272         err = ioctl(sk, SIOCBRDELIF, &ifr);
1273
1274         close(sk);
1275
1276         if (err < 0) {
1277                 connman_error("Remove interface from bridge error %s",
1278                                                         strerror(errno));
1279                 return err;
1280         }
1281
1282         return 0;
1283 }
1284
1285 int connman_inet_add_to_bridge(int index, const char *bridge)
1286 {
1287         struct ifreq ifr;
1288         int sk, err;
1289
1290         if (bridge == NULL)
1291                 return -EINVAL;
1292
1293         sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
1294         if (sk < 0)
1295                 return sk;
1296
1297         memset(&ifr, 0, sizeof(ifr));
1298         strncpy(ifr.ifr_name, bridge, IFNAMSIZ - 1);
1299         ifr.ifr_ifindex = index;
1300
1301         err = ioctl(sk, SIOCBRADDIF, &ifr);
1302
1303         close(sk);
1304
1305         if (err < 0) {
1306                 connman_error("Add interface to bridge error %s",
1307                                                         strerror(errno));
1308                 return err;
1309         }
1310
1311         return 0;
1312 }
1313
1314 int connman_inet_set_mtu(int index, int mtu)
1315 {
1316         struct ifreq ifr;
1317         int sk, err;
1318
1319         sk = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1320         if (sk < 0)
1321                 return sk;
1322
1323         memset(&ifr, 0, sizeof(ifr));
1324         ifr.ifr_ifindex = index;
1325
1326         err = ioctl(sk, SIOCGIFNAME, &ifr);
1327         if (err == 0) {
1328                 ifr.ifr_mtu = mtu;
1329                 err = ioctl(sk, SIOCSIFMTU, &ifr);
1330         }
1331
1332         close(sk);
1333         return err;
1334 }
1335
1336 int connman_inet_setup_tunnel(char *tunnel, int mtu)
1337 {
1338         struct ifreq ifr;
1339         int sk, err, index;
1340         __u32 mask;
1341         __u32 flags;
1342
1343         if (tunnel == NULL)
1344                 return -EINVAL;
1345
1346         sk = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1347         if (sk < 0)
1348                 return sk;
1349
1350         index = if_nametoindex(tunnel);
1351
1352         err = connman_inet_set_mtu(index, mtu);
1353         if (err < 0)
1354                 return err;
1355         else if (err)
1356                 goto done;
1357
1358         memset(&ifr, 0, sizeof(ifr));
1359         strncpy(ifr.ifr_name, tunnel, IFNAMSIZ);
1360         err = ioctl(sk, SIOCGIFFLAGS, &ifr);
1361         if (err)
1362                 goto done;
1363
1364         mask = IFF_UP;
1365         flags = IFF_UP;
1366
1367         if ((ifr.ifr_flags ^ flags) & mask) {
1368                 ifr.ifr_flags &= ~mask;
1369                 ifr.ifr_flags |= mask & flags;
1370                 err = ioctl(sk, SIOCSIFFLAGS, &ifr);
1371                 if (err)
1372                         connman_error("SIOCSIFFLAGS failed: %s",
1373                                                         strerror(errno));
1374         }
1375
1376 done:
1377         close(sk);
1378         return err;
1379 }
1380
1381 int connman_inet_create_tunnel(char **iface)
1382 {
1383         struct ifreq ifr;
1384         int i, fd;
1385
1386         fd = open("/dev/net/tun", O_RDWR | O_CLOEXEC);
1387         if (fd < 0) {
1388                 i = -errno;
1389                 connman_error("Failed to open /dev/net/tun: %s",
1390                                 strerror(errno));
1391                 return i;
1392         }
1393
1394         memset(&ifr, 0, sizeof(ifr));
1395         ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
1396
1397         for (i = 0; i < 256; i++) {
1398                 sprintf(ifr.ifr_name, "tun%d", i);
1399
1400                 if (!ioctl(fd, TUNSETIFF, (void *)&ifr))
1401                         break;
1402         }
1403
1404         if (i == 256) {
1405                 connman_error("Failed to find available tun device");
1406                 close(fd);
1407                 return -ENODEV;
1408         }
1409
1410         *iface = g_strdup(ifr.ifr_name);
1411
1412         return fd;
1413 }
1414
1415 struct rs_cb_data {
1416         GIOChannel *channel;
1417         __connman_inet_rs_cb_t callback;
1418         struct sockaddr_in6 addr;
1419         guint rs_timeout;
1420         void *user_data;
1421 };
1422
1423 #define CMSG_BUF_LEN 512
1424 #define IN6ADDR_ALL_NODES_MC_INIT \
1425         { { { 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0x1 } } } /* ff02::1 */
1426 #define IN6ADDR_ALL_ROUTERS_MC_INIT \
1427         { { { 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0x2 } } } /* ff02::2 */
1428
1429 static const struct in6_addr in6addr_all_nodes_mc = IN6ADDR_ALL_NODES_MC_INIT;
1430 static const struct in6_addr in6addr_all_routers_mc =
1431                                                 IN6ADDR_ALL_ROUTERS_MC_INIT;
1432
1433 static void rs_cleanup(struct rs_cb_data *data)
1434 {
1435         g_io_channel_shutdown(data->channel, TRUE, NULL);
1436         g_io_channel_unref(data->channel);
1437         data->channel = 0;
1438
1439         if (data->rs_timeout > 0)
1440                 g_source_remove(data->rs_timeout);
1441
1442         g_free(data);
1443 }
1444
1445 static gboolean rs_timeout_cb(gpointer user_data)
1446 {
1447         struct rs_cb_data *data = user_data;
1448
1449         DBG("user data %p", user_data);
1450
1451         if (data == NULL)
1452                 return FALSE;
1453
1454         if (data->callback != NULL)
1455                 data->callback(NULL, data->user_data);
1456
1457         data->rs_timeout = 0;
1458         rs_cleanup(data);
1459         return FALSE;
1460 }
1461
1462 static int icmpv6_recv(int fd, gpointer user_data)
1463 {
1464         struct msghdr mhdr;
1465         struct iovec iov;
1466         unsigned char chdr[CMSG_BUF_LEN];
1467         unsigned char buf[1540];
1468         struct rs_cb_data *data = user_data;
1469         struct nd_router_advert *hdr;
1470         struct sockaddr_in6 saddr;
1471         ssize_t len;
1472
1473         DBG("");
1474
1475         iov.iov_len = sizeof(buf);
1476         iov.iov_base = buf;
1477
1478         mhdr.msg_name = (void *)&saddr;
1479         mhdr.msg_namelen = sizeof(struct sockaddr_in6);
1480         mhdr.msg_iov = &iov;
1481         mhdr.msg_iovlen = 1;
1482         mhdr.msg_control = (void *)chdr;
1483         mhdr.msg_controllen = CMSG_BUF_LEN;
1484
1485         len = recvmsg(fd, &mhdr, 0);
1486         if (len < 0) {
1487                 data->callback(NULL, data->user_data);
1488                 rs_cleanup(data);
1489                 return -errno;
1490         }
1491
1492         hdr = (struct nd_router_advert *)buf;
1493         if (hdr->nd_ra_code != 0)
1494                 return 0;
1495
1496         data->callback(hdr, data->user_data);
1497         rs_cleanup(data);
1498
1499         return len;
1500 }
1501
1502 static gboolean icmpv6_event(GIOChannel *chan, GIOCondition cond,
1503                                                                 gpointer data)
1504 {
1505         int fd, ret;
1506
1507         DBG("");
1508
1509         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
1510                 return FALSE;
1511
1512         fd = g_io_channel_unix_get_fd(chan);
1513         ret = icmpv6_recv(fd, data);
1514         if (ret == 0)
1515                 return TRUE;
1516
1517         return FALSE;
1518 }
1519
1520 /* Adapted from RFC 1071 "C" Implementation Example */
1521 static uint16_t csum(const void *phdr, const void *data, socklen_t datalen)
1522 {
1523         register unsigned long sum = 0;
1524         socklen_t count;
1525         uint16_t *addr;
1526         int i;
1527
1528         /* caller must make sure datalen is even */
1529
1530         addr = (uint16_t *)phdr;
1531         for (i = 0; i < 20; i++)
1532                 sum += *addr++;
1533
1534         count = datalen;
1535         addr = (uint16_t *)data;
1536
1537         while (count > 1) {
1538                 sum += *(addr++);
1539                 count -= 2;
1540         }
1541
1542         while (sum >> 16)
1543                 sum = (sum & 0xffff) + (sum >> 16);
1544
1545         return (uint16_t)~sum;
1546 }
1547
1548 static int ndisc_send_unspec(int type, int oif, const struct in6_addr *dest)
1549 {
1550         struct _phdr {
1551                 struct in6_addr src;
1552                 struct in6_addr dst;
1553                 uint32_t plen;
1554                 uint8_t reserved[3];
1555                 uint8_t nxt;
1556         } phdr;
1557
1558         struct {
1559                 struct ip6_hdr ip;
1560                 union {
1561                         struct icmp6_hdr icmp;
1562                         struct nd_neighbor_solicit ns;
1563                         struct nd_router_solicit rs;
1564                 } i;
1565         } frame;
1566
1567         struct msghdr msgh;
1568         struct cmsghdr *cmsg;
1569         struct in6_pktinfo *pinfo;
1570         struct sockaddr_in6 dst;
1571         char cbuf[CMSG_SPACE(sizeof(*pinfo))];
1572         struct iovec iov;
1573         int fd, datalen, ret;
1574
1575         DBG("");
1576
1577         fd = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_RAW);
1578         if (fd < 0)
1579                 return -errno;
1580
1581         memset(&frame, 0, sizeof(frame));
1582         memset(&dst, 0, sizeof(dst));
1583
1584         datalen = sizeof(frame.i.rs); /* 8, csum() safe */
1585         dst.sin6_addr = *dest;
1586
1587         /* Fill in the IPv6 header */
1588         frame.ip.ip6_vfc = 0x60;
1589         frame.ip.ip6_plen = htons(datalen);
1590         frame.ip.ip6_nxt = IPPROTO_ICMPV6;
1591         frame.ip.ip6_hlim = 255;
1592         frame.ip.ip6_dst = dst.sin6_addr;
1593         /* all other fields are already set to zero */
1594
1595         /* Prepare pseudo header for csum */
1596         memset(&phdr, 0, sizeof(phdr));
1597         phdr.dst = dst.sin6_addr;
1598         phdr.plen = htonl(datalen);
1599         phdr.nxt = IPPROTO_ICMPV6;
1600
1601         /* Fill in remaining ICMP header fields */
1602         frame.i.icmp.icmp6_type = type;
1603         frame.i.icmp.icmp6_cksum = csum(&phdr, &frame.i, datalen);
1604
1605         iov.iov_base = &frame;
1606         iov.iov_len = sizeof(frame.ip) + datalen;
1607
1608         dst.sin6_family = AF_INET6;
1609         msgh.msg_name = &dst;
1610         msgh.msg_namelen = sizeof(dst);
1611         msgh.msg_iov = &iov;
1612         msgh.msg_iovlen = 1;
1613         msgh.msg_flags = 0;
1614
1615         memset(cbuf, 0, CMSG_SPACE(sizeof(*pinfo)));
1616         cmsg = (struct cmsghdr *)cbuf;
1617         pinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
1618         pinfo->ipi6_ifindex = oif;
1619
1620         cmsg->cmsg_len = CMSG_LEN(sizeof(*pinfo));
1621         cmsg->cmsg_level = IPPROTO_IPV6;
1622         cmsg->cmsg_type = IPV6_PKTINFO;
1623         msgh.msg_control = cmsg;
1624         msgh.msg_controllen = cmsg->cmsg_len;
1625
1626         ret = sendmsg(fd, &msgh, 0);
1627
1628         close(fd);
1629         return ret;
1630 }
1631
1632 static inline void ipv6_addr_set(struct in6_addr *addr,
1633                                 uint32_t w1, uint32_t w2,
1634                                 uint32_t w3, uint32_t w4)
1635 {
1636         addr->s6_addr32[0] = w1;
1637         addr->s6_addr32[1] = w2;
1638         addr->s6_addr32[2] = w3;
1639         addr->s6_addr32[3] = w4;
1640 }
1641
1642 static inline void ipv6_addr_solict_mult(const struct in6_addr *addr,
1643                                         struct in6_addr *solicited)
1644 {
1645         ipv6_addr_set(solicited, htonl(0xFF020000), 0, htonl(0x1),
1646                         htonl(0xFF000000) | addr->s6_addr32[3]);
1647 }
1648
1649 static int if_mc_group(int sock, int ifindex, const struct in6_addr *mc_addr,
1650                                                                 int cmd)
1651 {
1652         unsigned int val = 0;
1653         struct ipv6_mreq mreq;
1654         int ret;
1655
1656         memset(&mreq, 0, sizeof(mreq));
1657         mreq.ipv6mr_interface = ifindex;
1658         mreq.ipv6mr_multiaddr = *mc_addr;
1659
1660         ret = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
1661                         &val, sizeof(int));
1662
1663         if (ret < 0)
1664                 return ret;
1665
1666         return setsockopt(sock, IPPROTO_IPV6, cmd, &mreq, sizeof(mreq));
1667 }
1668
1669 int __connman_inet_ipv6_send_rs(int index, int timeout,
1670                         __connman_inet_rs_cb_t callback, void *user_data)
1671 {
1672         struct rs_cb_data *data;
1673         struct icmp6_filter filter;
1674         struct in6_addr solicit;
1675         struct in6_addr dst = in6addr_all_routers_mc;
1676         int sk;
1677
1678         DBG("");
1679
1680         if (timeout <= 0)
1681                 return -EINVAL;
1682
1683         data = g_try_malloc0(sizeof(struct rs_cb_data));
1684         if (data == NULL)
1685                 return -ENOMEM;
1686
1687         data->callback = callback;
1688         data->user_data = user_data;
1689         data->rs_timeout = g_timeout_add_seconds(timeout, rs_timeout_cb, data);
1690
1691         sk = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_ICMPV6);
1692         if (sk < 0)
1693                 return -errno;
1694
1695         ICMP6_FILTER_SETBLOCKALL(&filter);
1696         ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
1697
1698         setsockopt(sk, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
1699                                                 sizeof(struct icmp6_filter));
1700
1701         ipv6_addr_solict_mult(&dst, &solicit);
1702         if_mc_group(sk, index, &in6addr_all_nodes_mc, IPV6_JOIN_GROUP);
1703         if_mc_group(sk, index, &solicit, IPV6_JOIN_GROUP);
1704
1705         data->channel = g_io_channel_unix_new(sk);
1706         g_io_channel_set_close_on_unref(data->channel, TRUE);
1707
1708         g_io_channel_set_encoding(data->channel, NULL, NULL);
1709         g_io_channel_set_buffered(data->channel, FALSE);
1710
1711         g_io_add_watch(data->channel,
1712                         G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
1713                         icmpv6_event, data);
1714
1715         ndisc_send_unspec(ND_ROUTER_SOLICIT, index, &dst);
1716
1717         return 0;
1718 }