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