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