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