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