OSDN Git Service

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