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