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>
28 #include <resolv_netid.h>
29 #include <resolv_params.h>
31 #define __STDC_FORMAT_MACROS 1
34 #define LOG_TAG "CommandListener"
36 #include <cutils/log.h>
37 #include <netutils/ifc.h>
38 #include <sysutils/SocketClient.h>
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"
54 using android::net::gCtls;
58 const unsigned NUM_OEM_IDS = NetworkController::MAX_OEM_ID - NetworkController::MIN_OEM_ID + 1;
60 Permission stringToPermission(const char* arg) {
61 if (!strcmp(arg, "NETWORK")) {
62 return PERMISSION_NETWORK;
64 if (!strcmp(arg, "SYSTEM")) {
65 return PERMISSION_SYSTEM;
67 return PERMISSION_NONE;
70 unsigned stringToNetId(const char* arg) {
71 if (!strcmp(arg, "local")) {
72 return NetworkController::LOCAL_NET_ID;
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;
82 // strtoul() returns 0 on errors, which is fine because 0 is an invalid netId.
83 return strtoul(arg, NULL, 0);
86 class LockingFrameworkCommand : public FrameworkCommand {
88 LockingFrameworkCommand(FrameworkCommand *wrappedCmd, android::RWLock& lock) :
89 FrameworkCommand(wrappedCmd->getCommand()),
90 mWrappedCmd(wrappedCmd),
93 int runCommand(SocketClient *c, int argc, char **argv) {
94 android::RWLock::AutoWLock lock(mLock);
95 return mWrappedCmd->runCommand(c, argc, argv);
99 FrameworkCommand *mWrappedCmd;
100 android::RWLock& mLock;
107 * List of module chains to be created, along with explicit ordering. ORDERING
108 * IS CRITICAL, AND SHOULD BE TRIPLE-CHECKED WITH EACH CHANGE.
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,
118 static const char* FILTER_FORWARD[] = {
119 OEM_IPTABLES_FILTER_FORWARD,
120 FirewallController::LOCAL_FORWARD,
121 BandwidthController::LOCAL_FORWARD,
122 NatController::LOCAL_FORWARD,
126 static const char* FILTER_OUTPUT[] = {
127 OEM_IPTABLES_FILTER_OUTPUT,
128 FirewallController::LOCAL_OUTPUT,
129 StrictController::LOCAL_OUTPUT,
130 BandwidthController::LOCAL_OUTPUT,
134 static const char* RAW_PREROUTING[] = {
135 BandwidthController::LOCAL_RAW_PREROUTING,
136 IdletimerController::LOCAL_RAW_PREROUTING,
140 static const char* MANGLE_POSTROUTING[] = {
141 BandwidthController::LOCAL_MANGLE_POSTROUTING,
142 IdletimerController::LOCAL_MANGLE_POSTROUTING,
146 static const char* MANGLE_FORWARD[] = {
147 NatController::LOCAL_MANGLE_FORWARD,
151 static const char* NAT_PREROUTING[] = {
152 OEM_IPTABLES_NAT_PREROUTING,
156 static const char* NAT_POSTROUTING[] = {
157 NatController::LOCAL_NAT_POSTROUTING,
161 static void createChildChains(IptablesTarget target, const char* table, const char* parentChain,
162 const char** childChains) {
163 const char** childChain = childChains;
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
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);
181 void CommandListener::registerLockingCmd(FrameworkCommand *cmd, android::RWLock& lock) {
182 registerCmd(new LockingFrameworkCommand(cmd, lock));
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());
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.
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.
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);
222 // Let each module setup their child chains
223 setupOemIptablesHook();
225 /* When enabled, DROPs all packets except those matching rules. */
226 gCtls->firewallCtrl.setupIptablesHooks();
228 /* Does DROPs in FORWARD by default */
229 gCtls->natCtrl.setupIptablesHooks();
231 * Does REJECT in INPUT, OUTPUT. Does counting also.
232 * No DROP/REJECT allowed later in netfilter-flow hook order.
234 gCtls->bandwidthCtrl.setupIptablesHooks();
236 * Counts in nat: PREROUTING, POSTROUTING.
237 * No DROP/REJECT allowed later in netfilter-flow hook order.
239 gCtls->idletimerCtrl.setupIptablesHooks();
241 gCtls->bandwidthCtrl.enableBandwidthControl(false);
243 if (int ret = RouteController::Init(NetworkController::LOCAL_NET_ID)) {
244 ALOGE("failed to initialize RouteController (%s)", strerror(-ret));
248 CommandListener::InterfaceCmd::InterfaceCmd() :
249 NetdCommand("interface") {
252 int CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
253 int argc, char **argv) {
255 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
259 if (!strcmp(argv[1], "list")) {
263 if (!(d = opendir("/sys/class/net"))) {
264 cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true);
268 while((de = readdir(d))) {
269 if (de->d_name[0] == '.')
271 cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false);
274 cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false);
278 * These commands take a minimum of 3 arguments
281 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
285 if (!strcmp(argv[1], "getcfg")) {
288 unsigned char hwaddr[6];
292 memset(hwaddr, 0, sizeof(hwaddr));
294 if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) {
295 cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
300 if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) {
301 ALOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno));
304 char *addr_s = strdup(inet_ntoa(addr));
305 const char *updown, *brdcst, *loopbk, *ppp, *running, *multi;
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" : "";
316 asprintf(&flag_s, "%s%s%s%s%s%s", updown, brdcst, loopbk, ppp, running, multi);
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);
323 cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false);
331 } else if (!strcmp(argv[1], "setcfg")) {
332 // arglist: iface [addr prefixLength] flags
334 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
337 ALOGD("Setting iface cfg");
344 if (!inet_aton(argv[3], &addr)) {
345 // Handle flags only case
348 if (ifc_set_addr(argv[2], 0)) {
349 cli->sendMsg(ResponseCode::OperationFailed, "Failed to clear address", true);
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);
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);
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);
381 } else if (!strcmp(flag, "broadcast")) {
383 } else if (!strcmp(flag, "multicast")) {
385 } else if (!strcmp(flag, "running")) {
387 } else if (!strcmp(flag, "loopback")) {
389 } else if (!strcmp(flag, "point-to-point")) {
392 cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false);
398 cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false);
401 } else if (!strcmp(argv[1], "clearaddrs")) {
403 ALOGD("Clearing all IP addresses on %s", argv[2]);
405 ifc_clear_addresses(argv[2]);
407 cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false);
409 } else if (!strcmp(argv[1], "ipv6privacyextensions")) {
411 cli->sendMsg(ResponseCode::CommandSyntaxError,
412 "Usage: interface ipv6privacyextensions <interface> <enable|disable>",
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);
420 cli->sendMsg(ResponseCode::OperationFailed,
421 "Failed to set ipv6 privacy extensions", true);
424 } else if (!strcmp(argv[1], "ipv6")) {
426 cli->sendMsg(ResponseCode::CommandSyntaxError,
427 "Usage: interface ipv6 <interface> <enable|disable>",
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);
436 cli->sendMsg(ResponseCode::OperationFailed,
437 "Failed to change IPv6 state", true);
440 } else if (!strcmp(argv[1], "ipv6ndoffload")) {
442 cli->sendMsg(ResponseCode::CommandSyntaxError,
443 "Usage: interface ipv6ndoffload <interface> <enable|disable>",
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);
451 cli->sendMsg(ResponseCode::OperationFailed,
452 "Failed to change IPv6 ND offload state", true);
455 } else if (!strcmp(argv[1], "setmtu")) {
457 cli->sendMsg(ResponseCode::CommandSyntaxError,
458 "Usage: interface setmtu <interface> <val>", false);
461 if (gCtls->interfaceCtrl.setMtu(argv[2], argv[3]) == 0) {
462 cli->sendMsg(ResponseCode::CommandOkay, "MTU changed", false);
464 cli->sendMsg(ResponseCode::OperationFailed,
465 "Failed to set MTU", true);
469 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
477 CommandListener::ListTtysCmd::ListTtysCmd() :
478 NetdCommand("list_ttys") {
481 int CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
482 int /* argc */, char ** /* argv */) {
483 TtyCollection *tlist = gCtls->pppCtrl.getTtyList();
484 TtyCollection::iterator it;
486 for (it = tlist->begin(); it != tlist->end(); ++it) {
487 cli->sendMsg(ResponseCode::TtyListResult, *it, false);
490 cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
494 CommandListener::IpFwdCmd::IpFwdCmd() :
495 NetdCommand("ipfwd") {
498 int CommandListener::IpFwdCmd::runCommand(SocketClient *cli, int argc, char **argv) {
499 bool matched = false;
505 if (!strcmp(argv[1], "status")) {
508 asprintf(&tmp, "Forwarding %s",
509 ((gCtls->tetherCtrl.forwardingRequestCount() > 0) ? "enabled" : "disabled"));
510 cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
514 } else if (argc == 3) {
516 // ipfwd enable <requester>
517 // ipfwd disable <requester>
518 if (!strcmp(argv[1], "enable")) {
520 success = gCtls->tetherCtrl.enableForwarding(argv[2]);
521 } else if (!strcmp(argv[1], "disable")) {
523 success = gCtls->tetherCtrl.disableForwarding(argv[2]);
525 } else if (argc == 4) {
527 // ipfwd add wlan0 dummy0
528 // ipfwd remove wlan0 dummy0
530 if (!strcmp(argv[1], "add")) {
532 ret = RouteController::enableTethering(argv[2], argv[3]);
533 } else if (!strcmp(argv[1], "remove")) {
535 ret = RouteController::disableTethering(argv[2], argv[3]);
537 success = (ret == 0);
542 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
547 cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
549 cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
554 CommandListener::TetherCmd::TetherCmd() :
555 NetdCommand("tether") {
558 int CommandListener::TetherCmd::runCommand(SocketClient *cli,
559 int argc, char **argv) {
563 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
567 if (!strcmp(argv[1], "stop")) {
568 rc = gCtls->tetherCtrl.stopTethering();
569 } else if (!strcmp(argv[1], "status")) {
572 asprintf(&tmp, "Tethering services %s",
573 (gCtls->tetherCtrl.isTetheringStarted() ? "started" : "stopped"));
574 cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
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);
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);
589 for (const auto &fwdr : *(gCtls->tetherCtrl.getDnsForwarders())) {
590 cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, fwdr.c_str(), false);
595 * These commands take a minimum of 4 arguments
598 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
602 if (!strcmp(argv[1], "start")) {
604 cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false);
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);
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 */
626 cli->sendMsg(ResponseCode::CommandParameterError,
627 "Unknown tether interface operation", false);
630 } else if (!strcmp(argv[1], "dns")) {
631 if (!strcmp(argv[2], "set")) {
633 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
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 */
640 cli->sendMsg(ResponseCode::CommandParameterError,
641 "Unknown tether interface operation", false);
645 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
651 cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
653 cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
659 CommandListener::NatCmd::NatCmd() :
663 int CommandListener::NatCmd::runCommand(SocketClient *cli,
664 int argc, char **argv) {
668 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
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]);
678 /* Ignore ifaces for now. */
679 rc = gCtls->bandwidthCtrl.setGlobalAlertInForwardChain();
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]);
686 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
691 cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
693 cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
699 CommandListener::PppdCmd::PppdCmd() :
700 NetdCommand("pppd") {
703 int CommandListener::PppdCmd::runCommand(SocketClient *cli,
704 int argc, char **argv) {
708 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
712 if (!strcmp(argv[1], "attach")) {
713 struct in_addr l, r, dns1, dns2;
715 memset(&dns1, 0, sizeof(struct in_addr));
716 memset(&dns2, 0, sizeof(struct in_addr));
718 if (!inet_aton(argv[3], &l)) {
719 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false);
722 if (!inet_aton(argv[4], &r)) {
723 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false);
726 if ((argc > 3) && (!inet_aton(argv[5], &dns1))) {
727 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false);
730 if ((argc > 4) && (!inet_aton(argv[6], &dns2))) {
731 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false);
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]);
738 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false);
743 cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false);
745 cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true);
751 CommandListener::SoftapCmd::SoftapCmd() :
752 NetdCommand("softap") {
755 int CommandListener::SoftapCmd::runCommand(SocketClient *cli,
756 int argc, char **argv) {
757 int rc = ResponseCode::SoftapStatusResult;
760 if (gCtls == nullptr) {
761 cli->sendMsg(ResponseCode::ServiceStartFailed, "SoftAP is not available", false);
765 cli->sendMsg(ResponseCode::CommandSyntaxError,
766 "Missing argument in a SoftAP command", false);
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);
782 } else if (!strcmp(argv[1], "set")) {
783 rc = gCtls->softapCtrl.setSoftap(argc, argv);
785 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unrecognized SoftAP command", false);
789 if (rc >= 400 && rc < 600)
790 cli->sendMsg(rc, "SoftAP command has failed", false);
792 cli->sendMsg(rc, "Ok", false);
797 CommandListener::ResolverCmd::ResolverCmd() :
798 NetdCommand("resolver") {
801 int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **margv) {
803 const char **argv = const_cast<const char **>(margv);
806 cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false);
810 unsigned netId = stringToNetId(argv[2]);
811 // TODO: Consider making NetworkController.isValidNetwork() public
812 // and making that check here.
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);
820 } else if (!strcmp(argv[1], "clearnetdns")) { // "resolver clearnetdns <netId>"
822 rc = gCtls->resolverCtrl.clearDnsServers(netId);
824 cli->sendMsg(ResponseCode::CommandSyntaxError,
825 "Wrong number of arguments to resolver clearnetdns", false);
829 cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false);
834 cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false);
836 cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true);
842 bool CommandListener::ResolverCmd::parseAndExecuteSetNetDns(int netId, int argc,
844 // "resolver setnetdns <netId> <domains> <dns1> [<dns2> ...] [--params <params>]"
845 // TODO: This code has to be replaced by a Binder call ASAP
851 const __res_params* paramsPtr = nullptr;
852 if (end > 6 && !strcmp(argv[end - 2], "--params")) {
853 const char* paramsStr = argv[end - 1];
855 if (sscanf(paramsStr, "%hu %hhu %hhu %hhu", ¶ms.sample_validity,
856 ¶ms.success_threshold, ¶ms.min_samples, ¶ms.max_samples) != 4) {
861 return gCtls->resolverCtrl.setDnsServers(netId, argv[3], &argv[4], end - 4, paramsPtr) == 0;
864 CommandListener::BandwidthControlCmd::BandwidthControlCmd() :
865 NetdCommand("bandwidth") {
868 void CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) {
870 asprintf(&msg, "Usage: bandwidth %s", usageMsg);
871 cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false);
875 void CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) {
877 cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
879 cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false);
883 void CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) {
884 cli->sendMsg(ResponseCode::OperationFailed, errMsg, false);
887 int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
889 sendGenericSyntaxError(cli, "<cmds> <args...>");
893 ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
895 if (!strcmp(argv[1], "enable")) {
896 int rc = gCtls->bandwidthCtrl.enableBandwidthControl(true);
897 sendGenericOkFail(cli, rc);
901 if (!strcmp(argv[1], "disable")) {
902 int rc = gCtls->bandwidthCtrl.disableBandwidthControl();
903 sendGenericOkFail(cli, rc);
907 if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
909 sendGenericSyntaxError(cli, "removequota <interface>");
912 int rc = gCtls->bandwidthCtrl.removeInterfaceSharedQuota(argv[2]);
913 sendGenericOkFail(cli, rc);
917 if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) {
920 sendGenericSyntaxError(cli, "getquota");
923 int rc = gCtls->bandwidthCtrl.getInterfaceSharedQuota(&bytes);
925 sendGenericOpFailed(cli, "Failed to get quota");
930 asprintf(&msg, "%" PRId64, bytes);
931 cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
936 if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) {
939 sendGenericSyntaxError(cli, "getiquota <iface>");
943 int rc = gCtls->bandwidthCtrl.getInterfaceQuota(argv[2], &bytes);
945 sendGenericOpFailed(cli, "Failed to get quota");
949 asprintf(&msg, "%" PRId64, bytes);
950 cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
955 if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
957 sendGenericSyntaxError(cli, "setquota <interface> <bytes>");
960 int rc = gCtls->bandwidthCtrl.setInterfaceSharedQuota(argv[2], atoll(argv[3]));
961 sendGenericOkFail(cli, rc);
964 if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
967 sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ...");
971 for (int q = 3; argc >= 4; q++, argc--) {
972 rc = gCtls->bandwidthCtrl.setInterfaceSharedQuota(argv[q], atoll(argv[2]));
975 asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]);
976 cli->sendMsg(ResponseCode::OperationFailed,
982 sendGenericOkFail(cli, rc);
986 if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) {
989 sendGenericSyntaxError(cli, "removequotas <interface> ...");
993 for (int q = 2; argc >= 3; q++, argc--) {
994 rc = gCtls->bandwidthCtrl.removeInterfaceSharedQuota(argv[q]);
997 asprintf(&msg, "bandwidth removequotas %s failed", argv[q]);
998 cli->sendMsg(ResponseCode::OperationFailed,
1004 sendGenericOkFail(cli, rc);
1008 if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
1010 sendGenericSyntaxError(cli, "removeiquota <interface>");
1013 int rc = gCtls->bandwidthCtrl.removeInterfaceQuota(argv[2]);
1014 sendGenericOkFail(cli, rc);
1018 if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
1020 sendGenericSyntaxError(cli, "setiquota <interface> <bytes>");
1023 int rc = gCtls->bandwidthCtrl.setInterfaceQuota(argv[2], atoll(argv[3]));
1024 sendGenericOkFail(cli, rc);
1028 if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
1030 sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ...");
1033 int rc = gCtls->bandwidthCtrl.addNaughtyApps(argc - 2, argv + 2);
1034 sendGenericOkFail(cli, rc);
1039 if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
1041 sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ...");
1044 int rc = gCtls->bandwidthCtrl.removeNaughtyApps(argc - 2, argv + 2);
1045 sendGenericOkFail(cli, rc);
1048 if (!strcmp(argv[1], "addniceapps") || !strcmp(argv[1], "aha")) {
1050 sendGenericSyntaxError(cli, "addniceapps <appUid> ...");
1053 int rc = gCtls->bandwidthCtrl.addNiceApps(argc - 2, argv + 2);
1054 sendGenericOkFail(cli, rc);
1057 if (!strcmp(argv[1], "removeniceapps") || !strcmp(argv[1], "rha")) {
1059 sendGenericSyntaxError(cli, "removeniceapps <appUid> ...");
1062 int rc = gCtls->bandwidthCtrl.removeNiceApps(argc - 2, argv + 2);
1063 sendGenericOkFail(cli, rc);
1066 if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) {
1068 sendGenericSyntaxError(cli, "setglobalalert <bytes>");
1071 int rc = gCtls->bandwidthCtrl.setGlobalAlert(atoll(argv[2]));
1072 sendGenericOkFail(cli, rc);
1075 if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) {
1077 sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>");
1080 /* We ignore the interfaces for now. */
1081 int rc = gCtls->bandwidthCtrl.setGlobalAlertInForwardChain();
1082 sendGenericOkFail(cli, rc);
1086 if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
1088 sendGenericSyntaxError(cli, "removeglobalalert");
1091 int rc = gCtls->bandwidthCtrl.removeGlobalAlert();
1092 sendGenericOkFail(cli, rc);
1096 if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) {
1098 sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>");
1101 /* We ignore the interfaces for now. */
1102 int rc = gCtls->bandwidthCtrl.removeGlobalAlertInForwardChain();
1103 sendGenericOkFail(cli, rc);
1107 if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
1109 sendGenericSyntaxError(cli, "setsharedalert <bytes>");
1112 int rc = gCtls->bandwidthCtrl.setSharedAlert(atoll(argv[2]));
1113 sendGenericOkFail(cli, rc);
1117 if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) {
1119 sendGenericSyntaxError(cli, "removesharedalert");
1122 int rc = gCtls->bandwidthCtrl.removeSharedAlert();
1123 sendGenericOkFail(cli, rc);
1127 if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) {
1129 sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>");
1132 int rc = gCtls->bandwidthCtrl.setInterfaceAlert(argv[2], atoll(argv[3]));
1133 sendGenericOkFail(cli, rc);
1137 if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) {
1139 sendGenericSyntaxError(cli, "removeinterfacealert <interface>");
1142 int rc = gCtls->bandwidthCtrl.removeInterfaceAlert(argv[2]);
1143 sendGenericOkFail(cli, rc);
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>]");
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);
1161 int rc = gCtls->bandwidthCtrl.getTetherStats(cli, tetherStats, extraProcessingInfo);
1163 extraProcessingInfo.insert(0, "Failed to get tethering stats.\n");
1164 sendGenericOpFailed(cli, extraProcessingInfo.c_str());
1171 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
1175 CommandListener::IdletimerControlCmd::IdletimerControlCmd() :
1176 NetdCommand("idletimer") {
1179 int CommandListener::IdletimerControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
1180 // TODO(ashish): Change the error statements
1182 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1186 ALOGV("idletimerctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
1188 if (!strcmp(argv[1], "enable")) {
1189 if (0 != gCtls->idletimerCtrl.enableIdletimerControl()) {
1190 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1192 cli->sendMsg(ResponseCode::CommandOkay, "Enable success", false);
1197 if (!strcmp(argv[1], "disable")) {
1198 if (0 != gCtls->idletimerCtrl.disableIdletimerControl()) {
1199 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1201 cli->sendMsg(ResponseCode::CommandOkay, "Disable success", false);
1205 if (!strcmp(argv[1], "add")) {
1207 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1210 if(0 != gCtls->idletimerCtrl.addInterfaceIdletimer(
1211 argv[2], atoi(argv[3]), argv[4])) {
1212 cli->sendMsg(ResponseCode::OperationFailed, "Failed to add interface", false);
1214 cli->sendMsg(ResponseCode::CommandOkay, "Add success", false);
1218 if (!strcmp(argv[1], "remove")) {
1220 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
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);
1228 cli->sendMsg(ResponseCode::CommandOkay, "Remove success", false);
1233 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown idletimer cmd", false);
1237 CommandListener::FirewallCmd::FirewallCmd() :
1238 NetdCommand("firewall") {
1241 int CommandListener::FirewallCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1243 cli->sendMsg(ResponseCode::CommandOkay, "Firewall command succeeded", false);
1245 cli->sendMsg(ResponseCode::OperationFailed, "Firewall command failed", false);
1250 FirewallRule CommandListener::FirewallCmd::parseRule(const char* arg) {
1251 if (!strcmp(arg, "allow")) {
1253 } else if (!strcmp(arg, "deny")) {
1256 ALOGE("failed to parse uid rule (%s)", arg);
1261 FirewallType CommandListener::FirewallCmd::parseFirewallType(const char* arg) {
1262 if (!strcmp(arg, "whitelist")) {
1264 } else if (!strcmp(arg, "blacklist")) {
1267 ALOGE("failed to parse firewall type (%s)", arg);
1272 ChildChain CommandListener::FirewallCmd::parseChildChain(const char* arg) {
1273 if (!strcmp(arg, "dozable")) {
1275 } else if (!strcmp(arg, "standby")) {
1277 } else if (!strcmp(arg, "powersave")) {
1279 } else if (!strcmp(arg, "none")) {
1282 ALOGE("failed to parse child firewall chain (%s)", arg);
1283 return INVALID_CHAIN;
1287 int CommandListener::FirewallCmd::runCommand(SocketClient *cli, int argc,
1290 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
1294 if (!strcmp(argv[1], "enable")) {
1296 cli->sendMsg(ResponseCode::CommandSyntaxError,
1297 "Usage: firewall enable <whitelist|blacklist>", false);
1300 FirewallType firewallType = parseFirewallType(argv[2]);
1302 int res = gCtls->firewallCtrl.enableFirewall(firewallType);
1303 return sendGenericOkFail(cli, res);
1305 if (!strcmp(argv[1], "disable")) {
1306 int res = gCtls->firewallCtrl.disableFirewall();
1307 return sendGenericOkFail(cli, res);
1309 if (!strcmp(argv[1], "is_enabled")) {
1310 int res = gCtls->firewallCtrl.isFirewallEnabled();
1311 return sendGenericOkFail(cli, res);
1314 if (!strcmp(argv[1], "set_interface_rule")) {
1316 cli->sendMsg(ResponseCode::CommandSyntaxError,
1317 "Usage: firewall set_interface_rule <rmnet0> <allow|deny>", false);
1321 const char* iface = argv[2];
1322 FirewallRule rule = parseRule(argv[3]);
1324 int res = gCtls->firewallCtrl.setInterfaceRule(iface, rule);
1325 return sendGenericOkFail(cli, res);
1328 if (!strcmp(argv[1], "set_egress_source_rule")) {
1330 cli->sendMsg(ResponseCode::CommandSyntaxError,
1331 "Usage: firewall set_egress_source_rule <192.168.0.1> <allow|deny>",
1336 const char* addr = argv[2];
1337 FirewallRule rule = parseRule(argv[3]);
1339 int res = gCtls->firewallCtrl.setEgressSourceRule(addr, rule);
1340 return sendGenericOkFail(cli, res);
1343 if (!strcmp(argv[1], "set_egress_dest_rule")) {
1345 cli->sendMsg(ResponseCode::CommandSyntaxError,
1346 "Usage: firewall set_egress_dest_rule <192.168.0.1> <80> <allow|deny>",
1351 const char* addr = argv[2];
1352 int port = atoi(argv[3]);
1353 FirewallRule rule = parseRule(argv[4]);
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);
1361 if (!strcmp(argv[1], "set_uid_rule")) {
1363 cli->sendMsg(ResponseCode::CommandSyntaxError,
1364 "Usage: firewall set_uid_rule <dozable|standby|none> <1000> <allow|deny>",
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>",
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);
1382 if (!strcmp(argv[1], "enable_chain")) {
1384 cli->sendMsg(ResponseCode::CommandSyntaxError,
1385 "Usage: firewall enable_chain <dozable|standby>",
1390 ChildChain childChain = parseChildChain(argv[2]);
1391 int res = gCtls->firewallCtrl.enableChildChains(childChain, true);
1392 return sendGenericOkFail(cli, res);
1395 if (!strcmp(argv[1], "disable_chain")) {
1397 cli->sendMsg(ResponseCode::CommandSyntaxError,
1398 "Usage: firewall disable_chain <dozable|standby>",
1403 ChildChain childChain = parseChildChain(argv[2]);
1404 int res = gCtls->firewallCtrl.enableChildChains(childChain, false);
1405 return sendGenericOkFail(cli, res);
1408 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
1412 CommandListener::ClatdCmd::ClatdCmd() : NetdCommand("clatd") {
1415 int CommandListener::ClatdCmd::runCommand(SocketClient *cli, int argc,
1419 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1423 if (!strcmp(argv[1], "stop")) {
1424 rc = gCtls->clatdCtrl.stopClatd(argv[2]);
1425 } else if (!strcmp(argv[1], "status")) {
1427 asprintf(&tmp, "Clatd status: %s", (gCtls->clatdCtrl.isClatdStarted(argv[2]) ?
1428 "started" : "stopped"));
1429 cli->sendMsg(ResponseCode::ClatdStatusResult, tmp, false);
1432 } else if (!strcmp(argv[1], "start")) {
1433 rc = gCtls->clatdCtrl.startClatd(argv[2]);
1435 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown clatd cmd", false);
1440 cli->sendMsg(ResponseCode::CommandOkay, "Clatd operation succeeded", false);
1442 cli->sendMsg(ResponseCode::OperationFailed, "Clatd operation failed", false);
1448 CommandListener::StrictCmd::StrictCmd() :
1449 NetdCommand("strict") {
1452 int CommandListener::StrictCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1454 cli->sendMsg(ResponseCode::CommandOkay, "Strict command succeeded", false);
1456 cli->sendMsg(ResponseCode::OperationFailed, "Strict command failed", false);
1461 StrictPenalty CommandListener::StrictCmd::parsePenalty(const char* arg) {
1462 if (!strcmp(arg, "reject")) {
1464 } else if (!strcmp(arg, "log")) {
1466 } else if (!strcmp(arg, "accept")) {
1473 int CommandListener::StrictCmd::runCommand(SocketClient *cli, int argc,
1476 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
1480 if (!strcmp(argv[1], "enable")) {
1481 int res = gCtls->strictCtrl.enableStrict();
1482 return sendGenericOkFail(cli, res);
1484 if (!strcmp(argv[1], "disable")) {
1485 int res = gCtls->strictCtrl.disableStrict();
1486 return sendGenericOkFail(cli, res);
1489 if (!strcmp(argv[1], "set_uid_cleartext_policy")) {
1491 cli->sendMsg(ResponseCode::CommandSyntaxError,
1492 "Usage: strict set_uid_cleartext_policy <uid> <accept|log|reject>",
1498 unsigned long int uid = strtoul(argv[2], NULL, 0);
1499 if (errno || uid > UID_MAX) {
1500 cli->sendMsg(ResponseCode::CommandSyntaxError, "Invalid UID", false);
1504 StrictPenalty penalty = parsePenalty(argv[3]);
1505 if (penalty == INVALID) {
1506 cli->sendMsg(ResponseCode::CommandSyntaxError, "Invalid penalty argument", false);
1510 int res = gCtls->strictCtrl.setUidCleartextPenalty((uid_t) uid, penalty);
1511 return sendGenericOkFail(cli, res);
1514 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
1518 CommandListener::NetworkCommand::NetworkCommand() : NetdCommand("network") {
1521 int CommandListener::NetworkCommand::syntaxError(SocketClient* client, const char* message) {
1522 client->sendMsg(ResponseCode::CommandSyntaxError, message, false);
1526 int CommandListener::NetworkCommand::operationError(SocketClient* client, const char* message,
1529 client->sendMsg(ResponseCode::OperationFailed, message, true);
1533 int CommandListener::NetworkCommand::success(SocketClient* client) {
1534 client->sendMsg(ResponseCode::CommandOkay, "success", false);
1538 int CommandListener::NetworkCommand::runCommand(SocketClient* client, int argc, char** argv) {
1540 return syntaxError(client, "Missing argument");
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]
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");
1554 bool legacy = false;
1556 if (!strcmp(argv[nextArg], "legacy")) {
1559 uid = strtoul(argv[nextArg++], NULL, 0);
1563 if (!strcmp(argv[nextArg], "add")) {
1565 } else if (strcmp(argv[nextArg], "remove")) {
1566 return syntaxError(client, "Unknown argument");
1570 if (argc < nextArg + 3 || argc > nextArg + 4) {
1571 return syntaxError(client, "Incorrect number of arguments");
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;
1581 ret = gCtls->netCtrl.addRoute(netId, interface, destination, nexthop, legacy, uid);
1583 ret = gCtls->netCtrl.removeRoute(netId, interface, destination, nexthop, legacy, uid);
1586 return operationError(client, add ? "addRoute() failed" : "removeRoute() failed", ret);
1589 return success(client);
1593 // network interface add <netId> <interface>
1594 // network interface remove <netId> <interface>
1595 if (!strcmp(argv[1], "interface")) {
1597 return syntaxError(client, "Missing argument");
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);
1604 } else if (!strcmp(argv[2], "remove")) {
1605 if (int ret = gCtls->netCtrl.removeInterfaceFromNetwork(netId, argv[4])) {
1606 return operationError(client, "removeInterfaceFromNetwork() failed", ret);
1609 return syntaxError(client, "Unknown argument");
1611 return success(client);
1615 // network create <netId> [permission]
1618 // network create <netId> vpn <hasDns> <secure>
1619 if (!strcmp(argv[1], "create")) {
1621 return syntaxError(client, "Missing argument");
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);
1630 } else if (argc > 4) {
1631 return syntaxError(client, "Unknown trailing argument(s)");
1633 Permission permission = PERMISSION_NONE;
1635 permission = stringToPermission(argv[3]);
1636 if (permission == PERMISSION_NONE) {
1637 return syntaxError(client, "Unknown permission");
1640 if (int ret = gCtls->netCtrl.createPhysicalNetwork(netId, permission)) {
1641 return operationError(client, "createPhysicalNetwork() failed", ret);
1644 return success(client);
1648 // network destroy <netId>
1649 if (!strcmp(argv[1], "destroy")) {
1651 return syntaxError(client, "Incorrect number of arguments");
1653 unsigned netId = stringToNetId(argv[2]);
1654 if (int ret = gCtls->netCtrl.destroyNetwork(netId)) {
1655 return operationError(client, "destroyNetwork() failed", ret);
1657 return success(client);
1661 // network default set <netId>
1662 // network default clear
1663 if (!strcmp(argv[1], "default")) {
1665 return syntaxError(client, "Missing argument");
1667 unsigned netId = NETID_UNSET;
1668 if (!strcmp(argv[2], "set")) {
1670 return syntaxError(client, "Missing netId");
1672 netId = stringToNetId(argv[3]);
1673 } else if (strcmp(argv[2], "clear")) {
1674 return syntaxError(client, "Unknown argument");
1676 if (int ret = gCtls->netCtrl.setDefaultNetwork(netId)) {
1677 return operationError(client, "setDefaultNetwork() failed", ret);
1679 return success(client);
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")) {
1689 return syntaxError(client, "Missing argument");
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");
1699 } else if (strcmp(argv[3], "clear")) {
1700 return syntaxError(client, "Unknown argument");
1702 if (nextArg == argc) {
1703 return syntaxError(client, "Missing id");
1706 bool userPermissions = !strcmp(argv[2], "user");
1707 bool networkPermissions = !strcmp(argv[2], "network");
1708 if (!userPermissions && !networkPermissions) {
1709 return syntaxError(client, "Unknown argument");
1712 std::vector<unsigned> ids;
1713 for (; nextArg < argc; ++nextArg) {
1714 if (userPermissions) {
1716 unsigned id = strtoul(argv[nextArg], &endPtr, 0);
1717 if (!*argv[nextArg] || *endPtr) {
1718 return syntaxError(client, "Invalid id");
1722 // networkPermissions
1723 ids.push_back(stringToNetId(argv[nextArg]));
1726 if (userPermissions) {
1727 gCtls->netCtrl.setPermissionForUsers(permission, ids);
1729 // networkPermissions
1730 if (int ret = gCtls->netCtrl.setPermissionForNetworks(permission, ids)) {
1731 return operationError(client, "setPermissionForNetworks() failed", ret);
1735 return success(client);
1739 // network users add <netId> [<uid>[-<uid>]] ...
1740 // network users remove <netId> [<uid>[-<uid>]] ...
1741 if (!strcmp(argv[1], "users")) {
1743 return syntaxError(client, "Missing argument");
1745 unsigned netId = stringToNetId(argv[3]);
1746 UidRanges uidRanges;
1747 if (!uidRanges.parseFrom(argc - 4, argv + 4)) {
1748 return syntaxError(client, "Invalid UIDs");
1750 if (!strcmp(argv[2], "add")) {
1751 if (int ret = gCtls->netCtrl.addUsersToNetwork(netId, uidRanges)) {
1752 return operationError(client, "addUsersToNetwork() failed", ret);
1754 } else if (!strcmp(argv[2], "remove")) {
1755 if (int ret = gCtls->netCtrl.removeUsersFromNetwork(netId, uidRanges)) {
1756 return operationError(client, "removeUsersFromNetwork() failed", ret);
1759 return syntaxError(client, "Unknown argument");
1761 return success(client);
1765 // network protect allow <uid> ...
1766 // network protect deny <uid> ...
1767 if (!strcmp(argv[1], "protect")) {
1769 return syntaxError(client, "Missing argument");
1771 std::vector<uid_t> uids;
1772 for (int i = 3; i < argc; ++i) {
1773 uids.push_back(strtoul(argv[i], NULL, 0));
1775 if (!strcmp(argv[2], "allow")) {
1776 gCtls->netCtrl.allowProtect(uids);
1777 } else if (!strcmp(argv[2], "deny")) {
1778 gCtls->netCtrl.denyProtect(uids);
1780 return syntaxError(client, "Unknown argument");
1782 return success(client);
1785 return syntaxError(client, "Unknown argument");