1 /*
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 
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <inttypes.h>
20 #include <netdb.h>
21 #include <spawn.h>
22 #include <string.h>
23 
24 #include <sys/socket.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <sys/wait.h>
28 
29 #include <netinet/in.h>
30 #include <arpa/inet.h>
31 
32 #include <array>
33 #include <cstdlib>
34 #include <regex>
35 #include <string>
36 #include <vector>
37 
38 #define LOG_TAG "TetherController"
39 #include <android-base/scopeguard.h>
40 #include <android-base/stringprintf.h>
41 #include <android-base/strings.h>
42 #include <android-base/unique_fd.h>
43 #include <cutils/properties.h>
44 #include <log/log.h>
45 #include <net/if.h>
46 #include <netdutils/DumpWriter.h>
47 #include <netdutils/StatusOr.h>
48 
49 #include "Controllers.h"
50 #include "Fwmark.h"
51 #include "InterfaceController.h"
52 #include "NetdConstants.h"
53 #include "NetworkController.h"
54 #include "OffloadUtils.h"
55 #include "Permission.h"
56 #include "TetherController.h"
57 
58 #include "android/net/TetherOffloadRuleParcel.h"
59 
60 namespace android {
61 namespace net {
62 
63 using android::base::Error;
64 using android::base::Join;
65 using android::base::Pipe;
66 using android::base::Result;
67 using android::base::StringAppendF;
68 using android::base::StringPrintf;
69 using android::base::unique_fd;
70 using android::net::TetherOffloadRuleParcel;
71 using android::netdutils::DumpWriter;
72 using android::netdutils::ScopedIndent;
73 using android::netdutils::statusFromErrno;
74 using android::netdutils::StatusOr;
75 
76 namespace {
77 
78 const char BP_TOOLS_MODE[] = "bp-tools";
79 const char IPV4_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv4/ip_forward";
80 const char IPV6_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv6/conf/all/forwarding";
81 const char SEPARATOR[] = "|";
82 constexpr const char kTcpBeLiberal[] = "/proc/sys/net/netfilter/nf_conntrack_tcp_be_liberal";
83 
84 // Chosen to match AID_DNS_TETHER, as made "friendly" by fs_config_generator.py.
85 constexpr const char kDnsmasqUsername[] = "dns_tether";
86 
87 // A value used by interface quota indicates there is no limit.
88 // Sync from frameworks/base/core/java/android/net/netstats/provider/NetworkStatsProvider.java
89 constexpr int64_t QUOTA_UNLIMITED = -1;
90 
writeToFile(const char * filename,const char * value)91 bool writeToFile(const char* filename, const char* value) {
92     int fd = open(filename, O_WRONLY | O_CLOEXEC);
93     if (fd < 0) {
94         ALOGE("Failed to open %s: %s", filename, strerror(errno));
95         return false;
96     }
97 
98     const ssize_t len = strlen(value);
99     if (write(fd, value, len) != len) {
100         ALOGE("Failed to write %s to %s: %s", value, filename, strerror(errno));
101         close(fd);
102         return false;
103     }
104     close(fd);
105     return true;
106 }
107 
108 // TODO: Consider altering TCP and UDP timeouts as well.
configureForTethering(bool enabled)109 void configureForTethering(bool enabled) {
110     writeToFile(kTcpBeLiberal, enabled ? "1" : "0");
111 }
112 
configureForIPv6Router(const char * interface)113 bool configureForIPv6Router(const char *interface) {
114     return (InterfaceController::setEnableIPv6(interface, 0) == 0)
115             && (InterfaceController::setAcceptIPv6Ra(interface, 0) == 0)
116             && (InterfaceController::setAcceptIPv6Dad(interface, 0) == 0)
117             && (InterfaceController::setIPv6DadTransmits(interface, "0") == 0)
118             && (InterfaceController::setEnableIPv6(interface, 1) == 0);
119 }
120 
configureForIPv6Client(const char * interface)121 void configureForIPv6Client(const char *interface) {
122     InterfaceController::setAcceptIPv6Ra(interface, 1);
123     InterfaceController::setAcceptIPv6Dad(interface, 1);
124     InterfaceController::setIPv6DadTransmits(interface, "1");
125     InterfaceController::setEnableIPv6(interface, 0);
126 }
127 
inBpToolsMode()128 bool inBpToolsMode() {
129     // In BP tools mode, do not disable IP forwarding
130     char bootmode[PROPERTY_VALUE_MAX] = {0};
131     property_get("ro.bootmode", bootmode, "unknown");
132     return !strcmp(BP_TOOLS_MODE, bootmode);
133 }
134 
135 }  // namespace
136 
137 auto TetherController::iptablesRestoreFunction = execIptablesRestoreWithOutput;
138 
139 const std::string GET_TETHER_STATS_COMMAND = StringPrintf(
140     "*filter\n"
141     "-nvx -L %s\n"
142     "COMMIT\n", android::net::TetherController::LOCAL_TETHER_COUNTERS_CHAIN);
143 
sendCmd(int daemonFd,const std::string & cmd)144 int TetherController::DnsmasqState::sendCmd(int daemonFd, const std::string& cmd) {
145     if (cmd.empty()) return 0;
146 
147     gLog.log("Sending update msg to dnsmasq [%s]", cmd.c_str());
148     // Send the trailing \0 as well.
149     if (write(daemonFd, cmd.c_str(), cmd.size() + 1) < 0) {
150         gLog.error("Failed to send update command to dnsmasq (%s)", strerror(errno));
151         errno = EREMOTEIO;
152         return -1;
153     }
154     return 0;
155 }
156 
clear()157 void TetherController::DnsmasqState::clear() {
158     update_ifaces_cmd.clear();
159     update_dns_cmd.clear();
160 }
161 
sendAllState(int daemonFd) const162 int TetherController::DnsmasqState::sendAllState(int daemonFd) const {
163     return sendCmd(daemonFd, update_ifaces_cmd) | sendCmd(daemonFd, update_dns_cmd);
164 }
165 
TetherController()166 TetherController::TetherController() {
167     if (inBpToolsMode()) {
168         enableForwarding(BP_TOOLS_MODE);
169     } else {
170         setIpFwdEnabled();
171     }
172     maybeInitMaps();
173 }
174 
setIpFwdEnabled()175 bool TetherController::setIpFwdEnabled() {
176     bool success = true;
177     bool disable = mForwardingRequests.empty();
178     const char* value = disable ? "0" : "1";
179     ALOGD("Setting IP forward enable = %s", value);
180     success &= writeToFile(IPV4_FORWARDING_PROC_FILE, value);
181     success &= writeToFile(IPV6_FORWARDING_PROC_FILE, value);
182     if (disable) {
183         // Turning off the forwarding sysconf in the kernel has the side effect
184         // of turning on ICMP redirect, which is a security hazard.
185         // Turn ICMP redirect back off immediately.
186         int rv = InterfaceController::disableIcmpRedirects();
187         success &= (rv == 0);
188     }
189     return success;
190 }
191 
enableForwarding(const char * requester)192 bool TetherController::enableForwarding(const char* requester) {
193     // Don't return an error if this requester already requested forwarding. Only return errors for
194     // things that the caller caller needs to care about, such as "couldn't write to the file to
195     // enable forwarding".
196     mForwardingRequests.insert(requester);
197     return setIpFwdEnabled();
198 }
199 
disableForwarding(const char * requester)200 bool TetherController::disableForwarding(const char* requester) {
201     mForwardingRequests.erase(requester);
202     return setIpFwdEnabled();
203 }
204 
maybeInitMaps()205 void TetherController::maybeInitMaps() {
206     if (!bpf::isBpfSupported()) return;
207 
208     // Open BPF maps, ignoring errors because the device might not support BPF offload.
209     int fd = getTetherIngressMapFd();
210     if (fd >= 0) {
211         mBpfIngressMap.reset(fd);
212         mBpfIngressMap.clear();
213     }
214     fd = getTetherStatsMapFd();
215     if (fd >= 0) {
216         mBpfStatsMap.reset(fd);
217         mBpfStatsMap.clear();
218     }
219     fd = getTetherLimitMapFd();
220     if (fd >= 0) {
221         mBpfLimitMap.reset(fd);
222         mBpfLimitMap.clear();
223     }
224 }
225 
getIpfwdRequesterList() const226 const std::set<std::string>& TetherController::getIpfwdRequesterList() const {
227     return mForwardingRequests;
228 }
229 
startTethering(bool usingLegacyDnsProxy,int num_addrs,char ** dhcp_ranges)230 int TetherController::startTethering(bool usingLegacyDnsProxy, int num_addrs, char** dhcp_ranges) {
231     if (!usingLegacyDnsProxy && num_addrs == 0) {
232         // Both DHCP and DnsProxy are disabled, we don't need to start dnsmasq
233         configureForTethering(true);
234         mIsTetheringStarted = true;
235         return 0;
236     }
237 
238     if (mIsTetheringStarted) {
239         ALOGE("Tethering already started");
240         errno = EBUSY;
241         return -errno;
242     }
243 
244     ALOGD("Starting tethering services");
245 
246     unique_fd pipeRead, pipeWrite;
247     if (!Pipe(&pipeRead, &pipeWrite, O_CLOEXEC)) {
248         int res = errno;
249         ALOGE("pipe2() failed (%s)", strerror(errno));
250         return -res;
251     }
252 
253     // Set parameters
254     Fwmark fwmark;
255     fwmark.netId = NetworkController::LOCAL_NET_ID;
256     fwmark.explicitlySelected = true;
257     fwmark.protectedFromVpn = true;
258     fwmark.permission = PERMISSION_SYSTEM;
259     char markStr[UINT32_HEX_STRLEN];
260     snprintf(markStr, sizeof(markStr), "0x%x", fwmark.intValue);
261 
262     std::vector<const std::string> argVector = {
263             "/system/bin/dnsmasq",
264             "--keep-in-foreground",
265             "--no-resolv",
266             "--no-poll",
267             "--dhcp-authoritative",
268             // TODO: pipe through metered status from ConnService
269             "--dhcp-option-force=43,ANDROID_METERED",
270             "--pid-file",
271             "--listen-mark",
272             markStr,
273             "--user",
274             kDnsmasqUsername,
275     };
276 
277     if (!usingLegacyDnsProxy) {
278         argVector.push_back("--port=0");
279     }
280 
281     // DHCP server will be disabled if num_addrs == 0 and no --dhcp-range is passed.
282     for (int addrIndex = 0; addrIndex < num_addrs; addrIndex += 2) {
283         argVector.push_back(StringPrintf("--dhcp-range=%s,%s,1h", dhcp_ranges[addrIndex],
284                                          dhcp_ranges[addrIndex + 1]));
285     }
286 
287     std::vector<char*> args(argVector.size() + 1);
288     for (unsigned i = 0; i < argVector.size(); i++) {
289         args[i] = (char*)argVector[i].c_str();
290     }
291 
292     /*
293      * TODO: Create a monitoring thread to handle and restart
294      * the daemon if it exits prematurely
295      */
296 
297     // Note that don't modify any memory between vfork and execv.
298     // Changing state of file descriptors would be fine. See posix_spawn_file_actions_add*
299     // dup2 creates fd without CLOEXEC, dnsmasq will receive commands through the
300     // duplicated fd.
301     posix_spawn_file_actions_t fa;
302     int res = posix_spawn_file_actions_init(&fa);
303     if (res) {
304         ALOGE("posix_spawn_file_actions_init failed (%s)", strerror(res));
305         return -res;
306     }
307     const android::base::ScopeGuard faGuard = [&] { posix_spawn_file_actions_destroy(&fa); };
308     res = posix_spawn_file_actions_adddup2(&fa, pipeRead.get(), STDIN_FILENO);
309     if (res) {
310         ALOGE("posix_spawn_file_actions_adddup2 failed (%s)", strerror(res));
311         return -res;
312     }
313 
314     posix_spawnattr_t attr;
315     res = posix_spawnattr_init(&attr);
316     if (res) {
317         ALOGE("posix_spawnattr_init failed (%s)", strerror(res));
318         return -res;
319     }
320     const android::base::ScopeGuard attrGuard = [&] { posix_spawnattr_destroy(&attr); };
321     res = posix_spawnattr_setflags(&attr, POSIX_SPAWN_USEVFORK);
322     if (res) {
323         ALOGE("posix_spawnattr_setflags failed (%s)", strerror(res));
324         return -res;
325     }
326 
327     pid_t pid;
328     res = posix_spawn(&pid, args[0], &fa, &attr, &args[0], nullptr);
329     if (res) {
330         ALOGE("posix_spawn failed (%s)", strerror(res));
331         return -res;
332     }
333     mDaemonPid = pid;
334     mDaemonFd = pipeWrite.release();
335     configureForTethering(true);
336     mIsTetheringStarted = true;
337     applyDnsInterfaces();
338     ALOGD("Tethering services running");
339 
340     return 0;
341 }
342 
toCstrVec(const std::vector<std::string> & addrs)343 std::vector<char*> TetherController::toCstrVec(const std::vector<std::string>& addrs) {
344     std::vector<char*> addrsCstrVec{};
345     addrsCstrVec.reserve(addrs.size());
346     for (const auto& addr : addrs) {
347         addrsCstrVec.push_back(const_cast<char*>(addr.data()));
348     }
349     return addrsCstrVec;
350 }
351 
startTethering(bool usingLegacyDnsProxy,const std::vector<std::string> & dhcpRanges)352 int TetherController::startTethering(bool usingLegacyDnsProxy,
353                                      const std::vector<std::string>& dhcpRanges) {
354     struct in_addr v4_addr;
355     for (const auto& dhcpRange : dhcpRanges) {
356         if (!inet_aton(dhcpRange.c_str(), &v4_addr)) {
357             return -EINVAL;
358         }
359     }
360     auto dhcp_ranges = toCstrVec(dhcpRanges);
361     return startTethering(usingLegacyDnsProxy, dhcp_ranges.size(), dhcp_ranges.data());
362 }
363 
stopTethering()364 int TetherController::stopTethering() {
365     configureForTethering(false);
366 
367     if (!mIsTetheringStarted) {
368         ALOGE("Tethering already stopped");
369         return 0;
370     }
371 
372     mIsTetheringStarted = false;
373     // dnsmasq is not started
374     if (mDaemonPid == 0) {
375         return 0;
376     }
377 
378     ALOGD("Stopping tethering services");
379 
380     kill(mDaemonPid, SIGTERM);
381     waitpid(mDaemonPid, nullptr, 0);
382     mDaemonPid = 0;
383     close(mDaemonFd);
384     mDaemonFd = -1;
385     mDnsmasqState.clear();
386     ALOGD("Tethering services stopped");
387     return 0;
388 }
389 
isTetheringStarted()390 bool TetherController::isTetheringStarted() {
391     return mIsTetheringStarted;
392 }
393 
394 // dnsmasq can't parse commands larger than this due to the fixed-size buffer
395 // in check_android_listeners(). The receiving buffer is 1024 bytes long, but
396 // dnsmasq reads up to 1023 bytes.
397 const size_t MAX_CMD_SIZE = 1023;
398 
399 // TODO: Remove overload function and update this after NDC migration.
setDnsForwarders(unsigned netId,char ** servers,int numServers)400 int TetherController::setDnsForwarders(unsigned netId, char **servers, int numServers) {
401     Fwmark fwmark;
402     fwmark.netId = netId;
403     fwmark.explicitlySelected = true;
404     fwmark.protectedFromVpn = true;
405     fwmark.permission = PERMISSION_SYSTEM;
406 
407     std::string daemonCmd = StringPrintf("update_dns%s0x%x", SEPARATOR, fwmark.intValue);
408 
409     mDnsForwarders.clear();
410     for (int i = 0; i < numServers; i++) {
411         ALOGD("setDnsForwarders(0x%x %d = '%s')", fwmark.intValue, i, servers[i]);
412 
413         addrinfo *res, hints = { .ai_flags = AI_NUMERICHOST };
414         int ret = getaddrinfo(servers[i], nullptr, &hints, &res);
415         freeaddrinfo(res);
416         if (ret) {
417             ALOGE("Failed to parse DNS server '%s'", servers[i]);
418             mDnsForwarders.clear();
419             errno = EINVAL;
420             return -errno;
421         }
422 
423         if (daemonCmd.size() + 1 + strlen(servers[i]) >= MAX_CMD_SIZE) {
424             ALOGE("Too many DNS servers listed");
425             break;
426         }
427 
428         daemonCmd += SEPARATOR;
429         daemonCmd += servers[i];
430         mDnsForwarders.push_back(servers[i]);
431     }
432 
433     mDnsNetId = netId;
434     mDnsmasqState.update_dns_cmd = std::move(daemonCmd);
435     if (mDaemonFd != -1) {
436         if (mDnsmasqState.sendAllState(mDaemonFd) != 0) {
437             mDnsForwarders.clear();
438             errno = EREMOTEIO;
439             return -errno;
440         }
441     }
442     return 0;
443 }
444 
setDnsForwarders(unsigned netId,const std::vector<std::string> & servers)445 int TetherController::setDnsForwarders(unsigned netId, const std::vector<std::string>& servers) {
446     auto dnsServers = toCstrVec(servers);
447     return setDnsForwarders(netId, dnsServers.data(), dnsServers.size());
448 }
449 
getDnsNetId()450 unsigned TetherController::getDnsNetId() {
451     return mDnsNetId;
452 }
453 
getDnsForwarders() const454 const std::list<std::string> &TetherController::getDnsForwarders() const {
455     return mDnsForwarders;
456 }
457 
applyDnsInterfaces()458 bool TetherController::applyDnsInterfaces() {
459     std::string daemonCmd = "update_ifaces";
460     bool haveInterfaces = false;
461 
462     for (const auto& ifname : mInterfaces) {
463         if (daemonCmd.size() + 1 + ifname.size() >= MAX_CMD_SIZE) {
464             ALOGE("Too many DNS servers listed");
465             break;
466         }
467 
468         daemonCmd += SEPARATOR;
469         daemonCmd += ifname;
470         haveInterfaces = true;
471     }
472 
473     if (!haveInterfaces) {
474         mDnsmasqState.update_ifaces_cmd.clear();
475     } else {
476         mDnsmasqState.update_ifaces_cmd = std::move(daemonCmd);
477         if (mDaemonFd != -1) return (mDnsmasqState.sendAllState(mDaemonFd) == 0);
478     }
479     return true;
480 }
481 
tetherInterface(const char * interface)482 int TetherController::tetherInterface(const char *interface) {
483     ALOGD("tetherInterface(%s)", interface);
484     if (!isIfaceName(interface)) {
485         errno = ENOENT;
486         return -errno;
487     }
488 
489     if (!configureForIPv6Router(interface)) {
490         configureForIPv6Client(interface);
491         return -EREMOTEIO;
492     }
493     mInterfaces.push_back(interface);
494 
495     if (!applyDnsInterfaces()) {
496         mInterfaces.pop_back();
497         configureForIPv6Client(interface);
498         return -EREMOTEIO;
499     } else {
500         return 0;
501     }
502 }
503 
untetherInterface(const char * interface)504 int TetherController::untetherInterface(const char *interface) {
505     ALOGD("untetherInterface(%s)", interface);
506 
507     for (auto it = mInterfaces.cbegin(); it != mInterfaces.cend(); ++it) {
508         if (!strcmp(interface, it->c_str())) {
509             mInterfaces.erase(it);
510 
511             configureForIPv6Client(interface);
512             return applyDnsInterfaces() ? 0 : -EREMOTEIO;
513         }
514     }
515     errno = ENOENT;
516     return -errno;
517 }
518 
getTetheredInterfaceList() const519 const std::list<std::string> &TetherController::getTetheredInterfaceList() const {
520     return mInterfaces;
521 }
522 
setupIptablesHooks()523 int TetherController::setupIptablesHooks() {
524     int res;
525     res = setDefaults();
526     if (res < 0) {
527         return res;
528     }
529 
530     // Used to limit downstream mss to the upstream pmtu so we don't end up fragmenting every large
531     // packet tethered devices send. This is IPv4-only, because in IPv6 we send the MTU in the RA.
532     // This is no longer optional and tethering will fail to start if it fails.
533     std::string mssRewriteCommand = StringPrintf(
534         "*mangle\n"
535         "-A %s -p tcp --tcp-flags SYN SYN -j TCPMSS --clamp-mss-to-pmtu\n"
536         "COMMIT\n", LOCAL_MANGLE_FORWARD);
537 
538     // This is for tethering counters. This chain is reached via --goto, and then RETURNS.
539     std::string defaultCommands = StringPrintf(
540         "*filter\n"
541         ":%s -\n"
542         "COMMIT\n", LOCAL_TETHER_COUNTERS_CHAIN);
543 
544     res = iptablesRestoreFunction(V4, mssRewriteCommand, nullptr);
545     if (res < 0) {
546         return res;
547     }
548 
549     res = iptablesRestoreFunction(V4V6, defaultCommands, nullptr);
550     if (res < 0) {
551         return res;
552     }
553 
554     mFwdIfaces.clear();
555 
556     return 0;
557 }
558 
setDefaults()559 int TetherController::setDefaults() {
560     std::string v4Cmd = StringPrintf(
561         "*filter\n"
562         ":%s -\n"
563         "-A %s -j DROP\n"
564         "COMMIT\n"
565         "*nat\n"
566         ":%s -\n"
567         "COMMIT\n", LOCAL_FORWARD, LOCAL_FORWARD, LOCAL_NAT_POSTROUTING);
568 
569     std::string v6Cmd = StringPrintf(
570             "*filter\n"
571             ":%s -\n"
572             "COMMIT\n"
573             "*raw\n"
574             ":%s -\n"
575             "COMMIT\n",
576             LOCAL_FORWARD, LOCAL_RAW_PREROUTING);
577 
578     int res = iptablesRestoreFunction(V4, v4Cmd, nullptr);
579     if (res < 0) {
580         return res;
581     }
582 
583     res = iptablesRestoreFunction(V6, v6Cmd, nullptr);
584     if (res < 0) {
585         return res;
586     }
587 
588     return 0;
589 }
590 
enableNat(const char * intIface,const char * extIface)591 int TetherController::enableNat(const char* intIface, const char* extIface) {
592     ALOGV("enableNat(intIface=<%s>, extIface=<%s>)",intIface, extIface);
593 
594     if (!isIfaceName(intIface) || !isIfaceName(extIface)) {
595         return -ENODEV;
596     }
597 
598     /* Bug: b/9565268. "enableNat wlan0 wlan0". For now we fail until java-land is fixed */
599     if (!strcmp(intIface, extIface)) {
600         ALOGE("Duplicate interface specified: %s %s", intIface, extIface);
601         return -EINVAL;
602     }
603 
604     if (isForwardingPairEnabled(intIface, extIface)) {
605         return 0;
606     }
607 
608     // add this if we are the first enabled nat for this upstream
609     bool firstDownstreamForThisUpstream = !isAnyForwardingEnabledOnUpstream(extIface);
610     if (firstDownstreamForThisUpstream) {
611         std::vector<std::string> v4Cmds = {
612             "*nat",
613             StringPrintf("-A %s -o %s -j MASQUERADE", LOCAL_NAT_POSTROUTING, extIface),
614             "COMMIT\n"
615         };
616 
617         if (iptablesRestoreFunction(V4, Join(v4Cmds, '\n'), nullptr) || setupIPv6CountersChain() ||
618             setTetherGlobalAlertRule()) {
619             ALOGE("Error setting postroute rule: iface=%s", extIface);
620             if (!isAnyForwardingPairEnabled()) {
621                 // unwind what's been done, but don't care about success - what more could we do?
622                 setDefaults();
623             }
624             return -EREMOTEIO;
625         }
626     }
627 
628     if (setForwardRules(true, intIface, extIface) != 0) {
629         ALOGE("Error setting forward rules");
630         if (!isAnyForwardingPairEnabled()) {
631             setDefaults();
632         }
633         return -ENODEV;
634     }
635 
636     if (firstDownstreamForThisUpstream) maybeStartBpf(extIface);
637     return 0;
638 }
639 
setTetherGlobalAlertRule()640 int TetherController::setTetherGlobalAlertRule() {
641     // Only add this if we are the first enabled nat
642     if (isAnyForwardingPairEnabled()) {
643         return 0;
644     }
645     const std::string cmds =
646             "*filter\n" +
647             StringPrintf("-I %s -j %s\n", LOCAL_FORWARD, BandwidthController::LOCAL_GLOBAL_ALERT) +
648             "COMMIT\n";
649 
650     return iptablesRestoreFunction(V4V6, cmds, nullptr);
651 }
652 
setupIPv6CountersChain()653 int TetherController::setupIPv6CountersChain() {
654     // Only add this if we are the first enabled nat
655     if (isAnyForwardingPairEnabled()) {
656         return 0;
657     }
658 
659     /*
660      * IPv6 tethering doesn't need the state-based conntrack rules, so
661      * it unconditionally jumps to the tether counters chain all the time.
662      */
663     const std::string v6Cmds =
664             "*filter\n" +
665             StringPrintf("-A %s -g %s\n", LOCAL_FORWARD, LOCAL_TETHER_COUNTERS_CHAIN) + "COMMIT\n";
666 
667     return iptablesRestoreFunction(V6, v6Cmds, nullptr);
668 }
669 
670 // Gets a pointer to the ForwardingDownstream for an interface pair in the map, or nullptr
findForwardingDownstream(const std::string & intIface,const std::string & extIface)671 TetherController::ForwardingDownstream* TetherController::findForwardingDownstream(
672         const std::string& intIface, const std::string& extIface) {
673     auto extIfaceMatches = mFwdIfaces.equal_range(extIface);
674     for (auto it = extIfaceMatches.first; it != extIfaceMatches.second; ++it) {
675         if (it->second.iface == intIface) {
676             return &(it->second);
677         }
678     }
679     return nullptr;
680 }
681 
addForwardingPair(const std::string & intIface,const std::string & extIface)682 void TetherController::addForwardingPair(const std::string& intIface, const std::string& extIface) {
683     ForwardingDownstream* existingEntry = findForwardingDownstream(intIface, extIface);
684     if (existingEntry != nullptr) {
685         existingEntry->active = true;
686         return;
687     }
688 
689     mFwdIfaces.insert(std::pair<std::string, ForwardingDownstream>(extIface, {
690         .iface = intIface,
691         .active = true
692     }));
693 }
694 
markForwardingPairDisabled(const std::string & intIface,const std::string & extIface)695 void TetherController::markForwardingPairDisabled(
696         const std::string& intIface, const std::string& extIface) {
697     ForwardingDownstream* existingEntry = findForwardingDownstream(intIface, extIface);
698     if (existingEntry == nullptr) {
699         return;
700     }
701 
702     existingEntry->active = false;
703 }
704 
isForwardingPairEnabled(const std::string & intIface,const std::string & extIface)705 bool TetherController::isForwardingPairEnabled(
706         const std::string& intIface, const std::string& extIface) {
707     ForwardingDownstream* existingEntry = findForwardingDownstream(intIface, extIface);
708     return existingEntry != nullptr && existingEntry->active;
709 }
710 
isAnyForwardingEnabledOnUpstream(const std::string & extIface)711 bool TetherController::isAnyForwardingEnabledOnUpstream(const std::string& extIface) {
712     auto extIfaceMatches = mFwdIfaces.equal_range(extIface);
713     for (auto it = extIfaceMatches.first; it != extIfaceMatches.second; ++it) {
714         if (it->second.active) {
715             return true;
716         }
717     }
718     return false;
719 }
720 
isAnyForwardingPairEnabled()721 bool TetherController::isAnyForwardingPairEnabled() {
722     for (auto& it : mFwdIfaces) {
723         if (it.second.active) {
724             return true;
725         }
726     }
727     return false;
728 }
729 
tetherCountingRuleExists(const std::string & iface1,const std::string & iface2)730 bool TetherController::tetherCountingRuleExists(
731         const std::string& iface1, const std::string& iface2) {
732     // A counting rule exists if NAT was ever enabled for this interface pair, so if the pair
733     // is in the map regardless of its active status. Rules are added both ways so we check with
734     // the 2 combinations.
735     return findForwardingDownstream(iface1, iface2) != nullptr
736         || findForwardingDownstream(iface2, iface1) != nullptr;
737 }
738 
739 /* static */
makeTetherCountingRule(const char * if1,const char * if2)740 std::string TetherController::makeTetherCountingRule(const char *if1, const char *if2) {
741     return StringPrintf("-A %s -i %s -o %s -j RETURN", LOCAL_TETHER_COUNTERS_CHAIN, if1, if2);
742 }
743 
setForwardRules(bool add,const char * intIface,const char * extIface)744 int TetherController::setForwardRules(bool add, const char *intIface, const char *extIface) {
745     const char *op = add ? "-A" : "-D";
746 
747     std::string rpfilterCmd = StringPrintf(
748         "*raw\n"
749         "%s %s -i %s -m rpfilter --invert ! -s fe80::/64 -j DROP\n"
750         "COMMIT\n", op, LOCAL_RAW_PREROUTING, intIface);
751     if (iptablesRestoreFunction(V6, rpfilterCmd, nullptr) == -1 && add) {
752         return -EREMOTEIO;
753     }
754 
755     std::vector<std::string> v4 = {
756             "*raw",
757             StringPrintf("%s %s -p tcp --dport 21 -i %s -j CT --helper ftp", op,
758                          LOCAL_RAW_PREROUTING, intIface),
759             StringPrintf("%s %s -p tcp --dport 1723 -i %s -j CT --helper pptp", op,
760                          LOCAL_RAW_PREROUTING, intIface),
761             "COMMIT",
762             "*filter",
763             StringPrintf("%s %s -i %s -o %s -m state --state ESTABLISHED,RELATED -g %s", op,
764                          LOCAL_FORWARD, extIface, intIface, LOCAL_TETHER_COUNTERS_CHAIN),
765             StringPrintf("%s %s -i %s -o %s -m state --state INVALID -j DROP", op, LOCAL_FORWARD,
766                          intIface, extIface),
767             StringPrintf("%s %s -i %s -o %s -g %s", op, LOCAL_FORWARD, intIface, extIface,
768                          LOCAL_TETHER_COUNTERS_CHAIN),
769     };
770 
771     std::vector<std::string> v6 = {
772         "*filter",
773     };
774 
775     // We only ever add tethering quota rules so that they stick.
776     if (add && !tetherCountingRuleExists(intIface, extIface)) {
777         v4.push_back(makeTetherCountingRule(intIface, extIface));
778         v4.push_back(makeTetherCountingRule(extIface, intIface));
779         v6.push_back(makeTetherCountingRule(intIface, extIface));
780         v6.push_back(makeTetherCountingRule(extIface, intIface));
781     }
782 
783     // Always make sure the drop rule is at the end.
784     // TODO: instead of doing this, consider just rebuilding LOCAL_FORWARD completely from scratch
785     // every time, starting with ":tetherctrl_FORWARD -\n". This would likely be a bit simpler.
786     if (add) {
787         v4.push_back(StringPrintf("-D %s -j DROP", LOCAL_FORWARD));
788         v4.push_back(StringPrintf("-A %s -j DROP", LOCAL_FORWARD));
789     }
790 
791     v4.push_back("COMMIT\n");
792     v6.push_back("COMMIT\n");
793 
794     // We only add IPv6 rules here, never remove them.
795     if (iptablesRestoreFunction(V4, Join(v4, '\n'), nullptr) == -1 ||
796         (add && iptablesRestoreFunction(V6, Join(v6, '\n'), nullptr) == -1)) {
797         // unwind what's been done, but don't care about success - what more could we do?
798         if (add) {
799             setForwardRules(false, intIface, extIface);
800         }
801         return -EREMOTEIO;
802     }
803 
804     if (add) {
805         addForwardingPair(intIface, extIface);
806     } else {
807         markForwardingPairDisabled(intIface, extIface);
808     }
809 
810     return 0;
811 }
812 
disableNat(const char * intIface,const char * extIface)813 int TetherController::disableNat(const char* intIface, const char* extIface) {
814     if (!isIfaceName(intIface) || !isIfaceName(extIface)) {
815         errno = ENODEV;
816         return -errno;
817     }
818 
819     setForwardRules(false, intIface, extIface);
820     if (!isAnyForwardingEnabledOnUpstream(extIface)) maybeStopBpf(extIface);
821     if (!isAnyForwardingPairEnabled()) setDefaults();
822     return 0;
823 }
824 
825 namespace {
validateOffloadRule(const TetherOffloadRuleParcel & rule)826 Result<void> validateOffloadRule(const TetherOffloadRuleParcel& rule) {
827     struct ethhdr hdr;
828 
829     if (rule.inputInterfaceIndex <= 0) {
830         return Error(ENODEV) << "Invalid input interface " << rule.inputInterfaceIndex;
831     }
832     if (rule.outputInterfaceIndex <= 0) {
833         return Error(ENODEV) << "Invalid output interface " << rule.inputInterfaceIndex;
834     }
835     if (rule.prefixLength != 128) {
836         return Error(EINVAL) << "Prefix length must be 128, not " << rule.prefixLength;
837     }
838     if (rule.destination.size() != sizeof(in6_addr)) {
839         return Error(EAFNOSUPPORT) << "Invalid IP address length " << rule.destination.size();
840     }
841     if (rule.srcL2Address.size() != sizeof(hdr.h_source)) {
842         return Error(ENXIO) << "Invalid L2 src address length " << rule.srcL2Address.size();
843     }
844     if (rule.dstL2Address.size() != sizeof(hdr.h_dest)) {
845         return Error(ENXIO) << "Invalid L2 dst address length " << rule.dstL2Address.size();
846     }
847     if (rule.pmtu < IPV6_MIN_MTU || rule.pmtu > 0xFFFF) {
848         return Error(EINVAL) << "Invalid IPv6 path mtu " << rule.pmtu;
849     }
850     return Result<void>();
851 }
852 }  // namespace
853 
addOffloadRule(const TetherOffloadRuleParcel & rule)854 Result<void> TetherController::addOffloadRule(const TetherOffloadRuleParcel& rule) {
855     Result<void> res = validateOffloadRule(rule);
856     if (!res.ok()) return res;
857 
858     ethhdr hdr = {
859             .h_proto = htons(ETH_P_IPV6),
860     };
861     memcpy(&hdr.h_dest, rule.dstL2Address.data(), sizeof(hdr.h_dest));
862     memcpy(&hdr.h_source, rule.srcL2Address.data(), sizeof(hdr.h_source));
863 
864     // Only downstream supported for now.
865     TetherIngressKey key = {
866             .iif = static_cast<uint32_t>(rule.inputInterfaceIndex),
867             .neigh6 = *(const in6_addr*)rule.destination.data(),
868     };
869 
870     TetherIngressValue value = {
871             .oif = static_cast<uint32_t>(rule.outputInterfaceIndex),
872             .macHeader = hdr,
873             .pmtu = static_cast<uint16_t>(rule.pmtu),
874     };
875 
876     return mBpfIngressMap.writeValue(key, value, BPF_ANY);
877 }
878 
removeOffloadRule(const TetherOffloadRuleParcel & rule)879 Result<void> TetherController::removeOffloadRule(const TetherOffloadRuleParcel& rule) {
880     Result<void> res = validateOffloadRule(rule);
881     if (!res.ok()) return res;
882 
883     TetherIngressKey key = {
884             .iif = static_cast<uint32_t>(rule.inputInterfaceIndex),
885             .neigh6 = *(const in6_addr*)rule.destination.data(),
886     };
887 
888     Result<void> ret = mBpfIngressMap.deleteValue(key);
889 
890     // Silently return success if the rule did not exist.
891     if (!ret.ok() && ret.error().code() == ENOENT) return {};
892 
893     return ret;
894 }
895 
addStats(TetherStatsList & statsList,const TetherStats & stats)896 void TetherController::addStats(TetherStatsList& statsList, const TetherStats& stats) {
897     for (TetherStats& existing : statsList) {
898         if (existing.addStatsIfMatch(stats)) {
899             return;
900         }
901     }
902     // No match. Insert a new interface pair.
903     statsList.push_back(stats);
904 }
905 
906 /*
907  * Parse the ptks and bytes out of:
908  *   Chain tetherctrl_counters (4 references)
909  *       pkts      bytes target     prot opt in     out     source               destination
910  *         26     2373 RETURN     all  --  wlan0  rmnet0  0.0.0.0/0            0.0.0.0/0
911  *         27     2002 RETURN     all  --  rmnet0 wlan0   0.0.0.0/0            0.0.0.0/0
912  *       1040   107471 RETURN     all  --  bt-pan rmnet0  0.0.0.0/0            0.0.0.0/0
913  *       1450  1708806 RETURN     all  --  rmnet0 bt-pan  0.0.0.0/0            0.0.0.0/0
914  * or:
915  *   Chain tetherctrl_counters (0 references)
916  *       pkts      bytes target     prot opt in     out     source               destination
917  *          0        0 RETURN     all      wlan0  rmnet_data0  ::/0                 ::/0
918  *          0        0 RETURN     all      rmnet_data0 wlan0   ::/0                 ::/0
919  *
920  */
addForwardChainStats(TetherStatsList & statsList,const std::string & statsOutput,std::string & extraProcessingInfo)921 int TetherController::addForwardChainStats(TetherStatsList& statsList,
922                                            const std::string& statsOutput,
923                                            std::string &extraProcessingInfo) {
924     enum IndexOfIptChain {
925         ORIG_LINE,
926         PACKET_COUNTS,
927         BYTE_COUNTS,
928         HYPHEN,
929         IFACE0_NAME,
930         IFACE1_NAME,
931         SOURCE,
932         DESTINATION
933     };
934     TetherStats stats;
935     const TetherStats empty;
936 
937     static const std::string NUM = "(\\d+)";
938     static const std::string IFACE = "([^\\s]+)";
939     static const std::string DST = "(0.0.0.0/0|::/0)";
940     static const std::string COUNTERS = "\\s*" + NUM + "\\s+" + NUM +
941                                         " RETURN     all(  --  |      )" + IFACE + "\\s+" + IFACE +
942                                         "\\s+" + DST + "\\s+" + DST;
943     static const std::regex IP_RE(COUNTERS);
944 
945     const std::vector<std::string> lines = base::Split(statsOutput, "\n");
946     int headerLine = 0;
947     for (const std::string& line : lines) {
948         // Skip headers.
949         if (headerLine < 2) {
950             if (line.empty()) {
951                 ALOGV("Empty header while parsing tethering stats");
952                 return -EREMOTEIO;
953             }
954             headerLine++;
955             continue;
956         }
957 
958         if (line.empty()) continue;
959 
960         extraProcessingInfo = line;
961         std::smatch matches;
962         if (!std::regex_search(line, matches, IP_RE)) return -EREMOTEIO;
963         // Here use IP_RE to distiguish IPv4 and IPv6 iptables.
964         // IPv4 has "--" indicating what to do with fragments...
965         //		 26 	2373 RETURN     all  --  wlan0	rmnet0	0.0.0.0/0			 0.0.0.0/0
966         // ... but IPv6 does not.
967         //		 26 	2373 RETURN 	all      wlan0	rmnet0	::/0				 ::/0
968         // TODO: Replace strtoXX() calls with ParseUint() /ParseInt()
969         int64_t packets = strtoul(matches[PACKET_COUNTS].str().c_str(), nullptr, 10);
970         int64_t bytes = strtoul(matches[BYTE_COUNTS].str().c_str(), nullptr, 10);
971         std::string iface0 = matches[IFACE0_NAME].str();
972         std::string iface1 = matches[IFACE1_NAME].str();
973         std::string rest = matches[SOURCE].str();
974 
975         ALOGV("parse iface0=<%s> iface1=<%s> pkts=%" PRId64 " bytes=%" PRId64
976               " rest=<%s> orig line=<%s>",
977               iface0.c_str(), iface1.c_str(), packets, bytes, rest.c_str(), line.c_str());
978         /*
979          * The following assumes that the 1st rule has in:extIface out:intIface,
980          * which is what TetherController sets up.
981          * The 1st matches rx, and sets up the pair for the tx side.
982          */
983         if (!stats.intIface[0]) {
984             ALOGV("0Filter RX iface_in=%s iface_out=%s rx_bytes=%" PRId64 " rx_packets=%" PRId64
985                   " ", iface0.c_str(), iface1.c_str(), bytes, packets);
986             stats.intIface = iface0;
987             stats.extIface = iface1;
988             stats.txPackets = packets;
989             stats.txBytes = bytes;
990         } else if (stats.intIface == iface1 && stats.extIface == iface0) {
991             ALOGV("0Filter TX iface_in=%s iface_out=%s rx_bytes=%" PRId64 " rx_packets=%" PRId64
992                   " ", iface0.c_str(), iface1.c_str(), bytes, packets);
993             stats.rxPackets = packets;
994             stats.rxBytes = bytes;
995         }
996         if (stats.rxBytes != -1 && stats.txBytes != -1) {
997             ALOGV("rx_bytes=%" PRId64" tx_bytes=%" PRId64, stats.rxBytes, stats.txBytes);
998             addStats(statsList, stats);
999             stats = empty;
1000         }
1001     }
1002 
1003     /* It is always an error to find only one side of the stats. */
1004     if (((stats.rxBytes == -1) != (stats.txBytes == -1))) {
1005         return -EREMOTEIO;
1006     }
1007     return 0;
1008 }
1009 
getTetherStats()1010 StatusOr<TetherController::TetherStatsList> TetherController::getTetherStats() {
1011     TetherStatsList statsList;
1012     std::string parsedIptablesOutput;
1013 
1014     for (const IptablesTarget target : {V4, V6}) {
1015         std::string statsString;
1016         if (int ret = iptablesRestoreFunction(target, GET_TETHER_STATS_COMMAND, &statsString)) {
1017             return statusFromErrno(-ret, StringPrintf("failed to fetch tether stats (%d): %d",
1018                                                       target, ret));
1019         }
1020 
1021         if (int ret = addForwardChainStats(statsList, statsString, parsedIptablesOutput)) {
1022             return statusFromErrno(-ret, StringPrintf("failed to parse %s tether stats:\n%s",
1023                                                       target == V4 ? "IPv4": "IPv6",
1024                                                       parsedIptablesOutput.c_str()));
1025         }
1026     }
1027 
1028     return statsList;
1029 }
1030 
getTetherOffloadStats()1031 StatusOr<TetherController::TetherOffloadStatsList> TetherController::getTetherOffloadStats() {
1032     TetherOffloadStatsList statsList;
1033 
1034     const auto processTetherStats = [&statsList](const uint32_t& key, const TetherStatsValue& value,
1035                                                  const BpfMap<uint32_t, TetherStatsValue>&) {
1036         statsList.push_back({.ifIndex = static_cast<int>(key),
1037                              .rxBytes = static_cast<int64_t>(value.rxBytes),
1038                              .rxPackets = static_cast<int64_t>(value.rxPackets),
1039                              .txBytes = static_cast<int64_t>(value.txBytes),
1040                              .txPackets = static_cast<int64_t>(value.txPackets)});
1041         return Result<void>();
1042     };
1043 
1044     auto ret = mBpfStatsMap.iterateWithValue(processTetherStats);
1045     if (!ret.ok()) {
1046         // Ignore error to return the remaining tether stats result.
1047         ALOGE("Error processing tether stats from BPF maps: %s", ret.error().message().c_str());
1048     }
1049 
1050     return statsList;
1051 }
1052 
1053 // Use UINT64_MAX (~0uLL) for unlimited.
setBpfLimit(uint32_t ifIndex,uint64_t limit)1054 Result<void> TetherController::setBpfLimit(uint32_t ifIndex, uint64_t limit) {
1055     // The common case is an update, where the stats already exist,
1056     // hence we read first, even though writing with BPF_NOEXIST
1057     // first would make the code simpler.
1058     uint64_t rxBytes, txBytes;
1059     auto statsEntry = mBpfStatsMap.readValue(ifIndex);
1060 
1061     if (statsEntry.ok()) {
1062         // Ok, there was a stats entry.
1063         rxBytes = statsEntry.value().rxBytes;
1064         txBytes = statsEntry.value().txBytes;
1065     } else if (statsEntry.error().code() == ENOENT) {
1066         // No stats entry - create one with zeroes.
1067         TetherStatsValue stats = {};
1068         // This function is the *only* thing that can create entries.
1069         auto ret = mBpfStatsMap.writeValue(ifIndex, stats, BPF_NOEXIST);
1070         if (!ret.ok()) {
1071             ALOGE("mBpfStatsMap.writeValue failure: %s", strerror(ret.error().code()));
1072             return ret;
1073         }
1074         rxBytes = 0;
1075         txBytes = 0;
1076     } else {
1077         // Other error while trying to get stats entry.
1078         return statsEntry.error();
1079     }
1080 
1081     // rxBytes + txBytes won't overflow even at 5gbps for ~936 years.
1082     uint64_t newLimit = rxBytes + txBytes + limit;
1083 
1084     // if adding limit (e.g., if limit is UINT64_MAX) caused overflow: clamp to 'infinity'
1085     if (newLimit < rxBytes + txBytes) newLimit = ~0uLL;
1086 
1087     auto ret = mBpfLimitMap.writeValue(ifIndex, newLimit, BPF_ANY);
1088     if (!ret.ok()) {
1089         ALOGE("mBpfLimitMap.writeValue failure: %s", strerror(ret.error().code()));
1090         return ret;
1091     }
1092 
1093     return {};
1094 }
1095 
maybeStartBpf(const char * extIface)1096 void TetherController::maybeStartBpf(const char* extIface) {
1097     if (!bpf::isBpfSupported()) return;
1098 
1099     // TODO: perhaps ignore IPv4-only interface because IPv4 traffic downstream is not supported.
1100     int ifIndex = if_nametoindex(extIface);
1101     if (!ifIndex) {
1102         ALOGE("Fail to get index for interface %s", extIface);
1103         return;
1104     }
1105 
1106     auto isEthernet = android::net::isEthernet(extIface);
1107     if (!isEthernet.ok()) {
1108         ALOGE("isEthernet(%s[%d]) failure: %s", extIface, ifIndex,
1109               isEthernet.error().message().c_str());
1110         return;
1111     }
1112 
1113     int rv = getTetherIngressProgFd(isEthernet.value());
1114     if (rv < 0) {
1115         ALOGE("getTetherIngressProgFd(%d) failure: %s", isEthernet.value(), strerror(-rv));
1116         return;
1117     }
1118     unique_fd tetherProgFd(rv);
1119 
1120     rv = tcFilterAddDevIngressTether(ifIndex, tetherProgFd, isEthernet.value());
1121     if (rv) {
1122         ALOGE("tcFilterAddDevIngressTether(%d[%s], %d) failure: %s", ifIndex, extIface,
1123               isEthernet.value(), strerror(-rv));
1124         return;
1125     }
1126 }
1127 
maybeStopBpf(const char * extIface)1128 void TetherController::maybeStopBpf(const char* extIface) {
1129     if (!bpf::isBpfSupported()) return;
1130 
1131     // TODO: perhaps ignore IPv4-only interface because IPv4 traffic downstream is not supported.
1132     int ifIndex = if_nametoindex(extIface);
1133     if (!ifIndex) {
1134         ALOGE("Fail to get index for interface %s", extIface);
1135         return;
1136     }
1137 
1138     int rv = tcFilterDelDevIngressTether(ifIndex);
1139     if (rv < 0) {
1140         ALOGE("tcFilterDelDevIngressTether(%d[%s]) failure: %s", ifIndex, extIface, strerror(-rv));
1141     }
1142 }
1143 
setTetherOffloadInterfaceQuota(int ifIndex,int64_t maxBytes)1144 int TetherController::setTetherOffloadInterfaceQuota(int ifIndex, int64_t maxBytes) {
1145     if (!mBpfStatsMap.isValid() || !mBpfLimitMap.isValid()) return -ENOTSUP;
1146 
1147     if (ifIndex <= 0) return -ENODEV;
1148 
1149     if (maxBytes < QUOTA_UNLIMITED) {
1150         ALOGE("Invalid bytes value. Must be -1 (unlimited) or 0..max_int64.");
1151         return -ERANGE;
1152     }
1153 
1154     // Note that a value of unlimited quota (-1) indicates simply max_uint64.
1155     const auto res = setBpfLimit(static_cast<uint32_t>(ifIndex), static_cast<uint64_t>(maxBytes));
1156     if (!res.ok()) {
1157         ALOGE("Fail to set quota %" PRId64 " for interface index %d: %s", maxBytes, ifIndex,
1158               strerror(res.error().code()));
1159         return -res.error().code();
1160     }
1161 
1162     return 0;
1163 }
1164 
getAndClearTetherOffloadStats(int ifIndex)1165 Result<TetherController::TetherOffloadStats> TetherController::getAndClearTetherOffloadStats(
1166         int ifIndex) {
1167     if (!mBpfStatsMap.isValid() || !mBpfLimitMap.isValid()) return Error(ENOTSUP);
1168 
1169     if (ifIndex <= 0) {
1170         return Error(ENODEV) << "Invalid interface " << ifIndex;
1171     }
1172 
1173     // getAndClearTetherOffloadStats is called after all offload rules have already been deleted
1174     // for the given upstream interface. Before starting to do cleanup stuff in this function, use
1175     // synchronizeKernelRCU to make sure that all the current running eBPF programs are finished
1176     // on all CPUs, especially the unfinished packet processing. After synchronizeKernelRCU
1177     // returned, we can safely read or delete on the stats map or the limit map.
1178     if (int res = bpf::synchronizeKernelRCU()) {
1179         // Error log but don't return error. Do as much cleanup as possible.
1180         ALOGE("synchronize_rcu() failed: %s", strerror(-res));
1181     }
1182 
1183     const auto stats = mBpfStatsMap.readValue(ifIndex);
1184     if (!stats.ok()) {
1185         return Error(stats.error().code()) << "Fail to get stats for interface index " << ifIndex;
1186     }
1187 
1188     auto res = mBpfStatsMap.deleteValue(ifIndex);
1189     if (!res.ok()) {
1190         return Error(res.error().code()) << "Fail to delete stats for interface index " << ifIndex;
1191     }
1192 
1193     res = mBpfLimitMap.deleteValue(ifIndex);
1194     if (!res.ok()) {
1195         return Error(res.error().code()) << "Fail to delete limit for interface index " << ifIndex;
1196     }
1197 
1198     return TetherOffloadStats{.ifIndex = static_cast<int>(ifIndex),
1199                               .rxBytes = static_cast<int64_t>(stats.value().rxBytes),
1200                               .rxPackets = static_cast<int64_t>(stats.value().rxPackets),
1201                               .txBytes = static_cast<int64_t>(stats.value().txBytes),
1202                               .txPackets = static_cast<int64_t>(stats.value().txPackets)};
1203 }
1204 
dumpIfaces(DumpWriter & dw)1205 void TetherController::dumpIfaces(DumpWriter& dw) {
1206     dw.println("Interface pairs:");
1207 
1208     ScopedIndent ifaceIndent(dw);
1209     for (const auto& it : mFwdIfaces) {
1210         dw.println("%s -> %s %s", it.first.c_str(), it.second.iface.c_str(),
1211                    (it.second.active ? "ACTIVE" : "DISABLED"));
1212     }
1213 }
1214 
1215 namespace {
1216 
l2ToString(const uint8_t * addr,size_t len)1217 std::string l2ToString(const uint8_t* addr, size_t len) {
1218     std::string str;
1219 
1220     if (len == 0) return str;
1221 
1222     StringAppendF(&str, "%02x", addr[0]);
1223     for (size_t i = 1; i < len; i++) {
1224         StringAppendF(&str, ":%02x", addr[i]);
1225     }
1226 
1227     return str;
1228 }
1229 
1230 }  // namespace
1231 
dumpBpf(DumpWriter & dw)1232 void TetherController::dumpBpf(DumpWriter& dw) {
1233     if (!mBpfIngressMap.isValid() || !mBpfStatsMap.isValid() || !mBpfLimitMap.isValid()) {
1234         dw.println("BPF not supported");
1235         return;
1236     }
1237 
1238     dw.println("BPF ingress map: iif(iface) v6addr -> oif(iface) srcmac dstmac ethertype [pmtu]");
1239     const auto printIngressMap = [&dw](const TetherIngressKey& key, const TetherIngressValue& value,
1240                                        const BpfMap<TetherIngressKey, TetherIngressValue>&) {
1241         char addr[INET6_ADDRSTRLEN];
1242         std::string src = l2ToString(value.macHeader.h_source, sizeof(value.macHeader.h_source));
1243         std::string dst = l2ToString(value.macHeader.h_dest, sizeof(value.macHeader.h_dest));
1244         inet_ntop(AF_INET6, &key.neigh6, addr, sizeof(addr));
1245 
1246         char iifStr[IFNAMSIZ] = "?";
1247         char oifStr[IFNAMSIZ] = "?";
1248         if_indextoname(key.iif, iifStr);
1249         if_indextoname(value.oif, oifStr);
1250         dw.println("%u(%s) %s -> %u(%s) %s %s %04x [%u]", key.iif, iifStr, addr, value.oif, oifStr,
1251                    src.c_str(), dst.c_str(), ntohs(value.macHeader.h_proto), value.pmtu);
1252 
1253         return Result<void>();
1254     };
1255 
1256     dw.incIndent();
1257     auto ret = mBpfIngressMap.iterateWithValue(printIngressMap);
1258     if (!ret.ok()) {
1259         dw.println("Error printing BPF ingress map: %s", ret.error().message().c_str());
1260     }
1261     dw.decIndent();
1262 
1263     dw.println("BPF stats (downlink): iif(iface) -> packets bytes errors");
1264     const auto printStatsMap = [&dw](const uint32_t& key, const TetherStatsValue& value,
1265                                      const BpfMap<uint32_t, TetherStatsValue>&) {
1266         char iifStr[IFNAMSIZ] = "?";
1267         if_indextoname(key, iifStr);
1268         dw.println("%u(%s) -> %" PRIu64 " %" PRIu64 " %" PRIu64, key, iifStr, value.rxPackets,
1269                    value.rxBytes, value.rxErrors);
1270 
1271         return Result<void>();
1272     };
1273 
1274     dw.incIndent();
1275     ret = mBpfStatsMap.iterateWithValue(printStatsMap);
1276     if (!ret.ok()) {
1277         dw.println("Error printing BPF stats map: %s", ret.error().message().c_str());
1278     }
1279     dw.decIndent();
1280 
1281     dw.println("BPF limit: iif(iface) -> bytes");
1282     const auto printLimitMap = [&dw](const uint32_t& key, const uint64_t& value,
1283                                      const BpfMap<uint32_t, uint64_t>&) {
1284         char iifStr[IFNAMSIZ] = "?";
1285         if_indextoname(key, iifStr);
1286         dw.println("%u(%s) -> %" PRIu64, key, iifStr, value);
1287 
1288         return Result<void>();
1289     };
1290 
1291     dw.incIndent();
1292     ret = mBpfLimitMap.iterateWithValue(printLimitMap);
1293     if (!ret.ok()) {
1294         dw.println("Error printing BPF limit map: %s", ret.error().message().c_str());
1295     }
1296     dw.decIndent();
1297 }
1298 
dump(DumpWriter & dw)1299 void TetherController::dump(DumpWriter& dw) {
1300     std::lock_guard guard(lock);
1301 
1302     ScopedIndent tetherControllerIndent(dw);
1303     dw.println("TetherController");
1304     dw.incIndent();
1305 
1306     dw.println("Forwarding requests: " + Join(mForwardingRequests, ' '));
1307     if (mDnsNetId != 0) {
1308         dw.println(StringPrintf("DNS: netId %d servers [%s]", mDnsNetId,
1309                                 Join(mDnsForwarders, ", ").c_str()));
1310     }
1311     if (mDaemonPid != 0) {
1312         dw.println("dnsmasq PID: %d", mDaemonPid);
1313     }
1314 
1315     dumpIfaces(dw);
1316     dw.println("");
1317     dumpBpf(dw);
1318 }
1319 
1320 }  // namespace net
1321 }  // namespace android
1322