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