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 // #define LOG_NDEBUG 0
     18 
     19 #include <stdlib.h>
     20 #include <sys/socket.h>
     21 #include <sys/types.h>
     22 #include <netinet/in.h>
     23 #include <arpa/inet.h>
     24 #include <dirent.h>
     25 #include <errno.h>
     26 #include <string.h>
     27 #include <linux/if.h>
     28 #include <resolv_netid.h>
     29 #include <resolv_params.h>
     30 
     31 #define __STDC_FORMAT_MACROS 1
     32 #include <inttypes.h>
     33 
     34 #define LOG_TAG "CommandListener"
     35 
     36 #include <cutils/log.h>
     37 #include <netdutils/Status.h>
     38 #include <netdutils/StatusOr.h>
     39 #include <netutils/ifc.h>
     40 #include <sysutils/SocketClient.h>
     41 
     42 #include "Controllers.h"
     43 #include "CommandListener.h"
     44 #include "ResponseCode.h"
     45 #include "BandwidthController.h"
     46 #include "IdletimerController.h"
     47 #include "InterfaceController.h"
     48 #include "NetdConstants.h"
     49 #include "FirewallController.h"
     50 #include "RouteController.h"
     51 #include "UidRanges.h"
     52 
     53 #include <string>
     54 #include <vector>
     55 
     56 namespace android {
     57 namespace net {
     58 
     59 namespace {
     60 
     61 const unsigned NUM_OEM_IDS = NetworkController::MAX_OEM_ID - NetworkController::MIN_OEM_ID + 1;
     62 
     63 unsigned stringToNetId(const char* arg) {
     64     if (!strcmp(arg, "local")) {
     65         return NetworkController::LOCAL_NET_ID;
     66     }
     67     // OEM NetIds are "oem1", "oem2", .., "oem50".
     68     if (!strncmp(arg, "oem", 3)) {
     69         unsigned n = strtoul(arg + 3, NULL, 0);
     70         if (1 <= n && n <= NUM_OEM_IDS) {
     71             return NetworkController::MIN_OEM_ID + n;
     72         }
     73         return NETID_UNSET;
     74     } else if (!strncmp(arg, "handle", 6)) {
     75         unsigned n = netHandleToNetId((net_handle_t)strtoull(arg + 6, NULL, 10));
     76         if (NetworkController::MIN_OEM_ID <= n && n <= NetworkController::MAX_OEM_ID) {
     77             return n;
     78         }
     79         return NETID_UNSET;
     80     }
     81     // strtoul() returns 0 on errors, which is fine because 0 is an invalid netId.
     82     return strtoul(arg, NULL, 0);
     83 }
     84 
     85 class LockingFrameworkCommand : public FrameworkCommand {
     86 public:
     87     LockingFrameworkCommand(FrameworkCommand *wrappedCmd, android::RWLock& lock) :
     88             FrameworkCommand(wrappedCmd->getCommand()),
     89             mWrappedCmd(wrappedCmd),
     90             mLock(lock) {}
     91 
     92     int runCommand(SocketClient *c, int argc, char **argv) {
     93         android::RWLock::AutoWLock lock(mLock);
     94         return mWrappedCmd->runCommand(c, argc, argv);
     95     }
     96 
     97 private:
     98     FrameworkCommand *mWrappedCmd;
     99     android::RWLock& mLock;
    100 };
    101 
    102 
    103 }  // namespace
    104 
    105 void CommandListener::registerLockingCmd(FrameworkCommand *cmd, android::RWLock& lock) {
    106     registerCmd(new LockingFrameworkCommand(cmd, lock));
    107 }
    108 
    109 CommandListener::CommandListener() : FrameworkListener(SOCKET_NAME, true) {
    110     registerLockingCmd(new InterfaceCmd());
    111     registerLockingCmd(new IpFwdCmd(), gCtls->tetherCtrl.lock);
    112     registerLockingCmd(new TetherCmd(), gCtls->tetherCtrl.lock);
    113     registerLockingCmd(new NatCmd(), gCtls->tetherCtrl.lock);
    114     registerLockingCmd(new ListTtysCmd());
    115     registerLockingCmd(new PppdCmd());
    116     registerLockingCmd(new BandwidthControlCmd(), gCtls->bandwidthCtrl.lock);
    117     registerLockingCmd(new IdletimerControlCmd());
    118     registerLockingCmd(new ResolverCmd());
    119     registerLockingCmd(new FirewallCmd(), gCtls->firewallCtrl.lock);
    120     registerLockingCmd(new ClatdCmd());
    121     registerLockingCmd(new NetworkCommand());
    122     registerLockingCmd(new StrictCmd());
    123 }
    124 
    125 CommandListener::InterfaceCmd::InterfaceCmd() :
    126                  NetdCommand("interface") {
    127 }
    128 
    129 int CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
    130                                                       int argc, char **argv) {
    131     if (argc < 2) {
    132         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    133         return 0;
    134     }
    135 
    136     if (!strcmp(argv[1], "list")) {
    137         const auto ifacePairs =
    138             InterfaceController::getIfaceList();
    139         if (ifacePairs.status() != netdutils::status::ok) {
    140             cli->sendMsg(ResponseCode::OperationFailed, "Failed to get interface list", true);
    141             return 0;
    142         }
    143         for (const auto& ifacePair : ifacePairs.value()) {
    144             cli->sendMsg(ResponseCode::InterfaceListResult, ifacePair.first.c_str(), false);
    145         }
    146 
    147         cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false);
    148         return 0;
    149     } else {
    150         /*
    151          * These commands take a minimum of 3 arguments
    152          */
    153         if (argc < 3) {
    154             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    155             return 0;
    156         }
    157 
    158         if (!strcmp(argv[1], "getcfg")) {
    159             struct in_addr addr;
    160             int prefixLength;
    161             unsigned char hwaddr[6];
    162             unsigned flags = 0;
    163 
    164             ifc_init();
    165             memset(hwaddr, 0, sizeof(hwaddr));
    166 
    167             if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) {
    168                 cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
    169                 ifc_close();
    170                 return 0;
    171             }
    172 
    173             if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) {
    174                 ALOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno));
    175             }
    176 
    177             char *addr_s = strdup(inet_ntoa(addr));
    178             const char *updown, *brdcst, *loopbk, *ppp, *running, *multi;
    179 
    180             updown =  (flags & IFF_UP)           ? "up" : "down";
    181             brdcst =  (flags & IFF_BROADCAST)    ? " broadcast" : "";
    182             loopbk =  (flags & IFF_LOOPBACK)     ? " loopback" : "";
    183             ppp =     (flags & IFF_POINTOPOINT)  ? " point-to-point" : "";
    184             running = (flags & IFF_RUNNING)      ? " running" : "";
    185             multi =   (flags & IFF_MULTICAST)    ? " multicast" : "";
    186 
    187             char *flag_s;
    188 
    189             asprintf(&flag_s, "%s%s%s%s%s%s", updown, brdcst, loopbk, ppp, running, multi);
    190 
    191             char *msg = NULL;
    192             asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %d %s",
    193                      hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5],
    194                      addr_s, prefixLength, flag_s);
    195 
    196             cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false);
    197 
    198             free(addr_s);
    199             free(flag_s);
    200             free(msg);
    201 
    202             ifc_close();
    203             return 0;
    204         } else if (!strcmp(argv[1], "setcfg")) {
    205             // arglist: iface [addr prefixLength] flags
    206             if (argc < 4) {
    207                 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    208                 return 0;
    209             }
    210             ALOGD("Setting iface cfg");
    211 
    212             struct in_addr addr;
    213             int index = 5;
    214 
    215             ifc_init();
    216 
    217             if (!inet_aton(argv[3], &addr)) {
    218                 // Handle flags only case
    219                 index = 3;
    220             } else {
    221                 if (ifc_set_addr(argv[2], 0)) {
    222                     cli->sendMsg(ResponseCode::OperationFailed, "Failed to clear address", true);
    223                     ifc_close();
    224                     return 0;
    225                 }
    226                 if (addr.s_addr != 0) {
    227                     if (ifc_add_address(argv[2], argv[3], atoi(argv[4]))) {
    228                         cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true);
    229                         ifc_close();
    230                         return 0;
    231                     }
    232                 }
    233             }
    234 
    235             /* Process flags */
    236             for (int i = index; i < argc; i++) {
    237                 char *flag = argv[i];
    238                 if (!strcmp(flag, "up")) {
    239                     ALOGD("Trying to bring up %s", argv[2]);
    240                     if (ifc_up(argv[2])) {
    241                         ALOGE("Error upping interface");
    242                         cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true);
    243                         ifc_close();
    244                         return 0;
    245                     }
    246                 } else if (!strcmp(flag, "down")) {
    247                     ALOGD("Trying to bring down %s", argv[2]);
    248                     if (ifc_down(argv[2])) {
    249                         ALOGE("Error downing interface");
    250                         cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true);
    251                         ifc_close();
    252                         return 0;
    253                     }
    254                 } else if (!strcmp(flag, "broadcast")) {
    255                     // currently ignored
    256                 } else if (!strcmp(flag, "multicast")) {
    257                     // currently ignored
    258                 } else if (!strcmp(flag, "running")) {
    259                     // currently ignored
    260                 } else if (!strcmp(flag, "loopback")) {
    261                     // currently ignored
    262                 } else if (!strcmp(flag, "point-to-point")) {
    263                     // currently ignored
    264                 } else {
    265                     cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false);
    266                     ifc_close();
    267                     return 0;
    268                 }
    269             }
    270 
    271             cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false);
    272             ifc_close();
    273             return 0;
    274         } else if (!strcmp(argv[1], "clearaddrs")) {
    275             // arglist: iface
    276             ALOGD("Clearing all IP addresses on %s", argv[2]);
    277 
    278             ifc_clear_addresses(argv[2]);
    279 
    280             cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false);
    281             return 0;
    282         } else if (!strcmp(argv[1], "ipv6privacyextensions")) {
    283             if (argc != 4) {
    284                 cli->sendMsg(ResponseCode::CommandSyntaxError,
    285                         "Usage: interface ipv6privacyextensions <interface> <enable|disable>",
    286                         false);
    287                 return 0;
    288             }
    289             int enable = !strncmp(argv[3], "enable", 7);
    290             if (InterfaceController::setIPv6PrivacyExtensions(argv[2], enable) == 0) {
    291                 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false);
    292             } else {
    293                 cli->sendMsg(ResponseCode::OperationFailed,
    294                         "Failed to set ipv6 privacy extensions", true);
    295             }
    296             return 0;
    297         } else if (!strcmp(argv[1], "ipv6")) {
    298             if (argc != 4) {
    299                 cli->sendMsg(ResponseCode::CommandSyntaxError,
    300                         "Usage: interface ipv6 <interface> <enable|disable>",
    301                         false);
    302                 return 0;
    303             }
    304 
    305             int enable = !strncmp(argv[3], "enable", 7);
    306             if (InterfaceController::setEnableIPv6(argv[2], enable) == 0) {
    307                 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false);
    308             } else {
    309                 cli->sendMsg(ResponseCode::OperationFailed,
    310                         "Failed to change IPv6 state", true);
    311             }
    312             return 0;
    313         } else if (!strcmp(argv[1], "setmtu")) {
    314             if (argc != 4) {
    315                 cli->sendMsg(ResponseCode::CommandSyntaxError,
    316                         "Usage: interface setmtu <interface> <val>", false);
    317                 return 0;
    318             }
    319             if (InterfaceController::setMtu(argv[2], argv[3]) == 0) {
    320                 cli->sendMsg(ResponseCode::CommandOkay, "MTU changed", false);
    321             } else {
    322                 cli->sendMsg(ResponseCode::OperationFailed,
    323                         "Failed to set MTU", true);
    324             }
    325             return 0;
    326         } else {
    327             cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
    328             return 0;
    329         }
    330     }
    331     return 0;
    332 }
    333 
    334 
    335 CommandListener::ListTtysCmd::ListTtysCmd() :
    336                  NetdCommand("list_ttys") {
    337 }
    338 
    339 int CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
    340                                              int /* argc */, char ** /* argv */) {
    341     TtyCollection *tlist = gCtls->pppCtrl.getTtyList();
    342     TtyCollection::iterator it;
    343 
    344     for (it = tlist->begin(); it != tlist->end(); ++it) {
    345         cli->sendMsg(ResponseCode::TtyListResult, *it, false);
    346     }
    347 
    348     cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
    349     return 0;
    350 }
    351 
    352 CommandListener::IpFwdCmd::IpFwdCmd() :
    353                  NetdCommand("ipfwd") {
    354 }
    355 
    356 int CommandListener::IpFwdCmd::runCommand(SocketClient *cli, int argc, char **argv) {
    357     bool matched = false;
    358     bool success;
    359 
    360     if (argc == 2) {
    361         //   0     1
    362         // ipfwd status
    363         if (!strcmp(argv[1], "status")) {
    364             char *tmp = NULL;
    365 
    366             asprintf(&tmp, "Forwarding %s",
    367                      ((gCtls->tetherCtrl.forwardingRequestCount() > 0) ? "enabled" : "disabled"));
    368             cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
    369             free(tmp);
    370             return 0;
    371         }
    372     } else if (argc == 3) {
    373         //  0      1         2
    374         // ipfwd enable  <requester>
    375         // ipfwd disable <requester>
    376         if (!strcmp(argv[1], "enable")) {
    377             matched = true;
    378             success = gCtls->tetherCtrl.enableForwarding(argv[2]);
    379         } else if (!strcmp(argv[1], "disable")) {
    380             matched = true;
    381             success = gCtls->tetherCtrl.disableForwarding(argv[2]);
    382         }
    383     } else if (argc == 4) {
    384         //  0      1      2     3
    385         // ipfwd  add   wlan0 dummy0
    386         // ipfwd remove wlan0 dummy0
    387         int ret = 0;
    388         if (!strcmp(argv[1], "add")) {
    389             matched = true;
    390             ret = RouteController::enableTethering(argv[2], argv[3]);
    391         } else if (!strcmp(argv[1], "remove")) {
    392             matched = true;
    393             ret = RouteController::disableTethering(argv[2], argv[3]);
    394         }
    395         success = (ret == 0);
    396         errno = -ret;
    397     }
    398 
    399     if (!matched) {
    400         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
    401         return 0;
    402     }
    403 
    404     if (success) {
    405         cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
    406     } else {
    407         cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
    408     }
    409     return 0;
    410 }
    411 
    412 CommandListener::TetherCmd::TetherCmd() :
    413                  NetdCommand("tether") {
    414 }
    415 
    416 int CommandListener::TetherCmd::runCommand(SocketClient *cli,
    417                                                       int argc, char **argv) {
    418     int rc = 0;
    419 
    420     if (argc < 2) {
    421         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    422         return 0;
    423     }
    424 
    425     if (!strcmp(argv[1], "stop")) {
    426         rc = gCtls->tetherCtrl.stopTethering();
    427     } else if (!strcmp(argv[1], "status")) {
    428         char *tmp = NULL;
    429 
    430         asprintf(&tmp, "Tethering services %s",
    431                  (gCtls->tetherCtrl.isTetheringStarted() ? "started" : "stopped"));
    432         cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
    433         free(tmp);
    434         return 0;
    435     } else if (argc == 3) {
    436         if (!strcmp(argv[1], "interface") && !strcmp(argv[2], "list")) {
    437             for (const auto &ifname : gCtls->tetherCtrl.getTetheredInterfaceList()) {
    438                 cli->sendMsg(ResponseCode::TetherInterfaceListResult, ifname.c_str(), false);
    439             }
    440         } else if (!strcmp(argv[1], "dns") && !strcmp(argv[2], "list")) {
    441             char netIdStr[UINT32_STRLEN];
    442             snprintf(netIdStr, sizeof(netIdStr), "%u", gCtls->tetherCtrl.getDnsNetId());
    443             cli->sendMsg(ResponseCode::TetherDnsFwdNetIdResult, netIdStr, false);
    444 
    445             for (const auto &fwdr : gCtls->tetherCtrl.getDnsForwarders()) {
    446                 cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, fwdr.c_str(), false);
    447             }
    448         }
    449     } else {
    450         /*
    451          * These commands take a minimum of 4 arguments
    452          */
    453         if (argc < 4) {
    454             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    455             return 0;
    456         }
    457 
    458         if (!strcmp(argv[1], "start")) {
    459             if (argc % 2 == 1) {
    460                 cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false);
    461                 return 0;
    462             }
    463 
    464             const int num_addrs = argc - 2;
    465             // TODO: consider moving this validation into TetherController.
    466             struct in_addr tmp_addr;
    467             for (int arg_index = 2; arg_index < argc; arg_index++) {
    468                 if (!inet_aton(argv[arg_index], &tmp_addr)) {
    469                     cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
    470                     return 0;
    471                 }
    472             }
    473 
    474             rc = gCtls->tetherCtrl.startTethering(num_addrs, &(argv[2]));
    475         } else if (!strcmp(argv[1], "interface")) {
    476             if (!strcmp(argv[2], "add")) {
    477                 rc = gCtls->tetherCtrl.tetherInterface(argv[3]);
    478             } else if (!strcmp(argv[2], "remove")) {
    479                 rc = gCtls->tetherCtrl.untetherInterface(argv[3]);
    480             /* else if (!strcmp(argv[2], "list")) handled above */
    481             } else {
    482                 cli->sendMsg(ResponseCode::CommandParameterError,
    483                              "Unknown tether interface operation", false);
    484                 return 0;
    485             }
    486         } else if (!strcmp(argv[1], "dns")) {
    487             if (!strcmp(argv[2], "set")) {
    488                 if (argc < 5) {
    489                     cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    490                     return 0;
    491                 }
    492                 unsigned netId = stringToNetId(argv[3]);
    493                 rc = gCtls->tetherCtrl.setDnsForwarders(netId, &argv[4], argc - 4);
    494             /* else if (!strcmp(argv[2], "list")) handled above */
    495             } else {
    496                 cli->sendMsg(ResponseCode::CommandParameterError,
    497                              "Unknown tether interface operation", false);
    498                 return 0;
    499             }
    500         } else {
    501             cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
    502             return 0;
    503         }
    504     }
    505 
    506     if (!rc) {
    507         cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
    508     } else {
    509         cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
    510     }
    511 
    512     return 0;
    513 }
    514 
    515 CommandListener::NatCmd::NatCmd() :
    516                  NetdCommand("nat") {
    517 }
    518 
    519 int CommandListener::NatCmd::runCommand(SocketClient *cli,
    520                                                       int argc, char **argv) {
    521     int rc = 0;
    522 
    523     if (argc < 5) {
    524         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    525         return 0;
    526     }
    527 
    528     //  0     1       2        3
    529     // nat  enable intiface extiface
    530     // nat disable intiface extiface
    531     if (!strcmp(argv[1], "enable") && argc >= 4) {
    532         rc = gCtls->tetherCtrl.enableNat(argv[2], argv[3]);
    533         if(!rc) {
    534             /* Ignore ifaces for now. */
    535             rc = gCtls->bandwidthCtrl.setGlobalAlertInForwardChain();
    536         }
    537     } else if (!strcmp(argv[1], "disable") && argc >= 4) {
    538         /* Ignore ifaces for now. */
    539         rc = gCtls->bandwidthCtrl.removeGlobalAlertInForwardChain();
    540         rc |= gCtls->tetherCtrl.disableNat(argv[2], argv[3]);
    541     } else {
    542         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
    543         return 0;
    544     }
    545 
    546     if (!rc) {
    547         cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
    548     } else {
    549         cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
    550     }
    551 
    552     return 0;
    553 }
    554 
    555 CommandListener::PppdCmd::PppdCmd() :
    556                  NetdCommand("pppd") {
    557 }
    558 
    559 int CommandListener::PppdCmd::runCommand(SocketClient *cli,
    560                                                       int argc, char **argv) {
    561     int rc = 0;
    562 
    563     if (argc < 3) {
    564         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    565         return 0;
    566     }
    567 
    568     if (!strcmp(argv[1], "attach")) {
    569         struct in_addr l, r, dns1, dns2;
    570 
    571         memset(&dns1, 0, sizeof(struct in_addr));
    572         memset(&dns2, 0, sizeof(struct in_addr));
    573 
    574         if (!inet_aton(argv[3], &l)) {
    575             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false);
    576             return 0;
    577         }
    578         if (!inet_aton(argv[4], &r)) {
    579             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false);
    580             return 0;
    581         }
    582         if ((argc > 3) && (!inet_aton(argv[5], &dns1))) {
    583             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false);
    584             return 0;
    585         }
    586         if ((argc > 4) && (!inet_aton(argv[6], &dns2))) {
    587             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false);
    588             return 0;
    589         }
    590         rc = gCtls->pppCtrl.attachPppd(argv[2], l, r, dns1, dns2);
    591     } else if (!strcmp(argv[1], "detach")) {
    592         rc = gCtls->pppCtrl.detachPppd(argv[2]);
    593     } else {
    594         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false);
    595         return 0;
    596     }
    597 
    598     if (!rc) {
    599         cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false);
    600     } else {
    601         cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true);
    602     }
    603 
    604     return 0;
    605 }
    606 
    607 CommandListener::ResolverCmd::ResolverCmd() :
    608         NetdCommand("resolver") {
    609 }
    610 
    611 int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **margv) {
    612     int rc = 0;
    613     const char **argv = const_cast<const char **>(margv);
    614 
    615     if (argc < 3) {
    616         cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false);
    617         return 0;
    618     }
    619 
    620     unsigned netId = stringToNetId(argv[2]);
    621     // TODO: Consider making NetworkController.isValidNetwork() public
    622     // and making that check here.
    623 
    624     if (!strcmp(argv[1], "setnetdns")) {
    625         if (!parseAndExecuteSetNetDns(netId, argc, argv)) {
    626             cli->sendMsg(ResponseCode::CommandSyntaxError,
    627                     "Wrong number of or invalid arguments to resolver setnetdns", false);
    628             return 0;
    629         }
    630     } else if (!strcmp(argv[1], "clearnetdns")) { // "resolver clearnetdns <netId>"
    631         if (argc == 3) {
    632             rc = gCtls->resolverCtrl.clearDnsServers(netId);
    633         } else {
    634             cli->sendMsg(ResponseCode::CommandSyntaxError,
    635                     "Wrong number of arguments to resolver clearnetdns", false);
    636             return 0;
    637         }
    638     } else {
    639         cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false);
    640         return 0;
    641     }
    642 
    643     if (!rc) {
    644         cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false);
    645     } else {
    646         cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true);
    647     }
    648 
    649     return 0;
    650 }
    651 
    652 bool CommandListener::ResolverCmd::parseAndExecuteSetNetDns(int netId, int argc,
    653         const char** argv) {
    654     // "resolver setnetdns <netId> <domains> <dns1> [<dns2> ...] [--params <params>]"
    655     // TODO: This code has to be replaced by a Binder call ASAP
    656     if (argc < 5) {
    657         return false;
    658     }
    659     int end = argc;
    660     __res_params params;
    661     const __res_params* paramsPtr = nullptr;
    662     if (end > 6 && !strcmp(argv[end - 2], "--params")) {
    663         const char* paramsStr = argv[end - 1];
    664         end -= 2;
    665         if (sscanf(paramsStr, "%hu %hhu %hhu %hhu", &params.sample_validity,
    666                 &params.success_threshold, &params.min_samples, &params.max_samples) != 4) {
    667             return false;
    668         }
    669         paramsPtr = &params;
    670     }
    671     return gCtls->resolverCtrl.setDnsServers(netId, argv[3], &argv[4], end - 4, paramsPtr) == 0;
    672 }
    673 
    674 CommandListener::BandwidthControlCmd::BandwidthControlCmd() :
    675     NetdCommand("bandwidth") {
    676 }
    677 
    678 void CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) {
    679     char *msg;
    680     asprintf(&msg, "Usage: bandwidth %s", usageMsg);
    681     cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false);
    682     free(msg);
    683 }
    684 
    685 void CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) {
    686     if (!cond) {
    687         cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
    688     } else {
    689         cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false);
    690     }
    691 }
    692 
    693 void CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) {
    694     cli->sendMsg(ResponseCode::OperationFailed, errMsg, false);
    695 }
    696 
    697 int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
    698     if (argc < 2) {
    699         sendGenericSyntaxError(cli, "<cmds> <args...>");
    700         return 0;
    701     }
    702 
    703     ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
    704 
    705     if (!strcmp(argv[1], "enable")) {
    706         int rc = gCtls->bandwidthCtrl.enableBandwidthControl(true);
    707         sendGenericOkFail(cli, rc);
    708         return 0;
    709 
    710     }
    711     if (!strcmp(argv[1], "disable")) {
    712         int rc = gCtls->bandwidthCtrl.disableBandwidthControl();
    713         sendGenericOkFail(cli, rc);
    714         return 0;
    715 
    716     }
    717     if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
    718         if (argc != 3) {
    719             sendGenericSyntaxError(cli, "removequota <interface>");
    720             return 0;
    721         }
    722         int rc = gCtls->bandwidthCtrl.removeInterfaceSharedQuota(argv[2]);
    723         sendGenericOkFail(cli, rc);
    724         return 0;
    725 
    726     }
    727     if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) {
    728         int64_t bytes;
    729         if (argc != 2) {
    730             sendGenericSyntaxError(cli, "getquota");
    731             return 0;
    732         }
    733         int rc = gCtls->bandwidthCtrl.getInterfaceSharedQuota(&bytes);
    734         if (rc) {
    735             sendGenericOpFailed(cli, "Failed to get quota");
    736             return 0;
    737         }
    738 
    739         char *msg;
    740         asprintf(&msg, "%" PRId64, bytes);
    741         cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
    742         free(msg);
    743         return 0;
    744 
    745     }
    746     if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) {
    747         int64_t bytes;
    748         if (argc != 3) {
    749             sendGenericSyntaxError(cli, "getiquota <iface>");
    750             return 0;
    751         }
    752 
    753         int rc = gCtls->bandwidthCtrl.getInterfaceQuota(argv[2], &bytes);
    754         if (rc) {
    755             sendGenericOpFailed(cli, "Failed to get quota");
    756             return 0;
    757         }
    758         char *msg;
    759         asprintf(&msg, "%" PRId64, bytes);
    760         cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
    761         free(msg);
    762         return 0;
    763 
    764     }
    765     if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
    766         if (argc != 4) {
    767             sendGenericSyntaxError(cli, "setquota <interface> <bytes>");
    768             return 0;
    769         }
    770         int rc = gCtls->bandwidthCtrl.setInterfaceSharedQuota(argv[2], atoll(argv[3]));
    771         sendGenericOkFail(cli, rc);
    772         return 0;
    773     }
    774     if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
    775         int rc;
    776         if (argc < 4) {
    777             sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ...");
    778             return 0;
    779         }
    780 
    781         for (int q = 3; argc >= 4; q++, argc--) {
    782             rc = gCtls->bandwidthCtrl.setInterfaceSharedQuota(argv[q], atoll(argv[2]));
    783             if (rc) {
    784                 char *msg;
    785                 asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]);
    786                 cli->sendMsg(ResponseCode::OperationFailed,
    787                              msg, false);
    788                 free(msg);
    789                 return 0;
    790             }
    791         }
    792         sendGenericOkFail(cli, rc);
    793         return 0;
    794 
    795     }
    796     if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) {
    797         int rc;
    798         if (argc < 3) {
    799             sendGenericSyntaxError(cli, "removequotas <interface> ...");
    800             return 0;
    801         }
    802 
    803         for (int q = 2; argc >= 3; q++, argc--) {
    804             rc = gCtls->bandwidthCtrl.removeInterfaceSharedQuota(argv[q]);
    805             if (rc) {
    806                 char *msg;
    807                 asprintf(&msg, "bandwidth removequotas %s failed", argv[q]);
    808                 cli->sendMsg(ResponseCode::OperationFailed,
    809                              msg, false);
    810                 free(msg);
    811                 return 0;
    812             }
    813         }
    814         sendGenericOkFail(cli, rc);
    815         return 0;
    816 
    817     }
    818     if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
    819         if (argc != 3) {
    820             sendGenericSyntaxError(cli, "removeiquota <interface>");
    821             return 0;
    822         }
    823         int rc = gCtls->bandwidthCtrl.removeInterfaceQuota(argv[2]);
    824         sendGenericOkFail(cli, rc);
    825         return 0;
    826 
    827     }
    828     if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
    829         if (argc != 4) {
    830             sendGenericSyntaxError(cli, "setiquota <interface> <bytes>");
    831             return 0;
    832         }
    833         int rc = gCtls->bandwidthCtrl.setInterfaceQuota(argv[2], atoll(argv[3]));
    834         sendGenericOkFail(cli, rc);
    835         return 0;
    836 
    837     }
    838     if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
    839         if (argc < 3) {
    840             sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ...");
    841             return 0;
    842         }
    843         int rc = gCtls->bandwidthCtrl.addNaughtyApps(argc - 2, argv + 2);
    844         sendGenericOkFail(cli, rc);
    845         return 0;
    846 
    847 
    848     }
    849     if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
    850         if (argc < 3) {
    851             sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ...");
    852             return 0;
    853         }
    854         int rc = gCtls->bandwidthCtrl.removeNaughtyApps(argc - 2, argv + 2);
    855         sendGenericOkFail(cli, rc);
    856         return 0;
    857     }
    858     if (!strcmp(argv[1], "addniceapps") || !strcmp(argv[1], "aha")) {
    859         if (argc < 3) {
    860             sendGenericSyntaxError(cli, "addniceapps <appUid> ...");
    861             return 0;
    862         }
    863         int rc = gCtls->bandwidthCtrl.addNiceApps(argc - 2, argv + 2);
    864         sendGenericOkFail(cli, rc);
    865         return 0;
    866     }
    867     if (!strcmp(argv[1], "removeniceapps") || !strcmp(argv[1], "rha")) {
    868         if (argc < 3) {
    869             sendGenericSyntaxError(cli, "removeniceapps <appUid> ...");
    870             return 0;
    871         }
    872         int rc = gCtls->bandwidthCtrl.removeNiceApps(argc - 2, argv + 2);
    873         sendGenericOkFail(cli, rc);
    874         return 0;
    875     }
    876     if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) {
    877         if (argc != 3) {
    878             sendGenericSyntaxError(cli, "setglobalalert <bytes>");
    879             return 0;
    880         }
    881         int rc = gCtls->bandwidthCtrl.setGlobalAlert(atoll(argv[2]));
    882         sendGenericOkFail(cli, rc);
    883         return 0;
    884     }
    885     if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) {
    886         if (argc != 4) {
    887             sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>");
    888             return 0;
    889         }
    890         /* We ignore the interfaces for now. */
    891         int rc = gCtls->bandwidthCtrl.setGlobalAlertInForwardChain();
    892         sendGenericOkFail(cli, rc);
    893         return 0;
    894 
    895     }
    896     if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
    897         if (argc != 2) {
    898             sendGenericSyntaxError(cli, "removeglobalalert");
    899             return 0;
    900         }
    901         int rc = gCtls->bandwidthCtrl.removeGlobalAlert();
    902         sendGenericOkFail(cli, rc);
    903         return 0;
    904 
    905     }
    906     if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) {
    907         if (argc != 4) {
    908             sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>");
    909             return 0;
    910         }
    911         /* We ignore the interfaces for now. */
    912         int rc = gCtls->bandwidthCtrl.removeGlobalAlertInForwardChain();
    913         sendGenericOkFail(cli, rc);
    914         return 0;
    915 
    916     }
    917     if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
    918         if (argc != 3) {
    919             sendGenericSyntaxError(cli, "setsharedalert <bytes>");
    920             return 0;
    921         }
    922         int rc = gCtls->bandwidthCtrl.setSharedAlert(atoll(argv[2]));
    923         sendGenericOkFail(cli, rc);
    924         return 0;
    925 
    926     }
    927     if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) {
    928         if (argc != 2) {
    929             sendGenericSyntaxError(cli, "removesharedalert");
    930             return 0;
    931         }
    932         int rc = gCtls->bandwidthCtrl.removeSharedAlert();
    933         sendGenericOkFail(cli, rc);
    934         return 0;
    935 
    936     }
    937     if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) {
    938         if (argc != 4) {
    939             sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>");
    940             return 0;
    941         }
    942         int rc = gCtls->bandwidthCtrl.setInterfaceAlert(argv[2], atoll(argv[3]));
    943         sendGenericOkFail(cli, rc);
    944         return 0;
    945 
    946     }
    947     if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) {
    948         if (argc != 3) {
    949             sendGenericSyntaxError(cli, "removeinterfacealert <interface>");
    950             return 0;
    951         }
    952         int rc = gCtls->bandwidthCtrl.removeInterfaceAlert(argv[2]);
    953         sendGenericOkFail(cli, rc);
    954         return 0;
    955 
    956     }
    957 
    958     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
    959     return 0;
    960 }
    961 
    962 CommandListener::IdletimerControlCmd::IdletimerControlCmd() :
    963     NetdCommand("idletimer") {
    964 }
    965 
    966 int CommandListener::IdletimerControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
    967   // TODO(ashish): Change the error statements
    968     if (argc < 2) {
    969         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    970         return 0;
    971     }
    972 
    973     ALOGV("idletimerctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
    974 
    975     if (!strcmp(argv[1], "enable")) {
    976       if (0 != gCtls->idletimerCtrl.enableIdletimerControl()) {
    977         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    978       } else {
    979         cli->sendMsg(ResponseCode::CommandOkay, "Enable success", false);
    980       }
    981       return 0;
    982 
    983     }
    984     if (!strcmp(argv[1], "disable")) {
    985       if (0 != gCtls->idletimerCtrl.disableIdletimerControl()) {
    986         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    987       } else {
    988         cli->sendMsg(ResponseCode::CommandOkay, "Disable success", false);
    989       }
    990       return 0;
    991     }
    992     if (!strcmp(argv[1], "add")) {
    993         if (argc != 5) {
    994             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    995             return 0;
    996         }
    997         if(0 != gCtls->idletimerCtrl.addInterfaceIdletimer(
    998                                         argv[2], atoi(argv[3]), argv[4])) {
    999           cli->sendMsg(ResponseCode::OperationFailed, "Failed to add interface", false);
   1000         } else {
   1001           cli->sendMsg(ResponseCode::CommandOkay,  "Add success", false);
   1002         }
   1003         return 0;
   1004     }
   1005     if (!strcmp(argv[1], "remove")) {
   1006         if (argc != 5) {
   1007             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
   1008             return 0;
   1009         }
   1010         // ashish: fixme timeout
   1011         if (0 != gCtls->idletimerCtrl.removeInterfaceIdletimer(
   1012                                         argv[2], atoi(argv[3]), argv[4])) {
   1013           cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove interface", false);
   1014         } else {
   1015           cli->sendMsg(ResponseCode::CommandOkay, "Remove success", false);
   1016         }
   1017         return 0;
   1018     }
   1019 
   1020     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown idletimer cmd", false);
   1021     return 0;
   1022 }
   1023 
   1024 CommandListener::FirewallCmd::FirewallCmd() :
   1025     NetdCommand("firewall") {
   1026 }
   1027 
   1028 int CommandListener::FirewallCmd::sendGenericOkFail(SocketClient *cli, int cond) {
   1029     if (!cond) {
   1030         cli->sendMsg(ResponseCode::CommandOkay, "Firewall command succeeded", false);
   1031     } else {
   1032         cli->sendMsg(ResponseCode::OperationFailed, "Firewall command failed", false);
   1033     }
   1034     return 0;
   1035 }
   1036 
   1037 FirewallRule CommandListener::FirewallCmd::parseRule(const char* arg) {
   1038     if (!strcmp(arg, "allow")) {
   1039         return ALLOW;
   1040     } else if (!strcmp(arg, "deny")) {
   1041         return DENY;
   1042     } else {
   1043         ALOGE("failed to parse uid rule (%s)", arg);
   1044         return ALLOW;
   1045     }
   1046 }
   1047 
   1048 FirewallType CommandListener::FirewallCmd::parseFirewallType(const char* arg) {
   1049     if (!strcmp(arg, "whitelist")) {
   1050         return WHITELIST;
   1051     } else if (!strcmp(arg, "blacklist")) {
   1052         return BLACKLIST;
   1053     } else {
   1054         ALOGE("failed to parse firewall type (%s)", arg);
   1055         return BLACKLIST;
   1056     }
   1057 }
   1058 
   1059 ChildChain CommandListener::FirewallCmd::parseChildChain(const char* arg) {
   1060     if (!strcmp(arg, "dozable")) {
   1061         return DOZABLE;
   1062     } else if (!strcmp(arg, "standby")) {
   1063         return STANDBY;
   1064     } else if (!strcmp(arg, "powersave")) {
   1065         return POWERSAVE;
   1066     } else if (!strcmp(arg, "none")) {
   1067         return NONE;
   1068     } else {
   1069         ALOGE("failed to parse child firewall chain (%s)", arg);
   1070         return INVALID_CHAIN;
   1071     }
   1072 }
   1073 
   1074 int CommandListener::FirewallCmd::runCommand(SocketClient *cli, int argc,
   1075         char **argv) {
   1076     if (argc < 2) {
   1077         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
   1078         return 0;
   1079     }
   1080 
   1081     if (!strcmp(argv[1], "enable")) {
   1082         if (argc != 3) {
   1083             cli->sendMsg(ResponseCode::CommandSyntaxError,
   1084                         "Usage: firewall enable <whitelist|blacklist>", false);
   1085             return 0;
   1086         }
   1087         FirewallType firewallType = parseFirewallType(argv[2]);
   1088 
   1089         int res = gCtls->firewallCtrl.enableFirewall(firewallType);
   1090         return sendGenericOkFail(cli, res);
   1091     }
   1092     if (!strcmp(argv[1], "disable")) {
   1093         int res = gCtls->firewallCtrl.disableFirewall();
   1094         return sendGenericOkFail(cli, res);
   1095     }
   1096     if (!strcmp(argv[1], "is_enabled")) {
   1097         int res = gCtls->firewallCtrl.isFirewallEnabled();
   1098         return sendGenericOkFail(cli, res);
   1099     }
   1100 
   1101     if (!strcmp(argv[1], "set_interface_rule")) {
   1102         if (argc != 4) {
   1103             cli->sendMsg(ResponseCode::CommandSyntaxError,
   1104                          "Usage: firewall set_interface_rule <rmnet0> <allow|deny>", false);
   1105             return 0;
   1106         }
   1107 
   1108         const char* iface = argv[2];
   1109         FirewallRule rule = parseRule(argv[3]);
   1110 
   1111         int res = gCtls->firewallCtrl.setInterfaceRule(iface, rule);
   1112         return sendGenericOkFail(cli, res);
   1113     }
   1114 
   1115     if (!strcmp(argv[1], "set_uid_rule")) {
   1116         if (argc != 5) {
   1117             cli->sendMsg(ResponseCode::CommandSyntaxError,
   1118                          "Usage: firewall set_uid_rule <dozable|standby|none> <1000> <allow|deny>",
   1119                          false);
   1120             return 0;
   1121         }
   1122 
   1123         ChildChain childChain = parseChildChain(argv[2]);
   1124         if (childChain == INVALID_CHAIN) {
   1125             cli->sendMsg(ResponseCode::CommandSyntaxError,
   1126                          "Invalid chain name. Valid names are: <dozable|standby|none>",
   1127                          false);
   1128             return 0;
   1129         }
   1130         int uid = atoi(argv[3]);
   1131         FirewallRule rule = parseRule(argv[4]);
   1132         int res = gCtls->firewallCtrl.setUidRule(childChain, uid, rule);
   1133         return sendGenericOkFail(cli, res);
   1134     }
   1135 
   1136     if (!strcmp(argv[1], "enable_chain")) {
   1137         if (argc != 3) {
   1138             cli->sendMsg(ResponseCode::CommandSyntaxError,
   1139                          "Usage: firewall enable_chain <dozable|standby>",
   1140                          false);
   1141             return 0;
   1142         }
   1143 
   1144         ChildChain childChain = parseChildChain(argv[2]);
   1145         int res = gCtls->firewallCtrl.enableChildChains(childChain, true);
   1146         return sendGenericOkFail(cli, res);
   1147     }
   1148 
   1149     if (!strcmp(argv[1], "disable_chain")) {
   1150         if (argc != 3) {
   1151             cli->sendMsg(ResponseCode::CommandSyntaxError,
   1152                          "Usage: firewall disable_chain <dozable|standby>",
   1153                          false);
   1154             return 0;
   1155         }
   1156 
   1157         ChildChain childChain = parseChildChain(argv[2]);
   1158         int res = gCtls->firewallCtrl.enableChildChains(childChain, false);
   1159         return sendGenericOkFail(cli, res);
   1160     }
   1161 
   1162     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
   1163     return 0;
   1164 }
   1165 
   1166 CommandListener::ClatdCmd::ClatdCmd() : NetdCommand("clatd") {
   1167 }
   1168 
   1169 int CommandListener::ClatdCmd::runCommand(SocketClient *cli, int argc,
   1170                                                             char **argv) {
   1171     int rc = 0;
   1172     if (argc < 3) {
   1173         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
   1174         return 0;
   1175     }
   1176 
   1177     if (!strcmp(argv[1], "stop")) {
   1178         rc = gCtls->clatdCtrl.stopClatd(argv[2]);
   1179     } else if (!strcmp(argv[1], "status")) {
   1180         char *tmp = NULL;
   1181         asprintf(&tmp, "Clatd status: %s", (gCtls->clatdCtrl.isClatdStarted(argv[2]) ?
   1182                                             "started" : "stopped"));
   1183         cli->sendMsg(ResponseCode::ClatdStatusResult, tmp, false);
   1184         free(tmp);
   1185         return 0;
   1186     } else if (!strcmp(argv[1], "start")) {
   1187         rc = gCtls->clatdCtrl.startClatd(argv[2]);
   1188     } else {
   1189         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown clatd cmd", false);
   1190         return 0;
   1191     }
   1192 
   1193     if (!rc) {
   1194         cli->sendMsg(ResponseCode::CommandOkay, "Clatd operation succeeded", false);
   1195     } else {
   1196         cli->sendMsg(ResponseCode::OperationFailed, "Clatd operation failed", false);
   1197     }
   1198 
   1199     return 0;
   1200 }
   1201 
   1202 CommandListener::StrictCmd::StrictCmd() :
   1203     NetdCommand("strict") {
   1204 }
   1205 
   1206 int CommandListener::StrictCmd::sendGenericOkFail(SocketClient *cli, int cond) {
   1207     if (!cond) {
   1208         cli->sendMsg(ResponseCode::CommandOkay, "Strict command succeeded", false);
   1209     } else {
   1210         cli->sendMsg(ResponseCode::OperationFailed, "Strict command failed", false);
   1211     }
   1212     return 0;
   1213 }
   1214 
   1215 StrictPenalty CommandListener::StrictCmd::parsePenalty(const char* arg) {
   1216     if (!strcmp(arg, "reject")) {
   1217         return REJECT;
   1218     } else if (!strcmp(arg, "log")) {
   1219         return LOG;
   1220     } else if (!strcmp(arg, "accept")) {
   1221         return ACCEPT;
   1222     } else {
   1223         return INVALID;
   1224     }
   1225 }
   1226 
   1227 int CommandListener::StrictCmd::runCommand(SocketClient *cli, int argc,
   1228         char **argv) {
   1229     if (argc < 2) {
   1230         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
   1231         return 0;
   1232     }
   1233 
   1234     if (!strcmp(argv[1], "enable")) {
   1235         int res = gCtls->strictCtrl.enableStrict();
   1236         return sendGenericOkFail(cli, res);
   1237     }
   1238     if (!strcmp(argv[1], "disable")) {
   1239         int res = gCtls->strictCtrl.disableStrict();
   1240         return sendGenericOkFail(cli, res);
   1241     }
   1242 
   1243     if (!strcmp(argv[1], "set_uid_cleartext_policy")) {
   1244         if (argc != 4) {
   1245             cli->sendMsg(ResponseCode::CommandSyntaxError,
   1246                          "Usage: strict set_uid_cleartext_policy <uid> <accept|log|reject>",
   1247                          false);
   1248             return 0;
   1249         }
   1250 
   1251         errno = 0;
   1252         unsigned long int uid = strtoul(argv[2], NULL, 0);
   1253         if (errno || uid > UID_MAX) {
   1254             cli->sendMsg(ResponseCode::CommandSyntaxError, "Invalid UID", false);
   1255             return 0;
   1256         }
   1257 
   1258         StrictPenalty penalty = parsePenalty(argv[3]);
   1259         if (penalty == INVALID) {
   1260             cli->sendMsg(ResponseCode::CommandSyntaxError, "Invalid penalty argument", false);
   1261             return 0;
   1262         }
   1263 
   1264         int res = gCtls->strictCtrl.setUidCleartextPenalty((uid_t) uid, penalty);
   1265         return sendGenericOkFail(cli, res);
   1266     }
   1267 
   1268     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
   1269     return 0;
   1270 }
   1271 
   1272 CommandListener::NetworkCommand::NetworkCommand() : NetdCommand("network") {
   1273 }
   1274 
   1275 int CommandListener::NetworkCommand::syntaxError(SocketClient* client, const char* message) {
   1276     client->sendMsg(ResponseCode::CommandSyntaxError, message, false);
   1277     return 0;
   1278 }
   1279 
   1280 int CommandListener::NetworkCommand::operationError(SocketClient* client, const char* message,
   1281                                                     int ret) {
   1282     errno = -ret;
   1283     client->sendMsg(ResponseCode::OperationFailed, message, true);
   1284     return 0;
   1285 }
   1286 
   1287 int CommandListener::NetworkCommand::success(SocketClient* client) {
   1288     client->sendMsg(ResponseCode::CommandOkay, "success", false);
   1289     return 0;
   1290 }
   1291 
   1292 int CommandListener::NetworkCommand::runCommand(SocketClient* client, int argc, char** argv) {
   1293     if (argc < 2) {
   1294         return syntaxError(client, "Missing argument");
   1295     }
   1296 
   1297     //    0      1      2      3      4       5         6            7           8
   1298     // network route [legacy <uid>]  add   <netId> <interface> <destination> [nexthop]
   1299     // network route [legacy <uid>] remove <netId> <interface> <destination> [nexthop]
   1300     //
   1301     // nexthop may be either an IPv4/IPv6 address or one of "unreachable" or "throw".
   1302     if (!strcmp(argv[1], "route")) {
   1303         if (argc < 6 || argc > 9) {
   1304             return syntaxError(client, "Incorrect number of arguments");
   1305         }
   1306 
   1307         int nextArg = 2;
   1308         bool legacy = false;
   1309         uid_t uid = 0;
   1310         if (!strcmp(argv[nextArg], "legacy")) {
   1311             ++nextArg;
   1312             legacy = true;
   1313             uid = strtoul(argv[nextArg++], NULL, 0);
   1314         }
   1315 
   1316         bool add = false;
   1317         if (!strcmp(argv[nextArg], "add")) {
   1318             add = true;
   1319         } else if (strcmp(argv[nextArg], "remove")) {
   1320             return syntaxError(client, "Unknown argument");
   1321         }
   1322         ++nextArg;
   1323 
   1324         if (argc < nextArg + 3 || argc > nextArg + 4) {
   1325             return syntaxError(client, "Incorrect number of arguments");
   1326         }
   1327 
   1328         unsigned netId = stringToNetId(argv[nextArg++]);
   1329         const char* interface = argv[nextArg++];
   1330         const char* destination = argv[nextArg++];
   1331         const char* nexthop = argc > nextArg ? argv[nextArg] : NULL;
   1332 
   1333         int ret;
   1334         if (add) {
   1335             ret = gCtls->netCtrl.addRoute(netId, interface, destination, nexthop, legacy, uid);
   1336         } else {
   1337             ret = gCtls->netCtrl.removeRoute(netId, interface, destination, nexthop, legacy, uid);
   1338         }
   1339         if (ret) {
   1340             return operationError(client, add ? "addRoute() failed" : "removeRoute() failed", ret);
   1341         }
   1342 
   1343         return success(client);
   1344     }
   1345 
   1346     //    0        1       2       3         4
   1347     // network interface  add   <netId> <interface>
   1348     // network interface remove <netId> <interface>
   1349     if (!strcmp(argv[1], "interface")) {
   1350         if (argc != 5) {
   1351             return syntaxError(client, "Missing argument");
   1352         }
   1353         unsigned netId = stringToNetId(argv[3]);
   1354         if (!strcmp(argv[2], "add")) {
   1355             if (int ret = gCtls->netCtrl.addInterfaceToNetwork(netId, argv[4])) {
   1356                 return operationError(client, "addInterfaceToNetwork() failed", ret);
   1357             }
   1358         } else if (!strcmp(argv[2], "remove")) {
   1359             if (int ret = gCtls->netCtrl.removeInterfaceFromNetwork(netId, argv[4])) {
   1360                 return operationError(client, "removeInterfaceFromNetwork() failed", ret);
   1361             }
   1362         } else {
   1363             return syntaxError(client, "Unknown argument");
   1364         }
   1365         return success(client);
   1366     }
   1367 
   1368     //    0      1       2         3
   1369     // network create <netId> [permission]
   1370     //
   1371     //    0      1       2     3     4        5
   1372     // network create <netId> vpn <hasDns> <secure>
   1373     if (!strcmp(argv[1], "create")) {
   1374         if (argc < 3) {
   1375             return syntaxError(client, "Missing argument");
   1376         }
   1377         unsigned netId = stringToNetId(argv[2]);
   1378         if (argc == 6 && !strcmp(argv[3], "vpn")) {
   1379             bool hasDns = atoi(argv[4]);
   1380             bool secure = atoi(argv[5]);
   1381             if (int ret = gCtls->netCtrl.createVirtualNetwork(netId, hasDns, secure)) {
   1382                 return operationError(client, "createVirtualNetwork() failed", ret);
   1383             }
   1384         } else if (argc > 4) {
   1385             return syntaxError(client, "Unknown trailing argument(s)");
   1386         } else {
   1387             Permission permission = PERMISSION_NONE;
   1388             if (argc == 4) {
   1389                 permission = stringToPermission(argv[3]);
   1390                 if (permission == PERMISSION_NONE) {
   1391                     return syntaxError(client, "Unknown permission");
   1392                 }
   1393             }
   1394             if (int ret = gCtls->netCtrl.createPhysicalNetwork(netId, permission)) {
   1395                 return operationError(client, "createPhysicalNetwork() failed", ret);
   1396             }
   1397         }
   1398         return success(client);
   1399     }
   1400 
   1401     //    0       1       2
   1402     // network destroy <netId>
   1403     if (!strcmp(argv[1], "destroy")) {
   1404         if (argc != 3) {
   1405             return syntaxError(client, "Incorrect number of arguments");
   1406         }
   1407         unsigned netId = stringToNetId(argv[2]);
   1408         // Both of these functions manage their own locking internally.
   1409         if (int ret = gCtls->netCtrl.destroyNetwork(netId)) {
   1410             return operationError(client, "destroyNetwork() failed", ret);
   1411         }
   1412         gCtls->resolverCtrl.clearDnsServers(netId);
   1413         return success(client);
   1414     }
   1415 
   1416     //    0       1      2      3
   1417     // network default  set  <netId>
   1418     // network default clear
   1419     if (!strcmp(argv[1], "default")) {
   1420         if (argc < 3) {
   1421             return syntaxError(client, "Missing argument");
   1422         }
   1423         unsigned netId = NETID_UNSET;
   1424         if (!strcmp(argv[2], "set")) {
   1425             if (argc < 4) {
   1426                 return syntaxError(client, "Missing netId");
   1427             }
   1428             netId = stringToNetId(argv[3]);
   1429         } else if (strcmp(argv[2], "clear")) {
   1430             return syntaxError(client, "Unknown argument");
   1431         }
   1432         if (int ret = gCtls->netCtrl.setDefaultNetwork(netId)) {
   1433             return operationError(client, "setDefaultNetwork() failed", ret);
   1434         }
   1435         return success(client);
   1436     }
   1437 
   1438     //    0        1         2      3        4          5
   1439     // network permission   user   set  <permission>  <uid> ...
   1440     // network permission   user  clear    <uid> ...
   1441     // network permission network  set  <permission> <netId> ...
   1442     // network permission network clear   <netId> ...
   1443     if (!strcmp(argv[1], "permission")) {
   1444         if (argc < 5) {
   1445             return syntaxError(client, "Missing argument");
   1446         }
   1447         int nextArg = 4;
   1448         Permission permission = PERMISSION_NONE;
   1449         if (!strcmp(argv[3], "set")) {
   1450             permission = stringToPermission(argv[4]);
   1451             if (permission == PERMISSION_NONE) {
   1452                 return syntaxError(client, "Unknown permission");
   1453             }
   1454             nextArg = 5;
   1455         } else if (strcmp(argv[3], "clear")) {
   1456             return syntaxError(client, "Unknown argument");
   1457         }
   1458         if (nextArg == argc) {
   1459             return syntaxError(client, "Missing id");
   1460         }
   1461 
   1462         bool userPermissions = !strcmp(argv[2], "user");
   1463         bool networkPermissions = !strcmp(argv[2], "network");
   1464         if (!userPermissions && !networkPermissions) {
   1465             return syntaxError(client, "Unknown argument");
   1466         }
   1467 
   1468         std::vector<unsigned> ids;
   1469         for (; nextArg < argc; ++nextArg) {
   1470             if (userPermissions) {
   1471                 char* endPtr;
   1472                 unsigned id = strtoul(argv[nextArg], &endPtr, 0);
   1473                 if (!*argv[nextArg] || *endPtr) {
   1474                     return syntaxError(client, "Invalid id");
   1475                 }
   1476                 ids.push_back(id);
   1477             } else {
   1478                 // networkPermissions
   1479                 ids.push_back(stringToNetId(argv[nextArg]));
   1480             }
   1481         }
   1482         if (userPermissions) {
   1483             gCtls->netCtrl.setPermissionForUsers(permission, ids);
   1484         } else {
   1485             // networkPermissions
   1486             if (int ret = gCtls->netCtrl.setPermissionForNetworks(permission, ids)) {
   1487                 return operationError(client, "setPermissionForNetworks() failed", ret);
   1488             }
   1489         }
   1490 
   1491         return success(client);
   1492     }
   1493 
   1494     //    0      1     2       3           4
   1495     // network users  add   <netId> [<uid>[-<uid>]] ...
   1496     // network users remove <netId> [<uid>[-<uid>]] ...
   1497     if (!strcmp(argv[1], "users")) {
   1498         if (argc < 4) {
   1499             return syntaxError(client, "Missing argument");
   1500         }
   1501         unsigned netId = stringToNetId(argv[3]);
   1502         UidRanges uidRanges;
   1503         if (!uidRanges.parseFrom(argc - 4, argv + 4)) {
   1504             return syntaxError(client, "Invalid UIDs");
   1505         }
   1506         if (!strcmp(argv[2], "add")) {
   1507             if (int ret = gCtls->netCtrl.addUsersToNetwork(netId, uidRanges)) {
   1508                 return operationError(client, "addUsersToNetwork() failed", ret);
   1509             }
   1510         } else if (!strcmp(argv[2], "remove")) {
   1511             if (int ret = gCtls->netCtrl.removeUsersFromNetwork(netId, uidRanges)) {
   1512                 return operationError(client, "removeUsersFromNetwork() failed", ret);
   1513             }
   1514         } else {
   1515             return syntaxError(client, "Unknown argument");
   1516         }
   1517         return success(client);
   1518     }
   1519 
   1520     //    0       1      2     3
   1521     // network protect allow <uid> ...
   1522     // network protect  deny <uid> ...
   1523     if (!strcmp(argv[1], "protect")) {
   1524         if (argc < 4) {
   1525             return syntaxError(client, "Missing argument");
   1526         }
   1527         std::vector<uid_t> uids;
   1528         for (int i = 3; i < argc; ++i) {
   1529             uids.push_back(strtoul(argv[i], NULL, 0));
   1530         }
   1531         if (!strcmp(argv[2], "allow")) {
   1532             gCtls->netCtrl.allowProtect(uids);
   1533         } else if (!strcmp(argv[2], "deny")) {
   1534             gCtls->netCtrl.denyProtect(uids);
   1535         } else {
   1536             return syntaxError(client, "Unknown argument");
   1537         }
   1538         return success(client);
   1539     }
   1540 
   1541     return syntaxError(client, "Unknown argument");
   1542 }
   1543 
   1544 }  // namespace net
   1545 }  // namespace android
   1546