blob: d332e0c42d7f4faf40c00809eef4077bb91b3b34 [file] [log] [blame]
San Mehat9d10b342010-01-18 09:51:02 -08001/*
2 * Copyright (C) 2008 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
San Mehat9d10b342010-01-18 09:51:02 -080017#include <errno.h>
San Mehat18737842010-01-21 09:22:43 -080018#include <fcntl.h>
Lorenzo Colittia93126d2017-08-24 13:28:19 +090019#include <inttypes.h>
Lorenzo Colittic2841282015-11-25 22:13:57 +090020#include <netdb.h>
Luke Huang40962442019-02-26 11:46:10 +080021#include <spawn.h>
Olivier Baillyff2c0d82010-11-17 11:45:07 -080022#include <string.h>
San Mehat18737842010-01-21 09:22:43 -080023
San Mehat9d10b342010-01-18 09:51:02 -080024#include <sys/socket.h>
25#include <sys/stat.h>
San Mehat18737842010-01-21 09:22:43 -080026#include <sys/types.h>
27#include <sys/wait.h>
28
San Mehat9d10b342010-01-18 09:51:02 -080029#include <netinet/in.h>
30#include <arpa/inet.h>
31
Erik Kline5f0358b2018-02-16 15:08:09 +090032#include <array>
33#include <cstdlib>
waynema71a0b592018-11-21 13:31:34 +080034#include <regex>
Erik Kline5f0358b2018-02-16 15:08:09 +090035#include <string>
36#include <vector>
37
San Mehat9d10b342010-01-18 09:51:02 -080038#define LOG_TAG "TetherController"
Maciej Żenczykowski2cffd942019-05-05 13:40:35 -070039#include <android-base/scopeguard.h>
Lorenzo Colittia93126d2017-08-24 13:28:19 +090040#include <android-base/stringprintf.h>
George Burgess IVe3dc1312019-02-28 11:27:04 -080041#include <android-base/strings.h>
42#include <android-base/unique_fd.h>
Kazuhiro Ondo6b858eb2011-06-24 20:31:03 -050043#include <cutils/properties.h>
Logan Chien3f461482018-04-23 14:31:32 +080044#include <log/log.h>
Hungming Chen1da90082020-02-14 20:24:16 +080045#include <net/if.h>
Lorenzo Colitti52db3912020-02-17 23:59:45 +090046#include <netdutils/DumpWriter.h>
Lorenzo Colitti9a8a9ff2017-01-31 19:06:59 +090047#include <netdutils/StatusOr.h>
San Mehat9d10b342010-01-18 09:51:02 -080048
Erik Klineb31fd692018-06-06 20:50:11 +090049#include "Controllers.h"
Lorenzo Colitti667c4772014-08-26 14:13:07 -070050#include "Fwmark.h"
Erik Kline1d065ba2016-06-08 13:24:45 +090051#include "InterfaceController.h"
Mike Yuf0e019f2019-03-13 14:43:39 +080052#include "NetdConstants.h"
Lorenzo Colittie20a5262017-05-09 18:30:44 +090053#include "NetworkController.h"
Hungming Chen1da90082020-02-14 20:24:16 +080054#include "OffloadUtils.h"
Mike Yuf0e019f2019-03-13 14:43:39 +080055#include "Permission.h"
San Mehat9d10b342010-01-18 09:51:02 -080056#include "TetherController.h"
57
Bernie Innocenti4debf3b2018-09-12 13:54:50 +090058namespace android {
59namespace net {
60
Lorenzo Colittie801d3c2020-02-18 00:00:35 +090061using android::base::Error;
Lorenzo Colittia93126d2017-08-24 13:28:19 +090062using android::base::Join;
George Burgess IVe3dc1312019-02-28 11:27:04 -080063using android::base::Pipe;
Lorenzo Colittie801d3c2020-02-18 00:00:35 +090064using android::base::Result;
65using android::base::StringAppendF;
Erik Klineb31fd692018-06-06 20:50:11 +090066using android::base::StringPrintf;
George Burgess IVe3dc1312019-02-28 11:27:04 -080067using android::base::unique_fd;
Lorenzo Colitti52db3912020-02-17 23:59:45 +090068using android::netdutils::DumpWriter;
69using android::netdutils::ScopedIndent;
Lorenzo Colitti9a8a9ff2017-01-31 19:06:59 +090070using android::netdutils::statusFromErrno;
Erik Klineb31fd692018-06-06 20:50:11 +090071using android::netdutils::StatusOr;
Lorenzo Colittia93126d2017-08-24 13:28:19 +090072
Lorenzo Colitti799625c2015-02-25 12:52:00 +090073namespace {
74
Erik Kline1d065ba2016-06-08 13:24:45 +090075const char BP_TOOLS_MODE[] = "bp-tools";
76const char IPV4_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv4/ip_forward";
77const char IPV6_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv6/conf/all/forwarding";
78const char SEPARATOR[] = "|";
Erik Kline93f9b222017-10-22 21:24:58 +090079constexpr const char kTcpBeLiberal[] = "/proc/sys/net/netfilter/nf_conntrack_tcp_be_liberal";
Hungming Chen68dade32020-02-20 13:50:56 +080080
81// Dummy interface name, the name needs to be longer than 16 characters so it can never conflict
82// with a real interface name. See also IFNAMSIZ.
Hungming Chenc2e95fb2020-02-19 17:41:30 +080083constexpr const char kBpfOffloadInterface[] = "BPFOffloadInterface";
Lorenzo Colitti799625c2015-02-25 12:52:00 +090084
Erik Kline5f0358b2018-02-16 15:08:09 +090085// Chosen to match AID_DNS_TETHER, as made "friendly" by fs_config_generator.py.
86constexpr const char kDnsmasqUsername[] = "dns_tether";
87
Lorenzo Colitti799625c2015-02-25 12:52:00 +090088bool writeToFile(const char* filename, const char* value) {
Nick Kralevichb95c60c2016-11-19 09:09:16 -080089 int fd = open(filename, O_WRONLY | O_CLOEXEC);
Nicolas Geoffrayafd40372015-03-16 11:58:06 +000090 if (fd < 0) {
91 ALOGE("Failed to open %s: %s", filename, strerror(errno));
92 return false;
93 }
94
95 const ssize_t len = strlen(value);
96 if (write(fd, value, len) != len) {
97 ALOGE("Failed to write %s to %s: %s", value, filename, strerror(errno));
98 close(fd);
99 return false;
100 }
101 close(fd);
102 return true;
Lorenzo Colitti799625c2015-02-25 12:52:00 +0900103}
104
Erik Kline93f9b222017-10-22 21:24:58 +0900105// TODO: Consider altering TCP and UDP timeouts as well.
106void configureForTethering(bool enabled) {
107 writeToFile(kTcpBeLiberal, enabled ? "1" : "0");
108}
109
Erik Kline1d065ba2016-06-08 13:24:45 +0900110bool configureForIPv6Router(const char *interface) {
111 return (InterfaceController::setEnableIPv6(interface, 0) == 0)
112 && (InterfaceController::setAcceptIPv6Ra(interface, 0) == 0)
Erik Kline6cddf512016-08-09 15:28:42 +0900113 && (InterfaceController::setAcceptIPv6Dad(interface, 0) == 0)
114 && (InterfaceController::setIPv6DadTransmits(interface, "0") == 0)
Erik Kline1d065ba2016-06-08 13:24:45 +0900115 && (InterfaceController::setEnableIPv6(interface, 1) == 0);
116}
117
118void configureForIPv6Client(const char *interface) {
119 InterfaceController::setAcceptIPv6Ra(interface, 1);
Erik Kline6cddf512016-08-09 15:28:42 +0900120 InterfaceController::setAcceptIPv6Dad(interface, 1);
121 InterfaceController::setIPv6DadTransmits(interface, "1");
Erik Kline1d065ba2016-06-08 13:24:45 +0900122 InterfaceController::setEnableIPv6(interface, 0);
123}
124
Lorenzo Colitti799625c2015-02-25 12:52:00 +0900125bool inBpToolsMode() {
126 // In BP tools mode, do not disable IP forwarding
127 char bootmode[PROPERTY_VALUE_MAX] = {0};
128 property_get("ro.bootmode", bootmode, "unknown");
129 return !strcmp(BP_TOOLS_MODE, bootmode);
130}
131
132} // namespace
133
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900134auto TetherController::iptablesRestoreFunction = execIptablesRestoreWithOutput;
135
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900136const std::string GET_TETHER_STATS_COMMAND = StringPrintf(
137 "*filter\n"
138 "-nvx -L %s\n"
139 "COMMIT\n", android::net::TetherController::LOCAL_TETHER_COUNTERS_CHAIN);
140
Erik Kline15079dd2018-05-18 23:10:56 +0900141int TetherController::DnsmasqState::sendCmd(int daemonFd, const std::string& cmd) {
142 if (cmd.empty()) return 0;
143
Erik Klineb31fd692018-06-06 20:50:11 +0900144 gLog.log("Sending update msg to dnsmasq [%s]", cmd.c_str());
Erik Kline15079dd2018-05-18 23:10:56 +0900145 // Send the trailing \0 as well.
146 if (write(daemonFd, cmd.c_str(), cmd.size() + 1) < 0) {
Erik Klineb31fd692018-06-06 20:50:11 +0900147 gLog.error("Failed to send update command to dnsmasq (%s)", strerror(errno));
Erik Kline15079dd2018-05-18 23:10:56 +0900148 errno = EREMOTEIO;
149 return -1;
150 }
151 return 0;
152}
153
154void TetherController::DnsmasqState::clear() {
155 update_ifaces_cmd.clear();
156 update_dns_cmd.clear();
157}
158
159int TetherController::DnsmasqState::sendAllState(int daemonFd) const {
160 return sendCmd(daemonFd, update_ifaces_cmd) | sendCmd(daemonFd, update_dns_cmd);
161}
162
Sreeram Ramachandran87475a12014-07-15 16:20:28 -0700163TetherController::TetherController() {
Lorenzo Colitti799625c2015-02-25 12:52:00 +0900164 if (inBpToolsMode()) {
165 enableForwarding(BP_TOOLS_MODE);
166 } else {
167 setIpFwdEnabled();
168 }
Hungming Chenc2e95fb2020-02-19 17:41:30 +0800169 maybeInitMaps();
San Mehat9d10b342010-01-18 09:51:02 -0800170}
171
Lorenzo Colitti799625c2015-02-25 12:52:00 +0900172bool TetherController::setIpFwdEnabled() {
173 bool success = true;
Hugo Benichic4b3a0c2018-05-22 08:48:40 +0900174 bool disable = mForwardingRequests.empty();
175 const char* value = disable ? "0" : "1";
Lorenzo Colitti799625c2015-02-25 12:52:00 +0900176 ALOGD("Setting IP forward enable = %s", value);
177 success &= writeToFile(IPV4_FORWARDING_PROC_FILE, value);
178 success &= writeToFile(IPV6_FORWARDING_PROC_FILE, value);
Hugo Benichic4b3a0c2018-05-22 08:48:40 +0900179 if (disable) {
180 // Turning off the forwarding sysconf in the kernel has the side effect
181 // of turning on ICMP redirect, which is a security hazard.
182 // Turn ICMP redirect back off immediately.
183 int rv = InterfaceController::disableIcmpRedirects();
184 success &= (rv == 0);
185 }
Lorenzo Colitti799625c2015-02-25 12:52:00 +0900186 return success;
San Mehat9d10b342010-01-18 09:51:02 -0800187}
188
Lorenzo Colitti799625c2015-02-25 12:52:00 +0900189bool TetherController::enableForwarding(const char* requester) {
190 // Don't return an error if this requester already requested forwarding. Only return errors for
191 // things that the caller caller needs to care about, such as "couldn't write to the file to
192 // enable forwarding".
193 mForwardingRequests.insert(requester);
194 return setIpFwdEnabled();
195}
San Mehat9d10b342010-01-18 09:51:02 -0800196
Lorenzo Colitti799625c2015-02-25 12:52:00 +0900197bool TetherController::disableForwarding(const char* requester) {
198 mForwardingRequests.erase(requester);
199 return setIpFwdEnabled();
200}
San Mehat9d10b342010-01-18 09:51:02 -0800201
Hungming Chenc2e95fb2020-02-19 17:41:30 +0800202void TetherController::maybeInitMaps() {
203 if (!bpf::isBpfSupported()) return;
204
205 // Used for parsing tether stats from BPF maps. If open the map failed, skip to open
206 // tether BPF offload maps.
207 mIfaceIndexNameMap.init(IFACE_INDEX_NAME_MAP_PATH);
208 if (!mIfaceIndexNameMap.isValid()) return;
209
210 // Open BPF maps, ignoring errors because the device might not support BPF offload.
211 int fd = getTetherIngressMapFd();
212 if (fd != -1) {
213 mBpfIngressMap.reset(fd);
214 }
215 fd = getTetherStatsMapFd();
216 if (fd != -1) {
217 mBpfStatsMap.reset(fd);
218 }
219}
220
Luke Huang728cf4c2019-03-14 19:43:02 +0800221const std::set<std::string>& TetherController::getIpfwdRequesterList() const {
222 return mForwardingRequests;
San Mehat9d10b342010-01-18 09:51:02 -0800223}
224
Luke Huang91bd3e12019-08-20 11:33:52 +0800225int TetherController::startTethering(bool usingLegacyDnsProxy, int num_addrs, char** dhcp_ranges) {
226 if (!usingLegacyDnsProxy && num_addrs == 0) {
227 // Both DHCP and DnsProxy are disabled, we don't need to start dnsmasq
228 configureForTethering(true);
229 mIsTetheringStarted = true;
230 return 0;
231 }
232
233 if (mIsTetheringStarted) {
Steve Block5ea0c052012-01-06 19:18:11 +0000234 ALOGE("Tethering already started");
San Mehat9d10b342010-01-18 09:51:02 -0800235 errno = EBUSY;
Luke Huangb5733d72018-08-21 17:17:19 +0800236 return -errno;
San Mehat9d10b342010-01-18 09:51:02 -0800237 }
238
Steve Block7b984e32011-12-20 16:22:42 +0000239 ALOGD("Starting tethering services");
San Mehat9d10b342010-01-18 09:51:02 -0800240
George Burgess IVe3dc1312019-02-28 11:27:04 -0800241 unique_fd pipeRead, pipeWrite;
242 if (!Pipe(&pipeRead, &pipeWrite, O_CLOEXEC)) {
Luke Huangb5733d72018-08-21 17:17:19 +0800243 int res = errno;
Luke Huang94c43a12019-02-14 19:51:38 +0800244 ALOGE("pipe2() failed (%s)", strerror(errno));
Luke Huangb5733d72018-08-21 17:17:19 +0800245 return -res;
San Mehat9d10b342010-01-18 09:51:02 -0800246 }
247
Luke Huang94c43a12019-02-14 19:51:38 +0800248 // Set parameters
249 Fwmark fwmark;
250 fwmark.netId = NetworkController::LOCAL_NET_ID;
251 fwmark.explicitlySelected = true;
252 fwmark.protectedFromVpn = true;
253 fwmark.permission = PERMISSION_SYSTEM;
254 char markStr[UINT32_HEX_STRLEN];
255 snprintf(markStr, sizeof(markStr), "0x%x", fwmark.intValue);
San Mehat9d10b342010-01-18 09:51:02 -0800256
Luke Huang94c43a12019-02-14 19:51:38 +0800257 std::vector<const std::string> argVector = {
Erik Kline5f0358b2018-02-16 15:08:09 +0900258 "/system/bin/dnsmasq",
259 "--keep-in-foreground",
260 "--no-resolv",
261 "--no-poll",
262 "--dhcp-authoritative",
263 // TODO: pipe through metered status from ConnService
264 "--dhcp-option-force=43,ANDROID_METERED",
265 "--pid-file",
Luke Huang94c43a12019-02-14 19:51:38 +0800266 "--listen-mark",
267 markStr,
268 "--user",
269 kDnsmasqUsername,
270 };
San Mehat9d10b342010-01-18 09:51:02 -0800271
Luke Huang91bd3e12019-08-20 11:33:52 +0800272 if (!usingLegacyDnsProxy) {
273 argVector.push_back("--port=0");
274 }
275
276 // DHCP server will be disabled if num_addrs == 0 and no --dhcp-range is passed.
Luke Huang94c43a12019-02-14 19:51:38 +0800277 for (int addrIndex = 0; addrIndex < num_addrs; addrIndex += 2) {
278 argVector.push_back(StringPrintf("--dhcp-range=%s,%s,1h", dhcp_ranges[addrIndex],
279 dhcp_ranges[addrIndex + 1]));
San Mehat9d10b342010-01-18 09:51:02 -0800280 }
281
George Burgess IVe3dc1312019-02-28 11:27:04 -0800282 std::vector<char*> args(argVector.size() + 1);
Luke Huang94c43a12019-02-14 19:51:38 +0800283 for (unsigned i = 0; i < argVector.size(); i++) {
284 args[i] = (char*)argVector[i].c_str();
285 }
286
287 /*
288 * TODO: Create a monitoring thread to handle and restart
289 * the daemon if it exits prematurely
290 */
Luke Huang40962442019-02-26 11:46:10 +0800291
292 // Note that don't modify any memory between vfork and execv.
293 // Changing state of file descriptors would be fine. See posix_spawn_file_actions_add*
294 // dup2 creates fd without CLOEXEC, dnsmasq will receive commands through the
295 // duplicated fd.
296 posix_spawn_file_actions_t fa;
Maciej Żenczykowski2cffd942019-05-05 13:40:35 -0700297 int res = posix_spawn_file_actions_init(&fa);
Luke Huang40962442019-02-26 11:46:10 +0800298 if (res) {
Maciej Żenczykowski2cffd942019-05-05 13:40:35 -0700299 ALOGE("posix_spawn_file_actions_init failed (%s)", strerror(res));
300 return -res;
301 }
302 const android::base::ScopeGuard faGuard = [&] { posix_spawn_file_actions_destroy(&fa); };
303 res = posix_spawn_file_actions_adddup2(&fa, pipeRead.get(), STDIN_FILENO);
304 if (res) {
305 ALOGE("posix_spawn_file_actions_adddup2 failed (%s)", strerror(res));
Luke Huang94c43a12019-02-14 19:51:38 +0800306 return -res;
307 }
308
Luke Huang40962442019-02-26 11:46:10 +0800309 posix_spawnattr_t attr;
Maciej Żenczykowski2cffd942019-05-05 13:40:35 -0700310 res = posix_spawnattr_init(&attr);
Luke Huang40962442019-02-26 11:46:10 +0800311 if (res) {
Maciej Żenczykowski2cffd942019-05-05 13:40:35 -0700312 ALOGE("posix_spawnattr_init failed (%s)", strerror(res));
313 return -res;
314 }
315 const android::base::ScopeGuard attrGuard = [&] { posix_spawnattr_destroy(&attr); };
316 res = posix_spawnattr_setflags(&attr, POSIX_SPAWN_USEVFORK);
317 if (res) {
318 ALOGE("posix_spawnattr_setflags failed (%s)", strerror(res));
Luke Huang40962442019-02-26 11:46:10 +0800319 return -res;
320 }
321
322 pid_t pid;
George Burgess IVe3dc1312019-02-28 11:27:04 -0800323 res = posix_spawn(&pid, args[0], &fa, &attr, &args[0], nullptr);
Luke Huang40962442019-02-26 11:46:10 +0800324 if (res) {
325 ALOGE("posix_spawn failed (%s)", strerror(res));
Luke Huang40962442019-02-26 11:46:10 +0800326 return -res;
327 }
Luke Huang94c43a12019-02-14 19:51:38 +0800328 mDaemonPid = pid;
George Burgess IVe3dc1312019-02-28 11:27:04 -0800329 mDaemonFd = pipeWrite.release();
Luke Huang94c43a12019-02-14 19:51:38 +0800330 configureForTethering(true);
Luke Huang91bd3e12019-08-20 11:33:52 +0800331 mIsTetheringStarted = true;
Luke Huang94c43a12019-02-14 19:51:38 +0800332 applyDnsInterfaces();
333 ALOGD("Tethering services running");
334
San Mehat9d10b342010-01-18 09:51:02 -0800335 return 0;
336}
337
Luke Huangb5733d72018-08-21 17:17:19 +0800338std::vector<char*> TetherController::toCstrVec(const std::vector<std::string>& addrs) {
339 std::vector<char*> addrsCstrVec{};
340 addrsCstrVec.reserve(addrs.size());
341 for (const auto& addr : addrs) {
342 addrsCstrVec.push_back(const_cast<char*>(addr.data()));
343 }
344 return addrsCstrVec;
345}
346
Luke Huang91bd3e12019-08-20 11:33:52 +0800347int TetherController::startTethering(bool usingLegacyDnsProxy,
348 const std::vector<std::string>& dhcpRanges) {
Luke Huangb5733d72018-08-21 17:17:19 +0800349 struct in_addr v4_addr;
350 for (const auto& dhcpRange : dhcpRanges) {
351 if (!inet_aton(dhcpRange.c_str(), &v4_addr)) {
352 return -EINVAL;
353 }
354 }
355 auto dhcp_ranges = toCstrVec(dhcpRanges);
Luke Huang91bd3e12019-08-20 11:33:52 +0800356 return startTethering(usingLegacyDnsProxy, dhcp_ranges.size(), dhcp_ranges.data());
Luke Huangb5733d72018-08-21 17:17:19 +0800357}
358
San Mehat9d10b342010-01-18 09:51:02 -0800359int TetherController::stopTethering() {
Erik Kline93f9b222017-10-22 21:24:58 +0900360 configureForTethering(false);
San Mehat9d10b342010-01-18 09:51:02 -0800361
Luke Huang91bd3e12019-08-20 11:33:52 +0800362 if (!mIsTetheringStarted) {
Steve Block5ea0c052012-01-06 19:18:11 +0000363 ALOGE("Tethering already stopped");
San Mehat9d10b342010-01-18 09:51:02 -0800364 return 0;
365 }
366
Luke Huang91bd3e12019-08-20 11:33:52 +0800367 mIsTetheringStarted = false;
368 // dnsmasq is not started
369 if (mDaemonPid == 0) {
370 return 0;
371 }
372
Steve Block7b984e32011-12-20 16:22:42 +0000373 ALOGD("Stopping tethering services");
San Mehat9d10b342010-01-18 09:51:02 -0800374
375 kill(mDaemonPid, SIGTERM);
Yi Kongbdfd57e2018-07-25 13:26:10 -0700376 waitpid(mDaemonPid, nullptr, 0);
San Mehat9d10b342010-01-18 09:51:02 -0800377 mDaemonPid = 0;
378 close(mDaemonFd);
379 mDaemonFd = -1;
Erik Kline15079dd2018-05-18 23:10:56 +0900380 mDnsmasqState.clear();
Steve Block7b984e32011-12-20 16:22:42 +0000381 ALOGD("Tethering services stopped");
San Mehat9d10b342010-01-18 09:51:02 -0800382 return 0;
383}
Matthew Xie19944102012-07-12 16:42:07 -0700384
San Mehat9d10b342010-01-18 09:51:02 -0800385bool TetherController::isTetheringStarted() {
Luke Huang91bd3e12019-08-20 11:33:52 +0800386 return mIsTetheringStarted;
San Mehat9d10b342010-01-18 09:51:02 -0800387}
388
Bernie Innocenti15bb55c2018-06-03 16:19:51 +0900389// dnsmasq can't parse commands larger than this due to the fixed-size buffer
390// in check_android_listeners(). The receiving buffer is 1024 bytes long, but
391// dnsmasq reads up to 1023 bytes.
Bernie Innocenti45238a12018-12-04 14:57:48 +0900392const size_t MAX_CMD_SIZE = 1023;
Kenny Rootcf52faf2010-02-18 09:59:55 -0800393
Luke Huang8dc1cac2019-03-30 16:12:31 +0800394// TODO: Remove overload function and update this after NDC migration.
Lorenzo Colitti667c4772014-08-26 14:13:07 -0700395int TetherController::setDnsForwarders(unsigned netId, char **servers, int numServers) {
Lorenzo Colitti667c4772014-08-26 14:13:07 -0700396 Fwmark fwmark;
397 fwmark.netId = netId;
398 fwmark.explicitlySelected = true;
399 fwmark.protectedFromVpn = true;
400 fwmark.permission = PERMISSION_SYSTEM;
401
Bernie Innocenti15bb55c2018-06-03 16:19:51 +0900402 std::string daemonCmd = StringPrintf("update_dns%s0x%x", SEPARATOR, fwmark.intValue);
San Mehat9d10b342010-01-18 09:51:02 -0800403
Erik Kline1d065ba2016-06-08 13:24:45 +0900404 mDnsForwarders.clear();
Bernie Innocenti45238a12018-12-04 14:57:48 +0900405 for (int i = 0; i < numServers; i++) {
Lorenzo Colitti667c4772014-08-26 14:13:07 -0700406 ALOGD("setDnsForwarders(0x%x %d = '%s')", fwmark.intValue, i, servers[i]);
San Mehat9d10b342010-01-18 09:51:02 -0800407
Lorenzo Colittic2841282015-11-25 22:13:57 +0900408 addrinfo *res, hints = { .ai_flags = AI_NUMERICHOST };
Yi Kongbdfd57e2018-07-25 13:26:10 -0700409 int ret = getaddrinfo(servers[i], nullptr, &hints, &res);
Lorenzo Colittic2841282015-11-25 22:13:57 +0900410 freeaddrinfo(res);
411 if (ret) {
Steve Block5ea0c052012-01-06 19:18:11 +0000412 ALOGE("Failed to parse DNS server '%s'", servers[i]);
Erik Kline1d065ba2016-06-08 13:24:45 +0900413 mDnsForwarders.clear();
Lorenzo Colittic2841282015-11-25 22:13:57 +0900414 errno = EINVAL;
Luke Huangb5733d72018-08-21 17:17:19 +0800415 return -errno;
San Mehat9d10b342010-01-18 09:51:02 -0800416 }
Kenny Rootcf52faf2010-02-18 09:59:55 -0800417
Bernie Innocenti15bb55c2018-06-03 16:19:51 +0900418 if (daemonCmd.size() + 1 + strlen(servers[i]) >= MAX_CMD_SIZE) {
419 ALOGE("Too many DNS servers listed");
Kenny Rootcf52faf2010-02-18 09:59:55 -0800420 break;
421 }
422
Bernie Innocenti15bb55c2018-06-03 16:19:51 +0900423 daemonCmd += SEPARATOR;
424 daemonCmd += servers[i];
Erik Kline1d065ba2016-06-08 13:24:45 +0900425 mDnsForwarders.push_back(servers[i]);
San Mehat9d10b342010-01-18 09:51:02 -0800426 }
427
Lorenzo Colitti667c4772014-08-26 14:13:07 -0700428 mDnsNetId = netId;
Bernie Innocenti15bb55c2018-06-03 16:19:51 +0900429 mDnsmasqState.update_dns_cmd = std::move(daemonCmd);
San Mehat9d10b342010-01-18 09:51:02 -0800430 if (mDaemonFd != -1) {
Erik Kline15079dd2018-05-18 23:10:56 +0900431 if (mDnsmasqState.sendAllState(mDaemonFd) != 0) {
Erik Kline1d065ba2016-06-08 13:24:45 +0900432 mDnsForwarders.clear();
Lorenzo Colittic2841282015-11-25 22:13:57 +0900433 errno = EREMOTEIO;
Luke Huangb5733d72018-08-21 17:17:19 +0800434 return -errno;
San Mehat9d10b342010-01-18 09:51:02 -0800435 }
436 }
437 return 0;
438}
439
Luke Huangb5733d72018-08-21 17:17:19 +0800440int TetherController::setDnsForwarders(unsigned netId, const std::vector<std::string>& servers) {
Luke Huangb5733d72018-08-21 17:17:19 +0800441 auto dnsServers = toCstrVec(servers);
442 return setDnsForwarders(netId, dnsServers.data(), dnsServers.size());
443}
444
Lorenzo Colitti667c4772014-08-26 14:13:07 -0700445unsigned TetherController::getDnsNetId() {
446 return mDnsNetId;
447}
448
Erik Kline1d065ba2016-06-08 13:24:45 +0900449const std::list<std::string> &TetherController::getDnsForwarders() const {
San Mehat9d10b342010-01-18 09:51:02 -0800450 return mDnsForwarders;
451}
452
Erik Kline1d065ba2016-06-08 13:24:45 +0900453bool TetherController::applyDnsInterfaces() {
Bernie Innocenti15bb55c2018-06-03 16:19:51 +0900454 std::string daemonCmd = "update_ifaces";
Robert Greenwalt3d4c7582012-12-11 12:33:37 -0800455 bool haveInterfaces = false;
456
Bernie Innocenti15bb55c2018-06-03 16:19:51 +0900457 for (const auto& ifname : mInterfaces) {
458 if (daemonCmd.size() + 1 + ifname.size() >= MAX_CMD_SIZE) {
459 ALOGE("Too many DNS servers listed");
Robert Greenwalt3d4c7582012-12-11 12:33:37 -0800460 break;
461 }
462
Bernie Innocenti15bb55c2018-06-03 16:19:51 +0900463 daemonCmd += SEPARATOR;
464 daemonCmd += ifname;
Robert Greenwalt3d4c7582012-12-11 12:33:37 -0800465 haveInterfaces = true;
466 }
467
Erik Kline15079dd2018-05-18 23:10:56 +0900468 if (!haveInterfaces) {
469 mDnsmasqState.update_ifaces_cmd.clear();
470 } else {
Bernie Innocenti15bb55c2018-06-03 16:19:51 +0900471 mDnsmasqState.update_ifaces_cmd = std::move(daemonCmd);
Erik Kline15079dd2018-05-18 23:10:56 +0900472 if (mDaemonFd != -1) return (mDnsmasqState.sendAllState(mDaemonFd) == 0);
Robert Greenwalt3d4c7582012-12-11 12:33:37 -0800473 }
Erik Kline1d065ba2016-06-08 13:24:45 +0900474 return true;
San Mehat9d10b342010-01-18 09:51:02 -0800475}
476
Robert Greenwalt3d4c7582012-12-11 12:33:37 -0800477int TetherController::tetherInterface(const char *interface) {
478 ALOGD("tetherInterface(%s)", interface);
JP Abgrall69261cb2014-06-19 18:35:24 -0700479 if (!isIfaceName(interface)) {
480 errno = ENOENT;
Luke Huangb5733d72018-08-21 17:17:19 +0800481 return -errno;
JP Abgrall69261cb2014-06-19 18:35:24 -0700482 }
Robert Greenwalt3d4c7582012-12-11 12:33:37 -0800483
Erik Kline1d065ba2016-06-08 13:24:45 +0900484 if (!configureForIPv6Router(interface)) {
485 configureForIPv6Client(interface);
Luke Huangb5733d72018-08-21 17:17:19 +0800486 return -EREMOTEIO;
Erik Kline1d065ba2016-06-08 13:24:45 +0900487 }
488 mInterfaces.push_back(interface);
489
490 if (!applyDnsInterfaces()) {
491 mInterfaces.pop_back();
492 configureForIPv6Client(interface);
Luke Huangb5733d72018-08-21 17:17:19 +0800493 return -EREMOTEIO;
Robert Greenwalt3d4c7582012-12-11 12:33:37 -0800494 } else {
495 return 0;
496 }
497}
498
San Mehat9d10b342010-01-18 09:51:02 -0800499int TetherController::untetherInterface(const char *interface) {
Robert Greenwalt3d4c7582012-12-11 12:33:37 -0800500 ALOGD("untetherInterface(%s)", interface);
501
Erik Kline1d065ba2016-06-08 13:24:45 +0900502 for (auto it = mInterfaces.cbegin(); it != mInterfaces.cend(); ++it) {
503 if (!strcmp(interface, it->c_str())) {
504 mInterfaces.erase(it);
Robert Greenwalt3d4c7582012-12-11 12:33:37 -0800505
Erik Kline1d065ba2016-06-08 13:24:45 +0900506 configureForIPv6Client(interface);
Luke Huangb5733d72018-08-21 17:17:19 +0800507 return applyDnsInterfaces() ? 0 : -EREMOTEIO;
San Mehat9d10b342010-01-18 09:51:02 -0800508 }
509 }
510 errno = ENOENT;
Luke Huangb5733d72018-08-21 17:17:19 +0800511 return -errno;
San Mehat9d10b342010-01-18 09:51:02 -0800512}
513
Erik Kline1d065ba2016-06-08 13:24:45 +0900514const std::list<std::string> &TetherController::getTetheredInterfaceList() const {
San Mehat9d10b342010-01-18 09:51:02 -0800515 return mInterfaces;
516}
Lorenzo Colittie20a5262017-05-09 18:30:44 +0900517
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900518int TetherController::setupIptablesHooks() {
519 int res;
520 res = setDefaults();
521 if (res < 0) {
522 return res;
523 }
524
525 // Used to limit downstream mss to the upstream pmtu so we don't end up fragmenting every large
526 // packet tethered devices send. This is IPv4-only, because in IPv6 we send the MTU in the RA.
527 // This is no longer optional and tethering will fail to start if it fails.
528 std::string mssRewriteCommand = StringPrintf(
529 "*mangle\n"
530 "-A %s -p tcp --tcp-flags SYN SYN -j TCPMSS --clamp-mss-to-pmtu\n"
531 "COMMIT\n", LOCAL_MANGLE_FORWARD);
532
533 // This is for tethering counters. This chain is reached via --goto, and then RETURNS.
534 std::string defaultCommands = StringPrintf(
535 "*filter\n"
536 ":%s -\n"
537 "COMMIT\n", LOCAL_TETHER_COUNTERS_CHAIN);
538
539 res = iptablesRestoreFunction(V4, mssRewriteCommand, nullptr);
540 if (res < 0) {
541 return res;
542 }
543
544 res = iptablesRestoreFunction(V4V6, defaultCommands, nullptr);
545 if (res < 0) {
546 return res;
547 }
548
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900549 mFwdIfaces.clear();
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900550
551 return 0;
552}
553
554int TetherController::setDefaults() {
555 std::string v4Cmd = StringPrintf(
556 "*filter\n"
557 ":%s -\n"
558 "-A %s -j DROP\n"
559 "COMMIT\n"
560 "*nat\n"
561 ":%s -\n"
562 "COMMIT\n", LOCAL_FORWARD, LOCAL_FORWARD, LOCAL_NAT_POSTROUTING);
563
564 std::string v6Cmd = StringPrintf(
Luke Huangae038f82018-11-05 11:17:31 +0900565 "*filter\n"
566 ":%s -\n"
567 "COMMIT\n"
568 "*raw\n"
569 ":%s -\n"
570 "COMMIT\n",
571 LOCAL_FORWARD, LOCAL_RAW_PREROUTING);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900572
573 int res = iptablesRestoreFunction(V4, v4Cmd, nullptr);
574 if (res < 0) {
575 return res;
576 }
577
578 res = iptablesRestoreFunction(V6, v6Cmd, nullptr);
579 if (res < 0) {
580 return res;
581 }
582
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900583 return 0;
584}
585
586int TetherController::enableNat(const char* intIface, const char* extIface) {
587 ALOGV("enableNat(intIface=<%s>, extIface=<%s>)",intIface, extIface);
588
589 if (!isIfaceName(intIface) || !isIfaceName(extIface)) {
Luke Huang19b49c52018-10-22 12:12:05 +0900590 return -ENODEV;
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900591 }
592
593 /* Bug: b/9565268. "enableNat wlan0 wlan0". For now we fail until java-land is fixed */
594 if (!strcmp(intIface, extIface)) {
595 ALOGE("Duplicate interface specified: %s %s", intIface, extIface);
Luke Huang19b49c52018-10-22 12:12:05 +0900596 return -EINVAL;
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900597 }
598
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900599 if (isForwardingPairEnabled(intIface, extIface)) {
600 return 0;
601 }
602
603 // add this if we are the first enabled nat for this upstream
604 if (!isAnyForwardingEnabledOnUpstream(extIface)) {
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900605 std::vector<std::string> v4Cmds = {
606 "*nat",
607 StringPrintf("-A %s -o %s -j MASQUERADE", LOCAL_NAT_POSTROUTING, extIface),
608 "COMMIT\n"
609 };
610
Luke Huangae038f82018-11-05 11:17:31 +0900611 if (iptablesRestoreFunction(V4, Join(v4Cmds, '\n'), nullptr) || setupIPv6CountersChain() ||
612 setTetherGlobalAlertRule()) {
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900613 ALOGE("Error setting postroute rule: iface=%s", extIface);
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900614 if (!isAnyForwardingPairEnabled()) {
615 // unwind what's been done, but don't care about success - what more could we do?
616 setDefaults();
617 }
Luke Huang19b49c52018-10-22 12:12:05 +0900618 return -EREMOTEIO;
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900619 }
620 }
621
622 if (setForwardRules(true, intIface, extIface) != 0) {
623 ALOGE("Error setting forward rules");
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900624 if (!isAnyForwardingPairEnabled()) {
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900625 setDefaults();
626 }
Luke Huang19b49c52018-10-22 12:12:05 +0900627 return -ENODEV;
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900628 }
629
Hungming Chen1da90082020-02-14 20:24:16 +0800630 maybeStartBpf(extIface);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900631 return 0;
632}
633
Luke Huangae038f82018-11-05 11:17:31 +0900634int TetherController::setTetherGlobalAlertRule() {
635 // Only add this if we are the first enabled nat
636 if (isAnyForwardingPairEnabled()) {
637 return 0;
638 }
639 const std::string cmds =
640 "*filter\n" +
641 StringPrintf("-I %s -j %s\n", LOCAL_FORWARD, BandwidthController::LOCAL_GLOBAL_ALERT) +
642 "COMMIT\n";
643
644 return iptablesRestoreFunction(V4V6, cmds, nullptr);
645}
646
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900647int TetherController::setupIPv6CountersChain() {
648 // Only add this if we are the first enabled nat
649 if (isAnyForwardingPairEnabled()) {
650 return 0;
651 }
652
653 /*
654 * IPv6 tethering doesn't need the state-based conntrack rules, so
655 * it unconditionally jumps to the tether counters chain all the time.
656 */
Luke Huangae038f82018-11-05 11:17:31 +0900657 const std::string v6Cmds =
658 "*filter\n" +
659 StringPrintf("-A %s -g %s\n", LOCAL_FORWARD, LOCAL_TETHER_COUNTERS_CHAIN) + "COMMIT\n";
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900660
Luke Huangae038f82018-11-05 11:17:31 +0900661 return iptablesRestoreFunction(V6, v6Cmds, nullptr);
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900662}
663
664// Gets a pointer to the ForwardingDownstream for an interface pair in the map, or nullptr
665TetherController::ForwardingDownstream* TetherController::findForwardingDownstream(
666 const std::string& intIface, const std::string& extIface) {
667 auto extIfaceMatches = mFwdIfaces.equal_range(extIface);
668 for (auto it = extIfaceMatches.first; it != extIfaceMatches.second; ++it) {
669 if (it->second.iface == intIface) {
670 return &(it->second);
671 }
672 }
673 return nullptr;
674}
675
676void TetherController::addForwardingPair(const std::string& intIface, const std::string& extIface) {
677 ForwardingDownstream* existingEntry = findForwardingDownstream(intIface, extIface);
678 if (existingEntry != nullptr) {
679 existingEntry->active = true;
680 return;
681 }
682
683 mFwdIfaces.insert(std::pair<std::string, ForwardingDownstream>(extIface, {
684 .iface = intIface,
685 .active = true
686 }));
687}
688
689void TetherController::markForwardingPairDisabled(
690 const std::string& intIface, const std::string& extIface) {
691 ForwardingDownstream* existingEntry = findForwardingDownstream(intIface, extIface);
692 if (existingEntry == nullptr) {
693 return;
694 }
695
696 existingEntry->active = false;
697}
698
699bool TetherController::isForwardingPairEnabled(
700 const std::string& intIface, const std::string& extIface) {
701 ForwardingDownstream* existingEntry = findForwardingDownstream(intIface, extIface);
702 return existingEntry != nullptr && existingEntry->active;
703}
704
705bool TetherController::isAnyForwardingEnabledOnUpstream(const std::string& extIface) {
706 auto extIfaceMatches = mFwdIfaces.equal_range(extIface);
707 for (auto it = extIfaceMatches.first; it != extIfaceMatches.second; ++it) {
708 if (it->second.active) {
709 return true;
710 }
711 }
712 return false;
713}
714
715bool TetherController::isAnyForwardingPairEnabled() {
716 for (auto& it : mFwdIfaces) {
717 if (it.second.active) {
718 return true;
719 }
720 }
721 return false;
722}
723
724bool TetherController::tetherCountingRuleExists(
725 const std::string& iface1, const std::string& iface2) {
726 // A counting rule exists if NAT was ever enabled for this interface pair, so if the pair
727 // is in the map regardless of its active status. Rules are added both ways so we check with
728 // the 2 combinations.
729 return findForwardingDownstream(iface1, iface2) != nullptr
730 || findForwardingDownstream(iface2, iface1) != nullptr;
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900731}
732
733/* static */
734std::string TetherController::makeTetherCountingRule(const char *if1, const char *if2) {
735 return StringPrintf("-A %s -i %s -o %s -j RETURN", LOCAL_TETHER_COUNTERS_CHAIN, if1, if2);
736}
737
738int TetherController::setForwardRules(bool add, const char *intIface, const char *extIface) {
739 const char *op = add ? "-A" : "-D";
740
741 std::string rpfilterCmd = StringPrintf(
742 "*raw\n"
743 "%s %s -i %s -m rpfilter --invert ! -s fe80::/64 -j DROP\n"
744 "COMMIT\n", op, LOCAL_RAW_PREROUTING, intIface);
745 if (iptablesRestoreFunction(V6, rpfilterCmd, nullptr) == -1 && add) {
Luke Huang19b49c52018-10-22 12:12:05 +0900746 return -EREMOTEIO;
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900747 }
748
749 std::vector<std::string> v4 = {
hiroaki.yokoyama04f2cb52018-06-13 18:47:30 +0900750 "*raw",
751 StringPrintf("%s %s -p tcp --dport 21 -i %s -j CT --helper ftp", op,
752 LOCAL_RAW_PREROUTING, intIface),
753 StringPrintf("%s %s -p tcp --dport 1723 -i %s -j CT --helper pptp", op,
754 LOCAL_RAW_PREROUTING, intIface),
755 "COMMIT",
756 "*filter",
757 StringPrintf("%s %s -i %s -o %s -m state --state ESTABLISHED,RELATED -g %s", op,
758 LOCAL_FORWARD, extIface, intIface, LOCAL_TETHER_COUNTERS_CHAIN),
759 StringPrintf("%s %s -i %s -o %s -m state --state INVALID -j DROP", op, LOCAL_FORWARD,
760 intIface, extIface),
761 StringPrintf("%s %s -i %s -o %s -g %s", op, LOCAL_FORWARD, intIface, extIface,
762 LOCAL_TETHER_COUNTERS_CHAIN),
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900763 };
764
765 std::vector<std::string> v6 = {
766 "*filter",
767 };
768
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900769 // We only ever add tethering quota rules so that they stick.
770 if (add && !tetherCountingRuleExists(intIface, extIface)) {
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900771 v4.push_back(makeTetherCountingRule(intIface, extIface));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900772 v4.push_back(makeTetherCountingRule(extIface, intIface));
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900773 v6.push_back(makeTetherCountingRule(intIface, extIface));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900774 v6.push_back(makeTetherCountingRule(extIface, intIface));
775 }
776
777 // Always make sure the drop rule is at the end.
778 // TODO: instead of doing this, consider just rebuilding LOCAL_FORWARD completely from scratch
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900779 // every time, starting with ":tetherctrl_FORWARD -\n". This would likely be a bit simpler.
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900780 if (add) {
781 v4.push_back(StringPrintf("-D %s -j DROP", LOCAL_FORWARD));
782 v4.push_back(StringPrintf("-A %s -j DROP", LOCAL_FORWARD));
783 }
784
785 v4.push_back("COMMIT\n");
786 v6.push_back("COMMIT\n");
787
788 // We only add IPv6 rules here, never remove them.
789 if (iptablesRestoreFunction(V4, Join(v4, '\n'), nullptr) == -1 ||
790 (add && iptablesRestoreFunction(V6, Join(v6, '\n'), nullptr) == -1)) {
791 // unwind what's been done, but don't care about success - what more could we do?
792 if (add) {
793 setForwardRules(false, intIface, extIface);
794 }
Luke Huang19b49c52018-10-22 12:12:05 +0900795 return -EREMOTEIO;
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900796 }
797
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900798 if (add) {
799 addForwardingPair(intIface, extIface);
800 } else {
801 markForwardingPairDisabled(intIface, extIface);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900802 }
803
804 return 0;
805}
806
807int TetherController::disableNat(const char* intIface, const char* extIface) {
808 if (!isIfaceName(intIface) || !isIfaceName(extIface)) {
Luke Huangae038f82018-11-05 11:17:31 +0900809 errno = ENODEV;
810 return -errno;
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900811 }
812
813 setForwardRules(false, intIface, extIface);
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900814 if (!isAnyForwardingPairEnabled()) {
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900815 setDefaults();
816 }
Hungming Chen1da90082020-02-14 20:24:16 +0800817
818 maybeStopBpf(extIface);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900819 return 0;
820}
821
Lorenzo Colittie801d3c2020-02-18 00:00:35 +0900822Result<void> TetherController::addDownstreamIpv6Rule(int intIfaceIndex, int extIfaceIndex,
823 const std::vector<uint8_t>& ipAddress,
824 const std::vector<uint8_t>& srcL2Address,
825 const std::vector<uint8_t>& dstL2Address) {
826 ethhdr hdr = {
827 .h_proto = htons(ETH_P_IPV6),
828 };
829 if (ipAddress.size() != sizeof(in6_addr)) {
830 return Error(EINVAL) << "Invalid IP address length " << ipAddress.size();
831 }
832 if (srcL2Address.size() != sizeof(hdr.h_source)) {
833 return Error(EINVAL) << "Invalid L2 src address length " << srcL2Address.size();
834 }
835 if (dstL2Address.size() != sizeof(hdr.h_dest)) {
836 return Error(EINVAL) << "Invalid L2 dst address length " << dstL2Address.size();
837 }
838 memcpy(&hdr.h_dest, dstL2Address.data(), sizeof(hdr.h_dest));
839 memcpy(&hdr.h_source, srcL2Address.data(), sizeof(hdr.h_source));
840
841 TetherIngressKey key = {
842 .iif = static_cast<uint32_t>(extIfaceIndex),
843 .neigh6 = *(const in6_addr*)ipAddress.data(),
844 };
845
846 TetherIngressValue value = {
847 static_cast<uint32_t>(intIfaceIndex),
848 hdr,
849 };
850
851 return mBpfIngressMap.writeValue(key, value, BPF_ANY);
852}
853
854Result<void> TetherController::removeDownstreamIpv6Rule(int extIfaceIndex,
855 const std::vector<uint8_t>& ipAddress) {
856 if (ipAddress.size() != sizeof(in6_addr)) {
857 return Error(EINVAL) << "Invalid IP address length " << ipAddress.size();
858 }
859
860 TetherIngressKey key = {
861 .iif = static_cast<uint32_t>(extIfaceIndex),
862 .neigh6 = *(const in6_addr*)ipAddress.data(),
863 };
864
865 Result<void> ret = mBpfIngressMap.deleteValue(key);
866
867 // Silently return success if the rule did not exist.
868 if (!ret.ok() && ret.error().code() == ENOENT) return {};
869
870 return ret;
871}
872
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900873void TetherController::addStats(TetherStatsList& statsList, const TetherStats& stats) {
874 for (TetherStats& existing : statsList) {
875 if (existing.addStatsIfMatch(stats)) {
876 return;
877 }
878 }
879 // No match. Insert a new interface pair.
880 statsList.push_back(stats);
881}
882
883/*
884 * Parse the ptks and bytes out of:
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900885 * Chain tetherctrl_counters (4 references)
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900886 * pkts bytes target prot opt in out source destination
887 * 26 2373 RETURN all -- wlan0 rmnet0 0.0.0.0/0 0.0.0.0/0
888 * 27 2002 RETURN all -- rmnet0 wlan0 0.0.0.0/0 0.0.0.0/0
889 * 1040 107471 RETURN all -- bt-pan rmnet0 0.0.0.0/0 0.0.0.0/0
890 * 1450 1708806 RETURN all -- rmnet0 bt-pan 0.0.0.0/0 0.0.0.0/0
891 * or:
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900892 * Chain tetherctrl_counters (0 references)
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900893 * pkts bytes target prot opt in out source destination
894 * 0 0 RETURN all wlan0 rmnet_data0 ::/0 ::/0
895 * 0 0 RETURN all rmnet_data0 wlan0 ::/0 ::/0
896 *
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900897 */
Lorenzo Colitti09353392017-08-24 14:20:32 +0900898int TetherController::addForwardChainStats(TetherStatsList& statsList,
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900899 const std::string& statsOutput,
900 std::string &extraProcessingInfo) {
waynema71a0b592018-11-21 13:31:34 +0800901 enum IndexOfIptChain {
902 ORIG_LINE,
903 PACKET_COUNTS,
904 BYTE_COUNTS,
905 HYPHEN,
906 IFACE0_NAME,
907 IFACE1_NAME,
908 SOURCE,
909 DESTINATION
910 };
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900911 TetherStats stats;
Lorenzo Colitti09353392017-08-24 14:20:32 +0900912 const TetherStats empty;
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900913
waynema71a0b592018-11-21 13:31:34 +0800914 static const std::string NUM = "(\\d+)";
915 static const std::string IFACE = "([^\\s]+)";
916 static const std::string DST = "(0.0.0.0/0|::/0)";
917 static const std::string COUNTERS = "\\s*" + NUM + "\\s+" + NUM +
918 " RETURN all( -- | )" + IFACE + "\\s+" + IFACE +
919 "\\s+" + DST + "\\s+" + DST;
920 static const std::regex IP_RE(COUNTERS);
Lorenzo Colitti09353392017-08-24 14:20:32 +0900921
waynema71a0b592018-11-21 13:31:34 +0800922 const std::vector<std::string> lines = base::Split(statsOutput, "\n");
923 int headerLine = 0;
924 for (const std::string& line : lines) {
925 // Skip headers.
926 if (headerLine < 2) {
927 if (line.empty()) {
928 ALOGV("Empty header while parsing tethering stats");
929 return -EREMOTEIO;
930 }
931 headerLine++;
932 continue;
Lorenzo Colitti09353392017-08-24 14:20:32 +0900933 }
Lorenzo Colitti09353392017-08-24 14:20:32 +0900934
waynema71a0b592018-11-21 13:31:34 +0800935 if (line.empty()) continue;
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900936
waynema71a0b592018-11-21 13:31:34 +0800937 extraProcessingInfo = line;
938 std::smatch matches;
939 if (!std::regex_search(line, matches, IP_RE)) return -EREMOTEIO;
940 // Here use IP_RE to distiguish IPv4 and IPv6 iptables.
941 // IPv4 has "--" indicating what to do with fragments...
942 // 26 2373 RETURN all -- wlan0 rmnet0 0.0.0.0/0 0.0.0.0/0
943 // ... but IPv6 does not.
944 // 26 2373 RETURN all wlan0 rmnet0 ::/0 ::/0
945 // TODO: Replace strtoXX() calls with ParseUint() /ParseInt()
946 int64_t packets = strtoul(matches[PACKET_COUNTS].str().c_str(), nullptr, 10);
947 int64_t bytes = strtoul(matches[BYTE_COUNTS].str().c_str(), nullptr, 10);
948 std::string iface0 = matches[IFACE0_NAME].str();
949 std::string iface1 = matches[IFACE1_NAME].str();
950 std::string rest = matches[SOURCE].str();
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900951
waynema71a0b592018-11-21 13:31:34 +0800952 ALOGV("parse iface0=<%s> iface1=<%s> pkts=%" PRId64 " bytes=%" PRId64
953 " rest=<%s> orig line=<%s>",
954 iface0.c_str(), iface1.c_str(), packets, bytes, rest.c_str(), line.c_str());
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900955 /*
956 * The following assumes that the 1st rule has in:extIface out:intIface,
957 * which is what TetherController sets up.
Lorenzo Colitti09353392017-08-24 14:20:32 +0900958 * The 1st matches rx, and sets up the pair for the tx side.
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900959 */
Lorenzo Colitti09353392017-08-24 14:20:32 +0900960 if (!stats.intIface[0]) {
waynema71a0b592018-11-21 13:31:34 +0800961 ALOGV("0Filter RX iface_in=%s iface_out=%s rx_bytes=%" PRId64 " rx_packets=%" PRId64
962 " ", iface0.c_str(), iface1.c_str(), bytes, packets);
Lorenzo Colitti09353392017-08-24 14:20:32 +0900963 stats.intIface = iface0;
964 stats.extIface = iface1;
Lorenzo Colitti09353392017-08-24 14:20:32 +0900965 stats.txPackets = packets;
966 stats.txBytes = bytes;
Lorenzo Colitti9a65ac62017-09-04 18:07:56 +0900967 } else if (stats.intIface == iface1 && stats.extIface == iface0) {
waynema71a0b592018-11-21 13:31:34 +0800968 ALOGV("0Filter TX iface_in=%s iface_out=%s rx_bytes=%" PRId64 " rx_packets=%" PRId64
969 " ", iface0.c_str(), iface1.c_str(), bytes, packets);
Lorenzo Colitti9a65ac62017-09-04 18:07:56 +0900970 stats.rxPackets = packets;
971 stats.rxBytes = bytes;
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900972 }
973 if (stats.rxBytes != -1 && stats.txBytes != -1) {
Lorenzo Colitti09353392017-08-24 14:20:32 +0900974 ALOGV("rx_bytes=%" PRId64" tx_bytes=%" PRId64, stats.rxBytes, stats.txBytes);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900975 addStats(statsList, stats);
Lorenzo Colitti09353392017-08-24 14:20:32 +0900976 stats = empty;
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900977 }
978 }
979
980 /* It is always an error to find only one side of the stats. */
Lorenzo Colitti38fd1362017-09-15 11:40:01 +0900981 if (((stats.rxBytes == -1) != (stats.txBytes == -1))) {
Lorenzo Colitti9a8a9ff2017-01-31 19:06:59 +0900982 return -EREMOTEIO;
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900983 }
984 return 0;
985}
986
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900987StatusOr<TetherController::TetherStatsList> TetherController::getTetherStats() {
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900988 TetherStatsList statsList;
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900989 std::string parsedIptablesOutput;
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900990
991 for (const IptablesTarget target : {V4, V6}) {
992 std::string statsString;
Lorenzo Colitti09353392017-08-24 14:20:32 +0900993 if (int ret = iptablesRestoreFunction(target, GET_TETHER_STATS_COMMAND, &statsString)) {
Lorenzo Colitti9a8a9ff2017-01-31 19:06:59 +0900994 return statusFromErrno(-ret, StringPrintf("failed to fetch tether stats (%d): %d",
995 target, ret));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900996 }
997
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900998 if (int ret = addForwardChainStats(statsList, statsString, parsedIptablesOutput)) {
Lorenzo Colitti9a8a9ff2017-01-31 19:06:59 +0900999 return statusFromErrno(-ret, StringPrintf("failed to parse %s tether stats:\n%s",
1000 target == V4 ? "IPv4": "IPv6",
Lorenzo Colitti5192bf72017-09-04 13:30:59 +09001001 parsedIptablesOutput.c_str()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +09001002 }
1003 }
1004
Hungming Chen68dade32020-02-20 13:50:56 +08001005 if (!mBpfStatsMap.isValid()) {
1006 return statsList;
1007 }
Hungming Chenc2e95fb2020-02-19 17:41:30 +08001008
Hungming Chen68dade32020-02-20 13:50:56 +08001009 const auto processTetherStats = [this, &statsList](const uint32_t& key,
1010 const TetherStatsValue& value,
1011 const BpfMap<uint32_t, TetherStatsValue>&) {
1012 auto ifname = mIfaceIndexNameMap.readValue(key);
1013 if (!ifname.ok()) {
1014 // Keep on going regardless to parse as much as possible.
1015 return Result<void>();
Hungming Chenc2e95fb2020-02-19 17:41:30 +08001016 }
Hungming Chen68dade32020-02-20 13:50:56 +08001017 // Because the same interface name can have different interface IDs over time, there might
1018 // already be a TetherStats in the list with this interface name. This is fine because
1019 // addStats will increment an existing TetherStats if there is one in the list already,
1020 // and add a new TetherStats to the list if there isn't.
1021 addStats(statsList,
1022 {kBpfOffloadInterface, ifname.value().name, static_cast<int64_t>(value.rxBytes),
1023 static_cast<int64_t>(value.rxPackets), static_cast<int64_t>(value.txBytes),
1024 static_cast<int64_t>(value.txPackets)});
1025 return Result<void>();
1026 };
1027
1028 auto ret = mBpfStatsMap.iterateWithValue(processTetherStats);
1029 if (!ret.ok()) {
1030 // Ignore error to return the non-BPF tether stats result.
1031 ALOGE("Error processing tether stats from BPF maps: %s", ret.error().message().c_str());
Hungming Chenc2e95fb2020-02-19 17:41:30 +08001032 }
1033
Lorenzo Colitti9a8a9ff2017-01-31 19:06:59 +09001034 return statsList;
1035}
1036
Hungming Chen1da90082020-02-14 20:24:16 +08001037void TetherController::maybeStartBpf(const char* extIface) {
Maciej Żenczykowskiaef13012020-02-18 17:13:09 -08001038 if (!bpf::isBpfSupported()) return;
1039
Hungming Chen1da90082020-02-14 20:24:16 +08001040 // TODO: perhaps ignore IPv4-only interface because IPv4 traffic downstream is not supported.
1041 int ifIndex = if_nametoindex(extIface);
1042 if (!ifIndex) {
1043 ALOGE("Fail to get index for interface %s", extIface);
1044 return;
1045 }
1046
1047 auto isEthernet = android::net::isEthernet(extIface);
1048 if (!isEthernet.ok()) {
1049 ALOGE("isEthernet(%s[%d]) failure: %s", extIface, ifIndex,
1050 isEthernet.error().message().c_str());
1051 return;
1052 }
1053
1054 int rv = getTetherIngressProgFd(isEthernet.value());
1055 if (rv < 0) {
1056 ALOGE("getTetherIngressProgFd(%d) failure: %s", isEthernet.value(), strerror(-rv));
1057 return;
1058 }
1059 unique_fd tetherProgFd(rv);
1060
1061 rv = tcFilterAddDevIngressTether(ifIndex, tetherProgFd, isEthernet.value());
1062 if (rv) {
1063 ALOGE("tcFilterAddDevIngressTether(%d[%s], %d) failure: %s", ifIndex, extIface,
1064 isEthernet.value(), strerror(-rv));
1065 return;
1066 }
1067}
1068
1069void TetherController::maybeStopBpf(const char* extIface) {
Maciej Żenczykowskiaef13012020-02-18 17:13:09 -08001070 if (!bpf::isBpfSupported()) return;
1071
Hungming Chen1da90082020-02-14 20:24:16 +08001072 // TODO: perhaps ignore IPv4-only interface because IPv4 traffic downstream is not supported.
1073 int ifIndex = if_nametoindex(extIface);
1074 if (!ifIndex) {
1075 ALOGE("Fail to get index for interface %s", extIface);
1076 return;
1077 }
1078
1079 int rv = tcFilterDelDevIngressTether(ifIndex);
1080 if (rv < 0) {
1081 ALOGE("tcFilterDelDevIngressTether(%d[%s]) failure: %s", ifIndex, extIface, strerror(-rv));
1082 }
1083}
1084
Lorenzo Colitti52db3912020-02-17 23:59:45 +09001085void TetherController::dumpIfaces(DumpWriter& dw) {
1086 dw.println("Interface pairs:");
1087
1088 ScopedIndent ifaceIndent(dw);
1089 for (const auto& it : mFwdIfaces) {
1090 dw.println("%s -> %s %s", it.first.c_str(), it.second.iface.c_str(),
1091 (it.second.active ? "ACTIVE" : "DISABLED"));
1092 }
1093}
1094
Lorenzo Colittie801d3c2020-02-18 00:00:35 +09001095namespace {
1096
1097std::string l2ToString(const uint8_t* addr, size_t len) {
1098 std::string str;
1099
1100 if (len == 0) return str;
1101
1102 StringAppendF(&str, "%02x", addr[0]);
1103 for (size_t i = 1; i < len; i++) {
1104 StringAppendF(&str, ":%02x", addr[i]);
1105 }
1106
1107 return str;
1108}
1109
1110} // namespace
1111
1112void TetherController::dumpBpf(DumpWriter& dw) {
1113 if (!mBpfIngressMap.isValid() || !mBpfStatsMap.isValid()) {
1114 dw.println("BPF not supported");
1115 return;
1116 }
1117
1118 dw.println("BPF ingress map: iif v6addr -> oif srcmac dstmac ethertype");
1119 const auto printIngressMap = [&dw](const TetherIngressKey& key, const TetherIngressValue& value,
1120 const BpfMap<TetherIngressKey, TetherIngressValue>&) {
1121 char addr[INET6_ADDRSTRLEN];
1122 std::string src = l2ToString(value.macHeader.h_source, sizeof(value.macHeader.h_source));
1123 std::string dst = l2ToString(value.macHeader.h_dest, sizeof(value.macHeader.h_dest));
1124 inet_ntop(AF_INET6, &key.neigh6, addr, sizeof(addr));
1125
1126 dw.println("%d %s -> %d %s %s %04x", key.iif, addr, value.oif, src.c_str(), dst.c_str(),
1127 ntohs(value.macHeader.h_proto));
1128
1129 return Result<void>();
1130 };
1131
1132 dw.incIndent();
1133 auto ret = mBpfIngressMap.iterateWithValue(printIngressMap);
1134 if (!ret.ok()) {
1135 dw.println("Error printing BPF ingress map: %s", ret.error().message().c_str());
1136 }
1137 dw.decIndent();
1138
1139 dw.println("BPF stats (downlink): iif -> packets bytes errors");
1140 const auto printStatsMap = [&dw](const uint32_t& key, const TetherStatsValue& value,
1141 const BpfMap<uint32_t, TetherStatsValue>&) {
1142 dw.println("%d -> %" PRIu64 " %" PRIu64 " %" PRIu64, key, value.rxPackets, value.rxBytes,
1143 value.rxErrors);
1144
1145 return Result<void>();
1146 };
1147
1148 dw.incIndent();
1149 ret = mBpfStatsMap.iterateWithValue(printStatsMap);
1150 if (!ret.ok()) {
1151 dw.println("Error printing BPF stats map: %s", ret.error().message().c_str());
1152 }
1153 dw.decIndent();
1154}
1155
Lorenzo Colitti52db3912020-02-17 23:59:45 +09001156void TetherController::dump(DumpWriter& dw) {
1157 std::lock_guard guard(lock);
1158
1159 ScopedIndent tetherControllerIndent(dw);
1160 dw.println("TetherController");
1161 dw.incIndent();
1162
1163 dw.println("Forwarding requests: " + Join(mForwardingRequests, ' '));
1164 if (mDnsNetId != 0) {
1165 dw.println(StringPrintf("DNS: netId %d servers [%s]", mDnsNetId,
1166 Join(mDnsForwarders, ", ").c_str()));
1167 }
1168 if (mDaemonPid != 0) {
1169 dw.println("dnsmasq PID: %d", mDaemonPid);
1170 }
1171
1172 dumpIfaces(dw);
Lorenzo Colittie801d3c2020-02-18 00:00:35 +09001173 dw.println("");
1174 dumpBpf(dw);
Lorenzo Colitti52db3912020-02-17 23:59:45 +09001175}
1176
Lorenzo Colittie20a5262017-05-09 18:30:44 +09001177} // namespace net
1178} // namespace android