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