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