2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 // #define LOG_NDEBUG 0
20 #include <sys/socket.h>
21 #include <sys/types.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
29 #define LOG_TAG "CommandListener"
31 #include <cutils/log.h>
32 #include <netutils/ifc.h>
33 #include <sysutils/SocketClient.h>
35 #include "CommandListener.h"
36 #include "ResponseCode.h"
37 #include "BandwidthController.h"
38 #include "IdletimerController.h"
39 #include "SecondaryTableController.h"
40 #include "oem_iptables_hook.h"
41 #include "NetdConstants.h"
42 #include "FirewallController.h"
44 TetherController *CommandListener::sTetherCtrl = NULL;
45 NatController *CommandListener::sNatCtrl = NULL;
46 PppController *CommandListener::sPppCtrl = NULL;
47 SoftapController *CommandListener::sSoftapCtrl = NULL;
48 BandwidthController * CommandListener::sBandwidthCtrl = NULL;
49 IdletimerController * CommandListener::sIdletimerCtrl = NULL;
50 InterfaceController *CommandListener::sInterfaceCtrl = NULL;
51 ResolverController *CommandListener::sResolverCtrl = NULL;
52 SecondaryTableController *CommandListener::sSecondaryTableCtrl = NULL;
53 FirewallController *CommandListener::sFirewallCtrl = NULL;
54 ClatdController *CommandListener::sClatdCtrl = NULL;
57 * List of module chains to be created, along with explicit ordering. ORDERING
58 * IS CRITICAL, AND SHOULD BE TRIPLE-CHECKED WITH EACH CHANGE.
60 static const char* FILTER_INPUT[] = {
61 // Bandwidth should always be early in input chain, to make sure we
62 // correctly count incoming traffic against data plan.
63 BandwidthController::LOCAL_INPUT,
64 FirewallController::LOCAL_INPUT,
68 static const char* FILTER_FORWARD[] = {
69 OEM_IPTABLES_FILTER_FORWARD,
70 FirewallController::LOCAL_FORWARD,
71 BandwidthController::LOCAL_FORWARD,
72 NatController::LOCAL_FORWARD,
76 static const char* FILTER_OUTPUT[] = {
77 OEM_IPTABLES_FILTER_OUTPUT,
78 FirewallController::LOCAL_OUTPUT,
79 BandwidthController::LOCAL_OUTPUT,
83 static const char* RAW_PREROUTING[] = {
84 BandwidthController::LOCAL_RAW_PREROUTING,
85 IdletimerController::LOCAL_RAW_PREROUTING,
89 static const char* MANGLE_POSTROUTING[] = {
90 BandwidthController::LOCAL_MANGLE_POSTROUTING,
91 IdletimerController::LOCAL_MANGLE_POSTROUTING,
95 static const char* NAT_PREROUTING[] = {
96 OEM_IPTABLES_NAT_PREROUTING,
100 static const char* NAT_POSTROUTING[] = {
101 NatController::LOCAL_NAT_POSTROUTING,
105 static void createChildChains(IptablesTarget target, const char* table, const char* parentChain,
106 const char** childChains) {
107 const char** childChain = childChains;
109 // Order is important:
110 // -D to delete any pre-existing jump rule (removes references
111 // that would prevent -X from working)
112 // -F to flush any existing chain
113 // -X to delete any existing chain
114 // -N to create the chain
115 // -A to append the chain to parent
117 execIptablesSilently(target, "-t", table, "-D", parentChain, "-j", *childChain, NULL);
118 execIptablesSilently(target, "-t", table, "-F", *childChain, NULL);
119 execIptablesSilently(target, "-t", table, "-X", *childChain, NULL);
120 execIptables(target, "-t", table, "-N", *childChain, NULL);
121 execIptables(target, "-t", table, "-A", parentChain, "-j", *childChain, NULL);
122 } while (*(++childChain) != NULL);
125 CommandListener::CommandListener() :
126 FrameworkListener("netd", true) {
127 registerCmd(new InterfaceCmd());
128 registerCmd(new IpFwdCmd());
129 registerCmd(new TetherCmd());
130 registerCmd(new NatCmd());
131 registerCmd(new ListTtysCmd());
132 registerCmd(new PppdCmd());
133 registerCmd(new SoftapCmd());
134 registerCmd(new BandwidthControlCmd());
135 registerCmd(new IdletimerControlCmd());
136 registerCmd(new ResolverCmd());
137 registerCmd(new FirewallCmd());
138 registerCmd(new ClatdCmd());
140 if (!sSecondaryTableCtrl)
141 sSecondaryTableCtrl = new SecondaryTableController();
143 sTetherCtrl = new TetherController();
145 sNatCtrl = new NatController(sSecondaryTableCtrl);
147 sPppCtrl = new PppController();
149 sSoftapCtrl = new SoftapController();
151 sBandwidthCtrl = new BandwidthController();
153 sIdletimerCtrl = new IdletimerController();
155 sResolverCtrl = new ResolverController();
157 sFirewallCtrl = new FirewallController();
159 sInterfaceCtrl = new InterfaceController();
161 sClatdCtrl = new ClatdController();
164 * This is the only time we touch top-level chains in iptables; controllers
165 * should only mutate rules inside of their children chains, as created by
166 * the constants above.
168 * Modules should never ACCEPT packets (except in well-justified cases);
169 * they should instead defer to any remaining modules using RETURN, or
170 * otherwise DROP/REJECT.
173 // Create chains for children modules
174 createChildChains(V4V6, "filter", "INPUT", FILTER_INPUT);
175 createChildChains(V4V6, "filter", "FORWARD", FILTER_FORWARD);
176 createChildChains(V4V6, "filter", "OUTPUT", FILTER_OUTPUT);
177 createChildChains(V4V6, "raw", "PREROUTING", RAW_PREROUTING);
178 createChildChains(V4V6, "mangle", "POSTROUTING", MANGLE_POSTROUTING);
179 createChildChains(V4, "nat", "PREROUTING", NAT_PREROUTING);
180 createChildChains(V4, "nat", "POSTROUTING", NAT_POSTROUTING);
182 // Let each module setup their child chains
183 setupOemIptablesHook();
185 /* When enabled, DROPs all packets except those matching rules. */
186 sFirewallCtrl->setupIptablesHooks();
188 /* Does DROPs in FORWARD by default */
189 sNatCtrl->setupIptablesHooks();
191 * Does REJECT in INPUT, OUTPUT. Does counting also.
192 * No DROP/REJECT allowed later in netfilter-flow hook order.
194 sBandwidthCtrl->setupIptablesHooks();
196 * Counts in nat: PREROUTING, POSTROUTING.
197 * No DROP/REJECT allowed later in netfilter-flow hook order.
199 sIdletimerCtrl->setupIptablesHooks();
201 sBandwidthCtrl->enableBandwidthControl(false);
204 CommandListener::InterfaceCmd::InterfaceCmd() :
205 NetdCommand("interface") {
208 int CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
209 int argc, char **argv) {
211 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
215 if (!strcmp(argv[1], "list")) {
219 if (!(d = opendir("/sys/class/net"))) {
220 cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true);
224 while((de = readdir(d))) {
225 if (de->d_name[0] == '.')
227 cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false);
230 cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false);
232 } else if (!strcmp(argv[1], "driver")) {
237 cli->sendMsg(ResponseCode::CommandSyntaxError,
238 "Usage: interface driver <interface> <cmd> <args>", false);
241 rc = sInterfaceCtrl->interfaceCommand(argc, argv, &rbuf);
243 cli->sendMsg(ResponseCode::OperationFailed, "Failed to execute command", true);
245 cli->sendMsg(ResponseCode::CommandOkay, rbuf, false);
250 * These commands take a minimum of 3 arguments
253 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
258 // interface route add/remove iface default/secondary dest prefix gateway
259 if (!strcmp(argv[1], "route")) {
260 int prefix_length = 0;
262 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
265 if (sscanf(argv[6], "%d", &prefix_length) != 1) {
266 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid route prefix", false);
269 if (!strcmp(argv[2], "add")) {
270 if (!strcmp(argv[4], "default")) {
271 if (ifc_add_route(argv[3], argv[5], prefix_length, argv[7])) {
272 cli->sendMsg(ResponseCode::OperationFailed,
273 "Failed to add route to default table", true);
275 cli->sendMsg(ResponseCode::CommandOkay,
276 "Route added to default table", false);
278 } else if (!strcmp(argv[4], "secondary")) {
279 return sSecondaryTableCtrl->addRoute(cli, argv[3], argv[5],
280 prefix_length, argv[7]);
282 cli->sendMsg(ResponseCode::CommandParameterError,
283 "Invalid route type, expecting 'default' or 'secondary'", false);
286 } else if (!strcmp(argv[2], "remove")) {
287 if (!strcmp(argv[4], "default")) {
288 if (ifc_remove_route(argv[3], argv[5], prefix_length, argv[7])) {
289 cli->sendMsg(ResponseCode::OperationFailed,
290 "Failed to remove route from default table", true);
292 cli->sendMsg(ResponseCode::CommandOkay,
293 "Route removed from default table", false);
295 } else if (!strcmp(argv[4], "secondary")) {
296 return sSecondaryTableCtrl->removeRoute(cli, argv[3], argv[5],
297 prefix_length, argv[7]);
299 cli->sendMsg(ResponseCode::CommandParameterError,
300 "Invalid route type, expecting 'default' or 'secondary'", false);
304 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
309 if (!strcmp(argv[1], "getcfg")) {
312 unsigned char hwaddr[6];
316 memset(hwaddr, 0, sizeof(hwaddr));
318 if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) {
319 cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
324 if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) {
325 ALOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno));
328 char *addr_s = strdup(inet_ntoa(addr));
329 const char *updown, *brdcst, *loopbk, *ppp, *running, *multi;
331 updown = (flags & IFF_UP) ? "up" : "down";
332 brdcst = (flags & IFF_BROADCAST) ? " broadcast" : "";
333 loopbk = (flags & IFF_LOOPBACK) ? " loopback" : "";
334 ppp = (flags & IFF_POINTOPOINT) ? " point-to-point" : "";
335 running = (flags & IFF_RUNNING) ? " running" : "";
336 multi = (flags & IFF_MULTICAST) ? " multicast" : "";
340 asprintf(&flag_s, "%s%s%s%s%s%s", updown, brdcst, loopbk, ppp, running, multi);
343 asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %d %s",
344 hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5],
345 addr_s, prefixLength, flag_s);
347 cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false);
355 } else if (!strcmp(argv[1], "setcfg")) {
356 // arglist: iface [addr prefixLength] flags
358 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
361 ALOGD("Setting iface cfg");
369 if (!inet_aton(argv[3], &addr)) {
370 // Handle flags only case
373 if (ifc_set_addr(argv[2], addr.s_addr)) {
374 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true);
379 // Set prefix length on a non zero address
380 if (addr.s_addr != 0 && ifc_set_prefixLength(argv[2], atoi(argv[4]))) {
381 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set prefixLength", true);
388 for (int i = index; i < argc; i++) {
389 char *flag = argv[i];
390 if (!strcmp(flag, "up")) {
391 ALOGD("Trying to bring up %s", argv[2]);
392 if (ifc_up(argv[2])) {
393 ALOGE("Error upping interface");
394 cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true);
398 } else if (!strcmp(flag, "down")) {
399 ALOGD("Trying to bring down %s", argv[2]);
400 if (ifc_down(argv[2])) {
401 ALOGE("Error downing interface");
402 cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true);
406 } else if (!strcmp(flag, "broadcast")) {
408 } else if (!strcmp(flag, "multicast")) {
410 } else if (!strcmp(flag, "running")) {
412 } else if (!strcmp(flag, "loopback")) {
414 } else if (!strcmp(flag, "point-to-point")) {
417 cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false);
423 cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false);
426 } else if (!strcmp(argv[1], "clearaddrs")) {
428 ALOGD("Clearing all IP addresses on %s", argv[2]);
430 ifc_clear_addresses(argv[2]);
432 cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false);
434 } else if (!strcmp(argv[1], "ipv6privacyextensions")) {
436 cli->sendMsg(ResponseCode::CommandSyntaxError,
437 "Usage: interface ipv6privacyextensions <interface> <enable|disable>",
441 int enable = !strncmp(argv[3], "enable", 7);
442 if (sInterfaceCtrl->setIPv6PrivacyExtensions(argv[2], enable) == 0) {
443 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false);
445 cli->sendMsg(ResponseCode::OperationFailed,
446 "Failed to set ipv6 privacy extensions", true);
449 } else if (!strcmp(argv[1], "ipv6")) {
451 cli->sendMsg(ResponseCode::CommandSyntaxError,
452 "Usage: interface ipv6 <interface> <enable|disable>",
457 int enable = !strncmp(argv[3], "enable", 7);
458 if (sInterfaceCtrl->setEnableIPv6(argv[2], enable) == 0) {
459 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false);
461 cli->sendMsg(ResponseCode::OperationFailed,
462 "Failed to change IPv6 state", true);
466 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
474 CommandListener::ListTtysCmd::ListTtysCmd() :
475 NetdCommand("list_ttys") {
478 int CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
479 int argc, char **argv) {
480 TtyCollection *tlist = sPppCtrl->getTtyList();
481 TtyCollection::iterator it;
483 for (it = tlist->begin(); it != tlist->end(); ++it) {
484 cli->sendMsg(ResponseCode::TtyListResult, *it, false);
487 cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
491 CommandListener::IpFwdCmd::IpFwdCmd() :
492 NetdCommand("ipfwd") {
495 int CommandListener::IpFwdCmd::runCommand(SocketClient *cli,
496 int argc, char **argv) {
500 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
504 if (!strcmp(argv[1], "status")) {
507 asprintf(&tmp, "Forwarding %s", (sTetherCtrl->getIpFwdEnabled() ? "enabled" : "disabled"));
508 cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
511 } else if (!strcmp(argv[1], "enable")) {
512 rc = sTetherCtrl->setIpFwdEnabled(true);
513 } else if (!strcmp(argv[1], "disable")) {
514 rc = sTetherCtrl->setIpFwdEnabled(false);
516 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
521 cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
523 cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
529 CommandListener::TetherCmd::TetherCmd() :
530 NetdCommand("tether") {
533 int CommandListener::TetherCmd::runCommand(SocketClient *cli,
534 int argc, char **argv) {
538 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
542 if (!strcmp(argv[1], "stop")) {
543 rc = sTetherCtrl->stopTethering();
544 } else if (!strcmp(argv[1], "status")) {
547 asprintf(&tmp, "Tethering services %s",
548 (sTetherCtrl->isTetheringStarted() ? "started" : "stopped"));
549 cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
552 } else if (argc == 3) {
553 if (!strcmp(argv[1], "interface") && !strcmp(argv[2], "list")) {
554 InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList();
555 InterfaceCollection::iterator it;
556 for (it = ilist->begin(); it != ilist->end(); ++it) {
557 cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false);
559 } else if (!strcmp(argv[1], "dns") && !strcmp(argv[2], "list")) {
560 NetAddressCollection *dlist = sTetherCtrl->getDnsForwarders();
561 NetAddressCollection::iterator it;
563 for (it = dlist->begin(); it != dlist->end(); ++it) {
564 cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, inet_ntoa(*it), false);
569 * These commands take a minimum of 4 arguments
572 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
576 if (!strcmp(argv[1], "start")) {
578 cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false);
582 int num_addrs = argc - 2;
585 in_addr *addrs = (in_addr *)malloc(sizeof(in_addr) * num_addrs);
586 while (array_index < num_addrs) {
587 if (!inet_aton(argv[arg_index++], &(addrs[array_index++]))) {
588 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
593 rc = sTetherCtrl->startTethering(num_addrs, addrs);
595 } else if (!strcmp(argv[1], "interface")) {
596 if (!strcmp(argv[2], "add")) {
597 rc = sTetherCtrl->tetherInterface(argv[3]);
598 } else if (!strcmp(argv[2], "remove")) {
599 rc = sTetherCtrl->untetherInterface(argv[3]);
600 /* else if (!strcmp(argv[2], "list")) handled above */
602 cli->sendMsg(ResponseCode::CommandParameterError,
603 "Unknown tether interface operation", false);
606 } else if (!strcmp(argv[1], "dns")) {
607 if (!strcmp(argv[2], "set")) {
608 rc = sTetherCtrl->setDnsForwarders(&argv[3], argc - 3);
609 /* else if (!strcmp(argv[2], "list")) handled above */
611 cli->sendMsg(ResponseCode::CommandParameterError,
612 "Unknown tether interface operation", false);
616 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
622 cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
624 cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
630 CommandListener::NatCmd::NatCmd() :
634 int CommandListener::NatCmd::runCommand(SocketClient *cli,
635 int argc, char **argv) {
639 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
643 if (!strcmp(argv[1], "enable")) {
644 rc = sNatCtrl->enableNat(argc, argv);
646 /* Ignore ifaces for now. */
647 rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
649 } else if (!strcmp(argv[1], "disable")) {
650 /* Ignore ifaces for now. */
651 rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
652 rc |= sNatCtrl->disableNat(argc, argv);
654 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
659 cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
661 cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
667 CommandListener::PppdCmd::PppdCmd() :
668 NetdCommand("pppd") {
671 int CommandListener::PppdCmd::runCommand(SocketClient *cli,
672 int argc, char **argv) {
676 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
680 if (!strcmp(argv[1], "attach")) {
681 struct in_addr l, r, dns1, dns2;
683 memset(&dns1, sizeof(struct in_addr), 0);
684 memset(&dns2, sizeof(struct in_addr), 0);
686 if (!inet_aton(argv[3], &l)) {
687 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false);
690 if (!inet_aton(argv[4], &r)) {
691 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false);
694 if ((argc > 3) && (!inet_aton(argv[5], &dns1))) {
695 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false);
698 if ((argc > 4) && (!inet_aton(argv[6], &dns2))) {
699 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false);
702 rc = sPppCtrl->attachPppd(argv[2], l, r, dns1, dns2);
703 } else if (!strcmp(argv[1], "detach")) {
704 rc = sPppCtrl->detachPppd(argv[2]);
706 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false);
711 cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false);
713 cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true);
719 CommandListener::SoftapCmd::SoftapCmd() :
720 NetdCommand("softap") {
723 int CommandListener::SoftapCmd::runCommand(SocketClient *cli,
724 int argc, char **argv) {
725 int rc = ResponseCode::SoftapStatusResult;
729 if (sSoftapCtrl == NULL) {
730 cli->sendMsg(ResponseCode::ServiceStartFailed, "SoftAP is not available", false);
734 cli->sendMsg(ResponseCode::CommandSyntaxError,
735 "Missing argument in a SoftAP command", false);
739 if (!strcmp(argv[1], "startap")) {
740 rc = sSoftapCtrl->startSoftap();
741 } else if (!strcmp(argv[1], "stopap")) {
742 rc = sSoftapCtrl->stopSoftap();
743 } else if (!strcmp(argv[1], "fwreload")) {
744 rc = sSoftapCtrl->fwReloadSoftap(argc, argv);
745 } else if (!strcmp(argv[1], "status")) {
746 asprintf(&retbuf, "Softap service %s running",
747 (sSoftapCtrl->isSoftapStarted() ? "is" : "is not"));
748 cli->sendMsg(rc, retbuf, false);
751 } else if (!strcmp(argv[1], "set")) {
752 rc = sSoftapCtrl->setSoftap(argc, argv);
754 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unrecognized SoftAP command", false);
758 if (rc >= 400 && rc < 600)
759 cli->sendMsg(rc, "SoftAP command has failed", false);
761 cli->sendMsg(rc, "Ok", false);
766 CommandListener::ResolverCmd::ResolverCmd() :
767 NetdCommand("resolver") {
770 int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **argv) {
775 cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false);
779 if (!strcmp(argv[1], "setdefaultif")) { // "resolver setdefaultif <iface>"
781 rc = sResolverCtrl->setDefaultInterface(argv[2]);
783 cli->sendMsg(ResponseCode::CommandSyntaxError,
784 "Wrong number of arguments to resolver setdefaultif", false);
787 } else if (!strcmp(argv[1], "setifdns")) {
788 // "resolver setifdns <iface> <domains> <dns1> <dns2> ..."
790 rc = sResolverCtrl->setInterfaceDnsServers(argv[2], argv[3], &argv[4], argc - 4);
792 cli->sendMsg(ResponseCode::CommandSyntaxError,
793 "Wrong number of arguments to resolver setifdns", false);
797 // set the address of the interface to which the name servers
798 // are bound. Required in order to bind to right interface when
799 // doing the dns query.
802 ifc_get_info(argv[2], &addr.s_addr, NULL, 0);
804 rc = sResolverCtrl->setInterfaceAddress(argv[2], &addr);
806 } else if (!strcmp(argv[1], "flushdefaultif")) { // "resolver flushdefaultif"
808 rc = sResolverCtrl->flushDefaultDnsCache();
810 cli->sendMsg(ResponseCode::CommandSyntaxError,
811 "Wrong number of arguments to resolver flushdefaultif", false);
814 } else if (!strcmp(argv[1], "flushif")) { // "resolver flushif <iface>"
816 rc = sResolverCtrl->flushInterfaceDnsCache(argv[2]);
818 cli->sendMsg(ResponseCode::CommandSyntaxError,
819 "Wrong number of arguments to resolver setdefaultif", false);
822 } else if (!strcmp(argv[1], "setifaceforpid")) { // resolver setifaceforpid <iface> <pid>
824 rc = sResolverCtrl->setDnsInterfaceForPid(argv[2], atoi(argv[3]));
826 cli->sendMsg(ResponseCode::CommandSyntaxError,
827 "Wrong number of arguments to resolver setifaceforpid", false);
830 } else if (!strcmp(argv[1], "clearifaceforpid")) { // resolver clearifaceforpid <pid>
832 rc = sResolverCtrl->clearDnsInterfaceForPid(atoi(argv[2]));
834 cli->sendMsg(ResponseCode::CommandSyntaxError,
835 "Wrong number of arguments to resolver clearifaceforpid", false);
839 cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false);
844 cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false);
846 cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true);
852 CommandListener::BandwidthControlCmd::BandwidthControlCmd() :
853 NetdCommand("bandwidth") {
856 void CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) {
858 asprintf(&msg, "Usage: bandwidth %s", usageMsg);
859 cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false);
863 void CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) {
865 cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
867 cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false);
871 void CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) {
872 cli->sendMsg(ResponseCode::OperationFailed, errMsg, false);
875 int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
877 sendGenericSyntaxError(cli, "<cmds> <args...>");
881 ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
883 if (!strcmp(argv[1], "enable")) {
884 int rc = sBandwidthCtrl->enableBandwidthControl(true);
885 sendGenericOkFail(cli, rc);
889 if (!strcmp(argv[1], "disable")) {
890 int rc = sBandwidthCtrl->disableBandwidthControl();
891 sendGenericOkFail(cli, rc);
895 if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
897 sendGenericSyntaxError(cli, "removequota <interface>");
900 int rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[2]);
901 sendGenericOkFail(cli, rc);
905 if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) {
908 sendGenericSyntaxError(cli, "getquota");
911 int rc = sBandwidthCtrl->getInterfaceSharedQuota(&bytes);
913 sendGenericOpFailed(cli, "Failed to get quota");
918 asprintf(&msg, "%lld", bytes);
919 cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
924 if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) {
927 sendGenericSyntaxError(cli, "getiquota <iface>");
931 int rc = sBandwidthCtrl->getInterfaceQuota(argv[2], &bytes);
933 sendGenericOpFailed(cli, "Failed to get quota");
937 asprintf(&msg, "%lld", bytes);
938 cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
943 if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
945 sendGenericSyntaxError(cli, "setquota <interface> <bytes>");
948 int rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[2], atoll(argv[3]));
949 sendGenericOkFail(cli, rc);
952 if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
955 sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ...");
959 for (int q = 3; argc >= 4; q++, argc--) {
960 rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[q], atoll(argv[2]));
963 asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]);
964 cli->sendMsg(ResponseCode::OperationFailed,
970 sendGenericOkFail(cli, rc);
974 if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) {
977 sendGenericSyntaxError(cli, "removequotas <interface> ...");
981 for (int q = 2; argc >= 3; q++, argc--) {
982 rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[q]);
985 asprintf(&msg, "bandwidth removequotas %s failed", argv[q]);
986 cli->sendMsg(ResponseCode::OperationFailed,
992 sendGenericOkFail(cli, rc);
996 if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
998 sendGenericSyntaxError(cli, "removeiquota <interface>");
1001 int rc = sBandwidthCtrl->removeInterfaceQuota(argv[2]);
1002 sendGenericOkFail(cli, rc);
1006 if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
1008 sendGenericSyntaxError(cli, "setiquota <interface> <bytes>");
1011 int rc = sBandwidthCtrl->setInterfaceQuota(argv[2], atoll(argv[3]));
1012 sendGenericOkFail(cli, rc);
1016 if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
1018 sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ...");
1021 int rc = sBandwidthCtrl->addNaughtyApps(argc - 2, argv + 2);
1022 sendGenericOkFail(cli, rc);
1027 if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
1029 sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ...");
1032 int rc = sBandwidthCtrl->removeNaughtyApps(argc - 2, argv + 2);
1033 sendGenericOkFail(cli, rc);
1037 if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) {
1039 sendGenericSyntaxError(cli, "setglobalalert <bytes>");
1042 int rc = sBandwidthCtrl->setGlobalAlert(atoll(argv[2]));
1043 sendGenericOkFail(cli, rc);
1047 if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) {
1049 sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>");
1052 /* We ignore the interfaces for now. */
1053 int rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
1054 sendGenericOkFail(cli, rc);
1058 if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
1060 sendGenericSyntaxError(cli, "removeglobalalert");
1063 int rc = sBandwidthCtrl->removeGlobalAlert();
1064 sendGenericOkFail(cli, rc);
1068 if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) {
1070 sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>");
1073 /* We ignore the interfaces for now. */
1074 int rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
1075 sendGenericOkFail(cli, rc);
1079 if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
1081 sendGenericSyntaxError(cli, "setsharedalert <bytes>");
1084 int rc = sBandwidthCtrl->setSharedAlert(atoll(argv[2]));
1085 sendGenericOkFail(cli, rc);
1089 if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) {
1091 sendGenericSyntaxError(cli, "removesharedalert");
1094 int rc = sBandwidthCtrl->removeSharedAlert();
1095 sendGenericOkFail(cli, rc);
1099 if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) {
1101 sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>");
1104 int rc = sBandwidthCtrl->setInterfaceAlert(argv[2], atoll(argv[3]));
1105 sendGenericOkFail(cli, rc);
1109 if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) {
1111 sendGenericSyntaxError(cli, "removeinterfacealert <interface>");
1114 int rc = sBandwidthCtrl->removeInterfaceAlert(argv[2]);
1115 sendGenericOkFail(cli, rc);
1119 if (!strcmp(argv[1], "gettetherstats") || !strcmp(argv[1], "gts")) {
1120 BandwidthController::TetherStats tetherStats;
1121 std::string extraProcessingInfo = "";
1123 sendGenericSyntaxError(cli, "gettetherstats <interface0> <interface1>");
1127 tetherStats.ifaceIn = argv[2];
1128 tetherStats.ifaceOut = argv[3];
1129 int rc = sBandwidthCtrl->getTetherStats(tetherStats, extraProcessingInfo);
1131 extraProcessingInfo.insert(0, "Failed to get tethering stats.\n");
1132 sendGenericOpFailed(cli, extraProcessingInfo.c_str());
1136 char *msg = tetherStats.getStatsLine();
1137 cli->sendMsg(ResponseCode::TetheringStatsResult, msg, false);
1143 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
1147 CommandListener::IdletimerControlCmd::IdletimerControlCmd() :
1148 NetdCommand("idletimer") {
1151 int CommandListener::IdletimerControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
1152 // TODO(ashish): Change the error statements
1154 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1158 ALOGV("idletimerctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
1160 if (!strcmp(argv[1], "enable")) {
1161 if (0 != sIdletimerCtrl->enableIdletimerControl()) {
1162 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1164 cli->sendMsg(ResponseCode::CommandOkay, "Enable success", false);
1169 if (!strcmp(argv[1], "disable")) {
1170 if (0 != sIdletimerCtrl->disableIdletimerControl()) {
1171 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1173 cli->sendMsg(ResponseCode::CommandOkay, "Disable success", false);
1177 if (!strcmp(argv[1], "add")) {
1179 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1182 if(0 != sIdletimerCtrl->addInterfaceIdletimer(
1183 argv[2], atoi(argv[3]), argv[4])) {
1184 cli->sendMsg(ResponseCode::OperationFailed, "Failed to add interface", false);
1186 cli->sendMsg(ResponseCode::CommandOkay, "Add success", false);
1190 if (!strcmp(argv[1], "remove")) {
1192 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1195 // ashish: fixme timeout
1196 if (0 != sIdletimerCtrl->removeInterfaceIdletimer(
1197 argv[2], atoi(argv[3]), argv[4])) {
1198 cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove interface", false);
1200 cli->sendMsg(ResponseCode::CommandOkay, "Remove success", false);
1205 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown idletimer cmd", false);
1209 CommandListener::FirewallCmd::FirewallCmd() :
1210 NetdCommand("firewall") {
1213 int CommandListener::FirewallCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1215 cli->sendMsg(ResponseCode::CommandOkay, "Firewall command succeeded", false);
1217 cli->sendMsg(ResponseCode::OperationFailed, "Firewall command failed", false);
1222 FirewallRule CommandListener::FirewallCmd::parseRule(const char* arg) {
1223 if (!strcmp(arg, "allow")) {
1230 int CommandListener::FirewallCmd::runCommand(SocketClient *cli, int argc,
1233 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
1237 if (!strcmp(argv[1], "enable")) {
1238 int res = sFirewallCtrl->enableFirewall();
1239 return sendGenericOkFail(cli, res);
1241 if (!strcmp(argv[1], "disable")) {
1242 int res = sFirewallCtrl->disableFirewall();
1243 return sendGenericOkFail(cli, res);
1245 if (!strcmp(argv[1], "is_enabled")) {
1246 int res = sFirewallCtrl->isFirewallEnabled();
1247 return sendGenericOkFail(cli, res);
1250 if (!strcmp(argv[1], "set_interface_rule")) {
1252 cli->sendMsg(ResponseCode::CommandSyntaxError,
1253 "Usage: firewall set_interface_rule <rmnet0> <allow|deny>", false);
1257 const char* iface = argv[2];
1258 FirewallRule rule = parseRule(argv[3]);
1260 int res = sFirewallCtrl->setInterfaceRule(iface, rule);
1261 return sendGenericOkFail(cli, res);
1264 if (!strcmp(argv[1], "set_egress_source_rule")) {
1266 cli->sendMsg(ResponseCode::CommandSyntaxError,
1267 "Usage: firewall set_egress_source_rule <192.168.0.1> <allow|deny>",
1272 const char* addr = argv[2];
1273 FirewallRule rule = parseRule(argv[3]);
1275 int res = sFirewallCtrl->setEgressSourceRule(addr, rule);
1276 return sendGenericOkFail(cli, res);
1279 if (!strcmp(argv[1], "set_egress_dest_rule")) {
1281 cli->sendMsg(ResponseCode::CommandSyntaxError,
1282 "Usage: firewall set_egress_dest_rule <192.168.0.1> <80> <allow|deny>",
1287 const char* addr = argv[2];
1288 int port = atoi(argv[3]);
1289 FirewallRule rule = parseRule(argv[4]);
1292 res |= sFirewallCtrl->setEgressDestRule(addr, PROTOCOL_TCP, port, rule);
1293 res |= sFirewallCtrl->setEgressDestRule(addr, PROTOCOL_UDP, port, rule);
1294 return sendGenericOkFail(cli, res);
1297 if (!strcmp(argv[1], "set_uid_rule")) {
1299 cli->sendMsg(ResponseCode::CommandSyntaxError,
1300 "Usage: firewall set_uid_rule <1000> <allow|deny>",
1305 int uid = atoi(argv[2]);
1306 FirewallRule rule = parseRule(argv[3]);
1308 int res = sFirewallCtrl->setUidRule(uid, rule);
1309 return sendGenericOkFail(cli, res);
1312 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
1316 CommandListener::ClatdCmd::ClatdCmd() : NetdCommand("clatd") {
1319 int CommandListener::ClatdCmd::runCommand(SocketClient *cli, int argc,
1323 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1327 if(!strcmp(argv[1], "stop")) {
1328 rc = sClatdCtrl->stopClatd();
1329 } else if (!strcmp(argv[1], "status")) {
1332 asprintf(&tmp, "Clatd status: %s", (sClatdCtrl->isClatdStarted() ?
1333 "started" : "stopped"));
1334 cli->sendMsg(ResponseCode::ClatdStatusResult, tmp, false);
1337 } else if(!strcmp(argv[1], "start")) {
1339 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1342 rc = sClatdCtrl->startClatd(argv[2]);
1344 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown clatd cmd", false);
1349 cli->sendMsg(ResponseCode::CommandOkay, "Clatd operation succeeded", false);
1351 cli->sendMsg(ResponseCode::OperationFailed, "Clatd operation failed", false);