CommandListener.cpp revision 9589a4c6e0b6a5ec60c65b248e7deff2805749b2
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 <fcntl.h> 28#include <linux/if.h> 29 30#define LOG_TAG "CommandListener" 31 32#include <cutils/log.h> 33#include <netutils/ifc.h> 34#include <sysutils/SocketClient.h> 35 36#include "CommandListener.h" 37#include "ResponseCode.h" 38#include "ThrottleController.h" 39#include "BandwidthController.h" 40#include "IdletimerController.h" 41#include "SecondaryTableController.h" 42#include "oem_iptables_hook.h" 43#include "NetdConstants.h" 44 45TetherController *CommandListener::sTetherCtrl = NULL; 46NatController *CommandListener::sNatCtrl = NULL; 47PppController *CommandListener::sPppCtrl = NULL; 48PanController *CommandListener::sPanCtrl = NULL; 49SoftapController *CommandListener::sSoftapCtrl = NULL; 50BandwidthController * CommandListener::sBandwidthCtrl = NULL; 51IdletimerController * CommandListener::sIdletimerCtrl = NULL; 52ResolverController *CommandListener::sResolverCtrl = NULL; 53SecondaryTableController *CommandListener::sSecondaryTableCtrl = NULL; 54 55/** 56 * List of module chains to be created, along with explicit ordering. ORDERING 57 * IS CRITICAL, AND SHOULD BE TRIPLE-CHECKED WITH EACH CHANGE. 58 */ 59static const char* FILTER_INPUT[] = { 60 BandwidthController::LOCAL_INPUT, 61 NULL, 62}; 63 64static const char* FILTER_FORWARD[] = { 65 OEM_IPTABLES_FILTER_FORWARD, 66 BandwidthController::LOCAL_FORWARD, 67 NatController::LOCAL_FORWARD, 68 NULL, 69}; 70 71static const char* FILTER_OUTPUT[] = { 72 OEM_IPTABLES_FILTER_OUTPUT, 73 BandwidthController::LOCAL_OUTPUT, 74 NULL, 75}; 76 77static const char* RAW_PREROUTING[] = { 78 BandwidthController::LOCAL_RAW_PREROUTING, 79 NULL, 80}; 81 82static const char* MANGLE_POSTROUTING[] = { 83 BandwidthController::LOCAL_MANGLE_POSTROUTING, 84 NULL, 85}; 86 87static const char* NAT_PREROUTING[] = { 88 OEM_IPTABLES_NAT_PREROUTING, 89 IdletimerController::LOCAL_NAT_PREROUTING, 90 NULL, 91}; 92 93static const char* NAT_POSTROUTING[] = { 94 IdletimerController::LOCAL_NAT_POSTROUTING, 95 NatController::LOCAL_NAT_POSTROUTING, 96 NULL, 97}; 98 99static void createChildChains(IptablesTarget target, const char* table, const char* parentChain, 100 const char** childChains) { 101 const char** childChain = childChains; 102 do { 103 // Order is important: 104 // -D to delete any pre-existing jump rule (removes references 105 // that would prevent -X from working) 106 // -F to flush any existing chain 107 // -X to delete any existing chain 108 // -N to create the chain 109 // -A to append the chain to parent 110 111 execIptablesSilently(target, "-t", table, "-D", parentChain, "-j", *childChain, NULL); 112 execIptablesSilently(target, "-t", table, "-F", *childChain, NULL); 113 execIptablesSilently(target, "-t", table, "-X", *childChain, NULL); 114 execIptables(target, "-t", table, "-N", *childChain, NULL); 115 execIptables(target, "-t", table, "-A", parentChain, "-j", *childChain, NULL); 116 } while (*(++childChain) != NULL); 117} 118 119CommandListener::CommandListener() : 120 FrameworkListener("netd", true) { 121 registerCmd(new InterfaceCmd()); 122 registerCmd(new IpFwdCmd()); 123 registerCmd(new TetherCmd()); 124 registerCmd(new NatCmd()); 125 registerCmd(new ListTtysCmd()); 126 registerCmd(new PppdCmd()); 127 registerCmd(new PanCmd()); 128 registerCmd(new SoftapCmd()); 129 registerCmd(new BandwidthControlCmd()); 130 registerCmd(new IdletimerControlCmd()); 131 registerCmd(new ResolverCmd()); 132 133 if (!sSecondaryTableCtrl) 134 sSecondaryTableCtrl = new SecondaryTableController(); 135 if (!sTetherCtrl) 136 sTetherCtrl = new TetherController(); 137 if (!sNatCtrl) 138 sNatCtrl = new NatController(sSecondaryTableCtrl); 139 if (!sPppCtrl) 140 sPppCtrl = new PppController(); 141 if (!sPanCtrl) 142 sPanCtrl = new PanController(); 143 if (!sSoftapCtrl) 144 sSoftapCtrl = new SoftapController(); 145 if (!sBandwidthCtrl) 146 sBandwidthCtrl = new BandwidthController(); 147 if (!sIdletimerCtrl) 148 sIdletimerCtrl = new IdletimerController(); 149 if (!sResolverCtrl) 150 sResolverCtrl = new ResolverController(); 151 152 /* 153 * This is the only time we touch top-level chains in iptables; controllers 154 * should only mutate rules inside of their children chains, as created by 155 * the constants above. 156 * 157 * Modules should never ACCEPT packets (except in well-justified cases); 158 * they should instead defer to any remaining modules using RETURN, or 159 * otherwise DROP/REJECT. 160 */ 161 162 // Create chains for children modules 163 createChildChains(V4V6, "filter", "INPUT", FILTER_INPUT); 164 createChildChains(V4V6, "filter", "FORWARD", FILTER_FORWARD); 165 createChildChains(V4V6, "filter", "OUTPUT", FILTER_OUTPUT); 166 createChildChains(V4V6, "raw", "PREROUTING", RAW_PREROUTING); 167 createChildChains(V4V6, "mangle", "POSTROUTING", MANGLE_POSTROUTING); 168 createChildChains(V4, "nat", "PREROUTING", NAT_PREROUTING); 169 createChildChains(V4, "nat", "POSTROUTING", NAT_POSTROUTING); 170 171 // Let each module setup their child chains 172 setupOemIptablesHook(); 173 174 /* Does DROPs in FORWARD by default */ 175 sNatCtrl->setupIptablesHooks(); 176 /* 177 * Does REJECT in INPUT, OUTPUT. Does counting also. 178 * No DROP/REJECT allowed later in netfilter-flow hook order. 179 */ 180 sBandwidthCtrl->setupIptablesHooks(); 181 /* 182 * Counts in nat: PREROUTING, POSTROUTING. 183 * No DROP/REJECT allowed later in netfilter-flow hook order. 184 */ 185 sIdletimerCtrl->setupIptablesHooks(); 186 187 sBandwidthCtrl->enableBandwidthControl(false); 188} 189 190CommandListener::InterfaceCmd::InterfaceCmd() : 191 NetdCommand("interface") { 192} 193 194int CommandListener::writeFile(const char *path, const char *value, int size) { 195 int fd = open(path, O_WRONLY); 196 if (fd < 0) { 197 ALOGE("Failed to open %s: %s", path, strerror(errno)); 198 return -1; 199 } 200 201 if (write(fd, value, size) != size) { 202 ALOGE("Failed to write %s: %s", path, strerror(errno)); 203 close(fd); 204 return -1; 205 } 206 close(fd); 207 return 0; 208} 209 210int CommandListener::InterfaceCmd::runCommand(SocketClient *cli, 211 int argc, char **argv) { 212 if (argc < 2) { 213 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 214 return 0; 215 } 216 217 if (!strcmp(argv[1], "list")) { 218 DIR *d; 219 struct dirent *de; 220 221 if (!(d = opendir("/sys/class/net"))) { 222 cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true); 223 return 0; 224 } 225 226 while((de = readdir(d))) { 227 if (de->d_name[0] == '.') 228 continue; 229 cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false); 230 } 231 closedir(d); 232 cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false); 233 return 0; 234 } else if (!strcmp(argv[1], "readrxcounter")) { 235 if (argc != 3) { 236 cli->sendMsg(ResponseCode::CommandSyntaxError, 237 "Usage: interface readrxcounter <interface>", false); 238 return 0; 239 } 240 unsigned long rx = 0, tx = 0; 241 if (readInterfaceCounters(argv[2], &rx, &tx)) { 242 cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true); 243 return 0; 244 } 245 246 char *msg; 247 asprintf(&msg, "%lu", rx); 248 cli->sendMsg(ResponseCode::InterfaceRxCounterResult, msg, false); 249 free(msg); 250 251 return 0; 252 } else if (!strcmp(argv[1], "readtxcounter")) { 253 if (argc != 3) { 254 cli->sendMsg(ResponseCode::CommandSyntaxError, 255 "Usage: interface readtxcounter <interface>", false); 256 return 0; 257 } 258 unsigned long rx = 0, tx = 0; 259 if (readInterfaceCounters(argv[2], &rx, &tx)) { 260 cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true); 261 return 0; 262 } 263 264 char *msg = NULL; 265 asprintf(&msg, "%lu", tx); 266 cli->sendMsg(ResponseCode::InterfaceTxCounterResult, msg, false); 267 free(msg); 268 return 0; 269 } else if (!strcmp(argv[1], "getthrottle")) { 270 if (argc != 4 || (argc == 4 && (strcmp(argv[3], "rx") && (strcmp(argv[3], "tx"))))) { 271 cli->sendMsg(ResponseCode::CommandSyntaxError, 272 "Usage: interface getthrottle <interface> <rx|tx>", false); 273 return 0; 274 } 275 int val = 0; 276 int rc = 0; 277 int voldRc = ResponseCode::InterfaceRxThrottleResult; 278 279 if (!strcmp(argv[3], "rx")) { 280 rc = ThrottleController::getInterfaceRxThrottle(argv[2], &val); 281 } else { 282 rc = ThrottleController::getInterfaceTxThrottle(argv[2], &val); 283 voldRc = ResponseCode::InterfaceTxThrottleResult; 284 } 285 if (rc) { 286 cli->sendMsg(ResponseCode::OperationFailed, "Failed to get throttle", true); 287 } else { 288 char *msg = NULL; 289 asprintf(&msg, "%u", val); 290 cli->sendMsg(voldRc, msg, false); 291 free(msg); 292 return 0; 293 } 294 return 0; 295 } else if (!strcmp(argv[1], "setthrottle")) { 296 if (argc != 5) { 297 cli->sendMsg(ResponseCode::CommandSyntaxError, 298 "Usage: interface setthrottle <interface> <rx_kbps> <tx_kbps>", false); 299 return 0; 300 } 301 if (ThrottleController::setInterfaceThrottle(argv[2], atoi(argv[3]), atoi(argv[4]))) { 302 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set throttle", true); 303 } else { 304 cli->sendMsg(ResponseCode::CommandOkay, "Interface throttling set", false); 305 } 306 return 0; 307 } else { 308 /* 309 * These commands take a minimum of 3 arguments 310 */ 311 if (argc < 3) { 312 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 313 return 0; 314 } 315 316 // 0 1 2 3 4 5 6 7 317 // interface route add/remove iface default/secondary dest prefix gateway 318 if (!strcmp(argv[1], "route")) { 319 int prefix_length = 0; 320 if (argc < 8) { 321 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 322 return 0; 323 } 324 if (sscanf(argv[6], "%d", &prefix_length) != 1) { 325 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid route prefix", false); 326 return 0; 327 } 328 if (!strcmp(argv[2], "add")) { 329 if (!strcmp(argv[4], "default")) { 330 if (ifc_add_route(argv[3], argv[5], prefix_length, argv[7])) { 331 cli->sendMsg(ResponseCode::OperationFailed, 332 "Failed to add route to default table", true); 333 } else { 334 cli->sendMsg(ResponseCode::CommandOkay, 335 "Route added to default table", false); 336 } 337 } else if (!strcmp(argv[4], "secondary")) { 338 return sSecondaryTableCtrl->addRoute(cli, argv[3], argv[5], 339 prefix_length, argv[7]); 340 } else { 341 cli->sendMsg(ResponseCode::CommandParameterError, 342 "Invalid route type, expecting 'default' or 'secondary'", false); 343 return 0; 344 } 345 } else if (!strcmp(argv[2], "remove")) { 346 if (!strcmp(argv[4], "default")) { 347 if (ifc_remove_route(argv[3], argv[5], prefix_length, argv[7])) { 348 cli->sendMsg(ResponseCode::OperationFailed, 349 "Failed to remove route from default table", true); 350 } else { 351 cli->sendMsg(ResponseCode::CommandOkay, 352 "Route removed from default table", false); 353 } 354 } else if (!strcmp(argv[4], "secondary")) { 355 return sSecondaryTableCtrl->removeRoute(cli, argv[3], argv[5], 356 prefix_length, argv[7]); 357 } else { 358 cli->sendMsg(ResponseCode::CommandParameterError, 359 "Invalid route type, expecting 'default' or 'secondary'", false); 360 return 0; 361 } 362 } else { 363 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false); 364 } 365 return 0; 366 } 367 368 if (!strcmp(argv[1], "getcfg")) { 369 struct in_addr addr; 370 int prefixLength; 371 unsigned char hwaddr[6]; 372 unsigned flags = 0; 373 374 ifc_init(); 375 memset(hwaddr, 0, sizeof(hwaddr)); 376 377 if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) { 378 cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true); 379 ifc_close(); 380 return 0; 381 } 382 383 if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) { 384 ALOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno)); 385 } 386 387 char *addr_s = strdup(inet_ntoa(addr)); 388 const char *updown, *brdcst, *loopbk, *ppp, *running, *multi; 389 390 updown = (flags & IFF_UP) ? "up" : "down"; 391 brdcst = (flags & IFF_BROADCAST) ? " broadcast" : ""; 392 loopbk = (flags & IFF_LOOPBACK) ? " loopback" : ""; 393 ppp = (flags & IFF_POINTOPOINT) ? " point-to-point" : ""; 394 running = (flags & IFF_RUNNING) ? " running" : ""; 395 multi = (flags & IFF_MULTICAST) ? " multicast" : ""; 396 397 char *flag_s; 398 399 asprintf(&flag_s, "%s%s%s%s%s%s", updown, brdcst, loopbk, ppp, running, multi); 400 401 char *msg = NULL; 402 asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %d %s", 403 hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5], 404 addr_s, prefixLength, flag_s); 405 406 cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false); 407 408 free(addr_s); 409 free(flag_s); 410 free(msg); 411 412 ifc_close(); 413 return 0; 414 } else if (!strcmp(argv[1], "setcfg")) { 415 // arglist: iface [addr prefixLength] flags 416 if (argc < 4) { 417 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 418 return 0; 419 } 420 ALOGD("Setting iface cfg"); 421 422 struct in_addr addr; 423 unsigned flags = 0; 424 int index = 5; 425 426 ifc_init(); 427 428 if (!inet_aton(argv[3], &addr)) { 429 // Handle flags only case 430 index = 3; 431 } else { 432 if (ifc_set_addr(argv[2], addr.s_addr)) { 433 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true); 434 ifc_close(); 435 return 0; 436 } 437 438 // Set prefix length on a non zero address 439 if (addr.s_addr != 0 && ifc_set_prefixLength(argv[2], atoi(argv[4]))) { 440 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set prefixLength", true); 441 ifc_close(); 442 return 0; 443 } 444 } 445 446 /* Process flags */ 447 for (int i = index; i < argc; i++) { 448 char *flag = argv[i]; 449 if (!strcmp(flag, "up")) { 450 ALOGD("Trying to bring up %s", argv[2]); 451 if (ifc_up(argv[2])) { 452 ALOGE("Error upping interface"); 453 cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true); 454 ifc_close(); 455 return 0; 456 } 457 } else if (!strcmp(flag, "down")) { 458 ALOGD("Trying to bring down %s", argv[2]); 459 if (ifc_down(argv[2])) { 460 ALOGE("Error downing interface"); 461 cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true); 462 ifc_close(); 463 return 0; 464 } 465 } else if (!strcmp(flag, "broadcast")) { 466 // currently ignored 467 } else if (!strcmp(flag, "multicast")) { 468 // currently ignored 469 } else if (!strcmp(flag, "running")) { 470 // currently ignored 471 } else if (!strcmp(flag, "loopback")) { 472 // currently ignored 473 } else if (!strcmp(flag, "point-to-point")) { 474 // currently ignored 475 } else { 476 cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false); 477 ifc_close(); 478 return 0; 479 } 480 } 481 482 cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false); 483 ifc_close(); 484 return 0; 485 } else if (!strcmp(argv[1], "clearaddrs")) { 486 // arglist: iface 487 ALOGD("Clearing all IP addresses on %s", argv[2]); 488 489 ifc_clear_addresses(argv[2]); 490 491 cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false); 492 return 0; 493 } else if (!strcmp(argv[1], "ipv6privacyextensions")) { 494 if (argc != 4) { 495 cli->sendMsg(ResponseCode::CommandSyntaxError, 496 "Usage: interface ipv6privacyextensions <interface> <enable|disable>", 497 false); 498 return 0; 499 } 500 501 char *tmp; 502 asprintf(&tmp, "/proc/sys/net/ipv6/conf/%s/use_tempaddr", argv[2]); 503 504 if (writeFile(tmp, !strncmp(argv[3], "enable", 7) ? "2" : "0", 1) < 0) { 505 free(tmp); 506 cli->sendMsg(ResponseCode::OperationFailed, 507 "Failed to set ipv6 privacy extensions", true); 508 return 0; 509 } 510 511 free(tmp); 512 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false); 513 return 0; 514 } else if (!strcmp(argv[1], "ipv6")) { 515 if (argc != 4) { 516 cli->sendMsg(ResponseCode::CommandSyntaxError, 517 "Usage: interface ipv6 <interface> <enable|disable>", 518 false); 519 return 0; 520 } 521 522 char *tmp; 523 asprintf(&tmp, "/proc/sys/net/ipv6/conf/%s/disable_ipv6", argv[2]); 524 525 if (writeFile(tmp, !strncmp(argv[3], "enable", 7) ? "0" : "1", 1) < 0) { 526 free(tmp); 527 cli->sendMsg(ResponseCode::OperationFailed, 528 "Failed to change IPv6 state", true); 529 return 0; 530 } 531 532 free(tmp); 533 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false); 534 return 0; 535 } else { 536 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false); 537 return 0; 538 } 539 } 540 return 0; 541} 542 543 544CommandListener::ListTtysCmd::ListTtysCmd() : 545 NetdCommand("list_ttys") { 546} 547 548int CommandListener::ListTtysCmd::runCommand(SocketClient *cli, 549 int argc, char **argv) { 550 TtyCollection *tlist = sPppCtrl->getTtyList(); 551 TtyCollection::iterator it; 552 553 for (it = tlist->begin(); it != tlist->end(); ++it) { 554 cli->sendMsg(ResponseCode::TtyListResult, *it, false); 555 } 556 557 cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false); 558 return 0; 559} 560 561CommandListener::IpFwdCmd::IpFwdCmd() : 562 NetdCommand("ipfwd") { 563} 564 565int CommandListener::IpFwdCmd::runCommand(SocketClient *cli, 566 int argc, char **argv) { 567 int rc = 0; 568 569 if (argc < 2) { 570 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 571 return 0; 572 } 573 574 if (!strcmp(argv[1], "status")) { 575 char *tmp = NULL; 576 577 asprintf(&tmp, "Forwarding %s", (sTetherCtrl->getIpFwdEnabled() ? "enabled" : "disabled")); 578 cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false); 579 free(tmp); 580 return 0; 581 } else if (!strcmp(argv[1], "enable")) { 582 rc = sTetherCtrl->setIpFwdEnabled(true); 583 } else if (!strcmp(argv[1], "disable")) { 584 rc = sTetherCtrl->setIpFwdEnabled(false); 585 } else { 586 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false); 587 return 0; 588 } 589 590 if (!rc) { 591 cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false); 592 } else { 593 cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true); 594 } 595 596 return 0; 597} 598 599CommandListener::TetherCmd::TetherCmd() : 600 NetdCommand("tether") { 601} 602 603int CommandListener::TetherCmd::runCommand(SocketClient *cli, 604 int argc, char **argv) { 605 int rc = 0; 606 607 if (argc < 2) { 608 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 609 return 0; 610 } 611 612 if (!strcmp(argv[1], "stop")) { 613 rc = sTetherCtrl->stopTethering(); 614 } else if(!strcmp(argv[1], "start-reverse")) { 615 LOGD("CommandListener::TetherCmd::run, call startReverseTethering, iface:%s", argv[2]); 616 sTetherCtrl->startReverseTethering(argv[2]); 617 } else if (!strcmp(argv[1], "stop-reverse")) { 618 LOGD("CommandListener::TetherCmd::run, call stopReverseTethering"); 619 rc = sTetherCtrl->stopReverseTethering(); 620 } else if (!strcmp(argv[1], "status")) { 621 char *tmp = NULL; 622 623 asprintf(&tmp, "Tethering services %s", 624 (sTetherCtrl->isTetheringStarted() ? "started" : "stopped")); 625 cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false); 626 free(tmp); 627 return 0; 628 } else { 629 /* 630 * These commands take a minimum of 4 arguments 631 */ 632 if (argc < 4) { 633 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 634 return 0; 635 } 636 637 if (!strcmp(argv[1], "start")) { 638 if (argc % 2 == 1) { 639 cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false); 640 return 0; 641 } 642 643 int num_addrs = argc - 2; 644 int arg_index = 2; 645 int array_index = 0; 646 in_addr *addrs = (in_addr *)malloc(sizeof(in_addr) * num_addrs); 647 while (array_index < num_addrs) { 648 if (!inet_aton(argv[arg_index++], &(addrs[array_index++]))) { 649 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false); 650 free(addrs); 651 return 0; 652 } 653 } 654 rc = sTetherCtrl->startTethering(num_addrs, addrs); 655 free(addrs); 656 } else if (!strcmp(argv[1], "interface")) { 657 if (!strcmp(argv[2], "add")) { 658 rc = sTetherCtrl->tetherInterface(argv[3]); 659 } else if (!strcmp(argv[2], "remove")) { 660 rc = sTetherCtrl->untetherInterface(argv[3]); 661 } else if (!strcmp(argv[2], "list")) { 662 InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList(); 663 InterfaceCollection::iterator it; 664 665 for (it = ilist->begin(); it != ilist->end(); ++it) { 666 cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false); 667 } 668 } else { 669 cli->sendMsg(ResponseCode::CommandParameterError, 670 "Unknown tether interface operation", false); 671 return 0; 672 } 673 } else if (!strcmp(argv[1], "dns")) { 674 if (!strcmp(argv[2], "set")) { 675 rc = sTetherCtrl->setDnsForwarders(&argv[3], argc - 3); 676 } else if (!strcmp(argv[2], "list")) { 677 NetAddressCollection *dlist = sTetherCtrl->getDnsForwarders(); 678 NetAddressCollection::iterator it; 679 680 for (it = dlist->begin(); it != dlist->end(); ++it) { 681 cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, inet_ntoa(*it), false); 682 } 683 } else { 684 cli->sendMsg(ResponseCode::CommandParameterError, 685 "Unknown tether interface operation", false); 686 return 0; 687 } 688 } else { 689 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false); 690 return 0; 691 } 692 } 693 694 if (!rc) { 695 cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false); 696 } else { 697 cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true); 698 } 699 700 return 0; 701} 702 703CommandListener::NatCmd::NatCmd() : 704 NetdCommand("nat") { 705} 706 707int CommandListener::NatCmd::runCommand(SocketClient *cli, 708 int argc, char **argv) { 709 int rc = 0; 710 711 if (argc < 5) { 712 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 713 return 0; 714 } 715 716 if (!strcmp(argv[1], "enable")) { 717 rc = sNatCtrl->enableNat(argc, argv); 718 if(!rc) { 719 /* Ignore ifaces for now. */ 720 rc = sBandwidthCtrl->setGlobalAlertInForwardChain(); 721 } 722 } else if (!strcmp(argv[1], "disable")) { 723 /* Ignore ifaces for now. */ 724 rc = sBandwidthCtrl->removeGlobalAlertInForwardChain(); 725 rc |= sNatCtrl->disableNat(argc, argv); 726 } else { 727 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false); 728 return 0; 729 } 730 731 if (!rc) { 732 cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false); 733 } else { 734 cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true); 735 } 736 737 return 0; 738} 739 740CommandListener::PppdCmd::PppdCmd() : 741 NetdCommand("pppd") { 742} 743 744int CommandListener::PppdCmd::runCommand(SocketClient *cli, 745 int argc, char **argv) { 746 int rc = 0; 747 748 if (argc < 3) { 749 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 750 return 0; 751 } 752 753 if (!strcmp(argv[1], "attach")) { 754 struct in_addr l, r, dns1, dns2; 755 756 memset(&dns1, sizeof(struct in_addr), 0); 757 memset(&dns2, sizeof(struct in_addr), 0); 758 759 if (!inet_aton(argv[3], &l)) { 760 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false); 761 return 0; 762 } 763 if (!inet_aton(argv[4], &r)) { 764 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false); 765 return 0; 766 } 767 if ((argc > 3) && (!inet_aton(argv[5], &dns1))) { 768 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false); 769 return 0; 770 } 771 if ((argc > 4) && (!inet_aton(argv[6], &dns2))) { 772 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false); 773 return 0; 774 } 775 rc = sPppCtrl->attachPppd(argv[2], l, r, dns1, dns2); 776 } else if (!strcmp(argv[1], "detach")) { 777 rc = sPppCtrl->detachPppd(argv[2]); 778 } else { 779 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false); 780 return 0; 781 } 782 783 if (!rc) { 784 cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false); 785 } else { 786 cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true); 787 } 788 789 return 0; 790} 791 792CommandListener::PanCmd::PanCmd() : 793 NetdCommand("pan") { 794} 795 796int CommandListener::PanCmd::runCommand(SocketClient *cli, 797 int argc, char **argv) { 798 int rc = 0; 799 800 if (argc < 2) { 801 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 802 return 0; 803 } 804 805 if (!strcmp(argv[1], "start")) { 806 rc = sPanCtrl->startPan(); 807 } else if (!strcmp(argv[1], "stop")) { 808 rc = sPanCtrl->stopPan(); 809 } else if (!strcmp(argv[1], "status")) { 810 char *tmp = NULL; 811 812 asprintf(&tmp, "Pan services %s", 813 (sPanCtrl->isPanStarted() ? "started" : "stopped")); 814 cli->sendMsg(ResponseCode::PanStatusResult, tmp, false); 815 free(tmp); 816 return 0; 817 } else { 818 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pan cmd", false); 819 return 0; 820 } 821 822 if (!rc) { 823 cli->sendMsg(ResponseCode::CommandOkay, "Pan operation succeeded", false); 824 } else { 825 cli->sendMsg(ResponseCode::OperationFailed, "Pan operation failed", true); 826 } 827 828 return 0; 829} 830 831CommandListener::SoftapCmd::SoftapCmd() : 832 NetdCommand("softap") { 833} 834 835int CommandListener::SoftapCmd::runCommand(SocketClient *cli, 836 int argc, char **argv) { 837 int rc = 0, flag = 0; 838 char *retbuf = NULL; 839 840 if (argc < 2) { 841 cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Missing argument", false); 842 return 0; 843 } 844 845 if (!strcmp(argv[1], "startap")) { 846 rc = sSoftapCtrl->startSoftap(); 847 } else if (!strcmp(argv[1], "stopap")) { 848 rc = sSoftapCtrl->stopSoftap(); 849 } else if (!strcmp(argv[1], "fwreload")) { 850 rc = sSoftapCtrl->fwReloadSoftap(argc, argv); 851 } else if (!strcmp(argv[1], "clients")) { 852 rc = sSoftapCtrl->clientsSoftap(&retbuf); 853 if (!rc) { 854 cli->sendMsg(ResponseCode::CommandOkay, retbuf, false); 855 free(retbuf); 856 return 0; 857 } 858 } else if (!strcmp(argv[1], "status")) { 859 asprintf(&retbuf, "Softap service %s", 860 (sSoftapCtrl->isSoftapStarted() ? "started" : "stopped")); 861 cli->sendMsg(ResponseCode::SoftapStatusResult, retbuf, false); 862 free(retbuf); 863 return 0; 864 } else if (!strcmp(argv[1], "set")) { 865 rc = sSoftapCtrl->setSoftap(argc, argv); 866 } else { 867 cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Unknown cmd", false); 868 return 0; 869 } 870 871 if (!rc) { 872 cli->sendMsg(ResponseCode::CommandOkay, "Softap operation succeeded", false); 873 } else { 874 cli->sendMsg(ResponseCode::OperationFailed, "Softap operation failed", true); 875 } 876 877 return 0; 878} 879 880CommandListener::ResolverCmd::ResolverCmd() : 881 NetdCommand("resolver") { 882} 883 884int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **argv) { 885 int rc = 0; 886 struct in_addr addr; 887 888 if (argc < 2) { 889 cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false); 890 return 0; 891 } 892 893 if (!strcmp(argv[1], "setdefaultif")) { // "resolver setdefaultif <iface>" 894 if (argc == 3) { 895 rc = sResolverCtrl->setDefaultInterface(argv[2]); 896 } else { 897 cli->sendMsg(ResponseCode::CommandSyntaxError, 898 "Wrong number of arguments to resolver setdefaultif", false); 899 return 0; 900 } 901 } else if (!strcmp(argv[1], "setifdns")) { // "resolver setifdns <iface> <dns1> <dns2> ..." 902 if (argc >= 4) { 903 rc = sResolverCtrl->setInterfaceDnsServers(argv[2], &argv[3], argc - 3); 904 } else { 905 cli->sendMsg(ResponseCode::CommandSyntaxError, 906 "Wrong number of arguments to resolver setifdns", false); 907 return 0; 908 } 909 910 // set the address of the interface to which the name servers 911 // are bound. Required in order to bind to right interface when 912 // doing the dns query. 913 if (!rc) { 914 ifc_init(); 915 ifc_get_info(argv[2], &addr.s_addr, NULL, 0); 916 917 rc = sResolverCtrl->setInterfaceAddress(argv[2], &addr); 918 } 919 } else if (!strcmp(argv[1], "flushdefaultif")) { // "resolver flushdefaultif" 920 if (argc == 2) { 921 rc = sResolverCtrl->flushDefaultDnsCache(); 922 } else { 923 cli->sendMsg(ResponseCode::CommandSyntaxError, 924 "Wrong number of arguments to resolver flushdefaultif", false); 925 return 0; 926 } 927 } else if (!strcmp(argv[1], "flushif")) { // "resolver flushif <iface>" 928 if (argc == 3) { 929 rc = sResolverCtrl->flushInterfaceDnsCache(argv[2]); 930 } else { 931 cli->sendMsg(ResponseCode::CommandSyntaxError, 932 "Wrong number of arguments to resolver setdefaultif", false); 933 return 0; 934 } 935 } else { 936 cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false); 937 return 0; 938 } 939 940 if (!rc) { 941 cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false); 942 } else { 943 cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true); 944 } 945 946 return 0; 947} 948 949int CommandListener::readInterfaceCounters(const char *iface, unsigned long *rx, unsigned long *tx) { 950 FILE *fp = fopen("/proc/net/dev", "r"); 951 if (!fp) { 952 ALOGE("Failed to open /proc/net/dev (%s)", strerror(errno)); 953 return -1; 954 } 955 956 char buffer[512]; 957 958 fgets(buffer, sizeof(buffer), fp); // Header 1 959 fgets(buffer, sizeof(buffer), fp); // Header 2 960 while(fgets(buffer, sizeof(buffer), fp)) { 961 buffer[strlen(buffer)-1] = '\0'; 962 963 char name[31]; 964 unsigned long d; 965 sscanf(buffer, "%30s %lu %lu %lu %lu %lu %lu %lu %lu %lu", 966 name, rx, &d, &d, &d, &d, &d, &d, &d, tx); 967 char *rxString = strchr(name, ':'); 968 *rxString = '\0'; 969 rxString++; 970 // when the rx count gets too big it changes from "name: 999" to "name:1000" 971 // and the sscanf munge the two together. Detect that and fix 972 // note that all the %lu will be off by one and the real tx value will be in d 973 if (*rxString != '\0') { 974 *tx = d; 975 sscanf(rxString, "%20lu", rx); 976 } 977 if (strcmp(name, iface)) { 978 continue; 979 } 980 fclose(fp); 981 return 0; 982 } 983 984 fclose(fp); 985 *rx = 0; 986 *tx = 0; 987 return 0; 988} 989 990CommandListener::BandwidthControlCmd::BandwidthControlCmd() : 991 NetdCommand("bandwidth") { 992} 993 994void CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) { 995 char *msg; 996 asprintf(&msg, "Usage: bandwidth %s", usageMsg); 997 cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false); 998 free(msg); 999} 1000 1001void CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) { 1002 if (!cond) { 1003 cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false); 1004 } else { 1005 cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false); 1006 } 1007} 1008 1009void CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) { 1010 cli->sendMsg(ResponseCode::OperationFailed, errMsg, false); 1011} 1012 1013int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) { 1014 if (argc < 2) { 1015 sendGenericSyntaxError(cli, "<cmds> <args...>"); 1016 return 0; 1017 } 1018 1019 ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]); 1020 1021 if (!strcmp(argv[1], "enable")) { 1022 int rc = sBandwidthCtrl->enableBandwidthControl(true); 1023 sendGenericOkFail(cli, rc); 1024 return 0; 1025 1026 } 1027 if (!strcmp(argv[1], "disable")) { 1028 int rc = sBandwidthCtrl->disableBandwidthControl(); 1029 sendGenericOkFail(cli, rc); 1030 return 0; 1031 1032 } 1033 if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) { 1034 if (argc != 3) { 1035 sendGenericSyntaxError(cli, "removequota <interface>"); 1036 return 0; 1037 } 1038 int rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[2]); 1039 sendGenericOkFail(cli, rc); 1040 return 0; 1041 1042 } 1043 if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) { 1044 int64_t bytes; 1045 if (argc != 2) { 1046 sendGenericSyntaxError(cli, "getquota"); 1047 return 0; 1048 } 1049 int rc = sBandwidthCtrl->getInterfaceSharedQuota(&bytes); 1050 if (rc) { 1051 sendGenericOpFailed(cli, "Failed to get quota"); 1052 return 0; 1053 } 1054 1055 char *msg; 1056 asprintf(&msg, "%lld", bytes); 1057 cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false); 1058 free(msg); 1059 return 0; 1060 1061 } 1062 if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) { 1063 int64_t bytes; 1064 if (argc != 3) { 1065 sendGenericSyntaxError(cli, "getiquota <iface>"); 1066 return 0; 1067 } 1068 1069 int rc = sBandwidthCtrl->getInterfaceQuota(argv[2], &bytes); 1070 if (rc) { 1071 sendGenericOpFailed(cli, "Failed to get quota"); 1072 return 0; 1073 } 1074 char *msg; 1075 asprintf(&msg, "%lld", bytes); 1076 cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false); 1077 free(msg); 1078 return 0; 1079 1080 } 1081 if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) { 1082 if (argc != 4) { 1083 sendGenericSyntaxError(cli, "setquota <interface> <bytes>"); 1084 return 0; 1085 } 1086 int rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[2], atoll(argv[3])); 1087 sendGenericOkFail(cli, rc); 1088 return 0; 1089 } 1090 if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) { 1091 int rc; 1092 if (argc < 4) { 1093 sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ..."); 1094 return 0; 1095 } 1096 1097 for (int q = 3; argc >= 4; q++, argc--) { 1098 rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[q], atoll(argv[2])); 1099 if (rc) { 1100 char *msg; 1101 asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]); 1102 cli->sendMsg(ResponseCode::OperationFailed, 1103 msg, false); 1104 free(msg); 1105 return 0; 1106 } 1107 } 1108 sendGenericOkFail(cli, rc); 1109 return 0; 1110 1111 } 1112 if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) { 1113 int rc; 1114 if (argc < 3) { 1115 sendGenericSyntaxError(cli, "removequotas <interface> ..."); 1116 return 0; 1117 } 1118 1119 for (int q = 2; argc >= 3; q++, argc--) { 1120 rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[q]); 1121 if (rc) { 1122 char *msg; 1123 asprintf(&msg, "bandwidth removequotas %s failed", argv[q]); 1124 cli->sendMsg(ResponseCode::OperationFailed, 1125 msg, false); 1126 free(msg); 1127 return 0; 1128 } 1129 } 1130 sendGenericOkFail(cli, rc); 1131 return 0; 1132 1133 } 1134 if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) { 1135 if (argc != 3) { 1136 sendGenericSyntaxError(cli, "removeiquota <interface>"); 1137 return 0; 1138 } 1139 int rc = sBandwidthCtrl->removeInterfaceQuota(argv[2]); 1140 sendGenericOkFail(cli, rc); 1141 return 0; 1142 1143 } 1144 if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) { 1145 if (argc != 4) { 1146 sendGenericSyntaxError(cli, "setiquota <interface> <bytes>"); 1147 return 0; 1148 } 1149 int rc = sBandwidthCtrl->setInterfaceQuota(argv[2], atoll(argv[3])); 1150 sendGenericOkFail(cli, rc); 1151 return 0; 1152 1153 } 1154 if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) { 1155 if (argc < 3) { 1156 sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ..."); 1157 return 0; 1158 } 1159 int rc = sBandwidthCtrl->addNaughtyApps(argc - 2, argv + 2); 1160 sendGenericOkFail(cli, rc); 1161 return 0; 1162 1163 1164 } 1165 if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) { 1166 if (argc < 3) { 1167 sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ..."); 1168 return 0; 1169 } 1170 int rc = sBandwidthCtrl->removeNaughtyApps(argc - 2, argv + 2); 1171 sendGenericOkFail(cli, rc); 1172 return 0; 1173 1174 } 1175 if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) { 1176 if (argc != 3) { 1177 sendGenericSyntaxError(cli, "setglobalalert <bytes>"); 1178 return 0; 1179 } 1180 int rc = sBandwidthCtrl->setGlobalAlert(atoll(argv[2])); 1181 sendGenericOkFail(cli, rc); 1182 return 0; 1183 1184 } 1185 if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) { 1186 if (argc != 4) { 1187 sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>"); 1188 return 0; 1189 } 1190 /* We ignore the interfaces for now. */ 1191 int rc = sBandwidthCtrl->setGlobalAlertInForwardChain(); 1192 sendGenericOkFail(cli, rc); 1193 return 0; 1194 1195 } 1196 if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) { 1197 if (argc != 2) { 1198 sendGenericSyntaxError(cli, "removeglobalalert"); 1199 return 0; 1200 } 1201 int rc = sBandwidthCtrl->removeGlobalAlert(); 1202 sendGenericOkFail(cli, rc); 1203 return 0; 1204 1205 } 1206 if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) { 1207 if (argc != 4) { 1208 sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>"); 1209 return 0; 1210 } 1211 /* We ignore the interfaces for now. */ 1212 int rc = sBandwidthCtrl->removeGlobalAlertInForwardChain(); 1213 sendGenericOkFail(cli, rc); 1214 return 0; 1215 1216 } 1217 if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) { 1218 if (argc != 3) { 1219 sendGenericSyntaxError(cli, "setsharedalert <bytes>"); 1220 return 0; 1221 } 1222 int rc = sBandwidthCtrl->setSharedAlert(atoll(argv[2])); 1223 sendGenericOkFail(cli, rc); 1224 return 0; 1225 1226 } 1227 if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) { 1228 if (argc != 2) { 1229 sendGenericSyntaxError(cli, "removesharedalert"); 1230 return 0; 1231 } 1232 int rc = sBandwidthCtrl->removeSharedAlert(); 1233 sendGenericOkFail(cli, rc); 1234 return 0; 1235 1236 } 1237 if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) { 1238 if (argc != 4) { 1239 sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>"); 1240 return 0; 1241 } 1242 int rc = sBandwidthCtrl->setInterfaceAlert(argv[2], atoll(argv[3])); 1243 sendGenericOkFail(cli, rc); 1244 return 0; 1245 1246 } 1247 if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) { 1248 if (argc != 3) { 1249 sendGenericSyntaxError(cli, "removeinterfacealert <interface>"); 1250 return 0; 1251 } 1252 int rc = sBandwidthCtrl->removeInterfaceAlert(argv[2]); 1253 sendGenericOkFail(cli, rc); 1254 return 0; 1255 1256 } 1257 if (!strcmp(argv[1], "gettetherstats") || !strcmp(argv[1], "gts")) { 1258 BandwidthController::TetherStats tetherStats; 1259 std::string extraProcessingInfo = ""; 1260 if (argc != 4) { 1261 sendGenericSyntaxError(cli, "gettetherstats <interface0> <interface1>"); 1262 return 0; 1263 } 1264 1265 tetherStats.ifaceIn = argv[2]; 1266 tetherStats.ifaceOut = argv[3]; 1267 int rc = sBandwidthCtrl->getTetherStats(tetherStats, extraProcessingInfo); 1268 if (rc) { 1269 extraProcessingInfo.insert(0, "Failed to get tethering stats.\n"); 1270 sendGenericOpFailed(cli, extraProcessingInfo.c_str()); 1271 return 0; 1272 } 1273 1274 char *msg = tetherStats.getStatsLine(); 1275 cli->sendMsg(ResponseCode::TetheringStatsResult, msg, false); 1276 free(msg); 1277 return 0; 1278 1279 } 1280 1281 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false); 1282 return 0; 1283} 1284 1285CommandListener::IdletimerControlCmd::IdletimerControlCmd() : 1286 NetdCommand("idletimer") { 1287} 1288 1289int CommandListener::IdletimerControlCmd::runCommand(SocketClient *cli, int argc, char **argv) { 1290 // TODO(ashish): Change the error statements 1291 if (argc < 2) { 1292 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 1293 return 0; 1294 } 1295 1296 ALOGV("idletimerctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]); 1297 1298 if (!strcmp(argv[1], "enable")) { 1299 if (0 != sIdletimerCtrl->enableIdletimerControl()) { 1300 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 1301 } else { 1302 cli->sendMsg(ResponseCode::CommandOkay, "Enable success", false); 1303 } 1304 return 0; 1305 1306 } 1307 if (!strcmp(argv[1], "disable")) { 1308 if (0 != sIdletimerCtrl->disableIdletimerControl()) { 1309 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 1310 } else { 1311 cli->sendMsg(ResponseCode::CommandOkay, "Disable success", false); 1312 } 1313 return 0; 1314 } 1315 if (!strcmp(argv[1], "add")) { 1316 if (argc != 5) { 1317 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 1318 return 0; 1319 } 1320 if(0 != sIdletimerCtrl->addInterfaceIdletimer( 1321 argv[2], atoi(argv[3]), argv[4])) { 1322 cli->sendMsg(ResponseCode::OperationFailed, "Failed to add interface", false); 1323 } else { 1324 cli->sendMsg(ResponseCode::CommandOkay, "Add success", false); 1325 } 1326 return 0; 1327 } 1328 if (!strcmp(argv[1], "remove")) { 1329 if (argc != 5) { 1330 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 1331 return 0; 1332 } 1333 // ashish: fixme timeout 1334 if (0 != sIdletimerCtrl->removeInterfaceIdletimer( 1335 argv[2], atoi(argv[3]), argv[4])) { 1336 cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove interface", false); 1337 } else { 1338 cli->sendMsg(ResponseCode::CommandOkay, "Remove success", false); 1339 } 1340 return 0; 1341 } 1342 1343 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown idletimer cmd", false); 1344 return 0; 1345} 1346