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