OSDN Git Service

Support more than one clatd at a time.
[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, "android.permission.CHANGE_NETWORK_STATE")) {
58         return PERMISSION_NETWORK;
59     }
60     if (!strcmp(arg, "android.permission.CONNECTIVITY_INTERNAL")) {
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], "setmtu")) {
448             if (argc != 4) {
449                 cli->sendMsg(ResponseCode::CommandSyntaxError,
450                         "Usage: interface setmtu <interface> <val>", false);
451                 return 0;
452             }
453             if (sInterfaceCtrl->setMtu(argv[2], argv[3]) == 0) {
454                 cli->sendMsg(ResponseCode::CommandOkay, "MTU changed", false);
455             } else {
456                 cli->sendMsg(ResponseCode::OperationFailed,
457                         "Failed to get MTU", true);
458             }
459             return 0;
460         } else {
461             cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
462             return 0;
463         }
464     }
465     return 0;
466 }
467
468
469 CommandListener::ListTtysCmd::ListTtysCmd() :
470                  NetdCommand("list_ttys") {
471 }
472
473 int CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
474                                              int /* argc */, char ** /* argv */) {
475     TtyCollection *tlist = sPppCtrl->getTtyList();
476     TtyCollection::iterator it;
477
478     for (it = tlist->begin(); it != tlist->end(); ++it) {
479         cli->sendMsg(ResponseCode::TtyListResult, *it, false);
480     }
481
482     cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
483     return 0;
484 }
485
486 CommandListener::IpFwdCmd::IpFwdCmd() :
487                  NetdCommand("ipfwd") {
488 }
489
490 int CommandListener::IpFwdCmd::runCommand(SocketClient *cli,
491                                                       int argc, char **argv) {
492     int rc = 0;
493
494     if (argc < 2) {
495         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
496         return 0;
497     }
498
499     if (!strcmp(argv[1], "status")) {
500         char *tmp = NULL;
501
502         asprintf(&tmp, "Forwarding %s", (sTetherCtrl->getIpFwdEnabled() ? "enabled" : "disabled"));
503         cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
504         free(tmp);
505         return 0;
506     } else if (!strcmp(argv[1], "enable")) {
507         rc = sTetherCtrl->setIpFwdEnabled(true);
508     } else if (!strcmp(argv[1], "disable")) {
509         rc = sTetherCtrl->setIpFwdEnabled(false);
510     } else {
511         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
512         return 0;
513     }
514
515     if (!rc) {
516         cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
517     } else {
518         cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
519     }
520
521     return 0;
522 }
523
524 CommandListener::TetherCmd::TetherCmd() :
525                  NetdCommand("tether") {
526 }
527
528 int CommandListener::TetherCmd::runCommand(SocketClient *cli,
529                                                       int argc, char **argv) {
530     int rc = 0;
531
532     if (argc < 2) {
533         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
534         return 0;
535     }
536
537     if (!strcmp(argv[1], "stop")) {
538         rc = sTetherCtrl->stopTethering();
539     } else if (!strcmp(argv[1], "status")) {
540         char *tmp = NULL;
541
542         asprintf(&tmp, "Tethering services %s",
543                  (sTetherCtrl->isTetheringStarted() ? "started" : "stopped"));
544         cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
545         free(tmp);
546         return 0;
547     } else if (argc == 3) {
548         if (!strcmp(argv[1], "interface") && !strcmp(argv[2], "list")) {
549             InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList();
550             InterfaceCollection::iterator it;
551             for (it = ilist->begin(); it != ilist->end(); ++it) {
552                 cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false);
553             }
554         } else if (!strcmp(argv[1], "dns") && !strcmp(argv[2], "list")) {
555             char netIdStr[UINT32_STRLEN];
556             snprintf(netIdStr, sizeof(netIdStr), "%u", sTetherCtrl->getDnsNetId());
557             cli->sendMsg(ResponseCode::TetherDnsFwdNetIdResult, netIdStr, false);
558
559             NetAddressCollection *dlist = sTetherCtrl->getDnsForwarders();
560             NetAddressCollection::iterator it;
561
562             for (it = dlist->begin(); it != dlist->end(); ++it) {
563                 cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, inet_ntoa(*it), false);
564             }
565         }
566     } else {
567         /*
568          * These commands take a minimum of 4 arguments
569          */
570         if (argc < 4) {
571             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
572             return 0;
573         }
574
575         if (!strcmp(argv[1], "start")) {
576             if (argc % 2 == 1) {
577                 cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false);
578                 return 0;
579             }
580
581             int num_addrs = argc - 2;
582             int arg_index = 2;
583             int array_index = 0;
584             in_addr *addrs = (in_addr *)malloc(sizeof(in_addr) * num_addrs);
585             while (array_index < num_addrs) {
586                 if (!inet_aton(argv[arg_index++], &(addrs[array_index++]))) {
587                     cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
588                     free(addrs);
589                     return 0;
590                 }
591             }
592             rc = sTetherCtrl->startTethering(num_addrs, addrs);
593             free(addrs);
594         } else if (!strcmp(argv[1], "interface")) {
595             if (!strcmp(argv[2], "add")) {
596                 rc = sTetherCtrl->tetherInterface(argv[3]);
597             } else if (!strcmp(argv[2], "remove")) {
598                 rc = sTetherCtrl->untetherInterface(argv[3]);
599             /* else if (!strcmp(argv[2], "list")) handled above */
600             } else {
601                 cli->sendMsg(ResponseCode::CommandParameterError,
602                              "Unknown tether interface operation", false);
603                 return 0;
604             }
605         } else if (!strcmp(argv[1], "dns")) {
606             if (!strcmp(argv[2], "set")) {
607                 if (argc < 5) {
608                     cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
609                     return 0;
610                 }
611                 unsigned netId = stringToNetId(argv[3]);
612                 rc = sTetherCtrl->setDnsForwarders(netId, &argv[4], argc - 4);
613             /* else if (!strcmp(argv[2], "list")) handled above */
614             } else {
615                 cli->sendMsg(ResponseCode::CommandParameterError,
616                              "Unknown tether interface operation", false);
617                 return 0;
618             }
619         } else {
620             cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
621             return 0;
622         }
623     }
624
625     if (!rc) {
626         cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
627     } else {
628         cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
629     }
630
631     return 0;
632 }
633
634 CommandListener::NatCmd::NatCmd() :
635                  NetdCommand("nat") {
636 }
637
638 int CommandListener::NatCmd::runCommand(SocketClient *cli,
639                                                       int argc, char **argv) {
640     int rc = 0;
641
642     if (argc < 5) {
643         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
644         return 0;
645     }
646
647     //  0     1       2        3
648     // nat  enable intiface extiface
649     // nat disable intiface extiface
650     if (!strcmp(argv[1], "enable") && argc >= 4) {
651         rc = sNatCtrl->enableNat(argv[2], argv[3]);
652         if(!rc) {
653             /* Ignore ifaces for now. */
654             rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
655         }
656     } else if (!strcmp(argv[1], "disable") && argc >= 4) {
657         /* Ignore ifaces for now. */
658         rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
659         rc |= sNatCtrl->disableNat(argv[2], argv[3]);
660     } else {
661         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
662         return 0;
663     }
664
665     if (!rc) {
666         cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
667     } else {
668         cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
669     }
670
671     return 0;
672 }
673
674 CommandListener::PppdCmd::PppdCmd() :
675                  NetdCommand("pppd") {
676 }
677
678 int CommandListener::PppdCmd::runCommand(SocketClient *cli,
679                                                       int argc, char **argv) {
680     int rc = 0;
681
682     if (argc < 3) {
683         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
684         return 0;
685     }
686
687     if (!strcmp(argv[1], "attach")) {
688         struct in_addr l, r, dns1, dns2;
689
690         memset(&dns1, 0, sizeof(struct in_addr));
691         memset(&dns2, 0, sizeof(struct in_addr));
692
693         if (!inet_aton(argv[3], &l)) {
694             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false);
695             return 0;
696         }
697         if (!inet_aton(argv[4], &r)) {
698             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false);
699             return 0;
700         }
701         if ((argc > 3) && (!inet_aton(argv[5], &dns1))) {
702             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false);
703             return 0;
704         }
705         if ((argc > 4) && (!inet_aton(argv[6], &dns2))) {
706             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false);
707             return 0;
708         }
709         rc = sPppCtrl->attachPppd(argv[2], l, r, dns1, dns2);
710     } else if (!strcmp(argv[1], "detach")) {
711         rc = sPppCtrl->detachPppd(argv[2]);
712     } else {
713         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false);
714         return 0;
715     }
716
717     if (!rc) {
718         cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false);
719     } else {
720         cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true);
721     }
722
723     return 0;
724 }
725
726 CommandListener::SoftapCmd::SoftapCmd() :
727                  NetdCommand("softap") {
728 }
729
730 int CommandListener::SoftapCmd::runCommand(SocketClient *cli,
731                                         int argc, char **argv) {
732     int rc = ResponseCode::SoftapStatusResult;
733     char *retbuf = NULL;
734
735     if (sSoftapCtrl == NULL) {
736       cli->sendMsg(ResponseCode::ServiceStartFailed, "SoftAP is not available", false);
737       return -1;
738     }
739     if (argc < 2) {
740         cli->sendMsg(ResponseCode::CommandSyntaxError,
741                      "Missing argument in a SoftAP command", false);
742         return 0;
743     }
744
745     if (!strcmp(argv[1], "startap")) {
746         rc = sSoftapCtrl->startSoftap();
747     } else if (!strcmp(argv[1], "stopap")) {
748         rc = sSoftapCtrl->stopSoftap();
749     } else if (!strcmp(argv[1], "fwreload")) {
750         rc = sSoftapCtrl->fwReloadSoftap(argc, argv);
751     } else if (!strcmp(argv[1], "status")) {
752         asprintf(&retbuf, "Softap service %s running",
753                  (sSoftapCtrl->isSoftapStarted() ? "is" : "is not"));
754         cli->sendMsg(rc, retbuf, false);
755         free(retbuf);
756         return 0;
757     } else if (!strcmp(argv[1], "set")) {
758         rc = sSoftapCtrl->setSoftap(argc, argv);
759     } else {
760         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unrecognized SoftAP command", false);
761         return 0;
762     }
763
764     if (rc >= 400 && rc < 600)
765       cli->sendMsg(rc, "SoftAP command has failed", false);
766     else
767       cli->sendMsg(rc, "Ok", false);
768
769     return 0;
770 }
771
772 CommandListener::ResolverCmd::ResolverCmd() :
773         NetdCommand("resolver") {
774 }
775
776 int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **margv) {
777     int rc = 0;
778     const char **argv = const_cast<const char **>(margv);
779
780     if (argc < 2) {
781         cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false);
782         return 0;
783     }
784
785     if (!strcmp(argv[1], "setnetdns")) {
786         // "resolver setnetdns <netId> <domains> <dns1> <dns2> ..."
787         if (argc >= 5) {
788             rc = sResolverCtrl->setDnsServers(strtoul(argv[2], NULL, 0), argv[3], &argv[4], argc - 4);
789         } else {
790             cli->sendMsg(ResponseCode::CommandSyntaxError,
791                     "Wrong number of arguments to resolver setnetdns", false);
792             return 0;
793         }
794     } else if (!strcmp(argv[1], "flushnet")) { // "resolver flushnet <netId>"
795         if (argc == 3) {
796             rc = sResolverCtrl->flushDnsCache(strtoul(argv[2], NULL, 0));
797         } else {
798             cli->sendMsg(ResponseCode::CommandSyntaxError,
799                     "Wrong number of arguments to resolver flushnet", false);
800             return 0;
801         }
802     } else {
803         cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false);
804         return 0;
805     }
806
807     if (!rc) {
808         cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false);
809     } else {
810         cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true);
811     }
812
813     return 0;
814 }
815
816 CommandListener::BandwidthControlCmd::BandwidthControlCmd() :
817     NetdCommand("bandwidth") {
818 }
819
820 void CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) {
821     char *msg;
822     asprintf(&msg, "Usage: bandwidth %s", usageMsg);
823     cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false);
824     free(msg);
825 }
826
827 void CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) {
828     if (!cond) {
829         cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
830     } else {
831         cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false);
832     }
833 }
834
835 void CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) {
836     cli->sendMsg(ResponseCode::OperationFailed, errMsg, false);
837 }
838
839 int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
840     if (argc < 2) {
841         sendGenericSyntaxError(cli, "<cmds> <args...>");
842         return 0;
843     }
844
845     ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
846
847     if (!strcmp(argv[1], "enable")) {
848         int rc = sBandwidthCtrl->enableBandwidthControl(true);
849         sendGenericOkFail(cli, rc);
850         return 0;
851
852     }
853     if (!strcmp(argv[1], "disable")) {
854         int rc = sBandwidthCtrl->disableBandwidthControl();
855         sendGenericOkFail(cli, rc);
856         return 0;
857
858     }
859     if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
860         if (argc != 3) {
861             sendGenericSyntaxError(cli, "removequota <interface>");
862             return 0;
863         }
864         int rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[2]);
865         sendGenericOkFail(cli, rc);
866         return 0;
867
868     }
869     if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) {
870         int64_t bytes;
871         if (argc != 2) {
872             sendGenericSyntaxError(cli, "getquota");
873             return 0;
874         }
875         int rc = sBandwidthCtrl->getInterfaceSharedQuota(&bytes);
876         if (rc) {
877             sendGenericOpFailed(cli, "Failed to get quota");
878             return 0;
879         }
880
881         char *msg;
882         asprintf(&msg, "%" PRId64, bytes);
883         cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
884         free(msg);
885         return 0;
886
887     }
888     if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) {
889         int64_t bytes;
890         if (argc != 3) {
891             sendGenericSyntaxError(cli, "getiquota <iface>");
892             return 0;
893         }
894
895         int rc = sBandwidthCtrl->getInterfaceQuota(argv[2], &bytes);
896         if (rc) {
897             sendGenericOpFailed(cli, "Failed to get quota");
898             return 0;
899         }
900         char *msg;
901         asprintf(&msg, "%" PRId64, bytes);
902         cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
903         free(msg);
904         return 0;
905
906     }
907     if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
908         if (argc != 4) {
909             sendGenericSyntaxError(cli, "setquota <interface> <bytes>");
910             return 0;
911         }
912         int rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[2], atoll(argv[3]));
913         sendGenericOkFail(cli, rc);
914         return 0;
915     }
916     if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
917         int rc;
918         if (argc < 4) {
919             sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ...");
920             return 0;
921         }
922
923         for (int q = 3; argc >= 4; q++, argc--) {
924             rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[q], atoll(argv[2]));
925             if (rc) {
926                 char *msg;
927                 asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]);
928                 cli->sendMsg(ResponseCode::OperationFailed,
929                              msg, false);
930                 free(msg);
931                 return 0;
932             }
933         }
934         sendGenericOkFail(cli, rc);
935         return 0;
936
937     }
938     if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) {
939         int rc;
940         if (argc < 3) {
941             sendGenericSyntaxError(cli, "removequotas <interface> ...");
942             return 0;
943         }
944
945         for (int q = 2; argc >= 3; q++, argc--) {
946             rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[q]);
947             if (rc) {
948                 char *msg;
949                 asprintf(&msg, "bandwidth removequotas %s failed", argv[q]);
950                 cli->sendMsg(ResponseCode::OperationFailed,
951                              msg, false);
952                 free(msg);
953                 return 0;
954             }
955         }
956         sendGenericOkFail(cli, rc);
957         return 0;
958
959     }
960     if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
961         if (argc != 3) {
962             sendGenericSyntaxError(cli, "removeiquota <interface>");
963             return 0;
964         }
965         int rc = sBandwidthCtrl->removeInterfaceQuota(argv[2]);
966         sendGenericOkFail(cli, rc);
967         return 0;
968
969     }
970     if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
971         if (argc != 4) {
972             sendGenericSyntaxError(cli, "setiquota <interface> <bytes>");
973             return 0;
974         }
975         int rc = sBandwidthCtrl->setInterfaceQuota(argv[2], atoll(argv[3]));
976         sendGenericOkFail(cli, rc);
977         return 0;
978
979     }
980     if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
981         if (argc < 3) {
982             sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ...");
983             return 0;
984         }
985         int rc = sBandwidthCtrl->addNaughtyApps(argc - 2, argv + 2);
986         sendGenericOkFail(cli, rc);
987         return 0;
988
989
990     }
991     if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
992         if (argc < 3) {
993             sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ...");
994             return 0;
995         }
996         int rc = sBandwidthCtrl->removeNaughtyApps(argc - 2, argv + 2);
997         sendGenericOkFail(cli, rc);
998         return 0;
999     }
1000     if (!strcmp(argv[1], "happybox")) {
1001         if (argc < 3) {
1002             sendGenericSyntaxError(cli, "happybox (enable | disable)");
1003             return 0;
1004         }
1005         if (!strcmp(argv[2], "enable")) {
1006             int rc = sBandwidthCtrl->enableHappyBox();
1007             sendGenericOkFail(cli, rc);
1008             return 0;
1009
1010         }
1011         if (!strcmp(argv[2], "disable")) {
1012             int rc = sBandwidthCtrl->disableHappyBox();
1013             sendGenericOkFail(cli, rc);
1014             return 0;
1015         }
1016         sendGenericSyntaxError(cli, "happybox (enable | disable)");
1017         return 0;
1018     }
1019     if (!strcmp(argv[1], "addniceapps") || !strcmp(argv[1], "aha")) {
1020         if (argc < 3) {
1021             sendGenericSyntaxError(cli, "addniceapps <appUid> ...");
1022             return 0;
1023         }
1024         int rc = sBandwidthCtrl->addNiceApps(argc - 2, argv + 2);
1025         sendGenericOkFail(cli, rc);
1026         return 0;
1027     }
1028     if (!strcmp(argv[1], "removeniceapps") || !strcmp(argv[1], "rha")) {
1029         if (argc < 3) {
1030             sendGenericSyntaxError(cli, "removeniceapps <appUid> ...");
1031             return 0;
1032         }
1033         int rc = sBandwidthCtrl->removeNiceApps(argc - 2, argv + 2);
1034         sendGenericOkFail(cli, rc);
1035         return 0;
1036     }
1037     if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) {
1038         if (argc != 3) {
1039             sendGenericSyntaxError(cli, "setglobalalert <bytes>");
1040             return 0;
1041         }
1042         int rc = sBandwidthCtrl->setGlobalAlert(atoll(argv[2]));
1043         sendGenericOkFail(cli, rc);
1044         return 0;
1045     }
1046     if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) {
1047         if (argc != 4) {
1048             sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>");
1049             return 0;
1050         }
1051         /* We ignore the interfaces for now. */
1052         int rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
1053         sendGenericOkFail(cli, rc);
1054         return 0;
1055
1056     }
1057     if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
1058         if (argc != 2) {
1059             sendGenericSyntaxError(cli, "removeglobalalert");
1060             return 0;
1061         }
1062         int rc = sBandwidthCtrl->removeGlobalAlert();
1063         sendGenericOkFail(cli, rc);
1064         return 0;
1065
1066     }
1067     if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) {
1068         if (argc != 4) {
1069             sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>");
1070             return 0;
1071         }
1072         /* We ignore the interfaces for now. */
1073         int rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
1074         sendGenericOkFail(cli, rc);
1075         return 0;
1076
1077     }
1078     if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
1079         if (argc != 3) {
1080             sendGenericSyntaxError(cli, "setsharedalert <bytes>");
1081             return 0;
1082         }
1083         int rc = sBandwidthCtrl->setSharedAlert(atoll(argv[2]));
1084         sendGenericOkFail(cli, rc);
1085         return 0;
1086
1087     }
1088     if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) {
1089         if (argc != 2) {
1090             sendGenericSyntaxError(cli, "removesharedalert");
1091             return 0;
1092         }
1093         int rc = sBandwidthCtrl->removeSharedAlert();
1094         sendGenericOkFail(cli, rc);
1095         return 0;
1096
1097     }
1098     if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) {
1099         if (argc != 4) {
1100             sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>");
1101             return 0;
1102         }
1103         int rc = sBandwidthCtrl->setInterfaceAlert(argv[2], atoll(argv[3]));
1104         sendGenericOkFail(cli, rc);
1105         return 0;
1106
1107     }
1108     if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) {
1109         if (argc != 3) {
1110             sendGenericSyntaxError(cli, "removeinterfacealert <interface>");
1111             return 0;
1112         }
1113         int rc = sBandwidthCtrl->removeInterfaceAlert(argv[2]);
1114         sendGenericOkFail(cli, rc);
1115         return 0;
1116
1117     }
1118     if (!strcmp(argv[1], "gettetherstats") || !strcmp(argv[1], "gts")) {
1119         BandwidthController::TetherStats tetherStats;
1120         std::string extraProcessingInfo = "";
1121         if (argc < 2 || argc > 4) {
1122             sendGenericSyntaxError(cli, "gettetherstats [<intInterface> <extInterface>]");
1123             return 0;
1124         }
1125         tetherStats.intIface = argc > 2 ? argv[2] : "";
1126         tetherStats.extIface = argc > 3 ? argv[3] : "";
1127         // No filtering requested and there are no interface pairs to lookup.
1128         if (argc <= 2 && sNatCtrl->ifacePairList.empty()) {
1129             cli->sendMsg(ResponseCode::CommandOkay, "Tethering stats list completed", false);
1130             return 0;
1131         }
1132         int rc = sBandwidthCtrl->getTetherStats(cli, tetherStats, extraProcessingInfo);
1133         if (rc) {
1134                 extraProcessingInfo.insert(0, "Failed to get tethering stats.\n");
1135                 sendGenericOpFailed(cli, extraProcessingInfo.c_str());
1136                 return 0;
1137         }
1138         return 0;
1139
1140     }
1141
1142     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
1143     return 0;
1144 }
1145
1146 CommandListener::IdletimerControlCmd::IdletimerControlCmd() :
1147     NetdCommand("idletimer") {
1148 }
1149
1150 int CommandListener::IdletimerControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
1151   // TODO(ashish): Change the error statements
1152     if (argc < 2) {
1153         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1154         return 0;
1155     }
1156
1157     ALOGV("idletimerctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
1158
1159     if (!strcmp(argv[1], "enable")) {
1160       if (0 != sIdletimerCtrl->enableIdletimerControl()) {
1161         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1162       } else {
1163         cli->sendMsg(ResponseCode::CommandOkay, "Enable success", false);
1164       }
1165       return 0;
1166
1167     }
1168     if (!strcmp(argv[1], "disable")) {
1169       if (0 != sIdletimerCtrl->disableIdletimerControl()) {
1170         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1171       } else {
1172         cli->sendMsg(ResponseCode::CommandOkay, "Disable success", false);
1173       }
1174       return 0;
1175     }
1176     if (!strcmp(argv[1], "add")) {
1177         if (argc != 5) {
1178             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1179             return 0;
1180         }
1181         if(0 != sIdletimerCtrl->addInterfaceIdletimer(
1182                                         argv[2], atoi(argv[3]), argv[4])) {
1183           cli->sendMsg(ResponseCode::OperationFailed, "Failed to add interface", false);
1184         } else {
1185           cli->sendMsg(ResponseCode::CommandOkay,  "Add success", false);
1186         }
1187         return 0;
1188     }
1189     if (!strcmp(argv[1], "remove")) {
1190         if (argc != 5) {
1191             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1192             return 0;
1193         }
1194         // ashish: fixme timeout
1195         if (0 != sIdletimerCtrl->removeInterfaceIdletimer(
1196                                         argv[2], atoi(argv[3]), argv[4])) {
1197           cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove interface", false);
1198         } else {
1199           cli->sendMsg(ResponseCode::CommandOkay, "Remove success", false);
1200         }
1201         return 0;
1202     }
1203
1204     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown idletimer cmd", false);
1205     return 0;
1206 }
1207
1208 CommandListener::FirewallCmd::FirewallCmd() :
1209     NetdCommand("firewall") {
1210 }
1211
1212 int CommandListener::FirewallCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1213     if (!cond) {
1214         cli->sendMsg(ResponseCode::CommandOkay, "Firewall command succeeded", false);
1215     } else {
1216         cli->sendMsg(ResponseCode::OperationFailed, "Firewall command failed", false);
1217     }
1218     return 0;
1219 }
1220
1221 FirewallRule CommandListener::FirewallCmd::parseRule(const char* arg) {
1222     if (!strcmp(arg, "allow")) {
1223         return ALLOW;
1224     } else {
1225         return DENY;
1226     }
1227 }
1228
1229 int CommandListener::FirewallCmd::runCommand(SocketClient *cli, int argc,
1230         char **argv) {
1231     if (argc < 2) {
1232         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
1233         return 0;
1234     }
1235
1236     if (!strcmp(argv[1], "enable")) {
1237         int res = sFirewallCtrl->enableFirewall();
1238         return sendGenericOkFail(cli, res);
1239     }
1240     if (!strcmp(argv[1], "disable")) {
1241         int res = sFirewallCtrl->disableFirewall();
1242         return sendGenericOkFail(cli, res);
1243     }
1244     if (!strcmp(argv[1], "is_enabled")) {
1245         int res = sFirewallCtrl->isFirewallEnabled();
1246         return sendGenericOkFail(cli, res);
1247     }
1248
1249     if (!strcmp(argv[1], "set_interface_rule")) {
1250         if (argc != 4) {
1251             cli->sendMsg(ResponseCode::CommandSyntaxError,
1252                          "Usage: firewall set_interface_rule <rmnet0> <allow|deny>", false);
1253             return 0;
1254         }
1255
1256         const char* iface = argv[2];
1257         FirewallRule rule = parseRule(argv[3]);
1258
1259         int res = sFirewallCtrl->setInterfaceRule(iface, rule);
1260         return sendGenericOkFail(cli, res);
1261     }
1262
1263     if (!strcmp(argv[1], "set_egress_source_rule")) {
1264         if (argc != 4) {
1265             cli->sendMsg(ResponseCode::CommandSyntaxError,
1266                          "Usage: firewall set_egress_source_rule <192.168.0.1> <allow|deny>",
1267                          false);
1268             return 0;
1269         }
1270
1271         const char* addr = argv[2];
1272         FirewallRule rule = parseRule(argv[3]);
1273
1274         int res = sFirewallCtrl->setEgressSourceRule(addr, rule);
1275         return sendGenericOkFail(cli, res);
1276     }
1277
1278     if (!strcmp(argv[1], "set_egress_dest_rule")) {
1279         if (argc != 5) {
1280             cli->sendMsg(ResponseCode::CommandSyntaxError,
1281                          "Usage: firewall set_egress_dest_rule <192.168.0.1> <80> <allow|deny>",
1282                          false);
1283             return 0;
1284         }
1285
1286         const char* addr = argv[2];
1287         int port = atoi(argv[3]);
1288         FirewallRule rule = parseRule(argv[4]);
1289
1290         int res = 0;
1291         res |= sFirewallCtrl->setEgressDestRule(addr, PROTOCOL_TCP, port, rule);
1292         res |= sFirewallCtrl->setEgressDestRule(addr, PROTOCOL_UDP, port, rule);
1293         return sendGenericOkFail(cli, res);
1294     }
1295
1296     if (!strcmp(argv[1], "set_uid_rule")) {
1297         if (argc != 4) {
1298             cli->sendMsg(ResponseCode::CommandSyntaxError,
1299                          "Usage: firewall set_uid_rule <1000> <allow|deny>",
1300                          false);
1301             return 0;
1302         }
1303
1304         int uid = atoi(argv[2]);
1305         FirewallRule rule = parseRule(argv[3]);
1306
1307         int res = sFirewallCtrl->setUidRule(uid, rule);
1308         return sendGenericOkFail(cli, res);
1309     }
1310
1311     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
1312     return 0;
1313 }
1314
1315 CommandListener::ClatdCmd::ClatdCmd() : NetdCommand("clatd") {
1316 }
1317
1318 int CommandListener::ClatdCmd::runCommand(SocketClient *cli, int argc,
1319                                                             char **argv) {
1320     int rc = 0;
1321     if (argc < 3) {
1322         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1323         return 0;
1324     }
1325
1326     if (!strcmp(argv[1], "stop")) {
1327         rc = sClatdCtrl->stopClatd(argv[2]);
1328     } else if (!strcmp(argv[1], "status")) {
1329         char *tmp = NULL;
1330         asprintf(&tmp, "Clatd status: %s", (sClatdCtrl->isClatdStarted(argv[2]) ?
1331                                             "started" : "stopped"));
1332         cli->sendMsg(ResponseCode::ClatdStatusResult, tmp, false);
1333         free(tmp);
1334         return 0;
1335     } else if (!strcmp(argv[1], "start")) {
1336         rc = sClatdCtrl->startClatd(argv[2]);
1337     } else {
1338         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown clatd cmd", false);
1339         return 0;
1340     }
1341
1342     if (!rc) {
1343         cli->sendMsg(ResponseCode::CommandOkay, "Clatd operation succeeded", false);
1344     } else {
1345         cli->sendMsg(ResponseCode::OperationFailed, "Clatd operation failed", false);
1346     }
1347
1348     return 0;
1349 }
1350
1351 CommandListener::NetworkCommand::NetworkCommand() : NetdCommand("network") {
1352 }
1353
1354 int CommandListener::NetworkCommand::syntaxError(SocketClient* client, const char* message) {
1355     client->sendMsg(ResponseCode::CommandSyntaxError, message, false);
1356     return 0;
1357 }
1358
1359 int CommandListener::NetworkCommand::operationError(SocketClient* client, const char* message,
1360                                                     int ret) {
1361     errno = -ret;
1362     client->sendMsg(ResponseCode::OperationFailed, message, true);
1363     return 0;
1364 }
1365
1366 int CommandListener::NetworkCommand::success(SocketClient* client) {
1367     client->sendMsg(ResponseCode::CommandOkay, "success", false);
1368     return 0;
1369 }
1370
1371 int CommandListener::NetworkCommand::runCommand(SocketClient* client, int argc, char** argv) {
1372     if (argc < 2) {
1373         return syntaxError(client, "Missing argument");
1374     }
1375
1376     //    0      1      2      3      4       5         6            7           8
1377     // network route [legacy <uid>]  add   <netId> <interface> <destination> [nexthop]
1378     // network route [legacy <uid>] remove <netId> <interface> <destination> [nexthop]
1379     //
1380     // nexthop may be either an IPv4/IPv6 address or one of "unreachable" or "throw".
1381     if (!strcmp(argv[1], "route")) {
1382         if (argc < 6 || argc > 9) {
1383             return syntaxError(client, "Incorrect number of arguments");
1384         }
1385
1386         int nextArg = 2;
1387         bool legacy = false;
1388         uid_t uid = 0;
1389         if (!strcmp(argv[nextArg], "legacy")) {
1390             ++nextArg;
1391             legacy = true;
1392             uid = strtoul(argv[nextArg++], NULL, 0);
1393         }
1394
1395         bool add = false;
1396         if (!strcmp(argv[nextArg], "add")) {
1397             add = true;
1398         } else if (strcmp(argv[nextArg], "remove")) {
1399             return syntaxError(client, "Unknown argument");
1400         }
1401         ++nextArg;
1402
1403         if (argc < nextArg + 3 || argc > nextArg + 4) {
1404             return syntaxError(client, "Incorrect number of arguments");
1405         }
1406
1407         unsigned netId = stringToNetId(argv[nextArg++]);
1408         const char* interface = argv[nextArg++];
1409         const char* destination = argv[nextArg++];
1410         const char* nexthop = argc > nextArg ? argv[nextArg] : NULL;
1411
1412         int ret;
1413         if (add) {
1414             ret = sNetCtrl->addRoute(netId, interface, destination, nexthop, legacy, uid);
1415         } else {
1416             ret = sNetCtrl->removeRoute(netId, interface, destination, nexthop, legacy, uid);
1417         }
1418         if (ret) {
1419             return operationError(client, add ? "addRoute() failed" : "removeRoute() failed", ret);
1420         }
1421
1422         return success(client);
1423     }
1424
1425     //    0        1       2       3         4
1426     // network interface  add   <netId> <interface>
1427     // network interface remove <netId> <interface>
1428     if (!strcmp(argv[1], "interface")) {
1429         if (argc != 5) {
1430             return syntaxError(client, "Missing argument");
1431         }
1432         unsigned netId = stringToNetId(argv[3]);
1433         if (!strcmp(argv[2], "add")) {
1434             if (int ret = sNetCtrl->addInterfaceToNetwork(netId, argv[4])) {
1435                 return operationError(client, "addInterfaceToNetwork() failed", ret);
1436             }
1437         } else if (!strcmp(argv[2], "remove")) {
1438             if (int ret = sNetCtrl->removeInterfaceFromNetwork(netId, argv[4])) {
1439                 return operationError(client, "removeInterfaceFromNetwork() failed", ret);
1440             }
1441         } else {
1442             return syntaxError(client, "Unknown argument");
1443         }
1444         return success(client);
1445     }
1446
1447     //    0      1       2         3
1448     // network create <netId> [permission]
1449     //
1450     //    0      1       2     3     4        5
1451     // network create <netId> vpn <hasDns> <secure>
1452     if (!strcmp(argv[1], "create")) {
1453         if (argc < 3) {
1454             return syntaxError(client, "Missing argument");
1455         }
1456         unsigned netId = stringToNetId(argv[2]);
1457         if (argc == 6 && !strcmp(argv[3], "vpn")) {
1458             bool hasDns = atoi(argv[4]);
1459             bool secure = atoi(argv[5]);
1460             if (int ret = sNetCtrl->createVirtualNetwork(netId, hasDns, secure)) {
1461                 return operationError(client, "createVirtualNetwork() failed", ret);
1462             }
1463         } else if (argc > 4) {
1464             return syntaxError(client, "Unknown trailing argument(s)");
1465         } else {
1466             Permission permission = PERMISSION_NONE;
1467             if (argc == 4) {
1468                 permission = stringToPermission(argv[3]);
1469                 if (permission == PERMISSION_NONE) {
1470                     return syntaxError(client, "Unknown permission");
1471                 }
1472             }
1473             if (int ret = sNetCtrl->createPhysicalNetwork(netId, permission)) {
1474                 return operationError(client, "createPhysicalNetwork() failed", ret);
1475             }
1476         }
1477         return success(client);
1478     }
1479
1480     //    0       1       2
1481     // network destroy <netId>
1482     if (!strcmp(argv[1], "destroy")) {
1483         if (argc != 3) {
1484             return syntaxError(client, "Incorrect number of arguments");
1485         }
1486         unsigned netId = stringToNetId(argv[2]);
1487         if (int ret = sNetCtrl->destroyNetwork(netId)) {
1488             return operationError(client, "destroyNetwork() failed", ret);
1489         }
1490         return success(client);
1491     }
1492
1493     //    0       1      2      3
1494     // network default  set  <netId>
1495     // network default clear
1496     if (!strcmp(argv[1], "default")) {
1497         if (argc < 3) {
1498             return syntaxError(client, "Missing argument");
1499         }
1500         unsigned netId = NETID_UNSET;
1501         if (!strcmp(argv[2], "set")) {
1502             if (argc < 4) {
1503                 return syntaxError(client, "Missing netId");
1504             }
1505             netId = stringToNetId(argv[3]);
1506         } else if (strcmp(argv[2], "clear")) {
1507             return syntaxError(client, "Unknown argument");
1508         }
1509         if (int ret = sNetCtrl->setDefaultNetwork(netId)) {
1510             return operationError(client, "setDefaultNetwork() failed", ret);
1511         }
1512         return success(client);
1513     }
1514
1515     //    0        1         2      3        4          5
1516     // network permission   user   set  <permission>  <uid> ...
1517     // network permission   user  clear    <uid> ...
1518     // network permission network  set  <permission> <netId> ...
1519     // network permission network clear   <netId> ...
1520     if (!strcmp(argv[1], "permission")) {
1521         if (argc < 5) {
1522             return syntaxError(client, "Missing argument");
1523         }
1524         int nextArg = 4;
1525         Permission permission = PERMISSION_NONE;
1526         if (!strcmp(argv[3], "set")) {
1527             permission = stringToPermission(argv[4]);
1528             if (permission == PERMISSION_NONE) {
1529                 return syntaxError(client, "Unknown permission");
1530             }
1531             nextArg = 5;
1532         } else if (strcmp(argv[3], "clear")) {
1533             return syntaxError(client, "Unknown argument");
1534         }
1535         if (nextArg == argc) {
1536             return syntaxError(client, "Missing id");
1537         }
1538         std::vector<unsigned> ids;
1539         for (; nextArg < argc; ++nextArg) {
1540             char* endPtr;
1541             unsigned id = strtoul(argv[nextArg], &endPtr, 0);
1542             if (!*argv[nextArg] || *endPtr) {
1543                 return syntaxError(client, "Invalid id");
1544             }
1545             ids.push_back(id);
1546         }
1547         if (!strcmp(argv[2], "user")) {
1548             sNetCtrl->setPermissionForUsers(permission, ids);
1549         } else if (!strcmp(argv[2], "network")) {
1550             if (int ret = sNetCtrl->setPermissionForNetworks(permission, ids)) {
1551                 return operationError(client, "setPermissionForNetworks() failed", ret);
1552             }
1553         } else {
1554             return syntaxError(client, "Unknown argument");
1555         }
1556         return success(client);
1557     }
1558
1559     //    0      1     2       3           4
1560     // network users  add   <netId> [<uid>[-<uid>]] ...
1561     // network users remove <netId> [<uid>[-<uid>]] ...
1562     if (!strcmp(argv[1], "users")) {
1563         if (argc < 4) {
1564             return syntaxError(client, "Missing argument");
1565         }
1566         unsigned netId = stringToNetId(argv[3]);
1567         UidRanges uidRanges;
1568         if (!uidRanges.parseFrom(argc - 4, argv + 4)) {
1569             return syntaxError(client, "Invalid UIDs");
1570         }
1571         if (!strcmp(argv[2], "add")) {
1572             if (int ret = sNetCtrl->addUsersToNetwork(netId, uidRanges)) {
1573                 return operationError(client, "addUsersToNetwork() failed", ret);
1574             }
1575         } else if (!strcmp(argv[2], "remove")) {
1576             if (int ret = sNetCtrl->removeUsersFromNetwork(netId, uidRanges)) {
1577                 return operationError(client, "removeUsersFromNetwork() failed", ret);
1578             }
1579         } else {
1580             return syntaxError(client, "Unknown argument");
1581         }
1582         return success(client);
1583     }
1584
1585     //    0       1      2     3
1586     // network protect allow <uid> ...
1587     // network protect  deny <uid> ...
1588     if (!strcmp(argv[1], "protect")) {
1589         if (argc < 4) {
1590             return syntaxError(client, "Missing argument");
1591         }
1592         std::vector<uid_t> uids;
1593         for (int i = 3; i < argc; ++i) {
1594             uids.push_back(strtoul(argv[i], NULL, 0));
1595         }
1596         if (!strcmp(argv[2], "allow")) {
1597             sNetCtrl->allowProtect(uids);
1598         } else if (!strcmp(argv[2], "deny")) {
1599             sNetCtrl->denyProtect(uids);
1600         } else {
1601             return syntaxError(client, "Unknown argument");
1602         }
1603         return success(client);
1604     }
1605
1606     return syntaxError(client, "Unknown argument");
1607 }