OSDN Git Service

Initial netd binder interface.
[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     registerLockingCmd(new InterfaceCmd());
175     registerLockingCmd(new IpFwdCmd());
176     registerLockingCmd(new TetherCmd());
177     registerLockingCmd(new NatCmd());
178     registerLockingCmd(new ListTtysCmd());
179     registerLockingCmd(new PppdCmd());
180     registerLockingCmd(new SoftapCmd());
181     registerLockingCmd(new BandwidthControlCmd());
182     registerLockingCmd(new IdletimerControlCmd());
183     registerLockingCmd(new ResolverCmd());
184     registerLockingCmd(new FirewallCmd());
185     registerLockingCmd(new ClatdCmd());
186     registerLockingCmd(new NetworkCommand());
187     registerLockingCmd(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], 0)) {
361                     cli->sendMsg(ResponseCode::OperationFailed, "Failed to clear address", true);
362                     ifc_close();
363                     return 0;
364                 }
365                 if (addr.s_addr != 0) {
366                     if (ifc_add_address(argv[2], argv[3], atoi(argv[4]))) {
367                         cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true);
368                         ifc_close();
369                         return 0;
370                     }
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 set 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, int argc, char **argv) {
511     bool matched = false;
512     bool success;
513
514     if (argc == 2) {
515         //   0     1
516         // ipfwd status
517         if (!strcmp(argv[1], "status")) {
518             char *tmp = NULL;
519
520             asprintf(&tmp, "Forwarding %s",
521                      ((sTetherCtrl->forwardingRequestCount() > 0) ? "enabled" : "disabled"));
522             cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
523             free(tmp);
524             return 0;
525         }
526     } else if (argc == 3) {
527         //  0      1         2
528         // ipfwd enable  <requester>
529         // ipfwd disable <requester>
530         if (!strcmp(argv[1], "enable")) {
531             matched = true;
532             success = sTetherCtrl->enableForwarding(argv[2]);
533         } else if (!strcmp(argv[1], "disable")) {
534             matched = true;
535             success = sTetherCtrl->disableForwarding(argv[2]);
536         }
537     } else if (argc == 4) {
538         //  0      1      2     3
539         // ipfwd  add   wlan0 dummy0
540         // ipfwd remove wlan0 dummy0
541         int ret = 0;
542         if (!strcmp(argv[1], "add")) {
543             matched = true;
544             ret = RouteController::enableTethering(argv[2], argv[3]);
545         } else if (!strcmp(argv[1], "remove")) {
546             matched = true;
547             ret = RouteController::disableTethering(argv[2], argv[3]);
548         }
549         success = (ret == 0);
550         errno = -ret;
551     }
552
553     if (!matched) {
554         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
555         return 0;
556     }
557
558     if (success) {
559         cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
560     } else {
561         cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
562     }
563     return 0;
564 }
565
566 CommandListener::TetherCmd::TetherCmd() :
567                  NetdCommand("tether") {
568 }
569
570 int CommandListener::TetherCmd::runCommand(SocketClient *cli,
571                                                       int argc, char **argv) {
572     int rc = 0;
573
574     if (argc < 2) {
575         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
576         return 0;
577     }
578
579     if (!strcmp(argv[1], "stop")) {
580         rc = sTetherCtrl->stopTethering();
581     } else if (!strcmp(argv[1], "status")) {
582         char *tmp = NULL;
583
584         asprintf(&tmp, "Tethering services %s",
585                  (sTetherCtrl->isTetheringStarted() ? "started" : "stopped"));
586         cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
587         free(tmp);
588         return 0;
589     } else if (argc == 3) {
590         if (!strcmp(argv[1], "interface") && !strcmp(argv[2], "list")) {
591             InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList();
592             InterfaceCollection::iterator it;
593             for (it = ilist->begin(); it != ilist->end(); ++it) {
594                 cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false);
595             }
596         } else if (!strcmp(argv[1], "dns") && !strcmp(argv[2], "list")) {
597             char netIdStr[UINT32_STRLEN];
598             snprintf(netIdStr, sizeof(netIdStr), "%u", sTetherCtrl->getDnsNetId());
599             cli->sendMsg(ResponseCode::TetherDnsFwdNetIdResult, netIdStr, false);
600
601             for (const auto &fwdr : *(sTetherCtrl->getDnsForwarders())) {
602                 cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, fwdr.c_str(), false);
603             }
604         }
605     } else {
606         /*
607          * These commands take a minimum of 4 arguments
608          */
609         if (argc < 4) {
610             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
611             return 0;
612         }
613
614         if (!strcmp(argv[1], "start")) {
615             if (argc % 2 == 1) {
616                 cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false);
617                 return 0;
618             }
619
620             const int num_addrs = argc - 2;
621             // TODO: consider moving this validation into TetherController.
622             struct in_addr tmp_addr;
623             for (int arg_index = 2; arg_index < argc; arg_index++) {
624                 if (!inet_aton(argv[arg_index], &tmp_addr)) {
625                     cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
626                     return 0;
627                 }
628             }
629
630             rc = sTetherCtrl->startTethering(num_addrs, &(argv[2]));
631         } else if (!strcmp(argv[1], "interface")) {
632             if (!strcmp(argv[2], "add")) {
633                 rc = sTetherCtrl->tetherInterface(argv[3]);
634             } else if (!strcmp(argv[2], "remove")) {
635                 rc = sTetherCtrl->untetherInterface(argv[3]);
636             /* else if (!strcmp(argv[2], "list")) handled above */
637             } else {
638                 cli->sendMsg(ResponseCode::CommandParameterError,
639                              "Unknown tether interface operation", false);
640                 return 0;
641             }
642         } else if (!strcmp(argv[1], "dns")) {
643             if (!strcmp(argv[2], "set")) {
644                 if (argc < 5) {
645                     cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
646                     return 0;
647                 }
648                 unsigned netId = stringToNetId(argv[3]);
649                 rc = sTetherCtrl->setDnsForwarders(netId, &argv[4], argc - 4);
650             /* else if (!strcmp(argv[2], "list")) handled above */
651             } else {
652                 cli->sendMsg(ResponseCode::CommandParameterError,
653                              "Unknown tether interface operation", false);
654                 return 0;
655             }
656         } else {
657             cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
658             return 0;
659         }
660     }
661
662     if (!rc) {
663         cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
664     } else {
665         cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
666     }
667
668     return 0;
669 }
670
671 CommandListener::NatCmd::NatCmd() :
672                  NetdCommand("nat") {
673 }
674
675 int CommandListener::NatCmd::runCommand(SocketClient *cli,
676                                                       int argc, char **argv) {
677     int rc = 0;
678
679     if (argc < 5) {
680         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
681         return 0;
682     }
683
684     //  0     1       2        3
685     // nat  enable intiface extiface
686     // nat disable intiface extiface
687     if (!strcmp(argv[1], "enable") && argc >= 4) {
688         rc = sNatCtrl->enableNat(argv[2], argv[3]);
689         if(!rc) {
690             /* Ignore ifaces for now. */
691             rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
692         }
693     } else if (!strcmp(argv[1], "disable") && argc >= 4) {
694         /* Ignore ifaces for now. */
695         rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
696         rc |= sNatCtrl->disableNat(argv[2], argv[3]);
697     } else {
698         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
699         return 0;
700     }
701
702     if (!rc) {
703         cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
704     } else {
705         cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
706     }
707
708     return 0;
709 }
710
711 CommandListener::PppdCmd::PppdCmd() :
712                  NetdCommand("pppd") {
713 }
714
715 int CommandListener::PppdCmd::runCommand(SocketClient *cli,
716                                                       int argc, char **argv) {
717     int rc = 0;
718
719     if (argc < 3) {
720         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
721         return 0;
722     }
723
724     if (!strcmp(argv[1], "attach")) {
725         struct in_addr l, r, dns1, dns2;
726
727         memset(&dns1, 0, sizeof(struct in_addr));
728         memset(&dns2, 0, sizeof(struct in_addr));
729
730         if (!inet_aton(argv[3], &l)) {
731             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false);
732             return 0;
733         }
734         if (!inet_aton(argv[4], &r)) {
735             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false);
736             return 0;
737         }
738         if ((argc > 3) && (!inet_aton(argv[5], &dns1))) {
739             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false);
740             return 0;
741         }
742         if ((argc > 4) && (!inet_aton(argv[6], &dns2))) {
743             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false);
744             return 0;
745         }
746         rc = sPppCtrl->attachPppd(argv[2], l, r, dns1, dns2);
747     } else if (!strcmp(argv[1], "detach")) {
748         rc = sPppCtrl->detachPppd(argv[2]);
749     } else {
750         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false);
751         return 0;
752     }
753
754     if (!rc) {
755         cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false);
756     } else {
757         cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true);
758     }
759
760     return 0;
761 }
762
763 CommandListener::SoftapCmd::SoftapCmd() :
764                  NetdCommand("softap") {
765 }
766
767 int CommandListener::SoftapCmd::runCommand(SocketClient *cli,
768                                         int argc, char **argv) {
769     int rc = ResponseCode::SoftapStatusResult;
770     char *retbuf = NULL;
771
772     if (sSoftapCtrl == NULL) {
773       cli->sendMsg(ResponseCode::ServiceStartFailed, "SoftAP is not available", false);
774       return -1;
775     }
776     if (argc < 2) {
777         cli->sendMsg(ResponseCode::CommandSyntaxError,
778                      "Missing argument in a SoftAP command", false);
779         return 0;
780     }
781
782     if (!strcmp(argv[1], "startap")) {
783         rc = sSoftapCtrl->startSoftap();
784     } else if (!strcmp(argv[1], "stopap")) {
785         rc = sSoftapCtrl->stopSoftap();
786     } else if (!strcmp(argv[1], "fwreload")) {
787         rc = sSoftapCtrl->fwReloadSoftap(argc, argv);
788     } else if (!strcmp(argv[1], "status")) {
789         asprintf(&retbuf, "Softap service %s running",
790                  (sSoftapCtrl->isSoftapStarted() ? "is" : "is not"));
791         cli->sendMsg(rc, retbuf, false);
792         free(retbuf);
793         return 0;
794     } else if (!strcmp(argv[1], "set")) {
795         rc = sSoftapCtrl->setSoftap(argc, argv);
796     } else {
797         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unrecognized SoftAP command", false);
798         return 0;
799     }
800
801     if (rc >= 400 && rc < 600)
802       cli->sendMsg(rc, "SoftAP command has failed", false);
803     else
804       cli->sendMsg(rc, "Ok", false);
805
806     return 0;
807 }
808
809 CommandListener::ResolverCmd::ResolverCmd() :
810         NetdCommand("resolver") {
811 }
812
813 int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **margv) {
814     int rc = 0;
815     const char **argv = const_cast<const char **>(margv);
816
817     if (argc < 3) {
818         cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false);
819         return 0;
820     }
821
822     unsigned netId = stringToNetId(argv[2]);
823     // TODO: Consider making NetworkController.isValidNetwork() public
824     // and making that check here.
825
826     if (!strcmp(argv[1], "setnetdns")) {
827         // "resolver setnetdns <netId> <domains> <dns1> <dns2> ..."
828         if (argc >= 5) {
829             rc = sResolverCtrl->setDnsServers(netId, argv[3], &argv[4], argc - 4);
830         } else {
831             cli->sendMsg(ResponseCode::CommandSyntaxError,
832                     "Wrong number of arguments to resolver setnetdns", false);
833             return 0;
834         }
835     } else if (!strcmp(argv[1], "clearnetdns")) { // "resolver clearnetdns <netId>"
836         if (argc == 3) {
837             rc = sResolverCtrl->clearDnsServers(netId);
838         } else {
839             cli->sendMsg(ResponseCode::CommandSyntaxError,
840                     "Wrong number of arguments to resolver clearnetdns", false);
841             return 0;
842         }
843     } else if (!strcmp(argv[1], "flushnet")) { // "resolver flushnet <netId>"
844         if (argc == 3) {
845             rc = sResolverCtrl->flushDnsCache(netId);
846         } else {
847             cli->sendMsg(ResponseCode::CommandSyntaxError,
848                     "Wrong number of arguments to resolver flushnet", false);
849             return 0;
850         }
851     } else {
852         cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false);
853         return 0;
854     }
855
856     if (!rc) {
857         cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false);
858     } else {
859         cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true);
860     }
861
862     return 0;
863 }
864
865 CommandListener::BandwidthControlCmd::BandwidthControlCmd() :
866     NetdCommand("bandwidth") {
867 }
868
869 void CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) {
870     char *msg;
871     asprintf(&msg, "Usage: bandwidth %s", usageMsg);
872     cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false);
873     free(msg);
874 }
875
876 void CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) {
877     if (!cond) {
878         cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
879     } else {
880         cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false);
881     }
882 }
883
884 void CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) {
885     cli->sendMsg(ResponseCode::OperationFailed, errMsg, false);
886 }
887
888 int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
889     if (argc < 2) {
890         sendGenericSyntaxError(cli, "<cmds> <args...>");
891         return 0;
892     }
893
894     ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
895
896     if (!strcmp(argv[1], "enable")) {
897         int rc = sBandwidthCtrl->enableBandwidthControl(true);
898         sendGenericOkFail(cli, rc);
899         return 0;
900
901     }
902     if (!strcmp(argv[1], "disable")) {
903         int rc = sBandwidthCtrl->disableBandwidthControl();
904         sendGenericOkFail(cli, rc);
905         return 0;
906
907     }
908     if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
909         if (argc != 3) {
910             sendGenericSyntaxError(cli, "removequota <interface>");
911             return 0;
912         }
913         int rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[2]);
914         sendGenericOkFail(cli, rc);
915         return 0;
916
917     }
918     if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) {
919         int64_t bytes;
920         if (argc != 2) {
921             sendGenericSyntaxError(cli, "getquota");
922             return 0;
923         }
924         int rc = sBandwidthCtrl->getInterfaceSharedQuota(&bytes);
925         if (rc) {
926             sendGenericOpFailed(cli, "Failed to get quota");
927             return 0;
928         }
929
930         char *msg;
931         asprintf(&msg, "%" PRId64, bytes);
932         cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
933         free(msg);
934         return 0;
935
936     }
937     if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) {
938         int64_t bytes;
939         if (argc != 3) {
940             sendGenericSyntaxError(cli, "getiquota <iface>");
941             return 0;
942         }
943
944         int rc = sBandwidthCtrl->getInterfaceQuota(argv[2], &bytes);
945         if (rc) {
946             sendGenericOpFailed(cli, "Failed to get quota");
947             return 0;
948         }
949         char *msg;
950         asprintf(&msg, "%" PRId64, bytes);
951         cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
952         free(msg);
953         return 0;
954
955     }
956     if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
957         if (argc != 4) {
958             sendGenericSyntaxError(cli, "setquota <interface> <bytes>");
959             return 0;
960         }
961         int rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[2], atoll(argv[3]));
962         sendGenericOkFail(cli, rc);
963         return 0;
964     }
965     if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
966         int rc;
967         if (argc < 4) {
968             sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ...");
969             return 0;
970         }
971
972         for (int q = 3; argc >= 4; q++, argc--) {
973             rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[q], atoll(argv[2]));
974             if (rc) {
975                 char *msg;
976                 asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]);
977                 cli->sendMsg(ResponseCode::OperationFailed,
978                              msg, false);
979                 free(msg);
980                 return 0;
981             }
982         }
983         sendGenericOkFail(cli, rc);
984         return 0;
985
986     }
987     if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) {
988         int rc;
989         if (argc < 3) {
990             sendGenericSyntaxError(cli, "removequotas <interface> ...");
991             return 0;
992         }
993
994         for (int q = 2; argc >= 3; q++, argc--) {
995             rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[q]);
996             if (rc) {
997                 char *msg;
998                 asprintf(&msg, "bandwidth removequotas %s failed", argv[q]);
999                 cli->sendMsg(ResponseCode::OperationFailed,
1000                              msg, false);
1001                 free(msg);
1002                 return 0;
1003             }
1004         }
1005         sendGenericOkFail(cli, rc);
1006         return 0;
1007
1008     }
1009     if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
1010         if (argc != 3) {
1011             sendGenericSyntaxError(cli, "removeiquota <interface>");
1012             return 0;
1013         }
1014         int rc = sBandwidthCtrl->removeInterfaceQuota(argv[2]);
1015         sendGenericOkFail(cli, rc);
1016         return 0;
1017
1018     }
1019     if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
1020         if (argc != 4) {
1021             sendGenericSyntaxError(cli, "setiquota <interface> <bytes>");
1022             return 0;
1023         }
1024         int rc = sBandwidthCtrl->setInterfaceQuota(argv[2], atoll(argv[3]));
1025         sendGenericOkFail(cli, rc);
1026         return 0;
1027
1028     }
1029     if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
1030         if (argc < 3) {
1031             sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ...");
1032             return 0;
1033         }
1034         int rc = sBandwidthCtrl->addNaughtyApps(argc - 2, argv + 2);
1035         sendGenericOkFail(cli, rc);
1036         return 0;
1037
1038
1039     }
1040     if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
1041         if (argc < 3) {
1042             sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ...");
1043             return 0;
1044         }
1045         int rc = sBandwidthCtrl->removeNaughtyApps(argc - 2, argv + 2);
1046         sendGenericOkFail(cli, rc);
1047         return 0;
1048     }
1049     if (!strcmp(argv[1], "happybox")) {
1050         if (argc < 3) {
1051             sendGenericSyntaxError(cli, "happybox (enable | disable)");
1052             return 0;
1053         }
1054         if (!strcmp(argv[2], "enable")) {
1055             int rc = sBandwidthCtrl->enableHappyBox();
1056             sendGenericOkFail(cli, rc);
1057             return 0;
1058
1059         }
1060         if (!strcmp(argv[2], "disable")) {
1061             int rc = sBandwidthCtrl->disableHappyBox();
1062             sendGenericOkFail(cli, rc);
1063             return 0;
1064         }
1065         sendGenericSyntaxError(cli, "happybox (enable | disable)");
1066         return 0;
1067     }
1068     if (!strcmp(argv[1], "addniceapps") || !strcmp(argv[1], "aha")) {
1069         if (argc < 3) {
1070             sendGenericSyntaxError(cli, "addniceapps <appUid> ...");
1071             return 0;
1072         }
1073         int rc = sBandwidthCtrl->addNiceApps(argc - 2, argv + 2);
1074         sendGenericOkFail(cli, rc);
1075         return 0;
1076     }
1077     if (!strcmp(argv[1], "removeniceapps") || !strcmp(argv[1], "rha")) {
1078         if (argc < 3) {
1079             sendGenericSyntaxError(cli, "removeniceapps <appUid> ...");
1080             return 0;
1081         }
1082         int rc = sBandwidthCtrl->removeNiceApps(argc - 2, argv + 2);
1083         sendGenericOkFail(cli, rc);
1084         return 0;
1085     }
1086     if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) {
1087         if (argc != 3) {
1088             sendGenericSyntaxError(cli, "setglobalalert <bytes>");
1089             return 0;
1090         }
1091         int rc = sBandwidthCtrl->setGlobalAlert(atoll(argv[2]));
1092         sendGenericOkFail(cli, rc);
1093         return 0;
1094     }
1095     if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) {
1096         if (argc != 4) {
1097             sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>");
1098             return 0;
1099         }
1100         /* We ignore the interfaces for now. */
1101         int rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
1102         sendGenericOkFail(cli, rc);
1103         return 0;
1104
1105     }
1106     if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
1107         if (argc != 2) {
1108             sendGenericSyntaxError(cli, "removeglobalalert");
1109             return 0;
1110         }
1111         int rc = sBandwidthCtrl->removeGlobalAlert();
1112         sendGenericOkFail(cli, rc);
1113         return 0;
1114
1115     }
1116     if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) {
1117         if (argc != 4) {
1118             sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>");
1119             return 0;
1120         }
1121         /* We ignore the interfaces for now. */
1122         int rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
1123         sendGenericOkFail(cli, rc);
1124         return 0;
1125
1126     }
1127     if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
1128         if (argc != 3) {
1129             sendGenericSyntaxError(cli, "setsharedalert <bytes>");
1130             return 0;
1131         }
1132         int rc = sBandwidthCtrl->setSharedAlert(atoll(argv[2]));
1133         sendGenericOkFail(cli, rc);
1134         return 0;
1135
1136     }
1137     if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) {
1138         if (argc != 2) {
1139             sendGenericSyntaxError(cli, "removesharedalert");
1140             return 0;
1141         }
1142         int rc = sBandwidthCtrl->removeSharedAlert();
1143         sendGenericOkFail(cli, rc);
1144         return 0;
1145
1146     }
1147     if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) {
1148         if (argc != 4) {
1149             sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>");
1150             return 0;
1151         }
1152         int rc = sBandwidthCtrl->setInterfaceAlert(argv[2], atoll(argv[3]));
1153         sendGenericOkFail(cli, rc);
1154         return 0;
1155
1156     }
1157     if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) {
1158         if (argc != 3) {
1159             sendGenericSyntaxError(cli, "removeinterfacealert <interface>");
1160             return 0;
1161         }
1162         int rc = sBandwidthCtrl->removeInterfaceAlert(argv[2]);
1163         sendGenericOkFail(cli, rc);
1164         return 0;
1165
1166     }
1167     if (!strcmp(argv[1], "gettetherstats") || !strcmp(argv[1], "gts")) {
1168         BandwidthController::TetherStats tetherStats;
1169         std::string extraProcessingInfo = "";
1170         if (argc < 2 || argc > 4) {
1171             sendGenericSyntaxError(cli, "gettetherstats [<intInterface> <extInterface>]");
1172             return 0;
1173         }
1174         tetherStats.intIface = argc > 2 ? argv[2] : "";
1175         tetherStats.extIface = argc > 3 ? argv[3] : "";
1176         // No filtering requested and there are no interface pairs to lookup.
1177         if (argc <= 2 && sNatCtrl->ifacePairList.empty()) {
1178             cli->sendMsg(ResponseCode::CommandOkay, "Tethering stats list completed", false);
1179             return 0;
1180         }
1181         int rc = sBandwidthCtrl->getTetherStats(cli, tetherStats, extraProcessingInfo);
1182         if (rc) {
1183                 extraProcessingInfo.insert(0, "Failed to get tethering stats.\n");
1184                 sendGenericOpFailed(cli, extraProcessingInfo.c_str());
1185                 return 0;
1186         }
1187         return 0;
1188
1189     }
1190
1191     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
1192     return 0;
1193 }
1194
1195 CommandListener::IdletimerControlCmd::IdletimerControlCmd() :
1196     NetdCommand("idletimer") {
1197 }
1198
1199 int CommandListener::IdletimerControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
1200   // TODO(ashish): Change the error statements
1201     if (argc < 2) {
1202         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1203         return 0;
1204     }
1205
1206     ALOGV("idletimerctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
1207
1208     if (!strcmp(argv[1], "enable")) {
1209       if (0 != sIdletimerCtrl->enableIdletimerControl()) {
1210         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1211       } else {
1212         cli->sendMsg(ResponseCode::CommandOkay, "Enable success", false);
1213       }
1214       return 0;
1215
1216     }
1217     if (!strcmp(argv[1], "disable")) {
1218       if (0 != sIdletimerCtrl->disableIdletimerControl()) {
1219         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1220       } else {
1221         cli->sendMsg(ResponseCode::CommandOkay, "Disable success", false);
1222       }
1223       return 0;
1224     }
1225     if (!strcmp(argv[1], "add")) {
1226         if (argc != 5) {
1227             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1228             return 0;
1229         }
1230         if(0 != sIdletimerCtrl->addInterfaceIdletimer(
1231                                         argv[2], atoi(argv[3]), argv[4])) {
1232           cli->sendMsg(ResponseCode::OperationFailed, "Failed to add interface", false);
1233         } else {
1234           cli->sendMsg(ResponseCode::CommandOkay,  "Add success", false);
1235         }
1236         return 0;
1237     }
1238     if (!strcmp(argv[1], "remove")) {
1239         if (argc != 5) {
1240             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1241             return 0;
1242         }
1243         // ashish: fixme timeout
1244         if (0 != sIdletimerCtrl->removeInterfaceIdletimer(
1245                                         argv[2], atoi(argv[3]), argv[4])) {
1246           cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove interface", false);
1247         } else {
1248           cli->sendMsg(ResponseCode::CommandOkay, "Remove success", false);
1249         }
1250         return 0;
1251     }
1252
1253     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown idletimer cmd", false);
1254     return 0;
1255 }
1256
1257 CommandListener::FirewallCmd::FirewallCmd() :
1258     NetdCommand("firewall") {
1259 }
1260
1261 int CommandListener::FirewallCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1262     if (!cond) {
1263         cli->sendMsg(ResponseCode::CommandOkay, "Firewall command succeeded", false);
1264     } else {
1265         cli->sendMsg(ResponseCode::OperationFailed, "Firewall command failed", false);
1266     }
1267     return 0;
1268 }
1269
1270 FirewallRule CommandListener::FirewallCmd::parseRule(const char* arg) {
1271     if (!strcmp(arg, "allow")) {
1272         return ALLOW;
1273     } else if (!strcmp(arg, "deny")) {
1274         return DENY;
1275     } else {
1276         ALOGE("failed to parse uid rule (%s)", arg);
1277         return ALLOW;
1278     }
1279 }
1280
1281 FirewallType CommandListener::FirewallCmd::parseFirewallType(const char* arg) {
1282     if (!strcmp(arg, "whitelist")) {
1283         return WHITELIST;
1284     } else if (!strcmp(arg, "blacklist")) {
1285         return BLACKLIST;
1286     } else {
1287         ALOGE("failed to parse firewall type (%s)", arg);
1288         return BLACKLIST;
1289     }
1290 }
1291
1292 ChildChain CommandListener::FirewallCmd::parseChildChain(const char* arg) {
1293     if (!strcmp(arg, "dozable")) {
1294         return DOZABLE;
1295     } else if (!strcmp(arg, "standby")) {
1296         return STANDBY;
1297     } else if (!strcmp(arg, "none")) {
1298         return NONE;
1299     } else {
1300         ALOGE("failed to parse child firewall chain (%s)", arg);
1301         return INVALID_CHAIN;
1302     }
1303 }
1304
1305 int CommandListener::FirewallCmd::runCommand(SocketClient *cli, int argc,
1306         char **argv) {
1307     if (argc < 2) {
1308         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
1309         return 0;
1310     }
1311
1312     if (!strcmp(argv[1], "enable")) {
1313         if (argc != 3) {
1314             cli->sendMsg(ResponseCode::CommandSyntaxError,
1315                         "Usage: firewall enable <whitelist|blacklist>", false);
1316             return 0;
1317         }
1318         FirewallType firewallType = parseFirewallType(argv[2]);
1319
1320         int res = sFirewallCtrl->enableFirewall(firewallType);
1321         return sendGenericOkFail(cli, res);
1322     }
1323     if (!strcmp(argv[1], "disable")) {
1324         int res = sFirewallCtrl->disableFirewall();
1325         return sendGenericOkFail(cli, res);
1326     }
1327     if (!strcmp(argv[1], "is_enabled")) {
1328         int res = sFirewallCtrl->isFirewallEnabled();
1329         return sendGenericOkFail(cli, res);
1330     }
1331
1332     if (!strcmp(argv[1], "set_interface_rule")) {
1333         if (argc != 4) {
1334             cli->sendMsg(ResponseCode::CommandSyntaxError,
1335                          "Usage: firewall set_interface_rule <rmnet0> <allow|deny>", false);
1336             return 0;
1337         }
1338
1339         const char* iface = argv[2];
1340         FirewallRule rule = parseRule(argv[3]);
1341
1342         int res = sFirewallCtrl->setInterfaceRule(iface, rule);
1343         return sendGenericOkFail(cli, res);
1344     }
1345
1346     if (!strcmp(argv[1], "set_egress_source_rule")) {
1347         if (argc != 4) {
1348             cli->sendMsg(ResponseCode::CommandSyntaxError,
1349                          "Usage: firewall set_egress_source_rule <192.168.0.1> <allow|deny>",
1350                          false);
1351             return 0;
1352         }
1353
1354         const char* addr = argv[2];
1355         FirewallRule rule = parseRule(argv[3]);
1356
1357         int res = sFirewallCtrl->setEgressSourceRule(addr, rule);
1358         return sendGenericOkFail(cli, res);
1359     }
1360
1361     if (!strcmp(argv[1], "set_egress_dest_rule")) {
1362         if (argc != 5) {
1363             cli->sendMsg(ResponseCode::CommandSyntaxError,
1364                          "Usage: firewall set_egress_dest_rule <192.168.0.1> <80> <allow|deny>",
1365                          false);
1366             return 0;
1367         }
1368
1369         const char* addr = argv[2];
1370         int port = atoi(argv[3]);
1371         FirewallRule rule = parseRule(argv[4]);
1372
1373         int res = 0;
1374         res |= sFirewallCtrl->setEgressDestRule(addr, PROTOCOL_TCP, port, rule);
1375         res |= sFirewallCtrl->setEgressDestRule(addr, PROTOCOL_UDP, port, rule);
1376         return sendGenericOkFail(cli, res);
1377     }
1378
1379     if (!strcmp(argv[1], "set_uid_rule")) {
1380         if (argc != 5) {
1381             cli->sendMsg(ResponseCode::CommandSyntaxError,
1382                          "Usage: firewall set_uid_rule <dozable|standby|none> <1000> <allow|deny>",
1383                          false);
1384             return 0;
1385         }
1386
1387         ChildChain childChain = parseChildChain(argv[2]);
1388         if (childChain == INVALID_CHAIN) {
1389             cli->sendMsg(ResponseCode::CommandSyntaxError,
1390                          "Invalid chain name. Valid names are: <dozable|standby|none>",
1391                          false);
1392             return 0;
1393         }
1394         int uid = atoi(argv[3]);
1395         FirewallRule rule = parseRule(argv[4]);
1396         int res = sFirewallCtrl->setUidRule(childChain, uid, rule);
1397         return sendGenericOkFail(cli, res);
1398     }
1399
1400     if (!strcmp(argv[1], "enable_chain")) {
1401         if (argc != 3) {
1402             cli->sendMsg(ResponseCode::CommandSyntaxError,
1403                          "Usage: firewall enable_chain <dozable|standby>",
1404                          false);
1405             return 0;
1406         }
1407
1408         ChildChain childChain = parseChildChain(argv[2]);
1409         int res = sFirewallCtrl->enableChildChains(childChain, true);
1410         return sendGenericOkFail(cli, res);
1411     }
1412
1413     if (!strcmp(argv[1], "disable_chain")) {
1414         if (argc != 3) {
1415             cli->sendMsg(ResponseCode::CommandSyntaxError,
1416                          "Usage: firewall disable_chain <dozable|standby>",
1417                          false);
1418             return 0;
1419         }
1420
1421         ChildChain childChain = parseChildChain(argv[2]);
1422         int res = sFirewallCtrl->enableChildChains(childChain, false);
1423         return sendGenericOkFail(cli, res);
1424     }
1425
1426     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
1427     return 0;
1428 }
1429
1430 CommandListener::ClatdCmd::ClatdCmd() : NetdCommand("clatd") {
1431 }
1432
1433 int CommandListener::ClatdCmd::runCommand(SocketClient *cli, int argc,
1434                                                             char **argv) {
1435     int rc = 0;
1436     if (argc < 3) {
1437         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1438         return 0;
1439     }
1440
1441     if (!strcmp(argv[1], "stop")) {
1442         rc = sClatdCtrl->stopClatd(argv[2]);
1443     } else if (!strcmp(argv[1], "status")) {
1444         char *tmp = NULL;
1445         asprintf(&tmp, "Clatd status: %s", (sClatdCtrl->isClatdStarted(argv[2]) ?
1446                                             "started" : "stopped"));
1447         cli->sendMsg(ResponseCode::ClatdStatusResult, tmp, false);
1448         free(tmp);
1449         return 0;
1450     } else if (!strcmp(argv[1], "start")) {
1451         rc = sClatdCtrl->startClatd(argv[2]);
1452     } else {
1453         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown clatd cmd", false);
1454         return 0;
1455     }
1456
1457     if (!rc) {
1458         cli->sendMsg(ResponseCode::CommandOkay, "Clatd operation succeeded", false);
1459     } else {
1460         cli->sendMsg(ResponseCode::OperationFailed, "Clatd operation failed", false);
1461     }
1462
1463     return 0;
1464 }
1465
1466 CommandListener::StrictCmd::StrictCmd() :
1467     NetdCommand("strict") {
1468 }
1469
1470 int CommandListener::StrictCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1471     if (!cond) {
1472         cli->sendMsg(ResponseCode::CommandOkay, "Strict command succeeded", false);
1473     } else {
1474         cli->sendMsg(ResponseCode::OperationFailed, "Strict command failed", false);
1475     }
1476     return 0;
1477 }
1478
1479 StrictPenalty CommandListener::StrictCmd::parsePenalty(const char* arg) {
1480     if (!strcmp(arg, "reject")) {
1481         return REJECT;
1482     } else if (!strcmp(arg, "log")) {
1483         return LOG;
1484     } else if (!strcmp(arg, "accept")) {
1485         return ACCEPT;
1486     } else {
1487         return INVALID;
1488     }
1489 }
1490
1491 int CommandListener::StrictCmd::runCommand(SocketClient *cli, int argc,
1492         char **argv) {
1493     if (argc < 2) {
1494         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
1495         return 0;
1496     }
1497
1498     if (!strcmp(argv[1], "enable")) {
1499         int res = sStrictCtrl->enableStrict();
1500         return sendGenericOkFail(cli, res);
1501     }
1502     if (!strcmp(argv[1], "disable")) {
1503         int res = sStrictCtrl->disableStrict();
1504         return sendGenericOkFail(cli, res);
1505     }
1506
1507     if (!strcmp(argv[1], "set_uid_cleartext_policy")) {
1508         if (argc != 4) {
1509             cli->sendMsg(ResponseCode::CommandSyntaxError,
1510                          "Usage: strict set_uid_cleartext_policy <uid> <accept|log|reject>",
1511                          false);
1512             return 0;
1513         }
1514
1515         errno = 0;
1516         unsigned long int uid = strtoul(argv[2], NULL, 0);
1517         if (errno || uid > UID_MAX) {
1518             cli->sendMsg(ResponseCode::CommandSyntaxError, "Invalid UID", false);
1519             return 0;
1520         }
1521
1522         StrictPenalty penalty = parsePenalty(argv[3]);
1523         if (penalty == INVALID) {
1524             cli->sendMsg(ResponseCode::CommandSyntaxError, "Invalid penalty argument", false);
1525             return 0;
1526         }
1527
1528         int res = sStrictCtrl->setUidCleartextPenalty((uid_t) uid, penalty);
1529         return sendGenericOkFail(cli, res);
1530     }
1531
1532     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
1533     return 0;
1534 }
1535
1536 CommandListener::NetworkCommand::NetworkCommand() : NetdCommand("network") {
1537 }
1538
1539 int CommandListener::NetworkCommand::syntaxError(SocketClient* client, const char* message) {
1540     client->sendMsg(ResponseCode::CommandSyntaxError, message, false);
1541     return 0;
1542 }
1543
1544 int CommandListener::NetworkCommand::operationError(SocketClient* client, const char* message,
1545                                                     int ret) {
1546     errno = -ret;
1547     client->sendMsg(ResponseCode::OperationFailed, message, true);
1548     return 0;
1549 }
1550
1551 int CommandListener::NetworkCommand::success(SocketClient* client) {
1552     client->sendMsg(ResponseCode::CommandOkay, "success", false);
1553     return 0;
1554 }
1555
1556 int CommandListener::NetworkCommand::runCommand(SocketClient* client, int argc, char** argv) {
1557     if (argc < 2) {
1558         return syntaxError(client, "Missing argument");
1559     }
1560
1561     //    0      1      2      3      4       5         6            7           8
1562     // network route [legacy <uid>]  add   <netId> <interface> <destination> [nexthop]
1563     // network route [legacy <uid>] remove <netId> <interface> <destination> [nexthop]
1564     //
1565     // nexthop may be either an IPv4/IPv6 address or one of "unreachable" or "throw".
1566     if (!strcmp(argv[1], "route")) {
1567         if (argc < 6 || argc > 9) {
1568             return syntaxError(client, "Incorrect number of arguments");
1569         }
1570
1571         int nextArg = 2;
1572         bool legacy = false;
1573         uid_t uid = 0;
1574         if (!strcmp(argv[nextArg], "legacy")) {
1575             ++nextArg;
1576             legacy = true;
1577             uid = strtoul(argv[nextArg++], NULL, 0);
1578         }
1579
1580         bool add = false;
1581         if (!strcmp(argv[nextArg], "add")) {
1582             add = true;
1583         } else if (strcmp(argv[nextArg], "remove")) {
1584             return syntaxError(client, "Unknown argument");
1585         }
1586         ++nextArg;
1587
1588         if (argc < nextArg + 3 || argc > nextArg + 4) {
1589             return syntaxError(client, "Incorrect number of arguments");
1590         }
1591
1592         unsigned netId = stringToNetId(argv[nextArg++]);
1593         const char* interface = argv[nextArg++];
1594         const char* destination = argv[nextArg++];
1595         const char* nexthop = argc > nextArg ? argv[nextArg] : NULL;
1596
1597         int ret;
1598         if (add) {
1599             ret = sNetCtrl->addRoute(netId, interface, destination, nexthop, legacy, uid);
1600         } else {
1601             ret = sNetCtrl->removeRoute(netId, interface, destination, nexthop, legacy, uid);
1602         }
1603         if (ret) {
1604             return operationError(client, add ? "addRoute() failed" : "removeRoute() failed", ret);
1605         }
1606
1607         return success(client);
1608     }
1609
1610     //    0        1       2       3         4
1611     // network interface  add   <netId> <interface>
1612     // network interface remove <netId> <interface>
1613     if (!strcmp(argv[1], "interface")) {
1614         if (argc != 5) {
1615             return syntaxError(client, "Missing argument");
1616         }
1617         unsigned netId = stringToNetId(argv[3]);
1618         if (!strcmp(argv[2], "add")) {
1619             if (int ret = sNetCtrl->addInterfaceToNetwork(netId, argv[4])) {
1620                 return operationError(client, "addInterfaceToNetwork() failed", ret);
1621             }
1622         } else if (!strcmp(argv[2], "remove")) {
1623             if (int ret = sNetCtrl->removeInterfaceFromNetwork(netId, argv[4])) {
1624                 return operationError(client, "removeInterfaceFromNetwork() failed", ret);
1625             }
1626         } else {
1627             return syntaxError(client, "Unknown argument");
1628         }
1629         return success(client);
1630     }
1631
1632     //    0      1       2         3
1633     // network create <netId> [permission]
1634     //
1635     //    0      1       2     3     4        5
1636     // network create <netId> vpn <hasDns> <secure>
1637     if (!strcmp(argv[1], "create")) {
1638         if (argc < 3) {
1639             return syntaxError(client, "Missing argument");
1640         }
1641         unsigned netId = stringToNetId(argv[2]);
1642         if (argc == 6 && !strcmp(argv[3], "vpn")) {
1643             bool hasDns = atoi(argv[4]);
1644             bool secure = atoi(argv[5]);
1645             if (int ret = sNetCtrl->createVirtualNetwork(netId, hasDns, secure)) {
1646                 return operationError(client, "createVirtualNetwork() failed", ret);
1647             }
1648         } else if (argc > 4) {
1649             return syntaxError(client, "Unknown trailing argument(s)");
1650         } else {
1651             Permission permission = PERMISSION_NONE;
1652             if (argc == 4) {
1653                 permission = stringToPermission(argv[3]);
1654                 if (permission == PERMISSION_NONE) {
1655                     return syntaxError(client, "Unknown permission");
1656                 }
1657             }
1658             if (int ret = sNetCtrl->createPhysicalNetwork(netId, permission)) {
1659                 return operationError(client, "createPhysicalNetwork() failed", ret);
1660             }
1661         }
1662         return success(client);
1663     }
1664
1665     //    0       1       2
1666     // network destroy <netId>
1667     if (!strcmp(argv[1], "destroy")) {
1668         if (argc != 3) {
1669             return syntaxError(client, "Incorrect number of arguments");
1670         }
1671         unsigned netId = stringToNetId(argv[2]);
1672         if (int ret = sNetCtrl->destroyNetwork(netId)) {
1673             return operationError(client, "destroyNetwork() failed", ret);
1674         }
1675         return success(client);
1676     }
1677
1678     //    0       1      2      3
1679     // network default  set  <netId>
1680     // network default clear
1681     if (!strcmp(argv[1], "default")) {
1682         if (argc < 3) {
1683             return syntaxError(client, "Missing argument");
1684         }
1685         unsigned netId = NETID_UNSET;
1686         if (!strcmp(argv[2], "set")) {
1687             if (argc < 4) {
1688                 return syntaxError(client, "Missing netId");
1689             }
1690             netId = stringToNetId(argv[3]);
1691         } else if (strcmp(argv[2], "clear")) {
1692             return syntaxError(client, "Unknown argument");
1693         }
1694         if (int ret = sNetCtrl->setDefaultNetwork(netId)) {
1695             return operationError(client, "setDefaultNetwork() failed", ret);
1696         }
1697         return success(client);
1698     }
1699
1700     //    0        1         2      3        4          5
1701     // network permission   user   set  <permission>  <uid> ...
1702     // network permission   user  clear    <uid> ...
1703     // network permission network  set  <permission> <netId> ...
1704     // network permission network clear   <netId> ...
1705     if (!strcmp(argv[1], "permission")) {
1706         if (argc < 5) {
1707             return syntaxError(client, "Missing argument");
1708         }
1709         int nextArg = 4;
1710         Permission permission = PERMISSION_NONE;
1711         if (!strcmp(argv[3], "set")) {
1712             permission = stringToPermission(argv[4]);
1713             if (permission == PERMISSION_NONE) {
1714                 return syntaxError(client, "Unknown permission");
1715             }
1716             nextArg = 5;
1717         } else if (strcmp(argv[3], "clear")) {
1718             return syntaxError(client, "Unknown argument");
1719         }
1720         if (nextArg == argc) {
1721             return syntaxError(client, "Missing id");
1722         }
1723
1724         bool userPermissions = !strcmp(argv[2], "user");
1725         bool networkPermissions = !strcmp(argv[2], "network");
1726         if (!userPermissions && !networkPermissions) {
1727             return syntaxError(client, "Unknown argument");
1728         }
1729
1730         std::vector<unsigned> ids;
1731         for (; nextArg < argc; ++nextArg) {
1732             if (userPermissions) {
1733                 char* endPtr;
1734                 unsigned id = strtoul(argv[nextArg], &endPtr, 0);
1735                 if (!*argv[nextArg] || *endPtr) {
1736                     return syntaxError(client, "Invalid id");
1737                 }
1738                 ids.push_back(id);
1739             } else {
1740                 // networkPermissions
1741                 ids.push_back(stringToNetId(argv[nextArg]));
1742             }
1743         }
1744         if (userPermissions) {
1745             sNetCtrl->setPermissionForUsers(permission, ids);
1746         } else {
1747             // networkPermissions
1748             if (int ret = sNetCtrl->setPermissionForNetworks(permission, ids)) {
1749                 return operationError(client, "setPermissionForNetworks() failed", ret);
1750             }
1751         }
1752
1753         return success(client);
1754     }
1755
1756     //    0      1     2       3           4
1757     // network users  add   <netId> [<uid>[-<uid>]] ...
1758     // network users remove <netId> [<uid>[-<uid>]] ...
1759     if (!strcmp(argv[1], "users")) {
1760         if (argc < 4) {
1761             return syntaxError(client, "Missing argument");
1762         }
1763         unsigned netId = stringToNetId(argv[3]);
1764         UidRanges uidRanges;
1765         if (!uidRanges.parseFrom(argc - 4, argv + 4)) {
1766             return syntaxError(client, "Invalid UIDs");
1767         }
1768         if (!strcmp(argv[2], "add")) {
1769             if (int ret = sNetCtrl->addUsersToNetwork(netId, uidRanges)) {
1770                 return operationError(client, "addUsersToNetwork() failed", ret);
1771             }
1772         } else if (!strcmp(argv[2], "remove")) {
1773             if (int ret = sNetCtrl->removeUsersFromNetwork(netId, uidRanges)) {
1774                 return operationError(client, "removeUsersFromNetwork() failed", ret);
1775             }
1776         } else {
1777             return syntaxError(client, "Unknown argument");
1778         }
1779         return success(client);
1780     }
1781
1782     //    0       1      2     3
1783     // network protect allow <uid> ...
1784     // network protect  deny <uid> ...
1785     if (!strcmp(argv[1], "protect")) {
1786         if (argc < 4) {
1787             return syntaxError(client, "Missing argument");
1788         }
1789         std::vector<uid_t> uids;
1790         for (int i = 3; i < argc; ++i) {
1791             uids.push_back(strtoul(argv[i], NULL, 0));
1792         }
1793         if (!strcmp(argv[2], "allow")) {
1794             sNetCtrl->allowProtect(uids);
1795         } else if (!strcmp(argv[2], "deny")) {
1796             sNetCtrl->denyProtect(uids);
1797         } else {
1798             return syntaxError(client, "Unknown argument");
1799         }
1800         return success(client);
1801     }
1802
1803     return syntaxError(client, "Unknown argument");
1804 }