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 "InterfaceController.h"
46#include "oem_iptables_hook.h"
47#include "NetdConstants.h"
48#include "FirewallController.h"
49#include "RouteController.h"
50#include "UidRanges.h"
51
52#include <string>
53#include <vector>
54
55using android::net::gCtls;
56
57namespace {
58
59const unsigned NUM_OEM_IDS = NetworkController::MAX_OEM_ID - NetworkController::MIN_OEM_ID + 1;
60
61Permission stringToPermission(const char* arg) {
62    if (!strcmp(arg, "NETWORK")) {
63        return PERMISSION_NETWORK;
64    }
65    if (!strcmp(arg, "SYSTEM")) {
66        return PERMISSION_SYSTEM;
67    }
68    return PERMISSION_NONE;
69}
70
71unsigned stringToNetId(const char* arg) {
72    if (!strcmp(arg, "local")) {
73        return NetworkController::LOCAL_NET_ID;
74    }
75    // OEM NetIds are "oem1", "oem2", .., "oem50".
76    if (!strncmp(arg, "oem", 3)) {
77        unsigned n = strtoul(arg + 3, NULL, 0);
78        if (1 <= n && n <= NUM_OEM_IDS) {
79            return NetworkController::MIN_OEM_ID + n;
80        }
81        return NETID_UNSET;
82    }
83    // strtoul() returns 0 on errors, which is fine because 0 is an invalid netId.
84    return strtoul(arg, NULL, 0);
85}
86
87class LockingFrameworkCommand : public FrameworkCommand {
88public:
89    LockingFrameworkCommand(FrameworkCommand *wrappedCmd, android::RWLock& lock) :
90            FrameworkCommand(wrappedCmd->getCommand()),
91            mWrappedCmd(wrappedCmd),
92            mLock(lock) {}
93
94    int runCommand(SocketClient *c, int argc, char **argv) {
95        android::RWLock::AutoWLock lock(mLock);
96        return mWrappedCmd->runCommand(c, argc, argv);
97    }
98
99private:
100    FrameworkCommand *mWrappedCmd;
101    android::RWLock& mLock;
102};
103
104
105}  // namespace
106
107/**
108 * List of module chains to be created, along with explicit ordering. ORDERING
109 * IS CRITICAL, AND SHOULD BE TRIPLE-CHECKED WITH EACH CHANGE.
110 */
111static const char* FILTER_INPUT[] = {
112        // Bandwidth should always be early in input chain, to make sure we
113        // correctly count incoming traffic against data plan.
114        BandwidthController::LOCAL_INPUT,
115        FirewallController::LOCAL_INPUT,
116        NULL,
117};
118
119static const char* FILTER_FORWARD[] = {
120        OEM_IPTABLES_FILTER_FORWARD,
121        FirewallController::LOCAL_FORWARD,
122        BandwidthController::LOCAL_FORWARD,
123        NatController::LOCAL_FORWARD,
124        NULL,
125};
126
127static const char* FILTER_OUTPUT[] = {
128        OEM_IPTABLES_FILTER_OUTPUT,
129        FirewallController::LOCAL_OUTPUT,
130        StrictController::LOCAL_OUTPUT,
131        BandwidthController::LOCAL_OUTPUT,
132        NULL,
133};
134
135static const char* RAW_PREROUTING[] = {
136        BandwidthController::LOCAL_RAW_PREROUTING,
137        IdletimerController::LOCAL_RAW_PREROUTING,
138        NatController::LOCAL_RAW_PREROUTING,
139        NULL,
140};
141
142static const char* MANGLE_POSTROUTING[] = {
143        BandwidthController::LOCAL_MANGLE_POSTROUTING,
144        IdletimerController::LOCAL_MANGLE_POSTROUTING,
145        NULL,
146};
147
148static const char* MANGLE_FORWARD[] = {
149        NatController::LOCAL_MANGLE_FORWARD,
150        NULL,
151};
152
153static const char* NAT_PREROUTING[] = {
154        OEM_IPTABLES_NAT_PREROUTING,
155        NULL,
156};
157
158static const char* NAT_POSTROUTING[] = {
159        NatController::LOCAL_NAT_POSTROUTING,
160        NULL,
161};
162
163static void createChildChains(IptablesTarget target, const char* table, const char* parentChain,
164        const char** childChains) {
165    const char** childChain = childChains;
166    do {
167        // Order is important:
168        // -D to delete any pre-existing jump rule (removes references
169        //    that would prevent -X from working)
170        // -F to flush any existing chain
171        // -X to delete any existing chain
172        // -N to create the chain
173        // -A to append the chain to parent
174
175        execIptablesSilently(target, "-t", table, "-D", parentChain, "-j", *childChain, NULL);
176        execIptablesSilently(target, "-t", table, "-F", *childChain, NULL);
177        execIptablesSilently(target, "-t", table, "-X", *childChain, NULL);
178        execIptables(target, "-t", table, "-N", *childChain, NULL);
179        execIptables(target, "-t", table, "-A", parentChain, "-j", *childChain, NULL);
180    } while (*(++childChain) != NULL);
181}
182
183void CommandListener::registerLockingCmd(FrameworkCommand *cmd, android::RWLock& lock) {
184    registerCmd(new LockingFrameworkCommand(cmd, lock));
185}
186
187CommandListener::CommandListener() :
188                 FrameworkListener("netd", true) {
189    registerLockingCmd(new InterfaceCmd());
190    registerLockingCmd(new IpFwdCmd());
191    registerLockingCmd(new TetherCmd());
192    registerLockingCmd(new NatCmd());
193    registerLockingCmd(new ListTtysCmd());
194    registerLockingCmd(new PppdCmd());
195    registerLockingCmd(new SoftapCmd());
196    registerLockingCmd(new BandwidthControlCmd(), gCtls->bandwidthCtrl.lock);
197    registerLockingCmd(new IdletimerControlCmd());
198    registerLockingCmd(new ResolverCmd());
199    registerLockingCmd(new FirewallCmd(), gCtls->firewallCtrl.lock);
200    registerLockingCmd(new ClatdCmd());
201    registerLockingCmd(new NetworkCommand());
202    registerLockingCmd(new StrictCmd());
203
204    /*
205     * This is the only time we touch top-level chains in iptables; controllers
206     * should only mutate rules inside of their children chains, as created by
207     * the constants above.
208     *
209     * Modules should never ACCEPT packets (except in well-justified cases);
210     * they should instead defer to any remaining modules using RETURN, or
211     * otherwise DROP/REJECT.
212     */
213
214    // Create chains for children modules
215    createChildChains(V4V6, "filter", "INPUT", FILTER_INPUT);
216    createChildChains(V4V6, "filter", "FORWARD", FILTER_FORWARD);
217    createChildChains(V4V6, "filter", "OUTPUT", FILTER_OUTPUT);
218    createChildChains(V4V6, "raw", "PREROUTING", RAW_PREROUTING);
219    createChildChains(V4V6, "mangle", "POSTROUTING", MANGLE_POSTROUTING);
220    createChildChains(V4V6, "mangle", "FORWARD", MANGLE_FORWARD);
221    createChildChains(V4, "nat", "PREROUTING", NAT_PREROUTING);
222    createChildChains(V4, "nat", "POSTROUTING", NAT_POSTROUTING);
223
224    // Let each module setup their child chains
225    setupOemIptablesHook();
226
227    /* When enabled, DROPs all packets except those matching rules. */
228    gCtls->firewallCtrl.setupIptablesHooks();
229
230    /* Does DROPs in FORWARD by default */
231    gCtls->natCtrl.setupIptablesHooks();
232    /*
233     * Does REJECT in INPUT, OUTPUT. Does counting also.
234     * No DROP/REJECT allowed later in netfilter-flow hook order.
235     */
236    gCtls->bandwidthCtrl.setupIptablesHooks();
237    /*
238     * Counts in nat: PREROUTING, POSTROUTING.
239     * No DROP/REJECT allowed later in netfilter-flow hook order.
240     */
241    gCtls->idletimerCtrl.setupIptablesHooks();
242
243    gCtls->bandwidthCtrl.enableBandwidthControl(false);
244
245    if (int ret = RouteController::Init(NetworkController::LOCAL_NET_ID)) {
246        ALOGE("failed to initialize RouteController (%s)", strerror(-ret));
247    }
248}
249
250CommandListener::InterfaceCmd::InterfaceCmd() :
251                 NetdCommand("interface") {
252}
253
254int CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
255                                                      int argc, char **argv) {
256    if (argc < 2) {
257        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
258        return 0;
259    }
260
261    if (!strcmp(argv[1], "list")) {
262        DIR *d;
263        struct dirent *de;
264
265        if (!(d = opendir("/sys/class/net"))) {
266            cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true);
267            return 0;
268        }
269
270        while((de = readdir(d))) {
271            if (de->d_name[0] == '.')
272                continue;
273            cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false);
274        }
275        closedir(d);
276        cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false);
277        return 0;
278    } else {
279        /*
280         * These commands take a minimum of 3 arguments
281         */
282        if (argc < 3) {
283            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
284            return 0;
285        }
286
287        if (!strcmp(argv[1], "getcfg")) {
288            struct in_addr addr;
289            int prefixLength;
290            unsigned char hwaddr[6];
291            unsigned flags = 0;
292
293            ifc_init();
294            memset(hwaddr, 0, sizeof(hwaddr));
295
296            if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) {
297                cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
298                ifc_close();
299                return 0;
300            }
301
302            if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) {
303                ALOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno));
304            }
305
306            char *addr_s = strdup(inet_ntoa(addr));
307            const char *updown, *brdcst, *loopbk, *ppp, *running, *multi;
308
309            updown =  (flags & IFF_UP)           ? "up" : "down";
310            brdcst =  (flags & IFF_BROADCAST)    ? " broadcast" : "";
311            loopbk =  (flags & IFF_LOOPBACK)     ? " loopback" : "";
312            ppp =     (flags & IFF_POINTOPOINT)  ? " point-to-point" : "";
313            running = (flags & IFF_RUNNING)      ? " running" : "";
314            multi =   (flags & IFF_MULTICAST)    ? " multicast" : "";
315
316            char *flag_s;
317
318            asprintf(&flag_s, "%s%s%s%s%s%s", updown, brdcst, loopbk, ppp, running, multi);
319
320            char *msg = NULL;
321            asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %d %s",
322                     hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5],
323                     addr_s, prefixLength, flag_s);
324
325            cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false);
326
327            free(addr_s);
328            free(flag_s);
329            free(msg);
330
331            ifc_close();
332            return 0;
333        } else if (!strcmp(argv[1], "setcfg")) {
334            // arglist: iface [addr prefixLength] flags
335            if (argc < 4) {
336                cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
337                return 0;
338            }
339            ALOGD("Setting iface cfg");
340
341            struct in_addr addr;
342            int index = 5;
343
344            ifc_init();
345
346            if (!inet_aton(argv[3], &addr)) {
347                // Handle flags only case
348                index = 3;
349            } else {
350                if (ifc_set_addr(argv[2], 0)) {
351                    cli->sendMsg(ResponseCode::OperationFailed, "Failed to clear address", true);
352                    ifc_close();
353                    return 0;
354                }
355                if (addr.s_addr != 0) {
356                    if (ifc_add_address(argv[2], argv[3], atoi(argv[4]))) {
357                        cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true);
358                        ifc_close();
359                        return 0;
360                    }
361                }
362            }
363
364            /* Process flags */
365            for (int i = index; i < argc; i++) {
366                char *flag = argv[i];
367                if (!strcmp(flag, "up")) {
368                    ALOGD("Trying to bring up %s", argv[2]);
369                    if (ifc_up(argv[2])) {
370                        ALOGE("Error upping interface");
371                        cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true);
372                        ifc_close();
373                        return 0;
374                    }
375                } else if (!strcmp(flag, "down")) {
376                    ALOGD("Trying to bring down %s", argv[2]);
377                    if (ifc_down(argv[2])) {
378                        ALOGE("Error downing interface");
379                        cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true);
380                        ifc_close();
381                        return 0;
382                    }
383                } else if (!strcmp(flag, "broadcast")) {
384                    // currently ignored
385                } else if (!strcmp(flag, "multicast")) {
386                    // currently ignored
387                } else if (!strcmp(flag, "running")) {
388                    // currently ignored
389                } else if (!strcmp(flag, "loopback")) {
390                    // currently ignored
391                } else if (!strcmp(flag, "point-to-point")) {
392                    // currently ignored
393                } else {
394                    cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false);
395                    ifc_close();
396                    return 0;
397                }
398            }
399
400            cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false);
401            ifc_close();
402            return 0;
403        } else if (!strcmp(argv[1], "clearaddrs")) {
404            // arglist: iface
405            ALOGD("Clearing all IP addresses on %s", argv[2]);
406
407            ifc_clear_addresses(argv[2]);
408
409            cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false);
410            return 0;
411        } else if (!strcmp(argv[1], "ipv6privacyextensions")) {
412            if (argc != 4) {
413                cli->sendMsg(ResponseCode::CommandSyntaxError,
414                        "Usage: interface ipv6privacyextensions <interface> <enable|disable>",
415                        false);
416                return 0;
417            }
418            int enable = !strncmp(argv[3], "enable", 7);
419            if (InterfaceController::setIPv6PrivacyExtensions(argv[2], enable) == 0) {
420                cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false);
421            } else {
422                cli->sendMsg(ResponseCode::OperationFailed,
423                        "Failed to set ipv6 privacy extensions", true);
424            }
425            return 0;
426        } else if (!strcmp(argv[1], "ipv6")) {
427            if (argc != 4) {
428                cli->sendMsg(ResponseCode::CommandSyntaxError,
429                        "Usage: interface ipv6 <interface> <enable|disable>",
430                        false);
431                return 0;
432            }
433
434            int enable = !strncmp(argv[3], "enable", 7);
435            if (InterfaceController::setEnableIPv6(argv[2], enable) == 0) {
436                cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false);
437            } else {
438                cli->sendMsg(ResponseCode::OperationFailed,
439                        "Failed to change IPv6 state", true);
440            }
441            return 0;
442        } else if (!strcmp(argv[1], "ipv6ndoffload")) {
443            if (argc != 4) {
444                cli->sendMsg(ResponseCode::CommandSyntaxError,
445                        "Usage: interface ipv6ndoffload <interface> <enable|disable>",
446                        false);
447                return 0;
448            }
449            int enable = !strncmp(argv[3], "enable", 7);
450            if (InterfaceController::setIPv6NdOffload(argv[2], enable) == 0) {
451                cli->sendMsg(ResponseCode::CommandOkay, "IPv6 ND offload changed", false);
452            } else {
453                cli->sendMsg(ResponseCode::OperationFailed,
454                        "Failed to change IPv6 ND offload state", true);
455            }
456            return 0;
457        } else if (!strcmp(argv[1], "setmtu")) {
458            if (argc != 4) {
459                cli->sendMsg(ResponseCode::CommandSyntaxError,
460                        "Usage: interface setmtu <interface> <val>", false);
461                return 0;
462            }
463            if (InterfaceController::setMtu(argv[2], argv[3]) == 0) {
464                cli->sendMsg(ResponseCode::CommandOkay, "MTU changed", false);
465            } else {
466                cli->sendMsg(ResponseCode::OperationFailed,
467                        "Failed to set MTU", true);
468            }
469            return 0;
470        } else {
471            cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
472            return 0;
473        }
474    }
475    return 0;
476}
477
478
479CommandListener::ListTtysCmd::ListTtysCmd() :
480                 NetdCommand("list_ttys") {
481}
482
483int CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
484                                             int /* argc */, char ** /* argv */) {
485    TtyCollection *tlist = gCtls->pppCtrl.getTtyList();
486    TtyCollection::iterator it;
487
488    for (it = tlist->begin(); it != tlist->end(); ++it) {
489        cli->sendMsg(ResponseCode::TtyListResult, *it, false);
490    }
491
492    cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
493    return 0;
494}
495
496CommandListener::IpFwdCmd::IpFwdCmd() :
497                 NetdCommand("ipfwd") {
498}
499
500int CommandListener::IpFwdCmd::runCommand(SocketClient *cli, int argc, char **argv) {
501    bool matched = false;
502    bool success;
503
504    if (argc == 2) {
505        //   0     1
506        // ipfwd status
507        if (!strcmp(argv[1], "status")) {
508            char *tmp = NULL;
509
510            asprintf(&tmp, "Forwarding %s",
511                     ((gCtls->tetherCtrl.forwardingRequestCount() > 0) ? "enabled" : "disabled"));
512            cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
513            free(tmp);
514            return 0;
515        }
516    } else if (argc == 3) {
517        //  0      1         2
518        // ipfwd enable  <requester>
519        // ipfwd disable <requester>
520        if (!strcmp(argv[1], "enable")) {
521            matched = true;
522            success = gCtls->tetherCtrl.enableForwarding(argv[2]);
523        } else if (!strcmp(argv[1], "disable")) {
524            matched = true;
525            success = gCtls->tetherCtrl.disableForwarding(argv[2]);
526        }
527    } else if (argc == 4) {
528        //  0      1      2     3
529        // ipfwd  add   wlan0 dummy0
530        // ipfwd remove wlan0 dummy0
531        int ret = 0;
532        if (!strcmp(argv[1], "add")) {
533            matched = true;
534            ret = RouteController::enableTethering(argv[2], argv[3]);
535        } else if (!strcmp(argv[1], "remove")) {
536            matched = true;
537            ret = RouteController::disableTethering(argv[2], argv[3]);
538        }
539        success = (ret == 0);
540        errno = -ret;
541    }
542
543    if (!matched) {
544        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
545        return 0;
546    }
547
548    if (success) {
549        cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
550    } else {
551        cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
552    }
553    return 0;
554}
555
556CommandListener::TetherCmd::TetherCmd() :
557                 NetdCommand("tether") {
558}
559
560int CommandListener::TetherCmd::runCommand(SocketClient *cli,
561                                                      int argc, char **argv) {
562    int rc = 0;
563
564    if (argc < 2) {
565        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
566        return 0;
567    }
568
569    if (!strcmp(argv[1], "stop")) {
570        rc = gCtls->tetherCtrl.stopTethering();
571    } else if (!strcmp(argv[1], "status")) {
572        char *tmp = NULL;
573
574        asprintf(&tmp, "Tethering services %s",
575                 (gCtls->tetherCtrl.isTetheringStarted() ? "started" : "stopped"));
576        cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
577        free(tmp);
578        return 0;
579    } else if (argc == 3) {
580        if (!strcmp(argv[1], "interface") && !strcmp(argv[2], "list")) {
581            for (const auto &ifname : gCtls->tetherCtrl.getTetheredInterfaceList()) {
582                cli->sendMsg(ResponseCode::TetherInterfaceListResult, ifname.c_str(), 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