OSDN Git Service

Add counters for IPv6 tethering.
[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 #include <resolv_params.h>
30
31 #define __STDC_FORMAT_MACROS 1
32 #include <inttypes.h>
33
34 #define LOG_TAG "CommandListener"
35
36 #include <cutils/log.h>
37 #include <netutils/ifc.h>
38 #include <sysutils/SocketClient.h>
39
40 #include "Controllers.h"
41 #include "CommandListener.h"
42 #include "ResponseCode.h"
43 #include "BandwidthController.h"
44 #include "IdletimerController.h"
45 #include "InterfaceController.h"
46 #include "oem_iptables_hook.h"
47 #include "NetdConstants.h"
48 #include "FirewallController.h"
49 #include "RouteController.h"
50 #include "UidRanges.h"
51
52 #include <string>
53 #include <vector>
54
55 using android::net::gCtls;
56
57 namespace {
58
59 const unsigned NUM_OEM_IDS = NetworkController::MAX_OEM_ID - NetworkController::MIN_OEM_ID + 1;
60
61 Permission stringToPermission(const char* arg) {
62     if (!strcmp(arg, "NETWORK")) {
63         return PERMISSION_NETWORK;
64     }
65     if (!strcmp(arg, "SYSTEM")) {
66         return PERMISSION_SYSTEM;
67     }
68     return PERMISSION_NONE;
69 }
70
71 unsigned stringToNetId(const char* arg) {
72     if (!strcmp(arg, "local")) {
73         return NetworkController::LOCAL_NET_ID;
74     }
75     // OEM NetIds are "oem1", "oem2", .., "oem50".
76     if (!strncmp(arg, "oem", 3)) {
77         unsigned n = strtoul(arg + 3, NULL, 0);
78         if (1 <= n && n <= NUM_OEM_IDS) {
79             return NetworkController::MIN_OEM_ID + n;
80         }
81         return NETID_UNSET;
82     }
83     // strtoul() returns 0 on errors, which is fine because 0 is an invalid netId.
84     return strtoul(arg, NULL, 0);
85 }
86
87 class LockingFrameworkCommand : public FrameworkCommand {
88 public:
89     LockingFrameworkCommand(FrameworkCommand *wrappedCmd, android::RWLock& lock) :
90             FrameworkCommand(wrappedCmd->getCommand()),
91             mWrappedCmd(wrappedCmd),
92             mLock(lock) {}
93
94     int runCommand(SocketClient *c, int argc, char **argv) {
95         android::RWLock::AutoWLock lock(mLock);
96         return mWrappedCmd->runCommand(c, argc, argv);
97     }
98
99 private:
100     FrameworkCommand *mWrappedCmd;
101     android::RWLock& mLock;
102 };
103
104
105 }  // namespace
106
107 /**
108  * List of module chains to be created, along with explicit ordering. ORDERING
109  * IS CRITICAL, AND SHOULD BE TRIPLE-CHECKED WITH EACH CHANGE.
110  */
111 static const char* FILTER_INPUT[] = {
112         // Bandwidth should always be early in input chain, to make sure we
113         // correctly count incoming traffic against data plan.
114         BandwidthController::LOCAL_INPUT,
115         FirewallController::LOCAL_INPUT,
116         NULL,
117 };
118
119 static const char* FILTER_FORWARD[] = {
120         OEM_IPTABLES_FILTER_FORWARD,
121         FirewallController::LOCAL_FORWARD,
122         BandwidthController::LOCAL_FORWARD,
123         NatController::LOCAL_FORWARD,
124         NULL,
125 };
126
127 static const char* FILTER_OUTPUT[] = {
128         OEM_IPTABLES_FILTER_OUTPUT,
129         FirewallController::LOCAL_OUTPUT,
130         StrictController::LOCAL_OUTPUT,
131         BandwidthController::LOCAL_OUTPUT,
132         NULL,
133 };
134
135 static const char* RAW_PREROUTING[] = {
136         BandwidthController::LOCAL_RAW_PREROUTING,
137         IdletimerController::LOCAL_RAW_PREROUTING,
138         NULL,
139 };
140
141 static const char* MANGLE_POSTROUTING[] = {
142         BandwidthController::LOCAL_MANGLE_POSTROUTING,
143         IdletimerController::LOCAL_MANGLE_POSTROUTING,
144         NULL,
145 };
146
147 static const char* MANGLE_FORWARD[] = {
148         NatController::LOCAL_MANGLE_FORWARD,
149         NULL,
150 };
151
152 static const char* NAT_PREROUTING[] = {
153         OEM_IPTABLES_NAT_PREROUTING,
154         NULL,
155 };
156
157 static const char* NAT_POSTROUTING[] = {
158         NatController::LOCAL_NAT_POSTROUTING,
159         NULL,
160 };
161
162 static void createChildChains(IptablesTarget target, const char* table, const char* parentChain,
163         const char** childChains) {
164     const char** childChain = childChains;
165     do {
166         // Order is important:
167         // -D to delete any pre-existing jump rule (removes references
168         //    that would prevent -X from working)
169         // -F to flush any existing chain
170         // -X to delete any existing chain
171         // -N to create the chain
172         // -A to append the chain to parent
173
174         execIptablesSilently(target, "-t", table, "-D", parentChain, "-j", *childChain, NULL);
175         execIptablesSilently(target, "-t", table, "-F", *childChain, NULL);
176         execIptablesSilently(target, "-t", table, "-X", *childChain, NULL);
177         execIptables(target, "-t", table, "-N", *childChain, NULL);
178         execIptables(target, "-t", table, "-A", parentChain, "-j", *childChain, NULL);
179     } while (*(++childChain) != NULL);
180 }
181
182 void CommandListener::registerLockingCmd(FrameworkCommand *cmd, android::RWLock& lock) {
183     registerCmd(new LockingFrameworkCommand(cmd, lock));
184 }
185
186 CommandListener::CommandListener() :
187                  FrameworkListener("netd", true) {
188     registerLockingCmd(new InterfaceCmd());
189     registerLockingCmd(new IpFwdCmd());
190     registerLockingCmd(new TetherCmd());
191     registerLockingCmd(new NatCmd());
192     registerLockingCmd(new ListTtysCmd());
193     registerLockingCmd(new PppdCmd());
194     registerLockingCmd(new SoftapCmd());
195     registerLockingCmd(new BandwidthControlCmd(), gCtls->bandwidthCtrl.lock);
196     registerLockingCmd(new IdletimerControlCmd());
197     registerLockingCmd(new ResolverCmd());
198     registerLockingCmd(new FirewallCmd(), gCtls->firewallCtrl.lock);
199     registerLockingCmd(new ClatdCmd());
200     registerLockingCmd(new NetworkCommand());
201     registerLockingCmd(new StrictCmd());
202
203     /*
204      * This is the only time we touch top-level chains in iptables; controllers
205      * should only mutate rules inside of their children chains, as created by
206      * the constants above.
207      *
208      * Modules should never ACCEPT packets (except in well-justified cases);
209      * they should instead defer to any remaining modules using RETURN, or
210      * otherwise DROP/REJECT.
211      */
212
213     // Create chains for children modules
214     createChildChains(V4V6, "filter", "INPUT", FILTER_INPUT);
215     createChildChains(V4V6, "filter", "FORWARD", FILTER_FORWARD);
216     createChildChains(V4V6, "filter", "OUTPUT", FILTER_OUTPUT);
217     createChildChains(V4V6, "raw", "PREROUTING", RAW_PREROUTING);
218     createChildChains(V4V6, "mangle", "POSTROUTING", MANGLE_POSTROUTING);
219     createChildChains(V4V6, "mangle", "FORWARD", MANGLE_FORWARD);
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     gCtls->firewallCtrl.setupIptablesHooks();
228
229     /* Does DROPs in FORWARD by default */
230     gCtls->natCtrl.setupIptablesHooks();
231     /*
232      * Does REJECT in INPUT, OUTPUT. Does counting also.
233      * No DROP/REJECT allowed later in netfilter-flow hook order.
234      */
235     gCtls->bandwidthCtrl.setupIptablesHooks();
236     /*
237      * Counts in nat: PREROUTING, POSTROUTING.
238      * No DROP/REJECT allowed later in netfilter-flow hook order.
239      */
240     gCtls->idletimerCtrl.setupIptablesHooks();
241
242     gCtls->bandwidthCtrl.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], 0)) {
350                     cli->sendMsg(ResponseCode::OperationFailed, "Failed to clear address", true);
351                     ifc_close();
352                     return 0;
353                 }
354                 if (addr.s_addr != 0) {
355                     if (ifc_add_address(argv[2], argv[3], atoi(argv[4]))) {
356                         cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true);
357                         ifc_close();
358                         return 0;
359                     }
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 (InterfaceController::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 (InterfaceController::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], "ipv6ndoffload")) {
442             if (argc != 4) {
443                 cli->sendMsg(ResponseCode::CommandSyntaxError,
444                         "Usage: interface ipv6ndoffload <interface> <enable|disable>",
445                         false);
446                 return 0;
447             }
448             int enable = !strncmp(argv[3], "enable", 7);
449             if (InterfaceController::setIPv6NdOffload(argv[2], enable) == 0) {
450                 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 ND offload changed", false);
451             } else {
452                 cli->sendMsg(ResponseCode::OperationFailed,
453                         "Failed to change IPv6 ND offload state", true);
454             }
455             return 0;
456         } else if (!strcmp(argv[1], "setmtu")) {
457             if (argc != 4) {
458                 cli->sendMsg(ResponseCode::CommandSyntaxError,
459                         "Usage: interface setmtu <interface> <val>", false);
460                 return 0;
461             }
462             if (InterfaceController::setMtu(argv[2], argv[3]) == 0) {
463                 cli->sendMsg(ResponseCode::CommandOkay, "MTU changed", false);
464             } else {
465                 cli->sendMsg(ResponseCode::OperationFailed,
466                         "Failed to set MTU", true);
467             }
468             return 0;
469         } else {
470             cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
471             return 0;
472         }
473     }
474     return 0;
475 }
476
477
478 CommandListener::ListTtysCmd::ListTtysCmd() :
479                  NetdCommand("list_ttys") {
480 }
481
482 int CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
483                                              int /* argc */, char ** /* argv */) {
484     TtyCollection *tlist = gCtls->pppCtrl.getTtyList();
485     TtyCollection::iterator it;
486
487     for (it = tlist->begin(); it != tlist->end(); ++it) {
488         cli->sendMsg(ResponseCode::TtyListResult, *it, false);
489     }
490
491     cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
492     return 0;
493 }
494
495 CommandListener::IpFwdCmd::IpFwdCmd() :
496                  NetdCommand("ipfwd") {
497 }
498
499 int CommandListener::IpFwdCmd::runCommand(SocketClient *cli, int argc, char **argv) {
500     bool matched = false;
501     bool success;
502
503     if (argc == 2) {
504         //   0     1
505         // ipfwd status
506         if (!strcmp(argv[1], "status")) {
507             char *tmp = NULL;
508
509             asprintf(&tmp, "Forwarding %s",
510                      ((gCtls->tetherCtrl.forwardingRequestCount() > 0) ? "enabled" : "disabled"));
511             cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
512             free(tmp);
513             return 0;
514         }
515     } else if (argc == 3) {
516         //  0      1         2
517         // ipfwd enable  <requester>
518         // ipfwd disable <requester>
519         if (!strcmp(argv[1], "enable")) {
520             matched = true;
521             success = gCtls->tetherCtrl.enableForwarding(argv[2]);
522         } else if (!strcmp(argv[1], "disable")) {
523             matched = true;
524             success = gCtls->tetherCtrl.disableForwarding(argv[2]);
525         }
526     } else if (argc == 4) {
527         //  0      1      2     3
528         // ipfwd  add   wlan0 dummy0
529         // ipfwd remove wlan0 dummy0
530         int ret = 0;
531         if (!strcmp(argv[1], "add")) {
532             matched = true;
533             ret = RouteController::enableTethering(argv[2], argv[3]);
534         } else if (!strcmp(argv[1], "remove")) {
535             matched = true;
536             ret = RouteController::disableTethering(argv[2], argv[3]);
537         }
538         success = (ret == 0);
539         errno = -ret;
540     }
541
542     if (!matched) {
543         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
544         return 0;
545     }
546
547     if (success) {
548         cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
549     } else {
550         cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
551     }
552     return 0;
553 }
554
555 CommandListener::TetherCmd::TetherCmd() :
556                  NetdCommand("tether") {
557 }
558
559 int CommandListener::TetherCmd::runCommand(SocketClient *cli,
560                                                       int argc, char **argv) {
561     int rc = 0;
562
563     if (argc < 2) {
564         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
565         return 0;
566     }
567
568     if (!strcmp(argv[1], "stop")) {
569         rc = gCtls->tetherCtrl.stopTethering();
570     } else if (!strcmp(argv[1], "status")) {
571         char *tmp = NULL;
572
573         asprintf(&tmp, "Tethering services %s",
574                  (gCtls->tetherCtrl.isTetheringStarted() ? "started" : "stopped"));
575         cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
576         free(tmp);
577         return 0;
578     } else if (argc == 3) {
579         if (!strcmp(argv[1], "interface") && !strcmp(argv[2], "list")) {
580             for (const auto &ifname : gCtls->tetherCtrl.getTetheredInterfaceList()) {
581                 cli->sendMsg(ResponseCode::TetherInterfaceListResult, ifname.c_str(), false);
582             }
583         } else if (!strcmp(argv[1], "dns") && !strcmp(argv[2], "list")) {
584             char netIdStr[UINT32_STRLEN];
585             snprintf(netIdStr, sizeof(netIdStr), "%u", gCtls->tetherCtrl.getDnsNetId());
586             cli->sendMsg(ResponseCode::TetherDnsFwdNetIdResult, netIdStr, false);
587
588             for (const auto &fwdr : gCtls->tetherCtrl.getDnsForwarders()) {
589                 cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, fwdr.c_str(), false);
590             }
591         }
592     } else {
593         /*
594          * These commands take a minimum of 4 arguments
595          */
596         if (argc < 4) {
597             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
598             return 0;
599         }
600
601         if (!strcmp(argv[1], "start")) {
602             if (argc % 2 == 1) {
603                 cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false);
604                 return 0;
605             }
606
607             const int num_addrs = argc - 2;
608             // TODO: consider moving this validation into TetherController.
609             struct in_addr tmp_addr;
610             for (int arg_index = 2; arg_index < argc; arg_index++) {
611                 if (!inet_aton(argv[arg_index], &tmp_addr)) {
612                     cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
613                     return 0;
614                 }
615             }
616
617             rc = gCtls->tetherCtrl.startTethering(num_addrs, &(argv[2]));
618         } else if (!strcmp(argv[1], "interface")) {
619             if (!strcmp(argv[2], "add")) {
620                 rc = gCtls->tetherCtrl.tetherInterface(argv[3]);
621             } else if (!strcmp(argv[2], "remove")) {
622                 rc = gCtls->tetherCtrl.untetherInterface(argv[3]);
623             /* else if (!strcmp(argv[2], "list")) handled above */
624             } else {
625                 cli->sendMsg(ResponseCode::CommandParameterError,
626                              "Unknown tether interface operation", false);
627                 return 0;
628             }
629         } else if (!strcmp(argv[1], "dns")) {
630             if (!strcmp(argv[2], "set")) {
631                 if (argc < 5) {
632                     cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
633                     return 0;
634                 }
635                 unsigned netId = stringToNetId(argv[3]);
636                 rc = gCtls->tetherCtrl.setDnsForwarders(netId, &argv[4], argc - 4);
637             /* else if (!strcmp(argv[2], "list")) handled above */
638             } else {
639                 cli->sendMsg(ResponseCode::CommandParameterError,
640                              "Unknown tether interface operation", false);
641                 return 0;
642             }
643         } else {
644             cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
645             return 0;
646         }
647     }
648
649     if (!rc) {
650         cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
651     } else {
652         cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
653     }
654
655     return 0;
656 }
657
658 CommandListener::NatCmd::NatCmd() :
659                  NetdCommand("nat") {
660 }
661
662 int CommandListener::NatCmd::runCommand(SocketClient *cli,
663                                                       int argc, char **argv) {
664     int rc = 0;
665
666     if (argc < 5) {
667         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
668         return 0;
669     }
670
671     //  0     1       2        3
672     // nat  enable intiface extiface
673     // nat disable intiface extiface
674     if (!strcmp(argv[1], "enable") && argc >= 4) {
675         rc = gCtls->natCtrl.enableNat(argv[2], argv[3]);
676         if(!rc) {
677             /* Ignore ifaces for now. */
678             rc = gCtls->bandwidthCtrl.setGlobalAlertInForwardChain();
679         }
680     } else if (!strcmp(argv[1], "disable") && argc >= 4) {
681         /* Ignore ifaces for now. */
682         rc = gCtls->bandwidthCtrl.removeGlobalAlertInForwardChain();
683         rc |= gCtls->natCtrl.disableNat(argv[2], argv[3]);
684     } else {
685         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
686         return 0;
687     }
688
689     if (!rc) {
690         cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
691     } else {
692         cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
693     }
694
695     return 0;
696 }
697
698 CommandListener::PppdCmd::PppdCmd() :
699                  NetdCommand("pppd") {
700 }
701
702 int CommandListener::PppdCmd::runCommand(SocketClient *cli,
703                                                       int argc, char **argv) {
704     int rc = 0;
705
706     if (argc < 3) {
707         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
708         return 0;
709     }
710
711     if (!strcmp(argv[1], "attach")) {
712         struct in_addr l, r, dns1, dns2;
713
714         memset(&dns1, 0, sizeof(struct in_addr));
715         memset(&dns2, 0, sizeof(struct in_addr));
716
717         if (!inet_aton(argv[3], &l)) {
718             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false);
719             return 0;
720         }
721         if (!inet_aton(argv[4], &r)) {
722             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false);
723             return 0;
724         }
725         if ((argc > 3) && (!inet_aton(argv[5], &dns1))) {
726             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false);
727             return 0;
728         }
729         if ((argc > 4) && (!inet_aton(argv[6], &dns2))) {
730             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false);
731             return 0;
732         }
733         rc = gCtls->pppCtrl.attachPppd(argv[2], l, r, dns1, dns2);
734     } else if (!strcmp(argv[1], "detach")) {
735         rc = gCtls->pppCtrl.detachPppd(argv[2]);
736     } else {
737         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false);
738         return 0;
739     }
740
741     if (!rc) {
742         cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false);
743     } else {
744         cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true);
745     }
746
747     return 0;
748 }
749
750 CommandListener::SoftapCmd::SoftapCmd() :
751                  NetdCommand("softap") {
752 }
753
754 int CommandListener::SoftapCmd::runCommand(SocketClient *cli,
755                                         int argc, char **argv) {
756     int rc = ResponseCode::SoftapStatusResult;
757     char *retbuf = NULL;
758
759     if (gCtls == nullptr) {
760       cli->sendMsg(ResponseCode::ServiceStartFailed, "SoftAP is not available", false);
761       return -1;
762     }
763     if (argc < 2) {
764         cli->sendMsg(ResponseCode::CommandSyntaxError,
765                      "Missing argument in a SoftAP command", false);
766         return 0;
767     }
768
769     if (!strcmp(argv[1], "startap")) {
770         rc = gCtls->softapCtrl.startSoftap();
771     } else if (!strcmp(argv[1], "stopap")) {
772         rc = gCtls->softapCtrl.stopSoftap();
773     } else if (!strcmp(argv[1], "fwreload")) {
774         rc = gCtls->softapCtrl.fwReloadSoftap(argc, argv);
775     } else if (!strcmp(argv[1], "status")) {
776         asprintf(&retbuf, "Softap service %s running",
777                  (gCtls->softapCtrl.isSoftapStarted() ? "is" : "is not"));
778         cli->sendMsg(rc, retbuf, false);
779         free(retbuf);
780         return 0;
781     } else if (!strcmp(argv[1], "set")) {
782         rc = gCtls->softapCtrl.setSoftap(argc, argv);
783     } else {
784         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unrecognized SoftAP command", false);
785         return 0;
786     }
787
788     if (rc >= 400 && rc < 600)
789       cli->sendMsg(rc, "SoftAP command has failed", false);
790     else
791       cli->sendMsg(rc, "Ok", false);
792
793     return 0;
794 }
795
796 CommandListener::ResolverCmd::ResolverCmd() :
797         NetdCommand("resolver") {
798 }
799
800 int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **margv) {
801     int rc = 0;
802     const char **argv = const_cast<const char **>(margv);
803
804     if (argc < 3) {
805         cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false);
806         return 0;
807     }
808
809     unsigned netId = stringToNetId(argv[2]);
810     // TODO: Consider making NetworkController.isValidNetwork() public
811     // and making that check here.
812
813     if (!strcmp(argv[1], "setnetdns")) {
814         if (!parseAndExecuteSetNetDns(netId, argc, argv)) {
815             cli->sendMsg(ResponseCode::CommandSyntaxError,
816                     "Wrong number of or invalid arguments to resolver setnetdns", false);
817             return 0;
818         }
819     } else if (!strcmp(argv[1], "clearnetdns")) { // "resolver clearnetdns <netId>"
820         if (argc == 3) {
821             rc = gCtls->resolverCtrl.clearDnsServers(netId);
822         } else {
823             cli->sendMsg(ResponseCode::CommandSyntaxError,
824                     "Wrong number of arguments to resolver clearnetdns", false);
825             return 0;
826         }
827     } else {
828         cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false);
829         return 0;
830     }
831
832     if (!rc) {
833         cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false);
834     } else {
835         cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true);
836     }
837
838     return 0;
839 }
840
841 bool CommandListener::ResolverCmd::parseAndExecuteSetNetDns(int netId, int argc,
842         const char** argv) {
843     // "resolver setnetdns <netId> <domains> <dns1> [<dns2> ...] [--params <params>]"
844     // TODO: This code has to be replaced by a Binder call ASAP
845     if (argc < 5) {
846         return false;
847     }
848     int end = argc;
849     __res_params params;
850     const __res_params* paramsPtr = nullptr;
851     if (end > 6 && !strcmp(argv[end - 2], "--params")) {
852         const char* paramsStr = argv[end - 1];
853         end -= 2;
854         if (sscanf(paramsStr, "%hu %hhu %hhu %hhu", &params.sample_validity,
855                 &params.success_threshold, &params.min_samples, &params.max_samples) != 4) {
856             return false;
857         }
858         paramsPtr = &params;
859     }
860     return gCtls->resolverCtrl.setDnsServers(netId, argv[3], &argv[4], end - 4, paramsPtr) == 0;
861 }
862
863 CommandListener::BandwidthControlCmd::BandwidthControlCmd() :
864     NetdCommand("bandwidth") {
865 }
866
867 void CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) {
868     char *msg;
869     asprintf(&msg, "Usage: bandwidth %s", usageMsg);
870     cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false);
871     free(msg);
872 }
873
874 void CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) {
875     if (!cond) {
876         cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
877     } else {
878         cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false);
879     }
880 }
881
882 void CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) {
883     cli->sendMsg(ResponseCode::OperationFailed, errMsg, false);
884 }
885
886 int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
887     if (argc < 2) {
888         sendGenericSyntaxError(cli, "<cmds> <args...>");
889         return 0;
890     }
891
892     ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
893
894     if (!strcmp(argv[1], "enable")) {
895         int rc = gCtls->bandwidthCtrl.enableBandwidthControl(true);
896         sendGenericOkFail(cli, rc);
897         return 0;
898
899     }
900     if (!strcmp(argv[1], "disable")) {
901         int rc = gCtls->bandwidthCtrl.disableBandwidthControl();
902         sendGenericOkFail(cli, rc);
903         return 0;
904
905     }
906     if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
907         if (argc != 3) {
908             sendGenericSyntaxError(cli, "removequota <interface>");
909             return 0;
910         }
911         int rc = gCtls->bandwidthCtrl.removeInterfaceSharedQuota(argv[2]);
912         sendGenericOkFail(cli, rc);
913         return 0;
914
915     }
916     if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) {
917         int64_t bytes;
918         if (argc != 2) {
919             sendGenericSyntaxError(cli, "getquota");
920             return 0;
921         }
922         int rc = gCtls->bandwidthCtrl.getInterfaceSharedQuota(&bytes);
923         if (rc) {
924             sendGenericOpFailed(cli, "Failed to get quota");
925             return 0;
926         }
927
928         char *msg;
929         asprintf(&msg, "%" PRId64, bytes);
930         cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
931         free(msg);
932         return 0;
933
934     }
935     if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) {
936         int64_t bytes;
937         if (argc != 3) {
938             sendGenericSyntaxError(cli, "getiquota <iface>");
939             return 0;
940         }
941
942         int rc = gCtls->bandwidthCtrl.getInterfaceQuota(argv[2], &bytes);
943         if (rc) {
944             sendGenericOpFailed(cli, "Failed to get quota");
945             return 0;
946         }
947         char *msg;
948         asprintf(&msg, "%" PRId64, bytes);
949         cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
950         free(msg);
951         return 0;
952
953     }
954     if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
955         if (argc != 4) {
956             sendGenericSyntaxError(cli, "setquota <interface> <bytes>");
957             return 0;
958         }
959         int rc = gCtls->bandwidthCtrl.setInterfaceSharedQuota(argv[2], atoll(argv[3]));
960         sendGenericOkFail(cli, rc);
961         return 0;
962     }
963     if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
964         int rc;
965         if (argc < 4) {
966             sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ...");
967             return 0;
968         }
969
970         for (int q = 3; argc >= 4; q++, argc--) {
971             rc = gCtls->bandwidthCtrl.setInterfaceSharedQuota(argv[q], atoll(argv[2]));
972             if (rc) {
973                 char *msg;
974                 asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]);
975                 cli->sendMsg(ResponseCode::OperationFailed,
976                              msg, false);
977                 free(msg);
978                 return 0;
979             }
980         }
981         sendGenericOkFail(cli, rc);
982         return 0;
983
984     }
985     if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) {
986         int rc;
987         if (argc < 3) {
988             sendGenericSyntaxError(cli, "removequotas <interface> ...");
989             return 0;
990         }
991
992         for (int q = 2; argc >= 3; q++, argc--) {
993             rc = gCtls->bandwidthCtrl.removeInterfaceSharedQuota(argv[q]);
994             if (rc) {
995                 char *msg;
996                 asprintf(&msg, "bandwidth removequotas %s failed", argv[q]);
997                 cli->sendMsg(ResponseCode::OperationFailed,
998                              msg, false);
999                 free(msg);
1000                 return 0;
1001             }
1002         }
1003         sendGenericOkFail(cli, rc);
1004         return 0;
1005
1006     }
1007     if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
1008         if (argc != 3) {
1009             sendGenericSyntaxError(cli, "removeiquota <interface>");
1010             return 0;
1011         }
1012         int rc = gCtls->bandwidthCtrl.removeInterfaceQuota(argv[2]);
1013         sendGenericOkFail(cli, rc);
1014         return 0;
1015
1016     }
1017     if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
1018         if (argc != 4) {
1019             sendGenericSyntaxError(cli, "setiquota <interface> <bytes>");
1020             return 0;
1021         }
1022         int rc = gCtls->bandwidthCtrl.setInterfaceQuota(argv[2], atoll(argv[3]));
1023         sendGenericOkFail(cli, rc);
1024         return 0;
1025
1026     }
1027     if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
1028         if (argc < 3) {
1029             sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ...");
1030             return 0;
1031         }
1032         int rc = gCtls->bandwidthCtrl.addNaughtyApps(argc - 2, argv + 2);
1033         sendGenericOkFail(cli, rc);
1034         return 0;
1035
1036
1037     }
1038     if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
1039         if (argc < 3) {
1040             sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ...");
1041             return 0;
1042         }
1043         int rc = gCtls->bandwidthCtrl.removeNaughtyApps(argc - 2, argv + 2);
1044         sendGenericOkFail(cli, rc);
1045         return 0;
1046     }
1047     if (!strcmp(argv[1], "addniceapps") || !strcmp(argv[1], "aha")) {
1048         if (argc < 3) {
1049             sendGenericSyntaxError(cli, "addniceapps <appUid> ...");
1050             return 0;
1051         }
1052         int rc = gCtls->bandwidthCtrl.addNiceApps(argc - 2, argv + 2);
1053         sendGenericOkFail(cli, rc);
1054         return 0;
1055     }
1056     if (!strcmp(argv[1], "removeniceapps") || !strcmp(argv[1], "rha")) {
1057         if (argc < 3) {
1058             sendGenericSyntaxError(cli, "removeniceapps <appUid> ...");
1059             return 0;
1060         }
1061         int rc = gCtls->bandwidthCtrl.removeNiceApps(argc - 2, argv + 2);
1062         sendGenericOkFail(cli, rc);
1063         return 0;
1064     }
1065     if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) {
1066         if (argc != 3) {
1067             sendGenericSyntaxError(cli, "setglobalalert <bytes>");
1068             return 0;
1069         }
1070         int rc = gCtls->bandwidthCtrl.setGlobalAlert(atoll(argv[2]));
1071         sendGenericOkFail(cli, rc);
1072         return 0;
1073     }
1074     if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) {
1075         if (argc != 4) {
1076             sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>");
1077             return 0;
1078         }
1079         /* We ignore the interfaces for now. */
1080         int rc = gCtls->bandwidthCtrl.setGlobalAlertInForwardChain();
1081         sendGenericOkFail(cli, rc);
1082         return 0;
1083
1084     }
1085     if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
1086         if (argc != 2) {
1087             sendGenericSyntaxError(cli, "removeglobalalert");
1088             return 0;
1089         }
1090         int rc = gCtls->bandwidthCtrl.removeGlobalAlert();
1091         sendGenericOkFail(cli, rc);
1092         return 0;
1093
1094     }
1095     if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) {
1096         if (argc != 4) {
1097             sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>");
1098             return 0;
1099         }
1100         /* We ignore the interfaces for now. */
1101         int rc = gCtls->bandwidthCtrl.removeGlobalAlertInForwardChain();
1102         sendGenericOkFail(cli, rc);
1103         return 0;
1104
1105     }
1106     if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
1107         if (argc != 3) {
1108             sendGenericSyntaxError(cli, "setsharedalert <bytes>");
1109             return 0;
1110         }
1111         int rc = gCtls->bandwidthCtrl.setSharedAlert(atoll(argv[2]));
1112         sendGenericOkFail(cli, rc);
1113         return 0;
1114
1115     }
1116     if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) {
1117         if (argc != 2) {
1118             sendGenericSyntaxError(cli, "removesharedalert");
1119             return 0;
1120         }
1121         int rc = gCtls->bandwidthCtrl.removeSharedAlert();
1122         sendGenericOkFail(cli, rc);
1123         return 0;
1124
1125     }
1126     if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) {
1127         if (argc != 4) {
1128             sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>");
1129             return 0;
1130         }
1131         int rc = gCtls->bandwidthCtrl.setInterfaceAlert(argv[2], atoll(argv[3]));
1132         sendGenericOkFail(cli, rc);
1133         return 0;
1134
1135     }
1136     if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) {
1137         if (argc != 3) {
1138             sendGenericSyntaxError(cli, "removeinterfacealert <interface>");
1139             return 0;
1140         }
1141         int rc = gCtls->bandwidthCtrl.removeInterfaceAlert(argv[2]);
1142         sendGenericOkFail(cli, rc);
1143         return 0;
1144
1145     }
1146     if (!strcmp(argv[1], "gettetherstats") || !strcmp(argv[1], "gts")) {
1147         BandwidthController::TetherStats tetherStats;
1148         std::string extraProcessingInfo = "";
1149         if (argc < 2 || argc > 4) {
1150             sendGenericSyntaxError(cli, "gettetherstats [<intInterface> <extInterface>]");
1151             return 0;
1152         }
1153         tetherStats.intIface = argc > 2 ? argv[2] : "";
1154         tetherStats.extIface = argc > 3 ? argv[3] : "";
1155         // No filtering requested and there are no interface pairs to lookup.
1156         if (argc <= 2 && gCtls->natCtrl.ifacePairList.empty()) {
1157             cli->sendMsg(ResponseCode::CommandOkay, "Tethering stats list completed", false);
1158             return 0;
1159         }
1160         int rc = gCtls->bandwidthCtrl.getTetherStats(cli, tetherStats, extraProcessingInfo);
1161         if (rc) {
1162                 extraProcessingInfo.insert(0, "Failed to get tethering stats.\n");
1163                 sendGenericOpFailed(cli, extraProcessingInfo.c_str());
1164                 return 0;
1165         }
1166         return 0;
1167
1168     }
1169
1170     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
1171     return 0;
1172 }
1173
1174 CommandListener::IdletimerControlCmd::IdletimerControlCmd() :
1175     NetdCommand("idletimer") {
1176 }
1177
1178 int CommandListener::IdletimerControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
1179   // TODO(ashish): Change the error statements
1180     if (argc < 2) {
1181         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1182         return 0;
1183     }
1184
1185     ALOGV("idletimerctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
1186
1187     if (!strcmp(argv[1], "enable")) {
1188       if (0 != gCtls->idletimerCtrl.enableIdletimerControl()) {
1189         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1190       } else {
1191         cli->sendMsg(ResponseCode::CommandOkay, "Enable success", false);
1192       }
1193       return 0;
1194
1195     }
1196     if (!strcmp(argv[1], "disable")) {
1197       if (0 != gCtls->idletimerCtrl.disableIdletimerControl()) {
1198         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1199       } else {
1200         cli->sendMsg(ResponseCode::CommandOkay, "Disable success", false);
1201       }
1202       return 0;
1203     }
1204     if (!strcmp(argv[1], "add")) {
1205         if (argc != 5) {
1206             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1207             return 0;
1208         }
1209         if(0 != gCtls->idletimerCtrl.addInterfaceIdletimer(
1210                                         argv[2], atoi(argv[3]), argv[4])) {
1211           cli->sendMsg(ResponseCode::OperationFailed, "Failed to add interface", false);
1212         } else {
1213           cli->sendMsg(ResponseCode::CommandOkay,  "Add success", false);
1214         }
1215         return 0;
1216     }
1217     if (!strcmp(argv[1], "remove")) {
1218         if (argc != 5) {
1219             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1220             return 0;
1221         }
1222         // ashish: fixme timeout
1223         if (0 != gCtls->idletimerCtrl.removeInterfaceIdletimer(
1224                                         argv[2], atoi(argv[3]), argv[4])) {
1225           cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove interface", false);
1226         } else {
1227           cli->sendMsg(ResponseCode::CommandOkay, "Remove success", false);
1228         }
1229         return 0;
1230     }
1231
1232     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown idletimer cmd", false);
1233     return 0;
1234 }
1235
1236 CommandListener::FirewallCmd::FirewallCmd() :
1237     NetdCommand("firewall") {
1238 }
1239
1240 int CommandListener::FirewallCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1241     if (!cond) {
1242         cli->sendMsg(ResponseCode::CommandOkay, "Firewall command succeeded", false);
1243     } else {
1244         cli->sendMsg(ResponseCode::OperationFailed, "Firewall command failed", false);
1245     }
1246     return 0;
1247 }
1248
1249 FirewallRule CommandListener::FirewallCmd::parseRule(const char* arg) {
1250     if (!strcmp(arg, "allow")) {
1251         return ALLOW;
1252     } else if (!strcmp(arg, "deny")) {
1253         return DENY;
1254     } else {
1255         ALOGE("failed to parse uid rule (%s)", arg);
1256         return ALLOW;
1257     }
1258 }
1259
1260 FirewallType CommandListener::FirewallCmd::parseFirewallType(const char* arg) {
1261     if (!strcmp(arg, "whitelist")) {
1262         return WHITELIST;
1263     } else if (!strcmp(arg, "blacklist")) {
1264         return BLACKLIST;
1265     } else {
1266         ALOGE("failed to parse firewall type (%s)", arg);
1267         return BLACKLIST;
1268     }
1269 }
1270
1271 ChildChain CommandListener::FirewallCmd::parseChildChain(const char* arg) {
1272     if (!strcmp(arg, "dozable")) {
1273         return DOZABLE;
1274     } else if (!strcmp(arg, "standby")) {
1275         return STANDBY;
1276     } else if (!strcmp(arg, "powersave")) {
1277         return POWERSAVE;
1278     } else if (!strcmp(arg, "none")) {
1279         return NONE;
1280     } else {
1281         ALOGE("failed to parse child firewall chain (%s)", arg);
1282         return INVALID_CHAIN;
1283     }
1284 }
1285
1286 int CommandListener::FirewallCmd::runCommand(SocketClient *cli, int argc,
1287         char **argv) {
1288     if (argc < 2) {
1289         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
1290         return 0;
1291     }
1292
1293     if (!strcmp(argv[1], "enable")) {
1294         if (argc != 3) {
1295             cli->sendMsg(ResponseCode::CommandSyntaxError,
1296                         "Usage: firewall enable <whitelist|blacklist>", false);
1297             return 0;
1298         }
1299         FirewallType firewallType = parseFirewallType(argv[2]);
1300
1301         int res = gCtls->firewallCtrl.enableFirewall(firewallType);
1302         return sendGenericOkFail(cli, res);
1303     }
1304     if (!strcmp(argv[1], "disable")) {
1305         int res = gCtls->firewallCtrl.disableFirewall();
1306         return sendGenericOkFail(cli, res);
1307     }
1308     if (!strcmp(argv[1], "is_enabled")) {
1309         int res = gCtls->firewallCtrl.isFirewallEnabled();
1310         return sendGenericOkFail(cli, res);
1311     }
1312
1313     if (!strcmp(argv[1], "set_interface_rule")) {
1314         if (argc != 4) {
1315             cli->sendMsg(ResponseCode::CommandSyntaxError,
1316                          "Usage: firewall set_interface_rule <rmnet0> <allow|deny>", false);
1317             return 0;
1318         }
1319
1320         const char* iface = argv[2];
1321         FirewallRule rule = parseRule(argv[3]);
1322
1323         int res = gCtls->firewallCtrl.setInterfaceRule(iface, rule);
1324         return sendGenericOkFail(cli, res);
1325     }
1326
1327     if (!strcmp(argv[1], "set_egress_source_rule")) {
1328         if (argc != 4) {
1329             cli->sendMsg(ResponseCode::CommandSyntaxError,
1330                          "Usage: firewall set_egress_source_rule <192.168.0.1> <allow|deny>",
1331                          false);
1332             return 0;
1333         }
1334
1335         const char* addr = argv[2];
1336         FirewallRule rule = parseRule(argv[3]);
1337
1338         int res = gCtls->firewallCtrl.setEgressSourceRule(addr, rule);
1339         return sendGenericOkFail(cli, res);
1340     }
1341
1342     if (!strcmp(argv[1], "set_egress_dest_rule")) {
1343         if (argc != 5) {
1344             cli->sendMsg(ResponseCode::CommandSyntaxError,
1345                          "Usage: firewall set_egress_dest_rule <192.168.0.1> <80> <allow|deny>",
1346                          false);
1347             return 0;
1348         }
1349
1350         const char* addr = argv[2];
1351         int port = atoi(argv[3]);
1352         FirewallRule rule = parseRule(argv[4]);
1353
1354         int res = 0;
1355         res |= gCtls->firewallCtrl.setEgressDestRule(addr, PROTOCOL_TCP, port, rule);
1356         res |= gCtls->firewallCtrl.setEgressDestRule(addr, PROTOCOL_UDP, port, rule);
1357         return sendGenericOkFail(cli, res);
1358     }
1359
1360     if (!strcmp(argv[1], "set_uid_rule")) {
1361         if (argc != 5) {
1362             cli->sendMsg(ResponseCode::CommandSyntaxError,
1363                          "Usage: firewall set_uid_rule <dozable|standby|none> <1000> <allow|deny>",
1364                          false);
1365             return 0;
1366         }
1367
1368         ChildChain childChain = parseChildChain(argv[2]);
1369         if (childChain == INVALID_CHAIN) {
1370             cli->sendMsg(ResponseCode::CommandSyntaxError,
1371                          "Invalid chain name. Valid names are: <dozable|standby|none>",
1372                          false);
1373             return 0;
1374         }
1375         int uid = atoi(argv[3]);
1376         FirewallRule rule = parseRule(argv[4]);
1377         int res = gCtls->firewallCtrl.setUidRule(childChain, uid, rule);
1378         return sendGenericOkFail(cli, res);
1379     }
1380
1381     if (!strcmp(argv[1], "enable_chain")) {
1382         if (argc != 3) {
1383             cli->sendMsg(ResponseCode::CommandSyntaxError,
1384                          "Usage: firewall enable_chain <dozable|standby>",
1385                          false);
1386             return 0;
1387         }
1388
1389         ChildChain childChain = parseChildChain(argv[2]);
1390         int res = gCtls->firewallCtrl.enableChildChains(childChain, true);
1391         return sendGenericOkFail(cli, res);
1392     }
1393
1394     if (!strcmp(argv[1], "disable_chain")) {
1395         if (argc != 3) {
1396             cli->sendMsg(ResponseCode::CommandSyntaxError,
1397                          "Usage: firewall disable_chain <dozable|standby>",
1398                          false);
1399             return 0;
1400         }
1401
1402         ChildChain childChain = parseChildChain(argv[2]);
1403         int res = gCtls->firewallCtrl.enableChildChains(childChain, false);
1404         return sendGenericOkFail(cli, res);
1405     }
1406
1407     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
1408     return 0;
1409 }
1410
1411 CommandListener::ClatdCmd::ClatdCmd() : NetdCommand("clatd") {
1412 }
1413
1414 int CommandListener::ClatdCmd::runCommand(SocketClient *cli, int argc,
1415                                                             char **argv) {
1416     int rc = 0;
1417     if (argc < 3) {
1418         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1419         return 0;
1420     }
1421
1422     if (!strcmp(argv[1], "stop")) {
1423         rc = gCtls->clatdCtrl.stopClatd(argv[2]);
1424     } else if (!strcmp(argv[1], "status")) {
1425         char *tmp = NULL;
1426         asprintf(&tmp, "Clatd status: %s", (gCtls->clatdCtrl.isClatdStarted(argv[2]) ?
1427                                             "started" : "stopped"));
1428         cli->sendMsg(ResponseCode::ClatdStatusResult, tmp, false);
1429         free(tmp);
1430         return 0;
1431     } else if (!strcmp(argv[1], "start")) {
1432         rc = gCtls->clatdCtrl.startClatd(argv[2]);
1433     } else {
1434         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown clatd cmd", false);
1435         return 0;
1436     }
1437
1438     if (!rc) {
1439         cli->sendMsg(ResponseCode::CommandOkay, "Clatd operation succeeded", false);
1440     } else {
1441         cli->sendMsg(ResponseCode::OperationFailed, "Clatd operation failed", false);
1442     }
1443
1444     return 0;
1445 }
1446
1447 CommandListener::StrictCmd::StrictCmd() :
1448     NetdCommand("strict") {
1449 }
1450
1451 int CommandListener::StrictCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1452     if (!cond) {
1453         cli->sendMsg(ResponseCode::CommandOkay, "Strict command succeeded", false);
1454     } else {
1455         cli->sendMsg(ResponseCode::OperationFailed, "Strict command failed", false);
1456     }
1457     return 0;
1458 }
1459
1460 StrictPenalty CommandListener::StrictCmd::parsePenalty(const char* arg) {
1461     if (!strcmp(arg, "reject")) {
1462         return REJECT;
1463     } else if (!strcmp(arg, "log")) {
1464         return LOG;
1465     } else if (!strcmp(arg, "accept")) {
1466         return ACCEPT;
1467     } else {
1468         return INVALID;
1469     }
1470 }
1471
1472 int CommandListener::StrictCmd::runCommand(SocketClient *cli, int argc,
1473         char **argv) {
1474     if (argc < 2) {
1475         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
1476         return 0;
1477     }
1478
1479     if (!strcmp(argv[1], "enable")) {
1480         int res = gCtls->strictCtrl.enableStrict();
1481         return sendGenericOkFail(cli, res);
1482     }
1483     if (!strcmp(argv[1], "disable")) {
1484         int res = gCtls->strictCtrl.disableStrict();
1485         return sendGenericOkFail(cli, res);
1486     }
1487
1488     if (!strcmp(argv[1], "set_uid_cleartext_policy")) {
1489         if (argc != 4) {
1490             cli->sendMsg(ResponseCode::CommandSyntaxError,
1491                          "Usage: strict set_uid_cleartext_policy <uid> <accept|log|reject>",
1492                          false);
1493             return 0;
1494         }
1495
1496         errno = 0;
1497         unsigned long int uid = strtoul(argv[2], NULL, 0);
1498         if (errno || uid > UID_MAX) {
1499             cli->sendMsg(ResponseCode::CommandSyntaxError, "Invalid UID", false);
1500             return 0;
1501         }
1502
1503         StrictPenalty penalty = parsePenalty(argv[3]);
1504         if (penalty == INVALID) {
1505             cli->sendMsg(ResponseCode::CommandSyntaxError, "Invalid penalty argument", false);
1506             return 0;
1507         }
1508
1509         int res = gCtls->strictCtrl.setUidCleartextPenalty((uid_t) uid, penalty);
1510         return sendGenericOkFail(cli, res);
1511     }
1512
1513     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
1514     return 0;
1515 }
1516
1517 CommandListener::NetworkCommand::NetworkCommand() : NetdCommand("network") {
1518 }
1519
1520 int CommandListener::NetworkCommand::syntaxError(SocketClient* client, const char* message) {
1521     client->sendMsg(ResponseCode::CommandSyntaxError, message, false);
1522     return 0;
1523 }
1524
1525 int CommandListener::NetworkCommand::operationError(SocketClient* client, const char* message,
1526                                                     int ret) {
1527     errno = -ret;
1528     client->sendMsg(ResponseCode::OperationFailed, message, true);
1529     return 0;
1530 }
1531
1532 int CommandListener::NetworkCommand::success(SocketClient* client) {
1533     client->sendMsg(ResponseCode::CommandOkay, "success", false);
1534     return 0;
1535 }
1536
1537 int CommandListener::NetworkCommand::runCommand(SocketClient* client, int argc, char** argv) {
1538     if (argc < 2) {
1539         return syntaxError(client, "Missing argument");
1540     }
1541
1542     //    0      1      2      3      4       5         6            7           8
1543     // network route [legacy <uid>]  add   <netId> <interface> <destination> [nexthop]
1544     // network route [legacy <uid>] remove <netId> <interface> <destination> [nexthop]
1545     //
1546     // nexthop may be either an IPv4/IPv6 address or one of "unreachable" or "throw".
1547     if (!strcmp(argv[1], "route")) {
1548         if (argc < 6 || argc > 9) {
1549             return syntaxError(client, "Incorrect number of arguments");
1550         }
1551
1552         int nextArg = 2;
1553         bool legacy = false;
1554         uid_t uid = 0;
1555         if (!strcmp(argv[nextArg], "legacy")) {
1556             ++nextArg;
1557             legacy = true;
1558             uid = strtoul(argv[nextArg++], NULL, 0);
1559         }
1560
1561         bool add = false;
1562         if (!strcmp(argv[nextArg], "add")) {
1563             add = true;
1564         } else if (strcmp(argv[nextArg], "remove")) {
1565             return syntaxError(client, "Unknown argument");
1566         }
1567         ++nextArg;
1568
1569         if (argc < nextArg + 3 || argc > nextArg + 4) {
1570             return syntaxError(client, "Incorrect number of arguments");
1571         }
1572
1573         unsigned netId = stringToNetId(argv[nextArg++]);
1574         const char* interface = argv[nextArg++];
1575         const char* destination = argv[nextArg++];
1576         const char* nexthop = argc > nextArg ? argv[nextArg] : NULL;
1577
1578         int ret;
1579         if (add) {
1580             ret = gCtls->netCtrl.addRoute(netId, interface, destination, nexthop, legacy, uid);
1581         } else {
1582             ret = gCtls->netCtrl.removeRoute(netId, interface, destination, nexthop, legacy, uid);
1583         }
1584         if (ret) {
1585             return operationError(client, add ? "addRoute() failed" : "removeRoute() failed", ret);
1586         }
1587
1588         return success(client);
1589     }
1590
1591     //    0        1       2       3         4
1592     // network interface  add   <netId> <interface>
1593     // network interface remove <netId> <interface>
1594     if (!strcmp(argv[1], "interface")) {
1595         if (argc != 5) {
1596             return syntaxError(client, "Missing argument");
1597         }
1598         unsigned netId = stringToNetId(argv[3]);
1599         if (!strcmp(argv[2], "add")) {
1600             if (int ret = gCtls->netCtrl.addInterfaceToNetwork(netId, argv[4])) {
1601                 return operationError(client, "addInterfaceToNetwork() failed", ret);
1602             }
1603         } else if (!strcmp(argv[2], "remove")) {
1604             if (int ret = gCtls->netCtrl.removeInterfaceFromNetwork(netId, argv[4])) {
1605                 return operationError(client, "removeInterfaceFromNetwork() failed", ret);
1606             }
1607         } else {
1608             return syntaxError(client, "Unknown argument");
1609         }
1610         return success(client);
1611     }
1612
1613     //    0      1       2         3
1614     // network create <netId> [permission]
1615     //
1616     //    0      1       2     3     4        5
1617     // network create <netId> vpn <hasDns> <secure>
1618     if (!strcmp(argv[1], "create")) {
1619         if (argc < 3) {
1620             return syntaxError(client, "Missing argument");
1621         }
1622         unsigned netId = stringToNetId(argv[2]);
1623         if (argc == 6 && !strcmp(argv[3], "vpn")) {
1624             bool hasDns = atoi(argv[4]);
1625             bool secure = atoi(argv[5]);
1626             if (int ret = gCtls->netCtrl.createVirtualNetwork(netId, hasDns, secure)) {
1627                 return operationError(client, "createVirtualNetwork() failed", ret);
1628             }
1629         } else if (argc > 4) {
1630             return syntaxError(client, "Unknown trailing argument(s)");
1631         } else {
1632             Permission permission = PERMISSION_NONE;
1633             if (argc == 4) {
1634                 permission = stringToPermission(argv[3]);
1635                 if (permission == PERMISSION_NONE) {
1636                     return syntaxError(client, "Unknown permission");
1637                 }
1638             }
1639             if (int ret = gCtls->netCtrl.createPhysicalNetwork(netId, permission)) {
1640                 return operationError(client, "createPhysicalNetwork() failed", ret);
1641             }
1642         }
1643         return success(client);
1644     }
1645
1646     //    0       1       2
1647     // network destroy <netId>
1648     if (!strcmp(argv[1], "destroy")) {
1649         if (argc != 3) {
1650             return syntaxError(client, "Incorrect number of arguments");
1651         }
1652         unsigned netId = stringToNetId(argv[2]);
1653         if (int ret = gCtls->netCtrl.destroyNetwork(netId)) {
1654             return operationError(client, "destroyNetwork() failed", ret);
1655         }
1656         return success(client);
1657     }
1658
1659     //    0       1      2      3
1660     // network default  set  <netId>
1661     // network default clear
1662     if (!strcmp(argv[1], "default")) {
1663         if (argc < 3) {
1664             return syntaxError(client, "Missing argument");
1665         }
1666         unsigned netId = NETID_UNSET;
1667         if (!strcmp(argv[2], "set")) {
1668             if (argc < 4) {
1669                 return syntaxError(client, "Missing netId");
1670             }
1671             netId = stringToNetId(argv[3]);
1672         } else if (strcmp(argv[2], "clear")) {
1673             return syntaxError(client, "Unknown argument");
1674         }
1675         if (int ret = gCtls->netCtrl.setDefaultNetwork(netId)) {
1676             return operationError(client, "setDefaultNetwork() failed", ret);
1677         }
1678         return success(client);
1679     }
1680
1681     //    0        1         2      3        4          5
1682     // network permission   user   set  <permission>  <uid> ...
1683     // network permission   user  clear    <uid> ...
1684     // network permission network  set  <permission> <netId> ...
1685     // network permission network clear   <netId> ...
1686     if (!strcmp(argv[1], "permission")) {
1687         if (argc < 5) {
1688             return syntaxError(client, "Missing argument");
1689         }
1690         int nextArg = 4;
1691         Permission permission = PERMISSION_NONE;
1692         if (!strcmp(argv[3], "set")) {
1693             permission = stringToPermission(argv[4]);
1694             if (permission == PERMISSION_NONE) {
1695                 return syntaxError(client, "Unknown permission");
1696             }
1697             nextArg = 5;
1698         } else if (strcmp(argv[3], "clear")) {
1699             return syntaxError(client, "Unknown argument");
1700         }
1701         if (nextArg == argc) {
1702             return syntaxError(client, "Missing id");
1703         }
1704
1705         bool userPermissions = !strcmp(argv[2], "user");
1706         bool networkPermissions = !strcmp(argv[2], "network");
1707         if (!userPermissions && !networkPermissions) {
1708             return syntaxError(client, "Unknown argument");
1709         }
1710
1711         std::vector<unsigned> ids;
1712         for (; nextArg < argc; ++nextArg) {
1713             if (userPermissions) {
1714                 char* endPtr;
1715                 unsigned id = strtoul(argv[nextArg], &endPtr, 0);
1716                 if (!*argv[nextArg] || *endPtr) {
1717                     return syntaxError(client, "Invalid id");
1718                 }
1719                 ids.push_back(id);
1720             } else {
1721                 // networkPermissions
1722                 ids.push_back(stringToNetId(argv[nextArg]));
1723             }
1724         }
1725         if (userPermissions) {
1726             gCtls->netCtrl.setPermissionForUsers(permission, ids);
1727         } else {
1728             // networkPermissions
1729             if (int ret = gCtls->netCtrl.setPermissionForNetworks(permission, ids)) {
1730                 return operationError(client, "setPermissionForNetworks() failed", ret);
1731             }
1732         }
1733
1734         return success(client);
1735     }
1736
1737     //    0      1     2       3           4
1738     // network users  add   <netId> [<uid>[-<uid>]] ...
1739     // network users remove <netId> [<uid>[-<uid>]] ...
1740     if (!strcmp(argv[1], "users")) {
1741         if (argc < 4) {
1742             return syntaxError(client, "Missing argument");
1743         }
1744         unsigned netId = stringToNetId(argv[3]);
1745         UidRanges uidRanges;
1746         if (!uidRanges.parseFrom(argc - 4, argv + 4)) {
1747             return syntaxError(client, "Invalid UIDs");
1748         }
1749         if (!strcmp(argv[2], "add")) {
1750             if (int ret = gCtls->netCtrl.addUsersToNetwork(netId, uidRanges)) {
1751                 return operationError(client, "addUsersToNetwork() failed", ret);
1752             }
1753         } else if (!strcmp(argv[2], "remove")) {
1754             if (int ret = gCtls->netCtrl.removeUsersFromNetwork(netId, uidRanges)) {
1755                 return operationError(client, "removeUsersFromNetwork() failed", ret);
1756             }
1757         } else {
1758             return syntaxError(client, "Unknown argument");
1759         }
1760         return success(client);
1761     }
1762
1763     //    0       1      2     3
1764     // network protect allow <uid> ...
1765     // network protect  deny <uid> ...
1766     if (!strcmp(argv[1], "protect")) {
1767         if (argc < 4) {
1768             return syntaxError(client, "Missing argument");
1769         }
1770         std::vector<uid_t> uids;
1771         for (int i = 3; i < argc; ++i) {
1772             uids.push_back(strtoul(argv[i], NULL, 0));
1773         }
1774         if (!strcmp(argv[2], "allow")) {
1775             gCtls->netCtrl.allowProtect(uids);
1776         } else if (!strcmp(argv[2], "deny")) {
1777             gCtls->netCtrl.denyProtect(uids);
1778         } else {
1779             return syntaxError(client, "Unknown argument");
1780         }
1781         return success(client);
1782     }
1783
1784     return syntaxError(client, "Unknown argument");
1785 }