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