inet: Standardize error codes and messages
[framework/connectivity/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");
787
788         return err;
789 }
790
791 int connman_inet_del_ipv6_host_route(int index, const char *host)
792 {
793         return connman_inet_del_ipv6_network_route(index, host, 128);
794 }
795
796 int connman_inet_add_ipv6_network_route(int index, const char *host,
797                                         const char *gateway,
798                                                 unsigned char prefix_len)
799 {
800         struct in6_rtmsg rt;
801         int sk, err;
802
803         DBG("index %d host %s gateway %s", index, host, gateway);
804
805         if (host == NULL)
806                 return -EINVAL;
807
808         memset(&rt, 0, sizeof(rt));
809
810         rt.rtmsg_dst_len = prefix_len;
811
812         err = inet_pton(AF_INET6, host, &rt.rtmsg_dst);
813         if (err < 0)
814                 goto out;
815
816         rt.rtmsg_flags = RTF_UP | RTF_HOST;
817
818         if (gateway != NULL) {
819                 rt.rtmsg_flags |= RTF_GATEWAY;
820                 inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway);
821         }
822
823         rt.rtmsg_metric = 1;
824         rt.rtmsg_ifindex = index;
825
826         sk = socket(AF_INET6, SOCK_DGRAM, 0);
827         if (sk < 0) {
828                 err = -1;
829                 goto out;
830         }
831
832         err = ioctl(sk, SIOCADDRT, &rt);
833         close(sk);
834 out:
835         if (err < 0)
836                 connman_error("Set IPv6 host route error");
837
838         return err;
839 }
840
841 int connman_inet_add_ipv6_host_route(int index, const char *host,
842                                         const char *gateway)
843 {
844         return connman_inet_add_ipv6_network_route(index, host, gateway, 128);
845 }
846
847 int connman_inet_set_ipv6_gateway_address(int index, const char *gateway)
848 {
849         struct in6_rtmsg rt;
850         int sk, err;
851
852         DBG("index %d, gateway %s", index, gateway);
853
854         if (gateway == NULL)
855                 return -EINVAL;
856
857         memset(&rt, 0, sizeof(rt));
858
859         err = inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway);
860         if (err < 0)
861                 goto out;
862
863         rt.rtmsg_flags = RTF_UP | RTF_GATEWAY;
864         rt.rtmsg_metric = 1;
865         rt.rtmsg_dst_len = 0;
866         rt.rtmsg_ifindex = index;
867
868         sk = socket(AF_INET6, SOCK_DGRAM, 0);
869         if (sk < 0) {
870                 err = -1;
871                 goto out;
872         }
873
874         err = ioctl(sk, SIOCADDRT, &rt);
875         close(sk);
876 out:
877         if (err < 0)
878                 connman_error("Set default IPv6 gateway error");
879
880         return err;
881 }
882
883 int connman_inet_clear_ipv6_gateway_address(int index, const char *gateway)
884 {
885         struct in6_rtmsg rt;
886         int sk, err;
887
888         DBG("index %d, gateway %s", index, gateway);
889
890         if (gateway == NULL)
891                 return -EINVAL;
892
893         memset(&rt, 0, sizeof(rt));
894
895         err = inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway);
896         if (err < 0)
897                 goto out;
898
899         rt.rtmsg_flags = RTF_UP | RTF_GATEWAY;
900         rt.rtmsg_metric = 1;
901         rt.rtmsg_dst_len = 0;
902         rt.rtmsg_ifindex = index;
903
904         sk = socket(AF_INET6, SOCK_DGRAM, 0);
905         if (sk < 0) {
906                 err = -1;
907                 goto out;
908         }
909
910         err = ioctl(sk, SIOCDELRT, &rt);
911         close(sk);
912 out:
913         if (err < 0)
914                 connman_error("Clear default IPv6 gateway error");
915
916         return err;
917 }
918
919 int connman_inet_set_gateway_address(int index, const char *gateway)
920 {
921         struct ifreq ifr;
922         struct rtentry rt;
923         struct sockaddr_in addr;
924         int sk, err;
925
926         sk = socket(PF_INET, SOCK_DGRAM, 0);
927         if (sk < 0)
928                 return -1;
929
930         memset(&ifr, 0, sizeof(ifr));
931         ifr.ifr_ifindex = index;
932
933         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
934                 close(sk);
935                 return -1;
936         }
937
938         DBG("ifname %s", ifr.ifr_name);
939
940         memset(&rt, 0, sizeof(rt));
941         rt.rt_flags = RTF_UP | RTF_GATEWAY;
942
943         memset(&addr, 0, sizeof(addr));
944         addr.sin_family = AF_INET;
945         addr.sin_addr.s_addr = INADDR_ANY;
946         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
947
948         memset(&addr, 0, sizeof(addr));
949         addr.sin_family = AF_INET;
950         addr.sin_addr.s_addr = inet_addr(gateway);
951         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
952
953         memset(&addr, 0, sizeof(addr));
954         addr.sin_family = AF_INET;
955         addr.sin_addr.s_addr = INADDR_ANY;
956         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
957
958         err = ioctl(sk, SIOCADDRT, &rt);
959         if (err < 0)
960                 connman_error("Setting default gateway route failed (%s)",
961                                                         strerror(errno));
962
963         close(sk);
964
965         return err;
966 }
967
968 int connman_inet_set_gateway_interface(int index)
969 {
970         struct ifreq ifr;
971         struct rtentry rt;
972         struct sockaddr_in addr;
973         int sk, err;
974
975         DBG("");
976
977         sk = socket(PF_INET, SOCK_DGRAM, 0);
978         if (sk < 0)
979                 return -1;
980
981         memset(&ifr, 0, sizeof(ifr));
982         ifr.ifr_ifindex = index;
983
984         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
985                 close(sk);
986                 return -1;
987         }
988
989         DBG("ifname %s", ifr.ifr_name);
990
991         memset(&rt, 0, sizeof(rt));
992         rt.rt_flags = RTF_UP;
993
994         memset(&addr, 0, sizeof(addr));
995         addr.sin_family = AF_INET;
996         addr.sin_addr.s_addr = INADDR_ANY;
997
998         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
999         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1000         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1001
1002         rt.rt_dev = ifr.ifr_name;
1003
1004         err = ioctl(sk, SIOCADDRT, &rt);
1005         if (err < 0)
1006                 connman_error("Setting default interface route failed (%s)",
1007                                                         strerror(errno));
1008         close(sk);
1009
1010         return err;
1011 }
1012
1013 int connman_inet_clear_gateway_address(int index, const char *gateway)
1014 {
1015         struct ifreq ifr;
1016         struct rtentry rt;
1017         struct sockaddr_in addr;
1018         int sk, err;
1019
1020         DBG("");
1021
1022         sk = socket(PF_INET, SOCK_DGRAM, 0);
1023         if (sk < 0)
1024                 return -1;
1025
1026         memset(&ifr, 0, sizeof(ifr));
1027         ifr.ifr_ifindex = index;
1028
1029         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1030                 close(sk);
1031                 return -1;
1032         }
1033
1034         DBG("ifname %s", ifr.ifr_name);
1035
1036         memset(&rt, 0, sizeof(rt));
1037         rt.rt_flags = RTF_UP | RTF_GATEWAY;
1038
1039         memset(&addr, 0, sizeof(addr));
1040         addr.sin_family = AF_INET;
1041         addr.sin_addr.s_addr = INADDR_ANY;
1042         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1043
1044         memset(&addr, 0, sizeof(addr));
1045         addr.sin_family = AF_INET;
1046         addr.sin_addr.s_addr = inet_addr(gateway);
1047         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1048
1049         memset(&addr, 0, sizeof(addr));
1050         addr.sin_family = AF_INET;
1051         addr.sin_addr.s_addr = INADDR_ANY;
1052         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1053
1054         err = ioctl(sk, SIOCDELRT, &rt);
1055         if (err < 0)
1056                 connman_error("Removing default gateway route failed (%s)",
1057                                                         strerror(errno));
1058
1059         close(sk);
1060
1061         return err;
1062 }
1063
1064 int connman_inet_clear_gateway_interface(int index)
1065 {
1066         struct ifreq ifr;
1067         struct rtentry rt;
1068         struct sockaddr_in addr;
1069         int sk, err;
1070
1071         DBG("");
1072
1073         sk = socket(PF_INET, SOCK_DGRAM, 0);
1074         if (sk < 0)
1075                 return -1;
1076
1077         memset(&ifr, 0, sizeof(ifr));
1078         ifr.ifr_ifindex = index;
1079
1080         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1081                 close(sk);
1082                 return -1;
1083         }
1084
1085         DBG("ifname %s", ifr.ifr_name);
1086
1087         memset(&rt, 0, sizeof(rt));
1088         rt.rt_flags = RTF_UP;
1089
1090         memset(&addr, 0, sizeof(addr));
1091         addr.sin_family = AF_INET;
1092         addr.sin_addr.s_addr = INADDR_ANY;
1093
1094         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1095         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1096         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1097
1098         rt.rt_dev = ifr.ifr_name;
1099
1100         err = ioctl(sk, SIOCDELRT, &rt);
1101         if (err < 0)
1102                 connman_error("Removing default interface route failed (%s)",
1103                                                         strerror(errno));
1104         close(sk);
1105
1106         return err;
1107 }
1108
1109 connman_bool_t connman_inet_compare_subnet(int index, const char *host)
1110 {
1111         struct ifreq ifr;
1112         struct in_addr _host_addr;
1113         in_addr_t host_addr, netmask_addr, if_addr;
1114         struct sockaddr_in *netmask, *addr;
1115         int sk;
1116
1117         DBG("host %s", host);
1118
1119         if (host == NULL)
1120                 return FALSE;
1121
1122         if (inet_aton(host, &_host_addr) == 0)
1123                 return -1;
1124         host_addr = _host_addr.s_addr;
1125
1126         sk = socket(PF_INET, SOCK_DGRAM, 0);
1127         if (sk < 0)
1128                 return FALSE;
1129
1130         memset(&ifr, 0, sizeof(ifr));
1131         ifr.ifr_ifindex = index;
1132
1133         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1134                 close(sk);
1135                 return FALSE;
1136         }
1137
1138         if (ioctl(sk, SIOCGIFNETMASK, &ifr) < 0) {
1139                 close(sk);
1140                 return FALSE;
1141         }
1142
1143         netmask = (struct sockaddr_in *)&ifr.ifr_netmask;
1144         netmask_addr = netmask->sin_addr.s_addr;
1145
1146         if (ioctl(sk, SIOCGIFADDR, &ifr) < 0) {
1147                 close(sk);
1148                 return FALSE;
1149         }
1150         addr = (struct sockaddr_in *)&ifr.ifr_addr;
1151         if_addr = addr->sin_addr.s_addr;
1152
1153         return ((if_addr & netmask_addr) == (host_addr & netmask_addr));
1154 }
1155
1156 int connman_inet_remove_from_bridge(int index, const char *bridge)
1157 {
1158         struct ifreq ifr;
1159         int sk, err;
1160
1161         if (bridge == NULL)
1162                 return -EINVAL;
1163
1164         sk = socket(AF_INET, SOCK_STREAM, 0);
1165         if (sk < 0)
1166                 return sk;
1167
1168         memset(&ifr, 0, sizeof(ifr));
1169         strncpy(ifr.ifr_name, bridge, IFNAMSIZ - 1);
1170         ifr.ifr_ifindex = index;
1171
1172         err = ioctl(sk, SIOCBRDELIF, &ifr);
1173
1174         close(sk);
1175
1176         if (err < 0) {
1177                 connman_error("Remove interface from bridge error %s",
1178                                                         strerror(errno));
1179                 return err;
1180         }
1181
1182         return 0;
1183 }
1184
1185 int connman_inet_add_to_bridge(int index, const char *bridge)
1186 {
1187         struct ifreq ifr;
1188         int sk, err;
1189
1190         if (bridge == NULL)
1191                 return -EINVAL;
1192
1193         sk = socket(AF_INET, SOCK_STREAM, 0);
1194         if (sk < 0)
1195                 return sk;
1196
1197         memset(&ifr, 0, sizeof(ifr));
1198         strncpy(ifr.ifr_name, bridge, IFNAMSIZ - 1);
1199         ifr.ifr_ifindex = index;
1200
1201         err = ioctl(sk, SIOCBRADDIF, &ifr);
1202
1203         close(sk);
1204
1205         if (err < 0) {
1206                 connman_error("Add interface to bridge error %s",
1207                                                         strerror(errno));
1208                 return err;
1209         }
1210
1211         return 0;
1212 }
1213
1214 int connman_inet_set_mtu(int index, int mtu)
1215 {
1216         struct ifreq ifr;
1217         int sk, err;
1218
1219         sk = socket(AF_INET, SOCK_DGRAM, 0);
1220         if (sk < 0)
1221                 return sk;
1222
1223         memset(&ifr, 0, sizeof(ifr));
1224         ifr.ifr_ifindex = index;
1225
1226         err = ioctl(sk, SIOCGIFNAME, &ifr);
1227         if (err == 0) {
1228                 ifr.ifr_mtu = mtu;
1229                 err = ioctl(sk, SIOCSIFMTU, &ifr);
1230         }
1231
1232         close(sk);
1233         return err;
1234 }
1235
1236 int connman_inet_setup_tunnel(char *tunnel, int mtu)
1237 {
1238         struct ifreq ifr;
1239         int sk, err, index;
1240         __u32 mask;
1241         __u32 flags;
1242
1243         if (tunnel == NULL)
1244                 return -EINVAL;
1245
1246         sk = socket(AF_INET, SOCK_DGRAM, 0);
1247         if (sk < 0)
1248                 return sk;
1249
1250         index = if_nametoindex(tunnel);
1251
1252         err = connman_inet_set_mtu(index, mtu);
1253         if (err < 0)
1254                 return err;
1255         else if (err)
1256                 goto done;
1257
1258         memset(&ifr, 0, sizeof(ifr));
1259         strncpy(ifr.ifr_name, tunnel, IFNAMSIZ);
1260         err = ioctl(sk, SIOCGIFFLAGS, &ifr);
1261         if (err)
1262                 goto done;
1263
1264         mask = IFF_UP;
1265         flags = IFF_UP;
1266
1267         if ((ifr.ifr_flags ^ flags) & mask) {
1268                 ifr.ifr_flags &= ~mask;
1269                 ifr.ifr_flags |= mask & flags;
1270                 err = ioctl(sk, SIOCSIFFLAGS, &ifr);
1271                 if (err)
1272                         connman_error("SIOCSIFFLAGS failed: %s",
1273                                                         strerror(errno));
1274         }
1275
1276 done:
1277         close(sk);
1278         return err;
1279 }
1280
1281 int connman_inet_create_tunnel(char **iface)
1282 {
1283         struct ifreq ifr;
1284         int i, fd;
1285
1286         fd = open("/dev/net/tun", O_RDWR);
1287         if (fd < 0) {
1288                 i = -errno;
1289                 connman_error("Failed to open /dev/net/tun: %s",
1290                                 strerror(errno));
1291                 return i;
1292         }
1293
1294         memset(&ifr, 0, sizeof(ifr));
1295         ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
1296
1297         for (i = 0; i < 256; i++) {
1298                 sprintf(ifr.ifr_name, "tun%d", i);
1299
1300                 if (!ioctl(fd, TUNSETIFF, (void *)&ifr))
1301                         break;
1302         }
1303
1304         if (i == 256) {
1305                 connman_error("Failed to find available tun device");
1306                 close(fd);
1307                 return -ENODEV;
1308         }
1309
1310         *iface = g_strdup(ifr.ifr_name);
1311
1312         return fd;
1313 }
1314
1315 struct rs_cb_data {
1316         GIOChannel *channel;
1317         __connman_inet_rs_cb_t callback;
1318         struct sockaddr_in6 addr;
1319         guint rs_timeout;
1320         void *user_data;
1321 };
1322
1323 #define CMSG_BUF_LEN 512
1324 #define IN6ADDR_ALL_NODES_MC_INIT \
1325         { { { 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0x1 } } } /* ff02::1 */
1326 #define IN6ADDR_ALL_ROUTERS_MC_INIT \
1327         { { { 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0x2 } } } /* ff02::2 */
1328
1329 static const struct in6_addr in6addr_all_nodes_mc = IN6ADDR_ALL_NODES_MC_INIT;
1330 static const struct in6_addr in6addr_all_routers_mc =
1331                                                 IN6ADDR_ALL_ROUTERS_MC_INIT;
1332
1333 /* from netinet/in.h */
1334 struct in6_pktinfo {
1335         struct in6_addr ipi6_addr;  /* src/dst IPv6 address */
1336         unsigned int ipi6_ifindex;  /* send/recv interface index */
1337 };
1338
1339 static void rs_cleanup(struct rs_cb_data *data)
1340 {
1341         g_io_channel_shutdown(data->channel, TRUE, NULL);
1342         g_io_channel_unref(data->channel);
1343         data->channel = 0;
1344
1345         if (data->rs_timeout > 0)
1346                 g_source_remove(data->rs_timeout);
1347
1348         g_free(data);
1349 }
1350
1351 static gboolean rs_timeout_cb(gpointer user_data)
1352 {
1353         struct rs_cb_data *data = user_data;
1354
1355         DBG("user data %p", user_data);
1356
1357         if (data == NULL)
1358                 return FALSE;
1359
1360         if (data->callback != NULL)
1361                 data->callback(NULL, data->user_data);
1362
1363         data->rs_timeout = 0;
1364         rs_cleanup(data);
1365         return FALSE;
1366 }
1367
1368 static int icmpv6_recv(int fd, gpointer user_data)
1369 {
1370         struct msghdr mhdr;
1371         struct iovec iov;
1372         unsigned char chdr[CMSG_BUF_LEN];
1373         unsigned char buf[1540];
1374         struct rs_cb_data *data = user_data;
1375         struct nd_router_advert *hdr;
1376         struct sockaddr_in6 saddr;
1377         ssize_t len;
1378
1379         DBG("");
1380
1381         iov.iov_len = sizeof(buf);
1382         iov.iov_base = buf;
1383
1384         mhdr.msg_name = (void *)&saddr;
1385         mhdr.msg_namelen = sizeof(struct sockaddr_in6);
1386         mhdr.msg_iov = &iov;
1387         mhdr.msg_iovlen = 1;
1388         mhdr.msg_control = (void *)chdr;
1389         mhdr.msg_controllen = CMSG_BUF_LEN;
1390
1391         len = recvmsg(fd, &mhdr, 0);
1392         if (len < 0) {
1393                 data->callback(NULL, data->user_data);
1394                 return -errno;
1395         }
1396
1397         hdr = (struct nd_router_advert *)buf;
1398         if (hdr->nd_ra_code != 0)
1399                 return 0;
1400
1401         data->callback(hdr, data->user_data);
1402         rs_cleanup(data);
1403
1404         return len;
1405 }
1406
1407 static gboolean icmpv6_event(GIOChannel *chan, GIOCondition cond,
1408                                                                 gpointer data)
1409 {
1410         int fd, ret;
1411
1412         DBG("");
1413
1414         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
1415                 return FALSE;
1416
1417         fd = g_io_channel_unix_get_fd(chan);
1418         ret = icmpv6_recv(fd, data);
1419         if (ret == 0)
1420                 return TRUE;
1421
1422         return FALSE;
1423 }
1424
1425 /* Adapted from RFC 1071 "C" Implementation Example */
1426 static uint16_t csum(const void *phdr, const void *data, socklen_t datalen)
1427 {
1428         register unsigned long sum = 0;
1429         socklen_t count;
1430         uint16_t *addr;
1431         int i;
1432
1433         /* caller must make sure datalen is even */
1434
1435         addr = (uint16_t *)phdr;
1436         for (i = 0; i < 20; i++)
1437                 sum += *addr++;
1438
1439         count = datalen;
1440         addr = (uint16_t *)data;
1441
1442         while (count > 1) {
1443                 sum += *(addr++);
1444                 count -= 2;
1445         }
1446
1447         while (sum >> 16)
1448                 sum = (sum & 0xffff) + (sum >> 16);
1449
1450         return (uint16_t)~sum;
1451 }
1452
1453 static int ndisc_send_unspec(int type, int oif, const struct in6_addr *dest)
1454 {
1455         struct _phdr {
1456                 struct in6_addr src;
1457                 struct in6_addr dst;
1458                 uint32_t plen;
1459                 uint8_t reserved[3];
1460                 uint8_t nxt;
1461         } phdr;
1462
1463         struct {
1464                 struct ip6_hdr ip;
1465                 union {
1466                         struct icmp6_hdr icmp;
1467                         struct nd_neighbor_solicit ns;
1468                         struct nd_router_solicit rs;
1469                 } i;
1470         } frame;
1471
1472         struct msghdr msgh;
1473         struct cmsghdr *cmsg;
1474         struct in6_pktinfo *pinfo;
1475         struct sockaddr_in6 dst;
1476         char cbuf[CMSG_SPACE(sizeof(*pinfo))];
1477         struct iovec iov;
1478         int fd, datalen, ret;
1479
1480         DBG("");
1481
1482         fd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
1483         if (fd < 0)
1484                 return -errno;
1485
1486         memset(&frame, 0, sizeof(frame));
1487         memset(&dst, 0, sizeof(dst));
1488
1489         datalen = sizeof(frame.i.rs); /* 8, csum() safe */
1490         dst.sin6_addr = *dest;
1491
1492         /* Fill in the IPv6 header */
1493         frame.ip.ip6_vfc = 0x60;
1494         frame.ip.ip6_plen = htons(datalen);
1495         frame.ip.ip6_nxt = IPPROTO_ICMPV6;
1496         frame.ip.ip6_hlim = 255;
1497         frame.ip.ip6_dst = dst.sin6_addr;
1498         /* all other fields are already set to zero */
1499
1500         /* Prepare pseudo header for csum */
1501         memset(&phdr, 0, sizeof(phdr));
1502         phdr.dst = dst.sin6_addr;
1503         phdr.plen = htonl(datalen);
1504         phdr.nxt = IPPROTO_ICMPV6;
1505
1506         /* Fill in remaining ICMP header fields */
1507         frame.i.icmp.icmp6_type = type;
1508         frame.i.icmp.icmp6_cksum = csum(&phdr, &frame.i, datalen);
1509
1510         iov.iov_base = &frame;
1511         iov.iov_len = sizeof(frame.ip) + datalen;
1512
1513         dst.sin6_family = AF_INET6;
1514         msgh.msg_name = &dst;
1515         msgh.msg_namelen = sizeof(dst);
1516         msgh.msg_iov = &iov;
1517         msgh.msg_iovlen = 1;
1518         msgh.msg_flags = 0;
1519
1520         memset(cbuf, 0, CMSG_SPACE(sizeof(*pinfo)));
1521         cmsg = (struct cmsghdr *)cbuf;
1522         pinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
1523         pinfo->ipi6_ifindex = oif;
1524
1525         cmsg->cmsg_len = CMSG_LEN(sizeof(*pinfo));
1526         cmsg->cmsg_level = IPPROTO_IPV6;
1527         cmsg->cmsg_type = IPV6_PKTINFO;
1528         msgh.msg_control = cmsg;
1529         msgh.msg_controllen = cmsg->cmsg_len;
1530
1531         ret = sendmsg(fd, &msgh, 0);
1532
1533         close(fd);
1534         return ret;
1535 }
1536
1537 static inline void ipv6_addr_set(struct in6_addr *addr,
1538                                 uint32_t w1, uint32_t w2,
1539                                 uint32_t w3, uint32_t w4)
1540 {
1541         addr->s6_addr32[0] = w1;
1542         addr->s6_addr32[1] = w2;
1543         addr->s6_addr32[2] = w3;
1544         addr->s6_addr32[3] = w4;
1545 }
1546
1547 static inline void ipv6_addr_solict_mult(const struct in6_addr *addr,
1548                                         struct in6_addr *solicited)
1549 {
1550         ipv6_addr_set(solicited, htonl(0xFF020000), 0, htonl(0x1),
1551                         htonl(0xFF000000) | addr->s6_addr32[3]);
1552 }
1553
1554 static int if_mc_group(int sock, int ifindex, const struct in6_addr *mc_addr,
1555                                                                 int cmd)
1556 {
1557         unsigned int val = 0;
1558         struct ipv6_mreq mreq;
1559         int ret;
1560
1561         memset(&mreq, 0, sizeof(mreq));
1562         mreq.ipv6mr_interface = ifindex;
1563         mreq.ipv6mr_multiaddr = *mc_addr;
1564
1565         ret = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
1566                         &val, sizeof(int));
1567
1568         if (ret < 0)
1569                 return ret;
1570
1571         return setsockopt(sock, IPPROTO_IPV6, cmd, &mreq, sizeof(mreq));
1572 }
1573
1574 int __connman_inet_ipv6_send_rs(int index, int timeout,
1575                         __connman_inet_rs_cb_t callback, void *user_data)
1576 {
1577         struct rs_cb_data *data;
1578         struct icmp6_filter filter;
1579         struct in6_addr solicit;
1580         struct in6_addr dst = in6addr_all_routers_mc;
1581         int sk;
1582
1583         DBG("");
1584
1585         if (timeout <= 0)
1586                 return -EINVAL;
1587
1588         data = g_try_malloc0(sizeof(struct rs_cb_data));
1589         if (data == NULL)
1590                 return -ENOMEM;
1591
1592         data->callback = callback;
1593         data->user_data = user_data;
1594         data->rs_timeout = g_timeout_add_seconds(timeout, rs_timeout_cb, data);
1595
1596         sk = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
1597         if (sk < 0)
1598                 return -errno;
1599
1600         ICMP6_FILTER_SETBLOCKALL(&filter);
1601         ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
1602
1603         setsockopt(sk, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
1604                                                 sizeof(struct icmp6_filter));
1605
1606         ipv6_addr_solict_mult(&dst, &solicit);
1607         if_mc_group(sk, index, &in6addr_all_nodes_mc, IPV6_JOIN_GROUP);
1608         if_mc_group(sk, index, &solicit, IPV6_JOIN_GROUP);
1609
1610         data->channel = g_io_channel_unix_new(sk);
1611         g_io_channel_set_close_on_unref(data->channel, TRUE);
1612
1613         g_io_channel_set_encoding(data->channel, NULL, NULL);
1614         g_io_channel_set_buffered(data->channel, FALSE);
1615
1616         g_io_add_watch(data->channel,
1617                         G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
1618                         icmpv6_event, data);
1619
1620         ndisc_send_unspec(ND_ROUTER_SOLICIT, index, &dst);
1621
1622         return 0;
1623 }