CommandListener.cpp revision 8e188ed5c989ddcc07f0f5e9839493c22d17e7b6
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], "status")) { 615 char *tmp = NULL; 616 617 asprintf(&tmp, "Tethering services %s", 618 (sTetherCtrl->isTetheringStarted() ? "started" : "stopped")); 619 cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false); 620 free(tmp); 621 return 0; 622 } else { 623 /* 624 * These commands take a minimum of 4 arguments 625 */ 626 if (argc < 4) { 627 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 628 return 0; 629 } 630 631 if (!strcmp(argv[1], "start")) { 632 if (argc % 2 == 1) { 633 cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false); 634 return 0; 635 } 636 637 int num_addrs = argc - 2; 638 int arg_index = 2; 639 int array_index = 0; 640 in_addr *addrs = (in_addr *)malloc(sizeof(in_addr) * num_addrs); 641 while (array_index < num_addrs) { 642 if (!inet_aton(argv[arg_index++], &(addrs[array_index++]))) { 643 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false); 644 free(addrs); 645 return 0; 646 } 647 } 648 rc = sTetherCtrl->startTethering(num_addrs, addrs); 649 free(addrs); 650 } else if (!strcmp(argv[1], "interface")) { 651 if (!strcmp(argv[2], "add")) { 652 rc = sTetherCtrl->tetherInterface(argv[3]); 653 } else if (!strcmp(argv[2], "remove")) { 654 rc = sTetherCtrl->untetherInterface(argv[3]); 655 } else if (!strcmp(argv[2], "list")) { 656 InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList(); 657 InterfaceCollection::iterator it; 658 659 for (it = ilist->begin(); it != ilist->end(); ++it) { 660 cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false); 661 } 662 } else { 663 cli->sendMsg(ResponseCode::CommandParameterError, 664 "Unknown tether interface operation", false); 665 return 0; 666 } 667 } else if (!strcmp(argv[1], "dns")) { 668 if (!strcmp(argv[2], "set")) { 669 rc = sTetherCtrl->setDnsForwarders(&argv[3], argc - 3); 670 } else if (!strcmp(argv[2], "list")) { 671 NetAddressCollection *dlist = sTetherCtrl->getDnsForwarders(); 672 NetAddressCollection::iterator it; 673 674 for (it = dlist->begin(); it != dlist->end(); ++it) { 675 cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, inet_ntoa(*it), false); 676 } 677 } else { 678 cli->sendMsg(ResponseCode::CommandParameterError, 679 "Unknown tether interface operation", false); 680 return 0; 681 } 682 } else { 683 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false); 684 return 0; 685 } 686 } 687 688 if (!rc) { 689 cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false); 690 } else { 691 cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true); 692 } 693 694 return 0; 695} 696 697CommandListener::NatCmd::NatCmd() : 698 NetdCommand("nat") { 699} 700 701int CommandListener::NatCmd::runCommand(SocketClient *cli, 702 int argc, char **argv) { 703 int rc = 0; 704 705 if (argc < 5) { 706 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 707 return 0; 708 } 709 710 if (!strcmp(argv[1], "enable")) { 711 rc = sNatCtrl->enableNat(argc, argv); 712 if(!rc) { 713 /* Ignore ifaces for now. */ 714 rc = sBandwidthCtrl->setGlobalAlertInForwardChain(); 715 } 716 } else if (!strcmp(argv[1], "disable")) { 717 /* Ignore ifaces for now. */ 718 rc = sBandwidthCtrl->removeGlobalAlertInForwardChain(); 719 rc |= sNatCtrl->disableNat(argc, argv); 720 } else { 721 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false); 722 return 0; 723 } 724 725 if (!rc) { 726 cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false); 727 } else { 728 cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true); 729 } 730 731 return 0; 732} 733 734CommandListener::PppdCmd::PppdCmd() : 735 NetdCommand("pppd") { 736} 737 738int CommandListener::PppdCmd::runCommand(SocketClient *cli, 739 int argc, char **argv) { 740 int rc = 0; 741 742 if (argc < 3) { 743 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 744 return 0; 745 } 746 747 if (!strcmp(argv[1], "attach")) { 748 struct in_addr l, r, dns1, dns2; 749 750 memset(&dns1, sizeof(struct in_addr), 0); 751 memset(&dns2, sizeof(struct in_addr), 0); 752 753 if (!inet_aton(argv[3], &l)) { 754 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false); 755 return 0; 756 } 757 if (!inet_aton(argv[4], &r)) { 758 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false); 759 return 0; 760 } 761 if ((argc > 3) && (!inet_aton(argv[5], &dns1))) { 762 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false); 763 return 0; 764 } 765 if ((argc > 4) && (!inet_aton(argv[6], &dns2))) { 766 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false); 767 return 0; 768 } 769 rc = sPppCtrl->attachPppd(argv[2], l, r, dns1, dns2); 770 } else if (!strcmp(argv[1], "detach")) { 771 rc = sPppCtrl->detachPppd(argv[2]); 772 } else { 773 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false); 774 return 0; 775 } 776 777 if (!rc) { 778 cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false); 779 } else { 780 cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true); 781 } 782 783 return 0; 784} 785 786CommandListener::PanCmd::PanCmd() : 787 NetdCommand("pan") { 788} 789 790int CommandListener::PanCmd::runCommand(SocketClient *cli, 791 int argc, char **argv) { 792 int rc = 0; 793 794 if (argc < 2) { 795 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 796 return 0; 797 } 798 799 if (!strcmp(argv[1], "start")) { 800 rc = sPanCtrl->startPan(); 801 } else if (!strcmp(argv[1], "stop")) { 802 rc = sPanCtrl->stopPan(); 803 } else if (!strcmp(argv[1], "status")) { 804 char *tmp = NULL; 805 806 asprintf(&tmp, "Pan services %s", 807 (sPanCtrl->isPanStarted() ? "started" : "stopped")); 808 cli->sendMsg(ResponseCode::PanStatusResult, tmp, false); 809 free(tmp); 810 return 0; 811 } else { 812 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pan cmd", false); 813 return 0; 814 } 815 816 if (!rc) { 817 cli->sendMsg(ResponseCode::CommandOkay, "Pan operation succeeded", false); 818 } else { 819 cli->sendMsg(ResponseCode::OperationFailed, "Pan operation failed", true); 820 } 821 822 return 0; 823} 824 825CommandListener::SoftapCmd::SoftapCmd() : 826 NetdCommand("softap") { 827} 828 829int CommandListener::SoftapCmd::runCommand(SocketClient *cli, 830 int argc, char **argv) { 831 int rc = 0, flag = 0; 832 char *retbuf = NULL; 833 834 if (argc < 2) { 835 cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Missing argument", false); 836 return 0; 837 } 838 839 if (!strcmp(argv[1], "startap")) { 840 rc = sSoftapCtrl->startSoftap(); 841 } else if (!strcmp(argv[1], "stopap")) { 842 rc = sSoftapCtrl->stopSoftap(); 843 } else if (!strcmp(argv[1], "fwreload")) { 844 rc = sSoftapCtrl->fwReloadSoftap(argc, argv); 845 } else if (!strcmp(argv[1], "clients")) { 846 rc = sSoftapCtrl->clientsSoftap(&retbuf); 847 if (!rc) { 848 cli->sendMsg(ResponseCode::CommandOkay, retbuf, false); 849 free(retbuf); 850 return 0; 851 } 852 } else if (!strcmp(argv[1], "status")) { 853 asprintf(&retbuf, "Softap service %s", 854 (sSoftapCtrl->isSoftapStarted() ? "started" : "stopped")); 855 cli->sendMsg(ResponseCode::SoftapStatusResult, retbuf, false); 856 free(retbuf); 857 return 0; 858 } else if (!strcmp(argv[1], "set")) { 859 rc = sSoftapCtrl->setSoftap(argc, argv); 860 } else { 861 cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Unknown cmd", false); 862 return 0; 863 } 864 865 if (!rc) { 866 cli->sendMsg(ResponseCode::CommandOkay, "Softap operation succeeded", false); 867 } else { 868 cli->sendMsg(ResponseCode::OperationFailed, "Softap operation failed", true); 869 } 870 871 return 0; 872} 873 874CommandListener::ResolverCmd::ResolverCmd() : 875 NetdCommand("resolver") { 876} 877 878int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **argv) { 879 int rc = 0; 880 struct in_addr addr; 881 882 if (argc < 2) { 883 cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false); 884 return 0; 885 } 886 887 if (!strcmp(argv[1], "setdefaultif")) { // "resolver setdefaultif <iface>" 888 if (argc == 3) { 889 rc = sResolverCtrl->setDefaultInterface(argv[2]); 890 } else { 891 cli->sendMsg(ResponseCode::CommandSyntaxError, 892 "Wrong number of arguments to resolver setdefaultif", false); 893 return 0; 894 } 895 } else if (!strcmp(argv[1], "setifdns")) { // "resolver setifdns <iface> <dns1> <dns2> ..." 896 if (argc >= 4) { 897 rc = sResolverCtrl->setInterfaceDnsServers(argv[2], &argv[3], argc - 3); 898 } else { 899 cli->sendMsg(ResponseCode::CommandSyntaxError, 900 "Wrong number of arguments to resolver setifdns", false); 901 return 0; 902 } 903 904 // set the address of the interface to which the name servers 905 // are bound. Required in order to bind to right interface when 906 // doing the dns query. 907 if (!rc) { 908 ifc_init(); 909 ifc_get_info(argv[2], &addr.s_addr, NULL, 0); 910 911 rc = sResolverCtrl->setInterfaceAddress(argv[2], &addr); 912 } 913 } else if (!strcmp(argv[1], "flushdefaultif")) { // "resolver flushdefaultif" 914 if (argc == 2) { 915 rc = sResolverCtrl->flushDefaultDnsCache(); 916 } else { 917 cli->sendMsg(ResponseCode::CommandSyntaxError, 918 "Wrong number of arguments to resolver flushdefaultif", false); 919 return 0; 920 } 921 } else if (!strcmp(argv[1], "flushif")) { // "resolver flushif <iface>" 922 if (argc == 3) { 923 rc = sResolverCtrl->flushInterfaceDnsCache(argv[2]); 924 } else { 925 cli->sendMsg(ResponseCode::CommandSyntaxError, 926 "Wrong number of arguments to resolver setdefaultif", false); 927 return 0; 928 } 929 } else { 930 cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false); 931 return 0; 932 } 933 934 if (!rc) { 935 cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false); 936 } else { 937 cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true); 938 } 939 940 return 0; 941} 942 943int CommandListener::readInterfaceCounters(const char *iface, unsigned long *rx, unsigned long *tx) { 944 FILE *fp = fopen("/proc/net/dev", "r"); 945 if (!fp) { 946 ALOGE("Failed to open /proc/net/dev (%s)", strerror(errno)); 947 return -1; 948 } 949 950 char buffer[512]; 951 952 fgets(buffer, sizeof(buffer), fp); // Header 1 953 fgets(buffer, sizeof(buffer), fp); // Header 2 954 while(fgets(buffer, sizeof(buffer), fp)) { 955 buffer[strlen(buffer)-1] = '\0'; 956 957 char name[31]; 958 unsigned long d; 959 sscanf(buffer, "%30s %lu %lu %lu %lu %lu %lu %lu %lu %lu", 960 name, rx, &d, &d, &d, &d, &d, &d, &d, tx); 961 char *rxString = strchr(name, ':'); 962 *rxString = '\0'; 963 rxString++; 964 // when the rx count gets too big it changes from "name: 999" to "name:1000" 965 // and the sscanf munge the two together. Detect that and fix 966 // note that all the %lu will be off by one and the real tx value will be in d 967 if (*rxString != '\0') { 968 *tx = d; 969 sscanf(rxString, "%20lu", rx); 970 } 971 if (strcmp(name, iface)) { 972 continue; 973 } 974 fclose(fp); 975 return 0; 976 } 977 978 fclose(fp); 979 *rx = 0; 980 *tx = 0; 981 return 0; 982} 983 984CommandListener::BandwidthControlCmd::BandwidthControlCmd() : 985 NetdCommand("bandwidth") { 986} 987 988void CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) { 989 char *msg; 990 asprintf(&msg, "Usage: bandwidth %s", usageMsg); 991 cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false); 992 free(msg); 993} 994 995void CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) { 996 if (!cond) { 997 cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false); 998 } else { 999 cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false); 1000 } 1001} 1002 1003void CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) { 1004 cli->sendMsg(ResponseCode::OperationFailed, errMsg, false); 1005} 1006 1007int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) { 1008 if (argc < 2) { 1009 sendGenericSyntaxError(cli, "<cmds> <args...>"); 1010 return 0; 1011 } 1012 1013 ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]); 1014 1015 if (!strcmp(argv[1], "enable")) { 1016 int rc = sBandwidthCtrl->enableBandwidthControl(true); 1017 sendGenericOkFail(cli, rc); 1018 return 0; 1019 1020 } 1021 if (!strcmp(argv[1], "disable")) { 1022 int rc = sBandwidthCtrl->disableBandwidthControl(); 1023 sendGenericOkFail(cli, rc); 1024 return 0; 1025 1026 } 1027 if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) { 1028 if (argc != 3) { 1029 sendGenericSyntaxError(cli, "removequota <interface>"); 1030 return 0; 1031 } 1032 int rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[2]); 1033 sendGenericOkFail(cli, rc); 1034 return 0; 1035 1036 } 1037 if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) { 1038 int64_t bytes; 1039 if (argc != 2) { 1040 sendGenericSyntaxError(cli, "getquota"); 1041 return 0; 1042 } 1043 int rc = sBandwidthCtrl->getInterfaceSharedQuota(&bytes); 1044 if (rc) { 1045 sendGenericOpFailed(cli, "Failed to get quota"); 1046 return 0; 1047 } 1048 1049 char *msg; 1050 asprintf(&msg, "%lld", bytes); 1051 cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false); 1052 free(msg); 1053 return 0; 1054 1055 } 1056 if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) { 1057 int64_t bytes; 1058 if (argc != 3) { 1059 sendGenericSyntaxError(cli, "getiquota <iface>"); 1060 return 0; 1061 } 1062 1063 int rc = sBandwidthCtrl->getInterfaceQuota(argv[2], &bytes); 1064 if (rc) { 1065 sendGenericOpFailed(cli, "Failed to get quota"); 1066 return 0; 1067 } 1068 char *msg; 1069 asprintf(&msg, "%lld", bytes); 1070 cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false); 1071 free(msg); 1072 return 0; 1073 1074 } 1075 if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) { 1076 if (argc != 4) { 1077 sendGenericSyntaxError(cli, "setquota <interface> <bytes>"); 1078 return 0; 1079 } 1080 int rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[2], atoll(argv[3])); 1081 sendGenericOkFail(cli, rc); 1082 return 0; 1083 } 1084 if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) { 1085 int rc; 1086 if (argc < 4) { 1087 sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ..."); 1088 return 0; 1089 } 1090 1091 for (int q = 3; argc >= 4; q++, argc--) { 1092 rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[q], atoll(argv[2])); 1093 if (rc) { 1094 char *msg; 1095 asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]); 1096 cli->sendMsg(ResponseCode::OperationFailed, 1097 msg, false); 1098 free(msg); 1099 return 0; 1100 } 1101 } 1102 sendGenericOkFail(cli, rc); 1103 return 0; 1104 1105 } 1106 if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) { 1107 int rc; 1108 if (argc < 3) { 1109 sendGenericSyntaxError(cli, "removequotas <interface> ..."); 1110 return 0; 1111 } 1112 1113 for (int q = 2; argc >= 3; q++, argc--) { 1114 rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[q]); 1115 if (rc) { 1116 char *msg; 1117 asprintf(&msg, "bandwidth removequotas %s failed", argv[q]); 1118 cli->sendMsg(ResponseCode::OperationFailed, 1119 msg, false); 1120 free(msg); 1121 return 0; 1122 } 1123 } 1124 sendGenericOkFail(cli, rc); 1125 return 0; 1126 1127 } 1128 if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) { 1129 if (argc != 3) { 1130 sendGenericSyntaxError(cli, "removeiquota <interface>"); 1131 return 0; 1132 } 1133 int rc = sBandwidthCtrl->removeInterfaceQuota(argv[2]); 1134 sendGenericOkFail(cli, rc); 1135 return 0; 1136 1137 } 1138 if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) { 1139 if (argc != 4) { 1140 sendGenericSyntaxError(cli, "setiquota <interface> <bytes>"); 1141 return 0; 1142 } 1143 int rc = sBandwidthCtrl->setInterfaceQuota(argv[2], atoll(argv[3])); 1144 sendGenericOkFail(cli, rc); 1145 return 0; 1146 1147 } 1148 if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) { 1149 if (argc < 3) { 1150 sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ..."); 1151 return 0; 1152 } 1153 int rc = sBandwidthCtrl->addNaughtyApps(argc - 2, argv + 2); 1154 sendGenericOkFail(cli, rc); 1155 return 0; 1156 1157 1158 } 1159 if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) { 1160 if (argc < 3) { 1161 sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ..."); 1162 return 0; 1163 } 1164 int rc = sBandwidthCtrl->removeNaughtyApps(argc - 2, argv + 2); 1165 sendGenericOkFail(cli, rc); 1166 return 0; 1167 1168 } 1169 if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) { 1170 if (argc != 3) { 1171 sendGenericSyntaxError(cli, "setglobalalert <bytes>"); 1172 return 0; 1173 } 1174 int rc = sBandwidthCtrl->setGlobalAlert(atoll(argv[2])); 1175 sendGenericOkFail(cli, rc); 1176 return 0; 1177 1178 } 1179 if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) { 1180 if (argc != 4) { 1181 sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>"); 1182 return 0; 1183 } 1184 /* We ignore the interfaces for now. */ 1185 int rc = sBandwidthCtrl->setGlobalAlertInForwardChain(); 1186 sendGenericOkFail(cli, rc); 1187 return 0; 1188 1189 } 1190 if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) { 1191 if (argc != 2) { 1192 sendGenericSyntaxError(cli, "removeglobalalert"); 1193 return 0; 1194 } 1195 int rc = sBandwidthCtrl->removeGlobalAlert(); 1196 sendGenericOkFail(cli, rc); 1197 return 0; 1198 1199 } 1200 if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) { 1201 if (argc != 4) { 1202 sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>"); 1203 return 0; 1204 } 1205 /* We ignore the interfaces for now. */ 1206 int rc = sBandwidthCtrl->removeGlobalAlertInForwardChain(); 1207 sendGenericOkFail(cli, rc); 1208 return 0; 1209 1210 } 1211 if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) { 1212 if (argc != 3) { 1213 sendGenericSyntaxError(cli, "setsharedalert <bytes>"); 1214 return 0; 1215 } 1216 int rc = sBandwidthCtrl->setSharedAlert(atoll(argv[2])); 1217 sendGenericOkFail(cli, rc); 1218 return 0; 1219 1220 } 1221 if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) { 1222 if (argc != 2) { 1223 sendGenericSyntaxError(cli, "removesharedalert"); 1224 return 0; 1225 } 1226 int rc = sBandwidthCtrl->removeSharedAlert(); 1227 sendGenericOkFail(cli, rc); 1228 return 0; 1229 1230 } 1231 if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) { 1232 if (argc != 4) { 1233 sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>"); 1234 return 0; 1235 } 1236 int rc = sBandwidthCtrl->setInterfaceAlert(argv[2], atoll(argv[3])); 1237 sendGenericOkFail(cli, rc); 1238 return 0; 1239 1240 } 1241 if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) { 1242 if (argc != 3) { 1243 sendGenericSyntaxError(cli, "removeinterfacealert <interface>"); 1244 return 0; 1245 } 1246 int rc = sBandwidthCtrl->removeInterfaceAlert(argv[2]); 1247 sendGenericOkFail(cli, rc); 1248 return 0; 1249 1250 } 1251 if (!strcmp(argv[1], "gettetherstats") || !strcmp(argv[1], "gts")) { 1252 BandwidthController::TetherStats tetherStats; 1253 std::string extraProcessingInfo = ""; 1254 if (argc != 4) { 1255 sendGenericSyntaxError(cli, "gettetherstats <interface0> <interface1>"); 1256 return 0; 1257 } 1258 1259 tetherStats.ifaceIn = argv[2]; 1260 tetherStats.ifaceOut = argv[3]; 1261 int rc = sBandwidthCtrl->getTetherStats(tetherStats, extraProcessingInfo); 1262 if (rc) { 1263 extraProcessingInfo.insert(0, "Failed to get tethering stats.\n"); 1264 sendGenericOpFailed(cli, extraProcessingInfo.c_str()); 1265 return 0; 1266 } 1267 1268 char *msg = tetherStats.getStatsLine(); 1269 cli->sendMsg(ResponseCode::TetheringStatsResult, msg, false); 1270 free(msg); 1271 return 0; 1272 1273 } 1274 1275 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false); 1276 return 0; 1277} 1278 1279CommandListener::IdletimerControlCmd::IdletimerControlCmd() : 1280 NetdCommand("idletimer") { 1281} 1282 1283int CommandListener::IdletimerControlCmd::runCommand(SocketClient *cli, int argc, char **argv) { 1284 // TODO(ashish): Change the error statements 1285 if (argc < 2) { 1286 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 1287 return 0; 1288 } 1289 1290 ALOGV("idletimerctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]); 1291 1292 if (!strcmp(argv[1], "enable")) { 1293 if (0 != sIdletimerCtrl->enableIdletimerControl()) { 1294 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 1295 } else { 1296 cli->sendMsg(ResponseCode::CommandOkay, "Enable success", false); 1297 } 1298 return 0; 1299 1300 } 1301 if (!strcmp(argv[1], "disable")) { 1302 if (0 != sIdletimerCtrl->disableIdletimerControl()) { 1303 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 1304 } else { 1305 cli->sendMsg(ResponseCode::CommandOkay, "Disable success", false); 1306 } 1307 return 0; 1308 } 1309 if (!strcmp(argv[1], "add")) { 1310 if (argc != 5) { 1311 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 1312 return 0; 1313 } 1314 if(0 != sIdletimerCtrl->addInterfaceIdletimer( 1315 argv[2], atoi(argv[3]), argv[4])) { 1316 cli->sendMsg(ResponseCode::OperationFailed, "Failed to add interface", false); 1317 } else { 1318 cli->sendMsg(ResponseCode::CommandOkay, "Add success", false); 1319 } 1320 return 0; 1321 } 1322 if (!strcmp(argv[1], "remove")) { 1323 if (argc != 5) { 1324 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 1325 return 0; 1326 } 1327 // ashish: fixme timeout 1328 if (0 != sIdletimerCtrl->removeInterfaceIdletimer( 1329 argv[2], atoi(argv[3]), argv[4])) { 1330 cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove interface", false); 1331 } else { 1332 cli->sendMsg(ResponseCode::CommandOkay, "Remove success", false); 1333 } 1334 return 0; 1335 } 1336 1337 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown idletimer cmd", false); 1338 return 0; 1339} 1340