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#include <resolv_netid.h>
29
30#define __STDC_FORMAT_MACROS 1
31#include <inttypes.h>
32
33#define LOG_TAG "CommandListener"
34
35#include <cutils/log.h>
36#include <netutils/ifc.h>
37#include <sysutils/SocketClient.h>
38
39#include "CommandListener.h"
40#include "ResponseCode.h"
41#include "BandwidthController.h"
42#include "IdletimerController.h"
43#include "oem_iptables_hook.h"
44#include "NetdConstants.h"
45#include "FirewallController.h"
46#include "RouteController.h"
47#include "UidRanges.h"
48
49#include <string>
50#include <vector>
51
52namespace {
53
54const unsigned NUM_OEM_IDS = NetworkController::MAX_OEM_ID - NetworkController::MIN_OEM_ID + 1;
55
56Permission stringToPermission(const char* arg) {
57    if (!strcmp(arg, "NETWORK")) {
58        return PERMISSION_NETWORK;
59    }
60    if (!strcmp(arg, "SYSTEM")) {
61        return PERMISSION_SYSTEM;
62    }
63    return PERMISSION_NONE;
64}
65
66unsigned stringToNetId(const char* arg) {
67    if (!strcmp(arg, "local")) {
68        return NetworkController::LOCAL_NET_ID;
69    }
70    // OEM NetIds are "oem1", "oem2", .., "oem50".
71    if (!strncmp(arg, "oem", 3)) {
72        unsigned n = strtoul(arg + 3, NULL, 0);
73        if (1 <= n && n <= NUM_OEM_IDS) {
74            return NetworkController::MIN_OEM_ID + n;
75        }
76        return NETID_UNSET;
77    }
78    // strtoul() returns 0 on errors, which is fine because 0 is an invalid netId.
79    return strtoul(arg, NULL, 0);
80}
81
82}  // namespace
83
84NetworkController *CommandListener::sNetCtrl = NULL;
85TetherController *CommandListener::sTetherCtrl = NULL;
86NatController *CommandListener::sNatCtrl = NULL;
87PppController *CommandListener::sPppCtrl = NULL;
88SoftapController *CommandListener::sSoftapCtrl = NULL;
89BandwidthController * CommandListener::sBandwidthCtrl = NULL;
90IdletimerController * CommandListener::sIdletimerCtrl = NULL;
91InterfaceController *CommandListener::sInterfaceCtrl = NULL;
92ResolverController *CommandListener::sResolverCtrl = NULL;
93FirewallController *CommandListener::sFirewallCtrl = NULL;
94ClatdController *CommandListener::sClatdCtrl = NULL;
95StrictController *CommandListener::sStrictCtrl = NULL;
96
97/**
98 * List of module chains to be created, along with explicit ordering. ORDERING
99 * IS CRITICAL, AND SHOULD BE TRIPLE-CHECKED WITH EACH CHANGE.
100 */
101static const char* FILTER_INPUT[] = {
102        // Bandwidth should always be early in input chain, to make sure we
103        // correctly count incoming traffic against data plan.
104        BandwidthController::LOCAL_INPUT,
105        FirewallController::LOCAL_INPUT,
106        NULL,
107};
108
109static const char* FILTER_FORWARD[] = {
110        OEM_IPTABLES_FILTER_FORWARD,
111        FirewallController::LOCAL_FORWARD,
112        BandwidthController::LOCAL_FORWARD,
113        NatController::LOCAL_FORWARD,
114        NULL,
115};
116
117static const char* FILTER_OUTPUT[] = {
118        OEM_IPTABLES_FILTER_OUTPUT,
119        FirewallController::LOCAL_OUTPUT,
120        StrictController::LOCAL_OUTPUT,
121        BandwidthController::LOCAL_OUTPUT,
122        NULL,
123};
124
125static const char* RAW_PREROUTING[] = {
126        BandwidthController::LOCAL_RAW_PREROUTING,
127        IdletimerController::LOCAL_RAW_PREROUTING,
128        NULL,
129};
130
131static const char* MANGLE_POSTROUTING[] = {
132        BandwidthController::LOCAL_MANGLE_POSTROUTING,
133        IdletimerController::LOCAL_MANGLE_POSTROUTING,
134        NULL,
135};
136
137static const char* MANGLE_FORWARD[] = {
138        NatController::LOCAL_MANGLE_FORWARD,
139        NULL,
140};
141
142static const char* NAT_PREROUTING[] = {
143        OEM_IPTABLES_NAT_PREROUTING,
144        NULL,
145};
146
147static const char* NAT_POSTROUTING[] = {
148        NatController::LOCAL_NAT_POSTROUTING,
149        NULL,
150};
151
152static void createChildChains(IptablesTarget target, const char* table, const char* parentChain,
153        const char** childChains) {
154    const char** childChain = childChains;
155    do {
156        // Order is important:
157        // -D to delete any pre-existing jump rule (removes references
158        //    that would prevent -X from working)
159        // -F to flush any existing chain
160        // -X to delete any existing chain
161        // -N to create the chain
162        // -A to append the chain to parent
163
164        execIptablesSilently(target, "-t", table, "-D", parentChain, "-j", *childChain, NULL);
165        execIptablesSilently(target, "-t", table, "-F", *childChain, NULL);
166        execIptablesSilently(target, "-t", table, "-X", *childChain, NULL);
167        execIptables(target, "-t", table, "-N", *childChain, NULL);
168        execIptables(target, "-t", table, "-A", parentChain, "-j", *childChain, NULL);
169    } while (*(++childChain) != NULL);
170}
171
172CommandListener::CommandListener() :
173                 FrameworkListener("netd", true) {
174    registerCmd(new InterfaceCmd());
175    registerCmd(new IpFwdCmd());
176    registerCmd(new TetherCmd());
177    registerCmd(new NatCmd());
178    registerCmd(new ListTtysCmd());
179    registerCmd(new PppdCmd());
180    registerCmd(new SoftapCmd());
181    registerCmd(new BandwidthControlCmd());
182    registerCmd(new IdletimerControlCmd());
183    registerCmd(new ResolverCmd());
184    registerCmd(new FirewallCmd());
185    registerCmd(new ClatdCmd());
186    registerCmd(new NetworkCommand());
187    registerCmd(new StrictCmd());
188
189    if (!sNetCtrl)
190        sNetCtrl = new NetworkController();
191    if (!sTetherCtrl)
192        sTetherCtrl = new TetherController();
193    if (!sNatCtrl)
194        sNatCtrl = new NatController();
195    if (!sPppCtrl)
196        sPppCtrl = new PppController();
197    if (!sSoftapCtrl)
198        sSoftapCtrl = new SoftapController();
199    if (!sBandwidthCtrl)
200        sBandwidthCtrl = new BandwidthController();
201    if (!sIdletimerCtrl)
202        sIdletimerCtrl = new IdletimerController();
203    if (!sResolverCtrl)
204        sResolverCtrl = new ResolverController();
205    if (!sFirewallCtrl)
206        sFirewallCtrl = new FirewallController();
207    if (!sInterfaceCtrl)
208        sInterfaceCtrl = new InterfaceController();
209    if (!sClatdCtrl)
210        sClatdCtrl = new ClatdController(sNetCtrl);
211    if (!sStrictCtrl)
212        sStrictCtrl = new StrictController();
213
214    /*
215     * This is the only time we touch top-level chains in iptables; controllers
216     * should only mutate rules inside of their children chains, as created by
217     * the constants above.
218     *
219     * Modules should never ACCEPT packets (except in well-justified cases);
220     * they should instead defer to any remaining modules using RETURN, or
221     * otherwise DROP/REJECT.
222     */
223
224    // Create chains for children modules
225    createChildChains(V4V6, "filter", "INPUT", FILTER_INPUT);
226    createChildChains(V4V6, "filter", "FORWARD", FILTER_FORWARD);
227    createChildChains(V4V6, "filter", "OUTPUT", FILTER_OUTPUT);
228    createChildChains(V4V6, "raw", "PREROUTING", RAW_PREROUTING);
229    createChildChains(V4V6, "mangle", "POSTROUTING", MANGLE_POSTROUTING);
230    createChildChains(V4, "mangle", "FORWARD", MANGLE_FORWARD);
231    createChildChains(V4, "nat", "PREROUTING", NAT_PREROUTING);
232    createChildChains(V4, "nat", "POSTROUTING", NAT_POSTROUTING);
233
234    // Let each module setup their child chains
235    setupOemIptablesHook();
236
237    /* When enabled, DROPs all packets except those matching rules. */
238    sFirewallCtrl->setupIptablesHooks();
239
240    /* Does DROPs in FORWARD by default */
241    sNatCtrl->setupIptablesHooks();
242    /*
243     * Does REJECT in INPUT, OUTPUT. Does counting also.
244     * No DROP/REJECT allowed later in netfilter-flow hook order.
245     */
246    sBandwidthCtrl->setupIptablesHooks();
247    /*
248     * Counts in nat: PREROUTING, POSTROUTING.
249     * No DROP/REJECT allowed later in netfilter-flow hook order.
250     */
251    sIdletimerCtrl->setupIptablesHooks();
252
253    sBandwidthCtrl->enableBandwidthControl(false);
254
255    if (int ret = RouteController::Init(NetworkController::LOCAL_NET_ID)) {
256        ALOGE("failed to initialize RouteController (%s)", strerror(-ret));
257    }
258}
259
260CommandListener::InterfaceCmd::InterfaceCmd() :
261                 NetdCommand("interface") {
262}
263
264int CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
265                                                      int argc, char **argv) {
266    if (argc < 2) {
267        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
268        return 0;
269    }
270
271    if (!strcmp(argv[1], "list")) {
272        DIR *d;
273        struct dirent *de;
274
275        if (!(d = opendir("/sys/class/net"))) {
276            cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true);
277            return 0;
278        }
279
280        while((de = readdir(d))) {
281            if (de->d_name[0] == '.')
282                continue;
283            cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false);
284        }
285        closedir(d);
286        cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false);
287        return 0;
288    } else {
289        /*
290         * These commands take a minimum of 3 arguments
291         */
292        if (argc < 3) {
293            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
294            return 0;
295        }
296
297        if (!strcmp(argv[1], "getcfg")) {
298            struct in_addr addr;
299            int prefixLength;
300            unsigned char hwaddr[6];
301            unsigned flags = 0;
302
303            ifc_init();
304            memset(hwaddr, 0, sizeof(hwaddr));
305
306            if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) {
307                cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
308                ifc_close();
309                return 0;
310            }
311
312            if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) {
313                ALOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno));
314            }
315
316            char *addr_s = strdup(inet_ntoa(addr));
317            const char *updown, *brdcst, *loopbk, *ppp, *running, *multi;
318
319            updown =  (flags & IFF_UP)           ? "up" : "down";
320            brdcst =  (flags & IFF_BROADCAST)    ? " broadcast" : "";
321            loopbk =  (flags & IFF_LOOPBACK)     ? " loopback" : "";
322            ppp =     (flags & IFF_POINTOPOINT)  ? " point-to-point" : "";
323            running = (flags & IFF_RUNNING)      ? " running" : "";
324            multi =   (flags & IFF_MULTICAST)    ? " multicast" : "";
325
326            char *flag_s;
327
328            asprintf(&flag_s, "%s%s%s%s%s%s", updown, brdcst, loopbk, ppp, running, multi);
329
330            char *msg = NULL;
331            asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %d %s",
332                     hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5],
333                     addr_s, prefixLength, flag_s);
334
335            cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false);
336
337            free(addr_s);
338            free(flag_s);
339            free(msg);
340
341            ifc_close();
342            return 0;
343        } else if (!strcmp(argv[1], "setcfg")) {
344            // arglist: iface [addr prefixLength] flags
345            if (argc < 4) {
346                cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
347                return 0;
348            }
349            ALOGD("Setting iface cfg");
350
351            struct in_addr addr;
352            int index = 5;
353
354            ifc_init();
355
356            if (!inet_aton(argv[3], &addr)) {
357                // Handle flags only case
358                index = 3;
359            } else {
360                if (ifc_set_addr(argv[2], addr.s_addr)) {
361                    cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true);
362                    ifc_close();
363                    return 0;
364                }
365
366                // Set prefix length on a non zero address
367                if (addr.s_addr != 0 && ifc_set_prefixLength(argv[2], atoi(argv[4]))) {
368                   cli->sendMsg(ResponseCode::OperationFailed, "Failed to set prefixLength", true);
369                   ifc_close();
370                   return 0;
371               }
372            }
373
374            /* Process flags */
375            for (int i = index; i < argc; i++) {
376                char *flag = argv[i];
377                if (!strcmp(flag, "up")) {
378                    ALOGD("Trying to bring up %s", argv[2]);
379                    if (ifc_up(argv[2])) {
380                        ALOGE("Error upping interface");
381                        cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true);
382                        ifc_close();
383                        return 0;
384                    }
385                } else if (!strcmp(flag, "down")) {
386                    ALOGD("Trying to bring down %s", argv[2]);
387                    if (ifc_down(argv[2])) {
388                        ALOGE("Error downing interface");
389                        cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true);
390                        ifc_close();
391                        return 0;
392                    }
393                } else if (!strcmp(flag, "broadcast")) {
394                    // currently ignored
395                } else if (!strcmp(flag, "multicast")) {
396                    // currently ignored
397                } else if (!strcmp(flag, "running")) {
398                    // currently ignored
399                } else if (!strcmp(flag, "loopback")) {
400                    // currently ignored
401                } else if (!strcmp(flag, "point-to-point")) {
402                    // currently ignored
403                } else {
404                    cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false);
405                    ifc_close();
406                    return 0;
407                }
408            }
409
410            cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false);
411            ifc_close();
412            return 0;
413        } else if (!strcmp(argv[1], "clearaddrs")) {
414            // arglist: iface
415            ALOGD("Clearing all IP addresses on %s", argv[2]);
416
417            ifc_clear_addresses(argv[2]);
418
419            cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false);
420            return 0;
421        } else if (!strcmp(argv[1], "ipv6privacyextensions")) {
422            if (argc != 4) {
423                cli->sendMsg(ResponseCode::CommandSyntaxError,
424                        "Usage: interface ipv6privacyextensions <interface> <enable|disable>",
425                        false);
426                return 0;
427            }
428            int enable = !strncmp(argv[3], "enable", 7);
429            if (sInterfaceCtrl->setIPv6PrivacyExtensions(argv[2], enable) == 0) {
430                cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false);
431            } else {
432                cli->sendMsg(ResponseCode::OperationFailed,
433                        "Failed to set ipv6 privacy extensions", true);
434            }
435            return 0;
436        } else if (!strcmp(argv[1], "ipv6")) {
437            if (argc != 4) {
438                cli->sendMsg(ResponseCode::CommandSyntaxError,
439                        "Usage: interface ipv6 <interface> <enable|disable>",
440                        false);
441                return 0;
442            }
443
444            int enable = !strncmp(argv[3], "enable", 7);
445            if (sInterfaceCtrl->setEnableIPv6(argv[2], enable) == 0) {
446                cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false);
447            } else {
448                cli->sendMsg(ResponseCode::OperationFailed,
449                        "Failed to change IPv6 state", true);
450            }
451            return 0;
452        } else if (!strcmp(argv[1], "ipv6ndoffload")) {
453            if (argc != 4) {
454                cli->sendMsg(ResponseCode::CommandSyntaxError,
455                        "Usage: interface ipv6ndoffload <interface> <enable|disable>",
456                        false);
457                return 0;
458            }
459            int enable = !strncmp(argv[3], "enable", 7);
460            if (sInterfaceCtrl->setIPv6NdOffload(argv[2], enable) == 0) {
461                cli->sendMsg(ResponseCode::CommandOkay, "IPv6 ND offload changed", false);
462            } else {
463                cli->sendMsg(ResponseCode::OperationFailed,
464                        "Failed to change IPv6 ND offload state", true);
465            }
466            return 0;
467        } else if (!strcmp(argv[1], "setmtu")) {
468            if (argc != 4) {
469                cli->sendMsg(ResponseCode::CommandSyntaxError,
470                        "Usage: interface setmtu <interface> <val>", false);
471                return 0;
472            }
473            if (sInterfaceCtrl->setMtu(argv[2], argv[3]) == 0) {
474                cli->sendMsg(ResponseCode::CommandOkay, "MTU changed", false);
475            } else {
476                cli->sendMsg(ResponseCode::OperationFailed,
477                        "Failed to set MTU", true);
478            }
479            return 0;
480        } else {
481            cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
482            return 0;
483        }
484    }
485    return 0;
486}
487
488
489CommandListener::ListTtysCmd::ListTtysCmd() :
490                 NetdCommand("list_ttys") {
491}
492
493int CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
494                                             int /* argc */, char ** /* argv */) {
495    TtyCollection *tlist = sPppCtrl->getTtyList();
496    TtyCollection::iterator it;
497
498    for (it = tlist->begin(); it != tlist->end(); ++it) {
499        cli->sendMsg(ResponseCode::TtyListResult, *it, false);
500    }
501
502    cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
503    return 0;
504}
505
506CommandListener::IpFwdCmd::IpFwdCmd() :
507                 NetdCommand("ipfwd") {
508}
509
510int CommandListener::IpFwdCmd::runCommand(SocketClient *cli, int argc, char **argv) {
511    bool matched = false;
512    bool success;
513
514    if (argc == 2) {
515        //   0     1
516        // ipfwd status
517        if (!strcmp(argv[1], "status")) {
518            char *tmp = NULL;
519
520            asprintf(&tmp, "Forwarding %s",
521                     ((sTetherCtrl->forwardingRequestCount() > 0) ? "enabled" : "disabled"));
522            cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
523            free(tmp);
524            return 0;
525        }
526    } else if (argc == 3) {
527        //  0      1         2
528        // ipfwd enable  <requester>
529        // ipfwd disable <requester>
530        if (!strcmp(argv[1], "enable")) {
531            matched = true;
532            success = sTetherCtrl->enableForwarding(argv[2]);
533        } else if (!strcmp(argv[1], "disable")) {
534            matched = true;
535            success = sTetherCtrl->disableForwarding(argv[2]);
536        }
537    } else if (argc == 4) {
538        //  0      1      2     3
539        // ipfwd  add   wlan0 dummy0
540        // ipfwd remove wlan0 dummy0
541        int ret = 0;
542        if (!strcmp(argv[1], "add")) {
543            matched = true;
544            ret = RouteController::enableTethering(argv[2], argv[3]);
545        } else if (!strcmp(argv[1], "remove")) {
546            matched = true;
547            ret = RouteController::disableTethering(argv[2], argv[3]);
548        }
549        success = (ret == 0);
550        errno = -ret;
551    }
552
553    if (!matched) {
554        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
555        return 0;
556    }
557
558    if (success) {
559        cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
560    } else {
561        cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
562    }
563    return 0;
564}
565
566CommandListener::TetherCmd::TetherCmd() :
567                 NetdCommand("tether") {
568}
569
570int CommandListener::TetherCmd::runCommand(SocketClient *cli,
571                                                      int argc, char **argv) {
572    int rc = 0;
573
574    if (argc < 2) {
575        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
576        return 0;
577    }
578
579    if (!strcmp(argv[1], "stop")) {
580        rc = sTetherCtrl->stopTethering();
581    } else if (!strcmp(argv[1], "status")) {
582        char *tmp = NULL;
583
584        asprintf(&tmp, "Tethering services %s",
585                 (sTetherCtrl->isTetheringStarted() ? "started" : "stopped"));
586        cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
587        free(tmp);
588        return 0;
589    } else if (argc == 3) {
590        if (!strcmp(argv[1], "interface") && !strcmp(argv[2], "list")) {
591            InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList();
592            InterfaceCollection::iterator it;
593            for (it = ilist->begin(); it != ilist->end(); ++it) {
594                cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false);
595            }
596        } else if (!strcmp(argv[1], "dns") && !strcmp(argv[2], "list")) {
597            char netIdStr[UINT32_STRLEN];
598            snprintf(netIdStr, sizeof(netIdStr), "%u", sTetherCtrl->getDnsNetId());
599            cli->sendMsg(ResponseCode::TetherDnsFwdNetIdResult, netIdStr, false);
600
601            NetAddressCollection *dlist = sTetherCtrl->getDnsForwarders();
602            NetAddressCollection::iterator it;
603
604            for (it = dlist->begin(); it != dlist->end(); ++it) {
605                cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, inet_ntoa(*it), false);
606            }
607        }
608    } else {
609        /*
610         * These commands take a minimum of 4 arguments
611         */
612        if (argc < 4) {
613            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
614            return 0;
615        }
616
617        if (!strcmp(argv[1], "start")) {
618            if (argc % 2 == 1) {
619                cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false);
620                return 0;
621            }
622
623            int num_addrs = argc - 2;
624            int arg_index = 2;
625            int array_index = 0;
626            in_addr *addrs = (in_addr *)malloc(sizeof(in_addr) * num_addrs);
627            while (array_index < num_addrs) {
628                if (!inet_aton(argv[arg_index++], &(addrs[array_index++]))) {
629                    cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
630                    free(addrs);
631                    return 0;
632                }
633            }
634            rc = sTetherCtrl->startTethering(num_addrs, addrs);
635            free(addrs);
636        } else if (!strcmp(argv[1], "interface")) {
637            if (!strcmp(argv[2], "add")) {
638                rc = sTetherCtrl->tetherInterface(argv[3]);
639            } else if (!strcmp(argv[2], "remove")) {
640                rc = sTetherCtrl->untetherInterface(argv[3]);
641            /* else if (!strcmp(argv[2], "list")) handled above */
642            } else {
643                cli->sendMsg(ResponseCode::CommandParameterError,
644                             "Unknown tether interface operation", false);
645                return 0;
646            }
647        } else if (!strcmp(argv[1], "dns")) {
648            if (!strcmp(argv[2], "set")) {
649                if (argc < 5) {
650                    cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
651                    return 0;
652                }
653                unsigned netId = stringToNetId(argv[3]);
654                rc = sTetherCtrl->setDnsForwarders(netId, &argv[4], argc - 4);
655            /* else if (!strcmp(argv[2], "list")) handled above */
656            } else {
657                cli->sendMsg(ResponseCode::CommandParameterError,
658                             "Unknown tether interface operation", false);
659                return 0;
660            }
661        } else {
662            cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
663            return 0;
664        }
665    }
666
667    if (!rc) {
668        cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
669    } else {
670        cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
671    }
672
673    return 0;
674}
675
676CommandListener::NatCmd::NatCmd() :
677                 NetdCommand("nat") {
678}
679
680int CommandListener::NatCmd::runCommand(SocketClient *cli,
681                                                      int argc, char **argv) {
682    int rc = 0;
683
684    if (argc < 5) {
685        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
686        return 0;
687    }
688
689    //  0     1       2        3
690    // nat  enable intiface extiface
691    // nat disable intiface extiface
692    if (!strcmp(argv[1], "enable") && argc >= 4) {
693        rc = sNatCtrl->enableNat(argv[2], argv[3]);
694        if(!rc) {
695            /* Ignore ifaces for now. */
696            rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
697        }
698    } else if (!strcmp(argv[1], "disable") && argc >= 4) {
699        /* Ignore ifaces for now. */
700        rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
701        rc |= sNatCtrl->disableNat(argv[2], argv[3]);
702    } else {
703        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
704        return 0;
705    }
706
707    if (!rc) {
708        cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
709    } else {
710        cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
711    }
712
713    return 0;
714}
715
716CommandListener::PppdCmd::PppdCmd() :
717                 NetdCommand("pppd") {
718}
719
720int CommandListener::PppdCmd::runCommand(SocketClient *cli,
721                                                      int argc, char **argv) {
722    int rc = 0;
723
724    if (argc < 3) {
725        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
726        return 0;
727    }
728
729    if (!strcmp(argv[1], "attach")) {
730        struct in_addr l, r, dns1, dns2;
731
732        memset(&dns1, 0, sizeof(struct in_addr));
733        memset(&dns2, 0, sizeof(struct in_addr));
734
735        if (!inet_aton(argv[3], &l)) {
736            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false);
737            return 0;
738        }
739        if (!inet_aton(argv[4], &r)) {
740            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false);
741            return 0;
742        }
743        if ((argc > 3) && (!inet_aton(argv[5], &dns1))) {
744            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false);
745            return 0;
746        }
747        if ((argc > 4) && (!inet_aton(argv[6], &dns2))) {
748            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false);
749            return 0;
750        }
751        rc = sPppCtrl->attachPppd(argv[2], l, r, dns1, dns2);
752    } else if (!strcmp(argv[1], "detach")) {
753        rc = sPppCtrl->detachPppd(argv[2]);
754    } else {
755        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false);
756        return 0;
757    }
758
759    if (!rc) {
760        cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false);
761    } else {
762        cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true);
763    }
764
765    return 0;
766}
767
768CommandListener::SoftapCmd::SoftapCmd() :
769                 NetdCommand("softap") {
770}
771
772int CommandListener::SoftapCmd::runCommand(SocketClient *cli,
773                                        int argc, char **argv) {
774    int rc = ResponseCode::SoftapStatusResult;
775    char *retbuf = NULL;
776
777    if (sSoftapCtrl == NULL) {
778      cli->sendMsg(ResponseCode::ServiceStartFailed, "SoftAP is not available", false);
779      return -1;
780    }
781    if (argc < 2) {
782        cli->sendMsg(ResponseCode::CommandSyntaxError,
783                     "Missing argument in a SoftAP command", false);
784        return 0;
785    }
786
787    if (!strcmp(argv[1], "startap")) {
788        rc = sSoftapCtrl->startSoftap();
789    } else if (!strcmp(argv[1], "stopap")) {
790        rc = sSoftapCtrl->stopSoftap();
791    } else if (!strcmp(argv[1], "fwreload")) {
792        rc = sSoftapCtrl->fwReloadSoftap(argc, argv);
793    } else if (!strcmp(argv[1], "status")) {
794        asprintf(&retbuf, "Softap service %s running",
795                 (sSoftapCtrl->isSoftapStarted() ? "is" : "is not"));
796        cli->sendMsg(rc, retbuf, false);
797        free(retbuf);
798        return 0;
799    } else if (!strcmp(argv[1], "set")) {
800        rc = sSoftapCtrl->setSoftap(argc, argv);
801    } else {
802        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unrecognized SoftAP command", false);
803        return 0;
804    }
805
806    if (rc >= 400 && rc < 600)
807      cli->sendMsg(rc, "SoftAP command has failed", false);
808    else
809      cli->sendMsg(rc, "Ok", false);
810
811    return 0;
812}
813
814CommandListener::ResolverCmd::ResolverCmd() :
815        NetdCommand("resolver") {
816}
817
818int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **margv) {
819    int rc = 0;
820    const char **argv = const_cast<const char **>(margv);
821
822    if (argc < 3) {
823        cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false);
824        return 0;
825    }
826
827    unsigned netId = stringToNetId(argv[2]);
828    // TODO: Consider making NetworkController.isValidNetwork() public
829    // and making that check here.
830
831    if (!strcmp(argv[1], "setnetdns")) {
832        // "resolver setnetdns <netId> <domains> <dns1> <dns2> ..."
833        if (argc >= 5) {
834            rc = sResolverCtrl->setDnsServers(netId, argv[3], &argv[4], argc - 4);
835        } else {
836            cli->sendMsg(ResponseCode::CommandSyntaxError,
837                    "Wrong number of arguments to resolver setnetdns", false);
838            return 0;
839        }
840    } else if (!strcmp(argv[1], "clearnetdns")) { // "resolver clearnetdns <netId>"
841        if (argc == 3) {
842            rc = sResolverCtrl->clearDnsServers(netId);
843        } else {
844            cli->sendMsg(ResponseCode::CommandSyntaxError,
845                    "Wrong number of arguments to resolver clearnetdns", false);
846            return 0;
847        }
848    } else if (!strcmp(argv[1], "flushnet")) { // "resolver flushnet <netId>"
849        if (argc == 3) {
850            rc = sResolverCtrl->flushDnsCache(netId);
851        } else {
852            cli->sendMsg(ResponseCode::CommandSyntaxError,
853                    "Wrong number of arguments to resolver flushnet", false);
854            return 0;
855        }
856    } else {
857        cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false);
858        return 0;
859    }
860
861    if (!rc) {
862        cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false);
863    } else {
864        cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true);
865    }
866
867    return 0;
868}
869
870CommandListener::BandwidthControlCmd::BandwidthControlCmd() :
871    NetdCommand("bandwidth") {
872}
873
874void CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) {
875    char *msg;
876    asprintf(&msg, "Usage: bandwidth %s", usageMsg);
877    cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false);
878    free(msg);
879}
880
881void CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) {
882    if (!cond) {
883        cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
884    } else {
885        cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false);
886    }
887}
888
889void CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) {
890    cli->sendMsg(ResponseCode::OperationFailed, errMsg, false);
891}
892
893int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
894    if (argc < 2) {
895        sendGenericSyntaxError(cli, "<cmds> <args...>");
896        return 0;
897    }
898
899    ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
900
901    if (!strcmp(argv[1], "enable")) {
902        int rc = sBandwidthCtrl->enableBandwidthControl(true);
903        sendGenericOkFail(cli, rc);
904        return 0;
905
906    }
907    if (!strcmp(argv[1], "disable")) {
908        int rc = sBandwidthCtrl->disableBandwidthControl();
909        sendGenericOkFail(cli, rc);
910        return 0;
911
912    }
913    if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
914        if (argc != 3) {
915            sendGenericSyntaxError(cli, "removequota <interface>");
916            return 0;
917        }
918        int rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[2]);
919        sendGenericOkFail(cli, rc);
920        return 0;
921
922    }
923    if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) {
924        int64_t bytes;
925        if (argc != 2) {
926            sendGenericSyntaxError(cli, "getquota");
927            return 0;
928        }
929        int rc = sBandwidthCtrl->getInterfaceSharedQuota(&bytes);
930        if (rc) {
931            sendGenericOpFailed(cli, "Failed to get quota");
932            return 0;
933        }
934
935        char *msg;
936        asprintf(&msg, "%" PRId64, bytes);
937        cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
938        free(msg);
939        return 0;
940
941    }
942    if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) {
943        int64_t bytes;
944        if (argc != 3) {
945            sendGenericSyntaxError(cli, "getiquota <iface>");
946            return 0;
947        }
948
949        int rc = sBandwidthCtrl->getInterfaceQuota(argv[2], &bytes);
950        if (rc) {
951            sendGenericOpFailed(cli, "Failed to get quota");
952            return 0;
953        }
954        char *msg;
955        asprintf(&msg, "%" PRId64, bytes);
956        cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
957        free(msg);
958        return 0;
959
960    }
961    if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
962        if (argc != 4) {
963            sendGenericSyntaxError(cli, "setquota <interface> <bytes>");
964            return 0;
965        }
966        int rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[2], atoll(argv[3]));
967        sendGenericOkFail(cli, rc);
968        return 0;
969    }
970    if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
971        int rc;
972        if (argc < 4) {
973            sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ...");
974            return 0;
975        }
976
977        for (int q = 3; argc >= 4; q++, argc--) {
978            rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[q], atoll(argv[2]));
979            if (rc) {
980                char *msg;
981                asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]);
982                cli->sendMsg(ResponseCode::OperationFailed,
983                             msg, false);
984                free(msg);
985                return 0;
986            }
987        }
988        sendGenericOkFail(cli, rc);
989        return 0;
990
991    }
992    if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) {
993        int rc;
994        if (argc < 3) {
995            sendGenericSyntaxError(cli, "removequotas <interface> ...");
996            return 0;
997        }
998
999        for (int q = 2; argc >= 3; q++, argc--) {
1000            rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[q]);
1001            if (rc) {
1002                char *msg;
1003                asprintf(&msg, "bandwidth removequotas %s failed", argv[q]);
1004                cli->sendMsg(ResponseCode::OperationFailed,
1005                             msg, false);
1006                free(msg);
1007                return 0;
1008            }
1009        }
1010        sendGenericOkFail(cli, rc);
1011        return 0;
1012
1013    }
1014    if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
1015        if (argc != 3) {
1016            sendGenericSyntaxError(cli, "removeiquota <interface>");
1017            return 0;
1018        }
1019        int rc = sBandwidthCtrl->removeInterfaceQuota(argv[2]);
1020        sendGenericOkFail(cli, rc);
1021        return 0;
1022
1023    }
1024    if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
1025        if (argc != 4) {
1026            sendGenericSyntaxError(cli, "setiquota <interface> <bytes>");
1027            return 0;
1028        }
1029        int rc = sBandwidthCtrl->setInterfaceQuota(argv[2], atoll(argv[3]));
1030        sendGenericOkFail(cli, rc);
1031        return 0;
1032
1033    }
1034    if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
1035        if (argc < 3) {
1036            sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ...");
1037            return 0;
1038        }
1039        int rc = sBandwidthCtrl->addNaughtyApps(argc - 2, argv + 2);
1040        sendGenericOkFail(cli, rc);
1041        return 0;
1042
1043
1044    }
1045    if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
1046        if (argc < 3) {
1047            sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ...");
1048            return 0;
1049        }
1050        int rc = sBandwidthCtrl->removeNaughtyApps(argc - 2, argv + 2);
1051        sendGenericOkFail(cli, rc);
1052        return 0;
1053    }
1054    if (!strcmp(argv[1], "happybox")) {
1055        if (argc < 3) {
1056            sendGenericSyntaxError(cli, "happybox (enable | disable)");
1057            return 0;
1058        }
1059        if (!strcmp(argv[2], "enable")) {
1060            int rc = sBandwidthCtrl->enableHappyBox();
1061            sendGenericOkFail(cli, rc);
1062            return 0;
1063
1064        }
1065        if (!strcmp(argv[2], "disable")) {
1066            int rc = sBandwidthCtrl->disableHappyBox();
1067            sendGenericOkFail(cli, rc);
1068            return 0;
1069        }
1070        sendGenericSyntaxError(cli, "happybox (enable | disable)");
1071        return 0;
1072    }
1073    if (!strcmp(argv[1], "addniceapps") || !strcmp(argv[1], "aha")) {
1074        if (argc < 3) {
1075            sendGenericSyntaxError(cli, "addniceapps <appUid> ...");
1076            return 0;
1077        }
1078        int rc = sBandwidthCtrl->addNiceApps(argc - 2, argv + 2);
1079        sendGenericOkFail(cli, rc);
1080        return 0;
1081    }
1082    if (!strcmp(argv[1], "removeniceapps") || !strcmp(argv[1], "rha")) {
1083        if (argc < 3) {
1084            sendGenericSyntaxError(cli, "removeniceapps <appUid> ...");
1085            return 0;
1086        }
1087        int rc = sBandwidthCtrl->removeNiceApps(argc - 2, argv + 2);
1088        sendGenericOkFail(cli, rc);
1089        return 0;
1090    }
1091    if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) {
1092        if (argc != 3) {
1093            sendGenericSyntaxError(cli, "setglobalalert <bytes>");
1094            return 0;
1095        }
1096        int rc = sBandwidthCtrl->setGlobalAlert(atoll(argv[2]));
1097        sendGenericOkFail(cli, rc);
1098        return 0;
1099    }
1100    if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) {
1101        if (argc != 4) {
1102            sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>");
1103            return 0;
1104        }
1105        /* We ignore the interfaces for now. */
1106        int rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
1107        sendGenericOkFail(cli, rc);
1108        return 0;
1109
1110    }
1111    if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
1112        if (argc != 2) {
1113            sendGenericSyntaxError(cli, "removeglobalalert");
1114            return 0;
1115        }
1116        int rc = sBandwidthCtrl->removeGlobalAlert();
1117        sendGenericOkFail(cli, rc);
1118        return 0;
1119
1120    }
1121    if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) {
1122        if (argc != 4) {
1123            sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>");
1124            return 0;
1125        }
1126        /* We ignore the interfaces for now. */
1127        int rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
1128        sendGenericOkFail(cli, rc);
1129        return 0;
1130
1131    }
1132    if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
1133        if (argc != 3) {
1134            sendGenericSyntaxError(cli, "setsharedalert <bytes>");
1135            return 0;
1136        }
1137        int rc = sBandwidthCtrl->setSharedAlert(atoll(argv[2]));
1138        sendGenericOkFail(cli, rc);
1139        return 0;
1140
1141    }
1142    if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) {
1143        if (argc != 2) {
1144            sendGenericSyntaxError(cli, "removesharedalert");
1145            return 0;
1146        }
1147        int rc = sBandwidthCtrl->removeSharedAlert();
1148        sendGenericOkFail(cli, rc);
1149        return 0;
1150
1151    }
1152    if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) {
1153        if (argc != 4) {
1154            sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>");
1155            return 0;
1156        }
1157        int rc = sBandwidthCtrl->setInterfaceAlert(argv[2], atoll(argv[3]));
1158        sendGenericOkFail(cli, rc);
1159        return 0;
1160
1161    }
1162    if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) {
1163        if (argc != 3) {
1164            sendGenericSyntaxError(cli, "removeinterfacealert <interface>");
1165            return 0;
1166        }
1167        int rc = sBandwidthCtrl->removeInterfaceAlert(argv[2]);
1168        sendGenericOkFail(cli, rc);
1169        return 0;
1170
1171    }
1172    if (!strcmp(argv[1], "gettetherstats") || !strcmp(argv[1], "gts")) {
1173        BandwidthController::TetherStats tetherStats;
1174        std::string extraProcessingInfo = "";
1175        if (argc < 2 || argc > 4) {
1176            sendGenericSyntaxError(cli, "gettetherstats [<intInterface> <extInterface>]");
1177            return 0;
1178        }
1179        tetherStats.intIface = argc > 2 ? argv[2] : "";
1180        tetherStats.extIface = argc > 3 ? argv[3] : "";
1181        // No filtering requested and there are no interface pairs to lookup.
1182        if (argc <= 2 && sNatCtrl->ifacePairList.empty()) {
1183            cli->sendMsg(ResponseCode::CommandOkay, "Tethering stats list completed", false);
1184            return 0;
1185        }
1186        int rc = sBandwidthCtrl->getTetherStats(cli, tetherStats, extraProcessingInfo);
1187        if (rc) {
1188                extraProcessingInfo.insert(0, "Failed to get tethering stats.\n");
1189                sendGenericOpFailed(cli, extraProcessingInfo.c_str());
1190                return 0;
1191        }
1192        return 0;
1193
1194    }
1195
1196    cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
1197    return 0;
1198}
1199
1200CommandListener::IdletimerControlCmd::IdletimerControlCmd() :
1201    NetdCommand("idletimer") {
1202}
1203
1204int CommandListener::IdletimerControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
1205  // TODO(ashish): Change the error statements
1206    if (argc < 2) {
1207        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1208        return 0;
1209    }
1210
1211    ALOGV("idletimerctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
1212
1213    if (!strcmp(argv[1], "enable")) {
1214      if (0 != sIdletimerCtrl->enableIdletimerControl()) {
1215        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1216      } else {
1217        cli->sendMsg(ResponseCode::CommandOkay, "Enable success", false);
1218      }
1219      return 0;
1220
1221    }
1222    if (!strcmp(argv[1], "disable")) {
1223      if (0 != sIdletimerCtrl->disableIdletimerControl()) {
1224        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1225      } else {
1226        cli->sendMsg(ResponseCode::CommandOkay, "Disable success", false);
1227      }
1228      return 0;
1229    }
1230    if (!strcmp(argv[1], "add")) {
1231        if (argc != 5) {
1232            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1233            return 0;
1234        }
1235        if(0 != sIdletimerCtrl->addInterfaceIdletimer(
1236                                        argv[2], atoi(argv[3]), argv[4])) {
1237          cli->sendMsg(ResponseCode::OperationFailed, "Failed to add interface", false);
1238        } else {
1239          cli->sendMsg(ResponseCode::CommandOkay,  "Add success", false);
1240        }
1241        return 0;
1242    }
1243    if (!strcmp(argv[1], "remove")) {
1244        if (argc != 5) {
1245            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1246            return 0;
1247        }
1248        // ashish: fixme timeout
1249        if (0 != sIdletimerCtrl->removeInterfaceIdletimer(
1250                                        argv[2], atoi(argv[3]), argv[4])) {
1251          cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove interface", false);
1252        } else {
1253          cli->sendMsg(ResponseCode::CommandOkay, "Remove success", false);
1254        }
1255        return 0;
1256    }
1257
1258    cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown idletimer cmd", false);
1259    return 0;
1260}
1261
1262CommandListener::FirewallCmd::FirewallCmd() :
1263    NetdCommand("firewall") {
1264}
1265
1266int CommandListener::FirewallCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1267    if (!cond) {
1268        cli->sendMsg(ResponseCode::CommandOkay, "Firewall command succeeded", false);
1269    } else {
1270        cli->sendMsg(ResponseCode::OperationFailed, "Firewall command failed", false);
1271    }
1272    return 0;
1273}
1274
1275FirewallRule CommandListener::FirewallCmd::parseRule(const char* arg) {
1276    if (!strcmp(arg, "allow")) {
1277        return ALLOW;
1278    } else if (!strcmp(arg, "deny")) {
1279        return DENY;
1280    } else {
1281        ALOGE("failed to parse uid rule (%s)", arg);
1282        return ALLOW;
1283    }
1284}
1285
1286FirewallType CommandListener::FirewallCmd::parseFirewallType(const char* arg) {
1287    if (!strcmp(arg, "whitelist")) {
1288        return WHITELIST;
1289    } else if (!strcmp(arg, "blacklist")) {
1290        return BLACKLIST;
1291    } else {
1292        ALOGE("failed to parse firewall type (%s)", arg);
1293        return BLACKLIST;
1294    }
1295}
1296
1297ChildChain CommandListener::FirewallCmd::parseChildChain(const char* arg) {
1298    if (!strcmp(arg, "dozable")) {
1299        return DOZABLE;
1300    } else if (!strcmp(arg, "standby")) {
1301        return STANDBY;
1302    } else if (!strcmp(arg, "none")) {
1303        return NONE;
1304    } else {
1305        ALOGE("failed to parse child firewall chain (%s)", arg);
1306        return INVALID_CHAIN;
1307    }
1308}
1309
1310int CommandListener::FirewallCmd::runCommand(SocketClient *cli, int argc,
1311        char **argv) {
1312    if (argc < 2) {
1313        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
1314        return 0;
1315    }
1316
1317    if (!strcmp(argv[1], "enable")) {
1318        if (argc != 3) {
1319            cli->sendMsg(ResponseCode::CommandSyntaxError,
1320                        "Usage: firewall enable <whitelist|blacklist>", false);
1321            return 0;
1322        }
1323        FirewallType firewallType = parseFirewallType(argv[2]);
1324
1325        int res = sFirewallCtrl->enableFirewall(firewallType);
1326        return sendGenericOkFail(cli, res);
1327    }
1328    if (!strcmp(argv[1], "disable")) {
1329        int res = sFirewallCtrl->disableFirewall();
1330        return sendGenericOkFail(cli, res);
1331    }
1332    if (!strcmp(argv[1], "is_enabled")) {
1333        int res = sFirewallCtrl->isFirewallEnabled();
1334        return sendGenericOkFail(cli, res);
1335    }
1336
1337    if (!strcmp(argv[1], "set_interface_rule")) {
1338        if (argc != 4) {
1339            cli->sendMsg(ResponseCode::CommandSyntaxError,
1340                         "Usage: firewall set_interface_rule <rmnet0> <allow|deny>", false);
1341            return 0;
1342        }
1343
1344        const char* iface = argv[2];
1345        FirewallRule rule = parseRule(argv[3]);
1346
1347        int res = sFirewallCtrl->setInterfaceRule(iface, rule);
1348        return sendGenericOkFail(cli, res);
1349    }
1350
1351    if (!strcmp(argv[1], "set_egress_source_rule")) {
1352        if (argc != 4) {
1353            cli->sendMsg(ResponseCode::CommandSyntaxError,
1354                         "Usage: firewall set_egress_source_rule <192.168.0.1> <allow|deny>",
1355                         false);
1356            return 0;
1357        }
1358
1359        const char* addr = argv[2];
1360        FirewallRule rule = parseRule(argv[3]);
1361
1362        int res = sFirewallCtrl->setEgressSourceRule(addr, rule);
1363        return sendGenericOkFail(cli, res);
1364    }
1365
1366    if (!strcmp(argv[1], "set_egress_dest_rule")) {
1367        if (argc != 5) {
1368            cli->sendMsg(ResponseCode::CommandSyntaxError,
1369                         "Usage: firewall set_egress_dest_rule <192.168.0.1> <80> <allow|deny>",
1370                         false);
1371            return 0;
1372        }
1373
1374        const char* addr = argv[2];
1375        int port = atoi(argv[3]);
1376        FirewallRule rule = parseRule(argv[4]);
1377
1378        int res = 0;
1379        res |= sFirewallCtrl->setEgressDestRule(addr, PROTOCOL_TCP, port, rule);
1380        res |= sFirewallCtrl->setEgressDestRule(addr, PROTOCOL_UDP, port, rule);
1381        return sendGenericOkFail(cli, res);
1382    }
1383
1384    if (!strcmp(argv[1], "set_uid_rule")) {
1385        if (argc != 5) {
1386            cli->sendMsg(ResponseCode::CommandSyntaxError,
1387                         "Usage: firewall set_uid_rule <dozable|standby|none> <1000> <allow|deny>",
1388                         false);
1389            return 0;
1390        }
1391
1392        ChildChain childChain = parseChildChain(argv[2]);
1393        if (childChain == INVALID_CHAIN) {
1394            cli->sendMsg(ResponseCode::CommandSyntaxError,
1395                         "Invalid chain name. Valid names are: <dozable|standby|none>",
1396                         false);
1397            return 0;
1398        }
1399        int uid = atoi(argv[3]);
1400        FirewallRule rule = parseRule(argv[4]);
1401        int res = sFirewallCtrl->setUidRule(childChain, uid, rule);
1402        return sendGenericOkFail(cli, res);
1403    }
1404
1405    if (!strcmp(argv[1], "enable_chain")) {
1406        if (argc != 3) {
1407            cli->sendMsg(ResponseCode::CommandSyntaxError,
1408                         "Usage: firewall enable_chain <dozable|standby>",
1409                         false);
1410            return 0;
1411        }
1412
1413        ChildChain childChain = parseChildChain(argv[2]);
1414        int res = sFirewallCtrl->enableChildChains(childChain, true);
1415        return sendGenericOkFail(cli, res);
1416    }
1417
1418    if (!strcmp(argv[1], "disable_chain")) {
1419        if (argc != 3) {
1420            cli->sendMsg(ResponseCode::CommandSyntaxError,
1421                         "Usage: firewall disable_chain <dozable|standby>",
1422                         false);
1423            return 0;
1424        }
1425
1426        ChildChain childChain = parseChildChain(argv[2]);
1427        int res = sFirewallCtrl->enableChildChains(childChain, false);
1428        return sendGenericOkFail(cli, res);
1429    }
1430
1431    cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
1432    return 0;
1433}
1434
1435CommandListener::ClatdCmd::ClatdCmd() : NetdCommand("clatd") {
1436}
1437
1438int CommandListener::ClatdCmd::runCommand(SocketClient *cli, int argc,
1439                                                            char **argv) {
1440    int rc = 0;
1441    if (argc < 3) {
1442        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1443        return 0;
1444    }
1445
1446    if (!strcmp(argv[1], "stop")) {
1447        rc = sClatdCtrl->stopClatd(argv[2]);
1448    } else if (!strcmp(argv[1], "status")) {
1449        char *tmp = NULL;
1450        asprintf(&tmp, "Clatd status: %s", (sClatdCtrl->isClatdStarted(argv[2]) ?
1451                                            "started" : "stopped"));
1452        cli->sendMsg(ResponseCode::ClatdStatusResult, tmp, false);
1453        free(tmp);
1454        return 0;
1455    } else if (!strcmp(argv[1], "start")) {
1456        rc = sClatdCtrl->startClatd(argv[2]);
1457    } else {
1458        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown clatd cmd", false);
1459        return 0;
1460    }
1461
1462    if (!rc) {
1463        cli->sendMsg(ResponseCode::CommandOkay, "Clatd operation succeeded", false);
1464    } else {
1465        cli->sendMsg(ResponseCode::OperationFailed, "Clatd operation failed", false);
1466    }
1467
1468    return 0;
1469}
1470
1471CommandListener::StrictCmd::StrictCmd() :
1472    NetdCommand("strict") {
1473}
1474
1475int CommandListener::StrictCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1476    if (!cond) {
1477        cli->sendMsg(ResponseCode::CommandOkay, "Strict command succeeded", false);
1478    } else {
1479        cli->sendMsg(ResponseCode::OperationFailed, "Strict command failed", false);
1480    }
1481    return 0;
1482}
1483
1484StrictPenalty CommandListener::StrictCmd::parsePenalty(const char* arg) {
1485    if (!strcmp(arg, "reject")) {
1486        return REJECT;
1487    } else if (!strcmp(arg, "log")) {
1488        return LOG;
1489    } else if (!strcmp(arg, "accept")) {
1490        return ACCEPT;
1491    } else {
1492        return INVALID;
1493    }
1494}
1495
1496int CommandListener::StrictCmd::runCommand(SocketClient *cli, int argc,
1497        char **argv) {
1498    if (argc < 2) {
1499        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
1500        return 0;
1501    }
1502
1503    if (!strcmp(argv[1], "enable")) {
1504        int res = sStrictCtrl->enableStrict();
1505        return sendGenericOkFail(cli, res);
1506    }
1507    if (!strcmp(argv[1], "disable")) {
1508        int res = sStrictCtrl->disableStrict();
1509        return sendGenericOkFail(cli, res);
1510    }
1511
1512    if (!strcmp(argv[1], "set_uid_cleartext_policy")) {
1513        if (argc != 4) {
1514            cli->sendMsg(ResponseCode::CommandSyntaxError,
1515                         "Usage: strict set_uid_cleartext_policy <uid> <accept|log|reject>",
1516                         false);
1517            return 0;
1518        }
1519
1520        errno = 0;
1521        unsigned long int uid = strtoul(argv[2], NULL, 0);
1522        if (errno || uid > UID_MAX) {
1523            cli->sendMsg(ResponseCode::CommandSyntaxError, "Invalid UID", false);
1524            return 0;
1525        }
1526
1527        StrictPenalty penalty = parsePenalty(argv[3]);
1528        if (penalty == INVALID) {
1529            cli->sendMsg(ResponseCode::CommandSyntaxError, "Invalid penalty argument", false);
1530            return 0;
1531        }
1532
1533        int res = sStrictCtrl->setUidCleartextPenalty((uid_t) uid, penalty);
1534        return sendGenericOkFail(cli, res);
1535    }
1536
1537    cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
1538    return 0;
1539}
1540
1541CommandListener::NetworkCommand::NetworkCommand() : NetdCommand("network") {
1542}
1543
1544int CommandListener::NetworkCommand::syntaxError(SocketClient* client, const char* message) {
1545    client->sendMsg(ResponseCode::CommandSyntaxError, message, false);
1546    return 0;
1547}
1548
1549int CommandListener::NetworkCommand::operationError(SocketClient* client, const char* message,
1550                                                    int ret) {
1551    errno = -ret;
1552    client->sendMsg(ResponseCode::OperationFailed, message, true);
1553    return 0;
1554}
1555
1556int CommandListener::NetworkCommand::success(SocketClient* client) {
1557    client->sendMsg(ResponseCode::CommandOkay, "success", false);
1558    return 0;
1559}
1560
1561int CommandListener::NetworkCommand::runCommand(SocketClient* client, int argc, char** argv) {
1562    if (argc < 2) {
1563        return syntaxError(client, "Missing argument");
1564    }
1565
1566    //    0      1      2      3      4       5         6            7           8
1567    // network route [legacy <uid>]  add   <netId> <interface> <destination> [nexthop]
1568    // network route [legacy <uid>] remove <netId> <interface> <destination> [nexthop]
1569    //
1570    // nexthop may be either an IPv4/IPv6 address or one of "unreachable" or "throw".
1571    if (!strcmp(argv[1], "route")) {
1572        if (argc < 6 || argc > 9) {
1573            return syntaxError(client, "Incorrect number of arguments");
1574        }
1575
1576        int nextArg = 2;
1577        bool legacy = false;
1578        uid_t uid = 0;
1579        if (!strcmp(argv[nextArg], "legacy")) {
1580            ++nextArg;
1581            legacy = true;
1582            uid = strtoul(argv[nextArg++], NULL, 0);
1583        }
1584
1585        bool add = false;
1586        if (!strcmp(argv[nextArg], "add")) {
1587            add = true;
1588        } else if (strcmp(argv[nextArg], "remove")) {
1589            return syntaxError(client, "Unknown argument");
1590        }
1591        ++nextArg;
1592
1593        if (argc < nextArg + 3 || argc > nextArg + 4) {
1594            return syntaxError(client, "Incorrect number of arguments");
1595        }
1596
1597        unsigned netId = stringToNetId(argv[nextArg++]);
1598        const char* interface = argv[nextArg++];
1599        const char* destination = argv[nextArg++];
1600        const char* nexthop = argc > nextArg ? argv[nextArg] : NULL;
1601
1602        int ret;
1603        if (add) {
1604            ret = sNetCtrl->addRoute(netId, interface, destination, nexthop, legacy, uid);
1605        } else {
1606            ret = sNetCtrl->removeRoute(netId, interface, destination, nexthop, legacy, uid);
1607        }
1608        if (ret) {
1609            return operationError(client, add ? "addRoute() failed" : "removeRoute() failed", ret);
1610        }
1611
1612        return success(client);
1613    }
1614
1615    //    0        1       2       3         4
1616    // network interface  add   <netId> <interface>
1617    // network interface remove <netId> <interface>
1618    if (!strcmp(argv[1], "interface")) {
1619        if (argc != 5) {
1620            return syntaxError(client, "Missing argument");
1621        }
1622        unsigned netId = stringToNetId(argv[3]);
1623        if (!strcmp(argv[2], "add")) {
1624            if (int ret = sNetCtrl->addInterfaceToNetwork(netId, argv[4])) {
1625                return operationError(client, "addInterfaceToNetwork() failed", ret);
1626            }
1627        } else if (!strcmp(argv[2], "remove")) {
1628            if (int ret = sNetCtrl->removeInterfaceFromNetwork(netId, argv[4])) {
1629                return operationError(client, "removeInterfaceFromNetwork() failed", ret);
1630            }
1631        } else {
1632            return syntaxError(client, "Unknown argument");
1633        }
1634        return success(client);
1635    }
1636
1637    //    0      1       2         3
1638    // network create <netId> [permission]
1639    //
1640    //    0      1       2     3     4        5
1641    // network create <netId> vpn <hasDns> <secure>
1642    if (!strcmp(argv[1], "create")) {
1643        if (argc < 3) {
1644            return syntaxError(client, "Missing argument");
1645        }
1646        unsigned netId = stringToNetId(argv[2]);
1647        if (argc == 6 && !strcmp(argv[3], "vpn")) {
1648            bool hasDns = atoi(argv[4]);
1649            bool secure = atoi(argv[5]);
1650            if (int ret = sNetCtrl->createVirtualNetwork(netId, hasDns, secure)) {
1651                return operationError(client, "createVirtualNetwork() failed", ret);
1652            }
1653        } else if (argc > 4) {
1654            return syntaxError(client, "Unknown trailing argument(s)");
1655        } else {
1656            Permission permission = PERMISSION_NONE;
1657            if (argc == 4) {
1658                permission = stringToPermission(argv[3]);
1659                if (permission == PERMISSION_NONE) {
1660                    return syntaxError(client, "Unknown permission");
1661                }
1662            }
1663            if (int ret = sNetCtrl->createPhysicalNetwork(netId, permission)) {
1664                return operationError(client, "createPhysicalNetwork() failed", ret);
1665            }
1666        }
1667        return success(client);
1668    }
1669
1670    //    0       1       2
1671    // network destroy <netId>
1672    if (!strcmp(argv[1], "destroy")) {
1673        if (argc != 3) {
1674            return syntaxError(client, "Incorrect number of arguments");
1675        }
1676        unsigned netId = stringToNetId(argv[2]);
1677        if (int ret = sNetCtrl->destroyNetwork(netId)) {
1678            return operationError(client, "destroyNetwork() failed", ret);
1679        }
1680        return success(client);
1681    }
1682
1683    //    0       1      2      3
1684    // network default  set  <netId>
1685    // network default clear
1686    if (!strcmp(argv[1], "default")) {
1687        if (argc < 3) {
1688            return syntaxError(client, "Missing argument");
1689        }
1690        unsigned netId = NETID_UNSET;
1691        if (!strcmp(argv[2], "set")) {
1692            if (argc < 4) {
1693                return syntaxError(client, "Missing netId");
1694            }
1695            netId = stringToNetId(argv[3]);
1696        } else if (strcmp(argv[2], "clear")) {
1697            return syntaxError(client, "Unknown argument");
1698        }
1699        if (int ret = sNetCtrl->setDefaultNetwork(netId)) {
1700            return operationError(client, "setDefaultNetwork() failed", ret);
1701        }
1702        return success(client);
1703    }
1704
1705    //    0        1         2      3        4          5
1706    // network permission   user   set  <permission>  <uid> ...
1707    // network permission   user  clear    <uid> ...
1708    // network permission network  set  <permission> <netId> ...
1709    // network permission network clear   <netId> ...
1710    if (!strcmp(argv[1], "permission")) {
1711        if (argc < 5) {
1712            return syntaxError(client, "Missing argument");
1713        }
1714        int nextArg = 4;
1715        Permission permission = PERMISSION_NONE;
1716        if (!strcmp(argv[3], "set")) {
1717            permission = stringToPermission(argv[4]);
1718            if (permission == PERMISSION_NONE) {
1719                return syntaxError(client, "Unknown permission");
1720            }
1721            nextArg = 5;
1722        } else if (strcmp(argv[3], "clear")) {
1723            return syntaxError(client, "Unknown argument");
1724        }
1725        if (nextArg == argc) {
1726            return syntaxError(client, "Missing id");
1727        }
1728
1729        bool userPermissions = !strcmp(argv[2], "user");
1730        bool networkPermissions = !strcmp(argv[2], "network");
1731        if (!userPermissions && !networkPermissions) {
1732            return syntaxError(client, "Unknown argument");
1733        }
1734
1735        std::vector<unsigned> ids;
1736        for (; nextArg < argc; ++nextArg) {
1737            if (userPermissions) {
1738                char* endPtr;
1739                unsigned id = strtoul(argv[nextArg], &endPtr, 0);
1740                if (!*argv[nextArg] || *endPtr) {
1741                    return syntaxError(client, "Invalid id");
1742                }
1743                ids.push_back(id);
1744            } else {
1745                // networkPermissions
1746                ids.push_back(stringToNetId(argv[nextArg]));
1747            }
1748        }
1749        if (userPermissions) {
1750            sNetCtrl->setPermissionForUsers(permission, ids);
1751        } else {
1752            // networkPermissions
1753            if (int ret = sNetCtrl->setPermissionForNetworks(permission, ids)) {
1754                return operationError(client, "setPermissionForNetworks() failed", ret);
1755            }
1756        }
1757
1758        return success(client);
1759    }
1760
1761    //    0      1     2       3           4
1762    // network users  add   <netId> [<uid>[-<uid>]] ...
1763    // network users remove <netId> [<uid>[-<uid>]] ...
1764    if (!strcmp(argv[1], "users")) {
1765        if (argc < 4) {
1766            return syntaxError(client, "Missing argument");
1767        }
1768        unsigned netId = stringToNetId(argv[3]);
1769        UidRanges uidRanges;
1770        if (!uidRanges.parseFrom(argc - 4, argv + 4)) {
1771            return syntaxError(client, "Invalid UIDs");
1772        }
1773        if (!strcmp(argv[2], "add")) {
1774            if (int ret = sNetCtrl->addUsersToNetwork(netId, uidRanges)) {
1775                return operationError(client, "addUsersToNetwork() failed", ret);
1776            }
1777        } else if (!strcmp(argv[2], "remove")) {
1778            if (int ret = sNetCtrl->removeUsersFromNetwork(netId, uidRanges)) {
1779                return operationError(client, "removeUsersFromNetwork() failed", ret);
1780            }
1781        } else {
1782            return syntaxError(client, "Unknown argument");
1783        }
1784        return success(client);
1785    }
1786
1787    //    0       1      2     3
1788    // network protect allow <uid> ...
1789    // network protect  deny <uid> ...
1790    if (!strcmp(argv[1], "protect")) {
1791        if (argc < 4) {
1792            return syntaxError(client, "Missing argument");
1793        }
1794        std::vector<uid_t> uids;
1795        for (int i = 3; i < argc; ++i) {
1796            uids.push_back(strtoul(argv[i], NULL, 0));
1797        }
1798        if (!strcmp(argv[2], "allow")) {
1799            sNetCtrl->allowProtect(uids);
1800        } else if (!strcmp(argv[2], "deny")) {
1801            sNetCtrl->denyProtect(uids);
1802        } else {
1803            return syntaxError(client, "Unknown argument");
1804        }
1805        return success(client);
1806    }
1807
1808    return syntaxError(client, "Unknown argument");
1809}
1810