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