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