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