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