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>
20b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline#include <sys/socket.h>
212eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt
2231e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz#include <functional>
2331e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz
242eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#define LOG_TAG "InterfaceController"
25bbd5626b3d0994ff0ecbfceac75f6dc4abfb55c6Elliott Hughes#include <android-base/file.h>
26bbd5626b3d0994ff0ecbfceac75f6dc4abfb55c6Elliott Hughes#include <android-base/stringprintf.h>
272eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#include <cutils/log.h>
280ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti#include <logwrap/logwrap.h>
29c296f098b63a986265ded8adf13118ba512a0fa7Erik Kline#include <netutils/ifc.h>
3070afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti
312eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#include "InterfaceController.h"
32a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandran#include "RouteController.h"
332eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt
345407e14fd3d81bb76f94221b4a359faa2806de65Dan Albertusing android::base::StringPrintf;
35b218a87e0777d3d2c93231e03ef7315d783e3279Erik Klineusing android::base::ReadFileToString;
365407e14fd3d81bb76f94221b4a359faa2806de65Dan Albertusing android::base::WriteStringToFile;
377035f228d17e925116b1b64a7c917b3196ab8818Lorenzo Colittiusing android::net::RouteController;
385407e14fd3d81bb76f94221b4a359faa2806de65Dan Albert
39e1da484b30196cc6ec496407e32c67bcb5295becErik Klinenamespace {
40e1da484b30196cc6ec496407e32c67bcb5295becErik Kline
4137f2e371c43588ca3661584a79b6544de345189aLorenzo Colitticonst char ipv6_proc_path[] = "/proc/sys/net/ipv6/conf";
4237f2e371c43588ca3661584a79b6544de345189aLorenzo Colitti
43145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Klineconst char ipv4_neigh_conf_dir[] = "/proc/sys/net/ipv4/neigh";
44145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Kline
45145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Klineconst char ipv6_neigh_conf_dir[] = "/proc/sys/net/ipv6/neigh";
46145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Kline
47b218a87e0777d3d2c93231e03ef7315d783e3279Erik Klineconst char proc_net_path[] = "/proc/sys/net";
486d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidtconst char sys_net_path[] = "/sys/class/net";
496d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt
50bdcba1127a8709566fdec49bc303234e0e8ee924Erik Klineconst char wl_util_path[] = "/vendor/xbin/wlutil";
510ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti
5231e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelzconstexpr int kRouteInfoMinPrefixLen = 48;
5331e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz
5431e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz// RFC 7421 prefix length.
5531e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelzconstexpr int kRouteInfoMaxPrefixLen = 64;
5631e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz
57b218a87e0777d3d2c93231e03ef7315d783e3279Erik Klineinline bool isNormalPathComponent(const char *component) {
58b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline    return (strcmp(component, ".") != 0) &&
59b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline           (strcmp(component, "..") != 0) &&
60b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline           (strchr(component, '/') == nullptr);
61b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline}
62b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline
63b218a87e0777d3d2c93231e03ef7315d783e3279Erik Klineinline bool isAddressFamilyPathComponent(const char *component) {
64b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline    return strcmp(component, "ipv4") == 0 || strcmp(component, "ipv6") == 0;
65b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline}
66b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline
67b218a87e0777d3d2c93231e03ef7315d783e3279Erik Klineinline bool isInterfaceName(const char *name) {
68b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline    return isNormalPathComponent(name) &&
69b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline           (strcmp(name, "default") != 0) &&
70b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline           (strcmp(name, "all") != 0);
71e1da484b30196cc6ec496407e32c67bcb5295becErik Kline}
72e1da484b30196cc6ec496407e32c67bcb5295becErik Kline
73e1da484b30196cc6ec496407e32c67bcb5295becErik Klineint writeValueToPath(
74e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        const char* dirname, const char* subdirname, const char* basename,
75e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        const char* value) {
76e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    std::string path(StringPrintf("%s/%s/%s", dirname, subdirname, basename));
773f95777d2aafa6c0ac4671d55557cad0d04a223fErik Kline    return WriteStringToFile(value, path) ? 0 : -1;
78e1da484b30196cc6ec496407e32c67bcb5295becErik Kline}
79e1da484b30196cc6ec496407e32c67bcb5295becErik Kline
8031e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz// Run @fn on each interface as well as 'default' in the path @dirname.
8131e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelzvoid forEachInterface(const std::string& dirname,
8231e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz                      std::function<void(const std::string& path, const std::string& iface)> fn) {
8331e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz    // Run on default, which controls the behavior of any interfaces that are created in the future.
8431e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz    fn(dirname, "default");
8531e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz    DIR* dir = opendir(dirname.c_str());
86e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    if (!dir) {
8731e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz        ALOGE("Can't list %s: %s", dirname.c_str(), strerror(errno));
88e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        return;
89e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    }
9031e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz    while (true) {
9131e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz        const dirent *ent = readdir(dir);
9231e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz        if (!ent) {
9331e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz            break;
9431e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz        }
9531e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz        if ((ent->d_type != DT_DIR) || !isInterfaceName(ent->d_name)) {
96e1da484b30196cc6ec496407e32c67bcb5295becErik Kline            continue;
97e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        }
9831e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz        fn(dirname, ent->d_name);
99e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    }
100e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    closedir(dir);
101e1da484b30196cc6ec496407e32c67bcb5295becErik Kline}
102e1da484b30196cc6ec496407e32c67bcb5295becErik Kline
10331e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelzvoid setOnAllInterfaces(const char* dirname, const char* basename, const char* value) {
10431e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz    auto fn = [basename, value](const std::string& path, const std::string& iface) {
10531e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz        writeValueToPath(path.c_str(), iface.c_str(), basename, value);
10631e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz    };
10731e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz    forEachInterface(dirname, fn);
10831e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz}
10931e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz
1107adf8d71b80a729354c358d7a0110651750db5f2Erik Klinevoid setIPv6UseOutgoingInterfaceAddrsOnly(const char *value) {
1117adf8d71b80a729354c358d7a0110651750db5f2Erik Kline    setOnAllInterfaces(ipv6_proc_path, "use_oif_addrs_only", value);
1127adf8d71b80a729354c358d7a0110651750db5f2Erik Kline}
1137adf8d71b80a729354c358d7a0110651750db5f2Erik Kline
114b218a87e0777d3d2c93231e03ef7315d783e3279Erik Klinestd::string getParameterPathname(
115b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline        const char *family, const char *which, const char *interface, const char *parameter) {
116b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline    if (!isAddressFamilyPathComponent(family)) {
117b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline        errno = EAFNOSUPPORT;
118b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline        return "";
119b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline    } else if (!isNormalPathComponent(which) ||
120b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline               !isInterfaceName(interface) ||
121b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline               !isNormalPathComponent(parameter)) {
122b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline        errno = EINVAL;
123b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline        return "";
124b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline    }
125b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline
126b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline    return StringPrintf("%s/%s/%s/%s/%s", proc_net_path, family, which, interface, parameter);
127b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline}
128b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline
12931e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelzvoid setAcceptIPv6RIO(int min, int max) {
13031e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz    auto fn = [min, max](const std::string& prefix, const std::string& iface) {
13131e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz        int rv = writeValueToPath(prefix.c_str(), iface.c_str(), "accept_ra_rt_info_min_plen",
13231e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz                                  std::to_string(min).c_str());
13331e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz        if (rv != 0) {
13431e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz            // Only update max_plen if the write to min_plen succeeded. This ordering will prevent
13531e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz            // RIOs from being accepted unless both min and max are written successfully.
13631e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz            return;
13731e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz        }
13831e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz        writeValueToPath(prefix.c_str(), iface.c_str(), "accept_ra_rt_info_max_plen",
13931e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz                         std::to_string(max).c_str());
14031e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz    };
14131e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz    forEachInterface(ipv6_proc_path, fn);
14231e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz}
14331e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz
144e1da484b30196cc6ec496407e32c67bcb5295becErik Kline}  // namespace
145e1da484b30196cc6ec496407e32c67bcb5295becErik Kline
1462c5aaa1876db659556c2e9605beccc670e6b7c0dErik Klinevoid InterfaceController::initializeAll() {
1472c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    // Initial IPv6 settings.
1482c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    // By default, accept_ra is set to 1 (accept RAs unless forwarding is on) on all interfaces.
1492c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    // This causes RAs to work or not work based on whether forwarding is on, and causes routes
1502c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    // learned from RAs to go away when forwarding is turned on. Make this behaviour predictable
1512c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    // by always setting accept_ra to 2.
1522c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    setAcceptRA("2");
15337f2e371c43588ca3661584a79b6544de345189aLorenzo Colitti
15431e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz    // Accept RIOs with prefix length in the closed interval [48, 64].
15531e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz    setAcceptIPv6RIO(kRouteInfoMinPrefixLen, kRouteInfoMaxPrefixLen);
15631e2599eeae7bc06b2ab4293a1a24b01d03512bcJoel Scherpelz
1572c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    setAcceptRARouteTable(-RouteController::ROUTE_TABLE_OFFSET_FROM_INDEX);
15859273ede02fc91d2a3297547d959159c8c6f69f3Erik Kline
1592c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    // Enable optimistic DAD for IPv6 addresses on all interfaces.
1602c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    setIPv6OptimisticMode("1");
161145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Kline
1622c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    // Reduce the ARP/ND base reachable time from the default (30sec) to 15sec.
1632c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    setBaseReachableTimeMs(15 * 1000);
1647adf8d71b80a729354c358d7a0110651750db5f2Erik Kline
1652c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    // When sending traffic via a given interface use only addresses configured
1662c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline       // on that interface as possible source addresses.
1672c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    setIPv6UseOutgoingInterfaceAddrsOnly("1");
1682eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt}
16970afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti
17070afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colittiint InterfaceController::setEnableIPv6(const char *interface, const int on) {
171e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    if (!isIfaceName(interface)) {
172e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        errno = ENOENT;
173e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        return -1;
174e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    }
175e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    // When disable_ipv6 changes from 1 to 0, the kernel starts autoconf.
176e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    // When disable_ipv6 changes from 0 to 1, the kernel clears all autoconf
177e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    // addresses and routes and disables IPv6 on the interface.
178e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    const char *disable_ipv6 = on ? "0" : "1";
179e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    return writeValueToPath(ipv6_proc_path, interface, "disable_ipv6", disable_ipv6);
18070afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti}
18170afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti
1822c5aaa1876db659556c2e9605beccc670e6b7c0dErik Klineint InterfaceController::setAcceptIPv6Ra(const char *interface, const int on) {
1832c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    if (!isIfaceName(interface)) {
1842c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline        errno = ENOENT;
1852c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline        return -1;
1862c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    }
1872c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    // Because forwarding can be enabled even when tethering is off, we always
1882c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    // use mode "2" (accept RAs, even if forwarding is enabled).
1892c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    const char *accept_ra = on ? "2" : "0";
1902c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    return writeValueToPath(ipv6_proc_path, interface, "accept_ra", accept_ra);
1912c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline}
1922c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline
1932c5aaa1876db659556c2e9605beccc670e6b7c0dErik Klineint InterfaceController::setAcceptIPv6Dad(const char *interface, const int on) {
1942c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    if (!isIfaceName(interface)) {
1952c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline        errno = ENOENT;
1962c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline        return -1;
1972c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    }
1982c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    const char *accept_dad = on ? "1" : "0";
1992c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline    return writeValueToPath(ipv6_proc_path, interface, "accept_dad", accept_dad);
2002c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline}
2012c5aaa1876db659556c2e9605beccc670e6b7c0dErik Kline
20259d8c48cee74679d2305c535ab61d4a6f8258c64Erik Klineint InterfaceController::setIPv6DadTransmits(const char *interface, const char *value) {
20359d8c48cee74679d2305c535ab61d4a6f8258c64Erik Kline    if (!isIfaceName(interface)) {
20459d8c48cee74679d2305c535ab61d4a6f8258c64Erik Kline        errno = ENOENT;
20559d8c48cee74679d2305c535ab61d4a6f8258c64Erik Kline        return -1;
20659d8c48cee74679d2305c535ab61d4a6f8258c64Erik Kline    }
20759d8c48cee74679d2305c535ab61d4a6f8258c64Erik Kline    return writeValueToPath(ipv6_proc_path, interface, "dad_transmits", value);
20859d8c48cee74679d2305c535ab61d4a6f8258c64Erik Kline}
20959d8c48cee74679d2305c535ab61d4a6f8258c64Erik Kline
21070afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colittiint InterfaceController::setIPv6PrivacyExtensions(const char *interface, const int on) {
211e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    if (!isIfaceName(interface)) {
212e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        errno = ENOENT;
213e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        return -1;
214e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    }
215e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    // 0: disable IPv6 privacy addresses
216e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    // 0: enable IPv6 privacy addresses and prefer them over non-privacy ones.
217e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    return writeValueToPath(ipv6_proc_path, interface, "use_tempaddr", on ? "2" : "0");
21870afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti}
21937f2e371c43588ca3661584a79b6544de345189aLorenzo Colitti
2200ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti// Enables or disables IPv6 ND offload. This is useful for 464xlat on wifi, IPv6 tethering, and
2210ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti// generally implementing IPv6 neighbour discovery and duplicate address detection properly.
2220ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti// TODO: This should be implemented in wpa_supplicant via driver commands instead.
2230ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colittiint InterfaceController::setIPv6NdOffload(char* interface, const int on) {
2240ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti    // Only supported on Broadcom chipsets via wlutil for now.
2250ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti    if (access(wl_util_path, X_OK) == 0) {
2260ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti        const char *argv[] = {
2270ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti            wl_util_path,
2280ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti            "-a",
2290ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti            interface,
2300ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti            "ndoe",
2310ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti            on ? "1" : "0"
2320ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti        };
2330ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti        int ret = android_fork_execvp(ARRAY_SIZE(argv), const_cast<char**>(argv), NULL,
2340ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti                                      false, false);
2350ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti        ALOGD("%s ND offload on %s: %d (%s)",
2360ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti              (on ? "enabling" : "disabling"), interface, ret, strerror(errno));
2370ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti        return ret;
2380ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti    } else {
2390ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti        return 0;
2400ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti    }
2410ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti}
2420ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti
243a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandranvoid InterfaceController::setAcceptRA(const char *value) {
244e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    setOnAllInterfaces(ipv6_proc_path, "accept_ra", value);
245a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandran}
246a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandran
247a01d6eff4316c6c10e81bd8d48ae85aa82b933e3Sreeram Ramachandran// |tableOrOffset| is interpreted as:
248a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandran//     If == 0: default. Routes go into RT6_TABLE_MAIN.
249a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandran//     If > 0: user set. Routes go into the specified table.
250a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandran//     If < 0: automatic. The absolute value is intepreted as an offset and added to the interface
251a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandran//             ID to get the table. If it's set to -1000, routes from interface ID 5 will go into
252a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandran//             table 1005, etc.
253a01d6eff4316c6c10e81bd8d48ae85aa82b933e3Sreeram Ramachandranvoid InterfaceController::setAcceptRARouteTable(int tableOrOffset) {
254e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    std::string value(StringPrintf("%d", tableOrOffset));
255e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    setOnAllInterfaces(ipv6_proc_path, "accept_ra_rt_table", value.c_str());
25637f2e371c43588ca3661584a79b6544de345189aLorenzo Colitti}
2576d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt
2586d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidtint InterfaceController::setMtu(const char *interface, const char *mtu)
2596d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt{
260e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    if (!isIfaceName(interface)) {
261e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        errno = ENOENT;
262e1da484b30196cc6ec496407e32c67bcb5295becErik Kline        return -1;
263e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    }
264e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    return writeValueToPath(sys_net_path, interface, "mtu", mtu);
2656d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt}
26659273ede02fc91d2a3297547d959159c8c6f69f3Erik Kline
267c296f098b63a986265ded8adf13118ba512a0fa7Erik Klineint InterfaceController::addAddress(const char *interface,
268c296f098b63a986265ded8adf13118ba512a0fa7Erik Kline        const char *addrString, int prefixLength) {
269c296f098b63a986265ded8adf13118ba512a0fa7Erik Kline    return ifc_add_address(interface, addrString, prefixLength);
270c296f098b63a986265ded8adf13118ba512a0fa7Erik Kline}
271c296f098b63a986265ded8adf13118ba512a0fa7Erik Kline
272c296f098b63a986265ded8adf13118ba512a0fa7Erik Klineint InterfaceController::delAddress(const char *interface,
273c296f098b63a986265ded8adf13118ba512a0fa7Erik Kline        const char *addrString, int prefixLength) {
274c296f098b63a986265ded8adf13118ba512a0fa7Erik Kline    return ifc_del_address(interface, addrString, prefixLength);
275c296f098b63a986265ded8adf13118ba512a0fa7Erik Kline}
276c296f098b63a986265ded8adf13118ba512a0fa7Erik Kline
277b218a87e0777d3d2c93231e03ef7315d783e3279Erik Klineint InterfaceController::getParameter(
278b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline        const char *family, const char *which, const char *interface, const char *parameter,
279b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline        std::string *value) {
280b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline    const std::string path(getParameterPathname(family, which, interface, parameter));
281b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline    if (path.empty()) {
282b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline        return -errno;
283b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline    }
284b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline    return ReadFileToString(path, value) ? 0 : -errno;
285b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline}
286b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline
287b218a87e0777d3d2c93231e03ef7315d783e3279Erik Klineint InterfaceController::setParameter(
288b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline        const char *family, const char *which, const char *interface, const char *parameter,
289b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline        const char *value) {
290b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline    const std::string path(getParameterPathname(family, which, interface, parameter));
291b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline    if (path.empty()) {
292b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline        return -errno;
293b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline    }
294b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline    return WriteStringToFile(value, path) ? 0 : -errno;
295b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline}
296b218a87e0777d3d2c93231e03ef7315d783e3279Erik Kline
297145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Klinevoid InterfaceController::setBaseReachableTimeMs(unsigned int millis) {
298145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Kline    std::string value(StringPrintf("%u", millis));
299145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Kline    setOnAllInterfaces(ipv4_neigh_conf_dir, "base_reachable_time_ms", value.c_str());
300145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Kline    setOnAllInterfaces(ipv6_neigh_conf_dir, "base_reachable_time_ms", value.c_str());
301145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Kline}
302145fd25509e08fb2d76fcff8d011e1aa9a2e6455Erik Kline
30359273ede02fc91d2a3297547d959159c8c6f69f3Erik Klinevoid InterfaceController::setIPv6OptimisticMode(const char *value) {
304e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    setOnAllInterfaces(ipv6_proc_path, "optimistic_dad", value);
305e1da484b30196cc6ec496407e32c67bcb5295becErik Kline    setOnAllInterfaces(ipv6_proc_path, "use_optimistic", value);
30659273ede02fc91d2a3297547d959159c8c6f69f3Erik Kline}
307