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