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