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         NULL,
     81 };
     82 
     83 static const char* RAW_PREROUTING[] = {
     84         BandwidthController::LOCAL_RAW_PREROUTING,
     85         IdletimerController::LOCAL_RAW_PREROUTING,
     86         NULL,
     87 };
     88 
     89 static const char* MANGLE_POSTROUTING[] = {
     90         BandwidthController::LOCAL_MANGLE_POSTROUTING,
     91         IdletimerController::LOCAL_MANGLE_POSTROUTING,
     92         SecondaryTableController::LOCAL_MANGLE_POSTROUTING,
     93         NULL,
     94 };
     95 
     96 static const char* MANGLE_OUTPUT[] = {
     97         SecondaryTableController::LOCAL_MANGLE_OUTPUT,
     98         NULL,
     99 };
    100 
    101 static const char* NAT_PREROUTING[] = {
    102         OEM_IPTABLES_NAT_PREROUTING,
    103         NULL,
    104 };
    105 
    106 static const char* NAT_POSTROUTING[] = {
    107         NatController::LOCAL_NAT_POSTROUTING,
    108         SecondaryTableController::LOCAL_NAT_POSTROUTING,
    109         NULL,
    110 };
    111 
    112 static void createChildChains(IptablesTarget target, const char* table, const char* parentChain,
    113         const char** childChains) {
    114     const char** childChain = childChains;
    115     do {
    116         // Order is important:
    117         // -D to delete any pre-existing jump rule (removes references
    118         //    that would prevent -X from working)
    119         // -F to flush any existing chain
    120         // -X to delete any existing chain
    121         // -N to create the chain
    122         // -A to append the chain to parent
    123 
    124         execIptablesSilently(target, "-t", table, "-D", parentChain, "-j", *childChain, NULL);
    125         execIptablesSilently(target, "-t", table, "-F", *childChain, NULL);
    126         execIptablesSilently(target, "-t", table, "-X", *childChain, NULL);
    127         execIptables(target, "-t", table, "-N", *childChain, NULL);
    128         execIptables(target, "-t", table, "-A", parentChain, "-j", *childChain, NULL);
    129     } while (*(++childChain) != NULL);
    130 }
    131 
    132 CommandListener::CommandListener(UidMarkMap *map) :
    133                  FrameworkListener("netd", true) {
    134     registerCmd(new InterfaceCmd());
    135     registerCmd(new IpFwdCmd());
    136     registerCmd(new TetherCmd());
    137     registerCmd(new NatCmd());
    138     registerCmd(new ListTtysCmd());
    139     registerCmd(new PppdCmd());
    140     registerCmd(new SoftapCmd());
    141     registerCmd(new BandwidthControlCmd());
    142     registerCmd(new IdletimerControlCmd());
    143     registerCmd(new ResolverCmd());
    144     registerCmd(new FirewallCmd());
    145     registerCmd(new ClatdCmd());
    146 
    147     if (!sSecondaryTableCtrl)
    148         sSecondaryTableCtrl = new SecondaryTableController(map);
    149     if (!sTetherCtrl)
    150         sTetherCtrl = new TetherController();
    151     if (!sNatCtrl)
    152         sNatCtrl = new NatController(sSecondaryTableCtrl);
    153     if (!sPppCtrl)
    154         sPppCtrl = new PppController();
    155     if (!sSoftapCtrl)
    156         sSoftapCtrl = new SoftapController();
    157     if (!sBandwidthCtrl)
    158         sBandwidthCtrl = new BandwidthController();
    159     if (!sIdletimerCtrl)
    160         sIdletimerCtrl = new IdletimerController();
    161     if (!sResolverCtrl)
    162         sResolverCtrl = new ResolverController();
    163     if (!sFirewallCtrl)
    164         sFirewallCtrl = new FirewallController();
    165     if (!sInterfaceCtrl)
    166         sInterfaceCtrl = new InterfaceController();
    167     if (!sClatdCtrl)
    168         sClatdCtrl = new ClatdController();
    169 
    170     /*
    171      * This is the only time we touch top-level chains in iptables; controllers
    172      * should only mutate rules inside of their children chains, as created by
    173      * the constants above.
    174      *
    175      * Modules should never ACCEPT packets (except in well-justified cases);
    176      * they should instead defer to any remaining modules using RETURN, or
    177      * otherwise DROP/REJECT.
    178      */
    179 
    180     // Create chains for children modules
    181     createChildChains(V4V6, "filter", "INPUT", FILTER_INPUT);
    182     createChildChains(V4V6, "filter", "FORWARD", FILTER_FORWARD);
    183     createChildChains(V4V6, "filter", "OUTPUT", FILTER_OUTPUT);
    184     createChildChains(V4V6, "raw", "PREROUTING", RAW_PREROUTING);
    185     createChildChains(V4V6, "mangle", "POSTROUTING", MANGLE_POSTROUTING);
    186     createChildChains(V4V6, "mangle", "OUTPUT", MANGLE_OUTPUT);
    187     createChildChains(V4, "nat", "PREROUTING", NAT_PREROUTING);
    188     createChildChains(V4, "nat", "POSTROUTING", NAT_POSTROUTING);
    189 
    190     // Let each module setup their child chains
    191     setupOemIptablesHook();
    192 
    193     /* When enabled, DROPs all packets except those matching rules. */
    194     sFirewallCtrl->setupIptablesHooks();
    195 
    196     /* Does DROPs in FORWARD by default */
    197     sNatCtrl->setupIptablesHooks();
    198     /*
    199      * Does REJECT in INPUT, OUTPUT. Does counting also.
    200      * No DROP/REJECT allowed later in netfilter-flow hook order.
    201      */
    202     sBandwidthCtrl->setupIptablesHooks();
    203     /*
    204      * Counts in nat: PREROUTING, POSTROUTING.
    205      * No DROP/REJECT allowed later in netfilter-flow hook order.
    206      */
    207     sIdletimerCtrl->setupIptablesHooks();
    208 
    209     sBandwidthCtrl->enableBandwidthControl(false);
    210 
    211     sSecondaryTableCtrl->setupIptablesHooks();
    212 }
    213 
    214 CommandListener::InterfaceCmd::InterfaceCmd() :
    215                  NetdCommand("interface") {
    216 }
    217 
    218 int CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
    219                                                       int argc, char **argv) {
    220     if (argc < 2) {
    221         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    222         return 0;
    223     }
    224 
    225     if (!strcmp(argv[1], "list")) {
    226         DIR *d;
    227         struct dirent *de;
    228 
    229         if (!(d = opendir("/sys/class/net"))) {
    230             cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true);
    231             return 0;
    232         }
    233 
    234         while((de = readdir(d))) {
    235             if (de->d_name[0] == '.')
    236                 continue;
    237             cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false);
    238         }
    239         closedir(d);
    240         cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false);
    241         return 0;
    242     } else if (!strcmp(argv[1], "driver")) {
    243         int rc;
    244         char *rbuf;
    245 
    246         if (argc < 4) {
    247             cli->sendMsg(ResponseCode::CommandSyntaxError,
    248                     "Usage: interface driver <interface> <cmd> <args>", false);
    249             return 0;
    250         }
    251         rc = sInterfaceCtrl->interfaceCommand(argc, argv, &rbuf);
    252         if (rc) {
    253             cli->sendMsg(ResponseCode::OperationFailed, "Failed to execute command", true);
    254         } else {
    255             cli->sendMsg(ResponseCode::CommandOkay, rbuf, false);
    256         }
    257         return 0;
    258     } else {
    259         /*
    260          * These commands take a minimum of 3 arguments
    261          */
    262         if (argc < 3) {
    263             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    264             return 0;
    265         }
    266 
    267         //     0       1       2        3          4           5        6      7
    268         // interface route add/remove iface default/secondary dest    prefix gateway
    269         // interface fwmark  rule  add/remove    iface
    270         // interface fwmark  route add/remove    iface        dest    prefix
    271         // interface fwmark  uid   add/remove    iface      uid_start uid_end
    272         // interface fwmark exempt add/remove    dest
    273         // interface fwmark  get     protect
    274         // interface fwmark  get     mark        uid
    275         if (!strcmp(argv[1], "fwmark")) {
    276             if (!strcmp(argv[2], "rule")) {
    277                 if (argc < 5) {
    278                     cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    279                     return 0;
    280                 }
    281                 if (!strcmp(argv[3], "add")) {
    282                     if (!sSecondaryTableCtrl->addFwmarkRule(argv[4])) {
    283                         cli->sendMsg(ResponseCode::CommandOkay,
    284                                 "Fwmark rule successfully added", false);
    285                     } else {
    286                         cli->sendMsg(ResponseCode::OperationFailed, "Failed to add fwmark rule",
    287                                 true);
    288                     }
    289                 } else if (!strcmp(argv[3], "remove")) {
    290                     if (!sSecondaryTableCtrl->removeFwmarkRule(argv[4])) {
    291                         cli->sendMsg(ResponseCode::CommandOkay,
    292                                 "Fwmark rule successfully removed", false);
    293                     } else {
    294                         cli->sendMsg(ResponseCode::OperationFailed,
    295                                 "Failed to remove fwmark rule", true);
    296                     }
    297                 } else {
    298                     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown fwmark rule cmd",
    299                             false);
    300                 }
    301                 return 0;
    302             } else if (!strcmp(argv[2], "route")) {
    303                 if (argc < 7) {
    304                     cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    305                     return 0;
    306                 }
    307                 if (!strcmp(argv[3], "add")) {
    308                     if (!sSecondaryTableCtrl->addFwmarkRoute(argv[4], argv[5], atoi(argv[6]))) {
    309                         cli->sendMsg(ResponseCode::CommandOkay,
    310                                 "Fwmark route successfully added", false);
    311                     } else {
    312                         cli->sendMsg(ResponseCode::OperationFailed,
    313                                 "Failed to add fwmark route", true);
    314                     }
    315                 } else if (!strcmp(argv[3], "remove")) {
    316                     if (!sSecondaryTableCtrl->removeFwmarkRoute(argv[4], argv[5],
    317                                 atoi(argv[6]))) {
    318                         cli->sendMsg(ResponseCode::CommandOkay,
    319                                 "Fwmark route successfully removed", false);
    320                     } else {
    321                         cli->sendMsg(ResponseCode::OperationFailed,
    322                                 "Failed to remove fwmark route", true);
    323                     }
    324                 } else {
    325                     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown fwmark route cmd",
    326                             false);
    327                 }
    328                 return 0;
    329 
    330             } else if (!strcmp(argv[2], "uid")) {
    331                 if (argc < 7) {
    332                     cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    333                     return 0;
    334                 }
    335                 if (!strcmp(argv[3], "add")) {
    336                     if (!sSecondaryTableCtrl->addUidRule(argv[4], atoi(argv[5]), atoi(argv[6]))) {
    337                         cli->sendMsg(ResponseCode::CommandOkay, "uid rule successfully added",
    338                                 false);
    339                     } else {
    340                         cli->sendMsg(ResponseCode::OperationFailed, "Failed to add uid rule", true);
    341                     }
    342                 } else if (!strcmp(argv[3], "remove")) {
    343                     if (!sSecondaryTableCtrl->removeUidRule(argv[4],
    344                                 atoi(argv[5]), atoi(argv[6]))) {
    345                         cli->sendMsg(ResponseCode::CommandOkay, "uid rule successfully removed",
    346                                 false);
    347                     } else {
    348                         cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove uid rule",
    349                                 true);
    350                     }
    351                 } else {
    352                     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown uid cmd", false);
    353                 }
    354                 return 0;
    355             } else if (!strcmp(argv[2], "exempt")) {
    356                 if (argc < 5) {
    357                     cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    358                     return 0;
    359                 }
    360                 if (!strcmp(argv[3], "add")) {
    361                     if (!sSecondaryTableCtrl->addHostExemption(argv[4])) {
    362                         cli->sendMsg(ResponseCode::CommandOkay, "exemption rule successfully added",
    363                                 false);
    364                     } else {
    365                         cli->sendMsg(ResponseCode::OperationFailed, "Failed to add exemption rule",
    366                                 true);
    367                     }
    368                 } else if (!strcmp(argv[3], "remove")) {
    369                     if (!sSecondaryTableCtrl->removeHostExemption(argv[4])) {
    370                         cli->sendMsg(ResponseCode::CommandOkay,
    371                                 "exemption rule successfully removed", false);
    372                     } else {
    373                         cli->sendMsg(ResponseCode::OperationFailed,
    374                                 "Failed to remove exemption rule", true);
    375                     }
    376                 } else {
    377                     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown exemption cmd", false);
    378                 }
    379                 return 0;
    380             } else if (!strcmp(argv[2], "get")) {
    381                 if (argc < 4) {
    382                     cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    383                     return 0;
    384                 }
    385                 if (!strcmp(argv[3], "protect")) {
    386                     sSecondaryTableCtrl->getProtectMark(cli);
    387                     return 0;
    388                 } else if (!strcmp(argv[3], "mark")) {
    389                     if (argc < 5) {
    390                         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    391                         return 0;
    392                     }
    393                     sSecondaryTableCtrl->getUidMark(cli, atoi(argv[4]));
    394                     return 0;
    395                 } else {
    396                     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown fwmark get cmd", false);
    397                     return 0;
    398                 }
    399             } else {
    400                 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown fwmark cmd", false);
    401                 return 0;
    402             }
    403         }
    404         if (!strcmp(argv[1], "route")) {
    405             int prefix_length = 0;
    406             if (argc < 8) {
    407                 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    408                 return 0;
    409             }
    410             if (sscanf(argv[6], "%d", &prefix_length) != 1) {
    411                 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid route prefix", false);
    412                 return 0;
    413             }
    414             if (!strcmp(argv[2], "add")) {
    415                 if (!strcmp(argv[4], "default")) {
    416                     if (ifc_add_route(argv[3], argv[5], prefix_length, argv[7])) {
    417                         cli->sendMsg(ResponseCode::OperationFailed,
    418                                 "Failed to add route to default table", true);
    419                     } else {
    420                         cli->sendMsg(ResponseCode::CommandOkay,
    421                                 "Route added to default table", false);
    422                     }
    423                 } else if (!strcmp(argv[4], "secondary")) {
    424                     return sSecondaryTableCtrl->addRoute(cli, argv[3], argv[5],
    425                             prefix_length, argv[7]);
    426                 } else {
    427                     cli->sendMsg(ResponseCode::CommandParameterError,
    428                             "Invalid route type, expecting 'default' or 'secondary'", false);
    429                     return 0;
    430                 }
    431             } else if (!strcmp(argv[2], "remove")) {
    432                 if (!strcmp(argv[4], "default")) {
    433                     if (ifc_remove_route(argv[3], argv[5], prefix_length, argv[7])) {
    434                         cli->sendMsg(ResponseCode::OperationFailed,
    435                                 "Failed to remove route from default table", true);
    436                     } else {
    437                         cli->sendMsg(ResponseCode::CommandOkay,
    438                                 "Route removed from default table", false);
    439                     }
    440                 } else if (!strcmp(argv[4], "secondary")) {
    441                     return sSecondaryTableCtrl->removeRoute(cli, argv[3], argv[5],
    442                             prefix_length, argv[7]);
    443                 } else {
    444                     cli->sendMsg(ResponseCode::CommandParameterError,
    445                             "Invalid route type, expecting 'default' or 'secondary'", false);
    446                     return 0;
    447                 }
    448             } else {
    449                 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
    450             }
    451             return 0;
    452         }
    453 
    454         if (!strcmp(argv[1], "getcfg")) {
    455             struct in_addr addr;
    456             int prefixLength;
    457             unsigned char hwaddr[6];
    458             unsigned flags = 0;
    459 
    460             ifc_init();
    461             memset(hwaddr, 0, sizeof(hwaddr));
    462 
    463             if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) {
    464                 cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
    465                 ifc_close();
    466                 return 0;
    467             }
    468 
    469             if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) {
    470                 ALOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno));
    471             }
    472 
    473             char *addr_s = strdup(inet_ntoa(addr));
    474             const char *updown, *brdcst, *loopbk, *ppp, *running, *multi;
    475 
    476             updown =  (flags & IFF_UP)           ? "up" : "down";
    477             brdcst =  (flags & IFF_BROADCAST)    ? " broadcast" : "";
    478             loopbk =  (flags & IFF_LOOPBACK)     ? " loopback" : "";
    479             ppp =     (flags & IFF_POINTOPOINT)  ? " point-to-point" : "";
    480             running = (flags & IFF_RUNNING)      ? " running" : "";
    481             multi =   (flags & IFF_MULTICAST)    ? " multicast" : "";
    482 
    483             char *flag_s;
    484 
    485             asprintf(&flag_s, "%s%s%s%s%s%s", updown, brdcst, loopbk, ppp, running, multi);
    486 
    487             char *msg = NULL;
    488             asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %d %s",
    489                      hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5],
    490                      addr_s, prefixLength, flag_s);
    491 
    492             cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false);
    493 
    494             free(addr_s);
    495             free(flag_s);
    496             free(msg);
    497 
    498             ifc_close();
    499             return 0;
    500         } else if (!strcmp(argv[1], "setcfg")) {
    501             // arglist: iface [addr prefixLength] flags
    502             if (argc < 4) {
    503                 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    504                 return 0;
    505             }
    506             ALOGD("Setting iface cfg");
    507 
    508             struct in_addr addr;
    509             unsigned flags = 0;
    510             int index = 5;
    511 
    512             ifc_init();
    513 
    514             if (!inet_aton(argv[3], &addr)) {
    515                 // Handle flags only case
    516                 index = 3;
    517             } else {
    518                 if (ifc_set_addr(argv[2], addr.s_addr)) {
    519                     cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true);
    520                     ifc_close();
    521                     return 0;
    522                 }
    523 
    524                 // Set prefix length on a non zero address
    525                 if (addr.s_addr != 0 && ifc_set_prefixLength(argv[2], atoi(argv[4]))) {
    526                    cli->sendMsg(ResponseCode::OperationFailed, "Failed to set prefixLength", true);
    527                    ifc_close();
    528                    return 0;
    529                }
    530             }
    531 
    532             /* Process flags */
    533             for (int i = index; i < argc; i++) {
    534                 char *flag = argv[i];
    535                 if (!strcmp(flag, "up")) {
    536                     ALOGD("Trying to bring up %s", argv[2]);
    537                     if (ifc_up(argv[2])) {
    538                         ALOGE("Error upping interface");
    539                         cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true);
    540                         ifc_close();
    541                         return 0;
    542                     }
    543                 } else if (!strcmp(flag, "down")) {
    544                     ALOGD("Trying to bring down %s", argv[2]);
    545                     if (ifc_down(argv[2])) {
    546                         ALOGE("Error downing interface");
    547                         cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true);
    548                         ifc_close();
    549                         return 0;
    550                     }
    551                 } else if (!strcmp(flag, "broadcast")) {
    552                     // currently ignored
    553                 } else if (!strcmp(flag, "multicast")) {
    554                     // currently ignored
    555                 } else if (!strcmp(flag, "running")) {
    556                     // currently ignored
    557                 } else if (!strcmp(flag, "loopback")) {
    558                     // currently ignored
    559                 } else if (!strcmp(flag, "point-to-point")) {
    560                     // currently ignored
    561                 } else {
    562                     cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false);
    563                     ifc_close();
    564                     return 0;
    565                 }
    566             }
    567 
    568             cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false);
    569             ifc_close();
    570             return 0;
    571         } else if (!strcmp(argv[1], "clearaddrs")) {
    572             // arglist: iface
    573             ALOGD("Clearing all IP addresses on %s", argv[2]);
    574 
    575             ifc_clear_addresses(argv[2]);
    576 
    577             cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false);
    578             return 0;
    579         } else if (!strcmp(argv[1], "ipv6privacyextensions")) {
    580             if (argc != 4) {
    581                 cli->sendMsg(ResponseCode::CommandSyntaxError,
    582                         "Usage: interface ipv6privacyextensions <interface> <enable|disable>",
    583                         false);
    584                 return 0;
    585             }
    586             int enable = !strncmp(argv[3], "enable", 7);
    587             if (sInterfaceCtrl->setIPv6PrivacyExtensions(argv[2], enable) == 0) {
    588                 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false);
    589             } else {
    590                 cli->sendMsg(ResponseCode::OperationFailed,
    591                         "Failed to set ipv6 privacy extensions", true);
    592             }
    593             return 0;
    594         } else if (!strcmp(argv[1], "ipv6")) {
    595             if (argc != 4) {
    596                 cli->sendMsg(ResponseCode::CommandSyntaxError,
    597                         "Usage: interface ipv6 <interface> <enable|disable>",
    598                         false);
    599                 return 0;
    600             }
    601 
    602             int enable = !strncmp(argv[3], "enable", 7);
    603             if (sInterfaceCtrl->setEnableIPv6(argv[2], enable) == 0) {
    604                 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false);
    605             } else {
    606                 cli->sendMsg(ResponseCode::OperationFailed,
    607                         "Failed to change IPv6 state", true);
    608             }
    609             return 0;
    610         } else if (!strcmp(argv[1], "getmtu")) {
    611             char *msg = NULL;
    612             int mtu = 0;
    613             if (sInterfaceCtrl->getMtu(argv[2], &mtu) == 0) {
    614                 asprintf(&msg, "MTU = %d", mtu);
    615                 cli->sendMsg(ResponseCode::InterfaceGetMtuResult, msg, false);
    616                 free(msg);
    617             } else {
    618                 cli->sendMsg(ResponseCode::OperationFailed,
    619                         "Failed to get MTU", true);
    620             }
    621             return 0;
    622         } else if (!strcmp(argv[1], "setmtu")) {
    623             if (argc != 4) {
    624                 cli->sendMsg(ResponseCode::CommandSyntaxError,
    625                         "Usage: interface setmtu <interface> <val>", false);
    626                 return 0;
    627             }
    628             if (sInterfaceCtrl->setMtu(argv[2], argv[3]) == 0) {
    629                 cli->sendMsg(ResponseCode::CommandOkay, "MTU changed", false);
    630             } else {
    631                 cli->sendMsg(ResponseCode::OperationFailed,
    632                         "Failed to get MTU", true);
    633             }
    634             return 0;
    635         } else {
    636             cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
    637             return 0;
    638         }
    639     }
    640     return 0;
    641 }
    642 
    643 
    644 CommandListener::ListTtysCmd::ListTtysCmd() :
    645                  NetdCommand("list_ttys") {
    646 }
    647 
    648 int CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
    649                                              int argc, char **argv) {
    650     TtyCollection *tlist = sPppCtrl->getTtyList();
    651     TtyCollection::iterator it;
    652 
    653     for (it = tlist->begin(); it != tlist->end(); ++it) {
    654         cli->sendMsg(ResponseCode::TtyListResult, *it, false);
    655     }
    656 
    657     cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
    658     return 0;
    659 }
    660 
    661 CommandListener::IpFwdCmd::IpFwdCmd() :
    662                  NetdCommand("ipfwd") {
    663 }
    664 
    665 int CommandListener::IpFwdCmd::runCommand(SocketClient *cli,
    666                                                       int argc, char **argv) {
    667     int rc = 0;
    668 
    669     if (argc < 2) {
    670         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    671         return 0;
    672     }
    673 
    674     if (!strcmp(argv[1], "status")) {
    675         char *tmp = NULL;
    676 
    677         asprintf(&tmp, "Forwarding %s", (sTetherCtrl->getIpFwdEnabled() ? "enabled" : "disabled"));
    678         cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
    679         free(tmp);
    680         return 0;
    681     } else if (!strcmp(argv[1], "enable")) {
    682         rc = sTetherCtrl->setIpFwdEnabled(true);
    683     } else if (!strcmp(argv[1], "disable")) {
    684         rc = sTetherCtrl->setIpFwdEnabled(false);
    685     } else {
    686         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
    687         return 0;
    688     }
    689 
    690     if (!rc) {
    691         cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
    692     } else {
    693         cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
    694     }
    695 
    696     return 0;
    697 }
    698 
    699 CommandListener::TetherCmd::TetherCmd() :
    700                  NetdCommand("tether") {
    701 }
    702 
    703 int CommandListener::TetherCmd::runCommand(SocketClient *cli,
    704                                                       int argc, char **argv) {
    705     int rc = 0;
    706 
    707     if (argc < 2) {
    708         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    709         return 0;
    710     }
    711 
    712     if (!strcmp(argv[1], "stop")) {
    713         rc = sTetherCtrl->stopTethering();
    714     } else if (!strcmp(argv[1], "status")) {
    715         char *tmp = NULL;
    716 
    717         asprintf(&tmp, "Tethering services %s",
    718                  (sTetherCtrl->isTetheringStarted() ? "started" : "stopped"));
    719         cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
    720         free(tmp);
    721         return 0;
    722     } else if (argc == 3) {
    723         if (!strcmp(argv[1], "interface") && !strcmp(argv[2], "list")) {
    724             InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList();
    725             InterfaceCollection::iterator it;
    726             for (it = ilist->begin(); it != ilist->end(); ++it) {
    727                 cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false);
    728             }
    729         } else if (!strcmp(argv[1], "dns") && !strcmp(argv[2], "list")) {
    730             NetAddressCollection *dlist = sTetherCtrl->getDnsForwarders();
    731             NetAddressCollection::iterator it;
    732 
    733             for (it = dlist->begin(); it != dlist->end(); ++it) {
    734                 cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, inet_ntoa(*it), false);
    735             }
    736         }
    737     } else {
    738         /*
    739          * These commands take a minimum of 4 arguments
    740          */
    741         if (argc < 4) {
    742             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    743             return 0;
    744         }
    745 
    746         if (!strcmp(argv[1], "start")) {
    747             if (argc % 2 == 1) {
    748                 cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false);
    749                 return 0;
    750             }
    751 
    752             int num_addrs = argc - 2;
    753             int arg_index = 2;
    754             int array_index = 0;
    755             in_addr *addrs = (in_addr *)malloc(sizeof(in_addr) * num_addrs);
    756             while (array_index < num_addrs) {
    757                 if (!inet_aton(argv[arg_index++], &(addrs[array_index++]))) {
    758                     cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
    759                     free(addrs);
    760                     return 0;
    761                 }
    762             }
    763             rc = sTetherCtrl->startTethering(num_addrs, addrs);
    764             free(addrs);
    765         } else if (!strcmp(argv[1], "interface")) {
    766             if (!strcmp(argv[2], "add")) {
    767                 rc = sTetherCtrl->tetherInterface(argv[3]);
    768             } else if (!strcmp(argv[2], "remove")) {
    769                 rc = sTetherCtrl->untetherInterface(argv[3]);
    770             /* else if (!strcmp(argv[2], "list")) handled above */
    771             } else {
    772                 cli->sendMsg(ResponseCode::CommandParameterError,
    773                              "Unknown tether interface operation", false);
    774                 return 0;
    775             }
    776         } else if (!strcmp(argv[1], "dns")) {
    777             if (!strcmp(argv[2], "set")) {
    778                 rc = sTetherCtrl->setDnsForwarders(&argv[3], argc - 3);
    779             /* else if (!strcmp(argv[2], "list")) handled above */
    780             } else {
    781                 cli->sendMsg(ResponseCode::CommandParameterError,
    782                              "Unknown tether interface operation", false);
    783                 return 0;
    784             }
    785         } else {
    786             cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
    787             return 0;
    788         }
    789     }
    790 
    791     if (!rc) {
    792         cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
    793     } else {
    794         cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
    795     }
    796 
    797     return 0;
    798 }
    799 
    800 CommandListener::NatCmd::NatCmd() :
    801                  NetdCommand("nat") {
    802 }
    803 
    804 int CommandListener::NatCmd::runCommand(SocketClient *cli,
    805                                                       int argc, char **argv) {
    806     int rc = 0;
    807 
    808     if (argc < 5) {
    809         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    810         return 0;
    811     }
    812 
    813     if (!strcmp(argv[1], "enable")) {
    814         rc = sNatCtrl->enableNat(argc, argv);
    815         if(!rc) {
    816             /* Ignore ifaces for now. */
    817             rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
    818         }
    819     } else if (!strcmp(argv[1], "disable")) {
    820         /* Ignore ifaces for now. */
    821         rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
    822         rc |= sNatCtrl->disableNat(argc, argv);
    823     } else {
    824         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
    825         return 0;
    826     }
    827 
    828     if (!rc) {
    829         cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
    830     } else {
    831         cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
    832     }
    833 
    834     return 0;
    835 }
    836 
    837 CommandListener::PppdCmd::PppdCmd() :
    838                  NetdCommand("pppd") {
    839 }
    840 
    841 int CommandListener::PppdCmd::runCommand(SocketClient *cli,
    842                                                       int argc, char **argv) {
    843     int rc = 0;
    844 
    845     if (argc < 3) {
    846         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
    847         return 0;
    848     }
    849 
    850     if (!strcmp(argv[1], "attach")) {
    851         struct in_addr l, r, dns1, dns2;
    852 
    853         memset(&dns1, 0, sizeof(struct in_addr));
    854         memset(&dns2, 0, sizeof(struct in_addr));
    855 
    856         if (!inet_aton(argv[3], &l)) {
    857             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false);
    858             return 0;
    859         }
    860         if (!inet_aton(argv[4], &r)) {
    861             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false);
    862             return 0;
    863         }
    864         if ((argc > 3) && (!inet_aton(argv[5], &dns1))) {
    865             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false);
    866             return 0;
    867         }
    868         if ((argc > 4) && (!inet_aton(argv[6], &dns2))) {
    869             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false);
    870             return 0;
    871         }
    872         rc = sPppCtrl->attachPppd(argv[2], l, r, dns1, dns2);
    873     } else if (!strcmp(argv[1], "detach")) {
    874         rc = sPppCtrl->detachPppd(argv[2]);
    875     } else {
    876         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false);
    877         return 0;
    878     }
    879 
    880     if (!rc) {
    881         cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false);
    882     } else {
    883         cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true);
    884     }
    885 
    886     return 0;
    887 }
    888 
    889 CommandListener::SoftapCmd::SoftapCmd() :
    890                  NetdCommand("softap") {
    891 }
    892 
    893 int CommandListener::SoftapCmd::runCommand(SocketClient *cli,
    894                                         int argc, char **argv) {
    895     int rc = ResponseCode::SoftapStatusResult;
    896     int flag = 0;
    897     char *retbuf = NULL;
    898 
    899     if (sSoftapCtrl == NULL) {
    900       cli->sendMsg(ResponseCode::ServiceStartFailed, "SoftAP is not available", false);
    901       return -1;
    902     }
    903     if (argc < 2) {
    904         cli->sendMsg(ResponseCode::CommandSyntaxError,
    905                      "Missing argument in a SoftAP command", false);
    906         return 0;
    907     }
    908 
    909     if (!strcmp(argv[1], "startap")) {
    910         rc = sSoftapCtrl->startSoftap();
    911     } else if (!strcmp(argv[1], "stopap")) {
    912         rc = sSoftapCtrl->stopSoftap();
    913     } else if (!strcmp(argv[1], "fwreload")) {
    914         rc = sSoftapCtrl->fwReloadSoftap(argc, argv);
    915     } else if (!strcmp(argv[1], "status")) {
    916         asprintf(&retbuf, "Softap service %s running",
    917                  (sSoftapCtrl->isSoftapStarted() ? "is" : "is not"));
    918         cli->sendMsg(rc, retbuf, false);
    919         free(retbuf);
    920         return 0;
    921     } else if (!strcmp(argv[1], "set")) {
    922         rc = sSoftapCtrl->setSoftap(argc, argv);
    923     } else {
    924         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unrecognized SoftAP command", false);
    925         return 0;
    926     }
    927 
    928     if (rc >= 400 && rc < 600)
    929       cli->sendMsg(rc, "SoftAP command has failed", false);
    930     else
    931       cli->sendMsg(rc, "Ok", false);
    932 
    933     return 0;
    934 }
    935 
    936 CommandListener::ResolverCmd::ResolverCmd() :
    937         NetdCommand("resolver") {
    938 }
    939 
    940 int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **margv) {
    941     int rc = 0;
    942     struct in_addr addr;
    943     const char **argv = const_cast<const char **>(margv);
    944 
    945     if (argc < 2) {
    946         cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false);
    947         return 0;
    948     }
    949 
    950     if (!strcmp(argv[1], "setdefaultif")) { // "resolver setdefaultif <iface>"
    951         if (argc == 3) {
    952             rc = sResolverCtrl->setDefaultInterface(argv[2]);
    953         } else {
    954             cli->sendMsg(ResponseCode::CommandSyntaxError,
    955                     "Wrong number of arguments to resolver setdefaultif", false);
    956             return 0;
    957         }
    958     } else if (!strcmp(argv[1], "setifdns")) {
    959         // "resolver setifdns <iface> <domains> <dns1> <dns2> ..."
    960         if (argc >= 5) {
    961             rc = sResolverCtrl->setInterfaceDnsServers(argv[2], argv[3], &argv[4], argc - 4);
    962         } else {
    963             cli->sendMsg(ResponseCode::CommandSyntaxError,
    964                     "Wrong number of arguments to resolver setifdns", false);
    965             return 0;
    966         }
    967 
    968         // set the address of the interface to which the name servers
    969         // are bound. Required in order to bind to right interface when
    970         // doing the dns query.
    971         if (!rc) {
    972             ifc_init();
    973             ifc_get_info(argv[2], &addr.s_addr, NULL, 0);
    974 
    975             rc = sResolverCtrl->setInterfaceAddress(argv[2], &addr);
    976         }
    977     } else if (!strcmp(argv[1], "flushdefaultif")) { // "resolver flushdefaultif"
    978         if (argc == 2) {
    979             rc = sResolverCtrl->flushDefaultDnsCache();
    980         } else {
    981             cli->sendMsg(ResponseCode::CommandSyntaxError,
    982                     "Wrong number of arguments to resolver flushdefaultif", false);
    983             return 0;
    984         }
    985     } else if (!strcmp(argv[1], "flushif")) { // "resolver flushif <iface>"
    986         if (argc == 3) {
    987             rc = sResolverCtrl->flushInterfaceDnsCache(argv[2]);
    988         } else {
    989             cli->sendMsg(ResponseCode::CommandSyntaxError,
    990                     "Wrong number of arguments to resolver setdefaultif", false);
    991             return 0;
    992         }
    993     } else if (!strcmp(argv[1], "setifaceforpid")) { // resolver setifaceforpid <iface> <pid>
    994         if (argc == 4) {
    995             rc = sResolverCtrl->setDnsInterfaceForPid(argv[2], atoi(argv[3]));
    996         } else {
    997             cli->sendMsg(ResponseCode::CommandSyntaxError,
    998                     "Wrong number of arguments to resolver setifaceforpid", false);
    999             return 0;
   1000         }
   1001     } else if (!strcmp(argv[1], "clearifaceforpid")) { // resolver clearifaceforpid <pid>
   1002         if (argc == 3) {
   1003             rc = sResolverCtrl->clearDnsInterfaceForPid(atoi(argv[2]));
   1004         } else {
   1005             cli->sendMsg(ResponseCode::CommandSyntaxError,
   1006                     "Wrong number of arguments to resolver clearifaceforpid", false);
   1007             return 0;
   1008         }
   1009     } else if (!strcmp(argv[1], "setifaceforuidrange")) { // resolver setifaceforuid <iface> <l> <h>
   1010         if (argc == 5) {
   1011             rc = sResolverCtrl->setDnsInterfaceForUidRange(argv[2], atoi(argv[3]), atoi(argv[4]));
   1012         } else {
   1013             cli->sendMsg(ResponseCode::CommandSyntaxError,
   1014                     "Wrong number of arguments to resolver setifaceforuid", false);
   1015             return 0;
   1016         }
   1017     } else if (!strcmp(argv[1], "clearifaceforuidrange")) {
   1018         // resolver clearifaceforuid <if> <l> <h>
   1019         if (argc == 5) {
   1020             rc = sResolverCtrl->clearDnsInterfaceForUidRange(argv[2], atoi(argv[3]),
   1021                     atoi(argv[4]));
   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