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