Home | History | Annotate | Download | only in server
      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 <string.h>
     22 
     23 #include <sys/socket.h>
     24 #include <sys/stat.h>
     25 #include <sys/types.h>
     26 #include <sys/wait.h>
     27 
     28 #include <netinet/in.h>
     29 #include <arpa/inet.h>
     30 
     31 #include <array>
     32 #include <cstdlib>
     33 #include <string>
     34 #include <vector>
     35 
     36 #define LOG_TAG "TetherController"
     37 #include <android-base/strings.h>
     38 #include <android-base/stringprintf.h>
     39 #include <cutils/log.h>
     40 #include <cutils/properties.h>
     41 #include <netdutils/StatusOr.h>
     42 
     43 #include "Fwmark.h"
     44 #include "NetdConstants.h"
     45 #include "Permission.h"
     46 #include "InterfaceController.h"
     47 #include "NetworkController.h"
     48 #include "ResponseCode.h"
     49 #include "TetherController.h"
     50 
     51 using android::base::Join;
     52 using android::base::StringPrintf;
     53 using android::base::StringAppendF;
     54 using android::netdutils::StatusOr;
     55 using android::netdutils::statusFromErrno;
     56 
     57 namespace {
     58 
     59 const char BP_TOOLS_MODE[] = "bp-tools";
     60 const char IPV4_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv4/ip_forward";
     61 const char IPV6_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv6/conf/all/forwarding";
     62 const char SEPARATOR[] = "|";
     63 constexpr const char kTcpBeLiberal[] = "/proc/sys/net/netfilter/nf_conntrack_tcp_be_liberal";
     64 
     65 // Chosen to match AID_DNS_TETHER, as made "friendly" by fs_config_generator.py.
     66 constexpr const char kDnsmasqUsername[] = "dns_tether";
     67 
     68 bool writeToFile(const char* filename, const char* value) {
     69     int fd = open(filename, O_WRONLY | O_CLOEXEC);
     70     if (fd < 0) {
     71         ALOGE("Failed to open %s: %s", filename, strerror(errno));
     72         return false;
     73     }
     74 
     75     const ssize_t len = strlen(value);
     76     if (write(fd, value, len) != len) {
     77         ALOGE("Failed to write %s to %s: %s", value, filename, strerror(errno));
     78         close(fd);
     79         return false;
     80     }
     81     close(fd);
     82     return true;
     83 }
     84 
     85 // TODO: Consider altering TCP and UDP timeouts as well.
     86 void configureForTethering(bool enabled) {
     87     writeToFile(kTcpBeLiberal, enabled ? "1" : "0");
     88 }
     89 
     90 bool configureForIPv6Router(const char *interface) {
     91     return (InterfaceController::setEnableIPv6(interface, 0) == 0)
     92             && (InterfaceController::setAcceptIPv6Ra(interface, 0) == 0)
     93             && (InterfaceController::setAcceptIPv6Dad(interface, 0) == 0)
     94             && (InterfaceController::setIPv6DadTransmits(interface, "0") == 0)
     95             && (InterfaceController::setEnableIPv6(interface, 1) == 0);
     96 }
     97 
     98 void configureForIPv6Client(const char *interface) {
     99     InterfaceController::setAcceptIPv6Ra(interface, 1);
    100     InterfaceController::setAcceptIPv6Dad(interface, 1);
    101     InterfaceController::setIPv6DadTransmits(interface, "1");
    102     InterfaceController::setEnableIPv6(interface, 0);
    103 }
    104 
    105 bool inBpToolsMode() {
    106     // In BP tools mode, do not disable IP forwarding
    107     char bootmode[PROPERTY_VALUE_MAX] = {0};
    108     property_get("ro.bootmode", bootmode, "unknown");
    109     return !strcmp(BP_TOOLS_MODE, bootmode);
    110 }
    111 
    112 }  // namespace
    113 
    114 namespace android {
    115 namespace net {
    116 
    117 auto TetherController::iptablesRestoreFunction = execIptablesRestoreWithOutput;
    118 
    119 const int MAX_IPT_OUTPUT_LINE_LEN = 256;
    120 
    121 const std::string GET_TETHER_STATS_COMMAND = StringPrintf(
    122     "*filter\n"
    123     "-nvx -L %s\n"
    124     "COMMIT\n", android::net::TetherController::LOCAL_TETHER_COUNTERS_CHAIN);
    125 
    126 TetherController::TetherController() {
    127     mDnsNetId = 0;
    128     mDaemonFd = -1;
    129     mDaemonPid = 0;
    130     if (inBpToolsMode()) {
    131         enableForwarding(BP_TOOLS_MODE);
    132     } else {
    133         setIpFwdEnabled();
    134     }
    135 }
    136 
    137 TetherController::~TetherController() {
    138     mInterfaces.clear();
    139     mDnsForwarders.clear();
    140     mForwardingRequests.clear();
    141     mFwdIfaces.clear();
    142 }
    143 
    144 bool TetherController::setIpFwdEnabled() {
    145     bool success = true;
    146     const char* value = mForwardingRequests.empty() ? "0" : "1";
    147     ALOGD("Setting IP forward enable = %s", value);
    148     success &= writeToFile(IPV4_FORWARDING_PROC_FILE, value);
    149     success &= writeToFile(IPV6_FORWARDING_PROC_FILE, value);
    150     return success;
    151 }
    152 
    153 bool TetherController::enableForwarding(const char* requester) {
    154     // Don't return an error if this requester already requested forwarding. Only return errors for
    155     // things that the caller caller needs to care about, such as "couldn't write to the file to
    156     // enable forwarding".
    157     mForwardingRequests.insert(requester);
    158     return setIpFwdEnabled();
    159 }
    160 
    161 bool TetherController::disableForwarding(const char* requester) {
    162     mForwardingRequests.erase(requester);
    163     return setIpFwdEnabled();
    164 }
    165 
    166 size_t TetherController::forwardingRequestCount() {
    167     return mForwardingRequests.size();
    168 }
    169 
    170 int TetherController::startTethering(int num_addrs, char **dhcp_ranges) {
    171     if (mDaemonPid != 0) {
    172         ALOGE("Tethering already started");
    173         errno = EBUSY;
    174         return -1;
    175     }
    176 
    177     ALOGD("Starting tethering services");
    178 
    179     pid_t pid;
    180     int pipefd[2];
    181 
    182     if (pipe(pipefd) < 0) {
    183         ALOGE("pipe failed (%s)", strerror(errno));
    184         return -1;
    185     }
    186 
    187     /*
    188      * TODO: Create a monitoring thread to handle and restart
    189      * the daemon if it exits prematurely
    190      */
    191     if ((pid = fork()) < 0) {
    192         ALOGE("fork failed (%s)", strerror(errno));
    193         close(pipefd[0]);
    194         close(pipefd[1]);
    195         return -1;
    196     }
    197 
    198     if (!pid) {
    199         close(pipefd[1]);
    200         if (pipefd[0] != STDIN_FILENO) {
    201             if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) {
    202                 ALOGE("dup2 failed (%s)", strerror(errno));
    203                 return -1;
    204             }
    205             close(pipefd[0]);
    206         }
    207 
    208         Fwmark fwmark;
    209         fwmark.netId = NetworkController::LOCAL_NET_ID;
    210         fwmark.explicitlySelected = true;
    211         fwmark.protectedFromVpn = true;
    212         fwmark.permission = PERMISSION_SYSTEM;
    213         char markStr[UINT32_HEX_STRLEN];
    214         snprintf(markStr, sizeof(markStr), "0x%x", fwmark.intValue);
    215 
    216         std::vector<const std::string> argVector = {
    217             "/system/bin/dnsmasq",
    218             "--keep-in-foreground",
    219             "--no-resolv",
    220             "--no-poll",
    221             "--dhcp-authoritative",
    222             // TODO: pipe through metered status from ConnService
    223             "--dhcp-option-force=43,ANDROID_METERED",
    224             "--pid-file",
    225             "--listen-mark", markStr,
    226             "--user", kDnsmasqUsername,
    227         };
    228 
    229         for (int addrIndex = 0; addrIndex < num_addrs; addrIndex += 2) {
    230             argVector.push_back(
    231                     StringPrintf("--dhcp-range=%s,%s,1h",
    232                                  dhcp_ranges[addrIndex], dhcp_ranges[addrIndex+1]));
    233         }
    234 
    235         auto args = (char**)std::calloc(argVector.size() + 1, sizeof(char*));
    236         for (unsigned i = 0; i < argVector.size(); i++) {
    237             args[i] = (char*)argVector[i].c_str();
    238         }
    239 
    240         if (execv(args[0], args)) {
    241             ALOGE("execv failed (%s)", strerror(errno));
    242         }
    243         ALOGE("Should never get here!");
    244         _exit(-1);
    245     } else {
    246         close(pipefd[0]);
    247         mDaemonPid = pid;
    248         mDaemonFd = pipefd[1];
    249         configureForTethering(true);
    250         applyDnsInterfaces();
    251         ALOGD("Tethering services running");
    252     }
    253 
    254     return 0;
    255 }
    256 
    257 int TetherController::stopTethering() {
    258     configureForTethering(false);
    259 
    260     if (mDaemonPid == 0) {
    261         ALOGE("Tethering already stopped");
    262         return 0;
    263     }
    264 
    265     ALOGD("Stopping tethering services");
    266 
    267     kill(mDaemonPid, SIGTERM);
    268     waitpid(mDaemonPid, NULL, 0);
    269     mDaemonPid = 0;
    270     close(mDaemonFd);
    271     mDaemonFd = -1;
    272     ALOGD("Tethering services stopped");
    273     return 0;
    274 }
    275 
    276 bool TetherController::isTetheringStarted() {
    277     return (mDaemonPid == 0 ? false : true);
    278 }
    279 
    280 #define MAX_CMD_SIZE 1024
    281 
    282 int TetherController::setDnsForwarders(unsigned netId, char **servers, int numServers) {
    283     int i;
    284     char daemonCmd[MAX_CMD_SIZE];
    285 
    286     Fwmark fwmark;
    287     fwmark.netId = netId;
    288     fwmark.explicitlySelected = true;
    289     fwmark.protectedFromVpn = true;
    290     fwmark.permission = PERMISSION_SYSTEM;
    291 
    292     snprintf(daemonCmd, sizeof(daemonCmd), "update_dns%s0x%x", SEPARATOR, fwmark.intValue);
    293     int cmdLen = strlen(daemonCmd);
    294 
    295     mDnsForwarders.clear();
    296     for (i = 0; i < numServers; i++) {
    297         ALOGD("setDnsForwarders(0x%x %d = '%s')", fwmark.intValue, i, servers[i]);
    298 
    299         addrinfo *res, hints = { .ai_flags = AI_NUMERICHOST };
    300         int ret = getaddrinfo(servers[i], NULL, &hints, &res);
    301         freeaddrinfo(res);
    302         if (ret) {
    303             ALOGE("Failed to parse DNS server '%s'", servers[i]);
    304             mDnsForwarders.clear();
    305             errno = EINVAL;
    306             return -1;
    307         }
    308 
    309         cmdLen += (strlen(servers[i]) + 1);
    310         if (cmdLen + 1 >= MAX_CMD_SIZE) {
    311             ALOGD("Too many DNS servers listed");
    312             break;
    313         }
    314 
    315         strcat(daemonCmd, SEPARATOR);
    316         strcat(daemonCmd, servers[i]);
    317         mDnsForwarders.push_back(servers[i]);
    318     }
    319 
    320     mDnsNetId = netId;
    321     if (mDaemonFd != -1) {
    322         ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
    323         if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
    324             ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
    325             mDnsForwarders.clear();
    326             errno = EREMOTEIO;
    327             return -1;
    328         }
    329     }
    330     return 0;
    331 }
    332 
    333 unsigned TetherController::getDnsNetId() {
    334     return mDnsNetId;
    335 }
    336 
    337 const std::list<std::string> &TetherController::getDnsForwarders() const {
    338     return mDnsForwarders;
    339 }
    340 
    341 bool TetherController::applyDnsInterfaces() {
    342     char daemonCmd[MAX_CMD_SIZE];
    343 
    344     strcpy(daemonCmd, "update_ifaces");
    345     int cmdLen = strlen(daemonCmd);
    346     bool haveInterfaces = false;
    347 
    348     for (const auto &ifname : mInterfaces) {
    349         cmdLen += (ifname.size() + 1);
    350         if (cmdLen + 1 >= MAX_CMD_SIZE) {
    351             ALOGD("Too many DNS ifaces listed");
    352             break;
    353         }
    354 
    355         strcat(daemonCmd, SEPARATOR);
    356         strcat(daemonCmd, ifname.c_str());
    357         haveInterfaces = true;
    358     }
    359 
    360     if ((mDaemonFd != -1) && haveInterfaces) {
    361         ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
    362         if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
    363             ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
    364             return false;
    365         }
    366     }
    367     return true;
    368 }
    369 
    370 int TetherController::tetherInterface(const char *interface) {
    371     ALOGD("tetherInterface(%s)", interface);
    372     if (!isIfaceName(interface)) {
    373         errno = ENOENT;
    374         return -1;
    375     }
    376 
    377     if (!configureForIPv6Router(interface)) {
    378         configureForIPv6Client(interface);
    379         return -1;
    380     }
    381     mInterfaces.push_back(interface);
    382 
    383     if (!applyDnsInterfaces()) {
    384         mInterfaces.pop_back();
    385         configureForIPv6Client(interface);
    386         return -1;
    387     } else {
    388         return 0;
    389     }
    390 }
    391 
    392 int TetherController::untetherInterface(const char *interface) {
    393     ALOGD("untetherInterface(%s)", interface);
    394 
    395     for (auto it = mInterfaces.cbegin(); it != mInterfaces.cend(); ++it) {
    396         if (!strcmp(interface, it->c_str())) {
    397             mInterfaces.erase(it);
    398 
    399             configureForIPv6Client(interface);
    400             return applyDnsInterfaces() ? 0 : -1;
    401         }
    402     }
    403     errno = ENOENT;
    404     return -1;
    405 }
    406 
    407 const std::list<std::string> &TetherController::getTetheredInterfaceList() const {
    408     return mInterfaces;
    409 }
    410 
    411 int TetherController::setupIptablesHooks() {
    412     int res;
    413     res = setDefaults();
    414     if (res < 0) {
    415         return res;
    416     }
    417 
    418     // Used to limit downstream mss to the upstream pmtu so we don't end up fragmenting every large
    419     // packet tethered devices send. This is IPv4-only, because in IPv6 we send the MTU in the RA.
    420     // This is no longer optional and tethering will fail to start if it fails.
    421     std::string mssRewriteCommand = StringPrintf(
    422         "*mangle\n"
    423         "-A %s -p tcp --tcp-flags SYN SYN -j TCPMSS --clamp-mss-to-pmtu\n"
    424         "COMMIT\n", LOCAL_MANGLE_FORWARD);
    425 
    426     // This is for tethering counters. This chain is reached via --goto, and then RETURNS.
    427     std::string defaultCommands = StringPrintf(
    428         "*filter\n"
    429         ":%s -\n"
    430         "COMMIT\n", LOCAL_TETHER_COUNTERS_CHAIN);
    431 
    432     res = iptablesRestoreFunction(V4, mssRewriteCommand, nullptr);
    433     if (res < 0) {
    434         return res;
    435     }
    436 
    437     res = iptablesRestoreFunction(V4V6, defaultCommands, nullptr);
    438     if (res < 0) {
    439         return res;
    440     }
    441 
    442     mFwdIfaces.clear();
    443 
    444     return 0;
    445 }
    446 
    447 int TetherController::setDefaults() {
    448     std::string v4Cmd = StringPrintf(
    449         "*filter\n"
    450         ":%s -\n"
    451         "-A %s -j DROP\n"
    452         "COMMIT\n"
    453         "*nat\n"
    454         ":%s -\n"
    455         "COMMIT\n", LOCAL_FORWARD, LOCAL_FORWARD, LOCAL_NAT_POSTROUTING);
    456 
    457     std::string v6Cmd = StringPrintf(
    458         "*filter\n"
    459         ":%s -\n"
    460         "COMMIT\n"
    461         "*raw\n"
    462         ":%s -\n"
    463         "COMMIT\n", LOCAL_FORWARD, LOCAL_RAW_PREROUTING);
    464 
    465     int res = iptablesRestoreFunction(V4, v4Cmd, nullptr);
    466     if (res < 0) {
    467         return res;
    468     }
    469 
    470     res = iptablesRestoreFunction(V6, v6Cmd, nullptr);
    471     if (res < 0) {
    472         return res;
    473     }
    474 
    475     return 0;
    476 }
    477 
    478 int TetherController::enableNat(const char* intIface, const char* extIface) {
    479     ALOGV("enableNat(intIface=<%s>, extIface=<%s>)",intIface, extIface);
    480 
    481     if (!isIfaceName(intIface) || !isIfaceName(extIface)) {
    482         errno = ENODEV;
    483         return -1;
    484     }
    485 
    486     /* Bug: b/9565268. "enableNat wlan0 wlan0". For now we fail until java-land is fixed */
    487     if (!strcmp(intIface, extIface)) {
    488         ALOGE("Duplicate interface specified: %s %s", intIface, extIface);
    489         errno = EINVAL;
    490         return -1;
    491     }
    492 
    493     if (isForwardingPairEnabled(intIface, extIface)) {
    494         return 0;
    495     }
    496 
    497     // add this if we are the first enabled nat for this upstream
    498     if (!isAnyForwardingEnabledOnUpstream(extIface)) {
    499         std::vector<std::string> v4Cmds = {
    500             "*nat",
    501             StringPrintf("-A %s -o %s -j MASQUERADE", LOCAL_NAT_POSTROUTING, extIface),
    502             "COMMIT\n"
    503         };
    504 
    505         if (iptablesRestoreFunction(V4, Join(v4Cmds, '\n'), nullptr) ||
    506             setupIPv6CountersChain()) {
    507             ALOGE("Error setting postroute rule: iface=%s", extIface);
    508             if (!isAnyForwardingPairEnabled()) {
    509                 // unwind what's been done, but don't care about success - what more could we do?
    510                 setDefaults();
    511             }
    512             return -1;
    513         }
    514     }
    515 
    516     if (setForwardRules(true, intIface, extIface) != 0) {
    517         ALOGE("Error setting forward rules");
    518         if (!isAnyForwardingPairEnabled()) {
    519             setDefaults();
    520         }
    521         errno = ENODEV;
    522         return -1;
    523     }
    524 
    525     return 0;
    526 }
    527 
    528 int TetherController::setupIPv6CountersChain() {
    529     // Only add this if we are the first enabled nat
    530     if (isAnyForwardingPairEnabled()) {
    531         return 0;
    532     }
    533 
    534     /*
    535      * IPv6 tethering doesn't need the state-based conntrack rules, so
    536      * it unconditionally jumps to the tether counters chain all the time.
    537      */
    538     std::vector<std::string> v6Cmds = {
    539         "*filter",
    540         StringPrintf("-A %s -g %s", LOCAL_FORWARD, LOCAL_TETHER_COUNTERS_CHAIN),
    541         "COMMIT\n"
    542     };
    543 
    544     return iptablesRestoreFunction(V6, Join(v6Cmds, '\n'), nullptr);
    545 }
    546 
    547 // Gets a pointer to the ForwardingDownstream for an interface pair in the map, or nullptr
    548 TetherController::ForwardingDownstream* TetherController::findForwardingDownstream(
    549         const std::string& intIface, const std::string& extIface) {
    550     auto extIfaceMatches = mFwdIfaces.equal_range(extIface);
    551     for (auto it = extIfaceMatches.first; it != extIfaceMatches.second; ++it) {
    552         if (it->second.iface == intIface) {
    553             return &(it->second);
    554         }
    555     }
    556     return nullptr;
    557 }
    558 
    559 void TetherController::addForwardingPair(const std::string& intIface, const std::string& extIface) {
    560     ForwardingDownstream* existingEntry = findForwardingDownstream(intIface, extIface);
    561     if (existingEntry != nullptr) {
    562         existingEntry->active = true;
    563         return;
    564     }
    565 
    566     mFwdIfaces.insert(std::pair<std::string, ForwardingDownstream>(extIface, {
    567         .iface = intIface,
    568         .active = true
    569     }));
    570 }
    571 
    572 void TetherController::markForwardingPairDisabled(
    573         const std::string& intIface, const std::string& extIface) {
    574     ForwardingDownstream* existingEntry = findForwardingDownstream(intIface, extIface);
    575     if (existingEntry == nullptr) {
    576         return;
    577     }
    578 
    579     existingEntry->active = false;
    580 }
    581 
    582 bool TetherController::isForwardingPairEnabled(
    583         const std::string& intIface, const std::string& extIface) {
    584     ForwardingDownstream* existingEntry = findForwardingDownstream(intIface, extIface);
    585     return existingEntry != nullptr && existingEntry->active;
    586 }
    587 
    588 bool TetherController::isAnyForwardingEnabledOnUpstream(const std::string& extIface) {
    589     auto extIfaceMatches = mFwdIfaces.equal_range(extIface);
    590     for (auto it = extIfaceMatches.first; it != extIfaceMatches.second; ++it) {
    591         if (it->second.active) {
    592             return true;
    593         }
    594     }
    595     return false;
    596 }
    597 
    598 bool TetherController::isAnyForwardingPairEnabled() {
    599     for (auto& it : mFwdIfaces) {
    600         if (it.second.active) {
    601             return true;
    602         }
    603     }
    604     return false;
    605 }
    606 
    607 bool TetherController::tetherCountingRuleExists(
    608         const std::string& iface1, const std::string& iface2) {
    609     // A counting rule exists if NAT was ever enabled for this interface pair, so if the pair
    610     // is in the map regardless of its active status. Rules are added both ways so we check with
    611     // the 2 combinations.
    612     return findForwardingDownstream(iface1, iface2) != nullptr
    613         || findForwardingDownstream(iface2, iface1) != nullptr;
    614 }
    615 
    616 /* static */
    617 std::string TetherController::makeTetherCountingRule(const char *if1, const char *if2) {
    618     return StringPrintf("-A %s -i %s -o %s -j RETURN", LOCAL_TETHER_COUNTERS_CHAIN, if1, if2);
    619 }
    620 
    621 int TetherController::setForwardRules(bool add, const char *intIface, const char *extIface) {
    622     const char *op = add ? "-A" : "-D";
    623 
    624     std::string rpfilterCmd = StringPrintf(
    625         "*raw\n"
    626         "%s %s -i %s -m rpfilter --invert ! -s fe80::/64 -j DROP\n"
    627         "COMMIT\n", op, LOCAL_RAW_PREROUTING, intIface);
    628     if (iptablesRestoreFunction(V6, rpfilterCmd, nullptr) == -1 && add) {
    629         return -1;
    630     }
    631 
    632     std::vector<std::string> v4 = {
    633         "*filter",
    634         StringPrintf("%s %s -i %s -o %s -m state --state ESTABLISHED,RELATED -g %s",
    635                      op, LOCAL_FORWARD, extIface, intIface, LOCAL_TETHER_COUNTERS_CHAIN),
    636         StringPrintf("%s %s -i %s -o %s -m state --state INVALID -j DROP",
    637                      op, LOCAL_FORWARD, intIface, extIface),
    638         StringPrintf("%s %s -i %s -o %s -g %s",
    639                      op, LOCAL_FORWARD, intIface, extIface, LOCAL_TETHER_COUNTERS_CHAIN),
    640     };
    641 
    642     std::vector<std::string> v6 = {
    643         "*filter",
    644     };
    645 
    646     // We only ever add tethering quota rules so that they stick.
    647     if (add && !tetherCountingRuleExists(intIface, extIface)) {
    648         v4.push_back(makeTetherCountingRule(intIface, extIface));
    649         v4.push_back(makeTetherCountingRule(extIface, intIface));
    650         v6.push_back(makeTetherCountingRule(intIface, extIface));
    651         v6.push_back(makeTetherCountingRule(extIface, intIface));
    652     }
    653 
    654     // Always make sure the drop rule is at the end.
    655     // TODO: instead of doing this, consider just rebuilding LOCAL_FORWARD completely from scratch
    656     // every time, starting with ":tetherctrl_FORWARD -\n". This would likely be a bit simpler.
    657     if (add) {
    658         v4.push_back(StringPrintf("-D %s -j DROP", LOCAL_FORWARD));
    659         v4.push_back(StringPrintf("-A %s -j DROP", LOCAL_FORWARD));
    660     }
    661 
    662     v4.push_back("COMMIT\n");
    663     v6.push_back("COMMIT\n");
    664 
    665     // We only add IPv6 rules here, never remove them.
    666     if (iptablesRestoreFunction(V4, Join(v4, '\n'), nullptr) == -1 ||
    667         (add && iptablesRestoreFunction(V6, Join(v6, '\n'), nullptr) == -1)) {
    668         // unwind what's been done, but don't care about success - what more could we do?
    669         if (add) {
    670             setForwardRules(false, intIface, extIface);
    671         }
    672         return -1;
    673     }
    674 
    675     if (add) {
    676         addForwardingPair(intIface, extIface);
    677     } else {
    678         markForwardingPairDisabled(intIface, extIface);
    679     }
    680 
    681     return 0;
    682 }
    683 
    684 int TetherController::disableNat(const char* intIface, const char* extIface) {
    685     if (!isIfaceName(intIface) || !isIfaceName(extIface)) {
    686         errno = ENODEV;
    687         return -1;
    688     }
    689 
    690     setForwardRules(false, intIface, extIface);
    691     if (!isAnyForwardingPairEnabled()) {
    692         setDefaults();
    693     }
    694     return 0;
    695 }
    696 
    697 void TetherController::addStats(TetherStatsList& statsList, const TetherStats& stats) {
    698     for (TetherStats& existing : statsList) {
    699         if (existing.addStatsIfMatch(stats)) {
    700             return;
    701         }
    702     }
    703     // No match. Insert a new interface pair.
    704     statsList.push_back(stats);
    705 }
    706 
    707 /*
    708  * Parse the ptks and bytes out of:
    709  *   Chain tetherctrl_counters (4 references)
    710  *       pkts      bytes target     prot opt in     out     source               destination
    711  *         26     2373 RETURN     all  --  wlan0  rmnet0  0.0.0.0/0            0.0.0.0/0
    712  *         27     2002 RETURN     all  --  rmnet0 wlan0   0.0.0.0/0            0.0.0.0/0
    713  *       1040   107471 RETURN     all  --  bt-pan rmnet0  0.0.0.0/0            0.0.0.0/0
    714  *       1450  1708806 RETURN     all  --  rmnet0 bt-pan  0.0.0.0/0            0.0.0.0/0
    715  * or:
    716  *   Chain tetherctrl_counters (0 references)
    717  *       pkts      bytes target     prot opt in     out     source               destination
    718  *          0        0 RETURN     all      wlan0  rmnet_data0  ::/0                 ::/0
    719  *          0        0 RETURN     all      rmnet_data0 wlan0   ::/0                 ::/0
    720  *
    721  */
    722 int TetherController::addForwardChainStats(TetherStatsList& statsList,
    723                                            const std::string& statsOutput,
    724                                            std::string &extraProcessingInfo) {
    725     int res;
    726     std::string statsLine;
    727     char iface0[MAX_IPT_OUTPUT_LINE_LEN];
    728     char iface1[MAX_IPT_OUTPUT_LINE_LEN];
    729     char rest[MAX_IPT_OUTPUT_LINE_LEN];
    730 
    731     TetherStats stats;
    732     const TetherStats empty;
    733     const char *buffPtr;
    734     int64_t packets, bytes;
    735 
    736     std::stringstream stream(statsOutput);
    737 
    738     // Skip headers.
    739     for (int i = 0; i < 2; i++) {
    740         std::getline(stream, statsLine, '\n');
    741         extraProcessingInfo += statsLine + "\n";
    742         if (statsLine.empty()) {
    743             ALOGE("Empty header while parsing tethering stats");
    744             return -EREMOTEIO;
    745         }
    746     }
    747 
    748     while (std::getline(stream, statsLine, '\n')) {
    749         buffPtr = statsLine.c_str();
    750 
    751         /* Clean up, so a failed parse can still print info */
    752         iface0[0] = iface1[0] = rest[0] = packets = bytes = 0;
    753         if (strstr(buffPtr, "0.0.0.0")) {
    754             // IPv4 has -- indicating what to do with fragments...
    755             //       26     2373 RETURN     all  --  wlan0  rmnet0  0.0.0.0/0            0.0.0.0/0
    756             res = sscanf(buffPtr, "%" SCNd64" %" SCNd64" RETURN all -- %s %s 0.%s",
    757                     &packets, &bytes, iface0, iface1, rest);
    758         } else {
    759             // ... but IPv6 does not.
    760             //       26     2373 RETURN     all      wlan0  rmnet0  ::/0                 ::/0
    761             res = sscanf(buffPtr, "%" SCNd64" %" SCNd64" RETURN all %s %s ::/%s",
    762                     &packets, &bytes, iface0, iface1, rest);
    763         }
    764         ALOGV("parse res=%d iface0=<%s> iface1=<%s> pkts=%" PRId64" bytes=%" PRId64" rest=<%s> orig line=<%s>", res,
    765              iface0, iface1, packets, bytes, rest, buffPtr);
    766         extraProcessingInfo += buffPtr;
    767         extraProcessingInfo += "\n";
    768 
    769         if (res != 5) {
    770             return -EREMOTEIO;
    771         }
    772         /*
    773          * The following assumes that the 1st rule has in:extIface out:intIface,
    774          * which is what TetherController sets up.
    775          * The 1st matches rx, and sets up the pair for the tx side.
    776          */
    777         if (!stats.intIface[0]) {
    778             ALOGV("0Filter RX iface_in=%s iface_out=%s rx_bytes=%" PRId64" rx_packets=%" PRId64" ", iface0, iface1, bytes, packets);
    779             stats.intIface = iface0;
    780             stats.extIface = iface1;
    781             stats.txPackets = packets;
    782             stats.txBytes = bytes;
    783         } else if (stats.intIface == iface1 && stats.extIface == iface0) {
    784             ALOGV("0Filter TX iface_in=%s iface_out=%s rx_bytes=%" PRId64" rx_packets=%" PRId64" ", iface0, iface1, bytes, packets);
    785             stats.rxPackets = packets;
    786             stats.rxBytes = bytes;
    787         }
    788         if (stats.rxBytes != -1 && stats.txBytes != -1) {
    789             ALOGV("rx_bytes=%" PRId64" tx_bytes=%" PRId64, stats.rxBytes, stats.txBytes);
    790             addStats(statsList, stats);
    791             stats = empty;
    792         }
    793     }
    794 
    795     /* It is always an error to find only one side of the stats. */
    796     if (((stats.rxBytes == -1) != (stats.txBytes == -1))) {
    797         return -EREMOTEIO;
    798     }
    799     return 0;
    800 }
    801 
    802 StatusOr<TetherController::TetherStatsList> TetherController::getTetherStats() {
    803     TetherStatsList statsList;
    804     std::string parsedIptablesOutput;
    805 
    806     for (const IptablesTarget target : {V4, V6}) {
    807         std::string statsString;
    808         if (int ret = iptablesRestoreFunction(target, GET_TETHER_STATS_COMMAND, &statsString)) {
    809             return statusFromErrno(-ret, StringPrintf("failed to fetch tether stats (%d): %d",
    810                                                       target, ret));
    811         }
    812 
    813         if (int ret = addForwardChainStats(statsList, statsString, parsedIptablesOutput)) {
    814             return statusFromErrno(-ret, StringPrintf("failed to parse %s tether stats:\n%s",
    815                                                       target == V4 ? "IPv4": "IPv6",
    816                                                       parsedIptablesOutput.c_str()));
    817         }
    818     }
    819 
    820     return statsList;
    821 }
    822 
    823 }  // namespace net
    824 }  // namespace android
    825