OSDN Git Service

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