blob: 5a630255176181b92e6f373d59d06d9b82f81fef [file] [log] [blame]
Dmitry Shmidt2eab1f72012-07-26 16:08:02 -07001/*
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 *
Sasha Levitskiy329c3b42012-07-30 16:11:23 -07008 * http://www.apache.org/licenses/LICENSE-2.0
Dmitry Shmidt2eab1f72012-07-26 16:08:02 -07009 *
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
Lorenzo Colitti37f2e372013-04-12 00:44:06 +090017#include <dirent.h>
Dan Albertaa1be2b2015-01-06 09:36:17 -080018#include <errno.h>
Elliott Hughes5f4938f2015-01-28 11:22:38 -080019#include <malloc.h>
Chenbo Feng7e974052018-02-28 22:57:21 -080020#include <net/if.h>
Erik Klineb218a872016-07-04 09:57:18 +090021#include <sys/socket.h>
Dmitry Shmidt2eab1f72012-07-26 16:08:02 -070022
Joel Scherpelz31e25992017-03-24 12:40:00 +090023#include <functional>
24
Dmitry Shmidt2eab1f72012-07-26 16:08:02 -070025#define LOG_TAG "InterfaceController"
Elliott Hughesbbd56262015-12-04 15:45:10 -080026#include <android-base/file.h>
Joel Scherpelzde937962017-06-01 13:20:21 +090027#include <android-base/properties.h>
Elliott Hughesbbd56262015-12-04 15:45:10 -080028#include <android-base/stringprintf.h>
Dmitry Shmidt2eab1f72012-07-26 16:08:02 -070029#include <cutils/log.h>
Lorenzo Colitti0ea8ff82014-10-28 00:15:07 +090030#include <logwrap/logwrap.h>
Erik Klinec296f092016-08-02 15:22:53 +090031#include <netutils/ifc.h>
Lorenzo Colitti70afde62013-03-04 17:58:40 +090032
Joel Scherpelzde937962017-06-01 13:20:21 +090033#include <android/net/INetd.h>
34#include <netdutils/Misc.h>
35#include <netdutils/Slice.h>
36#include <netdutils/Syscalls.h>
37
Dmitry Shmidt2eab1f72012-07-26 16:08:02 -070038#include "InterfaceController.h"
Sreeram Ramachandrana4811802014-04-10 12:10:24 -070039#include "RouteController.h"
Dmitry Shmidt2eab1f72012-07-26 16:08:02 -070040
Erik Klineb218a872016-07-04 09:57:18 +090041using android::base::ReadFileToString;
Joel Scherpelzde937962017-06-01 13:20:21 +090042using android::base::StringPrintf;
Dan Albert5407e142015-03-16 10:05:59 -070043using android::base::WriteStringToFile;
Joel Scherpelzde937962017-06-01 13:20:21 +090044using android::net::INetd;
Lorenzo Colitti7035f222017-02-13 18:29:00 +090045using android::net::RouteController;
Joel Scherpelzde937962017-06-01 13:20:21 +090046using android::netdutils::Status;
47using android::netdutils::StatusOr;
48using android::netdutils::makeSlice;
49using android::netdutils::sSyscalls;
50using android::netdutils::status::ok;
51using android::netdutils::statusFromErrno;
52using android::netdutils::toString;
Dan Albert5407e142015-03-16 10:05:59 -070053
Erik Klinee1da4842015-05-12 15:56:06 +090054namespace {
55
Lorenzo Colitti37f2e372013-04-12 00:44:06 +090056const char ipv6_proc_path[] = "/proc/sys/net/ipv6/conf";
57
Erik Kline145fd252015-05-12 15:58:49 +090058const char ipv4_neigh_conf_dir[] = "/proc/sys/net/ipv4/neigh";
59
60const char ipv6_neigh_conf_dir[] = "/proc/sys/net/ipv6/neigh";
61
Erik Klineb218a872016-07-04 09:57:18 +090062const char proc_net_path[] = "/proc/sys/net";
Dmitry Shmidt6d6c0e62013-06-11 16:18:06 -070063const char sys_net_path[] = "/sys/class/net";
64
Joel Scherpelz31e25992017-03-24 12:40:00 +090065constexpr int kRouteInfoMinPrefixLen = 48;
66
67// RFC 7421 prefix length.
68constexpr int kRouteInfoMaxPrefixLen = 64;
69
Joel Scherpelzde937962017-06-01 13:20:21 +090070// Property used to persist RFC 7217 stable secret. Protected by SELinux policy.
71const char kStableSecretProperty[] = "persist.netd.stable_secret";
72
73// RFC 7217 stable secret on linux is formatted as an IPv6 address.
74// This function uses 128 bits of high quality entropy to generate an
75// address for this purpose. This function should be not be called
76// frequently.
77StatusOr<std::string> randomIPv6Address() {
78 in6_addr addr = {};
79 const auto& sys = sSyscalls.get();
80 ASSIGN_OR_RETURN(auto fd, sys.open("/dev/random", O_RDONLY));
81 RETURN_IF_NOT_OK(sys.read(fd, makeSlice(addr)));
82 return toString(addr);
83}
84
Erik Klineb218a872016-07-04 09:57:18 +090085inline bool isNormalPathComponent(const char *component) {
86 return (strcmp(component, ".") != 0) &&
87 (strcmp(component, "..") != 0) &&
88 (strchr(component, '/') == nullptr);
89}
90
91inline bool isAddressFamilyPathComponent(const char *component) {
92 return strcmp(component, "ipv4") == 0 || strcmp(component, "ipv6") == 0;
93}
94
95inline bool isInterfaceName(const char *name) {
96 return isNormalPathComponent(name) &&
97 (strcmp(name, "default") != 0) &&
98 (strcmp(name, "all") != 0);
Erik Klinee1da4842015-05-12 15:56:06 +090099}
100
101int writeValueToPath(
102 const char* dirname, const char* subdirname, const char* basename,
103 const char* value) {
104 std::string path(StringPrintf("%s/%s/%s", dirname, subdirname, basename));
Erik Kline3f957772015-06-03 17:44:24 +0900105 return WriteStringToFile(value, path) ? 0 : -1;
Erik Klinee1da4842015-05-12 15:56:06 +0900106}
107
Joel Scherpelz31e25992017-03-24 12:40:00 +0900108// Run @fn on each interface as well as 'default' in the path @dirname.
109void forEachInterface(const std::string& dirname,
110 std::function<void(const std::string& path, const std::string& iface)> fn) {
111 // Run on default, which controls the behavior of any interfaces that are created in the future.
112 fn(dirname, "default");
113 DIR* dir = opendir(dirname.c_str());
Erik Klinee1da4842015-05-12 15:56:06 +0900114 if (!dir) {
Joel Scherpelz31e25992017-03-24 12:40:00 +0900115 ALOGE("Can't list %s: %s", dirname.c_str(), strerror(errno));
Erik Klinee1da4842015-05-12 15:56:06 +0900116 return;
117 }
Joel Scherpelz31e25992017-03-24 12:40:00 +0900118 while (true) {
119 const dirent *ent = readdir(dir);
120 if (!ent) {
121 break;
122 }
123 if ((ent->d_type != DT_DIR) || !isInterfaceName(ent->d_name)) {
Erik Klinee1da4842015-05-12 15:56:06 +0900124 continue;
125 }
Joel Scherpelz31e25992017-03-24 12:40:00 +0900126 fn(dirname, ent->d_name);
Erik Klinee1da4842015-05-12 15:56:06 +0900127 }
128 closedir(dir);
129}
130
Joel Scherpelz31e25992017-03-24 12:40:00 +0900131void setOnAllInterfaces(const char* dirname, const char* basename, const char* value) {
132 auto fn = [basename, value](const std::string& path, const std::string& iface) {
133 writeValueToPath(path.c_str(), iface.c_str(), basename, value);
134 };
135 forEachInterface(dirname, fn);
136}
137
Erik Kline7adf8d72015-07-28 18:51:01 +0900138void setIPv6UseOutgoingInterfaceAddrsOnly(const char *value) {
139 setOnAllInterfaces(ipv6_proc_path, "use_oif_addrs_only", value);
140}
141
Erik Klineb218a872016-07-04 09:57:18 +0900142std::string getParameterPathname(
143 const char *family, const char *which, const char *interface, const char *parameter) {
144 if (!isAddressFamilyPathComponent(family)) {
145 errno = EAFNOSUPPORT;
146 return "";
147 } else if (!isNormalPathComponent(which) ||
148 !isInterfaceName(interface) ||
149 !isNormalPathComponent(parameter)) {
150 errno = EINVAL;
151 return "";
152 }
153
154 return StringPrintf("%s/%s/%s/%s/%s", proc_net_path, family, which, interface, parameter);
155}
156
Joel Scherpelz31e25992017-03-24 12:40:00 +0900157void setAcceptIPv6RIO(int min, int max) {
158 auto fn = [min, max](const std::string& prefix, const std::string& iface) {
159 int rv = writeValueToPath(prefix.c_str(), iface.c_str(), "accept_ra_rt_info_min_plen",
160 std::to_string(min).c_str());
161 if (rv != 0) {
162 // Only update max_plen if the write to min_plen succeeded. This ordering will prevent
163 // RIOs from being accepted unless both min and max are written successfully.
164 return;
165 }
166 writeValueToPath(prefix.c_str(), iface.c_str(), "accept_ra_rt_info_max_plen",
167 std::to_string(max).c_str());
168 };
169 forEachInterface(ipv6_proc_path, fn);
170}
171
Joel Scherpelzde937962017-06-01 13:20:21 +0900172// Ideally this function would return StatusOr<std::string>, however
173// there is no safe value for dflt that will always differ from the
174// stored property. Bugs code could conceivably end up persisting the
175// reserved value resulting in surprising behavior.
176std::string getProperty(const std::string& key, const std::string& dflt) {
177 return android::base::GetProperty(key, dflt);
178};
179
180Status setProperty(const std::string& key, const std::string& val) {
Lorenzo Colitti516764f2017-07-10 19:13:23 +0900181 // SetProperty does not dependably set errno to a meaningful value. Use our own error code so
182 // callers don't get confused.
Joel Scherpelzde937962017-06-01 13:20:21 +0900183 return android::base::SetProperty(key, val)
184 ? ok
Lorenzo Colitti516764f2017-07-10 19:13:23 +0900185 : statusFromErrno(EREMOTEIO, "SetProperty failed, see libc logs");
Joel Scherpelzde937962017-06-01 13:20:21 +0900186};
187
188
Erik Klinee1da4842015-05-12 15:56:06 +0900189} // namespace
190
Joel Scherpelzde937962017-06-01 13:20:21 +0900191android::netdutils::Status InterfaceController::enableStablePrivacyAddresses(
192 const std::string& iface, GetPropertyFn getProperty, SetPropertyFn setProperty) {
193 const auto& sys = sSyscalls.get();
194 const std::string procTarget = std::string(ipv6_proc_path) + "/" + iface + "/stable_secret";
195 auto procFd = sys.open(procTarget, O_CLOEXEC | O_WRONLY);
196
197 // Devices with old kernels (typically < 4.4) don't support
198 // RFC 7217 stable privacy addresses.
199 if (equalToErrno(procFd, ENOENT)) {
200 return statusFromErrno(EOPNOTSUPP,
201 "Failed to open stable_secret. Assuming unsupported kernel version");
202 }
203
204 // If stable_secret exists but we can't open it, something strange is going on.
205 RETURN_IF_NOT_OK(procFd);
206
207 const char kUninitialized[] = "uninitialized";
208 const auto oldSecret = getProperty(kStableSecretProperty, kUninitialized);
209 std::string secret = oldSecret;
210
211 // Generate a new secret if no persistent property existed.
212 if (oldSecret == kUninitialized) {
213 ASSIGN_OR_RETURN(secret, randomIPv6Address());
214 }
215
216 // Ask the OS to generate SLAAC addresses on iface using secret.
217 RETURN_IF_NOT_OK(sys.write(procFd.value(), makeSlice(secret)));
218
219 // Don't persist an existing secret.
220 if (oldSecret != kUninitialized) {
221 return ok;
222 }
223
224 return setProperty(kStableSecretProperty, secret);
225}
226
Erik Kline2c5aaa12016-06-08 13:24:45 +0900227void InterfaceController::initializeAll() {
228 // Initial IPv6 settings.
229 // By default, accept_ra is set to 1 (accept RAs unless forwarding is on) on all interfaces.
230 // This causes RAs to work or not work based on whether forwarding is on, and causes routes
231 // learned from RAs to go away when forwarding is turned on. Make this behaviour predictable
232 // by always setting accept_ra to 2.
233 setAcceptRA("2");
Lorenzo Colitti37f2e372013-04-12 00:44:06 +0900234
Joel Scherpelz31e25992017-03-24 12:40:00 +0900235 // Accept RIOs with prefix length in the closed interval [48, 64].
236 setAcceptIPv6RIO(kRouteInfoMinPrefixLen, kRouteInfoMaxPrefixLen);
237
Erik Kline2c5aaa12016-06-08 13:24:45 +0900238 setAcceptRARouteTable(-RouteController::ROUTE_TABLE_OFFSET_FROM_INDEX);
Erik Kline59273ed2014-12-08 16:05:28 +0900239
Erik Kline2c5aaa12016-06-08 13:24:45 +0900240 // Enable optimistic DAD for IPv6 addresses on all interfaces.
241 setIPv6OptimisticMode("1");
Erik Kline145fd252015-05-12 15:58:49 +0900242
Erik Kline2c5aaa12016-06-08 13:24:45 +0900243 // Reduce the ARP/ND base reachable time from the default (30sec) to 15sec.
244 setBaseReachableTimeMs(15 * 1000);
Erik Kline7adf8d72015-07-28 18:51:01 +0900245
Erik Kline2c5aaa12016-06-08 13:24:45 +0900246 // When sending traffic via a given interface use only addresses configured
247 // on that interface as possible source addresses.
248 setIPv6UseOutgoingInterfaceAddrsOnly("1");
Dmitry Shmidt2eab1f72012-07-26 16:08:02 -0700249}
Lorenzo Colitti70afde62013-03-04 17:58:40 +0900250
Lorenzo Colitti70afde62013-03-04 17:58:40 +0900251int InterfaceController::setEnableIPv6(const char *interface, const int on) {
Erik Klinee1da4842015-05-12 15:56:06 +0900252 if (!isIfaceName(interface)) {
253 errno = ENOENT;
254 return -1;
255 }
256 // When disable_ipv6 changes from 1 to 0, the kernel starts autoconf.
257 // When disable_ipv6 changes from 0 to 1, the kernel clears all autoconf
258 // addresses and routes and disables IPv6 on the interface.
259 const char *disable_ipv6 = on ? "0" : "1";
260 return writeValueToPath(ipv6_proc_path, interface, "disable_ipv6", disable_ipv6);
Lorenzo Colitti70afde62013-03-04 17:58:40 +0900261}
262
Joel Scherpelzde937962017-06-01 13:20:21 +0900263// Changes to addrGenMode will not fully take effect until the next
264// time disable_ipv6 transitions from 1 to 0.
265Status InterfaceController::setIPv6AddrGenMode(const std::string& interface, int mode) {
266 if (!isIfaceName(interface)) {
267 return statusFromErrno(ENOENT, "invalid iface name: " + interface);
268 }
269
270 switch (mode) {
271 case INetd::IPV6_ADDR_GEN_MODE_EUI64:
272 // Ignore return value. If /proc/.../stable_secret is
273 // missing we're probably in EUI64 mode already.
274 writeValueToPath(ipv6_proc_path, interface.c_str(), "stable_secret", "");
275 break;
276 case INetd::IPV6_ADDR_GEN_MODE_STABLE_PRIVACY: {
277 return enableStablePrivacyAddresses(interface, getProperty, setProperty);
278 }
279 case INetd::IPV6_ADDR_GEN_MODE_NONE:
280 case INetd::IPV6_ADDR_GEN_MODE_RANDOM:
281 default:
282 return statusFromErrno(EOPNOTSUPP, "unsupported addrGenMode");
283 }
284
285 return ok;
286}
287
Erik Kline2c5aaa12016-06-08 13:24:45 +0900288int InterfaceController::setAcceptIPv6Ra(const char *interface, const int on) {
289 if (!isIfaceName(interface)) {
290 errno = ENOENT;
291 return -1;
292 }
293 // Because forwarding can be enabled even when tethering is off, we always
294 // use mode "2" (accept RAs, even if forwarding is enabled).
295 const char *accept_ra = on ? "2" : "0";
296 return writeValueToPath(ipv6_proc_path, interface, "accept_ra", accept_ra);
297}
298
299int InterfaceController::setAcceptIPv6Dad(const char *interface, const int on) {
300 if (!isIfaceName(interface)) {
301 errno = ENOENT;
302 return -1;
303 }
304 const char *accept_dad = on ? "1" : "0";
305 return writeValueToPath(ipv6_proc_path, interface, "accept_dad", accept_dad);
306}
307
Erik Kline59d8c482016-08-09 15:28:42 +0900308int InterfaceController::setIPv6DadTransmits(const char *interface, const char *value) {
309 if (!isIfaceName(interface)) {
310 errno = ENOENT;
311 return -1;
312 }
313 return writeValueToPath(ipv6_proc_path, interface, "dad_transmits", value);
314}
315
Lorenzo Colitti70afde62013-03-04 17:58:40 +0900316int InterfaceController::setIPv6PrivacyExtensions(const char *interface, const int on) {
Erik Klinee1da4842015-05-12 15:56:06 +0900317 if (!isIfaceName(interface)) {
318 errno = ENOENT;
319 return -1;
320 }
321 // 0: disable IPv6 privacy addresses
Joel Scherpelzde937962017-06-01 13:20:21 +0900322 // 2: enable IPv6 privacy addresses and prefer them over non-privacy ones.
Erik Klinee1da4842015-05-12 15:56:06 +0900323 return writeValueToPath(ipv6_proc_path, interface, "use_tempaddr", on ? "2" : "0");
Lorenzo Colitti70afde62013-03-04 17:58:40 +0900324}
Lorenzo Colitti37f2e372013-04-12 00:44:06 +0900325
Sreeram Ramachandrana4811802014-04-10 12:10:24 -0700326void InterfaceController::setAcceptRA(const char *value) {
Erik Klinee1da4842015-05-12 15:56:06 +0900327 setOnAllInterfaces(ipv6_proc_path, "accept_ra", value);
Sreeram Ramachandrana4811802014-04-10 12:10:24 -0700328}
329
Sreeram Ramachandrana01d6ef2014-04-10 19:37:59 -0700330// |tableOrOffset| is interpreted as:
Sreeram Ramachandrana4811802014-04-10 12:10:24 -0700331// If == 0: default. Routes go into RT6_TABLE_MAIN.
332// If > 0: user set. Routes go into the specified table.
333// If < 0: automatic. The absolute value is intepreted as an offset and added to the interface
334// ID to get the table. If it's set to -1000, routes from interface ID 5 will go into
335// table 1005, etc.
Sreeram Ramachandrana01d6ef2014-04-10 19:37:59 -0700336void InterfaceController::setAcceptRARouteTable(int tableOrOffset) {
Erik Klinee1da4842015-05-12 15:56:06 +0900337 std::string value(StringPrintf("%d", tableOrOffset));
338 setOnAllInterfaces(ipv6_proc_path, "accept_ra_rt_table", value.c_str());
Lorenzo Colitti37f2e372013-04-12 00:44:06 +0900339}
Dmitry Shmidt6d6c0e62013-06-11 16:18:06 -0700340
Dmitry Shmidt6d6c0e62013-06-11 16:18:06 -0700341int InterfaceController::setMtu(const char *interface, const char *mtu)
342{
Erik Klinee1da4842015-05-12 15:56:06 +0900343 if (!isIfaceName(interface)) {
344 errno = ENOENT;
345 return -1;
346 }
347 return writeValueToPath(sys_net_path, interface, "mtu", mtu);
Dmitry Shmidt6d6c0e62013-06-11 16:18:06 -0700348}
Erik Kline59273ed2014-12-08 16:05:28 +0900349
Erik Klinec296f092016-08-02 15:22:53 +0900350int InterfaceController::addAddress(const char *interface,
351 const char *addrString, int prefixLength) {
352 return ifc_add_address(interface, addrString, prefixLength);
353}
354
355int InterfaceController::delAddress(const char *interface,
356 const char *addrString, int prefixLength) {
357 return ifc_del_address(interface, addrString, prefixLength);
358}
359
Erik Klineb218a872016-07-04 09:57:18 +0900360int InterfaceController::getParameter(
361 const char *family, const char *which, const char *interface, const char *parameter,
362 std::string *value) {
363 const std::string path(getParameterPathname(family, which, interface, parameter));
364 if (path.empty()) {
365 return -errno;
366 }
367 return ReadFileToString(path, value) ? 0 : -errno;
368}
369
370int InterfaceController::setParameter(
371 const char *family, const char *which, const char *interface, const char *parameter,
372 const char *value) {
373 const std::string path(getParameterPathname(family, which, interface, parameter));
374 if (path.empty()) {
375 return -errno;
376 }
377 return WriteStringToFile(value, path) ? 0 : -errno;
378}
379
Erik Kline145fd252015-05-12 15:58:49 +0900380void InterfaceController::setBaseReachableTimeMs(unsigned int millis) {
381 std::string value(StringPrintf("%u", millis));
382 setOnAllInterfaces(ipv4_neigh_conf_dir, "base_reachable_time_ms", value.c_str());
383 setOnAllInterfaces(ipv6_neigh_conf_dir, "base_reachable_time_ms", value.c_str());
384}
385
Erik Kline59273ed2014-12-08 16:05:28 +0900386void InterfaceController::setIPv6OptimisticMode(const char *value) {
Erik Klinee1da4842015-05-12 15:56:06 +0900387 setOnAllInterfaces(ipv6_proc_path, "optimistic_dad", value);
388 setOnAllInterfaces(ipv6_proc_path, "use_optimistic", value);
Erik Kline59273ed2014-12-08 16:05:28 +0900389}
Chenbo Feng7e974052018-02-28 22:57:21 -0800390
391StatusOr<std::map<std::string, uint32_t>> InterfaceController::getIfaceList() {
392 std::map<std::string, uint32_t> ifacePairs;
393 DIR* d;
394 struct dirent* de;
395
396 if (!(d = opendir("/sys/class/net"))) {
397 return statusFromErrno(errno, "Cannot open iface directory");
398 }
399 while ((de = readdir(d))) {
400 if (de->d_name[0] == '.') continue;
401 uint32_t ifaceIndex = if_nametoindex(de->d_name);
402 if (ifaceIndex) {
403 ifacePairs.insert(std::pair<std::string, uint32_t>(de->d_name, ifaceIndex));
404 }
405 }
406 closedir(d);
407 return ifacePairs;
408}