blob: f6c5c10949e5b0dd3ead47c159fe56d4c7bf1d49 [file] [log] [blame]
San Mehatd1830422010-01-15 08:02:39 -08001/*
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
JP Abgrall1fb02df2012-04-24 23:27:44 -070017// #define LOG_NDEBUG 0
JP Abgralldb7da582011-09-18 12:57:32 -070018
San Mehatd1830422010-01-15 08:02:39 -080019#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>
Olivier Baillyff2c0d82010-11-17 11:45:07 -080026#include <string.h>
San Mehat5c1b8af2010-01-21 15:37:10 -080027#include <linux/if.h>
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050028#include <resolv_netid.h>
Pierre Imai95f5f942016-03-09 18:09:25 +090029#include <resolv_params.h>
San Mehat5c1b8af2010-01-21 15:37:10 -080030
Matthew Leach2a54d962013-01-14 15:07:12 +000031#define __STDC_FORMAT_MACROS 1
32#include <inttypes.h>
33
San Mehatd1830422010-01-15 08:02:39 -080034#define LOG_TAG "CommandListener"
San Mehatd1830422010-01-15 08:02:39 -080035
Lorenzo Colitti1ed47c42011-09-27 11:10:46 -070036#include <cutils/log.h>
37#include <netutils/ifc.h>
San Mehatd1830422010-01-15 08:02:39 -080038#include <sysutils/SocketClient.h>
39
Pierre Imai1cfa5432016-02-24 18:00:03 +090040#include "Controllers.h"
San Mehatd1830422010-01-15 08:02:39 -080041#include "CommandListener.h"
42#include "ResponseCode.h"
JP Abgrall4a5f5ca2011-06-15 18:37:39 -070043#include "BandwidthController.h"
JP Abgrall0031cea2012-04-17 16:38:23 -070044#include "IdletimerController.h"
JP Abgrall0031cea2012-04-17 16:38:23 -070045#include "oem_iptables_hook.h"
Jeff Sharkey8e188ed2012-07-12 18:32:03 -070046#include "NetdConstants.h"
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070047#include "FirewallController.h"
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070048#include "RouteController.h"
Sreeram Ramachandranb1425cc2014-06-23 18:54:27 -070049#include "UidRanges.h"
Devi Sandeep Endluri V V893c1222016-04-27 22:31:19 +053050#include "QtiConnectivityAdapter.h"
Manjunatha Prabhu163228f2016-06-27 14:37:54 +053051#include "QtiDataController.h"
San Mehat5c1b8af2010-01-21 15:37:10 -080052
c_rrajiv9400fcf2014-07-18 18:50:37 -070053#ifdef QSAP_WLAN
54#include "qsap_api.h"
55#endif
56
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070057#include <string>
58#include <vector>
59
Pierre Imai1cfa5432016-02-24 18:00:03 +090060using android::net::gCtls;
61
Sreeram Ramachandran379bd332014-04-10 19:58:06 -070062namespace {
63
Sreeram Ramachandranbbdde992014-09-05 16:05:03 -070064const unsigned NUM_OEM_IDS = NetworkController::MAX_OEM_ID - NetworkController::MIN_OEM_ID + 1;
65
Sreeram Ramachandraned4bd1f2014-07-05 12:31:05 -070066Permission stringToPermission(const char* arg) {
Sreeram Ramachandran584dbee2014-11-04 10:18:25 -080067 if (!strcmp(arg, "NETWORK")) {
Sreeram Ramachandraned4bd1f2014-07-05 12:31:05 -070068 return PERMISSION_NETWORK;
Sreeram Ramachandran379bd332014-04-10 19:58:06 -070069 }
Sreeram Ramachandran584dbee2014-11-04 10:18:25 -080070 if (!strcmp(arg, "SYSTEM")) {
Sreeram Ramachandraned4bd1f2014-07-05 12:31:05 -070071 return PERMISSION_SYSTEM;
72 }
73 return PERMISSION_NONE;
Sreeram Ramachandran379bd332014-04-10 19:58:06 -070074}
75
Sreeram Ramachandran87475a12014-07-15 16:20:28 -070076unsigned stringToNetId(const char* arg) {
77 if (!strcmp(arg, "local")) {
78 return NetworkController::LOCAL_NET_ID;
79 }
Sreeram Ramachandranbbdde992014-09-05 16:05:03 -070080 // OEM NetIds are "oem1", "oem2", .., "oem50".
81 if (!strncmp(arg, "oem", 3)) {
82 unsigned n = strtoul(arg + 3, NULL, 0);
83 if (1 <= n && n <= NUM_OEM_IDS) {
84 return NetworkController::MIN_OEM_ID + n;
85 }
86 return NETID_UNSET;
87 }
Sreeram Ramachandran87475a12014-07-15 16:20:28 -070088 // strtoul() returns 0 on errors, which is fine because 0 is an invalid netId.
89 return strtoul(arg, NULL, 0);
90}
91
Lorenzo Colittiddf2d5b2016-02-26 11:30:59 +090092class LockingFrameworkCommand : public FrameworkCommand {
93public:
94 LockingFrameworkCommand(FrameworkCommand *wrappedCmd, android::RWLock& lock) :
95 FrameworkCommand(wrappedCmd->getCommand()),
96 mWrappedCmd(wrappedCmd),
97 mLock(lock) {}
98
99 int runCommand(SocketClient *c, int argc, char **argv) {
100 android::RWLock::AutoWLock lock(mLock);
101 return mWrappedCmd->runCommand(c, argc, argv);
102 }
103
104private:
105 FrameworkCommand *mWrappedCmd;
106 android::RWLock& mLock;
107};
108
109
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700110} // namespace
111
Jeff Sharkey8e188ed2012-07-12 18:32:03 -0700112/**
113 * List of module chains to be created, along with explicit ordering. ORDERING
114 * IS CRITICAL, AND SHOULD BE TRIPLE-CHECKED WITH EACH CHANGE.
115 */
116static const char* FILTER_INPUT[] = {
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700117 // Bandwidth should always be early in input chain, to make sure we
118 // correctly count incoming traffic against data plan.
Jeff Sharkey8e188ed2012-07-12 18:32:03 -0700119 BandwidthController::LOCAL_INPUT,
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700120 FirewallController::LOCAL_INPUT,
Jeff Sharkey8e188ed2012-07-12 18:32:03 -0700121 NULL,
122};
123
124static const char* FILTER_FORWARD[] = {
125 OEM_IPTABLES_FILTER_FORWARD,
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700126 FirewallController::LOCAL_FORWARD,
Jeff Sharkey8e188ed2012-07-12 18:32:03 -0700127 BandwidthController::LOCAL_FORWARD,
128 NatController::LOCAL_FORWARD,
129 NULL,
130};
131
132static const char* FILTER_OUTPUT[] = {
133 OEM_IPTABLES_FILTER_OUTPUT,
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700134 FirewallController::LOCAL_OUTPUT,
Jeff Sharkeyfbe497f2014-10-28 16:50:07 -0700135 StrictController::LOCAL_OUTPUT,
Jeff Sharkey8e188ed2012-07-12 18:32:03 -0700136 BandwidthController::LOCAL_OUTPUT,
137 NULL,
138};
139
140static const char* RAW_PREROUTING[] = {
141 BandwidthController::LOCAL_RAW_PREROUTING,
Haoyu Bai5c4faf72012-07-26 15:36:53 -0700142 IdletimerController::LOCAL_RAW_PREROUTING,
Jeff Sharkey8e188ed2012-07-12 18:32:03 -0700143 NULL,
144};
145
146static const char* MANGLE_POSTROUTING[] = {
147 BandwidthController::LOCAL_MANGLE_POSTROUTING,
Haoyu Bai5c4faf72012-07-26 15:36:53 -0700148 IdletimerController::LOCAL_MANGLE_POSTROUTING,
Chad Brubaker9a508892013-05-31 20:51:46 -0700149 NULL,
150};
151
Lorenzo Colittie8164dd2014-10-02 20:46:23 +0900152static const char* MANGLE_FORWARD[] = {
153 NatController::LOCAL_MANGLE_FORWARD,
154 NULL,
155};
156
Jeff Sharkey8e188ed2012-07-12 18:32:03 -0700157static const char* NAT_PREROUTING[] = {
158 OEM_IPTABLES_NAT_PREROUTING,
Jeff Sharkey8e188ed2012-07-12 18:32:03 -0700159 NULL,
160};
161
162static const char* NAT_POSTROUTING[] = {
Jeff Sharkey8e188ed2012-07-12 18:32:03 -0700163 NatController::LOCAL_NAT_POSTROUTING,
164 NULL,
165};
166
167static void createChildChains(IptablesTarget target, const char* table, const char* parentChain,
168 const char** childChains) {
169 const char** childChain = childChains;
170 do {
171 // Order is important:
172 // -D to delete any pre-existing jump rule (removes references
173 // that would prevent -X from working)
174 // -F to flush any existing chain
175 // -X to delete any existing chain
176 // -N to create the chain
177 // -A to append the chain to parent
178
179 execIptablesSilently(target, "-t", table, "-D", parentChain, "-j", *childChain, NULL);
180 execIptablesSilently(target, "-t", table, "-F", *childChain, NULL);
181 execIptablesSilently(target, "-t", table, "-X", *childChain, NULL);
182 execIptables(target, "-t", table, "-N", *childChain, NULL);
183 execIptables(target, "-t", table, "-A", parentChain, "-j", *childChain, NULL);
184 } while (*(++childChain) != NULL);
185}
186
Lorenzo Colittiddf2d5b2016-02-26 11:30:59 +0900187void CommandListener::registerLockingCmd(FrameworkCommand *cmd, android::RWLock& lock) {
188 registerCmd(new LockingFrameworkCommand(cmd, lock));
189}
190
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500191CommandListener::CommandListener() :
Robert Greenwalta8e59f82012-02-16 14:48:11 -0800192 FrameworkListener("netd", true) {
Lorenzo Colittie4d626e2016-02-02 17:19:04 +0900193 registerLockingCmd(new InterfaceCmd());
194 registerLockingCmd(new IpFwdCmd());
195 registerLockingCmd(new TetherCmd());
196 registerLockingCmd(new NatCmd());
197 registerLockingCmd(new ListTtysCmd());
198 registerLockingCmd(new PppdCmd());
199 registerLockingCmd(new SoftapCmd());
Lorenzo Colittidedd2712016-03-22 12:36:29 +0900200 registerLockingCmd(new BandwidthControlCmd(), gCtls->bandwidthCtrl.lock);
Lorenzo Colittie4d626e2016-02-02 17:19:04 +0900201 registerLockingCmd(new IdletimerControlCmd());
202 registerLockingCmd(new ResolverCmd());
Lorenzo Colittiddf2d5b2016-02-26 11:30:59 +0900203 registerLockingCmd(new FirewallCmd(), gCtls->firewallCtrl.lock);
Lorenzo Colittie4d626e2016-02-02 17:19:04 +0900204 registerLockingCmd(new ClatdCmd());
205 registerLockingCmd(new NetworkCommand());
206 registerLockingCmd(new StrictCmd());
Devi Sandeep Endluri V V893c1222016-04-27 22:31:19 +0530207 registerLockingCmd(getQtiConnectivityCmd(this));
San Mehat9d10b342010-01-18 09:51:02 -0800208
Manjunatha Prabhu163228f2016-06-27 14:37:54 +0530209 initializeDataControllerLib();
210
JP Abgrall0031cea2012-04-17 16:38:23 -0700211 /*
Jeff Sharkey8e188ed2012-07-12 18:32:03 -0700212 * This is the only time we touch top-level chains in iptables; controllers
213 * should only mutate rules inside of their children chains, as created by
214 * the constants above.
215 *
216 * Modules should never ACCEPT packets (except in well-justified cases);
217 * they should instead defer to any remaining modules using RETURN, or
218 * otherwise DROP/REJECT.
JP Abgrall0031cea2012-04-17 16:38:23 -0700219 */
Jeff Sharkey8e188ed2012-07-12 18:32:03 -0700220
221 // Create chains for children modules
222 createChildChains(V4V6, "filter", "INPUT", FILTER_INPUT);
223 createChildChains(V4V6, "filter", "FORWARD", FILTER_FORWARD);
224 createChildChains(V4V6, "filter", "OUTPUT", FILTER_OUTPUT);
225 createChildChains(V4V6, "raw", "PREROUTING", RAW_PREROUTING);
226 createChildChains(V4V6, "mangle", "POSTROUTING", MANGLE_POSTROUTING);
Lorenzo Colittie8164dd2014-10-02 20:46:23 +0900227 createChildChains(V4, "mangle", "FORWARD", MANGLE_FORWARD);
Jeff Sharkey8e188ed2012-07-12 18:32:03 -0700228 createChildChains(V4, "nat", "PREROUTING", NAT_PREROUTING);
229 createChildChains(V4, "nat", "POSTROUTING", NAT_POSTROUTING);
230
231 // Let each module setup their child chains
JP Abgrall0031cea2012-04-17 16:38:23 -0700232 setupOemIptablesHook();
Jeff Sharkey8e188ed2012-07-12 18:32:03 -0700233
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700234 /* When enabled, DROPs all packets except those matching rules. */
Pierre Imai1cfa5432016-02-24 18:00:03 +0900235 gCtls->firewallCtrl.setupIptablesHooks();
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700236
JP Abgrall0031cea2012-04-17 16:38:23 -0700237 /* Does DROPs in FORWARD by default */
Pierre Imai1cfa5432016-02-24 18:00:03 +0900238 gCtls->natCtrl.setupIptablesHooks();
JP Abgrall0031cea2012-04-17 16:38:23 -0700239 /*
240 * Does REJECT in INPUT, OUTPUT. Does counting also.
241 * No DROP/REJECT allowed later in netfilter-flow hook order.
242 */
Pierre Imai1cfa5432016-02-24 18:00:03 +0900243 gCtls->bandwidthCtrl.setupIptablesHooks();
JP Abgrall0031cea2012-04-17 16:38:23 -0700244 /*
245 * Counts in nat: PREROUTING, POSTROUTING.
246 * No DROP/REJECT allowed later in netfilter-flow hook order.
247 */
Pierre Imai1cfa5432016-02-24 18:00:03 +0900248 gCtls->idletimerCtrl.setupIptablesHooks();
JP Abgrall0031cea2012-04-17 16:38:23 -0700249
Pierre Imai1cfa5432016-02-24 18:00:03 +0900250 gCtls->bandwidthCtrl.enableBandwidthControl(false);
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700251
Sreeram Ramachandran87475a12014-07-15 16:20:28 -0700252 if (int ret = RouteController::Init(NetworkController::LOCAL_NET_ID)) {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700253 ALOGE("failed to initialize RouteController (%s)", strerror(-ret));
254 }
San Mehatd1830422010-01-15 08:02:39 -0800255}
256
San Mehat5c1b8af2010-01-21 15:37:10 -0800257CommandListener::InterfaceCmd::InterfaceCmd() :
258 NetdCommand("interface") {
San Mehatd1830422010-01-15 08:02:39 -0800259}
260
San Mehat5c1b8af2010-01-21 15:37:10 -0800261int CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
San Mehatd1830422010-01-15 08:02:39 -0800262 int argc, char **argv) {
San Mehat5c1b8af2010-01-21 15:37:10 -0800263 if (argc < 2) {
264 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
265 return 0;
266 }
267
268 if (!strcmp(argv[1], "list")) {
269 DIR *d;
270 struct dirent *de;
271
272 if (!(d = opendir("/sys/class/net"))) {
273 cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true);
274 return 0;
275 }
276
277 while((de = readdir(d))) {
278 if (de->d_name[0] == '.')
279 continue;
280 cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false);
281 }
282 closedir(d);
283 cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false);
284 return 0;
285 } else {
286 /*
287 * These commands take a minimum of 3 arguments
288 */
289 if (argc < 3) {
290 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
291 return 0;
292 }
Robert Greenwalte019b652011-05-10 14:57:03 -0700293
San Mehat5c1b8af2010-01-21 15:37:10 -0800294 if (!strcmp(argv[1], "getcfg")) {
Robert Greenwalt1d93e172011-02-01 13:54:35 -0800295 struct in_addr addr;
296 int prefixLength;
San Mehat5c1b8af2010-01-21 15:37:10 -0800297 unsigned char hwaddr[6];
298 unsigned flags = 0;
299
300 ifc_init();
301 memset(hwaddr, 0, sizeof(hwaddr));
302
Robert Greenwalt1d93e172011-02-01 13:54:35 -0800303 if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) {
San Mehat5c1b8af2010-01-21 15:37:10 -0800304 cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
Irfan Sheriffe734edd2011-06-16 10:28:47 -0700305 ifc_close();
San Mehat5c1b8af2010-01-21 15:37:10 -0800306 return 0;
307 }
308
309 if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) {
Steve Block0e76b762012-01-05 23:21:51 +0000310 ALOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno));
San Mehat5c1b8af2010-01-21 15:37:10 -0800311 }
312
313 char *addr_s = strdup(inet_ntoa(addr));
San Mehat5c1b8af2010-01-21 15:37:10 -0800314 const char *updown, *brdcst, *loopbk, *ppp, *running, *multi;
315
316 updown = (flags & IFF_UP) ? "up" : "down";
317 brdcst = (flags & IFF_BROADCAST) ? " broadcast" : "";
318 loopbk = (flags & IFF_LOOPBACK) ? " loopback" : "";
319 ppp = (flags & IFF_POINTOPOINT) ? " point-to-point" : "";
320 running = (flags & IFF_RUNNING) ? " running" : "";
321 multi = (flags & IFF_MULTICAST) ? " multicast" : "";
322
323 char *flag_s;
324
Jeff Sharkey31ea0b02011-11-29 18:38:14 -0800325 asprintf(&flag_s, "%s%s%s%s%s%s", updown, brdcst, loopbk, ppp, running, multi);
San Mehat5c1b8af2010-01-21 15:37:10 -0800326
327 char *msg = NULL;
Robert Greenwalt1d93e172011-02-01 13:54:35 -0800328 asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %d %s",
San Mehat5c1b8af2010-01-21 15:37:10 -0800329 hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5],
Robert Greenwalt1d93e172011-02-01 13:54:35 -0800330 addr_s, prefixLength, flag_s);
San Mehat5c1b8af2010-01-21 15:37:10 -0800331
San Mehat01fed782010-01-23 06:47:59 -0800332 cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false);
San Mehat5c1b8af2010-01-21 15:37:10 -0800333
334 free(addr_s);
San Mehat5c1b8af2010-01-21 15:37:10 -0800335 free(flag_s);
336 free(msg);
Irfan Sheriffe734edd2011-06-16 10:28:47 -0700337
338 ifc_close();
San Mehat5c1b8af2010-01-21 15:37:10 -0800339 return 0;
340 } else if (!strcmp(argv[1], "setcfg")) {
Dmitry Shmidt778ffe42012-06-20 12:59:21 -0700341 // arglist: iface [addr prefixLength] flags
342 if (argc < 4) {
San Mehat5c1b8af2010-01-21 15:37:10 -0800343 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
344 return 0;
345 }
Steve Block7b984e32011-12-20 16:22:42 +0000346 ALOGD("Setting iface cfg");
San Mehat5c1b8af2010-01-21 15:37:10 -0800347
Robert Greenwalt1d93e172011-02-01 13:54:35 -0800348 struct in_addr addr;
Dmitry Shmidt778ffe42012-06-20 12:59:21 -0700349 int index = 5;
San Mehat5c1b8af2010-01-21 15:37:10 -0800350
San Mehat5c1b8af2010-01-21 15:37:10 -0800351 ifc_init();
San Mehat5c1b8af2010-01-21 15:37:10 -0800352
Dmitry Shmidt778ffe42012-06-20 12:59:21 -0700353 if (!inet_aton(argv[3], &addr)) {
354 // Handle flags only case
355 index = 3;
356 } else {
Erik Kline5e69c7f2016-02-05 18:06:15 +0900357 if (ifc_set_addr(argv[2], 0)) {
358 cli->sendMsg(ResponseCode::OperationFailed, "Failed to clear address", true);
Dmitry Shmidt778ffe42012-06-20 12:59:21 -0700359 ifc_close();
360 return 0;
361 }
Erik Kline5e69c7f2016-02-05 18:06:15 +0900362 if (addr.s_addr != 0) {
363 if (ifc_add_address(argv[2], argv[3], atoi(argv[4]))) {
364 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true);
365 ifc_close();
366 return 0;
367 }
368 }
San Mehat5c1b8af2010-01-21 15:37:10 -0800369 }
370
371 /* Process flags */
Dmitry Shmidt778ffe42012-06-20 12:59:21 -0700372 for (int i = index; i < argc; i++) {
Robert Greenwalte7b94222010-02-18 10:54:08 -0800373 char *flag = argv[i];
Robert Greenwalte7b94222010-02-18 10:54:08 -0800374 if (!strcmp(flag, "up")) {
Steve Block7b984e32011-12-20 16:22:42 +0000375 ALOGD("Trying to bring up %s", argv[2]);
San Mehat5c1b8af2010-01-21 15:37:10 -0800376 if (ifc_up(argv[2])) {
Steve Block5ea0c052012-01-06 19:18:11 +0000377 ALOGE("Error upping interface");
San Mehat5c1b8af2010-01-21 15:37:10 -0800378 cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true);
Irfan Sheriffe734edd2011-06-16 10:28:47 -0700379 ifc_close();
San Mehat5c1b8af2010-01-21 15:37:10 -0800380 return 0;
381 }
Robert Greenwalte7b94222010-02-18 10:54:08 -0800382 } else if (!strcmp(flag, "down")) {
Steve Block7b984e32011-12-20 16:22:42 +0000383 ALOGD("Trying to bring down %s", argv[2]);
San Mehat5c1b8af2010-01-21 15:37:10 -0800384 if (ifc_down(argv[2])) {
Steve Block5ea0c052012-01-06 19:18:11 +0000385 ALOGE("Error downing interface");
San Mehat5c1b8af2010-01-21 15:37:10 -0800386 cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true);
Irfan Sheriffe734edd2011-06-16 10:28:47 -0700387 ifc_close();
San Mehat5c1b8af2010-01-21 15:37:10 -0800388 return 0;
389 }
Robert Greenwalte7b94222010-02-18 10:54:08 -0800390 } else if (!strcmp(flag, "broadcast")) {
Jeff Sharkey7c2ddd82011-12-01 15:25:28 -0800391 // currently ignored
Robert Greenwalte7b94222010-02-18 10:54:08 -0800392 } else if (!strcmp(flag, "multicast")) {
Jeff Sharkey7c2ddd82011-12-01 15:25:28 -0800393 // currently ignored
394 } else if (!strcmp(flag, "running")) {
395 // currently ignored
396 } else if (!strcmp(flag, "loopback")) {
397 // currently ignored
398 } else if (!strcmp(flag, "point-to-point")) {
399 // currently ignored
San Mehat5c1b8af2010-01-21 15:37:10 -0800400 } else {
401 cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false);
Irfan Sheriffe734edd2011-06-16 10:28:47 -0700402 ifc_close();
San Mehat5c1b8af2010-01-21 15:37:10 -0800403 return 0;
404 }
405 }
Irfan Sheriffe734edd2011-06-16 10:28:47 -0700406
San Mehat5c1b8af2010-01-21 15:37:10 -0800407 cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false);
Irfan Sheriffe734edd2011-06-16 10:28:47 -0700408 ifc_close();
409 return 0;
410 } else if (!strcmp(argv[1], "clearaddrs")) {
411 // arglist: iface
Steve Block7b984e32011-12-20 16:22:42 +0000412 ALOGD("Clearing all IP addresses on %s", argv[2]);
Irfan Sheriffe734edd2011-06-16 10:28:47 -0700413
Lorenzo Colitti1ed47c42011-09-27 11:10:46 -0700414 ifc_clear_addresses(argv[2]);
415
Irfan Sheriffe734edd2011-06-16 10:28:47 -0700416 cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false);
San Mehat5c1b8af2010-01-21 15:37:10 -0800417 return 0;
Irfan Sheriff32a9dc62011-09-14 12:32:47 -0700418 } else if (!strcmp(argv[1], "ipv6privacyextensions")) {
419 if (argc != 4) {
420 cli->sendMsg(ResponseCode::CommandSyntaxError,
421 "Usage: interface ipv6privacyextensions <interface> <enable|disable>",
422 false);
423 return 0;
424 }
Lorenzo Colitti70afde62013-03-04 17:58:40 +0900425 int enable = !strncmp(argv[3], "enable", 7);
Pierre Imai1cfa5432016-02-24 18:00:03 +0900426 if (gCtls->interfaceCtrl.setIPv6PrivacyExtensions(argv[2], enable) == 0) {
Lorenzo Colitti70afde62013-03-04 17:58:40 +0900427 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false);
428 } else {
Irfan Sheriff32a9dc62011-09-14 12:32:47 -0700429 cli->sendMsg(ResponseCode::OperationFailed,
430 "Failed to set ipv6 privacy extensions", true);
Irfan Sheriff32a9dc62011-09-14 12:32:47 -0700431 }
Irfan Sheriff32a9dc62011-09-14 12:32:47 -0700432 return 0;
repo syncc1b38702011-09-29 16:10:42 -0700433 } else if (!strcmp(argv[1], "ipv6")) {
434 if (argc != 4) {
435 cli->sendMsg(ResponseCode::CommandSyntaxError,
436 "Usage: interface ipv6 <interface> <enable|disable>",
437 false);
438 return 0;
439 }
440
Lorenzo Colitti70afde62013-03-04 17:58:40 +0900441 int enable = !strncmp(argv[3], "enable", 7);
Pierre Imai1cfa5432016-02-24 18:00:03 +0900442 if (gCtls->interfaceCtrl.setEnableIPv6(argv[2], enable) == 0) {
Lorenzo Colitti70afde62013-03-04 17:58:40 +0900443 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false);
444 } else {
repo syncc1b38702011-09-29 16:10:42 -0700445 cli->sendMsg(ResponseCode::OperationFailed,
446 "Failed to change IPv6 state", true);
repo syncc1b38702011-09-29 16:10:42 -0700447 }
repo syncc1b38702011-09-29 16:10:42 -0700448 return 0;
Lorenzo Colitti0ea8ff82014-10-28 00:15:07 +0900449 } else if (!strcmp(argv[1], "ipv6ndoffload")) {
450 if (argc != 4) {
451 cli->sendMsg(ResponseCode::CommandSyntaxError,
452 "Usage: interface ipv6ndoffload <interface> <enable|disable>",
453 false);
454 return 0;
455 }
456 int enable = !strncmp(argv[3], "enable", 7);
Pierre Imai1cfa5432016-02-24 18:00:03 +0900457 if (gCtls->interfaceCtrl.setIPv6NdOffload(argv[2], enable) == 0) {
Lorenzo Colitti0ea8ff82014-10-28 00:15:07 +0900458 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 ND offload changed", false);
459 } else {
460 cli->sendMsg(ResponseCode::OperationFailed,
461 "Failed to change IPv6 ND offload state", true);
462 }
463 return 0;
Dmitry Shmidt6d6c0e62013-06-11 16:18:06 -0700464 } else if (!strcmp(argv[1], "setmtu")) {
465 if (argc != 4) {
466 cli->sendMsg(ResponseCode::CommandSyntaxError,
467 "Usage: interface setmtu <interface> <val>", false);
468 return 0;
469 }
Pierre Imai1cfa5432016-02-24 18:00:03 +0900470 if (gCtls->interfaceCtrl.setMtu(argv[2], argv[3]) == 0) {
Dmitry Shmidt6d6c0e62013-06-11 16:18:06 -0700471 cli->sendMsg(ResponseCode::CommandOkay, "MTU changed", false);
472 } else {
473 cli->sendMsg(ResponseCode::OperationFailed,
Erik Klinea59c9282015-04-01 11:38:14 +0900474 "Failed to set MTU", true);
Dmitry Shmidt6d6c0e62013-06-11 16:18:06 -0700475 }
476 return 0;
San Mehat5c1b8af2010-01-21 15:37:10 -0800477 } else {
478 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
479 return 0;
480 }
481 }
San Mehatd1830422010-01-15 08:02:39 -0800482 return 0;
483}
484
JP Abgrall4a5f5ca2011-06-15 18:37:39 -0700485
San Mehatd5573d32010-01-19 17:19:41 -0800486CommandListener::ListTtysCmd::ListTtysCmd() :
487 NetdCommand("list_ttys") {
488}
489
490int CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
Sreeram Ramachandran56afacf2014-05-28 15:07:00 -0700491 int /* argc */, char ** /* argv */) {
Pierre Imai1cfa5432016-02-24 18:00:03 +0900492 TtyCollection *tlist = gCtls->pppCtrl.getTtyList();
San Mehatd5573d32010-01-19 17:19:41 -0800493 TtyCollection::iterator it;
494
495 for (it = tlist->begin(); it != tlist->end(); ++it) {
496 cli->sendMsg(ResponseCode::TtyListResult, *it, false);
497 }
498
499 cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
500 return 0;
501}
502
San Mehatd1830422010-01-15 08:02:39 -0800503CommandListener::IpFwdCmd::IpFwdCmd() :
504 NetdCommand("ipfwd") {
505}
506
Lorenzo Colitti799625c2015-02-25 12:52:00 +0900507int CommandListener::IpFwdCmd::runCommand(SocketClient *cli, int argc, char **argv) {
Lorenzo Colitti32d76872015-02-26 01:26:53 +0900508 bool matched = false;
Lorenzo Colitti799625c2015-02-25 12:52:00 +0900509 bool success;
San Mehat9d10b342010-01-18 09:51:02 -0800510
Lorenzo Colitti32d76872015-02-26 01:26:53 +0900511 if (argc == 2) {
512 // 0 1
513 // ipfwd status
514 if (!strcmp(argv[1], "status")) {
515 char *tmp = NULL;
Lorenzo Colitti799625c2015-02-25 12:52:00 +0900516
Lorenzo Colitti32d76872015-02-26 01:26:53 +0900517 asprintf(&tmp, "Forwarding %s",
Pierre Imai1cfa5432016-02-24 18:00:03 +0900518 ((gCtls->tetherCtrl.forwardingRequestCount() > 0) ? "enabled" : "disabled"));
Lorenzo Colitti32d76872015-02-26 01:26:53 +0900519 cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
520 free(tmp);
521 return 0;
522 }
523 } else if (argc == 3) {
524 // 0 1 2
525 // ipfwd enable <requester>
526 // ipfwd disable <requester>
527 if (!strcmp(argv[1], "enable")) {
528 matched = true;
Pierre Imai1cfa5432016-02-24 18:00:03 +0900529 success = gCtls->tetherCtrl.enableForwarding(argv[2]);
Lorenzo Colitti32d76872015-02-26 01:26:53 +0900530 } else if (!strcmp(argv[1], "disable")) {
531 matched = true;
Pierre Imai1cfa5432016-02-24 18:00:03 +0900532 success = gCtls->tetherCtrl.disableForwarding(argv[2]);
Lorenzo Colitti32d76872015-02-26 01:26:53 +0900533 }
534 } else if (argc == 4) {
535 // 0 1 2 3
536 // ipfwd add wlan0 dummy0
537 // ipfwd remove wlan0 dummy0
538 int ret = 0;
539 if (!strcmp(argv[1], "add")) {
540 matched = true;
541 ret = RouteController::enableTethering(argv[2], argv[3]);
542 } else if (!strcmp(argv[1], "remove")) {
543 matched = true;
544 ret = RouteController::disableTethering(argv[2], argv[3]);
545 }
546 success = (ret == 0);
547 errno = -ret;
San Mehat9d10b342010-01-18 09:51:02 -0800548 }
549
Lorenzo Colitti32d76872015-02-26 01:26:53 +0900550 if (!matched) {
San Mehat9d10b342010-01-18 09:51:02 -0800551 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
552 return 0;
553 }
554
Lorenzo Colitti799625c2015-02-25 12:52:00 +0900555 if (success) {
San Mehat9d10b342010-01-18 09:51:02 -0800556 cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
557 } else {
558 cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
559 }
San Mehatd1830422010-01-15 08:02:39 -0800560 return 0;
561}
562
563CommandListener::TetherCmd::TetherCmd() :
564 NetdCommand("tether") {
565}
566
567int CommandListener::TetherCmd::runCommand(SocketClient *cli,
568 int argc, char **argv) {
San Mehat9d10b342010-01-18 09:51:02 -0800569 int rc = 0;
570
San Mehatd1830422010-01-15 08:02:39 -0800571 if (argc < 2) {
572 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
573 return 0;
574 }
575
San Mehat9d10b342010-01-18 09:51:02 -0800576 if (!strcmp(argv[1], "stop")) {
Pierre Imai1cfa5432016-02-24 18:00:03 +0900577 rc = gCtls->tetherCtrl.stopTethering();
San Mehatd1830422010-01-15 08:02:39 -0800578 } else if (!strcmp(argv[1], "status")) {
San Mehat9d10b342010-01-18 09:51:02 -0800579 char *tmp = NULL;
580
581 asprintf(&tmp, "Tethering services %s",
Pierre Imai1cfa5432016-02-24 18:00:03 +0900582 (gCtls->tetherCtrl.isTetheringStarted() ? "started" : "stopped"));
San Mehat9d10b342010-01-18 09:51:02 -0800583 cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
584 free(tmp);
San Mehatd1830422010-01-15 08:02:39 -0800585 return 0;
JP Abgrall36971a62013-03-18 13:04:17 -0700586 } else if (argc == 3) {
587 if (!strcmp(argv[1], "interface") && !strcmp(argv[2], "list")) {
Pierre Imai1cfa5432016-02-24 18:00:03 +0900588 InterfaceCollection *ilist = gCtls->tetherCtrl.getTetheredInterfaceList();
JP Abgrall36971a62013-03-18 13:04:17 -0700589 InterfaceCollection::iterator it;
590 for (it = ilist->begin(); it != ilist->end(); ++it) {
591 cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false);
592 }
593 } else if (!strcmp(argv[1], "dns") && !strcmp(argv[2], "list")) {
Lorenzo Colitti667c4772014-08-26 14:13:07 -0700594 char netIdStr[UINT32_STRLEN];
Pierre Imai1cfa5432016-02-24 18:00:03 +0900595 snprintf(netIdStr, sizeof(netIdStr), "%u", gCtls->tetherCtrl.getDnsNetId());
Lorenzo Colitti667c4772014-08-26 14:13:07 -0700596 cli->sendMsg(ResponseCode::TetherDnsFwdNetIdResult, netIdStr, false);
597
Pierre Imai1cfa5432016-02-24 18:00:03 +0900598 for (const auto &fwdr : *(gCtls->tetherCtrl.getDnsForwarders())) {
Erik Klinef90a8b92015-11-13 16:26:27 +0900599 cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, fwdr.c_str(), false);
JP Abgrall36971a62013-03-18 13:04:17 -0700600 }
JP Abgrall20f95ed2013-03-15 20:11:56 -0700601 }
San Mehat9d10b342010-01-18 09:51:02 -0800602 } else {
603 /*
604 * These commands take a minimum of 4 arguments
605 */
606 if (argc < 4) {
607 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
608 return 0;
609 }
610
611 if (!strcmp(argv[1], "start")) {
Robert Greenwalt3208ea02010-03-24 16:32:55 -0700612 if (argc % 2 == 1) {
613 cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false);
614 return 0;
615 }
San Mehat9d10b342010-01-18 09:51:02 -0800616
Erik Kline13fa01f2015-11-12 17:49:23 +0900617 const int num_addrs = argc - 2;
618 // TODO: consider moving this validation into TetherController.
619 struct in_addr tmp_addr;
620 for (int arg_index = 2; arg_index < argc; arg_index++) {
621 if (!inet_aton(argv[arg_index], &tmp_addr)) {
Robert Greenwalt3208ea02010-03-24 16:32:55 -0700622 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
Robert Greenwalt3208ea02010-03-24 16:32:55 -0700623 return 0;
624 }
San Mehat9d10b342010-01-18 09:51:02 -0800625 }
Erik Kline13fa01f2015-11-12 17:49:23 +0900626
Pierre Imai1cfa5432016-02-24 18:00:03 +0900627 rc = gCtls->tetherCtrl.startTethering(num_addrs, &(argv[2]));
San Mehat9d10b342010-01-18 09:51:02 -0800628 } else if (!strcmp(argv[1], "interface")) {
629 if (!strcmp(argv[2], "add")) {
Pierre Imai1cfa5432016-02-24 18:00:03 +0900630 rc = gCtls->tetherCtrl.tetherInterface(argv[3]);
San Mehat9d10b342010-01-18 09:51:02 -0800631 } else if (!strcmp(argv[2], "remove")) {
Pierre Imai1cfa5432016-02-24 18:00:03 +0900632 rc = gCtls->tetherCtrl.untetherInterface(argv[3]);
JP Abgrall20f95ed2013-03-15 20:11:56 -0700633 /* else if (!strcmp(argv[2], "list")) handled above */
San Mehat9d10b342010-01-18 09:51:02 -0800634 } else {
635 cli->sendMsg(ResponseCode::CommandParameterError,
636 "Unknown tether interface operation", false);
637 return 0;
638 }
639 } else if (!strcmp(argv[1], "dns")) {
640 if (!strcmp(argv[2], "set")) {
Lorenzo Colitti667c4772014-08-26 14:13:07 -0700641 if (argc < 5) {
642 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
643 return 0;
644 }
645 unsigned netId = stringToNetId(argv[3]);
Pierre Imai1cfa5432016-02-24 18:00:03 +0900646 rc = gCtls->tetherCtrl.setDnsForwarders(netId, &argv[4], argc - 4);
JP Abgrall36971a62013-03-18 13:04:17 -0700647 /* else if (!strcmp(argv[2], "list")) handled above */
San Mehat9d10b342010-01-18 09:51:02 -0800648 } else {
649 cli->sendMsg(ResponseCode::CommandParameterError,
650 "Unknown tether interface operation", false);
651 return 0;
652 }
653 } else {
654 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
655 return 0;
656 }
657 }
658
659 if (!rc) {
660 cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
661 } else {
662 cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
San Mehatd1830422010-01-15 08:02:39 -0800663 }
664
665 return 0;
666}
667
668CommandListener::NatCmd::NatCmd() :
669 NetdCommand("nat") {
670}
671
672int CommandListener::NatCmd::runCommand(SocketClient *cli,
673 int argc, char **argv) {
San Mehat9d10b342010-01-18 09:51:02 -0800674 int rc = 0;
675
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700676 if (argc < 5) {
San Mehat9d10b342010-01-18 09:51:02 -0800677 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
678 return 0;
679 }
680
Sreeram Ramachandran87475a12014-07-15 16:20:28 -0700681 // 0 1 2 3
682 // nat enable intiface extiface
683 // nat disable intiface extiface
684 if (!strcmp(argv[1], "enable") && argc >= 4) {
Pierre Imai1cfa5432016-02-24 18:00:03 +0900685 rc = gCtls->natCtrl.enableNat(argv[2], argv[3]);
JP Abgrallc6c67342011-10-07 16:28:54 -0700686 if(!rc) {
Devi Sandeep Endluri V V893c1222016-04-27 22:31:19 +0530687 natStarted(argv[2], argv[3]);
JP Abgrallc6c67342011-10-07 16:28:54 -0700688 /* Ignore ifaces for now. */
Pierre Imai1cfa5432016-02-24 18:00:03 +0900689 rc = gCtls->bandwidthCtrl.setGlobalAlertInForwardChain();
JP Abgrallc6c67342011-10-07 16:28:54 -0700690 }
Sreeram Ramachandran87475a12014-07-15 16:20:28 -0700691 } else if (!strcmp(argv[1], "disable") && argc >= 4) {
Robert Greenwaltf7bf29c2011-11-01 22:07:28 -0700692 /* Ignore ifaces for now. */
Devi Sandeep Endluri V V893c1222016-04-27 22:31:19 +0530693 natStopped(argv[2], argv[3]);
Pierre Imai1cfa5432016-02-24 18:00:03 +0900694 rc = gCtls->bandwidthCtrl.removeGlobalAlertInForwardChain();
695 rc |= gCtls->natCtrl.disableNat(argv[2], argv[3]);
San Mehat9d10b342010-01-18 09:51:02 -0800696 } else {
697 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
698 return 0;
699 }
700
701 if (!rc) {
702 cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
703 } else {
704 cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
705 }
San Mehatd1830422010-01-15 08:02:39 -0800706
707 return 0;
708}
709
San Mehatd5573d32010-01-19 17:19:41 -0800710CommandListener::PppdCmd::PppdCmd() :
711 NetdCommand("pppd") {
712}
713
714int CommandListener::PppdCmd::runCommand(SocketClient *cli,
715 int argc, char **argv) {
716 int rc = 0;
717
718 if (argc < 3) {
719 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
720 return 0;
721 }
722
723 if (!strcmp(argv[1], "attach")) {
Robert Greenwalt74d8fdd2010-02-01 10:02:28 -0800724 struct in_addr l, r, dns1, dns2;
725
Wang Liyong1c4a7792013-07-18 16:37:07 +0200726 memset(&dns1, 0, sizeof(struct in_addr));
727 memset(&dns2, 0, sizeof(struct in_addr));
San Mehatd5573d32010-01-19 17:19:41 -0800728
729 if (!inet_aton(argv[3], &l)) {
730 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false);
731 return 0;
732 }
733 if (!inet_aton(argv[4], &r)) {
734 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false);
735 return 0;
736 }
Robert Greenwalt74d8fdd2010-02-01 10:02:28 -0800737 if ((argc > 3) && (!inet_aton(argv[5], &dns1))) {
738 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false);
739 return 0;
740 }
741 if ((argc > 4) && (!inet_aton(argv[6], &dns2))) {
742 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false);
743 return 0;
744 }
Pierre Imai1cfa5432016-02-24 18:00:03 +0900745 rc = gCtls->pppCtrl.attachPppd(argv[2], l, r, dns1, dns2);
San Mehatd5573d32010-01-19 17:19:41 -0800746 } else if (!strcmp(argv[1], "detach")) {
Pierre Imai1cfa5432016-02-24 18:00:03 +0900747 rc = gCtls->pppCtrl.detachPppd(argv[2]);
San Mehatd5573d32010-01-19 17:19:41 -0800748 } else {
749 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false);
750 return 0;
751 }
752
753 if (!rc) {
754 cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false);
755 } else {
756 cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true);
757 }
758
759 return 0;
760}
San Mehat1bdac9e2010-01-21 14:03:06 -0800761
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800762CommandListener::SoftapCmd::SoftapCmd() :
763 NetdCommand("softap") {
764}
765
766int CommandListener::SoftapCmd::runCommand(SocketClient *cli,
767 int argc, char **argv) {
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800768 int rc = ResponseCode::SoftapStatusResult;
Dmitry Shmidt666fe252011-03-08 11:01:58 -0800769 char *retbuf = NULL;
c_rrajiv9400fcf2014-07-18 18:50:37 -0700770#ifdef QSAP_WLAN
771 char qccmd = 0;
772#endif
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800773
Pierre Imai1cfa5432016-02-24 18:00:03 +0900774 if (gCtls == nullptr) {
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800775 cli->sendMsg(ResponseCode::ServiceStartFailed, "SoftAP is not available", false);
776 return -1;
777 }
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800778 if (argc < 2) {
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800779 cli->sendMsg(ResponseCode::CommandSyntaxError,
780 "Missing argument in a SoftAP command", false);
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800781 return 0;
782 }
783
c_rrajiv9400fcf2014-07-18 18:50:37 -0700784#ifdef QSAP_WLAN
785
786 if (!strcmp(argv[1], "qccmd")) {
787 rc = qsap_hostd_exec(argc, argv);
788 qccmd = 1;
789 }
790 else if (!strcmp(argv[1], "startap")) {
Dedy Lansky56adaf42015-09-06 14:27:22 +0300791 rc = qsap_prepare_softap();
792 if (!rc) {
793 rc = gCtls->softapCtrl.startSoftap(qsap_is_fst_enabled());
794 if (rc != ResponseCode::SoftapStatusResult) {
795 ALOGE("failed to start SoftAP ResponseCode : %d", rc);
796 qsap_unprepare_softap();
797 }
798 } else {
799 ALOGE("qsap_prepare_softap failed");
800 rc = ResponseCode::ServiceStartFailed;
801 }
802 } else if (!strcmp(argv[1], "stopap")) {
803 rc = gCtls->softapCtrl.stopSoftap();
804 qsap_unprepare_softap();
c_rrajiv9400fcf2014-07-18 18:50:37 -0700805#else
Irfan Sheriff7e9eb7b2012-06-15 16:11:31 -0700806 if (!strcmp(argv[1], "startap")) {
Pierre Imai1cfa5432016-02-24 18:00:03 +0900807 rc = gCtls->softapCtrl.startSoftap();
Dmitry Shmidtc3539e22010-03-12 14:16:46 -0800808 } else if (!strcmp(argv[1], "stopap")) {
Pierre Imai1cfa5432016-02-24 18:00:03 +0900809 rc = gCtls->softapCtrl.stopSoftap();
Dedy Lansky56adaf42015-09-06 14:27:22 +0300810#endif
Dmitry Shmidt31fd6c52010-03-12 10:01:58 -0800811 } else if (!strcmp(argv[1], "fwreload")) {
Pierre Imai1cfa5432016-02-24 18:00:03 +0900812 rc = gCtls->softapCtrl.fwReloadSoftap(argc, argv);
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800813 } else if (!strcmp(argv[1], "status")) {
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800814 asprintf(&retbuf, "Softap service %s running",
Pierre Imai1cfa5432016-02-24 18:00:03 +0900815 (gCtls->softapCtrl.isSoftapStarted() ? "is" : "is not"));
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800816 cli->sendMsg(rc, retbuf, false);
Dmitry Shmidt666fe252011-03-08 11:01:58 -0800817 free(retbuf);
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800818 return 0;
819 } else if (!strcmp(argv[1], "set")) {
c_rrajiv9400fcf2014-07-18 18:50:37 -0700820#ifdef QSAP_WLAN
821 rc = qsapsetSoftap(argc, argv);
822 qccmd = 1;
823#else
Pierre Imai1cfa5432016-02-24 18:00:03 +0900824 rc = gCtls->softapCtrl.setSoftap(argc, argv);
c_rrajiv9400fcf2014-07-18 18:50:37 -0700825#endif
Nalla Kartheek5d459fb2016-05-19 13:48:41 +0530826#ifdef QSAP_WLAN
827 } else if (!strcmp(argv[1], "create")) {
828 if (argv[2]) {
829 ALOGD("Override softap create command");
830 rc = qsap_add_or_remove_interface(argv[2], 1);
831 }
832 } else if (!strcmp(argv[1], "remove")) {
833 if (argv[2]) {
834 ALOGD("Override softap remove command");
835 rc = qsap_add_or_remove_interface(argv[2], 0);
836 }
837#endif
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800838 } else {
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800839 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unrecognized SoftAP command", false);
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800840 return 0;
841 }
842
c_rrajiv9400fcf2014-07-18 18:50:37 -0700843#ifdef QSAP_WLAN
844 if (qccmd) {
845 if (!rc) {
846 cli->sendMsg(ResponseCode::CommandOkay, "Softap operation succeeded", false);
847 } else {
848 cli->sendMsg(ResponseCode::OperationFailed, "Softap operation failed", true);
849 }
850 return 0;
851 }
852#endif
853
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800854 if (rc >= 400 && rc < 600)
855 cli->sendMsg(rc, "SoftAP command has failed", false);
856 else
857 cli->sendMsg(rc, "Ok", false);
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800858
859 return 0;
860}
Robert Greenwalt3e6ba3c2010-02-18 10:54:08 -0800861
Mattias Falk89c1e972011-04-29 14:48:51 +0200862CommandListener::ResolverCmd::ResolverCmd() :
863 NetdCommand("resolver") {
864}
865
Sasha Levitskiy938ab2a2013-02-27 16:29:43 -0800866int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **margv) {
Mattias Falk89c1e972011-04-29 14:48:51 +0200867 int rc = 0;
Sasha Levitskiy938ab2a2013-02-27 16:29:43 -0800868 const char **argv = const_cast<const char **>(margv);
Mattias Falk89c1e972011-04-29 14:48:51 +0200869
Erik Kline9adc9f32015-01-20 13:36:05 +0900870 if (argc < 3) {
Mattias Falk89c1e972011-04-29 14:48:51 +0200871 cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false);
872 return 0;
873 }
874
Erik Kline9adc9f32015-01-20 13:36:05 +0900875 unsigned netId = stringToNetId(argv[2]);
876 // TODO: Consider making NetworkController.isValidNetwork() public
877 // and making that check here.
878
Paul Jensen35c77e32014-04-10 14:57:54 -0400879 if (!strcmp(argv[1], "setnetdns")) {
Pierre Imai95f5f942016-03-09 18:09:25 +0900880 if (!parseAndExecuteSetNetDns(netId, argc, argv)) {
Mattias Falk89c1e972011-04-29 14:48:51 +0200881 cli->sendMsg(ResponseCode::CommandSyntaxError,
Pierre Imai95f5f942016-03-09 18:09:25 +0900882 "Wrong number of or invalid arguments to resolver setnetdns", false);
Mattias Falk89c1e972011-04-29 14:48:51 +0200883 return 0;
884 }
Lorenzo Colittidadc5f82014-11-29 13:54:25 +0900885 } else if (!strcmp(argv[1], "clearnetdns")) { // "resolver clearnetdns <netId>"
886 if (argc == 3) {
Pierre Imai1cfa5432016-02-24 18:00:03 +0900887 rc = gCtls->resolverCtrl.clearDnsServers(netId);
Lorenzo Colittidadc5f82014-11-29 13:54:25 +0900888 } else {
889 cli->sendMsg(ResponseCode::CommandSyntaxError,
890 "Wrong number of arguments to resolver clearnetdns", false);
891 return 0;
892 }
Mattias Falk89c1e972011-04-29 14:48:51 +0200893 } else {
894 cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false);
895 return 0;
896 }
897
898 if (!rc) {
899 cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false);
900 } else {
901 cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true);
902 }
903
904 return 0;
905}
906
Pierre Imai95f5f942016-03-09 18:09:25 +0900907bool CommandListener::ResolverCmd::parseAndExecuteSetNetDns(int netId, int argc,
908 const char** argv) {
909 // "resolver setnetdns <netId> <domains> <dns1> [<dns2> ...] [--params <params>]"
910 // TODO: This code has to be replaced by a Binder call ASAP
911 if (argc < 5) {
912 return false;
913 }
914 int end = argc;
915 __res_params params;
916 const __res_params* paramsPtr = nullptr;
917 if (end > 6 && !strcmp(argv[end - 2], "--params")) {
918 const char* paramsStr = argv[end - 1];
919 end -= 2;
920 if (sscanf(paramsStr, "%hu %hhu %hhu %hhu", &params.sample_validity,
921 &params.success_threshold, &params.min_samples, &params.max_samples) != 4) {
922 return false;
923 }
924 paramsPtr = &params;
925 }
926 return gCtls->resolverCtrl.setDnsServers(netId, argv[3], &argv[4], end - 4, paramsPtr) == 0;
927}
928
JP Abgrall4a5f5ca2011-06-15 18:37:39 -0700929CommandListener::BandwidthControlCmd::BandwidthControlCmd() :
JP Abgrall0dad7c22011-06-24 11:58:14 -0700930 NetdCommand("bandwidth") {
JP Abgrall4a5f5ca2011-06-15 18:37:39 -0700931}
932
JP Abgralldb7da582011-09-18 12:57:32 -0700933void CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) {
934 char *msg;
935 asprintf(&msg, "Usage: bandwidth %s", usageMsg);
936 cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false);
937 free(msg);
938}
939
940void CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) {
941 if (!cond) {
942 cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
943 } else {
944 cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false);
945 }
946}
947
948void CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) {
949 cli->sendMsg(ResponseCode::OperationFailed, errMsg, false);
950}
951
JP Abgrallfa6f46d2011-06-17 23:17:28 -0700952int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
JP Abgrall4a5f5ca2011-06-15 18:37:39 -0700953 if (argc < 2) {
JP Abgralldb7da582011-09-18 12:57:32 -0700954 sendGenericSyntaxError(cli, "<cmds> <args...>");
JP Abgrall4a5f5ca2011-06-15 18:37:39 -0700955 return 0;
956 }
957
Steve Block3fb42e02011-10-20 11:55:56 +0100958 ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
JP Abgrall0dad7c22011-06-24 11:58:14 -0700959
JP Abgralldb7da582011-09-18 12:57:32 -0700960 if (!strcmp(argv[1], "enable")) {
Pierre Imai1cfa5432016-02-24 18:00:03 +0900961 int rc = gCtls->bandwidthCtrl.enableBandwidthControl(true);
JP Abgralldb7da582011-09-18 12:57:32 -0700962 sendGenericOkFail(cli, rc);
963 return 0;
964
965 }
966 if (!strcmp(argv[1], "disable")) {
Pierre Imai1cfa5432016-02-24 18:00:03 +0900967 int rc = gCtls->bandwidthCtrl.disableBandwidthControl();
JP Abgralldb7da582011-09-18 12:57:32 -0700968 sendGenericOkFail(cli, rc);
969 return 0;
970
971 }
972 if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
JP Abgrallfa6f46d2011-06-17 23:17:28 -0700973 if (argc != 3) {
JP Abgralldb7da582011-09-18 12:57:32 -0700974 sendGenericSyntaxError(cli, "removequota <interface>");
JP Abgrall4a5f5ca2011-06-15 18:37:39 -0700975 return 0;
JP Abgrallfa6f46d2011-06-17 23:17:28 -0700976 }
Pierre Imai1cfa5432016-02-24 18:00:03 +0900977 int rc = gCtls->bandwidthCtrl.removeInterfaceSharedQuota(argv[2]);
JP Abgralldb7da582011-09-18 12:57:32 -0700978 sendGenericOkFail(cli, rc);
979 return 0;
JP Abgrallfa6f46d2011-06-17 23:17:28 -0700980
JP Abgralldb7da582011-09-18 12:57:32 -0700981 }
982 if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) {
JP Abgrall8a932722011-07-13 19:17:35 -0700983 int64_t bytes;
984 if (argc != 2) {
JP Abgralldb7da582011-09-18 12:57:32 -0700985 sendGenericSyntaxError(cli, "getquota");
JP Abgrall8a932722011-07-13 19:17:35 -0700986 return 0;
987 }
Pierre Imai1cfa5432016-02-24 18:00:03 +0900988 int rc = gCtls->bandwidthCtrl.getInterfaceSharedQuota(&bytes);
JP Abgrall8a932722011-07-13 19:17:35 -0700989 if (rc) {
JP Abgralldb7da582011-09-18 12:57:32 -0700990 sendGenericOpFailed(cli, "Failed to get quota");
JP Abgrall8a932722011-07-13 19:17:35 -0700991 return 0;
992 }
JP Abgralldb7da582011-09-18 12:57:32 -0700993
JP Abgrall8a932722011-07-13 19:17:35 -0700994 char *msg;
SynergyDev7776cea2014-03-16 15:48:51 -0700995 asprintf(&msg, "%" PRId64, bytes);
JP Abgrall8a932722011-07-13 19:17:35 -0700996 cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
997 free(msg);
JP Abgralldb7da582011-09-18 12:57:32 -0700998 return 0;
JP Abgrall8a932722011-07-13 19:17:35 -0700999
JP Abgralldb7da582011-09-18 12:57:32 -07001000 }
1001 if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) {
JP Abgrall8a932722011-07-13 19:17:35 -07001002 int64_t bytes;
1003 if (argc != 3) {
JP Abgralldb7da582011-09-18 12:57:32 -07001004 sendGenericSyntaxError(cli, "getiquota <iface>");
JP Abgrall8a932722011-07-13 19:17:35 -07001005 return 0;
1006 }
JP Abgralldb7da582011-09-18 12:57:32 -07001007
Pierre Imai1cfa5432016-02-24 18:00:03 +09001008 int rc = gCtls->bandwidthCtrl.getInterfaceQuota(argv[2], &bytes);
JP Abgrall8a932722011-07-13 19:17:35 -07001009 if (rc) {
JP Abgralldb7da582011-09-18 12:57:32 -07001010 sendGenericOpFailed(cli, "Failed to get quota");
JP Abgrall8a932722011-07-13 19:17:35 -07001011 return 0;
1012 }
1013 char *msg;
SynergyDev7776cea2014-03-16 15:48:51 -07001014 asprintf(&msg, "%" PRId64, bytes);
JP Abgrall8a932722011-07-13 19:17:35 -07001015 cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
1016 free(msg);
JP Abgralldb7da582011-09-18 12:57:32 -07001017 return 0;
JP Abgrall8a932722011-07-13 19:17:35 -07001018
JP Abgralldb7da582011-09-18 12:57:32 -07001019 }
1020 if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
JP Abgrallfa6f46d2011-06-17 23:17:28 -07001021 if (argc != 4) {
JP Abgralldb7da582011-09-18 12:57:32 -07001022 sendGenericSyntaxError(cli, "setquota <interface> <bytes>");
JP Abgrallfa6f46d2011-06-17 23:17:28 -07001023 return 0;
1024 }
Pierre Imai1cfa5432016-02-24 18:00:03 +09001025 int rc = gCtls->bandwidthCtrl.setInterfaceSharedQuota(argv[2], atoll(argv[3]));
JP Abgralldb7da582011-09-18 12:57:32 -07001026 sendGenericOkFail(cli, rc);
1027 return 0;
1028 }
1029 if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
1030 int rc;
JP Abgrallfa6f46d2011-06-17 23:17:28 -07001031 if (argc < 4) {
JP Abgralldb7da582011-09-18 12:57:32 -07001032 sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ...");
JP Abgrallfa6f46d2011-06-17 23:17:28 -07001033 return 0;
1034 }
JP Abgralldb7da582011-09-18 12:57:32 -07001035
JP Abgrall8a932722011-07-13 19:17:35 -07001036 for (int q = 3; argc >= 4; q++, argc--) {
Pierre Imai1cfa5432016-02-24 18:00:03 +09001037 rc = gCtls->bandwidthCtrl.setInterfaceSharedQuota(argv[q], atoll(argv[2]));
JP Abgrall0dad7c22011-06-24 11:58:14 -07001038 if (rc) {
1039 char *msg;
1040 asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]);
1041 cli->sendMsg(ResponseCode::OperationFailed,
1042 msg, false);
1043 free(msg);
JP Abgralldb7da582011-09-18 12:57:32 -07001044 return 0;
JP Abgrall0dad7c22011-06-24 11:58:14 -07001045 }
1046 }
JP Abgralldb7da582011-09-18 12:57:32 -07001047 sendGenericOkFail(cli, rc);
1048 return 0;
JP Abgrall0dad7c22011-06-24 11:58:14 -07001049
JP Abgralldb7da582011-09-18 12:57:32 -07001050 }
1051 if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) {
1052 int rc;
JP Abgrall0dad7c22011-06-24 11:58:14 -07001053 if (argc < 3) {
JP Abgralldb7da582011-09-18 12:57:32 -07001054 sendGenericSyntaxError(cli, "removequotas <interface> ...");
JP Abgrall0dad7c22011-06-24 11:58:14 -07001055 return 0;
1056 }
JP Abgralldb7da582011-09-18 12:57:32 -07001057
JP Abgrall8a932722011-07-13 19:17:35 -07001058 for (int q = 2; argc >= 3; q++, argc--) {
Pierre Imai1cfa5432016-02-24 18:00:03 +09001059 rc = gCtls->bandwidthCtrl.removeInterfaceSharedQuota(argv[q]);
JP Abgrall0dad7c22011-06-24 11:58:14 -07001060 if (rc) {
1061 char *msg;
1062 asprintf(&msg, "bandwidth removequotas %s failed", argv[q]);
1063 cli->sendMsg(ResponseCode::OperationFailed,
1064 msg, false);
1065 free(msg);
JP Abgralldb7da582011-09-18 12:57:32 -07001066 return 0;
JP Abgrall0dad7c22011-06-24 11:58:14 -07001067 }
1068 }
JP Abgralldb7da582011-09-18 12:57:32 -07001069 sendGenericOkFail(cli, rc);
JP Abgrallfa6f46d2011-06-17 23:17:28 -07001070 return 0;
JP Abgralldb7da582011-09-18 12:57:32 -07001071
1072 }
1073 if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
1074 if (argc != 3) {
1075 sendGenericSyntaxError(cli, "removeiquota <interface>");
1076 return 0;
1077 }
Pierre Imai1cfa5432016-02-24 18:00:03 +09001078 int rc = gCtls->bandwidthCtrl.removeInterfaceQuota(argv[2]);
JP Abgralldb7da582011-09-18 12:57:32 -07001079 sendGenericOkFail(cli, rc);
1080 return 0;
1081
1082 }
1083 if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
1084 if (argc != 4) {
1085 sendGenericSyntaxError(cli, "setiquota <interface> <bytes>");
1086 return 0;
1087 }
Pierre Imai1cfa5432016-02-24 18:00:03 +09001088 int rc = gCtls->bandwidthCtrl.setInterfaceQuota(argv[2], atoll(argv[3]));
JP Abgralldb7da582011-09-18 12:57:32 -07001089 sendGenericOkFail(cli, rc);
1090 return 0;
1091
1092 }
1093 if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
1094 if (argc < 3) {
1095 sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ...");
1096 return 0;
1097 }
Pierre Imai1cfa5432016-02-24 18:00:03 +09001098 int rc = gCtls->bandwidthCtrl.addNaughtyApps(argc - 2, argv + 2);
JP Abgralldb7da582011-09-18 12:57:32 -07001099 sendGenericOkFail(cli, rc);
1100 return 0;
1101
1102
1103 }
1104 if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
1105 if (argc < 3) {
1106 sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ...");
1107 return 0;
1108 }
Pierre Imai1cfa5432016-02-24 18:00:03 +09001109 int rc = gCtls->bandwidthCtrl.removeNaughtyApps(argc - 2, argv + 2);
JP Abgralldb7da582011-09-18 12:57:32 -07001110 sendGenericOkFail(cli, rc);
1111 return 0;
JP Abgralle4788732013-07-02 20:28:45 -07001112 }
JP Abgralle4788732013-07-02 20:28:45 -07001113 if (!strcmp(argv[1], "addniceapps") || !strcmp(argv[1], "aha")) {
1114 if (argc < 3) {
1115 sendGenericSyntaxError(cli, "addniceapps <appUid> ...");
1116 return 0;
1117 }
Pierre Imai1cfa5432016-02-24 18:00:03 +09001118 int rc = gCtls->bandwidthCtrl.addNiceApps(argc - 2, argv + 2);
JP Abgralle4788732013-07-02 20:28:45 -07001119 sendGenericOkFail(cli, rc);
1120 return 0;
1121 }
1122 if (!strcmp(argv[1], "removeniceapps") || !strcmp(argv[1], "rha")) {
1123 if (argc < 3) {
1124 sendGenericSyntaxError(cli, "removeniceapps <appUid> ...");
1125 return 0;
1126 }
Pierre Imai1cfa5432016-02-24 18:00:03 +09001127 int rc = gCtls->bandwidthCtrl.removeNiceApps(argc - 2, argv + 2);
JP Abgralle4788732013-07-02 20:28:45 -07001128 sendGenericOkFail(cli, rc);
1129 return 0;
JP Abgralldb7da582011-09-18 12:57:32 -07001130 }
1131 if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) {
1132 if (argc != 3) {
1133 sendGenericSyntaxError(cli, "setglobalalert <bytes>");
1134 return 0;
1135 }
Pierre Imai1cfa5432016-02-24 18:00:03 +09001136 int rc = gCtls->bandwidthCtrl.setGlobalAlert(atoll(argv[2]));
JP Abgralldb7da582011-09-18 12:57:32 -07001137 sendGenericOkFail(cli, rc);
1138 return 0;
JP Abgralldb7da582011-09-18 12:57:32 -07001139 }
JP Abgrallc6c67342011-10-07 16:28:54 -07001140 if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) {
1141 if (argc != 4) {
1142 sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>");
1143 return 0;
1144 }
1145 /* We ignore the interfaces for now. */
Pierre Imai1cfa5432016-02-24 18:00:03 +09001146 int rc = gCtls->bandwidthCtrl.setGlobalAlertInForwardChain();
JP Abgrallc6c67342011-10-07 16:28:54 -07001147 sendGenericOkFail(cli, rc);
1148 return 0;
1149
1150 }
JP Abgralldb7da582011-09-18 12:57:32 -07001151 if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
1152 if (argc != 2) {
1153 sendGenericSyntaxError(cli, "removeglobalalert");
1154 return 0;
1155 }
Pierre Imai1cfa5432016-02-24 18:00:03 +09001156 int rc = gCtls->bandwidthCtrl.removeGlobalAlert();
JP Abgralldb7da582011-09-18 12:57:32 -07001157 sendGenericOkFail(cli, rc);
1158 return 0;
1159
1160 }
JP Abgrallc6c67342011-10-07 16:28:54 -07001161 if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) {
1162 if (argc != 4) {
1163 sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>");
1164 return 0;
1165 }
1166 /* We ignore the interfaces for now. */
Pierre Imai1cfa5432016-02-24 18:00:03 +09001167 int rc = gCtls->bandwidthCtrl.removeGlobalAlertInForwardChain();
JP Abgrallc6c67342011-10-07 16:28:54 -07001168 sendGenericOkFail(cli, rc);
1169 return 0;
1170
1171 }
JP Abgralldb7da582011-09-18 12:57:32 -07001172 if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
1173 if (argc != 3) {
1174 sendGenericSyntaxError(cli, "setsharedalert <bytes>");
1175 return 0;
1176 }
Pierre Imai1cfa5432016-02-24 18:00:03 +09001177 int rc = gCtls->bandwidthCtrl.setSharedAlert(atoll(argv[2]));
JP Abgralldb7da582011-09-18 12:57:32 -07001178 sendGenericOkFail(cli, rc);
1179 return 0;
1180
1181 }
1182 if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) {
1183 if (argc != 2) {
1184 sendGenericSyntaxError(cli, "removesharedalert");
1185 return 0;
1186 }
Pierre Imai1cfa5432016-02-24 18:00:03 +09001187 int rc = gCtls->bandwidthCtrl.removeSharedAlert();
JP Abgralldb7da582011-09-18 12:57:32 -07001188 sendGenericOkFail(cli, rc);
1189 return 0;
1190
1191 }
1192 if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) {
1193 if (argc != 4) {
1194 sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>");
1195 return 0;
1196 }
Pierre Imai1cfa5432016-02-24 18:00:03 +09001197 int rc = gCtls->bandwidthCtrl.setInterfaceAlert(argv[2], atoll(argv[3]));
JP Abgralldb7da582011-09-18 12:57:32 -07001198 sendGenericOkFail(cli, rc);
1199 return 0;
1200
1201 }
1202 if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) {
1203 if (argc != 3) {
1204 sendGenericSyntaxError(cli, "removeinterfacealert <interface>");
1205 return 0;
1206 }
Pierre Imai1cfa5432016-02-24 18:00:03 +09001207 int rc = gCtls->bandwidthCtrl.removeInterfaceAlert(argv[2]);
JP Abgralldb7da582011-09-18 12:57:32 -07001208 sendGenericOkFail(cli, rc);
1209 return 0;
1210
1211 }
1212 if (!strcmp(argv[1], "gettetherstats") || !strcmp(argv[1], "gts")) {
1213 BandwidthController::TetherStats tetherStats;
JP Abgralla2a64f02011-11-11 20:36:16 -08001214 std::string extraProcessingInfo = "";
JP Abgrallbaeccc42013-06-25 09:44:10 -07001215 if (argc < 2 || argc > 4) {
1216 sendGenericSyntaxError(cli, "gettetherstats [<intInterface> <extInterface>]");
JP Abgralldb7da582011-09-18 12:57:32 -07001217 return 0;
1218 }
JP Abgrallbaeccc42013-06-25 09:44:10 -07001219 tetherStats.intIface = argc > 2 ? argv[2] : "";
1220 tetherStats.extIface = argc > 3 ? argv[3] : "";
JP Abgrallf3cc83f2013-09-11 20:01:59 -07001221 // No filtering requested and there are no interface pairs to lookup.
Pierre Imai1cfa5432016-02-24 18:00:03 +09001222 if (argc <= 2 && gCtls->natCtrl.ifacePairList.empty()) {
JP Abgrallf3cc83f2013-09-11 20:01:59 -07001223 cli->sendMsg(ResponseCode::CommandOkay, "Tethering stats list completed", false);
1224 return 0;
1225 }
Pierre Imai1cfa5432016-02-24 18:00:03 +09001226 int rc = gCtls->bandwidthCtrl.getTetherStats(cli, tetherStats, extraProcessingInfo);
JP Abgralldb7da582011-09-18 12:57:32 -07001227 if (rc) {
JP Abgralla2a64f02011-11-11 20:36:16 -08001228 extraProcessingInfo.insert(0, "Failed to get tethering stats.\n");
1229 sendGenericOpFailed(cli, extraProcessingInfo.c_str());
JP Abgrallbaeccc42013-06-25 09:44:10 -07001230 return 0;
JP Abgralldb7da582011-09-18 12:57:32 -07001231 }
JP Abgralldb7da582011-09-18 12:57:32 -07001232 return 0;
1233
JP Abgrall4a5f5ca2011-06-15 18:37:39 -07001234 }
Manjunatha Prabhu163228f2016-06-27 14:37:54 +05301235 if (!strcmp(argv[1], "blockAllData")) {
1236 if (argc < 2) {
1237 sendGenericSyntaxError(cli, "zerobalanceblock");
1238 return 0;
1239 }
1240 int rc = blockAllData();
1241 sendGenericOkFail(cli, rc);
1242 return 0;
1243 }
1244 if (!strcmp(argv[1], "unblockAllData")) {
1245 if (argc < 2) {
1246 sendGenericSyntaxError(cli, "zerobalance unblock");
1247 return 0;
1248 }
1249 int rc = unblockAllData();
1250 sendGenericOkFail(cli, rc);
1251 return 0;
1252 }
JP Abgrall4a5f5ca2011-06-15 18:37:39 -07001253
JP Abgralldb7da582011-09-18 12:57:32 -07001254 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
JP Abgrall4a5f5ca2011-06-15 18:37:39 -07001255 return 0;
1256}
JP Abgrall0031cea2012-04-17 16:38:23 -07001257
1258CommandListener::IdletimerControlCmd::IdletimerControlCmd() :
1259 NetdCommand("idletimer") {
1260}
1261
1262int CommandListener::IdletimerControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
1263 // TODO(ashish): Change the error statements
1264 if (argc < 2) {
1265 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1266 return 0;
1267 }
1268
1269 ALOGV("idletimerctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
1270
1271 if (!strcmp(argv[1], "enable")) {
Pierre Imai1cfa5432016-02-24 18:00:03 +09001272 if (0 != gCtls->idletimerCtrl.enableIdletimerControl()) {
JP Abgrall0031cea2012-04-17 16:38:23 -07001273 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1274 } else {
1275 cli->sendMsg(ResponseCode::CommandOkay, "Enable success", false);
1276 }
1277 return 0;
1278
1279 }
1280 if (!strcmp(argv[1], "disable")) {
Pierre Imai1cfa5432016-02-24 18:00:03 +09001281 if (0 != gCtls->idletimerCtrl.disableIdletimerControl()) {
JP Abgrall0031cea2012-04-17 16:38:23 -07001282 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1283 } else {
1284 cli->sendMsg(ResponseCode::CommandOkay, "Disable success", false);
1285 }
1286 return 0;
1287 }
1288 if (!strcmp(argv[1], "add")) {
Haoyu Bai98f65d32012-06-28 16:16:51 -07001289 if (argc != 5) {
JP Abgrall0031cea2012-04-17 16:38:23 -07001290 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1291 return 0;
1292 }
Pierre Imai1cfa5432016-02-24 18:00:03 +09001293 if(0 != gCtls->idletimerCtrl.addInterfaceIdletimer(
Haoyu Bai98f65d32012-06-28 16:16:51 -07001294 argv[2], atoi(argv[3]), argv[4])) {
JP Abgrall0031cea2012-04-17 16:38:23 -07001295 cli->sendMsg(ResponseCode::OperationFailed, "Failed to add interface", false);
1296 } else {
1297 cli->sendMsg(ResponseCode::CommandOkay, "Add success", false);
1298 }
1299 return 0;
1300 }
1301 if (!strcmp(argv[1], "remove")) {
Haoyu Bai98f65d32012-06-28 16:16:51 -07001302 if (argc != 5) {
JP Abgrall0031cea2012-04-17 16:38:23 -07001303 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1304 return 0;
1305 }
1306 // ashish: fixme timeout
Pierre Imai1cfa5432016-02-24 18:00:03 +09001307 if (0 != gCtls->idletimerCtrl.removeInterfaceIdletimer(
Haoyu Bai98f65d32012-06-28 16:16:51 -07001308 argv[2], atoi(argv[3]), argv[4])) {
JP Abgrall0031cea2012-04-17 16:38:23 -07001309 cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove interface", false);
1310 } else {
1311 cli->sendMsg(ResponseCode::CommandOkay, "Remove success", false);
1312 }
1313 return 0;
1314 }
1315
1316 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown idletimer cmd", false);
1317 return 0;
1318}
Jeff Sharkeyd8c64022012-07-13 18:04:07 -07001319
1320CommandListener::FirewallCmd::FirewallCmd() :
1321 NetdCommand("firewall") {
1322}
1323
1324int CommandListener::FirewallCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1325 if (!cond) {
1326 cli->sendMsg(ResponseCode::CommandOkay, "Firewall command succeeded", false);
1327 } else {
1328 cli->sendMsg(ResponseCode::OperationFailed, "Firewall command failed", false);
1329 }
1330 return 0;
1331}
1332
1333FirewallRule CommandListener::FirewallCmd::parseRule(const char* arg) {
1334 if (!strcmp(arg, "allow")) {
1335 return ALLOW;
Amith Yamasani390e4ea2015-04-25 19:08:57 -07001336 } else if (!strcmp(arg, "deny")) {
Jeff Sharkeyd8c64022012-07-13 18:04:07 -07001337 return DENY;
Amith Yamasani390e4ea2015-04-25 19:08:57 -07001338 } else {
1339 ALOGE("failed to parse uid rule (%s)", arg);
1340 return ALLOW;
1341 }
1342}
1343
1344FirewallType CommandListener::FirewallCmd::parseFirewallType(const char* arg) {
1345 if (!strcmp(arg, "whitelist")) {
1346 return WHITELIST;
1347 } else if (!strcmp(arg, "blacklist")) {
1348 return BLACKLIST;
1349 } else {
1350 ALOGE("failed to parse firewall type (%s)", arg);
1351 return BLACKLIST;
Jeff Sharkeyd8c64022012-07-13 18:04:07 -07001352 }
1353}
1354
Xiaohui Chen1cdfa9a2015-06-08 16:28:12 -07001355ChildChain CommandListener::FirewallCmd::parseChildChain(const char* arg) {
1356 if (!strcmp(arg, "dozable")) {
1357 return DOZABLE;
1358 } else if (!strcmp(arg, "standby")) {
1359 return STANDBY;
Felipe Leme3f624342016-02-10 18:12:39 -08001360 } else if (!strcmp(arg, "powersave")) {
1361 return POWERSAVE;
Xiaohui Chen1cdfa9a2015-06-08 16:28:12 -07001362 } else if (!strcmp(arg, "none")) {
1363 return NONE;
1364 } else {
1365 ALOGE("failed to parse child firewall chain (%s)", arg);
1366 return INVALID_CHAIN;
1367 }
1368}
1369
Jeff Sharkeyd8c64022012-07-13 18:04:07 -07001370int CommandListener::FirewallCmd::runCommand(SocketClient *cli, int argc,
1371 char **argv) {
1372 if (argc < 2) {
1373 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
1374 return 0;
1375 }
1376
1377 if (!strcmp(argv[1], "enable")) {
Amith Yamasani390e4ea2015-04-25 19:08:57 -07001378 if (argc != 3) {
1379 cli->sendMsg(ResponseCode::CommandSyntaxError,
1380 "Usage: firewall enable <whitelist|blacklist>", false);
1381 return 0;
1382 }
1383 FirewallType firewallType = parseFirewallType(argv[2]);
1384
Pierre Imai1cfa5432016-02-24 18:00:03 +09001385 int res = gCtls->firewallCtrl.enableFirewall(firewallType);
Jeff Sharkeyd8c64022012-07-13 18:04:07 -07001386 return sendGenericOkFail(cli, res);
1387 }
1388 if (!strcmp(argv[1], "disable")) {
Pierre Imai1cfa5432016-02-24 18:00:03 +09001389 int res = gCtls->firewallCtrl.disableFirewall();
Jeff Sharkeyd8c64022012-07-13 18:04:07 -07001390 return sendGenericOkFail(cli, res);
1391 }
1392 if (!strcmp(argv[1], "is_enabled")) {
Pierre Imai1cfa5432016-02-24 18:00:03 +09001393 int res = gCtls->firewallCtrl.isFirewallEnabled();
Jeff Sharkeyd8c64022012-07-13 18:04:07 -07001394 return sendGenericOkFail(cli, res);
1395 }
1396
1397 if (!strcmp(argv[1], "set_interface_rule")) {
1398 if (argc != 4) {
1399 cli->sendMsg(ResponseCode::CommandSyntaxError,
1400 "Usage: firewall set_interface_rule <rmnet0> <allow|deny>", false);
1401 return 0;
1402 }
1403
1404 const char* iface = argv[2];
1405 FirewallRule rule = parseRule(argv[3]);
1406
Pierre Imai1cfa5432016-02-24 18:00:03 +09001407 int res = gCtls->firewallCtrl.setInterfaceRule(iface, rule);
Jeff Sharkeyd8c64022012-07-13 18:04:07 -07001408 return sendGenericOkFail(cli, res);
1409 }
1410
1411 if (!strcmp(argv[1], "set_egress_source_rule")) {
1412 if (argc != 4) {
1413 cli->sendMsg(ResponseCode::CommandSyntaxError,
1414 "Usage: firewall set_egress_source_rule <192.168.0.1> <allow|deny>",
1415 false);
1416 return 0;
1417 }
1418
1419 const char* addr = argv[2];
1420 FirewallRule rule = parseRule(argv[3]);
1421
Pierre Imai1cfa5432016-02-24 18:00:03 +09001422 int res = gCtls->firewallCtrl.setEgressSourceRule(addr, rule);
Jeff Sharkeyd8c64022012-07-13 18:04:07 -07001423 return sendGenericOkFail(cli, res);
1424 }
1425
1426 if (!strcmp(argv[1], "set_egress_dest_rule")) {
1427 if (argc != 5) {
1428 cli->sendMsg(ResponseCode::CommandSyntaxError,
1429 "Usage: firewall set_egress_dest_rule <192.168.0.1> <80> <allow|deny>",
1430 false);
1431 return 0;
1432 }
1433
1434 const char* addr = argv[2];
1435 int port = atoi(argv[3]);
1436 FirewallRule rule = parseRule(argv[4]);
1437
1438 int res = 0;
Pierre Imai1cfa5432016-02-24 18:00:03 +09001439 res |= gCtls->firewallCtrl.setEgressDestRule(addr, PROTOCOL_TCP, port, rule);
1440 res |= gCtls->firewallCtrl.setEgressDestRule(addr, PROTOCOL_UDP, port, rule);
Jeff Sharkeyd8c64022012-07-13 18:04:07 -07001441 return sendGenericOkFail(cli, res);
1442 }
1443
1444 if (!strcmp(argv[1], "set_uid_rule")) {
Xiaohui Chen1cdfa9a2015-06-08 16:28:12 -07001445 if (argc != 5) {
Jeff Sharkeyd8c64022012-07-13 18:04:07 -07001446 cli->sendMsg(ResponseCode::CommandSyntaxError,
Xiaohui Chen1cdfa9a2015-06-08 16:28:12 -07001447 "Usage: firewall set_uid_rule <dozable|standby|none> <1000> <allow|deny>",
Jeff Sharkeyd8c64022012-07-13 18:04:07 -07001448 false);
1449 return 0;
1450 }
1451
Xiaohui Chen1cdfa9a2015-06-08 16:28:12 -07001452 ChildChain childChain = parseChildChain(argv[2]);
1453 if (childChain == INVALID_CHAIN) {
1454 cli->sendMsg(ResponseCode::CommandSyntaxError,
1455 "Invalid chain name. Valid names are: <dozable|standby|none>",
1456 false);
1457 return 0;
1458 }
1459 int uid = atoi(argv[3]);
1460 FirewallRule rule = parseRule(argv[4]);
Pierre Imai1cfa5432016-02-24 18:00:03 +09001461 int res = gCtls->firewallCtrl.setUidRule(childChain, uid, rule);
Xiaohui Chen1cdfa9a2015-06-08 16:28:12 -07001462 return sendGenericOkFail(cli, res);
1463 }
1464
1465 if (!strcmp(argv[1], "enable_chain")) {
1466 if (argc != 3) {
1467 cli->sendMsg(ResponseCode::CommandSyntaxError,
1468 "Usage: firewall enable_chain <dozable|standby>",
1469 false);
1470 return 0;
1471 }
1472
1473 ChildChain childChain = parseChildChain(argv[2]);
Pierre Imai1cfa5432016-02-24 18:00:03 +09001474 int res = gCtls->firewallCtrl.enableChildChains(childChain, true);
Xiaohui Chen1cdfa9a2015-06-08 16:28:12 -07001475 return sendGenericOkFail(cli, res);
1476 }
1477
1478 if (!strcmp(argv[1], "disable_chain")) {
1479 if (argc != 3) {
1480 cli->sendMsg(ResponseCode::CommandSyntaxError,
1481 "Usage: firewall disable_chain <dozable|standby>",
1482 false);
1483 return 0;
1484 }
1485
1486 ChildChain childChain = parseChildChain(argv[2]);
Pierre Imai1cfa5432016-02-24 18:00:03 +09001487 int res = gCtls->firewallCtrl.enableChildChains(childChain, false);
Jeff Sharkeyd8c64022012-07-13 18:04:07 -07001488 return sendGenericOkFail(cli, res);
1489 }
1490
1491 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
1492 return 0;
1493}
Daniel Drown0da73fc2012-06-20 16:51:39 -05001494
1495CommandListener::ClatdCmd::ClatdCmd() : NetdCommand("clatd") {
1496}
1497
1498int CommandListener::ClatdCmd::runCommand(SocketClient *cli, int argc,
1499 char **argv) {
1500 int rc = 0;
Lorenzo Colittiac7fefc2014-10-20 17:14:13 +09001501 if (argc < 3) {
Daniel Drown0da73fc2012-06-20 16:51:39 -05001502 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1503 return 0;
1504 }
1505
Lorenzo Colittiac7fefc2014-10-20 17:14:13 +09001506 if (!strcmp(argv[1], "stop")) {
Pierre Imai1cfa5432016-02-24 18:00:03 +09001507 rc = gCtls->clatdCtrl.stopClatd(argv[2]);
Daniel Drown0da73fc2012-06-20 16:51:39 -05001508 } else if (!strcmp(argv[1], "status")) {
1509 char *tmp = NULL;
Pierre Imai1cfa5432016-02-24 18:00:03 +09001510 asprintf(&tmp, "Clatd status: %s", (gCtls->clatdCtrl.isClatdStarted(argv[2]) ?
Lorenzo Colittiac7fefc2014-10-20 17:14:13 +09001511 "started" : "stopped"));
Daniel Drown0da73fc2012-06-20 16:51:39 -05001512 cli->sendMsg(ResponseCode::ClatdStatusResult, tmp, false);
1513 free(tmp);
1514 return 0;
Lorenzo Colittiac7fefc2014-10-20 17:14:13 +09001515 } else if (!strcmp(argv[1], "start")) {
Pierre Imai1cfa5432016-02-24 18:00:03 +09001516 rc = gCtls->clatdCtrl.startClatd(argv[2]);
Daniel Drown0da73fc2012-06-20 16:51:39 -05001517 } else {
1518 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown clatd cmd", false);
1519 return 0;
1520 }
1521
1522 if (!rc) {
1523 cli->sendMsg(ResponseCode::CommandOkay, "Clatd operation succeeded", false);
1524 } else {
1525 cli->sendMsg(ResponseCode::OperationFailed, "Clatd operation failed", false);
1526 }
1527
1528 return 0;
1529}
Sreeram Ramachandrand736d4b2014-03-26 18:33:47 -07001530
Jeff Sharkeyfbe497f2014-10-28 16:50:07 -07001531CommandListener::StrictCmd::StrictCmd() :
1532 NetdCommand("strict") {
1533}
1534
1535int CommandListener::StrictCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1536 if (!cond) {
1537 cli->sendMsg(ResponseCode::CommandOkay, "Strict command succeeded", false);
1538 } else {
1539 cli->sendMsg(ResponseCode::OperationFailed, "Strict command failed", false);
1540 }
1541 return 0;
1542}
1543
1544StrictPenalty CommandListener::StrictCmd::parsePenalty(const char* arg) {
1545 if (!strcmp(arg, "reject")) {
1546 return REJECT;
1547 } else if (!strcmp(arg, "log")) {
1548 return LOG;
1549 } else if (!strcmp(arg, "accept")) {
1550 return ACCEPT;
1551 } else {
1552 return INVALID;
1553 }
1554}
1555
1556int CommandListener::StrictCmd::runCommand(SocketClient *cli, int argc,
1557 char **argv) {
1558 if (argc < 2) {
1559 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
1560 return 0;
1561 }
1562
1563 if (!strcmp(argv[1], "enable")) {
Pierre Imai1cfa5432016-02-24 18:00:03 +09001564 int res = gCtls->strictCtrl.enableStrict();
Jeff Sharkeyfbe497f2014-10-28 16:50:07 -07001565 return sendGenericOkFail(cli, res);
1566 }
1567 if (!strcmp(argv[1], "disable")) {
Pierre Imai1cfa5432016-02-24 18:00:03 +09001568 int res = gCtls->strictCtrl.disableStrict();
Jeff Sharkeyfbe497f2014-10-28 16:50:07 -07001569 return sendGenericOkFail(cli, res);
1570 }
1571
1572 if (!strcmp(argv[1], "set_uid_cleartext_policy")) {
1573 if (argc != 4) {
1574 cli->sendMsg(ResponseCode::CommandSyntaxError,
1575 "Usage: strict set_uid_cleartext_policy <uid> <accept|log|reject>",
1576 false);
1577 return 0;
1578 }
1579
1580 errno = 0;
1581 unsigned long int uid = strtoul(argv[2], NULL, 0);
1582 if (errno || uid > UID_MAX) {
1583 cli->sendMsg(ResponseCode::CommandSyntaxError, "Invalid UID", false);
1584 return 0;
1585 }
1586
1587 StrictPenalty penalty = parsePenalty(argv[3]);
1588 if (penalty == INVALID) {
1589 cli->sendMsg(ResponseCode::CommandSyntaxError, "Invalid penalty argument", false);
1590 return 0;
1591 }
1592
Pierre Imai1cfa5432016-02-24 18:00:03 +09001593 int res = gCtls->strictCtrl.setUidCleartextPenalty((uid_t) uid, penalty);
Jeff Sharkeyfbe497f2014-10-28 16:50:07 -07001594 return sendGenericOkFail(cli, res);
1595 }
1596
1597 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
1598 return 0;
1599}
1600
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -07001601CommandListener::NetworkCommand::NetworkCommand() : NetdCommand("network") {
Sreeram Ramachandrand736d4b2014-03-26 18:33:47 -07001602}
1603
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -07001604int CommandListener::NetworkCommand::syntaxError(SocketClient* client, const char* message) {
1605 client->sendMsg(ResponseCode::CommandSyntaxError, message, false);
Sreeram Ramachandrand736d4b2014-03-26 18:33:47 -07001606 return 0;
1607}
1608
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -07001609int CommandListener::NetworkCommand::operationError(SocketClient* client, const char* message,
1610 int ret) {
1611 errno = -ret;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -07001612 client->sendMsg(ResponseCode::OperationFailed, message, true);
1613 return 0;
1614}
1615
1616int CommandListener::NetworkCommand::success(SocketClient* client) {
1617 client->sendMsg(ResponseCode::CommandOkay, "success", false);
1618 return 0;
1619}
1620
1621int CommandListener::NetworkCommand::runCommand(SocketClient* client, int argc, char** argv) {
Sreeram Ramachandrand736d4b2014-03-26 18:33:47 -07001622 if (argc < 2) {
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -07001623 return syntaxError(client, "Missing argument");
Sreeram Ramachandrand736d4b2014-03-26 18:33:47 -07001624 }
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -07001625
Lorenzo Colitti4c95a122014-09-18 16:01:50 +09001626 // 0 1 2 3 4 5 6 7 8
1627 // network route [legacy <uid>] add <netId> <interface> <destination> [nexthop]
1628 // network route [legacy <uid>] remove <netId> <interface> <destination> [nexthop]
1629 //
1630 // nexthop may be either an IPv4/IPv6 address or one of "unreachable" or "throw".
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -07001631 if (!strcmp(argv[1], "route")) {
1632 if (argc < 6 || argc > 9) {
1633 return syntaxError(client, "Incorrect number of arguments");
1634 }
1635
1636 int nextArg = 2;
1637 bool legacy = false;
1638 uid_t uid = 0;
1639 if (!strcmp(argv[nextArg], "legacy")) {
1640 ++nextArg;
1641 legacy = true;
1642 uid = strtoul(argv[nextArg++], NULL, 0);
1643 }
1644
1645 bool add = false;
1646 if (!strcmp(argv[nextArg], "add")) {
1647 add = true;
1648 } else if (strcmp(argv[nextArg], "remove")) {
1649 return syntaxError(client, "Unknown argument");
1650 }
1651 ++nextArg;
1652
Sreeram Ramachandrande5d5df2014-07-26 18:43:25 -07001653 if (argc < nextArg + 3 || argc > nextArg + 4) {
1654 return syntaxError(client, "Incorrect number of arguments");
1655 }
1656
Sreeram Ramachandran87475a12014-07-15 16:20:28 -07001657 unsigned netId = stringToNetId(argv[nextArg++]);
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -07001658 const char* interface = argv[nextArg++];
1659 const char* destination = argv[nextArg++];
1660 const char* nexthop = argc > nextArg ? argv[nextArg] : NULL;
1661
1662 int ret;
1663 if (add) {
Pierre Imai1cfa5432016-02-24 18:00:03 +09001664 ret = gCtls->netCtrl.addRoute(netId, interface, destination, nexthop, legacy, uid);
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -07001665 } else {
Pierre Imai1cfa5432016-02-24 18:00:03 +09001666 ret = gCtls->netCtrl.removeRoute(netId, interface, destination, nexthop, legacy, uid);
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -07001667 }
1668 if (ret) {
1669 return operationError(client, add ? "addRoute() failed" : "removeRoute() failed", ret);
1670 }
1671
1672 return success(client);
1673 }
1674
Sreeram Ramachandran87475a12014-07-15 16:20:28 -07001675 // 0 1 2 3 4
1676 // network interface add <netId> <interface>
1677 // network interface remove <netId> <interface>
1678 if (!strcmp(argv[1], "interface")) {
1679 if (argc != 5) {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -07001680 return syntaxError(client, "Missing argument");
1681 }
Sreeram Ramachandran87475a12014-07-15 16:20:28 -07001682 unsigned netId = stringToNetId(argv[3]);
1683 if (!strcmp(argv[2], "add")) {
Pierre Imai1cfa5432016-02-24 18:00:03 +09001684 if (int ret = gCtls->netCtrl.addInterfaceToNetwork(netId, argv[4])) {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -07001685 return operationError(client, "addInterfaceToNetwork() failed", ret);
1686 }
Sreeram Ramachandran87475a12014-07-15 16:20:28 -07001687 } else if (!strcmp(argv[2], "remove")) {
Pierre Imai1cfa5432016-02-24 18:00:03 +09001688 if (int ret = gCtls->netCtrl.removeInterfaceFromNetwork(netId, argv[4])) {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -07001689 return operationError(client, "removeInterfaceFromNetwork() failed", ret);
1690<