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