OSDN Git Service

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