CommandListener.cpp revision 4a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11
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#include <stdlib.h> 18#include <sys/socket.h> 19#include <sys/types.h> 20#include <netinet/in.h> 21#include <arpa/inet.h> 22#include <dirent.h> 23#include <errno.h> 24#include <string.h> 25 26#include <linux/if.h> 27 28#define LOG_TAG "CommandListener" 29#include <cutils/log.h> 30 31#include <sysutils/SocketClient.h> 32 33#include "CommandListener.h" 34#include "ResponseCode.h" 35#include "ThrottleController.h" 36#include "BandwidthController.h" 37 38 39extern "C" int ifc_init(void); 40extern "C" int ifc_get_hwaddr(const char *name, void *ptr); 41extern "C" int ifc_get_info(const char *name, in_addr_t *addr, int *prefixLength, unsigned *flags); 42extern "C" int ifc_set_addr(const char *name, in_addr_t addr); 43extern "C" int ifc_set_prefixLength(const char *name, int prefixLength); 44extern "C" int ifc_up(const char *name); 45extern "C" int ifc_down(const char *name); 46extern "C" int ifc_add_route(const char *name, const char *dst, int prefix_length, const char *gw); 47extern "C" int ifc_remove_route(const char *name, const char *dst, int p_length, const char *gw); 48 49TetherController *CommandListener::sTetherCtrl = NULL; 50NatController *CommandListener::sNatCtrl = NULL; 51PppController *CommandListener::sPppCtrl = NULL; 52PanController *CommandListener::sPanCtrl = NULL; 53SoftapController *CommandListener::sSoftapCtrl = NULL; 54UsbController *CommandListener::sUsbCtrl = NULL; 55BandwidthController * CommandListener::sBandwidthCtrl = NULL; 56 57CommandListener::CommandListener() : 58 FrameworkListener("netd") { 59 registerCmd(new InterfaceCmd()); 60 registerCmd(new IpFwdCmd()); 61 registerCmd(new TetherCmd()); 62 registerCmd(new NatCmd()); 63 registerCmd(new ListTtysCmd()); 64 registerCmd(new PppdCmd()); 65 registerCmd(new PanCmd()); 66 registerCmd(new SoftapCmd()); 67 registerCmd(new UsbCmd()); 68 registerCmd(new BandwidthControlCmd()); 69 70 if (!sTetherCtrl) 71 sTetherCtrl = new TetherController(); 72 if (!sNatCtrl) 73 sNatCtrl = new NatController(); 74 if (!sPppCtrl) 75 sPppCtrl = new PppController(); 76 if (!sPanCtrl) 77 sPanCtrl = new PanController(); 78 if (!sSoftapCtrl) 79 sSoftapCtrl = new SoftapController(); 80 if (!sUsbCtrl) 81 sUsbCtrl = new UsbController(); 82 if (!sBandwidthCtrl) 83 sBandwidthCtrl = new BandwidthController(); 84} 85 86CommandListener::InterfaceCmd::InterfaceCmd() : 87 NetdCommand("interface") { 88} 89 90int CommandListener::InterfaceCmd::runCommand(SocketClient *cli, 91 int argc, char **argv) { 92 if (argc < 2) { 93 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 94 return 0; 95 } 96 97 if (!strcmp(argv[1], "list")) { 98 DIR *d; 99 struct dirent *de; 100 101 if (!(d = opendir("/sys/class/net"))) { 102 cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true); 103 return 0; 104 } 105 106 while((de = readdir(d))) { 107 if (de->d_name[0] == '.') 108 continue; 109 cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false); 110 } 111 closedir(d); 112 cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false); 113 return 0; 114 } else if (!strcmp(argv[1], "readrxcounter")) { 115 if (argc != 3) { 116 cli->sendMsg(ResponseCode::CommandSyntaxError, 117 "Usage: interface readrxcounter <interface>", false); 118 return 0; 119 } 120 unsigned long rx = 0, tx = 0; 121 if (readInterfaceCounters(argv[2], &rx, &tx)) { 122 cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true); 123 return 0; 124 } 125 126 char *msg; 127 asprintf(&msg, "%lu", rx); 128 cli->sendMsg(ResponseCode::InterfaceRxCounterResult, msg, false); 129 free(msg); 130 131 return 0; 132 } else if (!strcmp(argv[1], "readtxcounter")) { 133 if (argc != 3) { 134 cli->sendMsg(ResponseCode::CommandSyntaxError, 135 "Usage: interface readtxcounter <interface>", false); 136 return 0; 137 } 138 unsigned long rx = 0, tx = 0; 139 if (readInterfaceCounters(argv[2], &rx, &tx)) { 140 cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true); 141 return 0; 142 } 143 144 char *msg = NULL; 145 asprintf(&msg, "%lu", tx); 146 cli->sendMsg(ResponseCode::InterfaceTxCounterResult, msg, false); 147 free(msg); 148 return 0; 149 } else if (!strcmp(argv[1], "getthrottle")) { 150 if (argc != 4 || (argc == 4 && (strcmp(argv[3], "rx") && (strcmp(argv[3], "tx"))))) { 151 cli->sendMsg(ResponseCode::CommandSyntaxError, 152 "Usage: interface getthrottle <interface> <rx|tx>", false); 153 return 0; 154 } 155 int val = 0; 156 int rc = 0; 157 int voldRc = ResponseCode::InterfaceRxThrottleResult; 158 159 if (!strcmp(argv[3], "rx")) { 160 rc = ThrottleController::getInterfaceRxThrottle(argv[2], &val); 161 } else { 162 rc = ThrottleController::getInterfaceTxThrottle(argv[2], &val); 163 voldRc = ResponseCode::InterfaceTxThrottleResult; 164 } 165 if (rc) { 166 cli->sendMsg(ResponseCode::OperationFailed, "Failed to get throttle", true); 167 } else { 168 char *msg = NULL; 169 asprintf(&msg, "%u", val); 170 cli->sendMsg(voldRc, msg, false); 171 free(msg); 172 return 0; 173 } 174 return 0; 175 } else if (!strcmp(argv[1], "setthrottle")) { 176 if (argc != 5) { 177 cli->sendMsg(ResponseCode::CommandSyntaxError, 178 "Usage: interface setthrottle <interface> <rx_kbps> <tx_kbps>", false); 179 return 0; 180 } 181 if (ThrottleController::setInterfaceThrottle(argv[2], atoi(argv[3]), atoi(argv[4]))) { 182 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set throttle", true); 183 } else { 184 cli->sendMsg(ResponseCode::CommandOkay, "Interface throttling set", false); 185 } 186 return 0; 187 } else { 188 /* 189 * These commands take a minimum of 3 arguments 190 */ 191 if (argc < 3) { 192 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 193 return 0; 194 } 195 196 if (!strcmp(argv[1], "route")) { 197 int prefix_length = 0; 198 if (argc < 7) { 199 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 200 return 0; 201 } 202 if (sscanf(argv[5], "%d", &prefix_length) != 1) { 203 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid route prefix", false); 204 return 0; 205 } 206 if (!strcmp(argv[2], "add")) { 207 if (ifc_add_route(argv[3], argv[4], prefix_length, argv[6])) { 208 cli->sendMsg(ResponseCode::OperationFailed, "Failed to add route", true); 209 } else { 210 cli->sendMsg(ResponseCode::CommandOkay, "Route added", false); 211 } 212 } else if (!strcmp(argv[2], "remove")) { 213 if (ifc_remove_route(argv[3], argv[4], prefix_length, argv[6])) { 214 cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove route", true); 215 } else { 216 cli->sendMsg(ResponseCode::CommandOkay, "Route removed", false); 217 } 218 } else { 219 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false); 220 } 221 return 0; 222 } 223 224 if (!strcmp(argv[1], "getcfg")) { 225 struct in_addr addr; 226 int prefixLength; 227 unsigned char hwaddr[6]; 228 unsigned flags = 0; 229 230 ifc_init(); 231 memset(hwaddr, 0, sizeof(hwaddr)); 232 233 if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) { 234 cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true); 235 return 0; 236 } 237 238 if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) { 239 LOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno)); 240 } 241 242 char *addr_s = strdup(inet_ntoa(addr)); 243 const char *updown, *brdcst, *loopbk, *ppp, *running, *multi; 244 245 updown = (flags & IFF_UP) ? "up" : "down"; 246 brdcst = (flags & IFF_BROADCAST) ? " broadcast" : ""; 247 loopbk = (flags & IFF_LOOPBACK) ? " loopback" : ""; 248 ppp = (flags & IFF_POINTOPOINT) ? " point-to-point" : ""; 249 running = (flags & IFF_RUNNING) ? " running" : ""; 250 multi = (flags & IFF_MULTICAST) ? " multicast" : ""; 251 252 char *flag_s; 253 254 asprintf(&flag_s, "[%s%s%s%s%s%s]", updown, brdcst, loopbk, ppp, running, multi); 255 256 char *msg = NULL; 257 asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %d %s", 258 hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5], 259 addr_s, prefixLength, flag_s); 260 261 cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false); 262 263 free(addr_s); 264 free(flag_s); 265 free(msg); 266 return 0; 267 } else if (!strcmp(argv[1], "setcfg")) { 268 // arglist: iface addr prefixLength [flags] 269 if (argc < 5) { 270 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 271 return 0; 272 } 273 LOGD("Setting iface cfg"); 274 275 struct in_addr addr; 276 unsigned flags = 0; 277 278 if (!inet_aton(argv[3], &addr)) { 279 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false); 280 return 0; 281 } 282 283 ifc_init(); 284 if (ifc_set_addr(argv[2], addr.s_addr)) { 285 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true); 286 return 0; 287 } 288 289 if (ifc_set_prefixLength(argv[2], atoi(argv[4]))) { 290 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set prefixLength", true); 291 return 0; 292 } 293 294 /* Process flags */ 295 /* read from "[XX" arg to "YY]" arg */ 296 bool bStarted = false; 297 for (int i = 5; i < argc; i++) { 298 char *flag = argv[i]; 299 if (!bStarted) { 300 if (*flag == '[') { 301 flag++; 302 bStarted = true; 303 } else { 304 continue; 305 } 306 } 307 int len = strlen(flag); 308 if (flag[len-1] == ']') { 309 i = argc; // stop after this loop 310 flag[len-1] = 0; 311 } 312 if (!strcmp(flag, "up")) { 313 LOGD("Trying to bring up %s", argv[2]); 314 if (ifc_up(argv[2])) { 315 LOGE("Error upping interface"); 316 cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true); 317 return 0; 318 } 319 } else if (!strcmp(flag, "down")) { 320 LOGD("Trying to bring down %s", argv[2]); 321 if (ifc_down(argv[2])) { 322 LOGE("Error downing interface"); 323 cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true); 324 return 0; 325 } 326 } else if (!strcmp(flag, "broadcast")) { 327 LOGD("broadcast flag ignored"); 328 } else if (!strcmp(flag, "multicast")) { 329 LOGD("multicast flag ignored"); 330 } else { 331 cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false); 332 return 0; 333 } 334 } 335 cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false); 336 return 0; 337 } else { 338 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false); 339 return 0; 340 } 341 } 342 return 0; 343} 344 345 346CommandListener::ListTtysCmd::ListTtysCmd() : 347 NetdCommand("list_ttys") { 348} 349 350int CommandListener::ListTtysCmd::runCommand(SocketClient *cli, 351 int argc, char **argv) { 352 TtyCollection *tlist = sPppCtrl->getTtyList(); 353 TtyCollection::iterator it; 354 355 for (it = tlist->begin(); it != tlist->end(); ++it) { 356 cli->sendMsg(ResponseCode::TtyListResult, *it, false); 357 } 358 359 cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false); 360 return 0; 361} 362 363CommandListener::IpFwdCmd::IpFwdCmd() : 364 NetdCommand("ipfwd") { 365} 366 367int CommandListener::IpFwdCmd::runCommand(SocketClient *cli, 368 int argc, char **argv) { 369 int rc = 0; 370 371 if (argc < 2) { 372 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 373 return 0; 374 } 375 376 if (!strcmp(argv[1], "status")) { 377 char *tmp = NULL; 378 379 asprintf(&tmp, "Forwarding %s", (sTetherCtrl->getIpFwdEnabled() ? "enabled" : "disabled")); 380 cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false); 381 free(tmp); 382 return 0; 383 } else if (!strcmp(argv[1], "enable")) { 384 rc = sTetherCtrl->setIpFwdEnabled(true); 385 } else if (!strcmp(argv[1], "disable")) { 386 rc = sTetherCtrl->setIpFwdEnabled(false); 387 } else { 388 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false); 389 return 0; 390 } 391 392 if (!rc) { 393 cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false); 394 } else { 395 cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true); 396 } 397 398 return 0; 399} 400 401CommandListener::TetherCmd::TetherCmd() : 402 NetdCommand("tether") { 403} 404 405int CommandListener::TetherCmd::runCommand(SocketClient *cli, 406 int argc, char **argv) { 407 int rc = 0; 408 409 if (argc < 2) { 410 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 411 return 0; 412 } 413 414 if (!strcmp(argv[1], "stop")) { 415 rc = sTetherCtrl->stopTethering(); 416 } else if (!strcmp(argv[1], "status")) { 417 char *tmp = NULL; 418 419 asprintf(&tmp, "Tethering services %s", 420 (sTetherCtrl->isTetheringStarted() ? "started" : "stopped")); 421 cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false); 422 free(tmp); 423 return 0; 424 } else { 425 /* 426 * These commands take a minimum of 4 arguments 427 */ 428 if (argc < 4) { 429 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 430 return 0; 431 } 432 433 if (!strcmp(argv[1], "start")) { 434 if (argc % 2 == 1) { 435 cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false); 436 return 0; 437 } 438 439 int num_addrs = argc - 2; 440 int arg_index = 2; 441 int array_index = 0; 442 in_addr *addrs = (in_addr *)malloc(sizeof(in_addr) * num_addrs); 443 while (array_index < num_addrs) { 444 if (!inet_aton(argv[arg_index++], &(addrs[array_index++]))) { 445 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false); 446 free(addrs); 447 return 0; 448 } 449 } 450 rc = sTetherCtrl->startTethering(num_addrs, addrs); 451 free(addrs); 452 } else if (!strcmp(argv[1], "interface")) { 453 if (!strcmp(argv[2], "add")) { 454 rc = sTetherCtrl->tetherInterface(argv[3]); 455 } else if (!strcmp(argv[2], "remove")) { 456 rc = sTetherCtrl->untetherInterface(argv[3]); 457 } else if (!strcmp(argv[2], "list")) { 458 InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList(); 459 InterfaceCollection::iterator it; 460 461 for (it = ilist->begin(); it != ilist->end(); ++it) { 462 cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false); 463 } 464 } else { 465 cli->sendMsg(ResponseCode::CommandParameterError, 466 "Unknown tether interface operation", false); 467 return 0; 468 } 469 } else if (!strcmp(argv[1], "dns")) { 470 if (!strcmp(argv[2], "set")) { 471 rc = sTetherCtrl->setDnsForwarders(&argv[3], argc - 3); 472 } else if (!strcmp(argv[2], "list")) { 473 NetAddressCollection *dlist = sTetherCtrl->getDnsForwarders(); 474 NetAddressCollection::iterator it; 475 476 for (it = dlist->begin(); it != dlist->end(); ++it) { 477 cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, inet_ntoa(*it), false); 478 } 479 } else { 480 cli->sendMsg(ResponseCode::CommandParameterError, 481 "Unknown tether interface operation", false); 482 return 0; 483 } 484 } else { 485 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false); 486 return 0; 487 } 488 } 489 490 if (!rc) { 491 cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false); 492 } else { 493 cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true); 494 } 495 496 return 0; 497} 498 499CommandListener::NatCmd::NatCmd() : 500 NetdCommand("nat") { 501} 502 503int CommandListener::NatCmd::runCommand(SocketClient *cli, 504 int argc, char **argv) { 505 int rc = 0; 506 507 if (argc < 3) { 508 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 509 return 0; 510 } 511 512 if (!strcmp(argv[1], "enable")) { 513 rc = sNatCtrl->enableNat(argv[2], argv[3]); 514 } else if (!strcmp(argv[1], "disable")) { 515 rc = sNatCtrl->disableNat(argv[2], argv[3]); 516 } else { 517 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false); 518 return 0; 519 } 520 521 if (!rc) { 522 cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false); 523 } else { 524 cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true); 525 } 526 527 return 0; 528} 529 530CommandListener::PppdCmd::PppdCmd() : 531 NetdCommand("pppd") { 532} 533 534int CommandListener::PppdCmd::runCommand(SocketClient *cli, 535 int argc, char **argv) { 536 int rc = 0; 537 538 if (argc < 3) { 539 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 540 return 0; 541 } 542 543 if (!strcmp(argv[1], "attach")) { 544 struct in_addr l, r, dns1, dns2; 545 546 memset(&dns1, sizeof(struct in_addr), 0); 547 memset(&dns2, sizeof(struct in_addr), 0); 548 549 if (!inet_aton(argv[3], &l)) { 550 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false); 551 return 0; 552 } 553 if (!inet_aton(argv[4], &r)) { 554 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false); 555 return 0; 556 } 557 if ((argc > 3) && (!inet_aton(argv[5], &dns1))) { 558 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false); 559 return 0; 560 } 561 if ((argc > 4) && (!inet_aton(argv[6], &dns2))) { 562 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false); 563 return 0; 564 } 565 rc = sPppCtrl->attachPppd(argv[2], l, r, dns1, dns2); 566 } else if (!strcmp(argv[1], "detach")) { 567 rc = sPppCtrl->detachPppd(argv[2]); 568 } else { 569 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false); 570 return 0; 571 } 572 573 if (!rc) { 574 cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false); 575 } else { 576 cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true); 577 } 578 579 return 0; 580} 581 582CommandListener::PanCmd::PanCmd() : 583 NetdCommand("pan") { 584} 585 586int CommandListener::PanCmd::runCommand(SocketClient *cli, 587 int argc, char **argv) { 588 int rc = 0; 589 590 if (argc < 2) { 591 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 592 return 0; 593 } 594 595 if (!strcmp(argv[1], "start")) { 596 rc = sPanCtrl->startPan(); 597 } else if (!strcmp(argv[1], "stop")) { 598 rc = sPanCtrl->stopPan(); 599 } else if (!strcmp(argv[1], "status")) { 600 char *tmp = NULL; 601 602 asprintf(&tmp, "Pan services %s", 603 (sPanCtrl->isPanStarted() ? "started" : "stopped")); 604 cli->sendMsg(ResponseCode::PanStatusResult, tmp, false); 605 free(tmp); 606 return 0; 607 } else { 608 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pan cmd", false); 609 return 0; 610 } 611 612 if (!rc) { 613 cli->sendMsg(ResponseCode::CommandOkay, "Pan operation succeeded", false); 614 } else { 615 cli->sendMsg(ResponseCode::OperationFailed, "Pan operation failed", true); 616 } 617 618 return 0; 619} 620 621CommandListener::SoftapCmd::SoftapCmd() : 622 NetdCommand("softap") { 623} 624 625int CommandListener::SoftapCmd::runCommand(SocketClient *cli, 626 int argc, char **argv) { 627 int rc = 0, flag = 0; 628 char *retbuf = NULL; 629 630 if (argc < 2) { 631 cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Missing argument", false); 632 return 0; 633 } 634 635 if (!strcmp(argv[1], "start")) { 636 rc = sSoftapCtrl->startDriver(argv[2]); 637 } else if (!strcmp(argv[1], "stop")) { 638 rc = sSoftapCtrl->stopDriver(argv[2]); 639 } else if (!strcmp(argv[1], "startap")) { 640 rc = sSoftapCtrl->startSoftap(); 641 } else if (!strcmp(argv[1], "stopap")) { 642 rc = sSoftapCtrl->stopSoftap(); 643 } else if (!strcmp(argv[1], "fwreload")) { 644 rc = sSoftapCtrl->fwReloadSoftap(argc, argv); 645 } else if (!strcmp(argv[1], "clients")) { 646 rc = sSoftapCtrl->clientsSoftap(&retbuf); 647 if (!rc) { 648 cli->sendMsg(ResponseCode::CommandOkay, retbuf, false); 649 free(retbuf); 650 return 0; 651 } 652 } else if (!strcmp(argv[1], "status")) { 653 asprintf(&retbuf, "Softap service %s", 654 (sSoftapCtrl->isSoftapStarted() ? "started" : "stopped")); 655 cli->sendMsg(ResponseCode::SoftapStatusResult, retbuf, false); 656 free(retbuf); 657 return 0; 658 } else if (!strcmp(argv[1], "set")) { 659 rc = sSoftapCtrl->setSoftap(argc, argv); 660 } else { 661 cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Unknown cmd", false); 662 return 0; 663 } 664 665 if (!rc) { 666 cli->sendMsg(ResponseCode::CommandOkay, "Softap operation succeeded", false); 667 } else { 668 cli->sendMsg(ResponseCode::OperationFailed, "Softap operation failed", true); 669 } 670 671 return 0; 672} 673 674CommandListener::UsbCmd::UsbCmd() : 675 NetdCommand("usb") { 676} 677 678int CommandListener::UsbCmd::runCommand(SocketClient *cli, int argc, char **argv) { 679 int rc = 0; 680 681 if (argc < 2) { 682 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usb Missing argument", false); 683 return 0; 684 } 685 686 if (!strcmp(argv[1], "startrndis")) { 687 rc = sUsbCtrl->startRNDIS(); 688 } else if (!strcmp(argv[1], "stoprndis")) { 689 rc = sUsbCtrl->stopRNDIS(); 690 } else if (!strcmp(argv[1], "rndisstatus")) { 691 char *tmp = NULL; 692 693 asprintf(&tmp, "Usb RNDIS %s", 694 (sUsbCtrl->isRNDISStarted() ? "started" : "stopped")); 695 cli->sendMsg(ResponseCode::UsbRNDISStatusResult, tmp, false); 696 free(tmp); 697 return 0; 698 } else { 699 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usb Unknown cmd", false); 700 return 0; 701 } 702 703 if (!rc) { 704 cli->sendMsg(ResponseCode::CommandOkay, "Usb operation succeeded", false); 705 } else { 706 cli->sendMsg(ResponseCode::OperationFailed, "Usb operation failed", true); 707 } 708 709 return 0; 710} 711 712int CommandListener::readInterfaceCounters(const char *iface, unsigned long *rx, unsigned long *tx) { 713 FILE *fp = fopen("/proc/net/dev", "r"); 714 if (!fp) { 715 LOGE("Failed to open /proc/net/dev (%s)", strerror(errno)); 716 return -1; 717 } 718 719 char buffer[512]; 720 721 fgets(buffer, sizeof(buffer), fp); // Header 1 722 fgets(buffer, sizeof(buffer), fp); // Header 2 723 while(fgets(buffer, sizeof(buffer), fp)) { 724 buffer[strlen(buffer)-1] = '\0'; 725 726 char name[31]; 727 unsigned long d; 728 sscanf(buffer, "%30s %lu %lu %lu %lu %lu %lu %lu %lu %lu", 729 name, rx, &d, &d, &d, &d, &d, &d, &d, tx); 730 char *rxString = strchr(name, ':'); 731 *rxString = '\0'; 732 rxString++; 733 // when the rx count gets too big it changes from "name: 999" to "name:1000" 734 // and the sscanf munge the two together. Detect that and fix 735 // note that all the %lu will be off by one and the real tx value will be in d 736 if (*rxString != '\0') { 737 *tx = d; 738 sscanf(rxString, "%20lu", rx); 739 } 740 if (strcmp(name, iface)) { 741 continue; 742 } 743 fclose(fp); 744 return 0; 745 } 746 747 fclose(fp); 748 *rx = 0; 749 *tx = 0; 750 return 0; 751} 752 753CommandListener::BandwidthControlCmd::BandwidthControlCmd() : 754 NetdCommand("bandwidth") { 755} 756 757int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, 758 int argc, char **argv) { 759 int rc = 0; 760 if (argc < 2) { 761 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 762 return 0; 763 } 764 765 if (!strcmp(argv[1], "enable")) { 766 rc = sBandwidthCtrl->enableBandwidthControl(); 767 } else if (!strcmp(argv[1], "disable")) { 768 rc = sBandwidthCtrl->disableBandwidthControl(); 769 } else if (!strcmp(argv[1], "setquota")) { 770 if (argc != 4) { 771 cli->sendMsg(ResponseCode::CommandSyntaxError, 772 "Usage: bandwidth setquota <interface> <bytes>", false); 773 return 0; 774 } 775 rc = sBandwidthCtrl->setInterfaceQuota(argv[2], atoll(argv[3])); 776 } else { 777 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false); 778 return 0; 779 } 780 781 if (!rc) { 782 cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false); 783 } else { 784 cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", true); 785 } 786 return 0; 787} 788