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