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