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