CommandListener.cpp revision 31ea0b03afeedd17f703b7a6d1e5c9feb2d6000d
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 LOGD("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 LOGD("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 LOGD("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 LOGD("broadcast flag ignored"); 358 } else if (!strcmp(flag, "multicast")) { 359 LOGD("multicast flag ignored"); 360 } else { 361 cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false); 362 ifc_close(); 363 return 0; 364 } 365 } 366 367 cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false); 368 ifc_close(); 369 return 0; 370 } else if (!strcmp(argv[1], "clearaddrs")) { 371 // arglist: iface 372 LOGD("Clearing all IP addresses on %s", argv[2]); 373 374 ifc_clear_addresses(argv[2]); 375 376 cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false); 377 return 0; 378 } else if (!strcmp(argv[1], "ipv6privacyextensions")) { 379 if (argc != 4) { 380 cli->sendMsg(ResponseCode::CommandSyntaxError, 381 "Usage: interface ipv6privacyextensions <interface> <enable|disable>", 382 false); 383 return 0; 384 } 385 386 char *tmp; 387 asprintf(&tmp, "/proc/sys/net/ipv6/conf/%s/use_tempaddr", argv[2]); 388 389 if (writeFile(tmp, !strncmp(argv[3], "enable", 7) ? "2" : "0", 1) < 0) { 390 free(tmp); 391 cli->sendMsg(ResponseCode::OperationFailed, 392 "Failed to set ipv6 privacy extensions", true); 393 return 0; 394 } 395 396 free(tmp); 397 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false); 398 return 0; 399 } else if (!strcmp(argv[1], "ipv6")) { 400 if (argc != 4) { 401 cli->sendMsg(ResponseCode::CommandSyntaxError, 402 "Usage: interface ipv6 <interface> <enable|disable>", 403 false); 404 return 0; 405 } 406 407 char *tmp; 408 asprintf(&tmp, "/proc/sys/net/ipv6/conf/%s/disable_ipv6", argv[2]); 409 410 if (writeFile(tmp, !strncmp(argv[3], "enable", 7) ? "0" : "1", 1) < 0) { 411 free(tmp); 412 cli->sendMsg(ResponseCode::OperationFailed, 413 "Failed to change IPv6 state", true); 414 return 0; 415 } 416 417 free(tmp); 418 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false); 419 return 0; 420 } else { 421 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false); 422 return 0; 423 } 424 } 425 return 0; 426} 427 428 429CommandListener::ListTtysCmd::ListTtysCmd() : 430 NetdCommand("list_ttys") { 431} 432 433int CommandListener::ListTtysCmd::runCommand(SocketClient *cli, 434 int argc, char **argv) { 435 TtyCollection *tlist = sPppCtrl->getTtyList(); 436 TtyCollection::iterator it; 437 438 for (it = tlist->begin(); it != tlist->end(); ++it) { 439 cli->sendMsg(ResponseCode::TtyListResult, *it, false); 440 } 441 442 cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false); 443 return 0; 444} 445 446CommandListener::IpFwdCmd::IpFwdCmd() : 447 NetdCommand("ipfwd") { 448} 449 450int CommandListener::IpFwdCmd::runCommand(SocketClient *cli, 451 int argc, char **argv) { 452 int rc = 0; 453 454 if (argc < 2) { 455 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 456 return 0; 457 } 458 459 if (!strcmp(argv[1], "status")) { 460 char *tmp = NULL; 461 462 asprintf(&tmp, "Forwarding %s", (sTetherCtrl->getIpFwdEnabled() ? "enabled" : "disabled")); 463 cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false); 464 free(tmp); 465 return 0; 466 } else if (!strcmp(argv[1], "enable")) { 467 rc = sTetherCtrl->setIpFwdEnabled(true); 468 } else if (!strcmp(argv[1], "disable")) { 469 rc = sTetherCtrl->setIpFwdEnabled(false); 470 } else { 471 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false); 472 return 0; 473 } 474 475 if (!rc) { 476 cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false); 477 } else { 478 cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true); 479 } 480 481 return 0; 482} 483 484CommandListener::TetherCmd::TetherCmd() : 485 NetdCommand("tether") { 486} 487 488int CommandListener::TetherCmd::runCommand(SocketClient *cli, 489 int argc, char **argv) { 490 int rc = 0; 491 492 if (argc < 2) { 493 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 494 return 0; 495 } 496 497 if (!strcmp(argv[1], "stop")) { 498 rc = sTetherCtrl->stopTethering(); 499 } else if (!strcmp(argv[1], "status")) { 500 char *tmp = NULL; 501 502 asprintf(&tmp, "Tethering services %s", 503 (sTetherCtrl->isTetheringStarted() ? "started" : "stopped")); 504 cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false); 505 free(tmp); 506 return 0; 507 } else { 508 /* 509 * These commands take a minimum of 4 arguments 510 */ 511 if (argc < 4) { 512 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 513 return 0; 514 } 515 516 if (!strcmp(argv[1], "start")) { 517 if (argc % 2 == 1) { 518 cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false); 519 return 0; 520 } 521 522 int num_addrs = argc - 2; 523 int arg_index = 2; 524 int array_index = 0; 525 in_addr *addrs = (in_addr *)malloc(sizeof(in_addr) * num_addrs); 526 while (array_index < num_addrs) { 527 if (!inet_aton(argv[arg_index++], &(addrs[array_index++]))) { 528 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false); 529 free(addrs); 530 return 0; 531 } 532 } 533 rc = sTetherCtrl->startTethering(num_addrs, addrs); 534 free(addrs); 535 } else if (!strcmp(argv[1], "interface")) { 536 if (!strcmp(argv[2], "add")) { 537 rc = sTetherCtrl->tetherInterface(argv[3]); 538 } else if (!strcmp(argv[2], "remove")) { 539 rc = sTetherCtrl->untetherInterface(argv[3]); 540 } else if (!strcmp(argv[2], "list")) { 541 InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList(); 542 InterfaceCollection::iterator it; 543 544 for (it = ilist->begin(); it != ilist->end(); ++it) { 545 cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false); 546 } 547 } else { 548 cli->sendMsg(ResponseCode::CommandParameterError, 549 "Unknown tether interface operation", false); 550 return 0; 551 } 552 } else if (!strcmp(argv[1], "dns")) { 553 if (!strcmp(argv[2], "set")) { 554 rc = sTetherCtrl->setDnsForwarders(&argv[3], argc - 3); 555 } else if (!strcmp(argv[2], "list")) { 556 NetAddressCollection *dlist = sTetherCtrl->getDnsForwarders(); 557 NetAddressCollection::iterator it; 558 559 for (it = dlist->begin(); it != dlist->end(); ++it) { 560 cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, inet_ntoa(*it), false); 561 } 562 } else { 563 cli->sendMsg(ResponseCode::CommandParameterError, 564 "Unknown tether interface operation", false); 565 return 0; 566 } 567 } else { 568 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false); 569 return 0; 570 } 571 } 572 573 if (!rc) { 574 cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false); 575 } else { 576 cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true); 577 } 578 579 return 0; 580} 581 582CommandListener::NatCmd::NatCmd() : 583 NetdCommand("nat") { 584} 585 586int CommandListener::NatCmd::runCommand(SocketClient *cli, 587 int argc, char **argv) { 588 int rc = 0; 589 590 if (argc < 5) { 591 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 592 return 0; 593 } 594 595 if (!strcmp(argv[1], "enable")) { 596 rc = sNatCtrl->enableNat(argc, argv); 597 if(!rc) { 598 /* Ignore ifaces for now. */ 599 rc = sBandwidthCtrl->setGlobalAlertInForwardChain(); 600 } 601 } else if (!strcmp(argv[1], "disable")) { 602 /* Ignore ifaces for now. */ 603 rc = sBandwidthCtrl->removeGlobalAlertInForwardChain(); 604 rc |= sNatCtrl->disableNat(argc, argv); 605 } else { 606 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false); 607 return 0; 608 } 609 610 if (!rc) { 611 cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false); 612 } else { 613 cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true); 614 } 615 616 return 0; 617} 618 619CommandListener::PppdCmd::PppdCmd() : 620 NetdCommand("pppd") { 621} 622 623int CommandListener::PppdCmd::runCommand(SocketClient *cli, 624 int argc, char **argv) { 625 int rc = 0; 626 627 if (argc < 3) { 628 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 629 return 0; 630 } 631 632 if (!strcmp(argv[1], "attach")) { 633 struct in_addr l, r, dns1, dns2; 634 635 memset(&dns1, sizeof(struct in_addr), 0); 636 memset(&dns2, sizeof(struct in_addr), 0); 637 638 if (!inet_aton(argv[3], &l)) { 639 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false); 640 return 0; 641 } 642 if (!inet_aton(argv[4], &r)) { 643 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false); 644 return 0; 645 } 646 if ((argc > 3) && (!inet_aton(argv[5], &dns1))) { 647 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false); 648 return 0; 649 } 650 if ((argc > 4) && (!inet_aton(argv[6], &dns2))) { 651 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false); 652 return 0; 653 } 654 rc = sPppCtrl->attachPppd(argv[2], l, r, dns1, dns2); 655 } else if (!strcmp(argv[1], "detach")) { 656 rc = sPppCtrl->detachPppd(argv[2]); 657 } else { 658 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false); 659 return 0; 660 } 661 662 if (!rc) { 663 cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false); 664 } else { 665 cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true); 666 } 667 668 return 0; 669} 670 671CommandListener::PanCmd::PanCmd() : 672 NetdCommand("pan") { 673} 674 675int CommandListener::PanCmd::runCommand(SocketClient *cli, 676 int argc, char **argv) { 677 int rc = 0; 678 679 if (argc < 2) { 680 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 681 return 0; 682 } 683 684 if (!strcmp(argv[1], "start")) { 685 rc = sPanCtrl->startPan(); 686 } else if (!strcmp(argv[1], "stop")) { 687 rc = sPanCtrl->stopPan(); 688 } else if (!strcmp(argv[1], "status")) { 689 char *tmp = NULL; 690 691 asprintf(&tmp, "Pan services %s", 692 (sPanCtrl->isPanStarted() ? "started" : "stopped")); 693 cli->sendMsg(ResponseCode::PanStatusResult, tmp, false); 694 free(tmp); 695 return 0; 696 } else { 697 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pan cmd", false); 698 return 0; 699 } 700 701 if (!rc) { 702 cli->sendMsg(ResponseCode::CommandOkay, "Pan operation succeeded", false); 703 } else { 704 cli->sendMsg(ResponseCode::OperationFailed, "Pan operation failed", true); 705 } 706 707 return 0; 708} 709 710CommandListener::SoftapCmd::SoftapCmd() : 711 NetdCommand("softap") { 712} 713 714int CommandListener::SoftapCmd::runCommand(SocketClient *cli, 715 int argc, char **argv) { 716 int rc = 0, flag = 0; 717 char *retbuf = NULL; 718 719 if (argc < 2) { 720 cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Missing argument", false); 721 return 0; 722 } 723 724 if (!strcmp(argv[1], "start")) { 725 rc = sSoftapCtrl->startDriver(argv[2]); 726 } else if (!strcmp(argv[1], "stop")) { 727 rc = sSoftapCtrl->stopDriver(argv[2]); 728 } else if (!strcmp(argv[1], "startap")) { 729 rc = sSoftapCtrl->startSoftap(); 730 } else if (!strcmp(argv[1], "stopap")) { 731 rc = sSoftapCtrl->stopSoftap(); 732 } else if (!strcmp(argv[1], "fwreload")) { 733 rc = sSoftapCtrl->fwReloadSoftap(argc, argv); 734 } else if (!strcmp(argv[1], "clients")) { 735 rc = sSoftapCtrl->clientsSoftap(&retbuf); 736 if (!rc) { 737 cli->sendMsg(ResponseCode::CommandOkay, retbuf, false); 738 free(retbuf); 739 return 0; 740 } 741 } else if (!strcmp(argv[1], "status")) { 742 asprintf(&retbuf, "Softap service %s", 743 (sSoftapCtrl->isSoftapStarted() ? "started" : "stopped")); 744 cli->sendMsg(ResponseCode::SoftapStatusResult, retbuf, false); 745 free(retbuf); 746 return 0; 747 } else if (!strcmp(argv[1], "set")) { 748 rc = sSoftapCtrl->setSoftap(argc, argv); 749 } else { 750 cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Unknown cmd", false); 751 return 0; 752 } 753 754 if (!rc) { 755 cli->sendMsg(ResponseCode::CommandOkay, "Softap operation succeeded", false); 756 } else { 757 cli->sendMsg(ResponseCode::OperationFailed, "Softap operation failed", true); 758 } 759 760 return 0; 761} 762 763CommandListener::ResolverCmd::ResolverCmd() : 764 NetdCommand("resolver") { 765} 766 767int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **argv) { 768 int rc = 0; 769 struct in_addr addr; 770 771 if (argc < 2) { 772 cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false); 773 return 0; 774 } 775 776 if (!strcmp(argv[1], "setdefaultif")) { // "resolver setdefaultif <iface>" 777 if (argc == 3) { 778 rc = sResolverCtrl->setDefaultInterface(argv[2]); 779 } else { 780 cli->sendMsg(ResponseCode::CommandSyntaxError, 781 "Wrong number of arguments to resolver setdefaultif", false); 782 return 0; 783 } 784 } else if (!strcmp(argv[1], "setifdns")) { // "resolver setifdns <iface> <dns1> <dns2> ..." 785 if (argc >= 4) { 786 rc = sResolverCtrl->setInterfaceDnsServers(argv[2], &argv[3], argc - 3); 787 } else { 788 cli->sendMsg(ResponseCode::CommandSyntaxError, 789 "Wrong number of arguments to resolver setifdns", false); 790 return 0; 791 } 792 793 // set the address of the interface to which the name servers 794 // are bound. Required in order to bind to right interface when 795 // doing the dns query. 796 if (!rc) { 797 ifc_init(); 798 ifc_get_info(argv[2], &addr.s_addr, NULL, 0); 799 800 rc = sResolverCtrl->setInterfaceAddress(argv[2], &addr); 801 } 802 } else if (!strcmp(argv[1], "flushdefaultif")) { // "resolver flushdefaultif" 803 if (argc == 2) { 804 rc = sResolverCtrl->flushDefaultDnsCache(); 805 } else { 806 cli->sendMsg(ResponseCode::CommandSyntaxError, 807 "Wrong number of arguments to resolver flushdefaultif", false); 808 return 0; 809 } 810 } else if (!strcmp(argv[1], "flushif")) { // "resolver flushif <iface>" 811 if (argc == 3) { 812 rc = sResolverCtrl->flushInterfaceDnsCache(argv[2]); 813 } else { 814 cli->sendMsg(ResponseCode::CommandSyntaxError, 815 "Wrong number of arguments to resolver setdefaultif", false); 816 return 0; 817 } 818 } else { 819 cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false); 820 return 0; 821 } 822 823 if (!rc) { 824 cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false); 825 } else { 826 cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true); 827 } 828 829 return 0; 830} 831 832int CommandListener::readInterfaceCounters(const char *iface, unsigned long *rx, unsigned long *tx) { 833 FILE *fp = fopen("/proc/net/dev", "r"); 834 if (!fp) { 835 LOGE("Failed to open /proc/net/dev (%s)", strerror(errno)); 836 return -1; 837 } 838 839 char buffer[512]; 840 841 fgets(buffer, sizeof(buffer), fp); // Header 1 842 fgets(buffer, sizeof(buffer), fp); // Header 2 843 while(fgets(buffer, sizeof(buffer), fp)) { 844 buffer[strlen(buffer)-1] = '\0'; 845 846 char name[31]; 847 unsigned long d; 848 sscanf(buffer, "%30s %lu %lu %lu %lu %lu %lu %lu %lu %lu", 849 name, rx, &d, &d, &d, &d, &d, &d, &d, tx); 850 char *rxString = strchr(name, ':'); 851 *rxString = '\0'; 852 rxString++; 853 // when the rx count gets too big it changes from "name: 999" to "name:1000" 854 // and the sscanf munge the two together. Detect that and fix 855 // note that all the %lu will be off by one and the real tx value will be in d 856 if (*rxString != '\0') { 857 *tx = d; 858 sscanf(rxString, "%20lu", rx); 859 } 860 if (strcmp(name, iface)) { 861 continue; 862 } 863 fclose(fp); 864 return 0; 865 } 866 867 fclose(fp); 868 *rx = 0; 869 *tx = 0; 870 return 0; 871} 872 873CommandListener::BandwidthControlCmd::BandwidthControlCmd() : 874 NetdCommand("bandwidth") { 875} 876 877void CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) { 878 char *msg; 879 asprintf(&msg, "Usage: bandwidth %s", usageMsg); 880 cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false); 881 free(msg); 882} 883 884void CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) { 885 if (!cond) { 886 cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false); 887 } else { 888 cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false); 889 } 890} 891 892void CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) { 893 cli->sendMsg(ResponseCode::OperationFailed, errMsg, false); 894} 895 896int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) { 897 if (argc < 2) { 898 sendGenericSyntaxError(cli, "<cmds> <args...>"); 899 return 0; 900 } 901 902 ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]); 903 904 if (!strcmp(argv[1], "enable")) { 905 int rc = sBandwidthCtrl->enableBandwidthControl(); 906 sendGenericOkFail(cli, rc); 907 return 0; 908 909 } 910 if (!strcmp(argv[1], "disable")) { 911 int rc = sBandwidthCtrl->disableBandwidthControl(); 912 sendGenericOkFail(cli, rc); 913 return 0; 914 915 } 916 if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) { 917 if (argc != 3) { 918 sendGenericSyntaxError(cli, "removequota <interface>"); 919 return 0; 920 } 921 int rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[2]); 922 sendGenericOkFail(cli, rc); 923 return 0; 924 925 } 926 if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) { 927 int64_t bytes; 928 if (argc != 2) { 929 sendGenericSyntaxError(cli, "getquota"); 930 return 0; 931 } 932 int rc = sBandwidthCtrl->getInterfaceSharedQuota(&bytes); 933 if (rc) { 934 sendGenericOpFailed(cli, "Failed to get quota"); 935 return 0; 936 } 937 938 char *msg; 939 asprintf(&msg, "%lld", bytes); 940 cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false); 941 free(msg); 942 return 0; 943 944 } 945 if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) { 946 int64_t bytes; 947 if (argc != 3) { 948 sendGenericSyntaxError(cli, "getiquota <iface>"); 949 return 0; 950 } 951 952 int rc = sBandwidthCtrl->getInterfaceQuota(argv[2], &bytes); 953 if (rc) { 954 sendGenericOpFailed(cli, "Failed to get quota"); 955 return 0; 956 } 957 char *msg; 958 asprintf(&msg, "%lld", bytes); 959 cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false); 960 free(msg); 961 return 0; 962 963 } 964 if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) { 965 if (argc != 4) { 966 sendGenericSyntaxError(cli, "setquota <interface> <bytes>"); 967 return 0; 968 } 969 int rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[2], atoll(argv[3])); 970 sendGenericOkFail(cli, rc); 971 return 0; 972 } 973 if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) { 974 int rc; 975 if (argc < 4) { 976 sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ..."); 977 return 0; 978 } 979 980 for (int q = 3; argc >= 4; q++, argc--) { 981 rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[q], atoll(argv[2])); 982 if (rc) { 983 char *msg; 984 asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]); 985 cli->sendMsg(ResponseCode::OperationFailed, 986 msg, false); 987 free(msg); 988 return 0; 989 } 990 } 991 sendGenericOkFail(cli, rc); 992 return 0; 993 994 } 995 if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) { 996 int rc; 997 if (argc < 3) { 998 sendGenericSyntaxError(cli, "removequotas <interface> ..."); 999 return 0; 1000 } 1001 1002 for (int q = 2; argc >= 3; q++, argc--) { 1003 rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[q]); 1004 if (rc) { 1005 char *msg; 1006 asprintf(&msg, "bandwidth removequotas %s failed", argv[q]); 1007 cli->sendMsg(ResponseCode::OperationFailed, 1008 msg, false); 1009 free(msg); 1010 return 0; 1011 } 1012 } 1013 sendGenericOkFail(cli, rc); 1014 return 0; 1015 1016 } 1017 if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) { 1018 if (argc != 3) { 1019 sendGenericSyntaxError(cli, "removeiquota <interface>"); 1020 return 0; 1021 } 1022 int rc = sBandwidthCtrl->removeInterfaceQuota(argv[2]); 1023 sendGenericOkFail(cli, rc); 1024 return 0; 1025 1026 } 1027 if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) { 1028 if (argc != 4) { 1029 sendGenericSyntaxError(cli, "setiquota <interface> <bytes>"); 1030 return 0; 1031 } 1032 int rc = sBandwidthCtrl->setInterfaceQuota(argv[2], atoll(argv[3])); 1033 sendGenericOkFail(cli, rc); 1034 return 0; 1035 1036 } 1037 if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) { 1038 if (argc < 3) { 1039 sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ..."); 1040 return 0; 1041 } 1042 int rc = sBandwidthCtrl->addNaughtyApps(argc - 2, argv + 2); 1043 sendGenericOkFail(cli, rc); 1044 return 0; 1045 1046 1047 } 1048 if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) { 1049 if (argc < 3) { 1050 sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ..."); 1051 return 0; 1052 } 1053 int rc = sBandwidthCtrl->removeNaughtyApps(argc - 2, argv + 2); 1054 sendGenericOkFail(cli, rc); 1055 return 0; 1056 1057 } 1058 if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) { 1059 if (argc != 3) { 1060 sendGenericSyntaxError(cli, "setglobalalert <bytes>"); 1061 return 0; 1062 } 1063 int rc = sBandwidthCtrl->setGlobalAlert(atoll(argv[2])); 1064 sendGenericOkFail(cli, rc); 1065 return 0; 1066 1067 } 1068 if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) { 1069 if (argc != 4) { 1070 sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>"); 1071 return 0; 1072 } 1073 /* We ignore the interfaces for now. */ 1074 int rc = sBandwidthCtrl->setGlobalAlertInForwardChain(); 1075 sendGenericOkFail(cli, rc); 1076 return 0; 1077 1078 } 1079 if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) { 1080 if (argc != 2) { 1081 sendGenericSyntaxError(cli, "removeglobalalert"); 1082 return 0; 1083 } 1084 int rc = sBandwidthCtrl->removeGlobalAlert(); 1085 sendGenericOkFail(cli, rc); 1086 return 0; 1087 1088 } 1089 if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) { 1090 if (argc != 4) { 1091 sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>"); 1092 return 0; 1093 } 1094 /* We ignore the interfaces for now. */ 1095 int rc = sBandwidthCtrl->removeGlobalAlertInForwardChain(); 1096 sendGenericOkFail(cli, rc); 1097 return 0; 1098 1099 } 1100 if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) { 1101 if (argc != 3) { 1102 sendGenericSyntaxError(cli, "setsharedalert <bytes>"); 1103 return 0; 1104 } 1105 int rc = sBandwidthCtrl->setSharedAlert(atoll(argv[2])); 1106 sendGenericOkFail(cli, rc); 1107 return 0; 1108 1109 } 1110 if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) { 1111 if (argc != 2) { 1112 sendGenericSyntaxError(cli, "removesharedalert"); 1113 return 0; 1114 } 1115 int rc = sBandwidthCtrl->removeSharedAlert(); 1116 sendGenericOkFail(cli, rc); 1117 return 0; 1118 1119 } 1120 if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) { 1121 if (argc != 4) { 1122 sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>"); 1123 return 0; 1124 } 1125 int rc = sBandwidthCtrl->setInterfaceAlert(argv[2], atoll(argv[3])); 1126 sendGenericOkFail(cli, rc); 1127 return 0; 1128 1129 } 1130 if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) { 1131 if (argc != 3) { 1132 sendGenericSyntaxError(cli, "removeinterfacealert <interface>"); 1133 return 0; 1134 } 1135 int rc = sBandwidthCtrl->removeInterfaceAlert(argv[2]); 1136 sendGenericOkFail(cli, rc); 1137 return 0; 1138 1139 } 1140 if (!strcmp(argv[1], "gettetherstats") || !strcmp(argv[1], "gts")) { 1141 BandwidthController::TetherStats tetherStats; 1142 std::string extraProcessingInfo = ""; 1143 if (argc != 4) { 1144 sendGenericSyntaxError(cli, "gettetherstats <interface0> <interface1>"); 1145 return 0; 1146 } 1147 1148 tetherStats.ifaceIn = argv[2]; 1149 tetherStats.ifaceOut = argv[3]; 1150 int rc = sBandwidthCtrl->getTetherStats(tetherStats, extraProcessingInfo); 1151 if (rc) { 1152 extraProcessingInfo.insert(0, "Failed to get tethering stats.\n"); 1153 sendGenericOpFailed(cli, extraProcessingInfo.c_str()); 1154 return 0; 1155 } 1156 1157 char *msg = tetherStats.getStatsLine(); 1158 cli->sendMsg(ResponseCode::TetheringStatsResult, msg, false); 1159 free(msg); 1160 return 0; 1161 1162 } 1163 1164 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false); 1165 return 0; 1166} 1167