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