Using netlink to set and clear ipv6 addresses
[platform/upstream/connman.git] / src / inet.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/stat.h>
32 #include <sys/ioctl.h>
33 #include <sys/socket.h>
34 #include <arpa/inet.h>
35 #include <net/route.h>
36 #include <net/ethernet.h>
37 #include <linux/if_arp.h>
38 #include <linux/wireless.h>
39
40 #include "connman.h"
41
42 #define NLMSG_TAIL(nmsg)                                \
43         ((struct rtattr *) (((uint8_t*) (nmsg)) +       \
44         NLMSG_ALIGN((nmsg)->nlmsg_len)))
45
46 static int add_rtattr(struct nlmsghdr *n, size_t max_length, int type,
47                                 const void *data, size_t data_length)
48 {
49         size_t length;
50         struct rtattr *rta;
51
52         length = RTA_LENGTH(data_length);
53
54         if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(length) > max_length)
55                 return -E2BIG;
56
57         rta = NLMSG_TAIL(n);
58         rta->rta_type = type;
59         rta->rta_len = length;
60         memcpy(RTA_DATA(rta), data, data_length);
61         n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(length);
62
63         return 0;
64 }
65
66 int __connman_inet_modify_address(int cmd, int flags,
67                                 int index, int family,
68                                 const char *address,
69                                 unsigned char prefixlen,
70                                 const char *broadcast)
71 {
72         uint8_t request[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
73                         NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
74                         RTA_LENGTH(sizeof(struct in6_addr))];
75
76         struct nlmsghdr *header;
77         struct sockaddr_nl nl_addr;
78         struct ifaddrmsg *ifaddrmsg;
79         struct in6_addr ipv6_addr;
80         struct in_addr ipv4_addr, ipv4_bcast;
81         int sk, err;
82
83         DBG("");
84
85         if (address == NULL)
86                 return -1;
87
88         if (family != AF_INET && family != AF_INET6)
89                 return -1;
90
91         memset(&request, 0, sizeof(request));
92
93         header = (struct nlmsghdr *)request;
94         header->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
95         header->nlmsg_type = cmd;
96         header->nlmsg_flags = NLM_F_REQUEST | flags;
97         header->nlmsg_seq = 1;
98
99         ifaddrmsg = NLMSG_DATA(header);
100         ifaddrmsg->ifa_family = family;
101         ifaddrmsg->ifa_prefixlen = prefixlen;
102         ifaddrmsg->ifa_flags = IFA_F_PERMANENT;
103         ifaddrmsg->ifa_scope = RT_SCOPE_UNIVERSE;
104         ifaddrmsg->ifa_index = index;
105
106         if (family == AF_INET) {
107                 if (inet_pton(AF_INET, address, &ipv4_addr) < 1)
108                         return -1;
109
110                 if (broadcast != NULL)
111                         inet_pton(AF_INET, broadcast, &ipv4_bcast);
112                 else
113                         ipv4_bcast.s_addr = ipv4_addr.s_addr |
114                                 htonl(0xfffffffflu >> prefixlen);
115
116                 if ((err = add_rtattr(header, sizeof(request), IFA_LOCAL,
117                                 &ipv4_addr, sizeof(ipv4_addr))) < 0)
118                         return err;
119
120                 if ((err = add_rtattr(header, sizeof(request), IFA_BROADCAST,
121                                 &ipv4_bcast, sizeof(ipv4_bcast))) < 0)
122                         return err;
123
124         } else if (family == AF_INET6) {
125                 if (inet_pton(AF_INET6, address, &ipv6_addr) < 1)
126                         return -1;
127
128                 if ((err = add_rtattr(header, sizeof(request), IFA_LOCAL,
129                                 &ipv6_addr, sizeof(ipv6_addr))) < 0)
130                         return err;
131         }
132
133         sk = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
134         if (sk < 0)
135                 return -1;
136
137         memset(&nl_addr, 0, sizeof(nl_addr));
138         nl_addr.nl_family = AF_NETLINK;
139
140         if ((err = sendto(sk, request, header->nlmsg_len, 0,
141                         (struct sockaddr *) &nl_addr, sizeof(nl_addr))) < 0)
142                 goto done;
143
144         err = 0;
145
146 done:
147         close(sk);
148
149         return err;
150 }
151
152 int connman_inet_ifindex(const char *name)
153 {
154         struct ifreq ifr;
155         int sk, err;
156
157         if (name == NULL)
158                 return -1;
159
160         sk = socket(PF_INET, SOCK_DGRAM, 0);
161         if (sk < 0)
162                 return -1;
163
164         memset(&ifr, 0, sizeof(ifr));
165         strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
166
167         err = ioctl(sk, SIOCGIFINDEX, &ifr);
168
169         close(sk);
170
171         if (err < 0)
172                 return -1;
173
174         return ifr.ifr_ifindex;
175 }
176
177 char *connman_inet_ifname(int index)
178 {
179         struct ifreq ifr;
180         int sk, err;
181
182         if (index < 0)
183                 return NULL;
184
185         sk = socket(PF_INET, SOCK_DGRAM, 0);
186         if (sk < 0)
187                 return NULL;
188
189         memset(&ifr, 0, sizeof(ifr));
190         ifr.ifr_ifindex = index;
191
192         err = ioctl(sk, SIOCGIFNAME, &ifr);
193
194         close(sk);
195
196         if (err < 0)
197                 return NULL;
198
199         return strdup(ifr.ifr_name);
200 }
201
202 short int connman_inet_ifflags(int index)
203 {
204         struct ifreq ifr;
205         int sk, err;
206
207         sk = socket(PF_INET, SOCK_DGRAM, 0);
208         if (sk < 0)
209                 return -errno;
210
211         memset(&ifr, 0, sizeof(ifr));
212         ifr.ifr_ifindex = index;
213
214         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
215                 err = -errno;
216                 goto done;
217         }
218
219         if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
220                 err = -errno;
221                 goto done;
222         }
223
224         err = ifr.ifr_flags;
225
226 done:
227         close(sk);
228
229         return err;
230 }
231
232 int connman_inet_ifup(int index)
233 {
234         struct ifreq ifr;
235         int sk, err;
236
237         sk = socket(PF_INET, SOCK_DGRAM, 0);
238         if (sk < 0)
239                 return -errno;
240
241         memset(&ifr, 0, sizeof(ifr));
242         ifr.ifr_ifindex = index;
243
244         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
245                 err = -errno;
246                 goto done;
247         }
248
249         if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
250                 err = -errno;
251                 goto done;
252         }
253
254         if (ifr.ifr_flags & IFF_UP) {
255                 err = -EALREADY;
256                 goto done;
257         }
258
259         ifr.ifr_flags |= IFF_UP;
260
261         if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0) {
262                 err = -errno;
263                 goto done;
264         }
265
266         err = 0;
267
268 done:
269         close(sk);
270
271         return err;
272 }
273
274 int connman_inet_ifdown(int index)
275 {
276         struct ifreq ifr;
277         int sk, err;
278
279         sk = socket(PF_INET, SOCK_DGRAM, 0);
280         if (sk < 0)
281                 return -errno;
282
283         memset(&ifr, 0, sizeof(ifr));
284         ifr.ifr_ifindex = index;
285
286         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
287                 err = -errno;
288                 goto done;
289         }
290
291         if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
292                 err = -errno;
293                 goto done;
294         }
295
296         if (!(ifr.ifr_flags & IFF_UP)) {
297                 err = -EALREADY;
298                 goto done;
299         }
300
301         ifr.ifr_flags &= ~IFF_UP;
302
303         if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0)
304                 err = -errno;
305         else
306                 err = 0;
307
308 done:
309         close(sk);
310
311         return err;
312 }
313
314 static char *index2addr(int index)
315 {
316         struct ifreq ifr;
317         struct ether_addr eth;
318         char *str;
319         int sk, err;
320
321         if (index < 0)
322                 return NULL;
323
324         sk = socket(PF_INET, SOCK_DGRAM, 0);
325         if (sk < 0)
326                 return NULL;
327
328         memset(&ifr, 0, sizeof(ifr));
329         ifr.ifr_ifindex = index;
330
331         err = ioctl(sk, SIOCGIFNAME, &ifr);
332
333         if (err == 0)
334                 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
335
336         close(sk);
337
338         if (err < 0)
339                 return NULL;
340
341         str = malloc(18);
342         if (!str)
343                 return NULL;
344
345         memcpy(&eth, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
346         snprintf(str, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
347                                                 eth.ether_addr_octet[0],
348                                                 eth.ether_addr_octet[1],
349                                                 eth.ether_addr_octet[2],
350                                                 eth.ether_addr_octet[3],
351                                                 eth.ether_addr_octet[4],
352                                                 eth.ether_addr_octet[5]);
353
354         return str;
355 }
356
357 static char *index2ident(int index, const char *prefix)
358 {
359         struct ifreq ifr;
360         struct ether_addr eth;
361         char *str;
362         int sk, err, len;
363
364         if (index < 0)
365                 return NULL;
366
367         sk = socket(PF_INET, SOCK_DGRAM, 0);
368         if (sk < 0)
369                 return NULL;
370
371         memset(&ifr, 0, sizeof(ifr));
372         ifr.ifr_ifindex = index;
373
374         err = ioctl(sk, SIOCGIFNAME, &ifr);
375
376         if (err == 0)
377                 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
378
379         close(sk);
380
381         if (err < 0)
382                 return NULL;
383
384         len = prefix ? strlen(prefix) + 18 : 18;
385
386         str = malloc(len);
387         if (!str)
388                 return NULL;
389
390         memcpy(&eth, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
391         snprintf(str, len, "%s%02x%02x%02x%02x%02x%02x",
392                                                 prefix ? prefix : "",
393                                                 eth.ether_addr_octet[0],
394                                                 eth.ether_addr_octet[1],
395                                                 eth.ether_addr_octet[2],
396                                                 eth.ether_addr_octet[3],
397                                                 eth.ether_addr_octet[4],
398                                                 eth.ether_addr_octet[5]);
399
400         return str;
401 }
402
403 connman_bool_t connman_inet_is_cfg80211(int index)
404 {
405         connman_bool_t result = FALSE;
406         char phy80211_path[PATH_MAX];
407         struct stat st;
408         struct ifreq ifr;
409         int sk;
410
411         sk = socket(PF_INET, SOCK_DGRAM, 0);
412         if (sk < 0)
413                 return FALSE;
414
415         memset(&ifr, 0, sizeof(ifr));
416         ifr.ifr_ifindex = index;
417
418         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0)
419                 goto done;
420
421         snprintf(phy80211_path, PATH_MAX,
422                                 "/sys/class/net/%s/phy80211", ifr.ifr_name);
423
424         if (stat(phy80211_path, &st) == 0 && (st.st_mode & S_IFDIR))
425                 result = TRUE;
426
427 done:
428         close(sk);
429
430         return result;
431 }
432
433 struct connman_device *connman_inet_create_device(int index)
434 {
435         enum connman_device_mode mode = CONNMAN_DEVICE_MODE_UNKNOWN;
436         enum connman_device_type type;
437         struct connman_device *device;
438         char *devname, *ident = NULL;
439         char *addr = NULL, *name = NULL, *node = NULL;
440
441         if (index < 0)
442                 return NULL;
443
444         devname = connman_inet_ifname(index);
445         if (devname == NULL)
446                 return NULL;
447
448         if (__connman_element_device_isfiltered(devname) == TRUE) {
449                 connman_info("Ignoring interface %s (filtered)", devname);
450                 return NULL;
451         }
452
453         type = __connman_rtnl_get_device_type(index);
454
455         switch (type) {
456         case CONNMAN_DEVICE_TYPE_UNKNOWN:
457                 connman_info("Ignoring interface %s (type unknown)", devname);
458                 g_free(devname);
459                 return NULL;
460         case CONNMAN_DEVICE_TYPE_ETHERNET:
461         case CONNMAN_DEVICE_TYPE_WIFI:
462         case CONNMAN_DEVICE_TYPE_WIMAX:
463                 name = index2ident(index, "");
464                 addr = index2addr(index);
465                 break;
466         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
467         case CONNMAN_DEVICE_TYPE_CELLULAR:
468         case CONNMAN_DEVICE_TYPE_GPS:
469         case CONNMAN_DEVICE_TYPE_VENDOR:
470                 name = strdup(devname);
471                 break;
472         }
473
474         device = connman_device_create(name, type);
475         if (device == NULL)
476                 goto done;
477
478         switch (type) {
479         case CONNMAN_DEVICE_TYPE_UNKNOWN:
480         case CONNMAN_DEVICE_TYPE_VENDOR:
481         case CONNMAN_DEVICE_TYPE_GPS:
482                 mode = CONNMAN_DEVICE_MODE_UNKNOWN;
483                 break;
484         case CONNMAN_DEVICE_TYPE_ETHERNET:
485                 mode = CONNMAN_DEVICE_MODE_NETWORK_SINGLE;
486                 ident = index2ident(index, NULL);
487                 break;
488         case CONNMAN_DEVICE_TYPE_WIFI:
489         case CONNMAN_DEVICE_TYPE_WIMAX:
490                 mode = CONNMAN_DEVICE_MODE_NETWORK_SINGLE;
491                 ident = index2ident(index, NULL);
492                 break;
493         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
494                 mode = CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE;
495                 break;
496         case CONNMAN_DEVICE_TYPE_CELLULAR:
497                 mode = CONNMAN_DEVICE_MODE_NETWORK_SINGLE;
498                 ident = index2ident(index, NULL);
499                 break;
500         }
501
502         connman_device_set_mode(device, mode);
503
504         connman_device_set_index(device, index);
505         connman_device_set_interface(device, devname, node);
506
507         if (ident != NULL) {
508                 connman_device_set_ident(device, ident);
509                 free(ident);
510         }
511
512         connman_device_set_string(device, "Address", addr);
513
514 done:
515         g_free(devname);
516         g_free(node);
517         free(name);
518         free(addr);
519
520         return device;
521 }
522
523 struct in6_ifreq {
524         struct in6_addr ifr6_addr;
525         __u32 ifr6_prefixlen;
526         unsigned int ifr6_ifindex;
527 };
528
529 int connman_inet_set_ipv6_address(int index,
530                 struct connman_ipaddress *ipaddress)
531 {
532         unsigned char prefix_len;
533         const char *address;
534
535         if (ipaddress->local == NULL)
536                 return 0;
537
538         prefix_len = ipaddress->prefixlen;
539         address = ipaddress->local;
540
541         DBG("index %d address %s prefix_len %d", index, address, prefix_len);
542
543         if ((__connman_inet_modify_address(RTM_NEWADDR,
544                         NLM_F_REPLACE | NLM_F_ACK, index, AF_INET6,
545                         address, prefix_len, NULL)) < 0) {
546                 connman_error("Set IPv6 address error");
547                 return -1;
548         }
549
550         return 0;
551 }
552
553 int connman_inet_set_address(int index, struct connman_ipaddress *ipaddress)
554 {
555         unsigned char prefix_len;
556         const char *address, *broadcast;
557
558         if (ipaddress->local == NULL)
559                 return -1;
560
561         prefix_len = ipaddress->prefixlen;
562         address = ipaddress->local;
563         broadcast = ipaddress->broadcast;
564
565         DBG("index %d address %s prefix_len %d", index, address, prefix_len);
566
567         if ((__connman_inet_modify_address(RTM_NEWADDR,
568                         NLM_F_REPLACE | NLM_F_ACK, index, AF_INET,
569                         address, prefix_len, broadcast)) < 0) {
570                 DBG("address setting failed");
571                 return -1;
572         }
573
574         return 0;
575 }
576
577 int connman_inet_clear_ipv6_address(int index, const char *address,
578                                                         int prefix_len)
579 {
580         DBG("index %d address %s prefix_len %d", index, address, prefix_len);
581
582         if ((__connman_inet_modify_address(RTM_DELADDR, 0, index, AF_INET6,
583                         address, prefix_len, NULL)) < 0) {
584                 connman_error("Clear IPv6 address error");
585                 return -1;
586         }
587
588         return 0;
589 }
590
591 int connman_inet_clear_address(int index, struct connman_ipaddress *ipaddress)
592 {
593         unsigned char prefix_len;
594         const char *address, *broadcast;
595
596         prefix_len = ipaddress->prefixlen;
597         address = ipaddress->local;
598         broadcast = ipaddress->broadcast;
599
600         DBG("index %d address %s prefix_len %d", index, address, prefix_len);
601
602         if ((__connman_inet_modify_address(RTM_DELADDR, 0, index, AF_INET,
603                         address, prefix_len, broadcast)) < 0) {
604                 DBG("address removal failed");
605                 return -1;
606         }
607
608         return 0;
609 }
610
611 int connman_inet_add_host_route(int index, const char *host, const char *gateway)
612 {
613         struct ifreq ifr;
614         struct rtentry rt;
615         struct sockaddr_in addr;
616         int sk, err;
617
618         sk = socket(PF_INET, SOCK_DGRAM, 0);
619         if (sk < 0)
620                 return -1;
621
622         memset(&ifr, 0, sizeof(ifr));
623         ifr.ifr_ifindex = index;
624
625         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
626                 close(sk);
627                 return -1;
628         }
629
630         DBG("ifname %s", ifr.ifr_name);
631
632         memset(&rt, 0, sizeof(rt));
633         rt.rt_flags = RTF_UP | RTF_HOST;
634         if (gateway != NULL)
635                 rt.rt_flags |= RTF_GATEWAY;
636
637         memset(&addr, 0, sizeof(addr));
638         addr.sin_family = AF_INET;
639         addr.sin_addr.s_addr = inet_addr(host);
640         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
641
642         memset(&addr, 0, sizeof(addr));
643         addr.sin_family = AF_INET;
644         if (gateway != NULL)
645                 addr.sin_addr.s_addr = inet_addr(gateway);
646         else
647                 addr.sin_addr.s_addr = INADDR_ANY;
648         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
649
650         memset(&addr, 0, sizeof(addr));
651         addr.sin_family = AF_INET;
652         addr.sin_addr.s_addr = INADDR_ANY;
653         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
654
655         rt.rt_dev = ifr.ifr_name;
656
657         err = ioctl(sk, SIOCADDRT, &rt);
658         if (err < 0)
659                 connman_error("Adding host route failed (%s)",
660                                                         strerror(errno));
661
662         close(sk);
663
664         return err;
665 }
666
667 int connman_inet_del_host_route(int index, const char *host)
668 {
669         struct ifreq ifr;
670         struct rtentry rt;
671         struct sockaddr_in addr;
672         int sk, err;
673
674         sk = socket(PF_INET, SOCK_DGRAM, 0);
675         if (sk < 0)
676                 return -1;
677
678         memset(&ifr, 0, sizeof(ifr));
679         ifr.ifr_ifindex = index;
680
681         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
682                 close(sk);
683                 return -1;
684         }
685
686         DBG("ifname %s", ifr.ifr_name);
687
688         memset(&rt, 0, sizeof(rt));
689         rt.rt_flags = RTF_UP | RTF_HOST;
690
691         memset(&addr, 0, sizeof(addr));
692         addr.sin_family = AF_INET;
693         addr.sin_addr.s_addr = inet_addr(host);
694         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
695
696         rt.rt_dev = ifr.ifr_name;
697
698         err = ioctl(sk, SIOCDELRT, &rt);
699         if (err < 0)
700                 connman_error("Deleting host route failed (%s)",
701                                                         strerror(errno));
702
703         close(sk);
704
705         return err;
706 }
707
708 int connman_inet_del_ipv6_host_route(int index, const char *host)
709 {
710         struct in6_rtmsg rt;
711         int sk, err;
712
713         DBG("index %d host %s", index, host);
714
715         if (host == NULL)
716                 return -EINVAL;
717
718         memset(&rt, 0, sizeof(rt));
719
720         rt.rtmsg_dst_len = 128;
721
722         err = inet_pton(AF_INET6, host, &rt.rtmsg_dst);
723         if (err < 0)
724                 goto out;
725
726         rt.rtmsg_flags = RTF_UP | RTF_HOST;
727
728         rt.rtmsg_metric = 1;
729         rt.rtmsg_ifindex = index;
730
731         sk = socket(AF_INET6, SOCK_DGRAM, 0);
732         if (sk < 0) {
733                 err = -1;
734                 goto out;
735         }
736
737         err = ioctl(sk, SIOCDELRT, &rt);
738         close(sk);
739 out:
740         if (err < 0)
741                 connman_error("Del IPv6 host route error");
742
743         return err;
744 }
745
746 int connman_inet_add_ipv6_host_route(int index, const char *host,
747                                                 const char *gateway)
748 {
749         struct in6_rtmsg rt;
750         int sk, err;
751
752         DBG("index %d host %s gateway %s", index, host, gateway);
753
754         if (host == NULL)
755                 return -EINVAL;
756
757         memset(&rt, 0, sizeof(rt));
758
759         rt.rtmsg_dst_len = 128;
760
761         err = inet_pton(AF_INET6, host, &rt.rtmsg_dst);
762         if (err < 0)
763                 goto out;
764
765         rt.rtmsg_flags = RTF_UP | RTF_HOST;
766
767         if (gateway != NULL) {
768                 rt.rtmsg_flags |= RTF_GATEWAY;
769                 inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway);
770         }
771
772         rt.rtmsg_metric = 1;
773         rt.rtmsg_ifindex = index;
774
775         sk = socket(AF_INET6, SOCK_DGRAM, 0);
776         if (sk < 0) {
777                 err = -1;
778                 goto out;
779         }
780
781         err = ioctl(sk, SIOCADDRT, &rt);
782         close(sk);
783 out:
784         if (err < 0)
785                 connman_error("Set IPv6 host route error");
786
787         return err;
788 }
789
790 int connman_inet_set_ipv6_gateway_address(int index, const char *gateway)
791 {
792         struct in6_rtmsg rt;
793         int sk, err;
794
795         DBG("index %d, gateway %s", index, gateway);
796
797         if (gateway == NULL)
798                 return -EINVAL;
799
800         memset(&rt, 0, sizeof(rt));
801
802         err = inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway);
803         if (err < 0)
804                 goto out;
805
806         rt.rtmsg_flags = RTF_UP | RTF_GATEWAY;
807         rt.rtmsg_metric = 1;
808         rt.rtmsg_dst_len = 0;
809         rt.rtmsg_ifindex = index;
810
811         sk = socket(AF_INET6, SOCK_DGRAM, 0);
812         if (sk < 0) {
813                 err = -1;
814                 goto out;
815         }
816
817         err = ioctl(sk, SIOCADDRT, &rt);
818         close(sk);
819 out:
820         if (err < 0)
821                 connman_error("Set default IPv6 gateway error");
822
823         return err;
824 }
825
826 int connman_inet_clear_ipv6_gateway_address(int index, const char *gateway)
827 {
828         struct in6_rtmsg rt;
829         int sk, err;
830
831         DBG("index %d, gateway %s", index, gateway);
832
833         if (gateway == NULL)
834                 return -EINVAL;
835
836         memset(&rt, 0, sizeof(rt));
837
838         err = inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway);
839         if (err < 0)
840                 goto out;
841
842         rt.rtmsg_flags = RTF_UP | RTF_GATEWAY;
843         rt.rtmsg_metric = 1;
844         rt.rtmsg_dst_len = 0;
845         rt.rtmsg_ifindex = index;
846
847         sk = socket(AF_INET6, SOCK_DGRAM, 0);
848         if (sk < 0) {
849                 err = -1;
850                 goto out;
851         }
852
853         err = ioctl(sk, SIOCDELRT, &rt);
854         close(sk);
855 out:
856         if (err < 0)
857                 connman_error("Clear default IPv6 gateway error");
858
859         return err;
860 }
861
862 int connman_inet_set_gateway_address(int index, const char *gateway)
863 {
864         struct ifreq ifr;
865         struct rtentry rt;
866         struct sockaddr_in addr;
867         int sk, err;
868
869         sk = socket(PF_INET, SOCK_DGRAM, 0);
870         if (sk < 0)
871                 return -1;
872
873         memset(&ifr, 0, sizeof(ifr));
874         ifr.ifr_ifindex = index;
875
876         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
877                 close(sk);
878                 return -1;
879         }
880
881         DBG("ifname %s", ifr.ifr_name);
882
883         memset(&rt, 0, sizeof(rt));
884         rt.rt_flags = RTF_UP | RTF_GATEWAY;
885
886         memset(&addr, 0, sizeof(addr));
887         addr.sin_family = AF_INET;
888         addr.sin_addr.s_addr = INADDR_ANY;
889         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
890
891         memset(&addr, 0, sizeof(addr));
892         addr.sin_family = AF_INET;
893         addr.sin_addr.s_addr = inet_addr(gateway);
894         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
895
896         memset(&addr, 0, sizeof(addr));
897         addr.sin_family = AF_INET;
898         addr.sin_addr.s_addr = INADDR_ANY;
899         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
900
901         err = ioctl(sk, SIOCADDRT, &rt);
902         if (err < 0)
903                 connman_error("Setting default gateway route failed (%s)",
904                                                         strerror(errno));
905
906         close(sk);
907
908         return err;
909 }
910
911 int connman_inet_set_gateway_interface(int index)
912 {
913         struct ifreq ifr;
914         struct rtentry rt;
915         struct sockaddr_in addr;
916         int sk, err;
917
918         DBG("");
919
920         sk = socket(PF_INET, SOCK_DGRAM, 0);
921         if (sk < 0)
922                 return -1;
923
924         memset(&ifr, 0, sizeof(ifr));
925         ifr.ifr_ifindex = index;
926
927         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
928                 close(sk);
929                 return -1;
930         }
931
932         DBG("ifname %s", ifr.ifr_name);
933
934         memset(&rt, 0, sizeof(rt));
935         rt.rt_flags = RTF_UP;
936
937         memset(&addr, 0, sizeof(addr));
938         addr.sin_family = AF_INET;
939         addr.sin_addr.s_addr = INADDR_ANY;
940
941         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
942         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
943         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
944
945         rt.rt_dev = ifr.ifr_name;
946
947         err = ioctl(sk, SIOCADDRT, &rt);
948         if (err < 0)
949                 connman_error("Setting default interface route failed (%s)",
950                                                         strerror(errno));
951         close(sk);
952
953         return err;
954 }
955
956 int connman_inet_clear_gateway_address(int index, const char *gateway)
957 {
958         struct ifreq ifr;
959         struct rtentry rt;
960         struct sockaddr_in addr;
961         int sk, err;
962
963         DBG("");
964
965         sk = socket(PF_INET, SOCK_DGRAM, 0);
966         if (sk < 0)
967                 return -1;
968
969         memset(&ifr, 0, sizeof(ifr));
970         ifr.ifr_ifindex = index;
971
972         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
973                 close(sk);
974                 return -1;
975         }
976
977         DBG("ifname %s", ifr.ifr_name);
978
979         memset(&rt, 0, sizeof(rt));
980         rt.rt_flags = RTF_UP | RTF_GATEWAY;
981
982         memset(&addr, 0, sizeof(addr));
983         addr.sin_family = AF_INET;
984         addr.sin_addr.s_addr = INADDR_ANY;
985         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
986
987         memset(&addr, 0, sizeof(addr));
988         addr.sin_family = AF_INET;
989         addr.sin_addr.s_addr = inet_addr(gateway);
990         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
991
992         memset(&addr, 0, sizeof(addr));
993         addr.sin_family = AF_INET;
994         addr.sin_addr.s_addr = INADDR_ANY;
995         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
996
997         err = ioctl(sk, SIOCDELRT, &rt);
998         if (err < 0)
999                 connman_error("Removing default gateway route failed (%s)",
1000                                                         strerror(errno));
1001
1002         close(sk);
1003
1004         return err;
1005 }
1006
1007 int connman_inet_clear_gateway_interface(int index)
1008 {
1009         struct ifreq ifr;
1010         struct rtentry rt;
1011         struct sockaddr_in addr;
1012         int sk, err;
1013
1014         DBG("");
1015
1016         sk = socket(PF_INET, SOCK_DGRAM, 0);
1017         if (sk < 0)
1018                 return -1;
1019
1020         memset(&ifr, 0, sizeof(ifr));
1021         ifr.ifr_ifindex = index;
1022
1023         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1024                 close(sk);
1025                 return -1;
1026         }
1027
1028         DBG("ifname %s", ifr.ifr_name);
1029
1030         memset(&rt, 0, sizeof(rt));
1031         rt.rt_flags = RTF_UP;
1032
1033         memset(&addr, 0, sizeof(addr));
1034         addr.sin_family = AF_INET;
1035         addr.sin_addr.s_addr = INADDR_ANY;
1036
1037         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1038         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1039         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1040
1041         rt.rt_dev = ifr.ifr_name;
1042
1043         err = ioctl(sk, SIOCDELRT, &rt);
1044         if (err < 0)
1045                 connman_error("Removing default interface route failed (%s)",
1046                                                         strerror(errno));
1047         close(sk);
1048
1049         return err;
1050 }
1051
1052 connman_bool_t connman_inet_compare_subnet(int index, const char *host)
1053 {
1054         struct ifreq ifr;
1055         struct in_addr _host_addr;
1056         in_addr_t host_addr, netmask_addr, if_addr;
1057         struct sockaddr_in *netmask, *addr;
1058         int sk;
1059
1060         DBG("host %s", host);
1061
1062         if (host == NULL)
1063                 return FALSE;
1064
1065         if (inet_aton(host, &_host_addr) == 0)
1066                 return -1;
1067         host_addr = _host_addr.s_addr;
1068
1069         sk = socket(PF_INET, SOCK_DGRAM, 0);
1070         if (sk < 0)
1071                 return FALSE;
1072
1073         memset(&ifr, 0, sizeof(ifr));
1074         ifr.ifr_ifindex = index;
1075
1076         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1077                 close(sk);
1078                 return FALSE;
1079         }
1080
1081         if (ioctl(sk, SIOCGIFNETMASK, &ifr) < 0) {
1082                 close(sk);
1083                 return FALSE;
1084         }
1085
1086         netmask = (struct sockaddr_in *)&ifr.ifr_netmask;
1087         netmask_addr = netmask->sin_addr.s_addr;
1088
1089         if (ioctl(sk, SIOCGIFADDR, &ifr) < 0) {
1090                 close(sk);
1091                 return FALSE;
1092         }
1093         addr = (struct sockaddr_in *)&ifr.ifr_addr;
1094         if_addr = addr->sin_addr.s_addr;
1095
1096         return ((if_addr & netmask_addr) == (host_addr & netmask_addr));
1097 }