OSDN Git Service

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