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