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