1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *	  http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <dirent.h>
18#include <errno.h>
19#include <malloc.h>
20#include <sys/socket.h>
21
22#include <functional>
23
24#define LOG_TAG "InterfaceController"
25#include <android-base/file.h>
26#include <android-base/stringprintf.h>
27#include <cutils/log.h>
28#include <logwrap/logwrap.h>
29#include <netutils/ifc.h>
30
31#include "InterfaceController.h"
32#include "RouteController.h"
33
34using android::base::StringPrintf;
35using android::base::ReadFileToString;
36using android::base::WriteStringToFile;
37using android::net::RouteController;
38
39namespace {
40
41const char ipv6_proc_path[] = "/proc/sys/net/ipv6/conf";
42
43const char ipv4_neigh_conf_dir[] = "/proc/sys/net/ipv4/neigh";
44
45const char ipv6_neigh_conf_dir[] = "/proc/sys/net/ipv6/neigh";
46
47const char proc_net_path[] = "/proc/sys/net";
48const char sys_net_path[] = "/sys/class/net";
49
50const char wl_util_path[] = "/vendor/xbin/wlutil";
51
52constexpr int kRouteInfoMinPrefixLen = 48;
53
54// RFC 7421 prefix length.
55constexpr int kRouteInfoMaxPrefixLen = 64;
56
57inline bool isNormalPathComponent(const char *component) {
58    return (strcmp(component, ".") != 0) &&
59           (strcmp(component, "..") != 0) &&
60           (strchr(component, '/') == nullptr);
61}
62
63inline bool isAddressFamilyPathComponent(const char *component) {
64    return strcmp(component, "ipv4") == 0 || strcmp(component, "ipv6") == 0;
65}
66
67inline bool isInterfaceName(const char *name) {
68    return isNormalPathComponent(name) &&
69           (strcmp(name, "default") != 0) &&
70           (strcmp(name, "all") != 0);
71}
72
73int writeValueToPath(
74        const char* dirname, const char* subdirname, const char* basename,
75        const char* value) {
76    std::string path(StringPrintf("%s/%s/%s", dirname, subdirname, basename));
77    return WriteStringToFile(value, path) ? 0 : -1;
78}
79
80// Run @fn on each interface as well as 'default' in the path @dirname.
81void forEachInterface(const std::string& dirname,
82                      std::function<void(const std::string& path, const std::string& iface)> fn) {
83    // Run on default, which controls the behavior of any interfaces that are created in the future.
84    fn(dirname, "default");
85    DIR* dir = opendir(dirname.c_str());
86    if (!dir) {
87        ALOGE("Can't list %s: %s", dirname.c_str(), strerror(errno));
88        return;
89    }
90    while (true) {
91        const dirent *ent = readdir(dir);
92        if (!ent) {
93            break;
94        }
95        if ((ent->d_type != DT_DIR) || !isInterfaceName(ent->d_name)) {
96            continue;
97        }
98        fn(dirname, ent->d_name);
99    }
100    closedir(dir);
101}
102
103void setOnAllInterfaces(const char* dirname, const char* basename, const char* value) {
104    auto fn = [basename, value](const std::string& path, const std::string& iface) {
105        writeValueToPath(path.c_str(), iface.c_str(), basename, value);
106    };
107    forEachInterface(dirname, fn);
108}
109
110void setIPv6UseOutgoingInterfaceAddrsOnly(const char *value) {
111    setOnAllInterfaces(ipv6_proc_path, "use_oif_addrs_only", value);
112}
113
114std::string getParameterPathname(
115        const char *family, const char *which, const char *interface, const char *parameter) {
116    if (!isAddressFamilyPathComponent(family)) {
117        errno = EAFNOSUPPORT;
118        return "";
119    } else if (!isNormalPathComponent(which) ||
120               !isInterfaceName(interface) ||
121               !isNormalPathComponent(parameter)) {
122        errno = EINVAL;
123        return "";
124    }
125
126    return StringPrintf("%s/%s/%s/%s/%s", proc_net_path, family, which, interface, parameter);
127}
128
129void setAcceptIPv6RIO(int min, int max) {
130    auto fn = [min, max](const std::string& prefix, const std::string& iface) {
131        int rv = writeValueToPath(prefix.c_str(), iface.c_str(), "accept_ra_rt_info_min_plen",
132                                  std::to_string(min).c_str());
133        if (rv != 0) {
134            // Only update max_plen if the write to min_plen succeeded. This ordering will prevent
135            // RIOs from being accepted unless both min and max are written successfully.
136            return;
137        }
138        writeValueToPath(prefix.c_str(), iface.c_str(), "accept_ra_rt_info_max_plen",
139                         std::to_string(max).c_str());
140    };
141    forEachInterface(ipv6_proc_path, fn);
142}
143
144}  // namespace
145
146void InterfaceController::initializeAll() {
147    // Initial IPv6 settings.
148    // By default, accept_ra is set to 1 (accept RAs unless forwarding is on) on all interfaces.
149    // This causes RAs to work or not work based on whether forwarding is on, and causes routes
150    // learned from RAs to go away when forwarding is turned on. Make this behaviour predictable
151    // by always setting accept_ra to 2.
152    setAcceptRA("2");
153
154    // Accept RIOs with prefix length in the closed interval [48, 64].
155    setAcceptIPv6RIO(kRouteInfoMinPrefixLen, kRouteInfoMaxPrefixLen);
156
157    setAcceptRARouteTable(-RouteController::ROUTE_TABLE_OFFSET_FROM_INDEX);
158
159    // Enable optimistic DAD for IPv6 addresses on all interfaces.
160    setIPv6OptimisticMode("1");
161
162    // Reduce the ARP/ND base reachable time from the default (30sec) to 15sec.
163    setBaseReachableTimeMs(15 * 1000);
164
165    // When sending traffic via a given interface use only addresses configured
166       // on that interface as possible source addresses.
167    setIPv6UseOutgoingInterfaceAddrsOnly("1");
168}
169
170int InterfaceController::setEnableIPv6(const char *interface, const int on) {
171    if (!isIfaceName(interface)) {
172        errno = ENOENT;
173        return -1;
174    }
175    // When disable_ipv6 changes from 1 to 0, the kernel starts autoconf.
176    // When disable_ipv6 changes from 0 to 1, the kernel clears all autoconf
177    // addresses and routes and disables IPv6 on the interface.
178    const char *disable_ipv6 = on ? "0" : "1";
179    return writeValueToPath(ipv6_proc_path, interface, "disable_ipv6", disable_ipv6);
180}
181
182int InterfaceController::setAcceptIPv6Ra(const char *interface, const int on) {
183    if (!isIfaceName(interface)) {
184        errno = ENOENT;
185        return -1;
186    }
187    // Because forwarding can be enabled even when tethering is off, we always
188    // use mode "2" (accept RAs, even if forwarding is enabled).
189    const char *accept_ra = on ? "2" : "0";
190    return writeValueToPath(ipv6_proc_path, interface, "accept_ra", accept_ra);
191}
192
193int InterfaceController::setAcceptIPv6Dad(const char *interface, const int on) {
194    if (!isIfaceName(interface)) {
195        errno = ENOENT;
196        return -1;
197    }
198    const char *accept_dad = on ? "1" : "0";
199    return writeValueToPath(ipv6_proc_path, interface, "accept_dad", accept_dad);
200}
201
202int InterfaceController::setIPv6DadTransmits(const char *interface, const char *value) {
203    if (!isIfaceName(interface)) {
204        errno = ENOENT;
205        return -1;
206    }
207    return writeValueToPath(ipv6_proc_path, interface, "dad_transmits", value);
208}
209
210int InterfaceController::setIPv6PrivacyExtensions(const char *interface, const int on) {
211    if (!isIfaceName(interface)) {
212        errno = ENOENT;
213        return -1;
214    }
215    // 0: disable IPv6 privacy addresses
216    // 0: enable IPv6 privacy addresses and prefer them over non-privacy ones.
217    return writeValueToPath(ipv6_proc_path, interface, "use_tempaddr", on ? "2" : "0");
218}
219
220// Enables or disables IPv6 ND offload. This is useful for 464xlat on wifi, IPv6 tethering, and
221// generally implementing IPv6 neighbour discovery and duplicate address detection properly.
222// TODO: This should be implemented in wpa_supplicant via driver commands instead.
223int InterfaceController::setIPv6NdOffload(char* interface, const int on) {
224    // Only supported on Broadcom chipsets via wlutil for now.
225    if (access(wl_util_path, X_OK) == 0) {
226        const char *argv[] = {
227            wl_util_path,
228            "-a",
229            interface,
230            "ndoe",
231            on ? "1" : "0"
232        };
233        int ret = android_fork_execvp(ARRAY_SIZE(argv), const_cast<char**>(argv), NULL,
234                                      false, false);
235        ALOGD("%s ND offload on %s: %d (%s)",
236              (on ? "enabling" : "disabling"), interface, ret, strerror(errno));
237        return ret;
238    } else {
239        return 0;
240    }
241}
242
243void InterfaceController::setAcceptRA(const char *value) {
244    setOnAllInterfaces(ipv6_proc_path, "accept_ra", value);
245}
246
247// |tableOrOffset| is interpreted as:
248//     If == 0: default. Routes go into RT6_TABLE_MAIN.
249//     If > 0: user set. Routes go into the specified table.
250//     If < 0: automatic. The absolute value is intepreted as an offset and added to the interface
251//             ID to get the table. If it's set to -1000, routes from interface ID 5 will go into
252//             table 1005, etc.
253void InterfaceController::setAcceptRARouteTable(int tableOrOffset) {
254    std::string value(StringPrintf("%d", tableOrOffset));
255    setOnAllInterfaces(ipv6_proc_path, "accept_ra_rt_table", value.c_str());
256}
257
258int InterfaceController::setMtu(const char *interface, const char *mtu)
259{
260    if (!isIfaceName(interface)) {
261        errno = ENOENT;
262        return -1;
263    }
264    return writeValueToPath(sys_net_path, interface, "mtu", mtu);
265}
266
267int InterfaceController::addAddress(const char *interface,
268        const char *addrString, int prefixLength) {
269    return ifc_add_address(interface, addrString, prefixLength);
270}
271
272int InterfaceController::delAddress(const char *interface,
273        const char *addrString, int prefixLength) {
274    return ifc_del_address(interface, addrString, prefixLength);
275}
276
277int InterfaceController::getParameter(
278        const char *family, const char *which, const char *interface, const char *parameter,
279        std::string *value) {
280    const std::string path(getParameterPathname(family, which, interface, parameter));
281    if (path.empty()) {
282        return -errno;
283    }
284    return ReadFileToString(path, value) ? 0 : -errno;
285}
286
287int InterfaceController::setParameter(
288        const char *family, const char *which, const char *interface, const char *parameter,
289        const char *value) {
290    const std::string path(getParameterPathname(family, which, interface, parameter));
291    if (path.empty()) {
292        return -errno;
293    }
294    return WriteStringToFile(value, path) ? 0 : -errno;
295}
296
297void InterfaceController::setBaseReachableTimeMs(unsigned int millis) {
298    std::string value(StringPrintf("%u", millis));
299    setOnAllInterfaces(ipv4_neigh_conf_dir, "base_reachable_time_ms", value.c_str());
300    setOnAllInterfaces(ipv6_neigh_conf_dir, "base_reachable_time_ms", value.c_str());
301}
302
303void InterfaceController::setIPv6OptimisticMode(const char *value) {
304    setOnAllInterfaces(ipv6_proc_path, "optimistic_dad", value);
305    setOnAllInterfaces(ipv6_proc_path, "use_optimistic", value);
306}
307