OSDN Git Service

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