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