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