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