inet: Fixed indentation.
[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_clear_gateway_address(int index, const char *gateway)
1018 {
1019         struct ifreq ifr;
1020         struct rtentry rt;
1021         struct sockaddr_in addr;
1022         int sk, err;
1023
1024         DBG("");
1025
1026         sk = socket(PF_INET, SOCK_DGRAM, 0);
1027         if (sk < 0)
1028                 return -1;
1029
1030         memset(&ifr, 0, sizeof(ifr));
1031         ifr.ifr_ifindex = index;
1032
1033         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1034                 close(sk);
1035                 return -1;
1036         }
1037
1038         DBG("ifname %s", ifr.ifr_name);
1039
1040         memset(&rt, 0, sizeof(rt));
1041         rt.rt_flags = RTF_UP | RTF_GATEWAY;
1042
1043         memset(&addr, 0, sizeof(addr));
1044         addr.sin_family = AF_INET;
1045         addr.sin_addr.s_addr = INADDR_ANY;
1046         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1047
1048         memset(&addr, 0, sizeof(addr));
1049         addr.sin_family = AF_INET;
1050         addr.sin_addr.s_addr = inet_addr(gateway);
1051         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1052
1053         memset(&addr, 0, sizeof(addr));
1054         addr.sin_family = AF_INET;
1055         addr.sin_addr.s_addr = INADDR_ANY;
1056         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1057
1058         err = ioctl(sk, SIOCDELRT, &rt);
1059         if (err < 0)
1060                 connman_error("Removing default gateway route failed (%s)",
1061                                                         strerror(errno));
1062
1063         close(sk);
1064
1065         return err;
1066 }
1067
1068 int connman_inet_clear_gateway_interface(int index)
1069 {
1070         struct ifreq ifr;
1071         struct rtentry rt;
1072         struct sockaddr_in addr;
1073         int sk, err;
1074
1075         DBG("");
1076
1077         sk = socket(PF_INET, SOCK_DGRAM, 0);
1078         if (sk < 0)
1079                 return -1;
1080
1081         memset(&ifr, 0, sizeof(ifr));
1082         ifr.ifr_ifindex = index;
1083
1084         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1085                 close(sk);
1086                 return -1;
1087         }
1088
1089         DBG("ifname %s", ifr.ifr_name);
1090
1091         memset(&rt, 0, sizeof(rt));
1092         rt.rt_flags = RTF_UP;
1093
1094         memset(&addr, 0, sizeof(addr));
1095         addr.sin_family = AF_INET;
1096         addr.sin_addr.s_addr = INADDR_ANY;
1097
1098         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1099         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1100         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1101
1102         rt.rt_dev = ifr.ifr_name;
1103
1104         err = ioctl(sk, SIOCDELRT, &rt);
1105         if (err < 0)
1106                 connman_error("Removing default interface route failed (%s)",
1107                                                         strerror(errno));
1108         close(sk);
1109
1110         return err;
1111 }
1112
1113 connman_bool_t connman_inet_compare_subnet(int index, const char *host)
1114 {
1115         struct ifreq ifr;
1116         struct in_addr _host_addr;
1117         in_addr_t host_addr, netmask_addr, if_addr;
1118         struct sockaddr_in *netmask, *addr;
1119         int sk;
1120
1121         DBG("host %s", host);
1122
1123         if (host == NULL)
1124                 return FALSE;
1125
1126         if (inet_aton(host, &_host_addr) == 0)
1127                 return -1;
1128         host_addr = _host_addr.s_addr;
1129
1130         sk = socket(PF_INET, SOCK_DGRAM, 0);
1131         if (sk < 0)
1132                 return FALSE;
1133
1134         memset(&ifr, 0, sizeof(ifr));
1135         ifr.ifr_ifindex = index;
1136
1137         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1138                 close(sk);
1139                 return FALSE;
1140         }
1141
1142         if (ioctl(sk, SIOCGIFNETMASK, &ifr) < 0) {
1143                 close(sk);
1144                 return FALSE;
1145         }
1146
1147         netmask = (struct sockaddr_in *)&ifr.ifr_netmask;
1148         netmask_addr = netmask->sin_addr.s_addr;
1149
1150         if (ioctl(sk, SIOCGIFADDR, &ifr) < 0) {
1151                 close(sk);
1152                 return FALSE;
1153         }
1154         addr = (struct sockaddr_in *)&ifr.ifr_addr;
1155         if_addr = addr->sin_addr.s_addr;
1156
1157         return ((if_addr & netmask_addr) == (host_addr & netmask_addr));
1158 }
1159
1160 int connman_inet_remove_from_bridge(int index, const char *bridge)
1161 {
1162         struct ifreq ifr;
1163         int sk, err;
1164
1165         if (bridge == NULL)
1166                 return -EINVAL;
1167
1168         sk = socket(AF_INET, SOCK_STREAM, 0);
1169         if (sk < 0)
1170                 return sk;
1171
1172         memset(&ifr, 0, sizeof(ifr));
1173         strncpy(ifr.ifr_name, bridge, IFNAMSIZ - 1);
1174         ifr.ifr_ifindex = index;
1175
1176         err = ioctl(sk, SIOCBRDELIF, &ifr);
1177
1178         close(sk);
1179
1180         if (err < 0) {
1181                 connman_error("Remove interface from bridge error %s",
1182                                                         strerror(errno));
1183                 return err;
1184         }
1185
1186         return 0;
1187 }
1188
1189 int connman_inet_add_to_bridge(int index, const char *bridge)
1190 {
1191         struct ifreq ifr;
1192         int sk, err;
1193
1194         if (bridge == NULL)
1195                 return -EINVAL;
1196
1197         sk = socket(AF_INET, SOCK_STREAM, 0);
1198         if (sk < 0)
1199                 return sk;
1200
1201         memset(&ifr, 0, sizeof(ifr));
1202         strncpy(ifr.ifr_name, bridge, IFNAMSIZ - 1);
1203         ifr.ifr_ifindex = index;
1204
1205         err = ioctl(sk, SIOCBRADDIF, &ifr);
1206
1207         close(sk);
1208
1209         if (err < 0) {
1210                 connman_error("Add interface to bridge error %s",
1211                                                         strerror(errno));
1212                 return err;
1213         }
1214
1215         return 0;
1216 }
1217
1218 int connman_inet_set_mtu(int index, int mtu)
1219 {
1220         struct ifreq ifr;
1221         int sk, err;
1222
1223         sk = socket(AF_INET, SOCK_DGRAM, 0);
1224         if (sk < 0)
1225                 return sk;
1226
1227         memset(&ifr, 0, sizeof(ifr));
1228         ifr.ifr_ifindex = index;
1229
1230         err = ioctl(sk, SIOCGIFNAME, &ifr);
1231         if (err == 0) {
1232                 ifr.ifr_mtu = mtu;
1233                 err = ioctl(sk, SIOCSIFMTU, &ifr);
1234         }
1235
1236         close(sk);
1237         return err;
1238 }
1239
1240 int connman_inet_setup_tunnel(char *tunnel, int mtu)
1241 {
1242         struct ifreq ifr;
1243         int sk, err, index;
1244         __u32 mask;
1245         __u32 flags;
1246
1247         if (tunnel == NULL)
1248                 return -EINVAL;
1249
1250         sk = socket(AF_INET, SOCK_DGRAM, 0);
1251         if (sk < 0)
1252                 return sk;
1253
1254         index = if_nametoindex(tunnel);
1255
1256         err = connman_inet_set_mtu(index, mtu);
1257         if (err < 0)
1258                 return err;
1259         else if (err)
1260                 goto done;
1261
1262         memset(&ifr, 0, sizeof(ifr));
1263         strncpy(ifr.ifr_name, tunnel, IFNAMSIZ);
1264         err = ioctl(sk, SIOCGIFFLAGS, &ifr);
1265         if (err)
1266                 goto done;
1267
1268         mask = IFF_UP;
1269         flags = IFF_UP;
1270
1271         if ((ifr.ifr_flags ^ flags) & mask) {
1272                 ifr.ifr_flags &= ~mask;
1273                 ifr.ifr_flags |= mask & flags;
1274                 err = ioctl(sk, SIOCSIFFLAGS, &ifr);
1275                 if (err)
1276                         connman_error("SIOCSIFFLAGS failed: %s",
1277                                                         strerror(errno));
1278         }
1279
1280 done:
1281         close(sk);
1282         return err;
1283 }
1284
1285 int connman_inet_create_tunnel(char **iface)
1286 {
1287         struct ifreq ifr;
1288         int i, fd;
1289
1290         fd = open("/dev/net/tun", O_RDWR);
1291         if (fd < 0) {
1292                 i = -errno;
1293                 connman_error("Failed to open /dev/net/tun: %s",
1294                                 strerror(errno));
1295                 return i;
1296         }
1297
1298         memset(&ifr, 0, sizeof(ifr));
1299         ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
1300
1301         for (i = 0; i < 256; i++) {
1302                 sprintf(ifr.ifr_name, "tun%d", i);
1303
1304                 if (!ioctl(fd, TUNSETIFF, (void *)&ifr))
1305                         break;
1306         }
1307
1308         if (i == 256) {
1309                 connman_error("Failed to find available tun device");
1310                 close(fd);
1311                 return -ENODEV;
1312         }
1313
1314         *iface = g_strdup(ifr.ifr_name);
1315
1316         return fd;
1317 }
1318
1319 struct rs_cb_data {
1320         GIOChannel *channel;
1321         __connman_inet_rs_cb_t callback;
1322         struct sockaddr_in6 addr;
1323         guint rs_timeout;
1324         void *user_data;
1325 };
1326
1327 #define CMSG_BUF_LEN 512
1328 #define IN6ADDR_ALL_NODES_MC_INIT \
1329         { { { 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0x1 } } } /* ff02::1 */
1330 #define IN6ADDR_ALL_ROUTERS_MC_INIT \
1331         { { { 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0x2 } } } /* ff02::2 */
1332
1333 static const struct in6_addr in6addr_all_nodes_mc = IN6ADDR_ALL_NODES_MC_INIT;
1334 static const struct in6_addr in6addr_all_routers_mc =
1335                                                 IN6ADDR_ALL_ROUTERS_MC_INIT;
1336
1337 /* from netinet/in.h */
1338 struct in6_pktinfo {
1339         struct in6_addr ipi6_addr;  /* src/dst IPv6 address */
1340         unsigned int ipi6_ifindex;  /* send/recv interface index */
1341 };
1342
1343 static void rs_cleanup(struct rs_cb_data *data)
1344 {
1345         g_io_channel_shutdown(data->channel, TRUE, NULL);
1346         g_io_channel_unref(data->channel);
1347         data->channel = 0;
1348
1349         if (data->rs_timeout > 0)
1350                 g_source_remove(data->rs_timeout);
1351
1352         g_free(data);
1353 }
1354
1355 static gboolean rs_timeout_cb(gpointer user_data)
1356 {
1357         struct rs_cb_data *data = user_data;
1358
1359         DBG("user data %p", user_data);
1360
1361         if (data == NULL)
1362                 return FALSE;
1363
1364         if (data->callback != NULL)
1365                 data->callback(NULL, data->user_data);
1366
1367         data->rs_timeout = 0;
1368         rs_cleanup(data);
1369         return FALSE;
1370 }
1371
1372 static int icmpv6_recv(int fd, gpointer user_data)
1373 {
1374         struct msghdr mhdr;
1375         struct iovec iov;
1376         unsigned char chdr[CMSG_BUF_LEN];
1377         unsigned char buf[1540];
1378         struct rs_cb_data *data = user_data;
1379         struct nd_router_advert *hdr;
1380         struct sockaddr_in6 saddr;
1381         ssize_t len;
1382
1383         DBG("");
1384
1385         iov.iov_len = sizeof(buf);
1386         iov.iov_base = buf;
1387
1388         mhdr.msg_name = (void *)&saddr;
1389         mhdr.msg_namelen = sizeof(struct sockaddr_in6);
1390         mhdr.msg_iov = &iov;
1391         mhdr.msg_iovlen = 1;
1392         mhdr.msg_control = (void *)chdr;
1393         mhdr.msg_controllen = CMSG_BUF_LEN;
1394
1395         len = recvmsg(fd, &mhdr, 0);
1396         if (len < 0) {
1397                 data->callback(NULL, data->user_data);
1398                 return -errno;
1399         }
1400
1401         hdr = (struct nd_router_advert *)buf;
1402         if (hdr->nd_ra_code != 0)
1403                 return 0;
1404
1405         data->callback(hdr, data->user_data);
1406         rs_cleanup(data);
1407
1408         return len;
1409 }
1410
1411 static gboolean icmpv6_event(GIOChannel *chan, GIOCondition cond,
1412                                                                 gpointer data)
1413 {
1414         int fd, ret;
1415
1416         DBG("");
1417
1418         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
1419                 return FALSE;
1420
1421         fd = g_io_channel_unix_get_fd(chan);
1422         ret = icmpv6_recv(fd, data);
1423         if (ret == 0)
1424                 return TRUE;
1425
1426         return FALSE;
1427 }
1428
1429 /* Adapted from RFC 1071 "C" Implementation Example */
1430 static uint16_t csum(const void *phdr, const void *data, socklen_t datalen)
1431 {
1432         register unsigned long sum = 0;
1433         socklen_t count;
1434         uint16_t *addr;
1435         int i;
1436
1437         /* caller must make sure datalen is even */
1438
1439         addr = (uint16_t *)phdr;
1440         for (i = 0; i < 20; i++)
1441                 sum += *addr++;
1442
1443         count = datalen;
1444         addr = (uint16_t *)data;
1445
1446         while (count > 1) {
1447                 sum += *(addr++);
1448                 count -= 2;
1449         }
1450
1451         while (sum >> 16)
1452                 sum = (sum & 0xffff) + (sum >> 16);
1453
1454         return (uint16_t)~sum;
1455 }
1456
1457 static int ndisc_send_unspec(int type, int oif, const struct in6_addr *dest)
1458 {
1459         struct _phdr {
1460                 struct in6_addr src;
1461                 struct in6_addr dst;
1462                 uint32_t plen;
1463                 uint8_t reserved[3];
1464                 uint8_t nxt;
1465         } phdr;
1466
1467         struct {
1468                 struct ip6_hdr ip;
1469                 union {
1470                         struct icmp6_hdr icmp;
1471                         struct nd_neighbor_solicit ns;
1472                         struct nd_router_solicit rs;
1473                 } i;
1474         } frame;
1475
1476         struct msghdr msgh;
1477         struct cmsghdr *cmsg;
1478         struct in6_pktinfo *pinfo;
1479         struct sockaddr_in6 dst;
1480         char cbuf[CMSG_SPACE(sizeof(*pinfo))];
1481         struct iovec iov;
1482         int fd, datalen, ret;
1483
1484         DBG("");
1485
1486         fd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
1487         if (fd < 0)
1488                 return -errno;
1489
1490         memset(&frame, 0, sizeof(frame));
1491         memset(&dst, 0, sizeof(dst));
1492
1493         datalen = sizeof(frame.i.rs); /* 8, csum() safe */
1494         dst.sin6_addr = *dest;
1495
1496         /* Fill in the IPv6 header */
1497         frame.ip.ip6_vfc = 0x60;
1498         frame.ip.ip6_plen = htons(datalen);
1499         frame.ip.ip6_nxt = IPPROTO_ICMPV6;
1500         frame.ip.ip6_hlim = 255;
1501         frame.ip.ip6_dst = dst.sin6_addr;
1502         /* all other fields are already set to zero */
1503
1504         /* Prepare pseudo header for csum */
1505         memset(&phdr, 0, sizeof(phdr));
1506         phdr.dst = dst.sin6_addr;
1507         phdr.plen = htonl(datalen);
1508         phdr.nxt = IPPROTO_ICMPV6;
1509
1510         /* Fill in remaining ICMP header fields */
1511         frame.i.icmp.icmp6_type = type;
1512         frame.i.icmp.icmp6_cksum = csum(&phdr, &frame.i, datalen);
1513
1514         iov.iov_base = &frame;
1515         iov.iov_len = sizeof(frame.ip) + datalen;
1516
1517         dst.sin6_family = AF_INET6;
1518         msgh.msg_name = &dst;
1519         msgh.msg_namelen = sizeof(dst);
1520         msgh.msg_iov = &iov;
1521         msgh.msg_iovlen = 1;
1522         msgh.msg_flags = 0;
1523
1524         memset(cbuf, 0, CMSG_SPACE(sizeof(*pinfo)));
1525         cmsg = (struct cmsghdr *)cbuf;
1526         pinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
1527         pinfo->ipi6_ifindex = oif;
1528
1529         cmsg->cmsg_len = CMSG_LEN(sizeof(*pinfo));
1530         cmsg->cmsg_level = IPPROTO_IPV6;
1531         cmsg->cmsg_type = IPV6_PKTINFO;
1532         msgh.msg_control = cmsg;
1533         msgh.msg_controllen = cmsg->cmsg_len;
1534
1535         ret = sendmsg(fd, &msgh, 0);
1536
1537         close(fd);
1538         return ret;
1539 }
1540
1541 static inline void ipv6_addr_set(struct in6_addr *addr,
1542                                 uint32_t w1, uint32_t w2,
1543                                 uint32_t w3, uint32_t w4)
1544 {
1545         addr->s6_addr32[0] = w1;
1546         addr->s6_addr32[1] = w2;
1547         addr->s6_addr32[2] = w3;
1548         addr->s6_addr32[3] = w4;
1549 }
1550
1551 static inline void ipv6_addr_solict_mult(const struct in6_addr *addr,
1552                                         struct in6_addr *solicited)
1553 {
1554         ipv6_addr_set(solicited, htonl(0xFF020000), 0, htonl(0x1),
1555                         htonl(0xFF000000) | addr->s6_addr32[3]);
1556 }
1557
1558 static int if_mc_group(int sock, int ifindex, const struct in6_addr *mc_addr,
1559                                                                 int cmd)
1560 {
1561         unsigned int val = 0;
1562         struct ipv6_mreq mreq;
1563         int ret;
1564
1565         memset(&mreq, 0, sizeof(mreq));
1566         mreq.ipv6mr_interface = ifindex;
1567         mreq.ipv6mr_multiaddr = *mc_addr;
1568
1569         ret = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
1570                         &val, sizeof(int));
1571
1572         if (ret < 0)
1573                 return ret;
1574
1575         return setsockopt(sock, IPPROTO_IPV6, cmd, &mreq, sizeof(mreq));
1576 }
1577
1578 int __connman_inet_ipv6_send_rs(int index, int timeout,
1579                         __connman_inet_rs_cb_t callback, void *user_data)
1580 {
1581         struct rs_cb_data *data;
1582         struct icmp6_filter filter;
1583         struct in6_addr solicit;
1584         struct in6_addr dst = in6addr_all_routers_mc;
1585         int sk;
1586
1587         DBG("");
1588
1589         if (timeout <= 0)
1590                 return -EINVAL;
1591
1592         data = g_try_malloc0(sizeof(struct rs_cb_data));
1593         if (data == NULL)
1594                 return -ENOMEM;
1595
1596         data->callback = callback;
1597         data->user_data = user_data;
1598         data->rs_timeout = g_timeout_add_seconds(timeout, rs_timeout_cb, data);
1599
1600         sk = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
1601         if (sk < 0)
1602                 return -errno;
1603
1604         ICMP6_FILTER_SETBLOCKALL(&filter);
1605         ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
1606
1607         setsockopt(sk, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
1608                                                 sizeof(struct icmp6_filter));
1609
1610         ipv6_addr_solict_mult(&dst, &solicit);
1611         if_mc_group(sk, index, &in6addr_all_nodes_mc, IPV6_JOIN_GROUP);
1612         if_mc_group(sk, index, &solicit, IPV6_JOIN_GROUP);
1613
1614         data->channel = g_io_channel_unix_new(sk);
1615         g_io_channel_set_close_on_unref(data->channel, TRUE);
1616
1617         g_io_channel_set_encoding(data->channel, NULL, NULL);
1618         g_io_channel_set_buffered(data->channel, FALSE);
1619
1620         g_io_add_watch(data->channel,
1621                         G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
1622                         icmpv6_event, data);
1623
1624         ndisc_send_unspec(ND_ROUTER_SOLICIT, index, &dst);
1625
1626         return 0;
1627 }