5 * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
6 * Copyright (C) 2003-2005 Go-Core Project
7 * Copyright (C) 2003-2006 Helsinki University of Technology
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.
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.
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
34 #include <sys/ioctl.h>
35 #include <sys/socket.h>
36 #include <linux/sockios.h>
37 #include <arpa/inet.h>
38 #include <net/route.h>
39 #include <net/ethernet.h>
41 #include <net/if_arp.h>
42 #include <netinet/icmp6.h>
44 #include <linux/if_tun.h>
48 #define NLMSG_TAIL(nmsg) \
49 ((struct rtattr *) (((uint8_t*) (nmsg)) + \
50 NLMSG_ALIGN((nmsg)->nlmsg_len)))
52 static int add_rtattr(struct nlmsghdr *n, size_t max_length, int type,
53 const void *data, size_t data_length)
58 length = RTA_LENGTH(data_length);
60 if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(length) > max_length)
65 rta->rta_len = length;
66 memcpy(RTA_DATA(rta), data, data_length);
67 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(length);
72 int __connman_inet_modify_address(int cmd, int flags,
73 int index, int family,
76 unsigned char prefixlen,
77 const char *broadcast)
79 uint8_t request[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
80 NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
81 RTA_LENGTH(sizeof(struct in6_addr)) +
82 RTA_LENGTH(sizeof(struct in6_addr))];
84 struct nlmsghdr *header;
85 struct sockaddr_nl nl_addr;
86 struct ifaddrmsg *ifaddrmsg;
87 struct in6_addr ipv6_addr;
88 struct in_addr ipv4_addr, ipv4_dest, ipv4_bcast;
91 DBG("cmd %#x flags %#x index %d family %d address %s peer %s "
92 "prefixlen %hhu broadcast %s", cmd, flags, index, family,
93 address, peer, prefixlen, broadcast);
98 if (family != AF_INET && family != AF_INET6)
101 memset(&request, 0, sizeof(request));
103 header = (struct nlmsghdr *)request;
104 header->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
105 header->nlmsg_type = cmd;
106 header->nlmsg_flags = NLM_F_REQUEST | flags;
107 header->nlmsg_seq = 1;
109 ifaddrmsg = NLMSG_DATA(header);
110 ifaddrmsg->ifa_family = family;
111 ifaddrmsg->ifa_prefixlen = prefixlen;
112 ifaddrmsg->ifa_flags = IFA_F_PERMANENT;
113 ifaddrmsg->ifa_scope = RT_SCOPE_UNIVERSE;
114 ifaddrmsg->ifa_index = index;
116 if (family == AF_INET) {
117 if (inet_pton(AF_INET, address, &ipv4_addr) < 1)
120 if (broadcast != NULL)
121 inet_pton(AF_INET, broadcast, &ipv4_bcast);
123 ipv4_bcast.s_addr = ipv4_addr.s_addr |
124 htonl(0xfffffffflu >> prefixlen);
127 if (inet_pton(AF_INET, peer, &ipv4_dest) < 1)
130 if ((err = add_rtattr(header, sizeof(request),
132 &ipv4_dest, sizeof(ipv4_dest))) < 0)
136 if ((err = add_rtattr(header, sizeof(request), IFA_LOCAL,
137 &ipv4_addr, sizeof(ipv4_addr))) < 0)
140 if ((err = add_rtattr(header, sizeof(request), IFA_BROADCAST,
141 &ipv4_bcast, sizeof(ipv4_bcast))) < 0)
144 } else if (family == AF_INET6) {
145 if (inet_pton(AF_INET6, address, &ipv6_addr) < 1)
148 if ((err = add_rtattr(header, sizeof(request), IFA_LOCAL,
149 &ipv6_addr, sizeof(ipv6_addr))) < 0)
153 sk = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
157 memset(&nl_addr, 0, sizeof(nl_addr));
158 nl_addr.nl_family = AF_NETLINK;
160 if ((err = sendto(sk, request, header->nlmsg_len, 0,
161 (struct sockaddr *) &nl_addr, sizeof(nl_addr))) < 0)
172 int connman_inet_ifindex(const char *name)
180 sk = socket(PF_INET, SOCK_DGRAM, 0);
184 memset(&ifr, 0, sizeof(ifr));
185 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
187 err = ioctl(sk, SIOCGIFINDEX, &ifr);
194 return ifr.ifr_ifindex;
197 char *connman_inet_ifname(int index)
205 sk = socket(PF_INET, SOCK_DGRAM, 0);
209 memset(&ifr, 0, sizeof(ifr));
210 ifr.ifr_ifindex = index;
212 err = ioctl(sk, SIOCGIFNAME, &ifr);
219 return strdup(ifr.ifr_name);
222 short int connman_inet_ifflags(int index)
227 sk = socket(PF_INET, SOCK_DGRAM, 0);
231 memset(&ifr, 0, sizeof(ifr));
232 ifr.ifr_ifindex = index;
234 if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
239 if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
252 int connman_inet_ifup(int index)
257 sk = socket(PF_INET, SOCK_DGRAM, 0);
261 memset(&ifr, 0, sizeof(ifr));
262 ifr.ifr_ifindex = index;
264 if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
269 if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
274 if (ifr.ifr_flags & IFF_UP) {
279 ifr.ifr_flags |= IFF_UP;
281 if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0) {
294 int connman_inet_ifdown(int index)
299 sk = socket(PF_INET, SOCK_DGRAM, 0);
303 memset(&ifr, 0, sizeof(ifr));
304 ifr.ifr_ifindex = index;
306 if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
311 if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
316 if (!(ifr.ifr_flags & IFF_UP)) {
321 ifr.ifr_flags &= ~IFF_UP;
323 if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0)
334 static char *index2addr(int index)
337 struct ether_addr eth;
344 sk = socket(PF_INET, SOCK_DGRAM, 0);
348 memset(&ifr, 0, sizeof(ifr));
349 ifr.ifr_ifindex = index;
351 err = ioctl(sk, SIOCGIFNAME, &ifr);
354 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
365 memcpy(ð, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
366 snprintf(str, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
367 eth.ether_addr_octet[0],
368 eth.ether_addr_octet[1],
369 eth.ether_addr_octet[2],
370 eth.ether_addr_octet[3],
371 eth.ether_addr_octet[4],
372 eth.ether_addr_octet[5]);
377 static char *index2ident(int index, const char *prefix)
380 struct ether_addr eth;
387 sk = socket(PF_INET, SOCK_DGRAM, 0);
391 memset(&ifr, 0, sizeof(ifr));
392 ifr.ifr_ifindex = index;
394 err = ioctl(sk, SIOCGIFNAME, &ifr);
397 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
404 len = prefix ? strlen(prefix) + 18 : 18;
410 memcpy(ð, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
411 snprintf(str, len, "%s%02x%02x%02x%02x%02x%02x",
412 prefix ? prefix : "",
413 eth.ether_addr_octet[0],
414 eth.ether_addr_octet[1],
415 eth.ether_addr_octet[2],
416 eth.ether_addr_octet[3],
417 eth.ether_addr_octet[4],
418 eth.ether_addr_octet[5]);
423 connman_bool_t connman_inet_is_cfg80211(int index)
425 connman_bool_t result = FALSE;
426 char phy80211_path[PATH_MAX];
431 sk = socket(PF_INET, SOCK_DGRAM, 0);
435 memset(&ifr, 0, sizeof(ifr));
436 ifr.ifr_ifindex = index;
438 if (ioctl(sk, SIOCGIFNAME, &ifr) < 0)
441 snprintf(phy80211_path, PATH_MAX,
442 "/sys/class/net/%s/phy80211", ifr.ifr_name);
444 if (stat(phy80211_path, &st) == 0 && (st.st_mode & S_IFDIR))
453 struct connman_device *connman_inet_create_device(int index)
455 enum connman_device_type type;
456 struct connman_device *device;
457 char *devname, *ident = NULL;
458 char *addr = NULL, *name = NULL;
463 devname = connman_inet_ifname(index);
467 if (__connman_device_isfiltered(devname) == TRUE) {
468 connman_info("Ignoring interface %s (filtered)", devname);
473 type = __connman_rtnl_get_device_type(index);
476 case CONNMAN_DEVICE_TYPE_UNKNOWN:
477 connman_info("Ignoring interface %s (type unknown)", devname);
480 case CONNMAN_DEVICE_TYPE_ETHERNET:
481 case CONNMAN_DEVICE_TYPE_GADGET:
482 case CONNMAN_DEVICE_TYPE_WIFI:
483 case CONNMAN_DEVICE_TYPE_WIMAX:
484 name = index2ident(index, "");
485 addr = index2addr(index);
487 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
488 case CONNMAN_DEVICE_TYPE_CELLULAR:
489 case CONNMAN_DEVICE_TYPE_GPS:
490 case CONNMAN_DEVICE_TYPE_VENDOR:
491 name = strdup(devname);
495 device = connman_device_create(name, type);
500 case CONNMAN_DEVICE_TYPE_UNKNOWN:
501 case CONNMAN_DEVICE_TYPE_VENDOR:
502 case CONNMAN_DEVICE_TYPE_GPS:
504 case CONNMAN_DEVICE_TYPE_ETHERNET:
505 case CONNMAN_DEVICE_TYPE_GADGET:
506 ident = index2ident(index, NULL);
508 case CONNMAN_DEVICE_TYPE_WIFI:
509 case CONNMAN_DEVICE_TYPE_WIMAX:
510 ident = index2ident(index, NULL);
512 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
514 case CONNMAN_DEVICE_TYPE_CELLULAR:
515 ident = index2ident(index, NULL);
519 connman_device_set_index(device, index);
520 connman_device_set_interface(device, devname);
523 connman_device_set_ident(device, ident);
527 connman_device_set_string(device, "Address", addr);
538 struct in6_addr ifr6_addr;
539 __u32 ifr6_prefixlen;
540 unsigned int ifr6_ifindex;
543 int connman_inet_set_ipv6_address(int index,
544 struct connman_ipaddress *ipaddress)
547 unsigned char prefix_len;
550 if (ipaddress->local == NULL)
553 prefix_len = ipaddress->prefixlen;
554 address = ipaddress->local;
556 DBG("index %d address %s prefix_len %d", index, address, prefix_len);
558 err = __connman_inet_modify_address(RTM_NEWADDR,
559 NLM_F_REPLACE | NLM_F_ACK, index, AF_INET6,
560 address, NULL, prefix_len, NULL);
562 connman_error("%s: %s", __func__, strerror(-err));
569 int connman_inet_set_address(int index, struct connman_ipaddress *ipaddress)
572 unsigned char prefix_len;
573 const char *address, *broadcast, *peer;
575 if (ipaddress->local == NULL)
578 prefix_len = ipaddress->prefixlen;
579 address = ipaddress->local;
580 broadcast = ipaddress->broadcast;
581 peer = ipaddress->peer;
583 DBG("index %d address %s prefix_len %d", index, address, prefix_len);
585 err = __connman_inet_modify_address(RTM_NEWADDR,
586 NLM_F_REPLACE | NLM_F_ACK, index, AF_INET,
587 address, peer, prefix_len, broadcast);
589 connman_error("%s: %s", __func__, strerror(-err));
596 int connman_inet_clear_ipv6_address(int index, const char *address,
601 DBG("index %d address %s prefix_len %d", index, address, prefix_len);
603 err = __connman_inet_modify_address(RTM_DELADDR, 0, index, AF_INET6,
604 address, NULL, prefix_len, NULL);
606 connman_error("%s: %s", __func__, strerror(-err));
613 int connman_inet_clear_address(int index, struct connman_ipaddress *ipaddress)
616 unsigned char prefix_len;
617 const char *address, *broadcast, *peer;
619 prefix_len = ipaddress->prefixlen;
620 address = ipaddress->local;
621 broadcast = ipaddress->broadcast;
622 peer = ipaddress->peer;
624 DBG("index %d address %s prefix_len %d", index, address, prefix_len);
626 err = __connman_inet_modify_address(RTM_DELADDR, 0, index, AF_INET,
627 address, peer, prefix_len, broadcast);
629 connman_error("%s: %s", __func__, strerror(-err));
636 int connman_inet_add_host_route(int index, const char *host,
639 return connman_inet_add_network_route(index, host, gateway, NULL);
642 int connman_inet_del_host_route(int index, const char *host)
644 return connman_inet_del_network_route(index, host);
647 int connman_inet_add_network_route(int index, const char *host,
653 struct sockaddr_in addr;
656 sk = socket(PF_INET, SOCK_DGRAM, 0);
660 memset(&ifr, 0, sizeof(ifr));
661 ifr.ifr_ifindex = index;
663 if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
668 DBG("ifname %s", ifr.ifr_name);
670 memset(&rt, 0, sizeof(rt));
671 rt.rt_flags = RTF_UP;
673 rt.rt_flags |= RTF_GATEWAY;
675 rt.rt_flags |= RTF_HOST;
677 memset(&addr, 0, sizeof(addr));
678 addr.sin_family = AF_INET;
679 addr.sin_addr.s_addr = inet_addr(host);
680 memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
682 memset(&addr, 0, sizeof(addr));
683 addr.sin_family = AF_INET;
685 addr.sin_addr.s_addr = inet_addr(gateway);
687 addr.sin_addr.s_addr = INADDR_ANY;
688 memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
690 memset(&addr, 0, sizeof(addr));
691 addr.sin_family = AF_INET;
692 addr.sin_addr.s_addr = INADDR_ANY;
694 addr.sin_addr.s_addr = inet_addr(netmask);
696 addr.sin_addr.s_addr = INADDR_ANY;
697 memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
699 rt.rt_dev = ifr.ifr_name;
701 err = ioctl(sk, SIOCADDRT, &rt);
703 connman_error("Adding host route failed (%s)",
711 int connman_inet_del_network_route(int index, const char *host)
715 struct sockaddr_in addr;
718 sk = socket(PF_INET, SOCK_DGRAM, 0);
722 memset(&ifr, 0, sizeof(ifr));
723 ifr.ifr_ifindex = index;
725 if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
730 DBG("ifname %s", ifr.ifr_name);
732 memset(&rt, 0, sizeof(rt));
733 rt.rt_flags = RTF_UP | RTF_HOST;
735 memset(&addr, 0, sizeof(addr));
736 addr.sin_family = AF_INET;
737 addr.sin_addr.s_addr = inet_addr(host);
738 memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
740 rt.rt_dev = ifr.ifr_name;
742 err = ioctl(sk, SIOCDELRT, &rt);
744 connman_error("Deleting host route failed (%s)",
752 int connman_inet_del_ipv6_network_route(int index, const char *host,
753 unsigned char prefix_len)
758 DBG("index %d host %s", index, host);
763 memset(&rt, 0, sizeof(rt));
765 rt.rtmsg_dst_len = prefix_len;
767 err = inet_pton(AF_INET6, host, &rt.rtmsg_dst);
771 rt.rtmsg_flags = RTF_UP | RTF_HOST;
774 rt.rtmsg_ifindex = index;
776 sk = socket(AF_INET6, SOCK_DGRAM, 0);
782 err = ioctl(sk, SIOCDELRT, &rt);
786 connman_error("Del IPv6 host route error (%s)",
792 int connman_inet_del_ipv6_host_route(int index, const char *host)
794 return connman_inet_del_ipv6_network_route(index, host, 128);
797 int connman_inet_add_ipv6_network_route(int index, const char *host,
799 unsigned char prefix_len)
804 DBG("index %d host %s gateway %s", index, host, gateway);
809 memset(&rt, 0, sizeof(rt));
811 rt.rtmsg_dst_len = prefix_len;
813 err = inet_pton(AF_INET6, host, &rt.rtmsg_dst);
817 rt.rtmsg_flags = RTF_UP | RTF_HOST;
819 if (gateway != NULL) {
820 rt.rtmsg_flags |= RTF_GATEWAY;
821 inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway);
825 rt.rtmsg_ifindex = index;
827 sk = socket(AF_INET6, SOCK_DGRAM, 0);
833 err = ioctl(sk, SIOCADDRT, &rt);
837 connman_error("Set IPv6 host route error (%s)",
843 int connman_inet_add_ipv6_host_route(int index, const char *host,
846 return connman_inet_add_ipv6_network_route(index, host, gateway, 128);
849 int connman_inet_set_ipv6_gateway_address(int index, const char *gateway)
854 DBG("index %d, gateway %s", index, gateway);
859 memset(&rt, 0, sizeof(rt));
861 err = inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway);
865 rt.rtmsg_flags = RTF_UP | RTF_GATEWAY;
867 rt.rtmsg_dst_len = 0;
868 rt.rtmsg_ifindex = index;
870 sk = socket(AF_INET6, SOCK_DGRAM, 0);
876 err = ioctl(sk, SIOCADDRT, &rt);
880 connman_error("Set default IPv6 gateway error (%s)",
886 int connman_inet_clear_ipv6_gateway_address(int index, const char *gateway)
891 DBG("index %d, gateway %s", index, gateway);
896 memset(&rt, 0, sizeof(rt));
898 err = inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway);
902 rt.rtmsg_flags = RTF_UP | RTF_GATEWAY;
904 rt.rtmsg_dst_len = 0;
905 rt.rtmsg_ifindex = index;
907 sk = socket(AF_INET6, SOCK_DGRAM, 0);
913 err = ioctl(sk, SIOCDELRT, &rt);
917 connman_error("Clear default IPv6 gateway error (%s)",
923 int connman_inet_set_gateway_address(int index, const char *gateway)
927 struct sockaddr_in addr;
930 sk = socket(PF_INET, SOCK_DGRAM, 0);
934 memset(&ifr, 0, sizeof(ifr));
935 ifr.ifr_ifindex = index;
937 if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
942 DBG("ifname %s", ifr.ifr_name);
944 memset(&rt, 0, sizeof(rt));
945 rt.rt_flags = RTF_UP | RTF_GATEWAY;
947 memset(&addr, 0, sizeof(addr));
948 addr.sin_family = AF_INET;
949 addr.sin_addr.s_addr = INADDR_ANY;
950 memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
952 memset(&addr, 0, sizeof(addr));
953 addr.sin_family = AF_INET;
954 addr.sin_addr.s_addr = inet_addr(gateway);
955 memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
957 memset(&addr, 0, sizeof(addr));
958 addr.sin_family = AF_INET;
959 addr.sin_addr.s_addr = INADDR_ANY;
960 memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
962 err = ioctl(sk, SIOCADDRT, &rt);
964 connman_error("Setting default gateway route failed (%s)",
972 int connman_inet_set_gateway_interface(int index)
976 struct sockaddr_in addr;
981 sk = socket(PF_INET, SOCK_DGRAM, 0);
985 memset(&ifr, 0, sizeof(ifr));
986 ifr.ifr_ifindex = index;
988 if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
993 DBG("ifname %s", ifr.ifr_name);
995 memset(&rt, 0, sizeof(rt));
996 rt.rt_flags = RTF_UP;
998 memset(&addr, 0, sizeof(addr));
999 addr.sin_family = AF_INET;
1000 addr.sin_addr.s_addr = INADDR_ANY;
1002 memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1003 memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1004 memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1006 rt.rt_dev = ifr.ifr_name;
1008 err = ioctl(sk, SIOCADDRT, &rt);
1010 connman_error("Setting default interface route failed (%s)",
1017 int connman_inet_set_ipv6_gateway_interface(int index)
1021 struct sockaddr_in6 addr;
1022 const struct in6_addr any = IN6ADDR_ANY_INIT;
1027 sk = socket(PF_INET6, SOCK_DGRAM, 0);
1031 memset(&ifr, 0, sizeof(ifr));
1032 ifr.ifr_ifindex = index;
1034 if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1039 DBG("ifname %s", ifr.ifr_name);
1041 memset(&rt, 0, sizeof(rt));
1042 rt.rt_flags = RTF_UP;
1044 memset(&addr, 0, sizeof(addr));
1045 addr.sin6_family = AF_INET6;
1046 addr.sin6_addr = any;
1048 memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1049 memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1050 memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1052 rt.rt_dev = ifr.ifr_name;
1054 err = ioctl(sk, SIOCADDRT, &rt);
1056 connman_error("Setting default interface route failed (%s)",
1063 int connman_inet_clear_gateway_address(int index, const char *gateway)
1067 struct sockaddr_in addr;
1072 sk = socket(PF_INET, SOCK_DGRAM, 0);
1076 memset(&ifr, 0, sizeof(ifr));
1077 ifr.ifr_ifindex = index;
1079 if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1084 DBG("ifname %s", ifr.ifr_name);
1086 memset(&rt, 0, sizeof(rt));
1087 rt.rt_flags = RTF_UP | RTF_GATEWAY;
1089 memset(&addr, 0, sizeof(addr));
1090 addr.sin_family = AF_INET;
1091 addr.sin_addr.s_addr = INADDR_ANY;
1092 memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1094 memset(&addr, 0, sizeof(addr));
1095 addr.sin_family = AF_INET;
1096 addr.sin_addr.s_addr = inet_addr(gateway);
1097 memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1099 memset(&addr, 0, sizeof(addr));
1100 addr.sin_family = AF_INET;
1101 addr.sin_addr.s_addr = INADDR_ANY;
1102 memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1104 err = ioctl(sk, SIOCDELRT, &rt);
1106 connman_error("Removing default gateway route failed (%s)",
1114 int connman_inet_clear_gateway_interface(int index)
1118 struct sockaddr_in addr;
1123 sk = socket(PF_INET, SOCK_DGRAM, 0);
1127 memset(&ifr, 0, sizeof(ifr));
1128 ifr.ifr_ifindex = index;
1130 if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1135 DBG("ifname %s", ifr.ifr_name);
1137 memset(&rt, 0, sizeof(rt));
1138 rt.rt_flags = RTF_UP;
1140 memset(&addr, 0, sizeof(addr));
1141 addr.sin_family = AF_INET;
1142 addr.sin_addr.s_addr = INADDR_ANY;
1144 memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1145 memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1146 memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1148 rt.rt_dev = ifr.ifr_name;
1150 err = ioctl(sk, SIOCDELRT, &rt);
1152 connman_error("Removing default interface route failed (%s)",
1159 int connman_inet_clear_ipv6_gateway_interface(int index)
1163 struct sockaddr_in6 addr;
1164 const struct in6_addr any = IN6ADDR_ANY_INIT;
1169 sk = socket(PF_INET6, SOCK_DGRAM, 0);
1173 memset(&ifr, 0, sizeof(ifr));
1174 ifr.ifr_ifindex = index;
1176 if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1181 DBG("ifname %s", ifr.ifr_name);
1183 memset(&rt, 0, sizeof(rt));
1184 rt.rt_flags = RTF_UP;
1186 memset(&addr, 0, sizeof(addr));
1187 addr.sin6_family = AF_INET6;
1188 addr.sin6_addr = any;
1190 memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1191 memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1192 memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1194 rt.rt_dev = ifr.ifr_name;
1196 err = ioctl(sk, SIOCDELRT, &rt);
1198 connman_error("Removing default interface route failed (%s)",
1205 connman_bool_t connman_inet_compare_subnet(int index, const char *host)
1208 struct in_addr _host_addr;
1209 in_addr_t host_addr, netmask_addr, if_addr;
1210 struct sockaddr_in *netmask, *addr;
1213 DBG("host %s", host);
1218 if (inet_aton(host, &_host_addr) == 0)
1220 host_addr = _host_addr.s_addr;
1222 sk = socket(PF_INET, SOCK_DGRAM, 0);
1226 memset(&ifr, 0, sizeof(ifr));
1227 ifr.ifr_ifindex = index;
1229 if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
1234 if (ioctl(sk, SIOCGIFNETMASK, &ifr) < 0) {
1239 netmask = (struct sockaddr_in *)&ifr.ifr_netmask;
1240 netmask_addr = netmask->sin_addr.s_addr;
1242 if (ioctl(sk, SIOCGIFADDR, &ifr) < 0) {
1246 addr = (struct sockaddr_in *)&ifr.ifr_addr;
1247 if_addr = addr->sin_addr.s_addr;
1249 return ((if_addr & netmask_addr) == (host_addr & netmask_addr));
1252 int connman_inet_remove_from_bridge(int index, const char *bridge)
1260 sk = socket(AF_INET, SOCK_STREAM, 0);
1264 memset(&ifr, 0, sizeof(ifr));
1265 strncpy(ifr.ifr_name, bridge, IFNAMSIZ - 1);
1266 ifr.ifr_ifindex = index;
1268 err = ioctl(sk, SIOCBRDELIF, &ifr);
1273 connman_error("Remove interface from bridge error %s",
1281 int connman_inet_add_to_bridge(int index, const char *bridge)
1289 sk = socket(AF_INET, SOCK_STREAM, 0);
1293 memset(&ifr, 0, sizeof(ifr));
1294 strncpy(ifr.ifr_name, bridge, IFNAMSIZ - 1);
1295 ifr.ifr_ifindex = index;
1297 err = ioctl(sk, SIOCBRADDIF, &ifr);
1302 connman_error("Add interface to bridge error %s",
1310 int connman_inet_set_mtu(int index, int mtu)
1315 sk = socket(AF_INET, SOCK_DGRAM, 0);
1319 memset(&ifr, 0, sizeof(ifr));
1320 ifr.ifr_ifindex = index;
1322 err = ioctl(sk, SIOCGIFNAME, &ifr);
1325 err = ioctl(sk, SIOCSIFMTU, &ifr);
1332 int connman_inet_setup_tunnel(char *tunnel, int mtu)
1342 sk = socket(AF_INET, SOCK_DGRAM, 0);
1346 index = if_nametoindex(tunnel);
1348 err = connman_inet_set_mtu(index, mtu);
1354 memset(&ifr, 0, sizeof(ifr));
1355 strncpy(ifr.ifr_name, tunnel, IFNAMSIZ);
1356 err = ioctl(sk, SIOCGIFFLAGS, &ifr);
1363 if ((ifr.ifr_flags ^ flags) & mask) {
1364 ifr.ifr_flags &= ~mask;
1365 ifr.ifr_flags |= mask & flags;
1366 err = ioctl(sk, SIOCSIFFLAGS, &ifr);
1368 connman_error("SIOCSIFFLAGS failed: %s",
1377 int connman_inet_create_tunnel(char **iface)
1382 fd = open("/dev/net/tun", O_RDWR);
1385 connman_error("Failed to open /dev/net/tun: %s",
1390 memset(&ifr, 0, sizeof(ifr));
1391 ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
1393 for (i = 0; i < 256; i++) {
1394 sprintf(ifr.ifr_name, "tun%d", i);
1396 if (!ioctl(fd, TUNSETIFF, (void *)&ifr))
1401 connman_error("Failed to find available tun device");
1406 *iface = g_strdup(ifr.ifr_name);
1412 GIOChannel *channel;
1413 __connman_inet_rs_cb_t callback;
1414 struct sockaddr_in6 addr;
1419 #define CMSG_BUF_LEN 512
1420 #define IN6ADDR_ALL_NODES_MC_INIT \
1421 { { { 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0x1 } } } /* ff02::1 */
1422 #define IN6ADDR_ALL_ROUTERS_MC_INIT \
1423 { { { 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0x2 } } } /* ff02::2 */
1425 static const struct in6_addr in6addr_all_nodes_mc = IN6ADDR_ALL_NODES_MC_INIT;
1426 static const struct in6_addr in6addr_all_routers_mc =
1427 IN6ADDR_ALL_ROUTERS_MC_INIT;
1429 /* from netinet/in.h */
1430 struct in6_pktinfo {
1431 struct in6_addr ipi6_addr; /* src/dst IPv6 address */
1432 unsigned int ipi6_ifindex; /* send/recv interface index */
1435 static void rs_cleanup(struct rs_cb_data *data)
1437 g_io_channel_shutdown(data->channel, TRUE, NULL);
1438 g_io_channel_unref(data->channel);
1441 if (data->rs_timeout > 0)
1442 g_source_remove(data->rs_timeout);
1447 static gboolean rs_timeout_cb(gpointer user_data)
1449 struct rs_cb_data *data = user_data;
1451 DBG("user data %p", user_data);
1456 if (data->callback != NULL)
1457 data->callback(NULL, data->user_data);
1459 data->rs_timeout = 0;
1464 static int icmpv6_recv(int fd, gpointer user_data)
1468 unsigned char chdr[CMSG_BUF_LEN];
1469 unsigned char buf[1540];
1470 struct rs_cb_data *data = user_data;
1471 struct nd_router_advert *hdr;
1472 struct sockaddr_in6 saddr;
1477 iov.iov_len = sizeof(buf);
1480 mhdr.msg_name = (void *)&saddr;
1481 mhdr.msg_namelen = sizeof(struct sockaddr_in6);
1482 mhdr.msg_iov = &iov;
1483 mhdr.msg_iovlen = 1;
1484 mhdr.msg_control = (void *)chdr;
1485 mhdr.msg_controllen = CMSG_BUF_LEN;
1487 len = recvmsg(fd, &mhdr, 0);
1489 data->callback(NULL, data->user_data);
1493 hdr = (struct nd_router_advert *)buf;
1494 if (hdr->nd_ra_code != 0)
1497 data->callback(hdr, data->user_data);
1503 static gboolean icmpv6_event(GIOChannel *chan, GIOCondition cond,
1510 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
1513 fd = g_io_channel_unix_get_fd(chan);
1514 ret = icmpv6_recv(fd, data);
1521 /* Adapted from RFC 1071 "C" Implementation Example */
1522 static uint16_t csum(const void *phdr, const void *data, socklen_t datalen)
1524 register unsigned long sum = 0;
1529 /* caller must make sure datalen is even */
1531 addr = (uint16_t *)phdr;
1532 for (i = 0; i < 20; i++)
1536 addr = (uint16_t *)data;
1544 sum = (sum & 0xffff) + (sum >> 16);
1546 return (uint16_t)~sum;
1549 static int ndisc_send_unspec(int type, int oif, const struct in6_addr *dest)
1552 struct in6_addr src;
1553 struct in6_addr dst;
1555 uint8_t reserved[3];
1562 struct icmp6_hdr icmp;
1563 struct nd_neighbor_solicit ns;
1564 struct nd_router_solicit rs;
1569 struct cmsghdr *cmsg;
1570 struct in6_pktinfo *pinfo;
1571 struct sockaddr_in6 dst;
1572 char cbuf[CMSG_SPACE(sizeof(*pinfo))];
1574 int fd, datalen, ret;
1578 fd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
1582 memset(&frame, 0, sizeof(frame));
1583 memset(&dst, 0, sizeof(dst));
1585 datalen = sizeof(frame.i.rs); /* 8, csum() safe */
1586 dst.sin6_addr = *dest;
1588 /* Fill in the IPv6 header */
1589 frame.ip.ip6_vfc = 0x60;
1590 frame.ip.ip6_plen = htons(datalen);
1591 frame.ip.ip6_nxt = IPPROTO_ICMPV6;
1592 frame.ip.ip6_hlim = 255;
1593 frame.ip.ip6_dst = dst.sin6_addr;
1594 /* all other fields are already set to zero */
1596 /* Prepare pseudo header for csum */
1597 memset(&phdr, 0, sizeof(phdr));
1598 phdr.dst = dst.sin6_addr;
1599 phdr.plen = htonl(datalen);
1600 phdr.nxt = IPPROTO_ICMPV6;
1602 /* Fill in remaining ICMP header fields */
1603 frame.i.icmp.icmp6_type = type;
1604 frame.i.icmp.icmp6_cksum = csum(&phdr, &frame.i, datalen);
1606 iov.iov_base = &frame;
1607 iov.iov_len = sizeof(frame.ip) + datalen;
1609 dst.sin6_family = AF_INET6;
1610 msgh.msg_name = &dst;
1611 msgh.msg_namelen = sizeof(dst);
1612 msgh.msg_iov = &iov;
1613 msgh.msg_iovlen = 1;
1616 memset(cbuf, 0, CMSG_SPACE(sizeof(*pinfo)));
1617 cmsg = (struct cmsghdr *)cbuf;
1618 pinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
1619 pinfo->ipi6_ifindex = oif;
1621 cmsg->cmsg_len = CMSG_LEN(sizeof(*pinfo));
1622 cmsg->cmsg_level = IPPROTO_IPV6;
1623 cmsg->cmsg_type = IPV6_PKTINFO;
1624 msgh.msg_control = cmsg;
1625 msgh.msg_controllen = cmsg->cmsg_len;
1627 ret = sendmsg(fd, &msgh, 0);
1633 static inline void ipv6_addr_set(struct in6_addr *addr,
1634 uint32_t w1, uint32_t w2,
1635 uint32_t w3, uint32_t w4)
1637 addr->s6_addr32[0] = w1;
1638 addr->s6_addr32[1] = w2;
1639 addr->s6_addr32[2] = w3;
1640 addr->s6_addr32[3] = w4;
1643 static inline void ipv6_addr_solict_mult(const struct in6_addr *addr,
1644 struct in6_addr *solicited)
1646 ipv6_addr_set(solicited, htonl(0xFF020000), 0, htonl(0x1),
1647 htonl(0xFF000000) | addr->s6_addr32[3]);
1650 static int if_mc_group(int sock, int ifindex, const struct in6_addr *mc_addr,
1653 unsigned int val = 0;
1654 struct ipv6_mreq mreq;
1657 memset(&mreq, 0, sizeof(mreq));
1658 mreq.ipv6mr_interface = ifindex;
1659 mreq.ipv6mr_multiaddr = *mc_addr;
1661 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
1667 return setsockopt(sock, IPPROTO_IPV6, cmd, &mreq, sizeof(mreq));
1670 int __connman_inet_ipv6_send_rs(int index, int timeout,
1671 __connman_inet_rs_cb_t callback, void *user_data)
1673 struct rs_cb_data *data;
1674 struct icmp6_filter filter;
1675 struct in6_addr solicit;
1676 struct in6_addr dst = in6addr_all_routers_mc;
1684 data = g_try_malloc0(sizeof(struct rs_cb_data));
1688 data->callback = callback;
1689 data->user_data = user_data;
1690 data->rs_timeout = g_timeout_add_seconds(timeout, rs_timeout_cb, data);
1692 sk = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
1696 ICMP6_FILTER_SETBLOCKALL(&filter);
1697 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
1699 setsockopt(sk, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
1700 sizeof(struct icmp6_filter));
1702 ipv6_addr_solict_mult(&dst, &solicit);
1703 if_mc_group(sk, index, &in6addr_all_nodes_mc, IPV6_JOIN_GROUP);
1704 if_mc_group(sk, index, &solicit, IPV6_JOIN_GROUP);
1706 data->channel = g_io_channel_unix_new(sk);
1707 g_io_channel_set_close_on_unref(data->channel, TRUE);
1709 g_io_channel_set_encoding(data->channel, NULL, NULL);
1710 g_io_channel_set_buffered(data->channel, FALSE);
1712 g_io_add_watch(data->channel,
1713 G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
1714 icmpv6_event, data);
1716 ndisc_send_unspec(ND_ROUTER_SOLICIT, index, &dst);