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