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