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