12eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt/*
22eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * Copyright (C) 2012 The Android Open Source Project
32eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt *
42eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * Licensed under the Apache License, Version 2.0 (the "License");
52eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * you may not use this file except in compliance with the License.
62eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * You may obtain a copy of the License at
72eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt *
8329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy *	  http://www.apache.org/licenses/LICENSE-2.0
92eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt *
102eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * Unless required by applicable law or agreed to in writing, software
112eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * distributed under the License is distributed on an "AS IS" BASIS,
122eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * See the License for the specific language governing permissions and
142eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * limitations under the License.
152eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt */
162eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt
1737f2e371c43588ca3661584a79b6544de345189aLorenzo Colitti#include <dirent.h>
18aa1be2b3d24d99f3ccb98ff4fbb2a81b63587effDan Albert#include <errno.h>
195f4938fea4170d251a3eb23ffc6239cfd1604cc8Elliott Hughes#include <malloc.h>
202eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt
212eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#define LOG_TAG "InterfaceController"
225407e14fd3d81bb76f94221b4a359faa2806de65Dan Albert#include <base/file.h>
235407e14fd3d81bb76f94221b4a359faa2806de65Dan Albert#include <base/stringprintf.h>
242eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#include <cutils/log.h>
250ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti#include <logwrap/logwrap.h>
2670afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti
272eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#include "InterfaceController.h"
28a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandran#include "RouteController.h"
292eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt
305407e14fd3d81bb76f94221b4a359faa2806de65Dan Albertusing android::base::StringPrintf;
315407e14fd3d81bb76f94221b4a359faa2806de65Dan Albertusing android::base::WriteStringToFile;
325407e14fd3d81bb76f94221b4a359faa2806de65Dan Albert
33e1da484b30196cc6ec496407e32c67bcb5295becErik Klinenamespace {
34e1da484b30196cc6ec496407e32c67bcb5295becErik Kline
3537f2e371c43588ca3661584a79b6544de345189aLorenzo Colitticonst char ipv6_proc_path[] = "/proc/sys/net/ipv6/conf";
3637f2e371c43588ca3661584a79b6544de345189aLorenzo Colitti
37145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Klineconst char ipv4_neigh_conf_dir[] = "/proc/sys/net/ipv4/neigh";
38145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Kline
39145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Klineconst char ipv6_neigh_conf_dir[] = "/proc/sys/net/ipv6/neigh";
40145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Kline
416d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidtconst char sys_net_path[] = "/sys/class/net";
426d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt
430ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitticonst char wl_util_path[] = "/system/xbin/wlutil";
440ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti
45e1da484b30196cc6ec496407e32c67bcb5295becErik Klinebool isInterfaceName(const char *name) {
46e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    return strcmp(name, ".") &&
47e1da484b30196cc6ec496407e32c67bcb5295becErik Kline            strcmp(name, "..") &&
48e1da484b30196cc6ec496407e32c67bcb5295becErik Kline            strcmp(name, "default") &&
49e1da484b30196cc6ec496407e32c67bcb5295becErik Kline            strcmp(name, "all");
50e1da484b30196cc6ec496407e32c67bcb5295becErik Kline}
51e1da484b30196cc6ec496407e32c67bcb5295becErik Kline
52e1da484b30196cc6ec496407e32c67bcb5295becErik Klineint writeValueToPath(
53e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        const char* dirname, const char* subdirname, const char* basename,
54e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        const char* value) {
55e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    std::string path(StringPrintf("%s/%s/%s", dirname, subdirname, basename));
563f95777d2aafa6c0ac4671d55557cad0d04a223fErik Kline    return WriteStringToFile(value, path) ? 0 : -1;
57e1da484b30196cc6ec496407e32c67bcb5295becErik Kline}
58e1da484b30196cc6ec496407e32c67bcb5295becErik Kline
59e1da484b30196cc6ec496407e32c67bcb5295becErik Klinevoid setOnAllInterfaces(const char* dirname, const char* basename, const char* value) {
60e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    // Set the default value, which is used by any interfaces that are created in the future.
61e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    writeValueToPath(dirname, "default", basename, value);
62e1da484b30196cc6ec496407e32c67bcb5295becErik Kline
63e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    // Set the value on all the interfaces that currently exist.
64e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    DIR* dir = opendir(dirname);
65e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    if (!dir) {
66e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        ALOGE("Can't list %s: %s", dirname, strerror(errno));
67e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        return;
68e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    }
69e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    dirent* d;
70e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    while ((d = readdir(dir))) {
71e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        if ((d->d_type != DT_DIR) || !isInterfaceName(d->d_name)) {
72e1da484b30196cc6ec496407e32c67bcb5295becErik Kline            continue;
73e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        }
74e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        writeValueToPath(dirname, d->d_name, basename, value);
75e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    }
76e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    closedir(dir);
77e1da484b30196cc6ec496407e32c67bcb5295becErik Kline}
78e1da484b30196cc6ec496407e32c67bcb5295becErik Kline
797adf8d71b80a729354c358d7a0110651750db5f2Erik Klinevoid setIPv6UseOutgoingInterfaceAddrsOnly(const char *value) {
807adf8d71b80a729354c358d7a0110651750db5f2Erik Kline    setOnAllInterfaces(ipv6_proc_path, "use_oif_addrs_only", value);
817adf8d71b80a729354c358d7a0110651750db5f2Erik Kline}
827adf8d71b80a729354c358d7a0110651750db5f2Erik Kline
83e1da484b30196cc6ec496407e32c67bcb5295becErik Kline}  // namespace
84e1da484b30196cc6ec496407e32c67bcb5295becErik Kline
851604e18615f824adb2d54c36320069ba6fcb4796Sreeram RamachandranInterfaceController::InterfaceController() {
8637f2e371c43588ca3661584a79b6544de345189aLorenzo Colitti	// Initial IPv6 settings.
8737f2e371c43588ca3661584a79b6544de345189aLorenzo Colitti	// By default, accept_ra is set to 1 (accept RAs unless forwarding is on) on all interfaces.
8837f2e371c43588ca3661584a79b6544de345189aLorenzo Colitti	// This causes RAs to work or not work based on whether forwarding is on, and causes routes
8937f2e371c43588ca3661584a79b6544de345189aLorenzo Colitti	// learned from RAs to go away when forwarding is turned on. Make this behaviour predictable
9037f2e371c43588ca3661584a79b6544de345189aLorenzo Colitti	// by always setting accept_ra to 2.
9137f2e371c43588ca3661584a79b6544de345189aLorenzo Colitti	setAcceptRA("2");
9237f2e371c43588ca3661584a79b6544de345189aLorenzo Colitti
93a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandran	setAcceptRARouteTable(-RouteController::ROUTE_TABLE_OFFSET_FROM_INDEX);
9459273ede02fc91d2a3297547d959159c8c6f69f3Erik Kline
9559273ede02fc91d2a3297547d959159c8c6f69f3Erik Kline	// Enable optimistic DAD for IPv6 addresses on all interfaces.
9659273ede02fc91d2a3297547d959159c8c6f69f3Erik Kline	setIPv6OptimisticMode("1");
97145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Kline
98145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Kline	// Reduce the ARP/ND base reachable time from the default (30sec) to 15sec.
99145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Kline	setBaseReachableTimeMs(15 * 1000);
1007adf8d71b80a729354c358d7a0110651750db5f2Erik Kline
1017adf8d71b80a729354c358d7a0110651750db5f2Erik Kline	// When sending traffic via a given interface use only addresses configured
1027adf8d71b80a729354c358d7a0110651750db5f2Erik Kline        // on that interface as possible source addresses.
1037adf8d71b80a729354c358d7a0110651750db5f2Erik Kline	setIPv6UseOutgoingInterfaceAddrsOnly("1");
1042eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt}
1052eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt
106329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha LevitskiyInterfaceController::~InterfaceController() {
1072eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt}
10870afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti
10970afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colittiint InterfaceController::setEnableIPv6(const char *interface, const int on) {
110e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    if (!isIfaceName(interface)) {
111e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        errno = ENOENT;
112e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        return -1;
113e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    }
114e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    // When disable_ipv6 changes from 1 to 0, the kernel starts autoconf.
115e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    // When disable_ipv6 changes from 0 to 1, the kernel clears all autoconf
116e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    // addresses and routes and disables IPv6 on the interface.
117e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    const char *disable_ipv6 = on ? "0" : "1";
118e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    return writeValueToPath(ipv6_proc_path, interface, "disable_ipv6", disable_ipv6);
11970afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti}
12070afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti
12170afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colittiint InterfaceController::setIPv6PrivacyExtensions(const char *interface, const int on) {
122e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    if (!isIfaceName(interface)) {
123e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        errno = ENOENT;
124e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        return -1;
125e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    }
126e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    // 0: disable IPv6 privacy addresses
127e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    // 0: enable IPv6 privacy addresses and prefer them over non-privacy ones.
128e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    return writeValueToPath(ipv6_proc_path, interface, "use_tempaddr", on ? "2" : "0");
12970afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti}
13037f2e371c43588ca3661584a79b6544de345189aLorenzo Colitti
1310ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti// Enables or disables IPv6 ND offload. This is useful for 464xlat on wifi, IPv6 tethering, and
1320ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti// generally implementing IPv6 neighbour discovery and duplicate address detection properly.
1330ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti// TODO: This should be implemented in wpa_supplicant via driver commands instead.
1340ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colittiint InterfaceController::setIPv6NdOffload(char* interface, const int on) {
1350ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti    // Only supported on Broadcom chipsets via wlutil for now.
1360ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti    if (access(wl_util_path, X_OK) == 0) {
1370ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti        const char *argv[] = {
1380ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti            wl_util_path,
1390ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti            "-a",
1400ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti            interface,
1410ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti            "ndoe",
1420ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti            on ? "1" : "0"
1430ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti        };
1440ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti        int ret = android_fork_execvp(ARRAY_SIZE(argv), const_cast<char**>(argv), NULL,
1450ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti                                      false, false);
1460ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti        ALOGD("%s ND offload on %s: %d (%s)",
1470ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti              (on ? "enabling" : "disabling"), interface, ret, strerror(errno));
1480ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti        return ret;
1490ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti    } else {
1500ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti        return 0;
1510ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti    }
1520ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti}
1530ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti
154a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandranvoid InterfaceController::setAcceptRA(const char *value) {
155e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    setOnAllInterfaces(ipv6_proc_path, "accept_ra", value);
156a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandran}
157a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandran
158a01d6eff4316c6c10e81bd8d48ae85aa82b933e3Sreeram Ramachandran// |tableOrOffset| is interpreted as:
159a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandran//     If == 0: default. Routes go into RT6_TABLE_MAIN.
160a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandran//     If > 0: user set. Routes go into the specified table.
161a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandran//     If < 0: automatic. The absolute value is intepreted as an offset and added to the interface
162a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandran//             ID to get the table. If it's set to -1000, routes from interface ID 5 will go into
163a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandran//             table 1005, etc.
164a01d6eff4316c6c10e81bd8d48ae85aa82b933e3Sreeram Ramachandranvoid InterfaceController::setAcceptRARouteTable(int tableOrOffset) {
165e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    std::string value(StringPrintf("%d", tableOrOffset));
166e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    setOnAllInterfaces(ipv6_proc_path, "accept_ra_rt_table", value.c_str());
16737f2e371c43588ca3661584a79b6544de345189aLorenzo Colitti}
1686d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt
1696d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidtint InterfaceController::setMtu(const char *interface, const char *mtu)
1706d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt{
171e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    if (!isIfaceName(interface)) {
172e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        errno = ENOENT;
173e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        return -1;
174e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    }
175e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    return writeValueToPath(sys_net_path, interface, "mtu", mtu);
1766d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt}
17759273ede02fc91d2a3297547d959159c8c6f69f3Erik Kline
178145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Klinevoid InterfaceController::setBaseReachableTimeMs(unsigned int millis) {
179145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Kline    std::string value(StringPrintf("%u", millis));
180145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Kline    setOnAllInterfaces(ipv4_neigh_conf_dir, "base_reachable_time_ms", value.c_str());
181145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Kline    setOnAllInterfaces(ipv6_neigh_conf_dir, "base_reachable_time_ms", value.c_str());
182145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Kline}
183145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Kline
18459273ede02fc91d2a3297547d959159c8c6f69f3Erik Klinevoid InterfaceController::setIPv6OptimisticMode(const char *value) {
185e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    setOnAllInterfaces(ipv6_proc_path, "optimistic_dad", value);
186e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    setOnAllInterfaces(ipv6_proc_path, "use_optimistic", value);
18759273ede02fc91d2a3297547d959159c8c6f69f3Erik Kline}
188