xref: /aosp_15_r20/system/netd/server/TetherController.cpp (revision 8542734a0dd1db395a4d42aae09c37f3c3c3e7a1)
1*8542734aSAndroid Build Coastguard Worker /*
2*8542734aSAndroid Build Coastguard Worker  * Copyright (C) 2008 The Android Open Source Project
3*8542734aSAndroid Build Coastguard Worker  *
4*8542734aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*8542734aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*8542734aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*8542734aSAndroid Build Coastguard Worker  *
8*8542734aSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*8542734aSAndroid Build Coastguard Worker  *
10*8542734aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*8542734aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*8542734aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8542734aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*8542734aSAndroid Build Coastguard Worker  * limitations under the License.
15*8542734aSAndroid Build Coastguard Worker  */
16*8542734aSAndroid Build Coastguard Worker 
17*8542734aSAndroid Build Coastguard Worker #include <errno.h>
18*8542734aSAndroid Build Coastguard Worker #include <fcntl.h>
19*8542734aSAndroid Build Coastguard Worker #include <inttypes.h>
20*8542734aSAndroid Build Coastguard Worker #include <netdb.h>
21*8542734aSAndroid Build Coastguard Worker #include <spawn.h>
22*8542734aSAndroid Build Coastguard Worker #include <string.h>
23*8542734aSAndroid Build Coastguard Worker 
24*8542734aSAndroid Build Coastguard Worker #include <sys/socket.h>
25*8542734aSAndroid Build Coastguard Worker #include <sys/stat.h>
26*8542734aSAndroid Build Coastguard Worker #include <sys/types.h>
27*8542734aSAndroid Build Coastguard Worker #include <sys/wait.h>
28*8542734aSAndroid Build Coastguard Worker 
29*8542734aSAndroid Build Coastguard Worker #include <netinet/in.h>
30*8542734aSAndroid Build Coastguard Worker #include <arpa/inet.h>
31*8542734aSAndroid Build Coastguard Worker 
32*8542734aSAndroid Build Coastguard Worker #include <array>
33*8542734aSAndroid Build Coastguard Worker #include <cstdlib>
34*8542734aSAndroid Build Coastguard Worker #include <regex>
35*8542734aSAndroid Build Coastguard Worker #include <string>
36*8542734aSAndroid Build Coastguard Worker #include <vector>
37*8542734aSAndroid Build Coastguard Worker 
38*8542734aSAndroid Build Coastguard Worker #define LOG_TAG "TetherController"
39*8542734aSAndroid Build Coastguard Worker #include <android-base/scopeguard.h>
40*8542734aSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
41*8542734aSAndroid Build Coastguard Worker #include <android-base/strings.h>
42*8542734aSAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
43*8542734aSAndroid Build Coastguard Worker #include <cutils/properties.h>
44*8542734aSAndroid Build Coastguard Worker #include <log/log.h>
45*8542734aSAndroid Build Coastguard Worker #include <net/if.h>
46*8542734aSAndroid Build Coastguard Worker #include <netdutils/DumpWriter.h>
47*8542734aSAndroid Build Coastguard Worker #include <netdutils/StatusOr.h>
48*8542734aSAndroid Build Coastguard Worker 
49*8542734aSAndroid Build Coastguard Worker #include "Controllers.h"
50*8542734aSAndroid Build Coastguard Worker #include "Fwmark.h"
51*8542734aSAndroid Build Coastguard Worker #include "InterfaceController.h"
52*8542734aSAndroid Build Coastguard Worker #include "NetdConstants.h"
53*8542734aSAndroid Build Coastguard Worker #include "NetworkController.h"
54*8542734aSAndroid Build Coastguard Worker #include "Permission.h"
55*8542734aSAndroid Build Coastguard Worker #include "TcUtils.h"
56*8542734aSAndroid Build Coastguard Worker #include "TetherController.h"
57*8542734aSAndroid Build Coastguard Worker 
58*8542734aSAndroid Build Coastguard Worker #include "android/net/TetherOffloadRuleParcel.h"
59*8542734aSAndroid Build Coastguard Worker 
60*8542734aSAndroid Build Coastguard Worker namespace android {
61*8542734aSAndroid Build Coastguard Worker namespace net {
62*8542734aSAndroid Build Coastguard Worker 
63*8542734aSAndroid Build Coastguard Worker using android::base::Join;
64*8542734aSAndroid Build Coastguard Worker using android::base::Pipe;
65*8542734aSAndroid Build Coastguard Worker using android::base::Result;
66*8542734aSAndroid Build Coastguard Worker using android::base::StringPrintf;
67*8542734aSAndroid Build Coastguard Worker using android::base::unique_fd;
68*8542734aSAndroid Build Coastguard Worker using android::netdutils::DumpWriter;
69*8542734aSAndroid Build Coastguard Worker using android::netdutils::ScopedIndent;
70*8542734aSAndroid Build Coastguard Worker using android::netdutils::statusFromErrno;
71*8542734aSAndroid Build Coastguard Worker using android::netdutils::StatusOr;
72*8542734aSAndroid Build Coastguard Worker 
73*8542734aSAndroid Build Coastguard Worker namespace {
74*8542734aSAndroid Build Coastguard Worker 
75*8542734aSAndroid Build Coastguard Worker const char BP_TOOLS_MODE[] = "bp-tools";
76*8542734aSAndroid Build Coastguard Worker const char IPV4_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv4/ip_forward";
77*8542734aSAndroid Build Coastguard Worker const char IPV6_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv6/conf/all/forwarding";
78*8542734aSAndroid Build Coastguard Worker const char SEPARATOR[] = "|";
79*8542734aSAndroid Build Coastguard Worker constexpr const char kTcpBeLiberal[] = "/proc/sys/net/netfilter/nf_conntrack_tcp_be_liberal";
80*8542734aSAndroid Build Coastguard Worker 
81*8542734aSAndroid Build Coastguard Worker // Chosen to match AID_DNS_TETHER, as made "friendly" by fs_config_generator.py.
82*8542734aSAndroid Build Coastguard Worker constexpr const char kDnsmasqUsername[] = "dns_tether";
83*8542734aSAndroid Build Coastguard Worker 
writeToFile(const char * filename,const char * value)84*8542734aSAndroid Build Coastguard Worker bool writeToFile(const char* filename, const char* value) {
85*8542734aSAndroid Build Coastguard Worker     int fd = open(filename, O_WRONLY | O_CLOEXEC);
86*8542734aSAndroid Build Coastguard Worker     if (fd < 0) {
87*8542734aSAndroid Build Coastguard Worker         ALOGE("Failed to open %s: %s", filename, strerror(errno));
88*8542734aSAndroid Build Coastguard Worker         return false;
89*8542734aSAndroid Build Coastguard Worker     }
90*8542734aSAndroid Build Coastguard Worker 
91*8542734aSAndroid Build Coastguard Worker     const ssize_t len = strlen(value);
92*8542734aSAndroid Build Coastguard Worker     if (write(fd, value, len) != len) {
93*8542734aSAndroid Build Coastguard Worker         ALOGE("Failed to write %s to %s: %s", value, filename, strerror(errno));
94*8542734aSAndroid Build Coastguard Worker         close(fd);
95*8542734aSAndroid Build Coastguard Worker         return false;
96*8542734aSAndroid Build Coastguard Worker     }
97*8542734aSAndroid Build Coastguard Worker     close(fd);
98*8542734aSAndroid Build Coastguard Worker     return true;
99*8542734aSAndroid Build Coastguard Worker }
100*8542734aSAndroid Build Coastguard Worker 
101*8542734aSAndroid Build Coastguard Worker // TODO: Consider altering TCP and UDP timeouts as well.
configureForTethering(bool enabled)102*8542734aSAndroid Build Coastguard Worker void configureForTethering(bool enabled) {
103*8542734aSAndroid Build Coastguard Worker     writeToFile(kTcpBeLiberal, enabled ? "1" : "0");
104*8542734aSAndroid Build Coastguard Worker }
105*8542734aSAndroid Build Coastguard Worker 
configureForIPv6Router(const char * interface)106*8542734aSAndroid Build Coastguard Worker bool configureForIPv6Router(const char *interface) {
107*8542734aSAndroid Build Coastguard Worker     return (InterfaceController::setEnableIPv6(interface, 0) == 0)
108*8542734aSAndroid Build Coastguard Worker             && (InterfaceController::setAcceptIPv6Ra(interface, 0) == 0)
109*8542734aSAndroid Build Coastguard Worker             && (InterfaceController::setAcceptIPv6Dad(interface, 0) == 0)
110*8542734aSAndroid Build Coastguard Worker             && (InterfaceController::setIPv6DadTransmits(interface, "0") == 0)
111*8542734aSAndroid Build Coastguard Worker             && (InterfaceController::setEnableIPv6(interface, 1) == 0);
112*8542734aSAndroid Build Coastguard Worker }
113*8542734aSAndroid Build Coastguard Worker 
configureForIPv6Client(const char * interface)114*8542734aSAndroid Build Coastguard Worker void configureForIPv6Client(const char *interface) {
115*8542734aSAndroid Build Coastguard Worker     InterfaceController::setAcceptIPv6Ra(interface, 1);
116*8542734aSAndroid Build Coastguard Worker     InterfaceController::setAcceptIPv6Dad(interface, 1);
117*8542734aSAndroid Build Coastguard Worker     InterfaceController::setIPv6DadTransmits(interface, "1");
118*8542734aSAndroid Build Coastguard Worker     InterfaceController::setEnableIPv6(interface, 0);
119*8542734aSAndroid Build Coastguard Worker }
120*8542734aSAndroid Build Coastguard Worker 
inBpToolsMode()121*8542734aSAndroid Build Coastguard Worker bool inBpToolsMode() {
122*8542734aSAndroid Build Coastguard Worker     // In BP tools mode, do not disable IP forwarding
123*8542734aSAndroid Build Coastguard Worker     char bootmode[PROPERTY_VALUE_MAX] = {0};
124*8542734aSAndroid Build Coastguard Worker     property_get("ro.bootmode", bootmode, "unknown");
125*8542734aSAndroid Build Coastguard Worker     return !strcmp(BP_TOOLS_MODE, bootmode);
126*8542734aSAndroid Build Coastguard Worker }
127*8542734aSAndroid Build Coastguard Worker 
128*8542734aSAndroid Build Coastguard Worker }  // namespace
129*8542734aSAndroid Build Coastguard Worker 
130*8542734aSAndroid Build Coastguard Worker auto TetherController::iptablesRestoreFunction = execIptablesRestoreWithOutput;
131*8542734aSAndroid Build Coastguard Worker 
132*8542734aSAndroid Build Coastguard Worker const std::string GET_TETHER_STATS_COMMAND = StringPrintf(
133*8542734aSAndroid Build Coastguard Worker     "*filter\n"
134*8542734aSAndroid Build Coastguard Worker     "-nvx -L %s\n"
135*8542734aSAndroid Build Coastguard Worker     "COMMIT\n", android::net::TetherController::LOCAL_TETHER_COUNTERS_CHAIN);
136*8542734aSAndroid Build Coastguard Worker 
sendCmd(int daemonFd,const std::string & cmd)137*8542734aSAndroid Build Coastguard Worker int TetherController::DnsmasqState::sendCmd(int daemonFd, const std::string& cmd) {
138*8542734aSAndroid Build Coastguard Worker     if (cmd.empty()) return 0;
139*8542734aSAndroid Build Coastguard Worker 
140*8542734aSAndroid Build Coastguard Worker     gLog.log("Sending update msg to dnsmasq [%s]", cmd.c_str());
141*8542734aSAndroid Build Coastguard Worker     // Send the trailing \0 as well.
142*8542734aSAndroid Build Coastguard Worker     if (write(daemonFd, cmd.c_str(), cmd.size() + 1) < 0) {
143*8542734aSAndroid Build Coastguard Worker         gLog.error("Failed to send update command to dnsmasq (%s)", strerror(errno));
144*8542734aSAndroid Build Coastguard Worker         errno = EREMOTEIO;
145*8542734aSAndroid Build Coastguard Worker         return -1;
146*8542734aSAndroid Build Coastguard Worker     }
147*8542734aSAndroid Build Coastguard Worker     return 0;
148*8542734aSAndroid Build Coastguard Worker }
149*8542734aSAndroid Build Coastguard Worker 
clear()150*8542734aSAndroid Build Coastguard Worker void TetherController::DnsmasqState::clear() {
151*8542734aSAndroid Build Coastguard Worker     update_ifaces_cmd.clear();
152*8542734aSAndroid Build Coastguard Worker     update_dns_cmd.clear();
153*8542734aSAndroid Build Coastguard Worker }
154*8542734aSAndroid Build Coastguard Worker 
sendAllState(int daemonFd) const155*8542734aSAndroid Build Coastguard Worker int TetherController::DnsmasqState::sendAllState(int daemonFd) const {
156*8542734aSAndroid Build Coastguard Worker     return sendCmd(daemonFd, update_ifaces_cmd) | sendCmd(daemonFd, update_dns_cmd);
157*8542734aSAndroid Build Coastguard Worker }
158*8542734aSAndroid Build Coastguard Worker 
TetherController()159*8542734aSAndroid Build Coastguard Worker TetherController::TetherController() {
160*8542734aSAndroid Build Coastguard Worker     gLog.info("enter TetherController ctor");
161*8542734aSAndroid Build Coastguard Worker     if (inBpToolsMode()) {
162*8542734aSAndroid Build Coastguard Worker         enableForwarding(BP_TOOLS_MODE);
163*8542734aSAndroid Build Coastguard Worker     } else {
164*8542734aSAndroid Build Coastguard Worker         setIpFwdEnabled();
165*8542734aSAndroid Build Coastguard Worker     }
166*8542734aSAndroid Build Coastguard Worker     gLog.info("leave TetherController ctor");
167*8542734aSAndroid Build Coastguard Worker }
168*8542734aSAndroid Build Coastguard Worker 
setIpFwdEnabled()169*8542734aSAndroid Build Coastguard Worker bool TetherController::setIpFwdEnabled() {
170*8542734aSAndroid Build Coastguard Worker     bool success = true;
171*8542734aSAndroid Build Coastguard Worker     bool disable = mForwardingRequests.empty();
172*8542734aSAndroid Build Coastguard Worker     const char* value = disable ? "0" : "1";
173*8542734aSAndroid Build Coastguard Worker     ALOGD("Setting IP forward enable = %s", value);
174*8542734aSAndroid Build Coastguard Worker     success &= writeToFile(IPV4_FORWARDING_PROC_FILE, value);
175*8542734aSAndroid Build Coastguard Worker     success &= writeToFile(IPV6_FORWARDING_PROC_FILE, value);
176*8542734aSAndroid Build Coastguard Worker     if (disable) {
177*8542734aSAndroid Build Coastguard Worker         // Turning off the forwarding sysconf in the kernel has the side effect
178*8542734aSAndroid Build Coastguard Worker         // of turning on ICMP redirect, which is a security hazard.
179*8542734aSAndroid Build Coastguard Worker         // Turn ICMP redirect back off immediately.
180*8542734aSAndroid Build Coastguard Worker         int rv = InterfaceController::disableIcmpRedirects();
181*8542734aSAndroid Build Coastguard Worker         success &= (rv == 0);
182*8542734aSAndroid Build Coastguard Worker     }
183*8542734aSAndroid Build Coastguard Worker     return success;
184*8542734aSAndroid Build Coastguard Worker }
185*8542734aSAndroid Build Coastguard Worker 
enableForwarding(const char * requester)186*8542734aSAndroid Build Coastguard Worker bool TetherController::enableForwarding(const char* requester) {
187*8542734aSAndroid Build Coastguard Worker     // Don't return an error if this requester already requested forwarding. Only return errors for
188*8542734aSAndroid Build Coastguard Worker     // things that the caller caller needs to care about, such as "couldn't write to the file to
189*8542734aSAndroid Build Coastguard Worker     // enable forwarding".
190*8542734aSAndroid Build Coastguard Worker     mForwardingRequests.insert(requester);
191*8542734aSAndroid Build Coastguard Worker     return setIpFwdEnabled();
192*8542734aSAndroid Build Coastguard Worker }
193*8542734aSAndroid Build Coastguard Worker 
disableForwarding(const char * requester)194*8542734aSAndroid Build Coastguard Worker bool TetherController::disableForwarding(const char* requester) {
195*8542734aSAndroid Build Coastguard Worker     mForwardingRequests.erase(requester);
196*8542734aSAndroid Build Coastguard Worker     return setIpFwdEnabled();
197*8542734aSAndroid Build Coastguard Worker }
198*8542734aSAndroid Build Coastguard Worker 
getIpfwdRequesterList() const199*8542734aSAndroid Build Coastguard Worker const std::set<std::string>& TetherController::getIpfwdRequesterList() const {
200*8542734aSAndroid Build Coastguard Worker     return mForwardingRequests;
201*8542734aSAndroid Build Coastguard Worker }
202*8542734aSAndroid Build Coastguard Worker 
startTethering(bool usingLegacyDnsProxy,int num_addrs,char ** dhcp_ranges)203*8542734aSAndroid Build Coastguard Worker int TetherController::startTethering(bool usingLegacyDnsProxy, int num_addrs, char** dhcp_ranges) {
204*8542734aSAndroid Build Coastguard Worker     if (!usingLegacyDnsProxy && num_addrs == 0) {
205*8542734aSAndroid Build Coastguard Worker         // Both DHCP and DnsProxy are disabled, we don't need to start dnsmasq
206*8542734aSAndroid Build Coastguard Worker         configureForTethering(true);
207*8542734aSAndroid Build Coastguard Worker         mIsTetheringStarted = true;
208*8542734aSAndroid Build Coastguard Worker         return 0;
209*8542734aSAndroid Build Coastguard Worker     }
210*8542734aSAndroid Build Coastguard Worker 
211*8542734aSAndroid Build Coastguard Worker     if (mIsTetheringStarted) {
212*8542734aSAndroid Build Coastguard Worker         ALOGE("Tethering already started");
213*8542734aSAndroid Build Coastguard Worker         errno = EBUSY;
214*8542734aSAndroid Build Coastguard Worker         return -errno;
215*8542734aSAndroid Build Coastguard Worker     }
216*8542734aSAndroid Build Coastguard Worker 
217*8542734aSAndroid Build Coastguard Worker     ALOGD("Starting tethering services");
218*8542734aSAndroid Build Coastguard Worker 
219*8542734aSAndroid Build Coastguard Worker     unique_fd pipeRead, pipeWrite;
220*8542734aSAndroid Build Coastguard Worker     if (!Pipe(&pipeRead, &pipeWrite, O_CLOEXEC)) {
221*8542734aSAndroid Build Coastguard Worker         int res = errno;
222*8542734aSAndroid Build Coastguard Worker         ALOGE("pipe2() failed (%s)", strerror(errno));
223*8542734aSAndroid Build Coastguard Worker         return -res;
224*8542734aSAndroid Build Coastguard Worker     }
225*8542734aSAndroid Build Coastguard Worker 
226*8542734aSAndroid Build Coastguard Worker     // Set parameters
227*8542734aSAndroid Build Coastguard Worker     Fwmark fwmark;
228*8542734aSAndroid Build Coastguard Worker     fwmark.netId = NetworkController::LOCAL_NET_ID;
229*8542734aSAndroid Build Coastguard Worker     fwmark.explicitlySelected = true;
230*8542734aSAndroid Build Coastguard Worker     fwmark.protectedFromVpn = true;
231*8542734aSAndroid Build Coastguard Worker     fwmark.permission = PERMISSION_SYSTEM;
232*8542734aSAndroid Build Coastguard Worker     char markStr[UINT32_HEX_STRLEN];
233*8542734aSAndroid Build Coastguard Worker     snprintf(markStr, sizeof(markStr), "0x%x", fwmark.intValue);
234*8542734aSAndroid Build Coastguard Worker 
235*8542734aSAndroid Build Coastguard Worker     std::vector<std::string> argVector = {
236*8542734aSAndroid Build Coastguard Worker             "/system/bin/dnsmasq",
237*8542734aSAndroid Build Coastguard Worker             "--keep-in-foreground",
238*8542734aSAndroid Build Coastguard Worker             "--no-resolv",
239*8542734aSAndroid Build Coastguard Worker             "--no-poll",
240*8542734aSAndroid Build Coastguard Worker             "--dhcp-authoritative",
241*8542734aSAndroid Build Coastguard Worker             // TODO: pipe through metered status from ConnService
242*8542734aSAndroid Build Coastguard Worker             "--dhcp-option-force=43,ANDROID_METERED",
243*8542734aSAndroid Build Coastguard Worker             "--pid-file",
244*8542734aSAndroid Build Coastguard Worker             "--listen-mark",
245*8542734aSAndroid Build Coastguard Worker             markStr,
246*8542734aSAndroid Build Coastguard Worker             "--user",
247*8542734aSAndroid Build Coastguard Worker             kDnsmasqUsername,
248*8542734aSAndroid Build Coastguard Worker     };
249*8542734aSAndroid Build Coastguard Worker 
250*8542734aSAndroid Build Coastguard Worker     if (!usingLegacyDnsProxy) {
251*8542734aSAndroid Build Coastguard Worker         argVector.push_back("--port=0");
252*8542734aSAndroid Build Coastguard Worker     }
253*8542734aSAndroid Build Coastguard Worker 
254*8542734aSAndroid Build Coastguard Worker     // DHCP server will be disabled if num_addrs == 0 and no --dhcp-range is passed.
255*8542734aSAndroid Build Coastguard Worker     for (int addrIndex = 0; addrIndex < num_addrs; addrIndex += 2) {
256*8542734aSAndroid Build Coastguard Worker         argVector.push_back(StringPrintf("--dhcp-range=%s,%s,1h", dhcp_ranges[addrIndex],
257*8542734aSAndroid Build Coastguard Worker                                          dhcp_ranges[addrIndex + 1]));
258*8542734aSAndroid Build Coastguard Worker     }
259*8542734aSAndroid Build Coastguard Worker 
260*8542734aSAndroid Build Coastguard Worker     std::vector<char*> args(argVector.size() + 1);
261*8542734aSAndroid Build Coastguard Worker     for (unsigned i = 0; i < argVector.size(); i++) {
262*8542734aSAndroid Build Coastguard Worker         args[i] = (char*)argVector[i].c_str();
263*8542734aSAndroid Build Coastguard Worker     }
264*8542734aSAndroid Build Coastguard Worker 
265*8542734aSAndroid Build Coastguard Worker     /*
266*8542734aSAndroid Build Coastguard Worker      * TODO: Create a monitoring thread to handle and restart
267*8542734aSAndroid Build Coastguard Worker      * the daemon if it exits prematurely
268*8542734aSAndroid Build Coastguard Worker      */
269*8542734aSAndroid Build Coastguard Worker 
270*8542734aSAndroid Build Coastguard Worker     // Note that don't modify any memory between vfork and execv.
271*8542734aSAndroid Build Coastguard Worker     // Changing state of file descriptors would be fine. See posix_spawn_file_actions_add*
272*8542734aSAndroid Build Coastguard Worker     // dup2 creates fd without CLOEXEC, dnsmasq will receive commands through the
273*8542734aSAndroid Build Coastguard Worker     // duplicated fd.
274*8542734aSAndroid Build Coastguard Worker     posix_spawn_file_actions_t fa;
275*8542734aSAndroid Build Coastguard Worker     int res = posix_spawn_file_actions_init(&fa);
276*8542734aSAndroid Build Coastguard Worker     if (res) {
277*8542734aSAndroid Build Coastguard Worker         ALOGE("posix_spawn_file_actions_init failed (%s)", strerror(res));
278*8542734aSAndroid Build Coastguard Worker         return -res;
279*8542734aSAndroid Build Coastguard Worker     }
280*8542734aSAndroid Build Coastguard Worker     const android::base::ScopeGuard faGuard = [&] { posix_spawn_file_actions_destroy(&fa); };
281*8542734aSAndroid Build Coastguard Worker     res = posix_spawn_file_actions_adddup2(&fa, pipeRead.get(), STDIN_FILENO);
282*8542734aSAndroid Build Coastguard Worker     if (res) {
283*8542734aSAndroid Build Coastguard Worker         ALOGE("posix_spawn_file_actions_adddup2 failed (%s)", strerror(res));
284*8542734aSAndroid Build Coastguard Worker         return -res;
285*8542734aSAndroid Build Coastguard Worker     }
286*8542734aSAndroid Build Coastguard Worker 
287*8542734aSAndroid Build Coastguard Worker     posix_spawnattr_t attr;
288*8542734aSAndroid Build Coastguard Worker     res = posix_spawnattr_init(&attr);
289*8542734aSAndroid Build Coastguard Worker     if (res) {
290*8542734aSAndroid Build Coastguard Worker         ALOGE("posix_spawnattr_init failed (%s)", strerror(res));
291*8542734aSAndroid Build Coastguard Worker         return -res;
292*8542734aSAndroid Build Coastguard Worker     }
293*8542734aSAndroid Build Coastguard Worker     const android::base::ScopeGuard attrGuard = [&] { posix_spawnattr_destroy(&attr); };
294*8542734aSAndroid Build Coastguard Worker     res = posix_spawnattr_setflags(&attr, POSIX_SPAWN_USEVFORK | POSIX_SPAWN_CLOEXEC_DEFAULT);
295*8542734aSAndroid Build Coastguard Worker     if (res) {
296*8542734aSAndroid Build Coastguard Worker         ALOGE("posix_spawnattr_setflags failed (%s)", strerror(res));
297*8542734aSAndroid Build Coastguard Worker         return -res;
298*8542734aSAndroid Build Coastguard Worker     }
299*8542734aSAndroid Build Coastguard Worker 
300*8542734aSAndroid Build Coastguard Worker     pid_t pid;
301*8542734aSAndroid Build Coastguard Worker     res = posix_spawn(&pid, args[0], &fa, &attr, &args[0], nullptr);
302*8542734aSAndroid Build Coastguard Worker     if (res) {
303*8542734aSAndroid Build Coastguard Worker         ALOGE("posix_spawn failed (%s)", strerror(res));
304*8542734aSAndroid Build Coastguard Worker         return -res;
305*8542734aSAndroid Build Coastguard Worker     }
306*8542734aSAndroid Build Coastguard Worker     mDaemonPid = pid;
307*8542734aSAndroid Build Coastguard Worker     mDaemonFd = pipeWrite.release();
308*8542734aSAndroid Build Coastguard Worker     configureForTethering(true);
309*8542734aSAndroid Build Coastguard Worker     mIsTetheringStarted = true;
310*8542734aSAndroid Build Coastguard Worker     applyDnsInterfaces();
311*8542734aSAndroid Build Coastguard Worker     ALOGD("Tethering services running");
312*8542734aSAndroid Build Coastguard Worker 
313*8542734aSAndroid Build Coastguard Worker     return 0;
314*8542734aSAndroid Build Coastguard Worker }
315*8542734aSAndroid Build Coastguard Worker 
toCstrVec(const std::vector<std::string> & addrs)316*8542734aSAndroid Build Coastguard Worker std::vector<char*> TetherController::toCstrVec(const std::vector<std::string>& addrs) {
317*8542734aSAndroid Build Coastguard Worker     std::vector<char*> addrsCstrVec{};
318*8542734aSAndroid Build Coastguard Worker     addrsCstrVec.reserve(addrs.size());
319*8542734aSAndroid Build Coastguard Worker     for (const auto& addr : addrs) {
320*8542734aSAndroid Build Coastguard Worker         addrsCstrVec.push_back(const_cast<char*>(addr.data()));
321*8542734aSAndroid Build Coastguard Worker     }
322*8542734aSAndroid Build Coastguard Worker     return addrsCstrVec;
323*8542734aSAndroid Build Coastguard Worker }
324*8542734aSAndroid Build Coastguard Worker 
startTethering(bool usingLegacyDnsProxy,const std::vector<std::string> & dhcpRanges)325*8542734aSAndroid Build Coastguard Worker int TetherController::startTethering(bool usingLegacyDnsProxy,
326*8542734aSAndroid Build Coastguard Worker                                      const std::vector<std::string>& dhcpRanges) {
327*8542734aSAndroid Build Coastguard Worker     struct in_addr v4_addr;
328*8542734aSAndroid Build Coastguard Worker     for (const auto& dhcpRange : dhcpRanges) {
329*8542734aSAndroid Build Coastguard Worker         if (!inet_aton(dhcpRange.c_str(), &v4_addr)) {
330*8542734aSAndroid Build Coastguard Worker             return -EINVAL;
331*8542734aSAndroid Build Coastguard Worker         }
332*8542734aSAndroid Build Coastguard Worker     }
333*8542734aSAndroid Build Coastguard Worker     auto dhcp_ranges = toCstrVec(dhcpRanges);
334*8542734aSAndroid Build Coastguard Worker     return startTethering(usingLegacyDnsProxy, dhcp_ranges.size(), dhcp_ranges.data());
335*8542734aSAndroid Build Coastguard Worker }
336*8542734aSAndroid Build Coastguard Worker 
stopTethering()337*8542734aSAndroid Build Coastguard Worker int TetherController::stopTethering() {
338*8542734aSAndroid Build Coastguard Worker     configureForTethering(false);
339*8542734aSAndroid Build Coastguard Worker 
340*8542734aSAndroid Build Coastguard Worker     if (!mIsTetheringStarted) {
341*8542734aSAndroid Build Coastguard Worker         ALOGE("Tethering already stopped");
342*8542734aSAndroid Build Coastguard Worker         return 0;
343*8542734aSAndroid Build Coastguard Worker     }
344*8542734aSAndroid Build Coastguard Worker 
345*8542734aSAndroid Build Coastguard Worker     mIsTetheringStarted = false;
346*8542734aSAndroid Build Coastguard Worker     // dnsmasq is not started
347*8542734aSAndroid Build Coastguard Worker     if (mDaemonPid == 0) {
348*8542734aSAndroid Build Coastguard Worker         return 0;
349*8542734aSAndroid Build Coastguard Worker     }
350*8542734aSAndroid Build Coastguard Worker 
351*8542734aSAndroid Build Coastguard Worker     ALOGD("Stopping tethering services");
352*8542734aSAndroid Build Coastguard Worker 
353*8542734aSAndroid Build Coastguard Worker     ::stopProcess(mDaemonPid, "tethering(dnsmasq)");
354*8542734aSAndroid Build Coastguard Worker     mDaemonPid = 0;
355*8542734aSAndroid Build Coastguard Worker     close(mDaemonFd);
356*8542734aSAndroid Build Coastguard Worker     mDaemonFd = -1;
357*8542734aSAndroid Build Coastguard Worker     mDnsmasqState.clear();
358*8542734aSAndroid Build Coastguard Worker     ALOGD("Tethering services stopped");
359*8542734aSAndroid Build Coastguard Worker     return 0;
360*8542734aSAndroid Build Coastguard Worker }
361*8542734aSAndroid Build Coastguard Worker 
isTetheringStarted()362*8542734aSAndroid Build Coastguard Worker bool TetherController::isTetheringStarted() {
363*8542734aSAndroid Build Coastguard Worker     return mIsTetheringStarted;
364*8542734aSAndroid Build Coastguard Worker }
365*8542734aSAndroid Build Coastguard Worker 
366*8542734aSAndroid Build Coastguard Worker // dnsmasq can't parse commands larger than this due to the fixed-size buffer
367*8542734aSAndroid Build Coastguard Worker // in check_android_listeners(). The receiving buffer is 1024 bytes long, but
368*8542734aSAndroid Build Coastguard Worker // dnsmasq reads up to 1023 bytes.
369*8542734aSAndroid Build Coastguard Worker const size_t MAX_CMD_SIZE = 1023;
370*8542734aSAndroid Build Coastguard Worker 
371*8542734aSAndroid Build Coastguard Worker // TODO: Remove overload function and update this after NDC migration.
setDnsForwarders(unsigned netId,char ** servers,int numServers)372*8542734aSAndroid Build Coastguard Worker int TetherController::setDnsForwarders(unsigned netId, char **servers, int numServers) {
373*8542734aSAndroid Build Coastguard Worker     Fwmark fwmark;
374*8542734aSAndroid Build Coastguard Worker     fwmark.netId = netId;
375*8542734aSAndroid Build Coastguard Worker     fwmark.explicitlySelected = true;
376*8542734aSAndroid Build Coastguard Worker     fwmark.protectedFromVpn = true;
377*8542734aSAndroid Build Coastguard Worker     fwmark.permission = PERMISSION_SYSTEM;
378*8542734aSAndroid Build Coastguard Worker 
379*8542734aSAndroid Build Coastguard Worker     std::string daemonCmd = StringPrintf("update_dns%s0x%x", SEPARATOR, fwmark.intValue);
380*8542734aSAndroid Build Coastguard Worker 
381*8542734aSAndroid Build Coastguard Worker     mDnsForwarders.clear();
382*8542734aSAndroid Build Coastguard Worker     for (int i = 0; i < numServers; i++) {
383*8542734aSAndroid Build Coastguard Worker         ALOGD("setDnsForwarders(0x%x %d = '%s')", fwmark.intValue, i, servers[i]);
384*8542734aSAndroid Build Coastguard Worker 
385*8542734aSAndroid Build Coastguard Worker         addrinfo *res, hints = { .ai_flags = AI_NUMERICHOST };
386*8542734aSAndroid Build Coastguard Worker         int ret = getaddrinfo(servers[i], nullptr, &hints, &res);
387*8542734aSAndroid Build Coastguard Worker         freeaddrinfo(res);
388*8542734aSAndroid Build Coastguard Worker         if (ret) {
389*8542734aSAndroid Build Coastguard Worker             ALOGE("Failed to parse DNS server '%s'", servers[i]);
390*8542734aSAndroid Build Coastguard Worker             mDnsForwarders.clear();
391*8542734aSAndroid Build Coastguard Worker             errno = EINVAL;
392*8542734aSAndroid Build Coastguard Worker             return -errno;
393*8542734aSAndroid Build Coastguard Worker         }
394*8542734aSAndroid Build Coastguard Worker 
395*8542734aSAndroid Build Coastguard Worker         if (daemonCmd.size() + 1 + strlen(servers[i]) >= MAX_CMD_SIZE) {
396*8542734aSAndroid Build Coastguard Worker             ALOGE("Too many DNS servers listed");
397*8542734aSAndroid Build Coastguard Worker             break;
398*8542734aSAndroid Build Coastguard Worker         }
399*8542734aSAndroid Build Coastguard Worker 
400*8542734aSAndroid Build Coastguard Worker         daemonCmd += SEPARATOR;
401*8542734aSAndroid Build Coastguard Worker         daemonCmd += servers[i];
402*8542734aSAndroid Build Coastguard Worker         mDnsForwarders.push_back(servers[i]);
403*8542734aSAndroid Build Coastguard Worker     }
404*8542734aSAndroid Build Coastguard Worker 
405*8542734aSAndroid Build Coastguard Worker     mDnsNetId = netId;
406*8542734aSAndroid Build Coastguard Worker     mDnsmasqState.update_dns_cmd = std::move(daemonCmd);
407*8542734aSAndroid Build Coastguard Worker     if (mDaemonFd != -1) {
408*8542734aSAndroid Build Coastguard Worker         if (mDnsmasqState.sendAllState(mDaemonFd) != 0) {
409*8542734aSAndroid Build Coastguard Worker             mDnsForwarders.clear();
410*8542734aSAndroid Build Coastguard Worker             errno = EREMOTEIO;
411*8542734aSAndroid Build Coastguard Worker             return -errno;
412*8542734aSAndroid Build Coastguard Worker         }
413*8542734aSAndroid Build Coastguard Worker     }
414*8542734aSAndroid Build Coastguard Worker     return 0;
415*8542734aSAndroid Build Coastguard Worker }
416*8542734aSAndroid Build Coastguard Worker 
setDnsForwarders(unsigned netId,const std::vector<std::string> & servers)417*8542734aSAndroid Build Coastguard Worker int TetherController::setDnsForwarders(unsigned netId, const std::vector<std::string>& servers) {
418*8542734aSAndroid Build Coastguard Worker     auto dnsServers = toCstrVec(servers);
419*8542734aSAndroid Build Coastguard Worker     return setDnsForwarders(netId, dnsServers.data(), dnsServers.size());
420*8542734aSAndroid Build Coastguard Worker }
421*8542734aSAndroid Build Coastguard Worker 
getDnsNetId()422*8542734aSAndroid Build Coastguard Worker unsigned TetherController::getDnsNetId() {
423*8542734aSAndroid Build Coastguard Worker     return mDnsNetId;
424*8542734aSAndroid Build Coastguard Worker }
425*8542734aSAndroid Build Coastguard Worker 
getDnsForwarders() const426*8542734aSAndroid Build Coastguard Worker const std::list<std::string> &TetherController::getDnsForwarders() const {
427*8542734aSAndroid Build Coastguard Worker     return mDnsForwarders;
428*8542734aSAndroid Build Coastguard Worker }
429*8542734aSAndroid Build Coastguard Worker 
applyDnsInterfaces()430*8542734aSAndroid Build Coastguard Worker bool TetherController::applyDnsInterfaces() {
431*8542734aSAndroid Build Coastguard Worker     std::string daemonCmd = "update_ifaces";
432*8542734aSAndroid Build Coastguard Worker     bool haveInterfaces = false;
433*8542734aSAndroid Build Coastguard Worker 
434*8542734aSAndroid Build Coastguard Worker     for (const auto& ifname : mInterfaces) {
435*8542734aSAndroid Build Coastguard Worker         if (daemonCmd.size() + 1 + ifname.size() >= MAX_CMD_SIZE) {
436*8542734aSAndroid Build Coastguard Worker             ALOGE("Too many DNS servers listed");
437*8542734aSAndroid Build Coastguard Worker             break;
438*8542734aSAndroid Build Coastguard Worker         }
439*8542734aSAndroid Build Coastguard Worker 
440*8542734aSAndroid Build Coastguard Worker         daemonCmd += SEPARATOR;
441*8542734aSAndroid Build Coastguard Worker         daemonCmd += ifname;
442*8542734aSAndroid Build Coastguard Worker         haveInterfaces = true;
443*8542734aSAndroid Build Coastguard Worker     }
444*8542734aSAndroid Build Coastguard Worker 
445*8542734aSAndroid Build Coastguard Worker     if (!haveInterfaces) {
446*8542734aSAndroid Build Coastguard Worker         mDnsmasqState.update_ifaces_cmd.clear();
447*8542734aSAndroid Build Coastguard Worker     } else {
448*8542734aSAndroid Build Coastguard Worker         mDnsmasqState.update_ifaces_cmd = std::move(daemonCmd);
449*8542734aSAndroid Build Coastguard Worker         if (mDaemonFd != -1) return (mDnsmasqState.sendAllState(mDaemonFd) == 0);
450*8542734aSAndroid Build Coastguard Worker     }
451*8542734aSAndroid Build Coastguard Worker     return true;
452*8542734aSAndroid Build Coastguard Worker }
453*8542734aSAndroid Build Coastguard Worker 
tetherInterface(const char * interface)454*8542734aSAndroid Build Coastguard Worker int TetherController::tetherInterface(const char *interface) {
455*8542734aSAndroid Build Coastguard Worker     ALOGD("tetherInterface(%s)", interface);
456*8542734aSAndroid Build Coastguard Worker     if (!isIfaceName(interface)) {
457*8542734aSAndroid Build Coastguard Worker         errno = ENOENT;
458*8542734aSAndroid Build Coastguard Worker         return -errno;
459*8542734aSAndroid Build Coastguard Worker     }
460*8542734aSAndroid Build Coastguard Worker 
461*8542734aSAndroid Build Coastguard Worker     if (!configureForIPv6Router(interface)) {
462*8542734aSAndroid Build Coastguard Worker         configureForIPv6Client(interface);
463*8542734aSAndroid Build Coastguard Worker         return -EREMOTEIO;
464*8542734aSAndroid Build Coastguard Worker     }
465*8542734aSAndroid Build Coastguard Worker     mInterfaces.push_back(interface);
466*8542734aSAndroid Build Coastguard Worker 
467*8542734aSAndroid Build Coastguard Worker     if (!applyDnsInterfaces()) {
468*8542734aSAndroid Build Coastguard Worker         mInterfaces.pop_back();
469*8542734aSAndroid Build Coastguard Worker         configureForIPv6Client(interface);
470*8542734aSAndroid Build Coastguard Worker         return -EREMOTEIO;
471*8542734aSAndroid Build Coastguard Worker     } else {
472*8542734aSAndroid Build Coastguard Worker         return 0;
473*8542734aSAndroid Build Coastguard Worker     }
474*8542734aSAndroid Build Coastguard Worker }
475*8542734aSAndroid Build Coastguard Worker 
untetherInterface(const char * interface)476*8542734aSAndroid Build Coastguard Worker int TetherController::untetherInterface(const char *interface) {
477*8542734aSAndroid Build Coastguard Worker     ALOGD("untetherInterface(%s)", interface);
478*8542734aSAndroid Build Coastguard Worker 
479*8542734aSAndroid Build Coastguard Worker     for (auto it = mInterfaces.cbegin(); it != mInterfaces.cend(); ++it) {
480*8542734aSAndroid Build Coastguard Worker         if (!strcmp(interface, it->c_str())) {
481*8542734aSAndroid Build Coastguard Worker             mInterfaces.erase(it);
482*8542734aSAndroid Build Coastguard Worker 
483*8542734aSAndroid Build Coastguard Worker             configureForIPv6Client(interface);
484*8542734aSAndroid Build Coastguard Worker             return applyDnsInterfaces() ? 0 : -EREMOTEIO;
485*8542734aSAndroid Build Coastguard Worker         }
486*8542734aSAndroid Build Coastguard Worker     }
487*8542734aSAndroid Build Coastguard Worker     errno = ENOENT;
488*8542734aSAndroid Build Coastguard Worker     return -errno;
489*8542734aSAndroid Build Coastguard Worker }
490*8542734aSAndroid Build Coastguard Worker 
getTetheredInterfaceList() const491*8542734aSAndroid Build Coastguard Worker const std::list<std::string> &TetherController::getTetheredInterfaceList() const {
492*8542734aSAndroid Build Coastguard Worker     return mInterfaces;
493*8542734aSAndroid Build Coastguard Worker }
494*8542734aSAndroid Build Coastguard Worker 
setupIptablesHooks()495*8542734aSAndroid Build Coastguard Worker int TetherController::setupIptablesHooks() {
496*8542734aSAndroid Build Coastguard Worker     int res;
497*8542734aSAndroid Build Coastguard Worker     res = setDefaults();
498*8542734aSAndroid Build Coastguard Worker     if (res < 0) {
499*8542734aSAndroid Build Coastguard Worker         return res;
500*8542734aSAndroid Build Coastguard Worker     }
501*8542734aSAndroid Build Coastguard Worker 
502*8542734aSAndroid Build Coastguard Worker     // Used to limit downstream mss to the upstream pmtu so we don't end up fragmenting every large
503*8542734aSAndroid Build Coastguard Worker     // packet tethered devices send. This is IPv4-only, because in IPv6 we send the MTU in the RA.
504*8542734aSAndroid Build Coastguard Worker     // This is no longer optional and tethering will fail to start if it fails.
505*8542734aSAndroid Build Coastguard Worker     std::string mssRewriteCommand = StringPrintf(
506*8542734aSAndroid Build Coastguard Worker         "*mangle\n"
507*8542734aSAndroid Build Coastguard Worker         "-A %s -p tcp --tcp-flags SYN SYN -j TCPMSS --clamp-mss-to-pmtu\n"
508*8542734aSAndroid Build Coastguard Worker         "COMMIT\n", LOCAL_MANGLE_FORWARD);
509*8542734aSAndroid Build Coastguard Worker 
510*8542734aSAndroid Build Coastguard Worker     // This is for tethering counters. This chain is reached via --goto, and then RETURNS.
511*8542734aSAndroid Build Coastguard Worker     std::string defaultCommands = StringPrintf(
512*8542734aSAndroid Build Coastguard Worker         "*filter\n"
513*8542734aSAndroid Build Coastguard Worker         ":%s -\n"
514*8542734aSAndroid Build Coastguard Worker         "COMMIT\n", LOCAL_TETHER_COUNTERS_CHAIN);
515*8542734aSAndroid Build Coastguard Worker 
516*8542734aSAndroid Build Coastguard Worker     res = iptablesRestoreFunction(V4, mssRewriteCommand, nullptr);
517*8542734aSAndroid Build Coastguard Worker     if (res < 0) {
518*8542734aSAndroid Build Coastguard Worker         return res;
519*8542734aSAndroid Build Coastguard Worker     }
520*8542734aSAndroid Build Coastguard Worker 
521*8542734aSAndroid Build Coastguard Worker     res = iptablesRestoreFunction(V4V6, defaultCommands, nullptr);
522*8542734aSAndroid Build Coastguard Worker     if (res < 0) {
523*8542734aSAndroid Build Coastguard Worker         return res;
524*8542734aSAndroid Build Coastguard Worker     }
525*8542734aSAndroid Build Coastguard Worker 
526*8542734aSAndroid Build Coastguard Worker     mFwdIfaces.clear();
527*8542734aSAndroid Build Coastguard Worker 
528*8542734aSAndroid Build Coastguard Worker     return 0;
529*8542734aSAndroid Build Coastguard Worker }
530*8542734aSAndroid Build Coastguard Worker 
setDefaults()531*8542734aSAndroid Build Coastguard Worker int TetherController::setDefaults() {
532*8542734aSAndroid Build Coastguard Worker     std::string v4Cmd = StringPrintf(
533*8542734aSAndroid Build Coastguard Worker         "*filter\n"
534*8542734aSAndroid Build Coastguard Worker         ":%s -\n"
535*8542734aSAndroid Build Coastguard Worker         "-A %s -j DROP\n"
536*8542734aSAndroid Build Coastguard Worker         "COMMIT\n"
537*8542734aSAndroid Build Coastguard Worker         "*nat\n"
538*8542734aSAndroid Build Coastguard Worker         ":%s -\n"
539*8542734aSAndroid Build Coastguard Worker         "COMMIT\n", LOCAL_FORWARD, LOCAL_FORWARD, LOCAL_NAT_POSTROUTING);
540*8542734aSAndroid Build Coastguard Worker 
541*8542734aSAndroid Build Coastguard Worker     std::string v6Cmd = StringPrintf(
542*8542734aSAndroid Build Coastguard Worker             "*filter\n"
543*8542734aSAndroid Build Coastguard Worker             ":%s -\n"
544*8542734aSAndroid Build Coastguard Worker             "COMMIT\n"
545*8542734aSAndroid Build Coastguard Worker             "*raw\n"
546*8542734aSAndroid Build Coastguard Worker             ":%s -\n"
547*8542734aSAndroid Build Coastguard Worker             "COMMIT\n",
548*8542734aSAndroid Build Coastguard Worker             LOCAL_FORWARD, LOCAL_RAW_PREROUTING);
549*8542734aSAndroid Build Coastguard Worker 
550*8542734aSAndroid Build Coastguard Worker     int res = iptablesRestoreFunction(V4, v4Cmd, nullptr);
551*8542734aSAndroid Build Coastguard Worker     if (res < 0) {
552*8542734aSAndroid Build Coastguard Worker         return res;
553*8542734aSAndroid Build Coastguard Worker     }
554*8542734aSAndroid Build Coastguard Worker 
555*8542734aSAndroid Build Coastguard Worker     res = iptablesRestoreFunction(V6, v6Cmd, nullptr);
556*8542734aSAndroid Build Coastguard Worker     if (res < 0) {
557*8542734aSAndroid Build Coastguard Worker         return res;
558*8542734aSAndroid Build Coastguard Worker     }
559*8542734aSAndroid Build Coastguard Worker 
560*8542734aSAndroid Build Coastguard Worker     return 0;
561*8542734aSAndroid Build Coastguard Worker }
562*8542734aSAndroid Build Coastguard Worker 
enableNat(const char * intIface,const char * extIface)563*8542734aSAndroid Build Coastguard Worker int TetherController::enableNat(const char* intIface, const char* extIface) {
564*8542734aSAndroid Build Coastguard Worker     ALOGV("enableNat(intIface=<%s>, extIface=<%s>)",intIface, extIface);
565*8542734aSAndroid Build Coastguard Worker 
566*8542734aSAndroid Build Coastguard Worker     if (!isIfaceName(intIface) || !isIfaceName(extIface)) {
567*8542734aSAndroid Build Coastguard Worker         return -ENODEV;
568*8542734aSAndroid Build Coastguard Worker     }
569*8542734aSAndroid Build Coastguard Worker 
570*8542734aSAndroid Build Coastguard Worker     /* Bug: b/9565268. "enableNat wlan0 wlan0". For now we fail until java-land is fixed */
571*8542734aSAndroid Build Coastguard Worker     if (!strcmp(intIface, extIface)) {
572*8542734aSAndroid Build Coastguard Worker         ALOGE("Duplicate interface specified: %s %s", intIface, extIface);
573*8542734aSAndroid Build Coastguard Worker         return -EINVAL;
574*8542734aSAndroid Build Coastguard Worker     }
575*8542734aSAndroid Build Coastguard Worker 
576*8542734aSAndroid Build Coastguard Worker     if (isForwardingPairEnabled(intIface, extIface)) {
577*8542734aSAndroid Build Coastguard Worker         return 0;
578*8542734aSAndroid Build Coastguard Worker     }
579*8542734aSAndroid Build Coastguard Worker 
580*8542734aSAndroid Build Coastguard Worker     // add this if we are the first enabled nat for this upstream
581*8542734aSAndroid Build Coastguard Worker     if (!isAnyForwardingEnabledOnUpstream(extIface)) {
582*8542734aSAndroid Build Coastguard Worker         std::vector<std::string> v4Cmds = {
583*8542734aSAndroid Build Coastguard Worker             "*nat",
584*8542734aSAndroid Build Coastguard Worker             StringPrintf("-A %s -o %s -j MASQUERADE", LOCAL_NAT_POSTROUTING, extIface),
585*8542734aSAndroid Build Coastguard Worker             "COMMIT\n"
586*8542734aSAndroid Build Coastguard Worker         };
587*8542734aSAndroid Build Coastguard Worker 
588*8542734aSAndroid Build Coastguard Worker         if (iptablesRestoreFunction(V4, Join(v4Cmds, '\n'), nullptr) || setupIPv6CountersChain() ||
589*8542734aSAndroid Build Coastguard Worker             setTetherGlobalAlertRule()) {
590*8542734aSAndroid Build Coastguard Worker             ALOGE("Error setting postroute rule: iface=%s", extIface);
591*8542734aSAndroid Build Coastguard Worker             if (!isAnyForwardingPairEnabled()) {
592*8542734aSAndroid Build Coastguard Worker                 // unwind what's been done, but don't care about success - what more could we do?
593*8542734aSAndroid Build Coastguard Worker                 setDefaults();
594*8542734aSAndroid Build Coastguard Worker             }
595*8542734aSAndroid Build Coastguard Worker             return -EREMOTEIO;
596*8542734aSAndroid Build Coastguard Worker         }
597*8542734aSAndroid Build Coastguard Worker     }
598*8542734aSAndroid Build Coastguard Worker 
599*8542734aSAndroid Build Coastguard Worker     if (setForwardRules(true, intIface, extIface) != 0) {
600*8542734aSAndroid Build Coastguard Worker         ALOGE("Error setting forward rules");
601*8542734aSAndroid Build Coastguard Worker         if (!isAnyForwardingPairEnabled()) {
602*8542734aSAndroid Build Coastguard Worker             setDefaults();
603*8542734aSAndroid Build Coastguard Worker         }
604*8542734aSAndroid Build Coastguard Worker         return -ENODEV;
605*8542734aSAndroid Build Coastguard Worker     }
606*8542734aSAndroid Build Coastguard Worker 
607*8542734aSAndroid Build Coastguard Worker     return 0;
608*8542734aSAndroid Build Coastguard Worker }
609*8542734aSAndroid Build Coastguard Worker 
setTetherGlobalAlertRule()610*8542734aSAndroid Build Coastguard Worker int TetherController::setTetherGlobalAlertRule() {
611*8542734aSAndroid Build Coastguard Worker     // Only add this if we are the first enabled nat
612*8542734aSAndroid Build Coastguard Worker     if (isAnyForwardingPairEnabled()) {
613*8542734aSAndroid Build Coastguard Worker         return 0;
614*8542734aSAndroid Build Coastguard Worker     }
615*8542734aSAndroid Build Coastguard Worker     const std::string cmds =
616*8542734aSAndroid Build Coastguard Worker             "*filter\n" +
617*8542734aSAndroid Build Coastguard Worker             StringPrintf("-I %s -j %s\n", LOCAL_FORWARD, BandwidthController::LOCAL_GLOBAL_ALERT) +
618*8542734aSAndroid Build Coastguard Worker             "COMMIT\n";
619*8542734aSAndroid Build Coastguard Worker 
620*8542734aSAndroid Build Coastguard Worker     return iptablesRestoreFunction(V4V6, cmds, nullptr);
621*8542734aSAndroid Build Coastguard Worker }
622*8542734aSAndroid Build Coastguard Worker 
setupIPv6CountersChain()623*8542734aSAndroid Build Coastguard Worker int TetherController::setupIPv6CountersChain() {
624*8542734aSAndroid Build Coastguard Worker     // Only add this if we are the first enabled nat
625*8542734aSAndroid Build Coastguard Worker     if (isAnyForwardingPairEnabled()) {
626*8542734aSAndroid Build Coastguard Worker         return 0;
627*8542734aSAndroid Build Coastguard Worker     }
628*8542734aSAndroid Build Coastguard Worker 
629*8542734aSAndroid Build Coastguard Worker     /*
630*8542734aSAndroid Build Coastguard Worker      * IPv6 tethering doesn't need the state-based conntrack rules, so
631*8542734aSAndroid Build Coastguard Worker      * it unconditionally jumps to the tether counters chain all the time.
632*8542734aSAndroid Build Coastguard Worker      */
633*8542734aSAndroid Build Coastguard Worker     const std::string v6Cmds =
634*8542734aSAndroid Build Coastguard Worker             "*filter\n" +
635*8542734aSAndroid Build Coastguard Worker             StringPrintf("-A %s -g %s\n", LOCAL_FORWARD, LOCAL_TETHER_COUNTERS_CHAIN) + "COMMIT\n";
636*8542734aSAndroid Build Coastguard Worker 
637*8542734aSAndroid Build Coastguard Worker     return iptablesRestoreFunction(V6, v6Cmds, nullptr);
638*8542734aSAndroid Build Coastguard Worker }
639*8542734aSAndroid Build Coastguard Worker 
640*8542734aSAndroid Build Coastguard Worker // Gets a pointer to the ForwardingDownstream for an interface pair in the map, or nullptr
findForwardingDownstream(const std::string & intIface,const std::string & extIface)641*8542734aSAndroid Build Coastguard Worker TetherController::ForwardingDownstream* TetherController::findForwardingDownstream(
642*8542734aSAndroid Build Coastguard Worker         const std::string& intIface, const std::string& extIface) {
643*8542734aSAndroid Build Coastguard Worker     auto extIfaceMatches = mFwdIfaces.equal_range(extIface);
644*8542734aSAndroid Build Coastguard Worker     for (auto it = extIfaceMatches.first; it != extIfaceMatches.second; ++it) {
645*8542734aSAndroid Build Coastguard Worker         if (it->second.iface == intIface) {
646*8542734aSAndroid Build Coastguard Worker             return &(it->second);
647*8542734aSAndroid Build Coastguard Worker         }
648*8542734aSAndroid Build Coastguard Worker     }
649*8542734aSAndroid Build Coastguard Worker     return nullptr;
650*8542734aSAndroid Build Coastguard Worker }
651*8542734aSAndroid Build Coastguard Worker 
addForwardingPair(const std::string & intIface,const std::string & extIface)652*8542734aSAndroid Build Coastguard Worker void TetherController::addForwardingPair(const std::string& intIface, const std::string& extIface) {
653*8542734aSAndroid Build Coastguard Worker     ForwardingDownstream* existingEntry = findForwardingDownstream(intIface, extIface);
654*8542734aSAndroid Build Coastguard Worker     if (existingEntry != nullptr) {
655*8542734aSAndroid Build Coastguard Worker         existingEntry->active = true;
656*8542734aSAndroid Build Coastguard Worker         return;
657*8542734aSAndroid Build Coastguard Worker     }
658*8542734aSAndroid Build Coastguard Worker 
659*8542734aSAndroid Build Coastguard Worker     mFwdIfaces.insert(std::pair<std::string, ForwardingDownstream>(extIface, {
660*8542734aSAndroid Build Coastguard Worker         .iface = intIface,
661*8542734aSAndroid Build Coastguard Worker         .active = true
662*8542734aSAndroid Build Coastguard Worker     }));
663*8542734aSAndroid Build Coastguard Worker }
664*8542734aSAndroid Build Coastguard Worker 
markForwardingPairDisabled(const std::string & intIface,const std::string & extIface)665*8542734aSAndroid Build Coastguard Worker void TetherController::markForwardingPairDisabled(
666*8542734aSAndroid Build Coastguard Worker         const std::string& intIface, const std::string& extIface) {
667*8542734aSAndroid Build Coastguard Worker     ForwardingDownstream* existingEntry = findForwardingDownstream(intIface, extIface);
668*8542734aSAndroid Build Coastguard Worker     if (existingEntry == nullptr) {
669*8542734aSAndroid Build Coastguard Worker         return;
670*8542734aSAndroid Build Coastguard Worker     }
671*8542734aSAndroid Build Coastguard Worker 
672*8542734aSAndroid Build Coastguard Worker     existingEntry->active = false;
673*8542734aSAndroid Build Coastguard Worker }
674*8542734aSAndroid Build Coastguard Worker 
isForwardingPairEnabled(const std::string & intIface,const std::string & extIface)675*8542734aSAndroid Build Coastguard Worker bool TetherController::isForwardingPairEnabled(
676*8542734aSAndroid Build Coastguard Worker         const std::string& intIface, const std::string& extIface) {
677*8542734aSAndroid Build Coastguard Worker     ForwardingDownstream* existingEntry = findForwardingDownstream(intIface, extIface);
678*8542734aSAndroid Build Coastguard Worker     return existingEntry != nullptr && existingEntry->active;
679*8542734aSAndroid Build Coastguard Worker }
680*8542734aSAndroid Build Coastguard Worker 
isAnyForwardingEnabledOnUpstream(const std::string & extIface)681*8542734aSAndroid Build Coastguard Worker bool TetherController::isAnyForwardingEnabledOnUpstream(const std::string& extIface) {
682*8542734aSAndroid Build Coastguard Worker     auto extIfaceMatches = mFwdIfaces.equal_range(extIface);
683*8542734aSAndroid Build Coastguard Worker     for (auto it = extIfaceMatches.first; it != extIfaceMatches.second; ++it) {
684*8542734aSAndroid Build Coastguard Worker         if (it->second.active) {
685*8542734aSAndroid Build Coastguard Worker             return true;
686*8542734aSAndroid Build Coastguard Worker         }
687*8542734aSAndroid Build Coastguard Worker     }
688*8542734aSAndroid Build Coastguard Worker     return false;
689*8542734aSAndroid Build Coastguard Worker }
690*8542734aSAndroid Build Coastguard Worker 
isAnyForwardingPairEnabled()691*8542734aSAndroid Build Coastguard Worker bool TetherController::isAnyForwardingPairEnabled() {
692*8542734aSAndroid Build Coastguard Worker     for (auto& it : mFwdIfaces) {
693*8542734aSAndroid Build Coastguard Worker         if (it.second.active) {
694*8542734aSAndroid Build Coastguard Worker             return true;
695*8542734aSAndroid Build Coastguard Worker         }
696*8542734aSAndroid Build Coastguard Worker     }
697*8542734aSAndroid Build Coastguard Worker     return false;
698*8542734aSAndroid Build Coastguard Worker }
699*8542734aSAndroid Build Coastguard Worker 
tetherCountingRuleExists(const std::string & iface1,const std::string & iface2)700*8542734aSAndroid Build Coastguard Worker bool TetherController::tetherCountingRuleExists(
701*8542734aSAndroid Build Coastguard Worker         const std::string& iface1, const std::string& iface2) {
702*8542734aSAndroid Build Coastguard Worker     // A counting rule exists if NAT was ever enabled for this interface pair, so if the pair
703*8542734aSAndroid Build Coastguard Worker     // is in the map regardless of its active status. Rules are added both ways so we check with
704*8542734aSAndroid Build Coastguard Worker     // the 2 combinations.
705*8542734aSAndroid Build Coastguard Worker     return findForwardingDownstream(iface1, iface2) != nullptr
706*8542734aSAndroid Build Coastguard Worker         || findForwardingDownstream(iface2, iface1) != nullptr;
707*8542734aSAndroid Build Coastguard Worker }
708*8542734aSAndroid Build Coastguard Worker 
709*8542734aSAndroid Build Coastguard Worker /* static */
makeTetherCountingRule(const char * if1,const char * if2)710*8542734aSAndroid Build Coastguard Worker std::string TetherController::makeTetherCountingRule(const char *if1, const char *if2) {
711*8542734aSAndroid Build Coastguard Worker     return StringPrintf("-A %s -i %s -o %s -j RETURN", LOCAL_TETHER_COUNTERS_CHAIN, if1, if2);
712*8542734aSAndroid Build Coastguard Worker }
713*8542734aSAndroid Build Coastguard Worker 
setForwardRules(bool add,const char * intIface,const char * extIface)714*8542734aSAndroid Build Coastguard Worker int TetherController::setForwardRules(bool add, const char *intIface, const char *extIface) {
715*8542734aSAndroid Build Coastguard Worker     const char *op = add ? "-A" : "-D";
716*8542734aSAndroid Build Coastguard Worker 
717*8542734aSAndroid Build Coastguard Worker     std::string rpfilterCmd = StringPrintf(
718*8542734aSAndroid Build Coastguard Worker         "*raw\n"
719*8542734aSAndroid Build Coastguard Worker         "%s %s -i %s -m rpfilter --invert ! -s fe80::/64 -j DROP\n"
720*8542734aSAndroid Build Coastguard Worker         "COMMIT\n", op, LOCAL_RAW_PREROUTING, intIface);
721*8542734aSAndroid Build Coastguard Worker     if (iptablesRestoreFunction(V6, rpfilterCmd, nullptr) == -1 && add) {
722*8542734aSAndroid Build Coastguard Worker         return -EREMOTEIO;
723*8542734aSAndroid Build Coastguard Worker     }
724*8542734aSAndroid Build Coastguard Worker 
725*8542734aSAndroid Build Coastguard Worker     std::vector<std::string> v4 = {
726*8542734aSAndroid Build Coastguard Worker             "*raw",
727*8542734aSAndroid Build Coastguard Worker             StringPrintf("%s %s -p tcp --dport 21 -i %s -j CT --helper ftp", op,
728*8542734aSAndroid Build Coastguard Worker                          LOCAL_RAW_PREROUTING, intIface),
729*8542734aSAndroid Build Coastguard Worker             StringPrintf("%s %s -p tcp --dport 1723 -i %s -j CT --helper pptp", op,
730*8542734aSAndroid Build Coastguard Worker                          LOCAL_RAW_PREROUTING, intIface),
731*8542734aSAndroid Build Coastguard Worker             "COMMIT",
732*8542734aSAndroid Build Coastguard Worker             "*filter",
733*8542734aSAndroid Build Coastguard Worker             StringPrintf("%s %s -i %s -o %s -m state --state ESTABLISHED,RELATED -g %s", op,
734*8542734aSAndroid Build Coastguard Worker                          LOCAL_FORWARD, extIface, intIface, LOCAL_TETHER_COUNTERS_CHAIN),
735*8542734aSAndroid Build Coastguard Worker             StringPrintf("%s %s -i %s -o %s -m state --state INVALID -j DROP", op, LOCAL_FORWARD,
736*8542734aSAndroid Build Coastguard Worker                          intIface, extIface),
737*8542734aSAndroid Build Coastguard Worker             StringPrintf("%s %s -i %s -o %s -g %s", op, LOCAL_FORWARD, intIface, extIface,
738*8542734aSAndroid Build Coastguard Worker                          LOCAL_TETHER_COUNTERS_CHAIN),
739*8542734aSAndroid Build Coastguard Worker     };
740*8542734aSAndroid Build Coastguard Worker 
741*8542734aSAndroid Build Coastguard Worker     std::vector<std::string> v6 = {
742*8542734aSAndroid Build Coastguard Worker         "*filter",
743*8542734aSAndroid Build Coastguard Worker     };
744*8542734aSAndroid Build Coastguard Worker 
745*8542734aSAndroid Build Coastguard Worker     // We only ever add tethering quota rules so that they stick.
746*8542734aSAndroid Build Coastguard Worker     if (add && !tetherCountingRuleExists(intIface, extIface)) {
747*8542734aSAndroid Build Coastguard Worker         v4.push_back(makeTetherCountingRule(intIface, extIface));
748*8542734aSAndroid Build Coastguard Worker         v4.push_back(makeTetherCountingRule(extIface, intIface));
749*8542734aSAndroid Build Coastguard Worker         v6.push_back(makeTetherCountingRule(intIface, extIface));
750*8542734aSAndroid Build Coastguard Worker         v6.push_back(makeTetherCountingRule(extIface, intIface));
751*8542734aSAndroid Build Coastguard Worker     }
752*8542734aSAndroid Build Coastguard Worker 
753*8542734aSAndroid Build Coastguard Worker     // Always make sure the drop rule is at the end.
754*8542734aSAndroid Build Coastguard Worker     // TODO: instead of doing this, consider just rebuilding LOCAL_FORWARD completely from scratch
755*8542734aSAndroid Build Coastguard Worker     // every time, starting with ":tetherctrl_FORWARD -\n". This would likely be a bit simpler.
756*8542734aSAndroid Build Coastguard Worker     if (add) {
757*8542734aSAndroid Build Coastguard Worker         v4.push_back(StringPrintf("-D %s -j DROP", LOCAL_FORWARD));
758*8542734aSAndroid Build Coastguard Worker         v4.push_back(StringPrintf("-A %s -j DROP", LOCAL_FORWARD));
759*8542734aSAndroid Build Coastguard Worker     }
760*8542734aSAndroid Build Coastguard Worker 
761*8542734aSAndroid Build Coastguard Worker     v4.push_back("COMMIT\n");
762*8542734aSAndroid Build Coastguard Worker     v6.push_back("COMMIT\n");
763*8542734aSAndroid Build Coastguard Worker 
764*8542734aSAndroid Build Coastguard Worker     // We only add IPv6 rules here, never remove them.
765*8542734aSAndroid Build Coastguard Worker     if (iptablesRestoreFunction(V4, Join(v4, '\n'), nullptr) == -1 ||
766*8542734aSAndroid Build Coastguard Worker         (add && iptablesRestoreFunction(V6, Join(v6, '\n'), nullptr) == -1)) {
767*8542734aSAndroid Build Coastguard Worker         // unwind what's been done, but don't care about success - what more could we do?
768*8542734aSAndroid Build Coastguard Worker         if (add) {
769*8542734aSAndroid Build Coastguard Worker             setForwardRules(false, intIface, extIface);
770*8542734aSAndroid Build Coastguard Worker         }
771*8542734aSAndroid Build Coastguard Worker         return -EREMOTEIO;
772*8542734aSAndroid Build Coastguard Worker     }
773*8542734aSAndroid Build Coastguard Worker 
774*8542734aSAndroid Build Coastguard Worker     if (add) {
775*8542734aSAndroid Build Coastguard Worker         addForwardingPair(intIface, extIface);
776*8542734aSAndroid Build Coastguard Worker     } else {
777*8542734aSAndroid Build Coastguard Worker         markForwardingPairDisabled(intIface, extIface);
778*8542734aSAndroid Build Coastguard Worker     }
779*8542734aSAndroid Build Coastguard Worker 
780*8542734aSAndroid Build Coastguard Worker     return 0;
781*8542734aSAndroid Build Coastguard Worker }
782*8542734aSAndroid Build Coastguard Worker 
disableNat(const char * intIface,const char * extIface)783*8542734aSAndroid Build Coastguard Worker int TetherController::disableNat(const char* intIface, const char* extIface) {
784*8542734aSAndroid Build Coastguard Worker     if (!isIfaceName(intIface) || !isIfaceName(extIface)) {
785*8542734aSAndroid Build Coastguard Worker         errno = ENODEV;
786*8542734aSAndroid Build Coastguard Worker         return -errno;
787*8542734aSAndroid Build Coastguard Worker     }
788*8542734aSAndroid Build Coastguard Worker 
789*8542734aSAndroid Build Coastguard Worker     setForwardRules(false, intIface, extIface);
790*8542734aSAndroid Build Coastguard Worker     if (!isAnyForwardingPairEnabled()) setDefaults();
791*8542734aSAndroid Build Coastguard Worker     return 0;
792*8542734aSAndroid Build Coastguard Worker }
793*8542734aSAndroid Build Coastguard Worker 
addStats(TetherStatsList & statsList,const TetherStats & stats)794*8542734aSAndroid Build Coastguard Worker void TetherController::addStats(TetherStatsList& statsList, const TetherStats& stats) {
795*8542734aSAndroid Build Coastguard Worker     for (TetherStats& existing : statsList) {
796*8542734aSAndroid Build Coastguard Worker         if (existing.addStatsIfMatch(stats)) {
797*8542734aSAndroid Build Coastguard Worker             return;
798*8542734aSAndroid Build Coastguard Worker         }
799*8542734aSAndroid Build Coastguard Worker     }
800*8542734aSAndroid Build Coastguard Worker     // No match. Insert a new interface pair.
801*8542734aSAndroid Build Coastguard Worker     statsList.push_back(stats);
802*8542734aSAndroid Build Coastguard Worker }
803*8542734aSAndroid Build Coastguard Worker 
804*8542734aSAndroid Build Coastguard Worker /*
805*8542734aSAndroid Build Coastguard Worker  * Parse the ptks and bytes out of:
806*8542734aSAndroid Build Coastguard Worker  *   Chain tetherctrl_counters (4 references)
807*8542734aSAndroid Build Coastguard Worker  *       pkts      bytes target     prot opt in     out     source               destination
808*8542734aSAndroid Build Coastguard Worker  *         26     2373 RETURN     all  --  wlan0  rmnet0  0.0.0.0/0            0.0.0.0/0
809*8542734aSAndroid Build Coastguard Worker  *         27     2002 RETURN     all  --  rmnet0 wlan0   0.0.0.0/0            0.0.0.0/0
810*8542734aSAndroid Build Coastguard Worker  *       1040   107471 RETURN     all  --  bt-pan rmnet0  0.0.0.0/0            0.0.0.0/0
811*8542734aSAndroid Build Coastguard Worker  *       1450  1708806 RETURN     all  --  rmnet0 bt-pan  0.0.0.0/0            0.0.0.0/0
812*8542734aSAndroid Build Coastguard Worker  * or:
813*8542734aSAndroid Build Coastguard Worker  *   Chain tetherctrl_counters (0 references)
814*8542734aSAndroid Build Coastguard Worker  *       pkts      bytes target     prot opt in     out     source               destination
815*8542734aSAndroid Build Coastguard Worker  *          0        0 RETURN     all  --  wlan0  rmnet_data0  ::/0                 ::/0
816*8542734aSAndroid Build Coastguard Worker  *          0        0 RETURN     all  --  rmnet_data0 wlan0   ::/0                 ::/0
817*8542734aSAndroid Build Coastguard Worker  *
818*8542734aSAndroid Build Coastguard Worker  */
addForwardChainStats(TetherStatsList & statsList,const std::string & statsOutput,std::string & extraProcessingInfo)819*8542734aSAndroid Build Coastguard Worker int TetherController::addForwardChainStats(TetherStatsList& statsList,
820*8542734aSAndroid Build Coastguard Worker                                            const std::string& statsOutput,
821*8542734aSAndroid Build Coastguard Worker                                            std::string &extraProcessingInfo) {
822*8542734aSAndroid Build Coastguard Worker     enum IndexOfIptChain {
823*8542734aSAndroid Build Coastguard Worker         ORIG_LINE,
824*8542734aSAndroid Build Coastguard Worker         PACKET_COUNTS,
825*8542734aSAndroid Build Coastguard Worker         BYTE_COUNTS,
826*8542734aSAndroid Build Coastguard Worker         IFACE0_NAME,
827*8542734aSAndroid Build Coastguard Worker         IFACE1_NAME,
828*8542734aSAndroid Build Coastguard Worker         SOURCE,
829*8542734aSAndroid Build Coastguard Worker         DESTINATION
830*8542734aSAndroid Build Coastguard Worker     };
831*8542734aSAndroid Build Coastguard Worker     TetherStats stats;
832*8542734aSAndroid Build Coastguard Worker     const TetherStats empty;
833*8542734aSAndroid Build Coastguard Worker 
834*8542734aSAndroid Build Coastguard Worker     static const std::string NUM = "(\\d+)";
835*8542734aSAndroid Build Coastguard Worker     static const std::string IFACE = "([^\\s]+)";
836*8542734aSAndroid Build Coastguard Worker     static const std::string DST = "(0.0.0.0/0|::/0)";
837*8542734aSAndroid Build Coastguard Worker     static const std::string COUNTERS = "\\s*" + NUM + "\\s+" + NUM +
838*8542734aSAndroid Build Coastguard Worker                                         " RETURN     all  --  " + IFACE + "\\s+" + IFACE +
839*8542734aSAndroid Build Coastguard Worker                                         "\\s+" + DST + "\\s+" + DST;
840*8542734aSAndroid Build Coastguard Worker     static const std::regex IP_RE(COUNTERS);
841*8542734aSAndroid Build Coastguard Worker 
842*8542734aSAndroid Build Coastguard Worker     const std::vector<std::string> lines = base::Split(statsOutput, "\n");
843*8542734aSAndroid Build Coastguard Worker     int headerLine = 0;
844*8542734aSAndroid Build Coastguard Worker     for (const std::string& line : lines) {
845*8542734aSAndroid Build Coastguard Worker         // Skip headers.
846*8542734aSAndroid Build Coastguard Worker         if (headerLine < 2) {
847*8542734aSAndroid Build Coastguard Worker             if (line.empty()) {
848*8542734aSAndroid Build Coastguard Worker                 ALOGV("Empty header while parsing tethering stats");
849*8542734aSAndroid Build Coastguard Worker                 return -EREMOTEIO;
850*8542734aSAndroid Build Coastguard Worker             }
851*8542734aSAndroid Build Coastguard Worker             headerLine++;
852*8542734aSAndroid Build Coastguard Worker             continue;
853*8542734aSAndroid Build Coastguard Worker         }
854*8542734aSAndroid Build Coastguard Worker 
855*8542734aSAndroid Build Coastguard Worker         if (line.empty()) continue;
856*8542734aSAndroid Build Coastguard Worker 
857*8542734aSAndroid Build Coastguard Worker         extraProcessingInfo = line;
858*8542734aSAndroid Build Coastguard Worker         std::smatch matches;
859*8542734aSAndroid Build Coastguard Worker         if (!std::regex_search(line, matches, IP_RE)) return -EREMOTEIO;
860*8542734aSAndroid Build Coastguard Worker         //		 26 	2373 RETURN     all  --  wlan0	rmnet0	0.0.0.0/0			 0.0.0.0/0
861*8542734aSAndroid Build Coastguard Worker         //		 26 	2373 RETURN     all  --  wlan0	rmnet0	::/0				 ::/0
862*8542734aSAndroid Build Coastguard Worker         // TODO: Replace strtoXX() calls with ParseUint() /ParseInt()
863*8542734aSAndroid Build Coastguard Worker         int64_t packets = strtoul(matches[PACKET_COUNTS].str().c_str(), nullptr, 10);
864*8542734aSAndroid Build Coastguard Worker         int64_t bytes = strtoul(matches[BYTE_COUNTS].str().c_str(), nullptr, 10);
865*8542734aSAndroid Build Coastguard Worker         std::string iface0 = matches[IFACE0_NAME].str();
866*8542734aSAndroid Build Coastguard Worker         std::string iface1 = matches[IFACE1_NAME].str();
867*8542734aSAndroid Build Coastguard Worker         std::string rest = matches[SOURCE].str();
868*8542734aSAndroid Build Coastguard Worker 
869*8542734aSAndroid Build Coastguard Worker         ALOGV("parse iface0=<%s> iface1=<%s> pkts=%" PRId64 " bytes=%" PRId64
870*8542734aSAndroid Build Coastguard Worker               " rest=<%s> orig line=<%s>",
871*8542734aSAndroid Build Coastguard Worker               iface0.c_str(), iface1.c_str(), packets, bytes, rest.c_str(), line.c_str());
872*8542734aSAndroid Build Coastguard Worker         /*
873*8542734aSAndroid Build Coastguard Worker          * The following assumes that the 1st rule has in:extIface out:intIface,
874*8542734aSAndroid Build Coastguard Worker          * which is what TetherController sets up.
875*8542734aSAndroid Build Coastguard Worker          * The 1st matches rx, and sets up the pair for the tx side.
876*8542734aSAndroid Build Coastguard Worker          */
877*8542734aSAndroid Build Coastguard Worker         if (stats.intIface.empty()) {
878*8542734aSAndroid Build Coastguard Worker             ALOGV("0Filter RX iface_in=%s iface_out=%s rx_bytes=%" PRId64 " rx_packets=%" PRId64
879*8542734aSAndroid Build Coastguard Worker                   " ", iface0.c_str(), iface1.c_str(), bytes, packets);
880*8542734aSAndroid Build Coastguard Worker             stats.intIface = iface0;
881*8542734aSAndroid Build Coastguard Worker             stats.extIface = iface1;
882*8542734aSAndroid Build Coastguard Worker             stats.txPackets = packets;
883*8542734aSAndroid Build Coastguard Worker             stats.txBytes = bytes;
884*8542734aSAndroid Build Coastguard Worker         } else if (stats.intIface == iface1 && stats.extIface == iface0) {
885*8542734aSAndroid Build Coastguard Worker             ALOGV("0Filter TX iface_in=%s iface_out=%s rx_bytes=%" PRId64 " rx_packets=%" PRId64
886*8542734aSAndroid Build Coastguard Worker                   " ", iface0.c_str(), iface1.c_str(), bytes, packets);
887*8542734aSAndroid Build Coastguard Worker             stats.rxPackets = packets;
888*8542734aSAndroid Build Coastguard Worker             stats.rxBytes = bytes;
889*8542734aSAndroid Build Coastguard Worker         }
890*8542734aSAndroid Build Coastguard Worker         if (stats.rxBytes != -1 && stats.txBytes != -1) {
891*8542734aSAndroid Build Coastguard Worker             ALOGV("rx_bytes=%" PRId64" tx_bytes=%" PRId64, stats.rxBytes, stats.txBytes);
892*8542734aSAndroid Build Coastguard Worker             addStats(statsList, stats);
893*8542734aSAndroid Build Coastguard Worker             stats = empty;
894*8542734aSAndroid Build Coastguard Worker         }
895*8542734aSAndroid Build Coastguard Worker     }
896*8542734aSAndroid Build Coastguard Worker 
897*8542734aSAndroid Build Coastguard Worker     /* It is always an error to find only one side of the stats. */
898*8542734aSAndroid Build Coastguard Worker     if (((stats.rxBytes == -1) != (stats.txBytes == -1))) {
899*8542734aSAndroid Build Coastguard Worker         return -EREMOTEIO;
900*8542734aSAndroid Build Coastguard Worker     }
901*8542734aSAndroid Build Coastguard Worker     return 0;
902*8542734aSAndroid Build Coastguard Worker }
903*8542734aSAndroid Build Coastguard Worker 
getTetherStats()904*8542734aSAndroid Build Coastguard Worker StatusOr<TetherController::TetherStatsList> TetherController::getTetherStats() {
905*8542734aSAndroid Build Coastguard Worker     TetherStatsList statsList;
906*8542734aSAndroid Build Coastguard Worker     std::string parsedIptablesOutput;
907*8542734aSAndroid Build Coastguard Worker 
908*8542734aSAndroid Build Coastguard Worker     for (const IptablesTarget target : {V4, V6}) {
909*8542734aSAndroid Build Coastguard Worker         std::string statsString;
910*8542734aSAndroid Build Coastguard Worker         if (int ret = iptablesRestoreFunction(target, GET_TETHER_STATS_COMMAND, &statsString)) {
911*8542734aSAndroid Build Coastguard Worker             return statusFromErrno(-ret, StringPrintf("failed to fetch tether stats (%d): %d",
912*8542734aSAndroid Build Coastguard Worker                                                       target, ret));
913*8542734aSAndroid Build Coastguard Worker         }
914*8542734aSAndroid Build Coastguard Worker 
915*8542734aSAndroid Build Coastguard Worker         if (int ret = addForwardChainStats(statsList, statsString, parsedIptablesOutput)) {
916*8542734aSAndroid Build Coastguard Worker             return statusFromErrno(-ret, StringPrintf("failed to parse %s tether stats:\n%s",
917*8542734aSAndroid Build Coastguard Worker                                                       target == V4 ? "IPv4": "IPv6",
918*8542734aSAndroid Build Coastguard Worker                                                       parsedIptablesOutput.c_str()));
919*8542734aSAndroid Build Coastguard Worker         }
920*8542734aSAndroid Build Coastguard Worker     }
921*8542734aSAndroid Build Coastguard Worker 
922*8542734aSAndroid Build Coastguard Worker     return statsList;
923*8542734aSAndroid Build Coastguard Worker }
924*8542734aSAndroid Build Coastguard Worker 
dumpIfaces(DumpWriter & dw)925*8542734aSAndroid Build Coastguard Worker void TetherController::dumpIfaces(DumpWriter& dw) {
926*8542734aSAndroid Build Coastguard Worker     dw.println("Interface pairs:");
927*8542734aSAndroid Build Coastguard Worker 
928*8542734aSAndroid Build Coastguard Worker     ScopedIndent ifaceIndent(dw);
929*8542734aSAndroid Build Coastguard Worker     for (const auto& it : mFwdIfaces) {
930*8542734aSAndroid Build Coastguard Worker         dw.println("%s -> %s %s", it.first.c_str(), it.second.iface.c_str(),
931*8542734aSAndroid Build Coastguard Worker                    (it.second.active ? "ACTIVE" : "DISABLED"));
932*8542734aSAndroid Build Coastguard Worker     }
933*8542734aSAndroid Build Coastguard Worker }
934*8542734aSAndroid Build Coastguard Worker 
dump(DumpWriter & dw)935*8542734aSAndroid Build Coastguard Worker void TetherController::dump(DumpWriter& dw) {
936*8542734aSAndroid Build Coastguard Worker     std::lock_guard guard(lock);
937*8542734aSAndroid Build Coastguard Worker 
938*8542734aSAndroid Build Coastguard Worker     ScopedIndent tetherControllerIndent(dw);
939*8542734aSAndroid Build Coastguard Worker     dw.println("TetherController");
940*8542734aSAndroid Build Coastguard Worker     dw.incIndent();
941*8542734aSAndroid Build Coastguard Worker 
942*8542734aSAndroid Build Coastguard Worker     dw.println("Forwarding requests: " + Join(mForwardingRequests, ' '));
943*8542734aSAndroid Build Coastguard Worker     if (mDnsNetId != 0) {
944*8542734aSAndroid Build Coastguard Worker         dw.println(StringPrintf("DNS: netId %d servers [%s]", mDnsNetId,
945*8542734aSAndroid Build Coastguard Worker                                 Join(mDnsForwarders, ", ").c_str()));
946*8542734aSAndroid Build Coastguard Worker     }
947*8542734aSAndroid Build Coastguard Worker     if (mDaemonPid != 0) {
948*8542734aSAndroid Build Coastguard Worker         dw.println("dnsmasq PID: %d", mDaemonPid);
949*8542734aSAndroid Build Coastguard Worker     }
950*8542734aSAndroid Build Coastguard Worker 
951*8542734aSAndroid Build Coastguard Worker     dumpIfaces(dw);
952*8542734aSAndroid Build Coastguard Worker }
953*8542734aSAndroid Build Coastguard Worker 
954*8542734aSAndroid Build Coastguard Worker }  // namespace net
955*8542734aSAndroid Build Coastguard Worker }  // namespace android
956