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