[connman] Added Tizen Wi-Fi Mesh
[platform/upstream/connman.git] / src / inet.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2013  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 #define _GNU_SOURCE
29 #include <stdio.h>
30 #include <errno.h>
31 #include <unistd.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/stat.h>
35 #include <sys/ioctl.h>
36 #include <sys/socket.h>
37 #include <linux/sockios.h>
38 #include <netdb.h>
39 #include <arpa/inet.h>
40 #include <net/route.h>
41 #include <net/ethernet.h>
42 #include <net/if.h>
43 #include <net/if_arp.h>
44 #include <netinet/icmp6.h>
45 #include <fcntl.h>
46 #include <linux/if_tun.h>
47 #include <ctype.h>
48 #include <ifaddrs.h>
49 #include <linux/fib_rules.h>
50
51 #include "connman.h"
52 #include <gdhcp/gdhcp.h>
53
54 #define NLMSG_TAIL(nmsg)                                \
55         ((struct rtattr *) (((uint8_t*) (nmsg)) +       \
56         NLMSG_ALIGN((nmsg)->nlmsg_len)))
57
58 int __connman_inet_rtnl_addattr_l(struct nlmsghdr *n, size_t max_length,
59                                 int type, const void *data, size_t data_length)
60 {
61         size_t length;
62         struct rtattr *rta;
63
64         length = RTA_LENGTH(data_length);
65
66         if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(length) > max_length)
67                 return -E2BIG;
68
69         rta = NLMSG_TAIL(n);
70         rta->rta_type = type;
71         rta->rta_len = length;
72         memcpy(RTA_DATA(rta), data, data_length);
73         n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(length);
74
75         return 0;
76 }
77
78 int __connman_inet_modify_address(int cmd, int flags,
79                                 int index, int family,
80                                 const char *address,
81                                 const char *peer,
82                                 unsigned char prefixlen,
83                                 const char *broadcast)
84 {
85         uint8_t request[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
86                         NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
87                         RTA_LENGTH(sizeof(struct in6_addr)) +
88                         RTA_LENGTH(sizeof(struct in6_addr))];
89
90         struct nlmsghdr *header;
91         struct sockaddr_nl nl_addr;
92         struct ifaddrmsg *ifaddrmsg;
93         struct in6_addr ipv6_addr;
94         struct in_addr ipv4_addr, ipv4_dest, ipv4_bcast;
95         int sk, err;
96
97         DBG("cmd %#x flags %#x index %d family %d address %s peer %s "
98                 "prefixlen %hhu broadcast %s", cmd, flags, index, family,
99                 address, peer, prefixlen, broadcast);
100
101         if (!address)
102                 return -EINVAL;
103
104         if (family != AF_INET && family != AF_INET6)
105                 return -EINVAL;
106
107         memset(&request, 0, sizeof(request));
108
109         header = (struct nlmsghdr *)request;
110         header->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
111         header->nlmsg_type = cmd;
112         header->nlmsg_flags = NLM_F_REQUEST | flags;
113         header->nlmsg_seq = 1;
114
115         ifaddrmsg = NLMSG_DATA(header);
116         ifaddrmsg->ifa_family = family;
117         ifaddrmsg->ifa_prefixlen = prefixlen;
118         ifaddrmsg->ifa_flags = IFA_F_PERMANENT;
119         ifaddrmsg->ifa_scope = RT_SCOPE_UNIVERSE;
120         ifaddrmsg->ifa_index = index;
121
122         if (family == AF_INET) {
123                 if (inet_pton(AF_INET, address, &ipv4_addr) < 1)
124                         return -1;
125
126                 if (broadcast)
127                         inet_pton(AF_INET, broadcast, &ipv4_bcast);
128                 else
129                         ipv4_bcast.s_addr = ipv4_addr.s_addr |
130                                 htonl(0xfffffffflu >> prefixlen);
131
132                 if (peer) {
133                         if (inet_pton(AF_INET, peer, &ipv4_dest) < 1)
134                                 return -1;
135
136                         err = __connman_inet_rtnl_addattr_l(header,
137                                                         sizeof(request),
138                                                         IFA_ADDRESS,
139                                                         &ipv4_dest,
140                                                         sizeof(ipv4_dest));
141                         if (err < 0)
142                                 return err;
143                 }
144
145                 err = __connman_inet_rtnl_addattr_l(header,
146                                                 sizeof(request),
147                                                 IFA_LOCAL,
148                                                 &ipv4_addr,
149                                                 sizeof(ipv4_addr));
150                 if (err < 0)
151                         return err;
152
153                 err = __connman_inet_rtnl_addattr_l(header,
154                                                 sizeof(request),
155                                                 IFA_BROADCAST,
156                                                 &ipv4_bcast,
157                                                 sizeof(ipv4_bcast));
158                 if (err < 0)
159                         return err;
160
161         } else if (family == AF_INET6) {
162                 if (inet_pton(AF_INET6, address, &ipv6_addr) < 1)
163                         return -1;
164
165                 err = __connman_inet_rtnl_addattr_l(header,
166                                                 sizeof(request),
167                                                 IFA_LOCAL,
168                                                 &ipv6_addr,
169                                                 sizeof(ipv6_addr));
170                 if (err < 0)
171                         return err;
172         }
173
174         sk = socket(AF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_ROUTE);
175         if (sk < 0)
176                 return -errno;
177
178         memset(&nl_addr, 0, sizeof(nl_addr));
179         nl_addr.nl_family = AF_NETLINK;
180
181         if ((err = sendto(sk, request, header->nlmsg_len, 0,
182                         (struct sockaddr *) &nl_addr, sizeof(nl_addr))) < 0)
183                 goto done;
184
185         err = 0;
186
187 done:
188         close(sk);
189
190         return err;
191 }
192
193 #if defined TIZEN_EXT_WIFI_MESH
194 char *connman_inet_ifaddr(const char *name)
195 {
196         struct ifreq ifr;
197         struct ether_addr eth;
198         char *str;
199         int sk, err;
200
201         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
202         if (sk < 0)
203                 return NULL;
204
205         strncpy(ifr.ifr_name, name, IFNAMSIZ-1);
206
207         err = ioctl(sk, SIOCGIFHWADDR, &ifr);
208         close(sk);
209
210         if (err < 0)
211                 return NULL;
212
213         str = g_malloc(18);
214         if (!str)
215                 return NULL;
216
217         memcpy(&eth, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
218         snprintf(str, 13, "%02x%02x%02x%02x%02x%02x",
219                                                 eth.ether_addr_octet[0],
220                                                 eth.ether_addr_octet[1],
221                                                 eth.ether_addr_octet[2],
222                                                 eth.ether_addr_octet[3],
223                                                 eth.ether_addr_octet[4],
224                                                 eth.ether_addr_octet[5]);
225
226         return str;
227 }
228
229 char *connman_inet_ifname2addr(const char *name)
230 {
231         struct ifreq ifr;
232         struct ether_addr eth;
233         char *str;
234         int sk, err;
235
236         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
237         if (sk < 0)
238                 return NULL;
239
240         strncpy(ifr.ifr_name, name, IFNAMSIZ-1);
241
242         err = ioctl(sk, SIOCGIFHWADDR, &ifr);
243         close(sk);
244
245         if (err < 0)
246                 return NULL;
247
248         str = g_malloc(18);
249         if (!str)
250                 return NULL;
251
252         memcpy(&eth, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
253         snprintf(str, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
254                                                 eth.ether_addr_octet[0],
255                                                 eth.ether_addr_octet[1],
256                                                 eth.ether_addr_octet[2],
257                                                 eth.ether_addr_octet[3],
258                                                 eth.ether_addr_octet[4],
259                                                 eth.ether_addr_octet[5]);
260
261         return str;
262 }
263 #endif
264
265 int connman_inet_ifindex(const char *name)
266 {
267         struct ifreq ifr;
268         int sk, err;
269
270         if (!name)
271                 return -1;
272
273         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
274         if (sk < 0)
275                 return -1;
276
277         memset(&ifr, 0, sizeof(ifr));
278         strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1);
279
280         err = ioctl(sk, SIOCGIFINDEX, &ifr);
281
282         close(sk);
283
284         if (err < 0)
285                 return -1;
286
287         return ifr.ifr_ifindex;
288 }
289
290 char *connman_inet_ifname(int index)
291 {
292         struct ifreq ifr;
293         int sk, err;
294
295         if (index < 0)
296                 return NULL;
297
298         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
299         if (sk < 0)
300                 return NULL;
301
302         memset(&ifr, 0, sizeof(ifr));
303         ifr.ifr_ifindex = index;
304
305         err = ioctl(sk, SIOCGIFNAME, &ifr);
306
307         close(sk);
308
309         if (err < 0)
310                 return NULL;
311
312         return g_strdup(ifr.ifr_name);
313 }
314
315 int connman_inet_ifup(int index)
316 {
317         struct ifreq ifr;
318         int sk, err;
319
320         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
321         if (sk < 0)
322                 return -errno;
323
324         memset(&ifr, 0, sizeof(ifr));
325         ifr.ifr_ifindex = index;
326
327         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
328                 err = -errno;
329                 goto done;
330         }
331
332         if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
333                 err = -errno;
334                 goto done;
335         }
336
337         if (ifr.ifr_flags & IFF_UP) {
338                 err = -EALREADY;
339                 goto done;
340         }
341
342         ifr.ifr_flags |= (IFF_UP|IFF_DYNAMIC);
343
344         if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0) {
345                 err = -errno;
346                 goto done;
347         }
348
349         err = 0;
350
351 done:
352         close(sk);
353
354         return err;
355 }
356
357 int connman_inet_ifdown(int index)
358 {
359         struct ifreq ifr, addr_ifr;
360         struct sockaddr_in *addr;
361         int sk, err;
362
363         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
364         if (sk < 0)
365                 return -errno;
366
367         memset(&ifr, 0, sizeof(ifr));
368         ifr.ifr_ifindex = index;
369
370         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
371                 err = -errno;
372                 goto done;
373         }
374
375         if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
376                 err = -errno;
377                 goto done;
378         }
379
380         memset(&addr_ifr, 0, sizeof(addr_ifr));
381         memcpy(&addr_ifr.ifr_name, &ifr.ifr_name, sizeof(ifr.ifr_name) - 1);
382         addr = (struct sockaddr_in *)&addr_ifr.ifr_addr;
383         addr->sin_family = AF_INET;
384         if (ioctl(sk, SIOCSIFADDR, &addr_ifr) < 0)
385                 connman_warn("Could not clear IPv4 address index %d", index);
386
387         if (!(ifr.ifr_flags & IFF_UP)) {
388                 err = -EALREADY;
389                 goto done;
390         }
391
392         ifr.ifr_flags = (ifr.ifr_flags & ~IFF_UP) | IFF_DYNAMIC;
393
394         if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0)
395                 err = -errno;
396         else
397                 err = 0;
398
399 done:
400         close(sk);
401
402         return err;
403 }
404
405 #if defined TIZEN_EXT
406 void connman_inet_update_device_ident(struct connman_device *device)
407 {
408         int index;
409         enum connman_device_type type;
410         char *ident = NULL, *addr = NULL;
411
412         index = connman_device_get_index(device);
413         type = connman_device_get_type(device);
414
415         switch (type) {
416         case CONNMAN_DEVICE_TYPE_UNKNOWN:
417                 return;
418         case CONNMAN_DEVICE_TYPE_ETHERNET:
419         case CONNMAN_DEVICE_TYPE_GADGET:
420         case CONNMAN_DEVICE_TYPE_WIFI:
421                 addr = index2addr(index);
422                 ident = index2ident(index, NULL);
423                 break;
424         case CONNMAN_DEVICE_TYPE_CELLULAR:
425                 ident = index2ident(index, NULL);
426                 break;
427         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
428         case CONNMAN_DEVICE_TYPE_GPS:
429         case CONNMAN_DEVICE_TYPE_VENDOR:
430                 break;
431         }
432
433         if (ident != NULL) {
434                 connman_device_set_ident(device, ident);
435                 g_free(ident);
436         }
437
438         if (addr != NULL) {
439                 connman_device_set_string(device, "Address", addr);
440                 g_free(addr);
441         }
442 }
443 #endif
444
445 struct in6_ifreq {
446         struct in6_addr ifr6_addr;
447         __u32 ifr6_prefixlen;
448         unsigned int ifr6_ifindex;
449 };
450
451 int connman_inet_set_ipv6_address(int index,
452                 struct connman_ipaddress *ipaddress)
453 {
454         int err;
455         unsigned char prefix_len;
456         const char *address;
457
458         if (!ipaddress->local)
459                 return 0;
460
461         prefix_len = ipaddress->prefixlen;
462         address = ipaddress->local;
463
464         DBG("index %d address %s prefix_len %d", index, address, prefix_len);
465
466         err = __connman_inet_modify_address(RTM_NEWADDR,
467                                 NLM_F_REPLACE | NLM_F_ACK, index, AF_INET6,
468                                 address, NULL, prefix_len, NULL);
469         if (err < 0) {
470                 connman_error("%s: %s", __func__, strerror(-err));
471                 return err;
472         }
473
474         return 0;
475 }
476
477 int connman_inet_set_address(int index, struct connman_ipaddress *ipaddress)
478 {
479         int err;
480         unsigned char prefix_len;
481         const char *address, *broadcast, *peer;
482
483         if (!ipaddress->local)
484                 return -1;
485
486         prefix_len = ipaddress->prefixlen;
487         address = ipaddress->local;
488         broadcast = ipaddress->broadcast;
489         peer = ipaddress->peer;
490
491         DBG("index %d address %s prefix_len %d", index, address, prefix_len);
492
493         err = __connman_inet_modify_address(RTM_NEWADDR,
494                                 NLM_F_REPLACE | NLM_F_ACK, index, AF_INET,
495                                 address, peer, prefix_len, broadcast);
496         if (err < 0) {
497                 connman_error("%s: %s", __func__, strerror(-err));
498                 return err;
499         }
500
501         return 0;
502 }
503
504 int connman_inet_clear_ipv6_address(int index, const char *address,
505                                                         int prefix_len)
506 {
507         int err;
508
509         DBG("index %d address %s prefix_len %d", index, address, prefix_len);
510
511         if (!address)
512                 return -EINVAL;
513
514         err = __connman_inet_modify_address(RTM_DELADDR, 0, index, AF_INET6,
515                                 address, NULL, prefix_len, NULL);
516         if (err < 0) {
517                 connman_error("%s: %s", __func__, strerror(-err));
518                 return err;
519         }
520
521         return 0;
522 }
523
524 int connman_inet_clear_address(int index, struct connman_ipaddress *ipaddress)
525 {
526         int err;
527         unsigned char prefix_len;
528         const char *address, *broadcast, *peer;
529
530         prefix_len = ipaddress->prefixlen;
531         address = ipaddress->local;
532         broadcast = ipaddress->broadcast;
533         peer = ipaddress->peer;
534
535         DBG("index %d address %s prefix_len %d peer %s broadcast %s", index,
536                 address, prefix_len, peer, broadcast);
537
538         if (!address)
539                 return -EINVAL;
540
541         err = __connman_inet_modify_address(RTM_DELADDR, 0, index, AF_INET,
542                                 address, peer, prefix_len, broadcast);
543         if (err < 0) {
544                 connman_error("%s: %s", __func__, strerror(-err));
545                 return err;
546         }
547
548         return 0;
549 }
550
551 int connman_inet_add_host_route(int index, const char *host,
552                                 const char *gateway)
553 {
554         return connman_inet_add_network_route(index, host, gateway, NULL);
555 }
556
557 int connman_inet_del_host_route(int index, const char *host)
558 {
559         return connman_inet_del_network_route(index, host);
560 }
561
562 int connman_inet_add_network_route(int index, const char *host,
563                                         const char *gateway,
564                                         const char *netmask)
565 {
566         struct ifreq ifr;
567         struct rtentry rt;
568         struct sockaddr_in addr;
569         int sk, err = 0;
570
571         DBG("index %d host %s gateway %s netmask %s", index,
572                 host, gateway, netmask);
573
574         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
575         if (sk < 0) {
576                 err = -errno;
577                 goto out;
578         }
579
580         memset(&ifr, 0, sizeof(ifr));
581         ifr.ifr_ifindex = index;
582
583         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
584                 err = -errno;
585                 close(sk);
586                 goto out;
587         }
588
589         DBG("ifname %s", ifr.ifr_name);
590
591         memset(&rt, 0, sizeof(rt));
592         rt.rt_flags = RTF_UP;
593         if (gateway)
594                 rt.rt_flags |= RTF_GATEWAY;
595         if (!netmask)
596                 rt.rt_flags |= RTF_HOST;
597
598         memset(&addr, 0, sizeof(addr));
599         addr.sin_family = AF_INET;
600         addr.sin_addr.s_addr = inet_addr(host);
601         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
602
603         memset(&addr, 0, sizeof(addr));
604         addr.sin_family = AF_INET;
605         if (gateway)
606                 addr.sin_addr.s_addr = inet_addr(gateway);
607         else
608                 addr.sin_addr.s_addr = INADDR_ANY;
609         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
610
611         memset(&addr, 0, sizeof(addr));
612         addr.sin_family = AF_INET;
613         addr.sin_addr.s_addr = INADDR_ANY;
614         if (netmask)
615                 addr.sin_addr.s_addr = inet_addr(netmask);
616         else
617                 addr.sin_addr.s_addr = INADDR_ANY;
618         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
619
620         rt.rt_dev = ifr.ifr_name;
621
622         if (ioctl(sk, SIOCADDRT, &rt) < 0 && errno != EEXIST)
623                 err = -errno;
624
625         close(sk);
626
627 out:
628         if (err < 0)
629                 connman_error("Adding host route failed (%s)",
630                                                         strerror(-err));
631
632         return err;
633 }
634
635 int connman_inet_del_network_route(int index, const char *host)
636 {
637         struct ifreq ifr;
638         struct rtentry rt;
639         struct sockaddr_in addr;
640         int sk, err = 0;
641
642         DBG("index %d host %s", index, host);
643
644         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
645         if (sk < 0) {
646                 err = -errno;
647                 goto out;
648         }
649
650         memset(&ifr, 0, sizeof(ifr));
651         ifr.ifr_ifindex = index;
652
653         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
654                 err = -errno;
655                 close(sk);
656                 goto out;
657         }
658
659         DBG("ifname %s", ifr.ifr_name);
660
661         memset(&rt, 0, sizeof(rt));
662         rt.rt_flags = RTF_UP | 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         rt.rt_dev = ifr.ifr_name;
670
671         if (ioctl(sk, SIOCDELRT, &rt) < 0 && errno != ESRCH)
672                 err = -errno;
673
674         close(sk);
675
676 out:
677         if (err < 0)
678                 connman_error("Deleting host route failed (%s)",
679                                                         strerror(-err));
680
681         return err;
682 }
683
684 int connman_inet_del_ipv6_network_route(int index, const char *host,
685                                                 unsigned char prefix_len)
686 {
687         struct in6_rtmsg rt;
688         int sk, err = 0;
689
690         DBG("index %d host %s", index, host);
691
692         if (!host)
693                 return -EINVAL;
694
695         memset(&rt, 0, sizeof(rt));
696
697         rt.rtmsg_dst_len = prefix_len;
698
699         if (inet_pton(AF_INET6, host, &rt.rtmsg_dst) < 0) {
700                 err = -errno;
701                 goto out;
702         }
703
704         rt.rtmsg_flags = RTF_UP | RTF_HOST;
705
706         rt.rtmsg_metric = 1;
707         rt.rtmsg_ifindex = index;
708
709         sk = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
710         if (sk < 0) {
711                 err = -errno;
712                 goto out;
713         }
714
715         if (ioctl(sk, SIOCDELRT, &rt) < 0 && errno != ESRCH)
716                 err = -errno;
717
718         close(sk);
719
720 out:
721         if (err < 0)
722                 connman_error("Del IPv6 host route error (%s)",
723                                                 strerror(-err));
724
725         return err;
726 }
727
728 int connman_inet_del_ipv6_host_route(int index, const char *host)
729 {
730         return connman_inet_del_ipv6_network_route(index, host, 128);
731 }
732
733 int connman_inet_add_ipv6_network_route(int index, const char *host,
734                                         const char *gateway,
735                                         unsigned char prefix_len)
736 {
737         struct in6_rtmsg rt;
738         int sk, err = 0;
739
740         DBG("index %d host %s gateway %s", index, host, gateway);
741
742         if (!host)
743                 return -EINVAL;
744
745         memset(&rt, 0, sizeof(rt));
746
747         rt.rtmsg_dst_len = prefix_len;
748
749         if (inet_pton(AF_INET6, host, &rt.rtmsg_dst) < 0) {
750                 err = -errno;
751                 goto out;
752         }
753
754         rt.rtmsg_flags = RTF_UP | RTF_HOST;
755
756         if (gateway) {
757                 rt.rtmsg_flags |= RTF_GATEWAY;
758                 inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway);
759         }
760
761         rt.rtmsg_metric = 1;
762         rt.rtmsg_ifindex = index;
763
764         sk = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
765         if (sk < 0) {
766                 err = -errno;
767                 goto out;
768         }
769
770         if (ioctl(sk, SIOCADDRT, &rt) < 0 && errno != EEXIST)
771                 err = -errno;
772
773         close(sk);
774
775 out:
776         if (err < 0)
777                 connman_error("Set IPv6 host route error (%s)",
778                                                 strerror(-err));
779
780         return err;
781 }
782
783 int connman_inet_add_ipv6_host_route(int index, const char *host,
784                                         const char *gateway)
785 {
786         return connman_inet_add_ipv6_network_route(index, host, gateway, 128);
787 }
788
789 int connman_inet_clear_ipv6_gateway_address(int index, const char *gateway)
790 {
791         struct in6_rtmsg rt;
792         int sk, err = 0;
793
794         DBG("index %d gateway %s", index, gateway);
795
796         if (!gateway)
797                 return -EINVAL;
798
799         memset(&rt, 0, sizeof(rt));
800
801         if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) {
802                 err = -errno;
803                 goto out;
804         }
805
806         rt.rtmsg_flags = RTF_UP | RTF_GATEWAY;
807         rt.rtmsg_metric = 1;
808         rt.rtmsg_dst_len = 0;
809         rt.rtmsg_ifindex = index;
810
811         sk = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
812         if (sk < 0) {
813                 err = -errno;
814                 goto out;
815         }
816
817         if (ioctl(sk, SIOCDELRT, &rt) < 0 && errno != ESRCH)
818                 err = -errno;
819
820         close(sk);
821
822 out:
823         if (err < 0)
824                 connman_error("Clear default IPv6 gateway error (%s)",
825                                                 strerror(-err));
826
827         return err;
828 }
829
830 int connman_inet_set_gateway_interface(int index)
831 {
832         struct ifreq ifr;
833         struct rtentry rt;
834         struct sockaddr_in addr;
835         int sk, err = 0;
836
837         DBG("index %d", index);
838
839         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
840         if (sk < 0) {
841                 err = -errno;
842                 goto out;
843         }
844
845         memset(&ifr, 0, sizeof(ifr));
846         ifr.ifr_ifindex = index;
847
848         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
849                 err = -errno;
850                 close(sk);
851                 goto out;
852         }
853
854         DBG("ifname %s", ifr.ifr_name);
855
856         memset(&rt, 0, sizeof(rt));
857         rt.rt_flags = RTF_UP;
858
859         memset(&addr, 0, sizeof(addr));
860         addr.sin_family = AF_INET;
861         addr.sin_addr.s_addr = INADDR_ANY;
862
863         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
864         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
865         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
866
867         rt.rt_dev = ifr.ifr_name;
868
869         if (ioctl(sk, SIOCADDRT, &rt) < 0 && errno != EEXIST)
870                 err = -errno;
871
872         close(sk);
873
874 out:
875         if (err < 0)
876                 connman_error("Setting default interface route failed (%s)",
877                                                         strerror(-err));
878
879         return err;
880 }
881
882 int connman_inet_set_ipv6_gateway_interface(int index)
883 {
884         struct ifreq ifr;
885         struct rtentry rt;
886         struct sockaddr_in6 addr;
887         const struct in6_addr any = IN6ADDR_ANY_INIT;
888         int sk, err = 0;
889
890         DBG("index %d", index);
891
892         sk = socket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
893         if (sk < 0) {
894                 err = -errno;
895                 goto out;
896         }
897
898         memset(&ifr, 0, sizeof(ifr));
899         ifr.ifr_ifindex = index;
900
901         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
902                 err = -errno;
903                 close(sk);
904                 goto out;
905         }
906
907         DBG("ifname %s", ifr.ifr_name);
908
909         memset(&rt, 0, sizeof(rt));
910         rt.rt_flags = RTF_UP;
911
912         memset(&addr, 0, sizeof(addr));
913         addr.sin6_family = AF_INET6;
914         addr.sin6_addr = any;
915
916         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
917         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
918         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
919
920         rt.rt_dev = ifr.ifr_name;
921
922         if (ioctl(sk, SIOCADDRT, &rt) < 0 && errno != EEXIST)
923                 err = -errno;
924
925         close(sk);
926
927 out:
928         if (err < 0)
929                 connman_error("Setting default interface route failed (%s)",
930                                                         strerror(-err));
931
932         return err;
933 }
934
935 int connman_inet_clear_gateway_address(int index, const char *gateway)
936 {
937         struct ifreq ifr;
938         struct rtentry rt;
939         struct sockaddr_in addr;
940         int sk, err = 0;
941
942         DBG("index %d gateway %s", index, gateway);
943
944         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
945         if (sk < 0) {
946                 err = -errno;
947                 goto out;
948         }
949
950         memset(&ifr, 0, sizeof(ifr));
951         ifr.ifr_ifindex = index;
952
953         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
954                 err = -errno;
955                 close(sk);
956                 goto out;
957         }
958
959         DBG("ifname %s", ifr.ifr_name);
960
961         memset(&rt, 0, sizeof(rt));
962         rt.rt_flags = RTF_UP | RTF_GATEWAY;
963
964         memset(&addr, 0, sizeof(addr));
965         addr.sin_family = AF_INET;
966         addr.sin_addr.s_addr = INADDR_ANY;
967         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
968
969         memset(&addr, 0, sizeof(addr));
970         addr.sin_family = AF_INET;
971         addr.sin_addr.s_addr = inet_addr(gateway);
972         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
973
974         memset(&addr, 0, sizeof(addr));
975         addr.sin_family = AF_INET;
976         addr.sin_addr.s_addr = INADDR_ANY;
977         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
978
979         if (ioctl(sk, SIOCDELRT, &rt) < 0 && errno != ESRCH)
980                 err = -errno;
981
982         close(sk);
983
984 out:
985         if (err < 0)
986                 connman_error("Removing default gateway route failed (%s)",
987                                                         strerror(-err));
988
989         return err;
990 }
991
992 int connman_inet_clear_gateway_interface(int index)
993 {
994         struct ifreq ifr;
995         struct rtentry rt;
996         struct sockaddr_in addr;
997         int sk, err = 0;
998
999         DBG("index %d", index);
1000
1001         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1002         if (sk < 0) {
1003                 err = -errno;
1004                 goto out;
1005         }
1006
1007         memset(&ifr, 0, sizeof(ifr));
1008         ifr.ifr_ifindex = index;
1009
1010         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1011                 err = -errno;
1012                 close(sk);
1013                 goto out;
1014         }
1015
1016         DBG("ifname %s", ifr.ifr_name);
1017
1018         memset(&rt, 0, sizeof(rt));
1019         rt.rt_flags = RTF_UP;
1020
1021         memset(&addr, 0, sizeof(addr));
1022         addr.sin_family = AF_INET;
1023         addr.sin_addr.s_addr = INADDR_ANY;
1024
1025         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1026         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1027         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1028
1029         rt.rt_dev = ifr.ifr_name;
1030
1031         if (ioctl(sk, SIOCDELRT, &rt) < 0 && errno != ESRCH)
1032                 err = -errno;
1033
1034         close(sk);
1035
1036 out:
1037         if (err < 0)
1038                 connman_error("Removing default interface route failed (%s)",
1039                                                         strerror(-err));
1040
1041         return err;
1042 }
1043
1044 int connman_inet_clear_ipv6_gateway_interface(int index)
1045 {
1046         struct ifreq ifr;
1047         struct rtentry rt;
1048         struct sockaddr_in6 addr;
1049         const struct in6_addr any = IN6ADDR_ANY_INIT;
1050         int sk, err = 0;
1051
1052         DBG("index %d", index);
1053
1054         sk = socket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1055         if (sk < 0) {
1056                 err = -errno;
1057                 goto out;
1058         }
1059
1060         memset(&ifr, 0, sizeof(ifr));
1061         ifr.ifr_ifindex = index;
1062
1063         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1064                 err = -errno;
1065                 close(sk);
1066                 goto out;
1067         }
1068
1069         DBG("ifname %s", ifr.ifr_name);
1070
1071         memset(&rt, 0, sizeof(rt));
1072         rt.rt_flags = RTF_UP;
1073
1074         memset(&addr, 0, sizeof(addr));
1075         addr.sin6_family = AF_INET6;
1076         addr.sin6_addr = any;
1077
1078         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1079         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1080         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1081
1082         rt.rt_dev = ifr.ifr_name;
1083
1084         if (ioctl(sk, SIOCDELRT, &rt) < 0 && errno != ESRCH)
1085                 err = -errno;
1086
1087         close(sk);
1088
1089 out:
1090         if (err < 0)
1091                 connman_error("Removing default interface route failed (%s)",
1092                                                         strerror(-err));
1093
1094         return err;
1095 }
1096
1097 bool connman_inet_compare_subnet(int index, const char *host)
1098 {
1099         struct ifreq ifr;
1100         struct in_addr _host_addr;
1101         in_addr_t host_addr, netmask_addr, if_addr;
1102         struct sockaddr_in *netmask, *addr;
1103         int sk;
1104
1105         DBG("host %s", host);
1106
1107         if (!host)
1108                 return false;
1109
1110         if (inet_aton(host, &_host_addr) == 0)
1111                 return -1;
1112         host_addr = _host_addr.s_addr;
1113
1114         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1115         if (sk < 0)
1116                 return false;
1117
1118         memset(&ifr, 0, sizeof(ifr));
1119         ifr.ifr_ifindex = index;
1120
1121         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1122                 close(sk);
1123                 return false;
1124         }
1125
1126         if (ioctl(sk, SIOCGIFNETMASK, &ifr) < 0) {
1127                 close(sk);
1128                 return false;
1129         }
1130
1131         netmask = (struct sockaddr_in *)&ifr.ifr_netmask;
1132         netmask_addr = netmask->sin_addr.s_addr;
1133
1134         if (ioctl(sk, SIOCGIFADDR, &ifr) < 0) {
1135                 close(sk);
1136                 return false;
1137         }
1138
1139         close(sk);
1140
1141         addr = (struct sockaddr_in *)&ifr.ifr_addr;
1142         if_addr = addr->sin_addr.s_addr;
1143
1144         return ((if_addr & netmask_addr) == (host_addr & netmask_addr));
1145 }
1146
1147 int connman_inet_remove_from_bridge(int index, const char *bridge)
1148 {
1149         struct ifreq ifr;
1150         int sk, err = 0;
1151
1152         if (!bridge)
1153                 return -EINVAL;
1154
1155         sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
1156         if (sk < 0) {
1157                 err = -errno;
1158                 goto out;
1159         }
1160
1161         memset(&ifr, 0, sizeof(ifr));
1162         strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name) - 1);
1163         ifr.ifr_ifindex = index;
1164
1165         if (ioctl(sk, SIOCBRDELIF, &ifr) < 0)
1166                 err = -errno;
1167
1168         close(sk);
1169
1170 out:
1171         if (err < 0)
1172                 connman_error("Remove interface from bridge error %s",
1173                                                         strerror(-err));
1174
1175         return err;
1176 }
1177
1178 int connman_inet_add_to_bridge(int index, const char *bridge)
1179 {
1180         struct ifreq ifr;
1181         int sk, err = 0;
1182
1183         if (!bridge)
1184                 return -EINVAL;
1185
1186         sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
1187         if (sk < 0) {
1188                 err = -errno;
1189                 goto out;
1190         }
1191
1192         memset(&ifr, 0, sizeof(ifr));
1193         strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name) - 1);
1194         ifr.ifr_ifindex = index;
1195
1196         if (ioctl(sk, SIOCBRADDIF, &ifr) < 0)
1197                 err = -errno;
1198
1199         close(sk);
1200
1201 out:
1202         if (err < 0)
1203                 connman_error("Add interface to bridge error %s",
1204                                                         strerror(-err));
1205
1206         return err;
1207 }
1208
1209 int connman_inet_set_mtu(int index, int mtu)
1210 {
1211         struct ifreq ifr;
1212         int sk, err;
1213
1214         sk = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1215         if (sk < 0)
1216                 return sk;
1217
1218         memset(&ifr, 0, sizeof(ifr));
1219         ifr.ifr_ifindex = index;
1220
1221         err = ioctl(sk, SIOCGIFNAME, &ifr);
1222         if (err == 0) {
1223                 ifr.ifr_mtu = mtu;
1224                 err = ioctl(sk, SIOCSIFMTU, &ifr);
1225         }
1226
1227         close(sk);
1228         return err;
1229 }
1230
1231 int connman_inet_setup_tunnel(char *tunnel, int mtu)
1232 {
1233         struct ifreq ifr;
1234         int sk, err, index;
1235         __u32 mask;
1236         __u32 flags;
1237
1238         if (!tunnel)
1239                 return -EINVAL;
1240
1241         sk = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1242         if (sk < 0)
1243                 return sk;
1244
1245         index = if_nametoindex(tunnel);
1246
1247         err = connman_inet_set_mtu(index, mtu);
1248         if (err != 0)
1249                 goto done;
1250
1251         memset(&ifr, 0, sizeof(ifr));
1252         strncpy(ifr.ifr_name, tunnel, sizeof(ifr.ifr_name) - 1);
1253         err = ioctl(sk, SIOCGIFFLAGS, &ifr);
1254         if (err)
1255                 goto done;
1256
1257         mask = IFF_UP;
1258         flags = IFF_UP;
1259
1260         if ((ifr.ifr_flags ^ flags) & mask) {
1261                 ifr.ifr_flags &= ~mask;
1262                 ifr.ifr_flags |= mask & flags;
1263                 err = ioctl(sk, SIOCSIFFLAGS, &ifr);
1264                 if (err)
1265                         connman_error("SIOCSIFFLAGS failed: %s",
1266                                                         strerror(errno));
1267         }
1268
1269 done:
1270         close(sk);
1271         return err;
1272 }
1273
1274 int connman_inet_create_tunnel(char **iface)
1275 {
1276         struct ifreq ifr;
1277         int i, fd;
1278
1279         fd = open("/dev/net/tun", O_RDWR | O_CLOEXEC);
1280         if (fd < 0) {
1281                 i = -errno;
1282                 connman_error("Failed to open /dev/net/tun: %s",
1283                                 strerror(errno));
1284                 return i;
1285         }
1286
1287         memset(&ifr, 0, sizeof(ifr));
1288         ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
1289
1290         for (i = 0; i < 256; i++) {
1291                 sprintf(ifr.ifr_name, "tun%d", i);
1292
1293                 if (!ioctl(fd, TUNSETIFF, (void *)&ifr))
1294                         break;
1295         }
1296
1297         if (i == 256) {
1298                 connman_error("Failed to find available tun device");
1299                 close(fd);
1300                 return -ENODEV;
1301         }
1302
1303         *iface = g_strdup(ifr.ifr_name);
1304
1305         return fd;
1306 }
1307
1308 /*
1309  * This callback struct is used when sending router and neighbor
1310  * solicitation and advertisement messages.
1311  */
1312 struct xs_cb_data {
1313         GIOChannel *channel;
1314         void *callback;
1315         struct sockaddr_in6 addr;
1316         guint timeout;
1317         guint watch_id;
1318         void *user_data;
1319 };
1320
1321 #define CMSG_BUF_LEN 512
1322 #define IN6ADDR_ALL_NODES_MC_INIT \
1323         { { { 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0x1 } } } /* ff02::1 */
1324 #define IN6ADDR_ALL_ROUTERS_MC_INIT \
1325         { { { 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0x2 } } } /* ff02::2 */
1326
1327 static const struct in6_addr in6addr_all_nodes_mc = IN6ADDR_ALL_NODES_MC_INIT;
1328 static const struct in6_addr in6addr_all_routers_mc =
1329                                                 IN6ADDR_ALL_ROUTERS_MC_INIT;
1330
1331 static void xs_cleanup(struct xs_cb_data *data)
1332 {
1333         if (data->channel) {
1334                 g_io_channel_shutdown(data->channel, TRUE, NULL);
1335                 g_io_channel_unref(data->channel);
1336                 data->channel = NULL;
1337         }
1338
1339         if (data->timeout > 0)
1340                 g_source_remove(data->timeout);
1341
1342         if (data->watch_id > 0)
1343                 g_source_remove(data->watch_id);
1344
1345         g_free(data);
1346 }
1347
1348 static gboolean rs_timeout_cb(gpointer user_data)
1349 {
1350         struct xs_cb_data *data = user_data;
1351
1352         DBG("user data %p", user_data);
1353
1354         if (!data)
1355                 return FALSE;
1356
1357         if (data->callback) {
1358                 __connman_inet_rs_cb_t cb = data->callback;
1359                 cb(NULL, 0, data->user_data);
1360         }
1361
1362         data->timeout = 0;
1363         xs_cleanup(data);
1364         return FALSE;
1365 }
1366
1367 static int icmpv6_recv(int fd, struct xs_cb_data *data)
1368 {
1369         struct msghdr mhdr;
1370         struct iovec iov;
1371         unsigned char chdr[CMSG_BUF_LEN];
1372         unsigned char buf[1540];
1373         struct nd_router_advert *hdr;
1374         struct sockaddr_in6 saddr;
1375         ssize_t len;
1376         __connman_inet_rs_cb_t cb = data->callback;
1377
1378         DBG("");
1379
1380         iov.iov_len = sizeof(buf);
1381         iov.iov_base = buf;
1382
1383         mhdr.msg_name = (void *)&saddr;
1384         mhdr.msg_namelen = sizeof(struct sockaddr_in6);
1385         mhdr.msg_flags = 0;
1386         mhdr.msg_iov = &iov;
1387         mhdr.msg_iovlen = 1;
1388         mhdr.msg_control = (void *)chdr;
1389         mhdr.msg_controllen = CMSG_BUF_LEN;
1390
1391         len = recvmsg(fd, &mhdr, 0);
1392         if (len < 0) {
1393                 cb(NULL, 0, data->user_data);
1394                 return -errno;
1395         }
1396
1397 #if defined TIZEN_EXT
1398         /* Set Received Source Address from router as IPv6 Gateway Address */
1399         char src_addr[INET6_ADDRSTRLEN];
1400         if(inet_ntop(AF_INET6, &(saddr.sin6_addr), src_addr, INET6_ADDRSTRLEN)
1401                         == NULL)
1402                 return -errno;
1403
1404         DBG("Received Source Address %s from router", src_addr);
1405
1406         /* icmpv6_recv() function can be called in two scenarios :
1407          * 1. When __connman_inet_ipv6_send_rs() is called from check_dhcpv6()
1408          * 2. When __connman_inet_ipv6_send_rs() is called from
1409          * __connman_6to4_probe()
1410          * In the second case it is not  required to set DHCPv6 Gateway  Address
1411          * as DHCPv6 was not started and  network structure was not passed as
1412          * user_data. If it is tried  to add Source Address as  Gateway Address
1413          * then it will lead to  crash because of  user_data being ip_address
1414          * instead of network structure. So Adding Gateway Address in case 1st
1415          * case only.
1416          */
1417         char *address = data->user_data;
1418         int err = 0;
1419         unsigned char buffer[sizeof(struct in6_addr)] = {0, };
1420         /* Checking if user_data is an ip_address */
1421         err = inet_pton(AF_INET, address, buffer);
1422         /* Setting Received Source Address from
1423          * router as Gateway Address */
1424         if(err <= 0)
1425                 __connman_network_set_auto_ipv6_gateway(src_addr, data->user_data);
1426 #endif
1427         hdr = (struct nd_router_advert *)buf;
1428         DBG("code %d len %zd hdr %zd", hdr->nd_ra_code, len,
1429                                 sizeof(struct nd_router_advert));
1430         if (hdr->nd_ra_code != 0)
1431                 return 0;
1432
1433         cb(hdr, len, data->user_data);
1434
1435         return len;
1436 }
1437
1438 static gboolean icmpv6_event(GIOChannel *chan, GIOCondition cond, gpointer data)
1439 {
1440         int fd, ret;
1441         struct xs_cb_data *xs_data = data;
1442
1443         DBG("");
1444
1445         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
1446                 goto cleanup;
1447
1448         fd = g_io_channel_unix_get_fd(chan);
1449         ret = icmpv6_recv(fd, xs_data);
1450         if (ret == 0)
1451                 return TRUE;
1452
1453 cleanup:
1454         xs_cleanup(xs_data);
1455         return TRUE;
1456 }
1457
1458 /* Adapted from RFC 1071 "C" Implementation Example */
1459 static uint16_t csum(const void *phdr, const void *data, socklen_t datalen,
1460                 const void *extra_data, socklen_t extra_datalen)
1461 {
1462         register unsigned long sum = 0;
1463         socklen_t count;
1464         uint16_t *addr;
1465         int i;
1466
1467         /* caller must make sure datalen is even */
1468
1469         addr = (uint16_t *)phdr;
1470         for (i = 0; i < 20; i++)
1471                 sum += *addr++;
1472
1473         count = datalen;
1474         addr = (uint16_t *)data;
1475
1476         while (count > 1) {
1477                 sum += *(addr++);
1478                 count -= 2;
1479         }
1480
1481         if (extra_data) {
1482                 count = extra_datalen;
1483                 addr = (uint16_t *)extra_data;
1484
1485                 while (count > 1) {
1486                         sum += *(addr++);
1487                         count -= 2;
1488                 }
1489         }
1490
1491         while (sum >> 16)
1492                 sum = (sum & 0xffff) + (sum >> 16);
1493
1494         return (uint16_t)~sum;
1495 }
1496
1497 static int ndisc_send_unspec(int type, int oif, const struct in6_addr *dest,
1498                         const struct in6_addr *source,
1499                         unsigned char *buf, size_t len, uint16_t lifetime)
1500 {
1501         struct _phdr {
1502                 struct in6_addr src;
1503                 struct in6_addr dst;
1504                 uint32_t plen;
1505                 uint8_t reserved[3];
1506                 uint8_t nxt;
1507         } phdr;
1508
1509         struct {
1510                 struct ip6_hdr ip;
1511                 union {
1512                         struct icmp6_hdr icmp;
1513                         struct nd_neighbor_solicit ns;
1514                         struct nd_router_solicit rs;
1515                         struct nd_router_advert ra;
1516                 } i;
1517         } frame;
1518
1519         struct msghdr msgh;
1520         struct cmsghdr *cmsg;
1521         struct in6_pktinfo *pinfo;
1522         struct sockaddr_in6 dst, src;
1523         char cbuf[CMSG_SPACE(sizeof(*pinfo))];
1524         struct iovec iov[2];
1525         int fd, datalen, ret, iovlen = 1;
1526 #if defined TIZEN_EXT
1527         char ebuf[256];
1528 #endif
1529
1530         DBG("");
1531
1532         fd = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_RAW);
1533         if (fd < 0)
1534                 return -errno;
1535
1536         memset(&frame, 0, sizeof(frame));
1537         memset(&dst, 0, sizeof(dst));
1538
1539         if (type == ND_ROUTER_SOLICIT)
1540                 datalen = sizeof(frame.i.rs); /* 8, csum() safe */
1541         else if (type == ND_ROUTER_ADVERT) {
1542                 datalen = sizeof(frame.i.ra); /* 16, csum() safe */
1543                 frame.i.ra.nd_ra_router_lifetime = htons(lifetime);
1544         } else if (type == ND_NEIGHBOR_SOLICIT) {
1545                 datalen = sizeof(frame.i.ns); /* 24, csum() safe */
1546                 memcpy(&frame.i.ns.nd_ns_target, buf, sizeof(struct in6_addr));
1547         } else {
1548                 close(fd);
1549                 return -EINVAL;
1550         }
1551
1552         dst.sin6_addr = *dest;
1553
1554         if (source)
1555                 src.sin6_addr = *source;
1556         else
1557                 src.sin6_addr = in6addr_any;
1558
1559         /* Fill in the IPv6 header */
1560         frame.ip.ip6_vfc = 0x60;
1561         frame.ip.ip6_plen = htons(datalen + len);
1562         frame.ip.ip6_nxt = IPPROTO_ICMPV6;
1563         frame.ip.ip6_hlim = 255;
1564         frame.ip.ip6_dst = dst.sin6_addr;
1565         frame.ip.ip6_src = src.sin6_addr;
1566         /* all other fields are already set to zero */
1567
1568         /* Prepare pseudo header for csum */
1569         memset(&phdr, 0, sizeof(phdr));
1570         phdr.dst = dst.sin6_addr;
1571         phdr.src = src.sin6_addr;
1572         phdr.plen = htonl(datalen + len);
1573         phdr.nxt = IPPROTO_ICMPV6;
1574
1575         /* Fill in remaining ICMP header fields */
1576         frame.i.icmp.icmp6_type = type;
1577         frame.i.icmp.icmp6_cksum = csum(&phdr, &frame.i, datalen, buf, len);
1578
1579         iov[0].iov_base = &frame;
1580         iov[0].iov_len = sizeof(frame.ip) + datalen;
1581
1582         if (buf) {
1583                 iov[1].iov_base = buf;
1584                 iov[1].iov_len = len;
1585                 iovlen = 2;
1586         }
1587
1588         dst.sin6_family = AF_INET6;
1589         msgh.msg_name = &dst;
1590         msgh.msg_namelen = sizeof(dst);
1591         msgh.msg_iov = iov;
1592         msgh.msg_iovlen = iovlen;
1593         msgh.msg_flags = 0;
1594
1595         memset(cbuf, 0, CMSG_SPACE(sizeof(*pinfo)));
1596         cmsg = (struct cmsghdr *)cbuf;
1597         pinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
1598         pinfo->ipi6_ifindex = oif;
1599
1600         cmsg->cmsg_len = CMSG_LEN(sizeof(*pinfo));
1601         cmsg->cmsg_level = IPPROTO_IPV6;
1602         cmsg->cmsg_type = IPV6_PKTINFO;
1603         msgh.msg_control = cmsg;
1604         msgh.msg_controllen = cmsg->cmsg_len;
1605
1606         ret = sendmsg(fd, &msgh, 0);
1607 #if defined TIZEN_EXT
1608         DBG("sendmsg errno: %d/%s", errno, strerror_r(errno, ebuf, sizeof(ebuf)));
1609 #endif
1610
1611         close(fd);
1612         return ret;
1613 }
1614
1615 static inline void ipv6_addr_set(struct in6_addr *addr,
1616                                 uint32_t w1, uint32_t w2,
1617                                 uint32_t w3, uint32_t w4)
1618 {
1619         addr->s6_addr32[0] = w1;
1620         addr->s6_addr32[1] = w2;
1621         addr->s6_addr32[2] = w3;
1622         addr->s6_addr32[3] = w4;
1623 }
1624
1625 static inline void ipv6_addr_solict_mult(const struct in6_addr *addr,
1626                                         struct in6_addr *solicited)
1627 {
1628         ipv6_addr_set(solicited, htonl(0xFF020000), 0, htonl(0x1),
1629                         htonl(0xFF000000) | addr->s6_addr32[3]);
1630 }
1631
1632 static int if_mc_group(int sock, int ifindex, const struct in6_addr *mc_addr,
1633                                                                 int cmd)
1634 {
1635         unsigned int val = 0;
1636         struct ipv6_mreq mreq;
1637         int ret;
1638
1639         memset(&mreq, 0, sizeof(mreq));
1640         mreq.ipv6mr_interface = ifindex;
1641         mreq.ipv6mr_multiaddr = *mc_addr;
1642
1643         ret = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
1644                         &val, sizeof(int));
1645         if (ret < 0) {
1646                 ret = -errno;
1647                 DBG("Cannot set IPV6_MULTICAST_LOOP %d/%s", ret,
1648                         strerror(-ret));
1649                 return ret;
1650         }
1651
1652         ret = setsockopt(sock, IPPROTO_IPV6, cmd, &mreq, sizeof(mreq));
1653         if (ret < 0) {
1654                 ret = -errno;
1655                 DBG("Cannot set option %d %d/%s", cmd, ret, strerror(-ret));
1656                 return ret;
1657         }
1658
1659         return 0;
1660 }
1661
1662 int __connman_inet_ipv6_send_rs(int index, int timeout,
1663                         __connman_inet_rs_cb_t callback, void *user_data)
1664 {
1665         struct xs_cb_data *data;
1666         struct icmp6_filter filter;
1667         struct in6_addr solicit;
1668         struct in6_addr dst = in6addr_all_routers_mc;
1669         int sk;
1670
1671         if (timeout <= 0)
1672                 return -EINVAL;
1673
1674         data = g_try_malloc0(sizeof(struct xs_cb_data));
1675         if (!data)
1676                 return -ENOMEM;
1677
1678         data->callback = callback;
1679         data->user_data = user_data;
1680         data->timeout = g_timeout_add_seconds(timeout, rs_timeout_cb, data);
1681
1682         sk = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_ICMPV6);
1683         if (sk < 0)
1684                 return -errno;
1685
1686         DBG("sock %d", sk);
1687
1688         ICMP6_FILTER_SETBLOCKALL(&filter);
1689         ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
1690
1691         setsockopt(sk, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
1692                                                 sizeof(struct icmp6_filter));
1693
1694         ipv6_addr_solict_mult(&dst, &solicit);
1695         if_mc_group(sk, index, &in6addr_all_nodes_mc, IPV6_JOIN_GROUP);
1696         if_mc_group(sk, index, &solicit, IPV6_JOIN_GROUP);
1697
1698         data->channel = g_io_channel_unix_new(sk);
1699         g_io_channel_set_close_on_unref(data->channel, TRUE);
1700
1701         g_io_channel_set_encoding(data->channel, NULL, NULL);
1702         g_io_channel_set_buffered(data->channel, FALSE);
1703
1704         data->watch_id = g_io_add_watch(data->channel,
1705                         G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
1706                         icmpv6_event, data);
1707
1708         ndisc_send_unspec(ND_ROUTER_SOLICIT, index, &dst, NULL, NULL, 0, 0);
1709
1710         return 0;
1711 }
1712
1713 static inline void ipv6_addr_advert_mult(const struct in6_addr *addr,
1714                                         struct in6_addr *advert)
1715 {
1716         ipv6_addr_set(advert, htonl(0xFF020000), 0, htonl(0x2),
1717                         htonl(0xFF000000) | addr->s6_addr32[3]);
1718 }
1719
1720 #define MSG_SIZE_SEND 1452
1721
1722 static int inc_len(int len, int inc)
1723 {
1724         if (len > MSG_SIZE_SEND)
1725                 return -EINVAL;
1726
1727         len += inc;
1728         return len;
1729 }
1730
1731 int __connman_inet_ipv6_send_ra(int index, struct in6_addr *src_addr,
1732                                 GSList *prefixes, int router_lifetime)
1733 {
1734         GSList *list;
1735         struct in6_addr src, *source;
1736         struct in6_addr dst = in6addr_all_nodes_mc;
1737         GDHCPIAPrefix *prefix;
1738         unsigned char buf[MSG_SIZE_SEND];
1739         char addr_str[INET6_ADDRSTRLEN];
1740         int sk, err = 0;
1741         int len, count = 0;
1742
1743         if (!prefixes)
1744                 return -EINVAL;
1745
1746         sk = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_ICMPV6);
1747         if (sk < 0)
1748                 return -errno;
1749
1750         if (!src_addr) {
1751                 __connman_inet_get_interface_ll_address(index, AF_INET6, &src);
1752                 source = &src;
1753         } else
1754                 source = src_addr;
1755
1756         DBG("sock %d index %d prefixes %p src %s lifetime %d", sk, index,
1757                 prefixes, inet_ntop(AF_INET6, source, addr_str,
1758                                 INET6_ADDRSTRLEN),
1759                 router_lifetime);
1760
1761         memset(buf, 0, MSG_SIZE_SEND);
1762         len = 0;
1763
1764         for (list = prefixes; list; list = list->next) {
1765                 struct nd_opt_prefix_info *pinfo;
1766
1767                 prefix = list->data;
1768                 pinfo = (struct nd_opt_prefix_info *)(buf + len);
1769
1770                 len = inc_len(len, sizeof(*pinfo));
1771                 if (len < 0) {
1772                         err = len;
1773                         goto out;
1774                 }
1775
1776                 pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
1777                 pinfo->nd_opt_pi_len = 4;
1778                 pinfo->nd_opt_pi_prefix_len = prefix->prefixlen;
1779                 pinfo->nd_opt_pi_flags_reserved = ND_OPT_PI_FLAG_ONLINK;
1780                 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
1781                 if (router_lifetime > 0) {
1782                         pinfo->nd_opt_pi_valid_time = htonl(prefix->valid);
1783                         pinfo->nd_opt_pi_preferred_time =
1784                                                 htonl(prefix->preferred);
1785                 }
1786                 pinfo->nd_opt_pi_reserved2 = 0;
1787
1788                 memcpy(&pinfo->nd_opt_pi_prefix, &prefix->prefix,
1789                                                 sizeof(struct in6_addr));
1790
1791                 DBG("[%d] index %d prefix %s/%d", count, index,
1792                         inet_ntop(AF_INET6, &prefix->prefix, addr_str,
1793                                 INET6_ADDRSTRLEN), prefix->prefixlen);
1794
1795                 count++;
1796         }
1797
1798         if (count > 0) {
1799                 err = ndisc_send_unspec(ND_ROUTER_ADVERT, index, &dst, source,
1800                                         buf, len, router_lifetime);
1801                 if (err < 0)
1802                         DBG("cannot send RA %d/%s", err, strerror(-err));
1803         }
1804
1805 out:
1806         close(sk);
1807         return err;
1808 }
1809
1810 void __connman_inet_ipv6_stop_recv_rs(void *context)
1811 {
1812         if (!context)
1813                 return;
1814
1815         xs_cleanup(context);
1816 }
1817
1818 static int icmpv6_rs_recv(int fd, struct xs_cb_data *data)
1819 {
1820         struct msghdr mhdr;
1821         struct iovec iov;
1822         unsigned char chdr[CMSG_BUF_LEN];
1823         unsigned char buf[1540];
1824         struct nd_router_solicit *hdr;
1825         struct sockaddr_in6 saddr;
1826         ssize_t len;
1827         __connman_inet_recv_rs_cb_t cb = data->callback;
1828
1829         DBG("");
1830
1831         iov.iov_len = sizeof(buf);
1832         iov.iov_base = buf;
1833
1834         mhdr.msg_name = (void *)&saddr;
1835         mhdr.msg_namelen = sizeof(struct sockaddr_in6);
1836         mhdr.msg_flags = 0;
1837         mhdr.msg_iov = &iov;
1838         mhdr.msg_iovlen = 1;
1839         mhdr.msg_control = (void *)chdr;
1840         mhdr.msg_controllen = CMSG_BUF_LEN;
1841
1842         len = recvmsg(fd, &mhdr, 0);
1843         if (len < 0) {
1844                 cb(NULL, 0, data->user_data);
1845                 return -errno;
1846         }
1847
1848         hdr = (struct nd_router_solicit *)buf;
1849         DBG("code %d len %zd hdr %zd", hdr->nd_rs_code, len,
1850                                 sizeof(struct nd_router_solicit));
1851         if (hdr->nd_rs_code != 0)
1852                 return 0;
1853
1854         cb(hdr, len, data->user_data);
1855         return len;
1856 }
1857
1858 static gboolean icmpv6_rs_event(GIOChannel *chan, GIOCondition cond,
1859                                                                 gpointer data)
1860 {
1861         int fd, ret;
1862         struct xs_cb_data *xs_data = data;
1863
1864         DBG("");
1865
1866         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
1867                 goto cleanup;
1868
1869         fd = g_io_channel_unix_get_fd(chan);
1870         ret = icmpv6_rs_recv(fd, xs_data);
1871         if (ret == 0)
1872                 return TRUE;
1873
1874 cleanup:
1875         xs_data->watch_id = 0;
1876         return FALSE;
1877 }
1878
1879 int __connman_inet_ipv6_start_recv_rs(int index,
1880                                         __connman_inet_recv_rs_cb_t callback,
1881                                         void *user_data,
1882                                         void **context)
1883 {
1884         struct xs_cb_data *data;
1885         struct icmp6_filter filter;
1886         char addr_str[INET6_ADDRSTRLEN];
1887         int sk, err;
1888
1889         data = g_try_malloc0(sizeof(struct xs_cb_data));
1890         if (!data)
1891                 return -ENOMEM;
1892
1893         data->callback = callback;
1894         data->user_data = user_data;
1895
1896         sk = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_ICMPV6);
1897         if (sk < 0) {
1898                 g_free(data);
1899                 return -errno;
1900         }
1901
1902         DBG("sock %d", sk);
1903
1904         ICMP6_FILTER_SETBLOCKALL(&filter);
1905         ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
1906
1907         setsockopt(sk, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
1908                                                 sizeof(struct icmp6_filter));
1909
1910         err = if_mc_group(sk, index, &in6addr_all_routers_mc, IPV6_JOIN_GROUP);
1911         if (err < 0)
1912                 DBG("Cannot join mc %s %d/%s", inet_ntop(AF_INET6,
1913                         &in6addr_all_routers_mc, addr_str, INET6_ADDRSTRLEN),
1914                         err, strerror(-err));
1915
1916         data->channel = g_io_channel_unix_new(sk);
1917         g_io_channel_set_close_on_unref(data->channel, TRUE);
1918
1919         g_io_channel_set_encoding(data->channel, NULL, NULL);
1920         g_io_channel_set_buffered(data->channel, FALSE);
1921
1922         data->watch_id = g_io_add_watch(data->channel,
1923                         G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
1924                         icmpv6_rs_event, data);
1925
1926         *context = data;
1927
1928         return 0;
1929 }
1930
1931 static gboolean ns_timeout_cb(gpointer user_data)
1932 {
1933         struct xs_cb_data *data = user_data;
1934
1935         DBG("user data %p", user_data);
1936
1937         if (!data)
1938                 return FALSE;
1939
1940         if (data->callback) {
1941                 __connman_inet_ns_cb_t cb = data->callback;
1942                 cb(NULL, 0, &data->addr.sin6_addr, data->user_data);
1943         }
1944
1945         data->timeout = 0;
1946         xs_cleanup(data);
1947         return FALSE;
1948 }
1949
1950 static int icmpv6_nd_recv(int fd, struct xs_cb_data *data)
1951 {
1952         struct msghdr mhdr;
1953         struct iovec iov;
1954         unsigned char chdr[CMSG_BUF_LEN];
1955         unsigned char buf[1540];
1956         struct nd_neighbor_advert *hdr;
1957         struct sockaddr_in6 saddr;
1958         ssize_t len;
1959         __connman_inet_ns_cb_t cb = data->callback;
1960
1961         DBG("");
1962
1963         iov.iov_len = sizeof(buf);
1964         iov.iov_base = buf;
1965
1966         mhdr.msg_name = (void *)&saddr;
1967         mhdr.msg_namelen = sizeof(struct sockaddr_in6);
1968         mhdr.msg_flags = 0;
1969         mhdr.msg_iov = &iov;
1970         mhdr.msg_iovlen = 1;
1971         mhdr.msg_control = (void *)chdr;
1972         mhdr.msg_controllen = CMSG_BUF_LEN;
1973
1974         len = recvmsg(fd, &mhdr, 0);
1975         if (len < 0) {
1976                 cb(NULL, 0, &data->addr.sin6_addr, data->user_data);
1977                 return -errno;
1978         }
1979
1980         hdr = (struct nd_neighbor_advert *)buf;
1981         DBG("code %d len %zd hdr %zd", hdr->nd_na_code, len,
1982                                 sizeof(struct nd_neighbor_advert));
1983         if (hdr->nd_na_code != 0)
1984                 return 0;
1985
1986         /*
1987          * We can receive any neighbor advertisement so we need to check if the
1988          * packet was meant for us and ignore the packet otherwise.
1989          */
1990         if (memcmp(&data->addr.sin6_addr, &hdr->nd_na_target,
1991                         sizeof(struct in6_addr)))
1992                 return 0;
1993
1994         cb(hdr, len, &data->addr.sin6_addr, data->user_data);
1995
1996         return len;
1997 }
1998
1999 static gboolean icmpv6_nd_event(GIOChannel *chan, GIOCondition cond,
2000                                                                 gpointer data)
2001 {
2002         int fd, ret;
2003         struct xs_cb_data *xs_data = data;
2004
2005         DBG("");
2006
2007         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
2008                 goto cleanup;
2009
2010         fd = g_io_channel_unix_get_fd(chan);
2011         ret = icmpv6_nd_recv(fd, xs_data);
2012         if (ret == 0)
2013                 return TRUE;
2014
2015 cleanup:
2016         xs_cleanup(xs_data);
2017         return TRUE;
2018 }
2019
2020 int __connman_inet_ipv6_do_dad(int index, int timeout_ms,
2021                                 struct in6_addr *addr,
2022                                 __connman_inet_ns_cb_t callback,
2023                                 void *user_data)
2024 {
2025         struct xs_cb_data *data;
2026         struct icmp6_filter filter;
2027         struct in6_addr solicit;
2028         int sk, err, val = 1;
2029
2030         if (timeout_ms <= 0)
2031                 return -EINVAL;
2032
2033         data = g_try_malloc0(sizeof(struct xs_cb_data));
2034         if (!data)
2035                 return -ENOMEM;
2036
2037         data->callback = callback;
2038         data->user_data = user_data;
2039         data->timeout = g_timeout_add_full(G_PRIORITY_DEFAULT,
2040                                         (guint)timeout_ms,
2041                                         ns_timeout_cb,
2042                                         data,
2043                                         NULL);
2044         memcpy(&data->addr.sin6_addr, addr, sizeof(struct in6_addr));
2045
2046         sk = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_ICMPV6);
2047         if (sk < 0)
2048                 return -errno;
2049
2050         DBG("sock %d", sk);
2051
2052         ICMP6_FILTER_SETBLOCKALL(&filter);
2053         ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filter);
2054
2055         setsockopt(sk, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
2056                                                 sizeof(struct icmp6_filter));
2057
2058         if (setsockopt(sk, IPPROTO_IPV6, IPV6_RECVPKTINFO,
2059                                                 &val, sizeof(val)) < 0) {
2060                 err = -errno;
2061                 DBG("Cannot set IPV6_RECVPKTINFO %d/%s", err,
2062                                                         strerror(-err));
2063                 close(sk);
2064                 return err;
2065         }
2066
2067         if (setsockopt(sk, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
2068                                                 &val, sizeof(val)) < 0) {
2069                 err = -errno;
2070                 DBG("Cannot set IPV6_RECVHOPLIMIT %d/%s", err,
2071                                                         strerror(-err));
2072                 close(sk);
2073                 return err;
2074         }
2075
2076         val = 0;
2077         setsockopt(sk, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &val, sizeof(val));
2078
2079         ipv6_addr_solict_mult(addr, &solicit);
2080         if_mc_group(sk, index, &in6addr_all_nodes_mc, IPV6_JOIN_GROUP);
2081         if_mc_group(sk, index, &solicit, IPV6_JOIN_GROUP);
2082
2083         data->channel = g_io_channel_unix_new(sk);
2084         g_io_channel_set_close_on_unref(data->channel, TRUE);
2085
2086         g_io_channel_set_encoding(data->channel, NULL, NULL);
2087         g_io_channel_set_buffered(data->channel, FALSE);
2088
2089         data->watch_id = g_io_add_watch(data->channel,
2090                         G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
2091                         icmpv6_nd_event, data);
2092
2093         err = ndisc_send_unspec(ND_NEIGHBOR_SOLICIT, index, &solicit, NULL,
2094                         (unsigned char *)addr, 0, 0);
2095         if (err < 0) {
2096                 DBG("Cannot send NS %d/%s", err, strerror(-err));
2097                 xs_cleanup(data);
2098         }
2099
2100         return err;
2101 }
2102
2103 GSList *__connman_inet_ipv6_get_prefixes(struct nd_router_advert *hdr,
2104                                         unsigned int length)
2105 {
2106         GSList *prefixes = NULL;
2107         uint8_t *pos;
2108         int len;
2109
2110         if (length <= sizeof(struct nd_router_advert))
2111                 return NULL;
2112
2113         len = length - sizeof(struct nd_router_advert);
2114         pos = (uint8_t *)hdr + sizeof(struct nd_router_advert);
2115
2116         while (len > 0) {
2117                 struct nd_opt_prefix_info *pinfo;
2118                 char prefix_str[INET6_ADDRSTRLEN+1], *str;
2119                 const char *prefix;
2120                 int optlen;
2121
2122                 if (len < 2)
2123                         break;
2124
2125                 optlen = pos[1] << 3;
2126                 if (optlen == 0 || optlen > len)
2127                         break;
2128
2129                 switch (pos[0]) {
2130                 case ND_OPT_PREFIX_INFORMATION:
2131                         pinfo = (struct nd_opt_prefix_info *)pos;
2132                         prefix = inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
2133                                         prefix_str, INET6_ADDRSTRLEN);
2134                         if (!prefix)
2135                                 break;
2136
2137                         str = g_strdup_printf("%s/%d", prefix,
2138                                                 pinfo->nd_opt_pi_prefix_len);
2139                         prefixes = g_slist_prepend(prefixes, str);
2140
2141                         DBG("prefix %s", str);
2142
2143                         break;
2144                 }
2145
2146                 len -= optlen;
2147                 pos += optlen;
2148         }
2149
2150         return prefixes;
2151 }
2152
2153 static int get_dest_addr(int family, int index, char *buf, int len)
2154 {
2155         struct ifreq ifr;
2156         void *addr;
2157         int sk;
2158
2159         sk = socket(family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
2160         if (sk < 0)
2161                 return -errno;
2162
2163         memset(&ifr, 0, sizeof(ifr));
2164         ifr.ifr_ifindex = index;
2165
2166         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
2167                 DBG("SIOCGIFNAME (%d/%s)", errno, strerror(errno));
2168                 close(sk);
2169                 return -errno;
2170         }
2171
2172         if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
2173                 DBG("SIOCGIFFLAGS (%d/%s)", errno, strerror(errno));
2174                 close(sk);
2175                 return -errno;
2176         }
2177
2178         if ((ifr.ifr_flags & IFF_POINTOPOINT) == 0) {
2179                 close(sk);
2180                 errno = EINVAL;
2181                 return -errno;
2182         }
2183
2184         DBG("index %d %s", index, ifr.ifr_name);
2185
2186         if (ioctl(sk, SIOCGIFDSTADDR, &ifr) < 0) {
2187                 connman_error("Get destination address failed (%s)",
2188                                                         strerror(errno));
2189                 close(sk);
2190                 return -errno;
2191         }
2192
2193         close(sk);
2194
2195         switch (family) {
2196         case AF_INET:
2197                 addr = &((struct sockaddr_in *)&ifr.ifr_dstaddr)->sin_addr;
2198                 break;
2199         case AF_INET6:
2200                 addr = &((struct sockaddr_in6 *)&ifr.ifr_dstaddr)->sin6_addr;
2201                 break;
2202         default:
2203                 errno = EINVAL;
2204                 return -errno;
2205         }
2206
2207         if (!inet_ntop(family, addr, buf, len)) {
2208                 DBG("error %d/%s", errno, strerror(errno));
2209                 return -errno;
2210         }
2211
2212         return 0;
2213 }
2214
2215 int connman_inet_get_dest_addr(int index, char **dest)
2216 {
2217         char addr[INET_ADDRSTRLEN];
2218         int ret;
2219
2220         ret = get_dest_addr(PF_INET, index, addr, INET_ADDRSTRLEN);
2221         if (ret < 0)
2222                 return ret;
2223
2224         *dest = g_strdup(addr);
2225
2226         DBG("destination %s", *dest);
2227
2228         return 0;
2229 }
2230
2231 int connman_inet_ipv6_get_dest_addr(int index, char **dest)
2232 {
2233         char addr[INET6_ADDRSTRLEN];
2234         int ret;
2235
2236         ret = get_dest_addr(PF_INET6, index, addr, INET6_ADDRSTRLEN);
2237         if (ret < 0)
2238                 return ret;
2239
2240         *dest = g_strdup(addr);
2241
2242         DBG("destination %s", *dest);
2243
2244         return 0;
2245 }
2246
2247 int __connman_inet_rtnl_open(struct __connman_inet_rtnl_handle *rth)
2248 {
2249         int sndbuf = 1024;
2250         int rcvbuf = 1024 * 4;
2251
2252         rth->fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
2253         if (rth->fd < 0) {
2254                 connman_error("Can not open netlink socket: %s",
2255                                                 strerror(errno));
2256                 return -errno;
2257         }
2258
2259         if (setsockopt(rth->fd, SOL_SOCKET, SO_SNDBUF, &sndbuf,
2260                         sizeof(sndbuf)) < 0) {
2261                 connman_error("SO_SNDBUF: %s", strerror(errno));
2262                 return -errno;
2263         }
2264
2265         if (setsockopt(rth->fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf,
2266                         sizeof(rcvbuf)) < 0) {
2267                 connman_error("SO_RCVBUF: %s", strerror(errno));
2268                 return -errno;
2269         }
2270
2271         memset(&rth->local, 0, sizeof(rth->local));
2272         rth->local.nl_family = AF_NETLINK;
2273         rth->local.nl_groups = 0;
2274
2275         if (bind(rth->fd, (struct sockaddr *)&rth->local,
2276                                                 sizeof(rth->local)) < 0) {
2277                 connman_error("Can not bind netlink socket: %s",
2278                                                         strerror(errno));
2279                 return -errno;
2280         }
2281
2282         rth->seq = time(NULL);
2283
2284         DBG("fd %d", rth->fd);
2285
2286         return 0;
2287 }
2288
2289 struct inet_rtnl_cb_data {
2290         GIOChannel *channel;
2291         __connman_inet_rtnl_cb_t callback;
2292         guint rtnl_timeout;
2293         guint watch_id;
2294         struct __connman_inet_rtnl_handle *rtnl;
2295         void *user_data;
2296 };
2297
2298 static void inet_rtnl_cleanup(struct inet_rtnl_cb_data *data)
2299 {
2300         struct __connman_inet_rtnl_handle *rth = data->rtnl;
2301
2302         if (data->channel) {
2303                 g_io_channel_shutdown(data->channel, TRUE, NULL);
2304                 g_io_channel_unref(data->channel);
2305                 data->channel = NULL;
2306         }
2307
2308         DBG("data %p", data);
2309
2310         if (data->rtnl_timeout > 0)
2311                 g_source_remove(data->rtnl_timeout);
2312
2313         if (data->watch_id > 0)
2314                 g_source_remove(data->watch_id);
2315
2316         if (rth) {
2317                 __connman_inet_rtnl_close(rth);
2318                 g_free(rth);
2319         }
2320
2321         g_free(data);
2322 }
2323
2324 static gboolean inet_rtnl_timeout_cb(gpointer user_data)
2325 {
2326         struct inet_rtnl_cb_data *data = user_data;
2327
2328         DBG("user data %p", user_data);
2329
2330         if (!data)
2331                 return FALSE;
2332
2333         if (data->callback)
2334                 data->callback(NULL, data->user_data);
2335
2336         data->rtnl_timeout = 0;
2337         inet_rtnl_cleanup(data);
2338         return FALSE;
2339 }
2340
2341 static int inet_rtnl_recv(GIOChannel *chan, struct inet_rtnl_cb_data *rtnl_data)
2342 {
2343         struct __connman_inet_rtnl_handle *rth = rtnl_data->rtnl;
2344         struct nlmsghdr *h = NULL;
2345         struct sockaddr_nl nladdr;
2346         socklen_t addr_len = sizeof(nladdr);
2347         unsigned char buf[4096];
2348         void *ptr = buf;
2349         gsize len;
2350         int status, fd;
2351
2352         memset(buf, 0, sizeof(buf));
2353         memset(&nladdr, 0, sizeof(nladdr));
2354
2355         fd = g_io_channel_unix_get_fd(chan);
2356
2357         status = recvfrom(fd, buf, sizeof(buf), 0,
2358                        (struct sockaddr *) &nladdr, &addr_len);
2359         if (status < 0) {
2360                 if (errno == EINTR || errno == EAGAIN)
2361                         return 0;
2362
2363                 return -1;
2364         }
2365
2366         if (status == 0)
2367                 return -1;
2368
2369         if (nladdr.nl_pid != 0) { /* not sent by kernel, ignore */
2370                 DBG("Received msg from %u, ignoring it", nladdr.nl_pid);
2371                 return 0;
2372         }
2373
2374         len = status;
2375
2376         while (len > 0) {
2377                 struct nlmsgerr *err;
2378
2379                 h = ptr;
2380
2381                 if (!NLMSG_OK(h, len))
2382                         return -1;
2383
2384                 if (h->nlmsg_seq != rth->seq) {
2385                         /* Skip this msg */
2386                         DBG("skip %d/%d len %d", rth->seq,
2387                                 h->nlmsg_seq, h->nlmsg_len);
2388
2389                         len -= h->nlmsg_len;
2390                         ptr += h->nlmsg_len;
2391                         continue;
2392                 }
2393
2394                 switch (h->nlmsg_type) {
2395                 case NLMSG_NOOP:
2396                 case NLMSG_OVERRUN:
2397                         return -1;
2398
2399                 case NLMSG_ERROR:
2400                         err = (struct nlmsgerr *)NLMSG_DATA(h);
2401                         connman_error("RTNETLINK answers %s (%d)",
2402                                 strerror(-err->error), -err->error);
2403                         return err->error;
2404                 }
2405
2406                 break;
2407         }
2408
2409         if (h->nlmsg_seq == rth->seq) {
2410                 DBG("received %d seq %d", h->nlmsg_len, h->nlmsg_seq);
2411
2412                 rtnl_data->callback(h, rtnl_data->user_data);
2413
2414                 inet_rtnl_cleanup(rtnl_data);
2415         }
2416
2417         return 0;
2418 }
2419
2420 static gboolean inet_rtnl_event(GIOChannel *chan, GIOCondition cond,
2421                                                         gpointer user_data)
2422 {
2423         int ret;
2424         struct inet_rtnl_cb_data *rtnl_data = user_data;
2425
2426         DBG("");
2427
2428         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
2429                 goto cleanup;
2430
2431         ret = inet_rtnl_recv(chan, rtnl_data);
2432         if (ret == 0)
2433                 return TRUE;
2434
2435 cleanup:
2436         inet_rtnl_cleanup(rtnl_data);
2437         return TRUE;
2438 }
2439
2440 int __connman_inet_rtnl_talk(struct __connman_inet_rtnl_handle *rtnl,
2441                         struct nlmsghdr *n, int timeout,
2442                         __connman_inet_rtnl_cb_t callback, void *user_data)
2443 {
2444         struct sockaddr_nl nladdr;
2445         struct inet_rtnl_cb_data *data;
2446         int err;
2447
2448         memset(&nladdr, 0, sizeof(nladdr));
2449         nladdr.nl_family = AF_NETLINK;
2450
2451         n->nlmsg_seq = ++rtnl->seq;
2452
2453         if (callback) {
2454                 data = g_try_malloc0(sizeof(struct inet_rtnl_cb_data));
2455                 if (!data)
2456                         return -ENOMEM;
2457
2458                 data->callback = callback;
2459                 data->user_data = user_data;
2460                 data->rtnl = rtnl;
2461                 data->rtnl_timeout = g_timeout_add_seconds(timeout,
2462                                                 inet_rtnl_timeout_cb, data);
2463
2464                 data->channel = g_io_channel_unix_new(rtnl->fd);
2465
2466                 g_io_channel_set_encoding(data->channel, NULL, NULL);
2467                 g_io_channel_set_buffered(data->channel, FALSE);
2468
2469                 data->watch_id = g_io_add_watch(data->channel,
2470                                 G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
2471                                                 inet_rtnl_event, data);
2472         } else
2473                 n->nlmsg_flags |= NLM_F_ACK;
2474
2475         err = sendto(rtnl->fd, &rtnl->req.n, rtnl->req.n.nlmsg_len, 0,
2476                 (struct sockaddr *) &nladdr, sizeof(nladdr));
2477         DBG("handle %p len %d", rtnl, rtnl->req.n.nlmsg_len);
2478         if (err < 0) {
2479                 connman_error("Can not talk to rtnetlink err %d %s",
2480                         -errno, strerror(errno));
2481                 return -errno;
2482         }
2483
2484         if ((unsigned int)err != rtnl->req.n.nlmsg_len) {
2485                 connman_error("Sent %d bytes, msg truncated", err);
2486                 return -EINVAL;
2487         }
2488
2489         return 0;
2490 }
2491
2492 void __connman_inet_rtnl_close(struct __connman_inet_rtnl_handle *rth)
2493 {
2494         DBG("handle %p", rth);
2495
2496         if (rth->fd >= 0) {
2497                 close(rth->fd);
2498                 rth->fd = -1;
2499         }
2500 }
2501
2502 int __connman_inet_rtnl_addattr32(struct nlmsghdr *n, size_t maxlen, int type,
2503                                 __u32 data)
2504 {
2505         int len = RTA_LENGTH(4);
2506         struct rtattr *rta;
2507
2508         if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) {
2509                 DBG("Error! max allowed bound %zd exceeded", maxlen);
2510                 return -1;
2511         }
2512         rta = NLMSG_TAIL(n);
2513         rta->rta_type = type;
2514         rta->rta_len = len;
2515         memcpy(RTA_DATA(rta), &data, 4);
2516         n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
2517
2518         return 0;
2519 }
2520
2521 static int parse_rtattr(struct rtattr *tb[], int max,
2522                         struct rtattr *rta, int len)
2523 {
2524         memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
2525         while (RTA_OK(rta, len)) {
2526                 if ((rta->rta_type <= max) && (!tb[rta->rta_type]))
2527                         tb[rta->rta_type] = rta;
2528                 rta = RTA_NEXT(rta, len);
2529         }
2530         if (len)
2531                 connman_error("Deficit %d, rta_len=%d", len, rta->rta_len);
2532
2533         return 0;
2534 }
2535
2536 struct get_route_cb_data {
2537         connman_inet_addr_cb_t callback;
2538         void *user_data;
2539 };
2540
2541 static void get_route_cb(struct nlmsghdr *answer, void *user_data)
2542 {
2543         struct get_route_cb_data *data = user_data;
2544         struct rtattr *tb[RTA_MAX+1];
2545         struct rtmsg *r = NLMSG_DATA(answer);
2546         int len, index = -1;
2547         char abuf[256];
2548         const char *addr = NULL;
2549
2550         DBG("answer %p data %p", answer, user_data);
2551
2552         if (!answer)
2553                 goto out;
2554
2555         len = answer->nlmsg_len;
2556
2557         if (answer->nlmsg_type != RTM_NEWROUTE &&
2558                                 answer->nlmsg_type != RTM_DELROUTE) {
2559                 connman_error("Not a route: %08x %08x %08x",
2560                         answer->nlmsg_len, answer->nlmsg_type,
2561                         answer->nlmsg_flags);
2562                 goto out;
2563         }
2564
2565         len -= NLMSG_LENGTH(sizeof(*r));
2566         if (len < 0) {
2567                 connman_error("BUG: wrong nlmsg len %d", len);
2568                 goto out;
2569         }
2570
2571         parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
2572
2573         if (tb[RTA_OIF])
2574                 index = *(int *)RTA_DATA(tb[RTA_OIF]);
2575
2576         if (tb[RTA_GATEWAY])
2577                 addr = inet_ntop(r->rtm_family,
2578                                 RTA_DATA(tb[RTA_GATEWAY]),
2579                                 abuf, sizeof(abuf));
2580
2581         DBG("addr %s index %d user %p", addr, index, data->user_data);
2582
2583 out:
2584         if (data && data->callback)
2585                 data->callback(addr, index, data->user_data);
2586
2587         g_free(data);
2588
2589         return;
2590 }
2591
2592 /*
2593  * Return the interface index that contains route to host.
2594  */
2595 int __connman_inet_get_route(const char *dest_address,
2596                         connman_inet_addr_cb_t callback, void *user_data)
2597 {
2598         struct get_route_cb_data *data;
2599         struct addrinfo hints, *rp;
2600         struct __connman_inet_rtnl_handle *rth;
2601         int err;
2602
2603         DBG("dest %s", dest_address);
2604
2605         if (!dest_address)
2606                 return -EINVAL;
2607
2608         memset(&hints, 0, sizeof(hints));
2609         hints.ai_family = AF_UNSPEC;
2610         hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV | AI_NUMERICHOST;
2611
2612         err = getaddrinfo(dest_address, NULL, &hints, &rp);
2613         if (err)
2614                 return -EINVAL;
2615
2616         rth = g_try_malloc0(sizeof(struct __connman_inet_rtnl_handle));
2617         if (!rth) {
2618                 freeaddrinfo(rp);
2619                 return -ENOMEM;
2620         }
2621
2622         rth->req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
2623         rth->req.n.nlmsg_flags = NLM_F_REQUEST;
2624         rth->req.n.nlmsg_type = RTM_GETROUTE;
2625         rth->req.u.r.rt.rtm_family = rp->ai_family;
2626         rth->req.u.r.rt.rtm_table = 0;
2627         rth->req.u.r.rt.rtm_protocol = 0;
2628         rth->req.u.r.rt.rtm_scope = 0;
2629         rth->req.u.r.rt.rtm_type = 0;
2630         rth->req.u.r.rt.rtm_src_len = 0;
2631         rth->req.u.r.rt.rtm_dst_len = rp->ai_addrlen << 3;
2632         rth->req.u.r.rt.rtm_tos = 0;
2633
2634         __connman_inet_rtnl_addattr_l(&rth->req.n, sizeof(rth->req), RTA_DST,
2635                                 &rp->ai_addr, rp->ai_addrlen);
2636
2637         freeaddrinfo(rp);
2638
2639         err = __connman_inet_rtnl_open(rth);
2640         if (err < 0)
2641                 goto fail;
2642
2643         data = g_try_malloc(sizeof(struct get_route_cb_data));
2644         if (!data) {
2645                 err = -ENOMEM;
2646                 goto done;
2647         }
2648
2649         data->callback = callback;
2650         data->user_data = user_data;
2651
2652 #define GET_ROUTE_TIMEOUT 2
2653         err = __connman_inet_rtnl_talk(rth, &rth->req.n, GET_ROUTE_TIMEOUT,
2654                                 get_route_cb, data);
2655         if (err < 0) {
2656                 g_free(data);
2657                 goto done;
2658         }
2659
2660         return 0;
2661
2662 done:
2663         __connman_inet_rtnl_close(rth);
2664
2665 fail:
2666         g_free(rth);
2667         return err;
2668 }
2669
2670 int connman_inet_check_ipaddress(const char *host)
2671 {
2672         struct addrinfo hints;
2673         struct addrinfo *addr;
2674         int result;
2675
2676         memset(&hints, 0, sizeof(struct addrinfo));
2677         hints.ai_flags = AI_NUMERICHOST;
2678         addr = NULL;
2679
2680         result = getaddrinfo(host, NULL, &hints, &addr);
2681         if (result == 0)
2682                 result = addr->ai_family;
2683         freeaddrinfo(addr);
2684
2685         return result;
2686 }
2687
2688 /* Check routine modified from ics-dhcp 4.2.3-P2 */
2689 bool connman_inet_check_hostname(const char *ptr, size_t len)
2690 {
2691         const char *p;
2692
2693         /*
2694          * Not empty or complete length not over 255 characters.
2695          */
2696         if ((len == 0) || (len > 256))
2697                 return false;
2698
2699         /*
2700          * Consists of [[:alnum:]-]+ labels separated by [.]
2701          * a [_] is against RFC but seems to be "widely used"
2702          */
2703         for (p = ptr; (*p != 0) && (len-- > 0); p++) {
2704
2705                 if ((*p == '-') || (*p == '_')) {
2706                         /*
2707                          * Not allowed at begin or end of a label.
2708                          */
2709                         if (((p - ptr) == 0) || (len == 0) || (p[1] == '.'))
2710                                 return false;
2711
2712                 } else if (*p == '.') {
2713                         /*
2714                          * Each label has to be 1-63 characters;
2715                          * we allow [.] at the end ('foo.bar.')
2716                          */
2717                         size_t d = p - ptr;
2718
2719                         if ((d <= 0) || (d >= 64))
2720                                 return false;
2721
2722                         ptr = p + 1; /* Jump to the next label */
2723
2724                 } else if (isalnum((unsigned char)*p) == 0) {
2725                         /*
2726                          * Also numbers at the begin are fine
2727                          */
2728                         return false;
2729                 }
2730         }
2731
2732         return true;
2733 }
2734
2735 char **__connman_inet_get_running_interfaces(void)
2736 {
2737         char **result;
2738         struct ifconf ifc;
2739         struct ifreq *ifr = NULL;
2740         int sk, i, numif, count = 0;
2741
2742         memset(&ifc, 0, sizeof(ifc));
2743
2744         sk = socket(AF_INET, SOCK_DGRAM, 0);
2745         if (sk < 0)
2746                 return NULL;
2747
2748         if (ioctl(sk, SIOCGIFCONF, &ifc) < 0)
2749                 goto error;
2750
2751         /*
2752          * Allocate some extra bytes just in case there will
2753          * be new interfaces added between two SIOCGIFCONF
2754          * calls.
2755          */
2756         ifr = g_try_malloc0(ifc.ifc_len * 2);
2757         if (!ifr)
2758                 goto error;
2759
2760         ifc.ifc_req = ifr;
2761
2762         if (ioctl(sk, SIOCGIFCONF, &ifc) < 0)
2763                 goto error;
2764
2765         numif = ifc.ifc_len / sizeof(struct ifreq);
2766
2767         result = g_try_malloc0((numif + 1) * sizeof(char *));
2768         if (!result)
2769                 goto error;
2770
2771         close(sk);
2772
2773         for (i = 0; i < numif; i++) {
2774                 struct ifreq *r = &ifr[i];
2775                 struct in6_addr *addr6;
2776                 in_addr_t addr4;
2777
2778                 /*
2779                  * Note that we do not return loopback interfaces here as they
2780                  * are not needed for our purposes.
2781                  */
2782                 switch (r->ifr_addr.sa_family) {
2783                 case AF_INET:
2784                         addr4 = ntohl(((struct sockaddr_in *)
2785                                                 &r->ifr_addr)->sin_addr.s_addr);
2786                         if (((addr4 & 0xff000000) >> 24) == 127)
2787                                 continue;
2788                         break;
2789                 case AF_INET6:
2790                         addr6 = &((struct sockaddr_in6 *)
2791                                                 &r->ifr_addr)->sin6_addr;
2792                         if (IN6_IS_ADDR_LINKLOCAL(addr6))
2793                                 continue;
2794                         break;
2795                 }
2796
2797                 result[count++] = g_strdup(r->ifr_name);
2798         }
2799
2800         g_free(ifr);
2801
2802         if (count < numif)
2803         {
2804                 char **prev_result = result;
2805                 result = g_try_realloc(result, (count + 1) * sizeof(char *));
2806                 if (!result) {
2807                         g_free(prev_result);
2808                         return NULL;
2809                 }
2810         }
2811
2812         return result;
2813
2814 error:
2815         close(sk);
2816         g_free(ifr);
2817         return NULL;
2818 }
2819
2820 bool connman_inet_is_ipv6_supported()
2821 {
2822         int sk;
2823
2824         sk = socket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
2825         if (sk < 0)
2826                 return false;
2827
2828         close(sk);
2829         return true;
2830 }
2831
2832 int __connman_inet_get_interface_address(int index, int family, void *address)
2833 {
2834         struct ifaddrs *ifaddr, *ifa;
2835         int err = -ENOENT;
2836         char name[IF_NAMESIZE];
2837
2838         if (!if_indextoname(index, name))
2839                 return -EINVAL;
2840
2841         DBG("index %d interface %s", index, name);
2842
2843         if (getifaddrs(&ifaddr) < 0) {
2844                 err = -errno;
2845                 DBG("Cannot get addresses err %d/%s", err, strerror(-err));
2846                 return err;
2847         }
2848
2849         for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
2850                 if (!ifa->ifa_addr)
2851                         continue;
2852
2853                 if (strncmp(ifa->ifa_name, name, IF_NAMESIZE) == 0 &&
2854                                         ifa->ifa_addr->sa_family == family) {
2855                         if (family == AF_INET) {
2856                                 struct sockaddr_in *in4 = (struct sockaddr_in *)
2857                                         ifa->ifa_addr;
2858                                 if (in4->sin_addr.s_addr == INADDR_ANY)
2859                                         continue;
2860                                 memcpy(address, &in4->sin_addr,
2861                                                         sizeof(struct in_addr));
2862                         } else if (family == AF_INET6) {
2863                                 struct sockaddr_in6 *in6 =
2864                                         (struct sockaddr_in6 *)ifa->ifa_addr;
2865                                 if (memcmp(&in6->sin6_addr, &in6addr_any,
2866                                                 sizeof(struct in6_addr)) == 0)
2867                                         continue;
2868                                 memcpy(address, &in6->sin6_addr,
2869                                                 sizeof(struct in6_addr));
2870
2871                         } else {
2872                                 err = -EINVAL;
2873                                 goto out;
2874                         }
2875
2876                         err = 0;
2877                         break;
2878                 }
2879         }
2880
2881 out:
2882         freeifaddrs(ifaddr);
2883         return err;
2884 }
2885
2886 static int iprule_modify(int cmd, int family, uint32_t table_id,
2887                         uint32_t fwmark)
2888 {
2889         struct __connman_inet_rtnl_handle rth;
2890         int ret;
2891
2892         memset(&rth, 0, sizeof(rth));
2893
2894         rth.req.n.nlmsg_type = cmd;
2895         rth.req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
2896         rth.req.n.nlmsg_flags = NLM_F_REQUEST;
2897         rth.req.u.r.rt.rtm_family = family;
2898         rth.req.u.r.rt.rtm_protocol = RTPROT_BOOT;
2899         rth.req.u.r.rt.rtm_scope = RT_SCOPE_UNIVERSE;
2900         rth.req.u.r.rt.rtm_table = table_id;
2901         rth.req.u.r.rt.rtm_type = RTN_UNSPEC;
2902         rth.req.u.r.rt.rtm_flags = 0;
2903
2904         if (cmd == RTM_NEWRULE) {
2905                 rth.req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL;
2906                 rth.req.u.r.rt.rtm_type = RTN_UNICAST;
2907         }
2908
2909         __connman_inet_rtnl_addattr32(&rth.req.n, sizeof(rth.req),
2910                                                         FRA_FWMARK, fwmark);
2911
2912         if (table_id < 256) {
2913                 rth.req.u.r.rt.rtm_table = table_id;
2914         } else {
2915                 rth.req.u.r.rt.rtm_table = RT_TABLE_UNSPEC;
2916                 __connman_inet_rtnl_addattr32(&rth.req.n, sizeof(rth.req),
2917                                                 FRA_TABLE, table_id);
2918         }
2919
2920         if (rth.req.u.r.rt.rtm_family == AF_UNSPEC)
2921                 rth.req.u.r.rt.rtm_family = AF_INET;
2922
2923         ret = __connman_inet_rtnl_open(&rth);
2924         if (ret < 0)
2925                 goto done;
2926
2927         ret = __connman_inet_rtnl_send(&rth, &rth.req.n);
2928
2929 done:
2930         __connman_inet_rtnl_close(&rth);
2931
2932         return ret;
2933 }
2934
2935 int __connman_inet_add_fwmark_rule(uint32_t table_id, int family, uint32_t fwmark)
2936 {
2937         /* ip rule add fwmark 9876 table 1234 */
2938
2939         return iprule_modify(RTM_NEWRULE, family, table_id, fwmark);
2940 }
2941
2942 int __connman_inet_del_fwmark_rule(uint32_t table_id, int family, uint32_t fwmark)
2943 {
2944         return iprule_modify(RTM_DELRULE, family, table_id, fwmark);
2945 }
2946
2947 static int iproute_default_modify(int cmd, uint32_t table_id, int ifindex,
2948                         const char *gateway)
2949 {
2950         struct __connman_inet_rtnl_handle rth;
2951         unsigned char buf[sizeof(struct in6_addr)];
2952         int ret, len;
2953         int family = connman_inet_check_ipaddress(gateway);
2954
2955         switch (family) {
2956         case AF_INET:
2957                 len = 4;
2958                 break;
2959         case AF_INET6:
2960                 len = 16;
2961                 break;
2962         default:
2963                 return -EINVAL;
2964         }
2965
2966         ret = inet_pton(family, gateway, buf);
2967         if (ret <= 0)
2968                 return -EINVAL;
2969
2970         memset(&rth, 0, sizeof(rth));
2971
2972         rth.req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
2973         rth.req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
2974         rth.req.n.nlmsg_type = cmd;
2975         rth.req.u.r.rt.rtm_family = family;
2976         rth.req.u.r.rt.rtm_table = RT_TABLE_MAIN;
2977         rth.req.u.r.rt.rtm_scope = RT_SCOPE_NOWHERE;
2978         rth.req.u.r.rt.rtm_protocol = RTPROT_BOOT;
2979         rth.req.u.r.rt.rtm_scope = RT_SCOPE_UNIVERSE;
2980         rth.req.u.r.rt.rtm_type = RTN_UNICAST;
2981
2982         __connman_inet_rtnl_addattr_l(&rth.req.n, sizeof(rth.req), RTA_GATEWAY,
2983                                                                 buf, len);
2984         if (table_id < 256) {
2985                 rth.req.u.r.rt.rtm_table = table_id;
2986         } else {
2987                 rth.req.u.r.rt.rtm_table = RT_TABLE_UNSPEC;
2988                 __connman_inet_rtnl_addattr32(&rth.req.n, sizeof(rth.req),
2989                                                         RTA_TABLE, table_id);
2990         }
2991
2992         __connman_inet_rtnl_addattr32(&rth.req.n, sizeof(rth.req),
2993                                                         RTA_OIF, ifindex);
2994
2995         ret = __connman_inet_rtnl_open(&rth);
2996         if (ret < 0)
2997                 goto done;
2998
2999         ret = __connman_inet_rtnl_send(&rth, &rth.req.n);
3000
3001 done:
3002         __connman_inet_rtnl_close(&rth);
3003
3004         return ret;
3005 }
3006
3007 int __connman_inet_add_default_to_table(uint32_t table_id, int ifindex,
3008                                                 const char *gateway)
3009 {
3010         /* ip route add default via 1.2.3.4 dev wlan0 table 1234 */
3011
3012         return iproute_default_modify(RTM_NEWROUTE, table_id, ifindex, gateway);
3013 }
3014
3015 int __connman_inet_del_default_from_table(uint32_t table_id, int ifindex,
3016                                                 const char *gateway)
3017 {
3018         /* ip route del default via 1.2.3.4 dev wlan0 table 1234 */
3019
3020         return iproute_default_modify(RTM_DELROUTE, table_id, ifindex, gateway);
3021 }
3022
3023 int __connman_inet_get_interface_ll_address(int index, int family,
3024                                                                 void *address)
3025 {
3026         struct ifaddrs *ifaddr, *ifa;
3027         int err = -ENOENT;
3028         char name[IF_NAMESIZE];
3029
3030         if (!if_indextoname(index, name))
3031                 return -EINVAL;
3032
3033         DBG("index %d interface %s", index, name);
3034
3035         if (getifaddrs(&ifaddr) < 0) {
3036                 err = -errno;
3037                 DBG("Cannot get addresses err %d/%s", err, strerror(-err));
3038                 return err;
3039         }
3040
3041         for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
3042                 if (!ifa->ifa_addr)
3043                         continue;
3044
3045                 if (strncmp(ifa->ifa_name, name, IF_NAMESIZE) == 0 &&
3046                                         ifa->ifa_addr->sa_family == family) {
3047                         if (family == AF_INET) {
3048                                 struct sockaddr_in *in4 = (struct sockaddr_in *)
3049                                         ifa->ifa_addr;
3050                                 if (in4->sin_addr.s_addr == INADDR_ANY)
3051                                         continue;
3052                                 if ((in4->sin_addr.s_addr & IN_CLASSB_NET) !=
3053                                                 ((in_addr_t) 0xa9fe0000))
3054                                         continue;
3055                                 memcpy(address, &in4->sin_addr,
3056                                                         sizeof(struct in_addr));
3057                         } else if (family == AF_INET6) {
3058                                 struct sockaddr_in6 *in6 =
3059                                         (struct sockaddr_in6 *)ifa->ifa_addr;
3060                                 if (memcmp(&in6->sin6_addr, &in6addr_any,
3061                                                 sizeof(struct in6_addr)) == 0)
3062                                         continue;
3063                                 if (!IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
3064                                         continue;
3065
3066                                 memcpy(address, &in6->sin6_addr,
3067                                                 sizeof(struct in6_addr));
3068                         } else {
3069                                 err = -EINVAL;
3070                                 goto out;
3071                         }
3072
3073                         err = 0;
3074                         break;
3075                 }
3076         }
3077
3078 out:
3079         freeifaddrs(ifaddr);
3080         return err;
3081 }
3082
3083 int __connman_inet_get_address_netmask(int ifindex,
3084                                         struct sockaddr_in *address,
3085                                         struct sockaddr_in *netmask)
3086 {
3087         int sk, ret = -EINVAL;
3088         struct ifreq ifr;
3089
3090         DBG("index %d", ifindex);
3091
3092         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
3093         if (sk < 0)
3094                 return -EINVAL;
3095
3096         memset(&ifr, 0, sizeof(ifr));
3097         ifr.ifr_ifindex = ifindex;
3098
3099         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0)
3100                 goto out;
3101
3102         if (ioctl(sk, SIOCGIFNETMASK, &ifr) < 0)
3103                 goto out;
3104
3105         memcpy(netmask, (struct sockaddr_in *)&ifr.ifr_netmask,
3106                                                 sizeof(struct sockaddr_in));
3107
3108         if (ioctl(sk, SIOCGIFADDR, &ifr) < 0)
3109                 goto out;
3110
3111         memcpy(address, (struct sockaddr_in *)&ifr.ifr_addr,
3112                                                 sizeof(struct sockaddr_in));
3113         ret = 0;
3114
3115 out:
3116         close(sk);
3117         return ret;
3118 }
3119
3120 static int get_nfs_server_ip(const char *cmdline_file, const char *pnp_file,
3121                                 struct in_addr *addr)
3122 {
3123         char *s, *nfsargs;
3124         size_t len;
3125         char addrstr[INET_ADDRSTRLEN];
3126         struct in_addr taddr;
3127         GError *error = NULL;
3128         char *cmdline = NULL;
3129         char *pnp = NULL;
3130         char **args = NULL;
3131         char **pnpent = NULL;
3132         char **pp = NULL;
3133         int err = -1;
3134
3135         if (!cmdline_file)
3136                 cmdline_file = "/proc/cmdline";
3137         if (!pnp_file)
3138                 pnp_file = "/proc/net/pnp";
3139         if (!addr)
3140                 addr = &taddr;
3141         addr->s_addr = INADDR_NONE;
3142
3143         if (!g_file_get_contents(cmdline_file, &cmdline, NULL, &error)) {
3144                 connman_error("%s: Cannot read %s %s\n", __func__,
3145                                 cmdline_file, error->message);
3146                 goto out;
3147         }
3148
3149         if (g_file_test(pnp_file, G_FILE_TEST_EXISTS)) {
3150                 if (!g_file_get_contents(pnp_file, &pnp, NULL, &error)) {
3151                         connman_error("%s: Cannot read %s %s\n", __func__,
3152                                                   pnp_file, error->message);
3153                         goto out;
3154                 }
3155         } else {
3156                 connman_error("%s: File %s doesn't exist\n", __func__, pnp_file);
3157                 goto out;
3158         }
3159
3160         len = strlen(cmdline);
3161         if (len <= 1) {
3162                 /* too short */
3163                 goto out;
3164         }
3165         /* remove newline */
3166         if (cmdline[len - 1] == '\n')
3167                 cmdline[--len] = '\0';
3168
3169         /* split in arguments (seperated by space) */
3170         args = g_strsplit(cmdline, " ", 0);
3171         if (!args) {
3172                 connman_error("%s: Cannot split cmdline \"%s\"\n", __func__,
3173                                 cmdline);
3174                 goto out;
3175         }
3176
3177         /* split in entries (by newlines) */
3178         pnpent = g_strsplit(pnp, "\n", 0);
3179         if (!pnpent) {
3180                 connman_error("%s: Cannot split pnp at file \"%s\"\n", __func__,
3181                                 pnp_file);
3182                 goto out;
3183         }
3184
3185         /* first find root argument */
3186         for (pp = args; *pp; pp++) {
3187                 if (!strcmp(*pp, "root=/dev/nfs"))
3188                         break;
3189         }
3190         /* no rootnfs found */
3191         if (!*pp)
3192                 goto out;
3193
3194         /* locate nfsroot argument */
3195         for (pp = args; *pp; pp++) {
3196                 if (!strncmp(*pp, "nfsroot=", strlen("nfsroot=")))
3197                         break;
3198         }
3199         /* no nfsroot argument found */
3200         if (!*pp)
3201                 goto out;
3202
3203         /* determine if nfsroot server is provided */
3204         nfsargs = strchr(*pp, '=');
3205         if (!nfsargs)
3206                 goto out;
3207         nfsargs++;
3208
3209         /* find whether serverip is present */
3210         s = strchr(nfsargs, ':');
3211         if (s) {
3212                 len = s - nfsargs;
3213                 s = nfsargs;
3214         } else {
3215                 /* no serverip, use bootserver */
3216                 for (pp = pnpent; *pp; pp++) {
3217                         if (!strncmp(*pp, "bootserver ", strlen("bootserver ")))
3218                                 break;
3219                 }
3220                 /* no bootserver found */
3221                 if (!*pp)
3222                         goto out;
3223                 s = *pp + strlen("bootserver ");
3224                 len = strlen(s);
3225         }
3226
3227         /* copy to addr string buffer */
3228         if (len >= sizeof(addrstr)) {
3229                 connman_error("%s: Bad server\n", __func__);
3230                 goto out;
3231         }
3232         memcpy(addrstr, s, len);
3233         addrstr[len] = '\0';
3234
3235         err = inet_pton(AF_INET, addrstr, addr);
3236         if (err <= 0) {
3237                 connman_error("%s: Cannot convert to numeric addr \"%s\"\n",
3238                                 __func__, addrstr);
3239                 err = -1;
3240                 goto out;
3241         }
3242
3243         /* all done */
3244         err = 0;
3245 out:
3246         g_strfreev(pnpent);
3247         g_strfreev(args);
3248         if (error)
3249                 g_error_free(error);
3250         g_free(pnp);
3251         g_free(cmdline);
3252
3253         return err;
3254 }
3255
3256 /* get interface out of which peer is reachable (IPv4 only) */
3257 static int get_peer_iface(struct in_addr *addr, char *ifname)
3258 {
3259         struct ifaddrs *ifaddr, *ifa;
3260         struct sockaddr_in saddr, *ifsaddr;
3261         socklen_t socklen;
3262         int s;
3263         int err = -1;
3264
3265         /* Obtain address(es) matching host/port */
3266         err = getifaddrs(&ifaddr);
3267         if (err < 0) {
3268                 connman_error("%s: getifaddrs() failed %d (%s)\n",
3269                                 __func__, errno, strerror(errno));
3270                 return -1;
3271         }
3272
3273         s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
3274         if (s < 0) {
3275                 connman_error("%s: socket() failed %d (%s)\n",
3276                                 __func__, errno, strerror(errno));
3277                 return -1;
3278         }
3279
3280         memset(&saddr, 0, sizeof(saddr));
3281         saddr.sin_family = AF_INET;
3282         saddr.sin_port = 0;     /* any port */
3283         saddr.sin_addr = *addr;
3284
3285         /* no need to bind, connect will select iface */
3286         err = connect(s, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in));
3287         if (err < 0) {
3288                 connman_error("%s: connect() failed: %d (%s)\n",
3289                                 __func__, errno, strerror(errno));
3290                 goto out;
3291         }
3292
3293         socklen = sizeof(saddr);
3294         err = getsockname(s, (struct sockaddr *)&saddr, &socklen);
3295         if (err < 0) {
3296                 connman_error("%s: getsockname() failed: %d (%s)\n",
3297                                 __func__, errno, strerror(errno));
3298                 goto out;
3299         }
3300
3301         err = -1;
3302         for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
3303                 if (!ifa->ifa_addr)
3304                         continue;
3305
3306                 /* only IPv4 address */
3307                 if (ifa->ifa_addr->sa_family != AF_INET)
3308                         continue;
3309
3310                 ifsaddr = (struct sockaddr_in *)ifa->ifa_addr;
3311
3312                 /* match address? */
3313                 if (ifsaddr->sin_addr.s_addr == saddr.sin_addr.s_addr)
3314                         break;
3315         }
3316
3317         if (ifa) {
3318                 err = 0;
3319                 if (ifname)
3320                         strcpy(ifname, ifa->ifa_name);
3321         }
3322
3323 out:
3324         close(s);
3325
3326         freeifaddrs(ifaddr);
3327
3328         return err;
3329 }
3330
3331 bool __connman_inet_isrootnfs_device(const char *devname)
3332 {
3333         struct in_addr addr;
3334         char ifname[IFNAMSIZ];
3335
3336         return get_nfs_server_ip(NULL, NULL, &addr) == 0 &&
3337                get_peer_iface(&addr, ifname) == 0 &&
3338                strcmp(devname, ifname) == 0;
3339 }
3340
3341 char **__connman_inet_get_pnp_nameservers(const char *pnp_file)
3342 {
3343         char **pp;
3344         char *s;
3345         int pass, count;
3346         GError *error = NULL;
3347         char *pnp = NULL;
3348         char **pnpent = NULL;
3349         char **nameservers = NULL;
3350
3351         if (!pnp_file)
3352                 pnp_file = "/proc/net/pnp";
3353
3354         if (!g_file_get_contents(pnp_file, &pnp, NULL, &error)) {
3355                 connman_error("%s: Cannot read %s %s\n", __func__,
3356                                 pnp_file, error->message);
3357                 goto out;
3358         }
3359
3360         /* split in entries (by newlines) */
3361         pnpent = g_strsplit(pnp, "\n", 0);
3362         if (!pnpent) {
3363                 connman_error("%s: Cannot split pnp \"%s\"\n", __func__,
3364                                 pnp_file);
3365                 goto out;
3366         }
3367
3368         /*
3369          * Perform two passes to retreive a char ** array of
3370          * nameservers that are not 0.0.0.0
3371          *
3372          * The first pass counts them, the second fills in the
3373          * array.
3374          */
3375         count = 0;
3376         nameservers = NULL;
3377         for (pass = 1; pass <= 2; pass++) {
3378
3379                 /* at the start of the second pass allocate */
3380                 if (pass == 2)
3381                         nameservers = g_new(char *, count + 1);
3382
3383                 count = 0;
3384                 for (pp = pnpent; *pp; pp++) {
3385                         /* match 'nameserver ' at the start of each line */
3386                         if (strncmp(*pp, "nameserver ", strlen("nameserver ")))
3387                                 continue;
3388
3389                         /* compare it against 0.0.0.0 */
3390                         s = *pp + strlen("nameserver ");
3391                         if (!strcmp(s, "0.0.0.0"))
3392                                 continue;
3393
3394                         /* on second pass fill in array */
3395                         if (pass == 2)
3396                                 nameservers[count] = g_strdup(s);
3397                         count++;
3398                 }
3399
3400                 /* no nameservers? */
3401                 if (count == 0)
3402                         goto out;
3403
3404                 /* and terminate char ** array with NULL */
3405                 if (pass == 2)
3406                         nameservers[count] = NULL;
3407
3408         }
3409
3410 out:
3411         g_strfreev(pnpent);
3412         g_free(pnp);
3413         if (error)
3414                 g_error_free(error);
3415
3416         return nameservers;
3417 }