OSDN Git Service

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