CommandListener.cpp revision 31fd6c5f3e9c39a13b028718dba5921a4300988c
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 { 105 /* 106 * These commands take a minimum of 3 arguments 107 */ 108 if (argc < 3) { 109 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 110 return 0; 111 } 112 if (!strcmp(argv[1], "getcfg")) { 113 struct in_addr addr, mask; 114 unsigned char hwaddr[6]; 115 unsigned flags = 0; 116 117 ifc_init(); 118 memset(hwaddr, 0, sizeof(hwaddr)); 119 120 if (ifc_get_info(argv[2], &addr.s_addr, &mask.s_addr, &flags)) { 121 cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true); 122 return 0; 123 } 124 125 if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) { 126 LOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno)); 127 } 128 129 char *addr_s = strdup(inet_ntoa(addr)); 130 char *mask_s = strdup(inet_ntoa(mask)); 131 const char *updown, *brdcst, *loopbk, *ppp, *running, *multi; 132 133 updown = (flags & IFF_UP) ? "up" : "down"; 134 brdcst = (flags & IFF_BROADCAST) ? " broadcast" : ""; 135 loopbk = (flags & IFF_LOOPBACK) ? " loopback" : ""; 136 ppp = (flags & IFF_POINTOPOINT) ? " point-to-point" : ""; 137 running = (flags & IFF_RUNNING) ? " running" : ""; 138 multi = (flags & IFF_MULTICAST) ? " multicast" : ""; 139 140 char *flag_s; 141 142 asprintf(&flag_s, "[%s%s%s%s%s%s]", updown, brdcst, loopbk, ppp, running, multi); 143 144 char *msg = NULL; 145 asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %s %s", 146 hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5], 147 addr_s, mask_s, flag_s); 148 149 cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false); 150 151 free(addr_s); 152 free(mask_s); 153 free(flag_s); 154 free(msg); 155 return 0; 156 } else if (!strcmp(argv[1], "setcfg")) { 157 // arglist: iface addr mask [flags] 158 if (argc < 5) { 159 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 160 return 0; 161 } 162 LOGD("Setting iface cfg"); 163 164 struct in_addr addr, mask; 165 unsigned flags = 0; 166 167 if (!inet_aton(argv[3], &addr)) { 168 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false); 169 return 0; 170 } 171 172 if (!inet_aton(argv[4], &mask)) { 173 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid netmask", false); 174 return 0; 175 } 176 177 ifc_init(); 178 if (ifc_set_addr(argv[2], addr.s_addr)) { 179 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true); 180 return 0; 181 } 182 183 if (ifc_set_mask(argv[2], mask.s_addr)) { 184 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set netmask", true); 185 return 0; 186 } 187 188 /* Process flags */ 189 /* read from "[XX" arg to "YY]" arg */ 190 bool bStarted = false; 191 for (int i = 5; i < argc; i++) { 192 char *flag = argv[i]; 193 if (!bStarted) { 194 if (*flag == '[') { 195 flag++; 196 bStarted = true; 197 } else { 198 continue; 199 } 200 } 201 int len = strlen(flag); 202 if (flag[len-1] == ']') { 203 i = argc; // stop after this loop 204 flag[len-1] = 0; 205 } 206 if (!strcmp(flag, "up")) { 207 LOGD("Trying to bring up %s", argv[2]); 208 if (ifc_up(argv[2])) { 209 LOGE("Error upping interface"); 210 cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true); 211 return 0; 212 } 213 } else if (!strcmp(flag, "down")) { 214 LOGD("Trying to bring down %s", argv[2]); 215 if (ifc_down(argv[2])) { 216 LOGE("Error downing interface"); 217 cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true); 218 return 0; 219 } 220 } else if (!strcmp(flag, "broadcast")) { 221 LOGD("broadcast flag ignored"); 222 } else if (!strcmp(flag, "multicast")) { 223 LOGD("multicast flag ignored"); 224 } else { 225 cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false); 226 return 0; 227 } 228 } 229 cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false); 230 return 0; 231 } else { 232 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false); 233 return 0; 234 } 235 } 236 return 0; 237} 238 239CommandListener::ListTtysCmd::ListTtysCmd() : 240 NetdCommand("list_ttys") { 241} 242 243int CommandListener::ListTtysCmd::runCommand(SocketClient *cli, 244 int argc, char **argv) { 245 TtyCollection *tlist = sPppCtrl->getTtyList(); 246 TtyCollection::iterator it; 247 248 for (it = tlist->begin(); it != tlist->end(); ++it) { 249 cli->sendMsg(ResponseCode::TtyListResult, *it, false); 250 } 251 252 cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false); 253 return 0; 254} 255 256CommandListener::IpFwdCmd::IpFwdCmd() : 257 NetdCommand("ipfwd") { 258} 259 260int CommandListener::IpFwdCmd::runCommand(SocketClient *cli, 261 int argc, char **argv) { 262 int rc = 0; 263 264 if (argc < 2) { 265 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 266 return 0; 267 } 268 269 if (!strcmp(argv[1], "status")) { 270 char *tmp = NULL; 271 272 asprintf(&tmp, "Forwarding %s", (sTetherCtrl->getIpFwdEnabled() ? "enabled" : "disabled")); 273 cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false); 274 free(tmp); 275 return 0; 276 } else if (!strcmp(argv[1], "enable")) { 277 rc = sTetherCtrl->setIpFwdEnabled(true); 278 } else if (!strcmp(argv[1], "disable")) { 279 rc = sTetherCtrl->setIpFwdEnabled(false); 280 } else { 281 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false); 282 return 0; 283 } 284 285 if (!rc) { 286 cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false); 287 } else { 288 cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true); 289 } 290 291 return 0; 292} 293 294CommandListener::TetherCmd::TetherCmd() : 295 NetdCommand("tether") { 296} 297 298int CommandListener::TetherCmd::runCommand(SocketClient *cli, 299 int argc, char **argv) { 300 int rc = 0; 301 302 if (argc < 2) { 303 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 304 return 0; 305 } 306 307 if (!strcmp(argv[1], "stop")) { 308 rc = sTetherCtrl->stopTethering(); 309 } else if (!strcmp(argv[1], "status")) { 310 char *tmp = NULL; 311 312 asprintf(&tmp, "Tethering services %s", 313 (sTetherCtrl->isTetheringStarted() ? "started" : "stopped")); 314 cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false); 315 free(tmp); 316 return 0; 317 } else { 318 /* 319 * These commands take a minimum of 4 arguments 320 */ 321 if (argc < 4) { 322 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 323 return 0; 324 } 325 326 if (!strcmp(argv[1], "start")) { 327 struct in_addr s, e; 328 329 if (!inet_aton(argv[2], &s)) { 330 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid start address", false); 331 return 0; 332 } 333 if (!inet_aton(argv[3], &e)) { 334 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid end address", false); 335 return 0; 336 } 337 rc = sTetherCtrl->startTethering(s, e); 338 } else if (!strcmp(argv[1], "interface")) { 339 if (!strcmp(argv[2], "add")) { 340 rc = sTetherCtrl->tetherInterface(argv[3]); 341 } else if (!strcmp(argv[2], "remove")) { 342 rc = sTetherCtrl->untetherInterface(argv[3]); 343 } else if (!strcmp(argv[2], "list")) { 344 InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList(); 345 InterfaceCollection::iterator it; 346 347 for (it = ilist->begin(); it != ilist->end(); ++it) { 348 cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false); 349 } 350 } else { 351 cli->sendMsg(ResponseCode::CommandParameterError, 352 "Unknown tether interface operation", false); 353 return 0; 354 } 355 } else if (!strcmp(argv[1], "dns")) { 356 if (!strcmp(argv[2], "set")) { 357 rc = sTetherCtrl->setDnsForwarders(&argv[3], argc - 3); 358 } else if (!strcmp(argv[2], "list")) { 359 NetAddressCollection *dlist = sTetherCtrl->getDnsForwarders(); 360 NetAddressCollection::iterator it; 361 362 for (it = dlist->begin(); it != dlist->end(); ++it) { 363 cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, inet_ntoa(*it), false); 364 } 365 } else { 366 cli->sendMsg(ResponseCode::CommandParameterError, 367 "Unknown tether interface operation", false); 368 return 0; 369 } 370 } else { 371 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false); 372 return 0; 373 } 374 } 375 376 if (!rc) { 377 cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false); 378 } else { 379 cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true); 380 } 381 382 return 0; 383} 384 385CommandListener::NatCmd::NatCmd() : 386 NetdCommand("nat") { 387} 388 389int CommandListener::NatCmd::runCommand(SocketClient *cli, 390 int argc, char **argv) { 391 int rc = 0; 392 393 if (argc < 3) { 394 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 395 return 0; 396 } 397 398 if (!strcmp(argv[1], "enable")) { 399 rc = sNatCtrl->enableNat(argv[2], argv[3]); 400 } else if (!strcmp(argv[1], "disable")) { 401 rc = sNatCtrl->disableNat(argv[2], argv[3]); 402 } else { 403 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false); 404 return 0; 405 } 406 407 if (!rc) { 408 cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false); 409 } else { 410 cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true); 411 } 412 413 return 0; 414} 415 416CommandListener::PppdCmd::PppdCmd() : 417 NetdCommand("pppd") { 418} 419 420int CommandListener::PppdCmd::runCommand(SocketClient *cli, 421 int argc, char **argv) { 422 int rc = 0; 423 424 if (argc < 3) { 425 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 426 return 0; 427 } 428 429 if (!strcmp(argv[1], "attach")) { 430 struct in_addr l, r, dns1, dns2; 431 432 memset(&dns1, sizeof(struct in_addr), 0); 433 memset(&dns2, sizeof(struct in_addr), 0); 434 435 if (!inet_aton(argv[3], &l)) { 436 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false); 437 return 0; 438 } 439 if (!inet_aton(argv[4], &r)) { 440 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false); 441 return 0; 442 } 443 if ((argc > 3) && (!inet_aton(argv[5], &dns1))) { 444 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false); 445 return 0; 446 } 447 if ((argc > 4) && (!inet_aton(argv[6], &dns2))) { 448 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false); 449 return 0; 450 } 451 rc = sPppCtrl->attachPppd(argv[2], l, r, dns1, dns2); 452 } else if (!strcmp(argv[1], "detach")) { 453 rc = sPppCtrl->detachPppd(argv[2]); 454 } else { 455 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false); 456 return 0; 457 } 458 459 if (!rc) { 460 cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false); 461 } else { 462 cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true); 463 } 464 465 return 0; 466} 467 468CommandListener::PanCmd::PanCmd() : 469 NetdCommand("pan") { 470} 471 472int CommandListener::PanCmd::runCommand(SocketClient *cli, 473 int argc, char **argv) { 474 int rc = 0; 475 476 if (argc < 2) { 477 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 478 return 0; 479 } 480 481 if (!strcmp(argv[1], "start")) { 482 rc = sPanCtrl->startPan(); 483 } else if (!strcmp(argv[1], "stop")) { 484 rc = sPanCtrl->stopPan(); 485 } else if (!strcmp(argv[1], "status")) { 486 char *tmp = NULL; 487 488 asprintf(&tmp, "Pan services %s", 489 (sPanCtrl->isPanStarted() ? "started" : "stopped")); 490 cli->sendMsg(ResponseCode::PanStatusResult, tmp, false); 491 free(tmp); 492 return 0; 493 } else { 494 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pan cmd", false); 495 return 0; 496 } 497 498 if (!rc) { 499 cli->sendMsg(ResponseCode::CommandOkay, "Pan operation succeeded", false); 500 } else { 501 cli->sendMsg(ResponseCode::OperationFailed, "Pan operation failed", true); 502 } 503 504 return 0; 505} 506 507CommandListener::SoftapCmd::SoftapCmd() : 508 NetdCommand("softap") { 509} 510 511int CommandListener::SoftapCmd::runCommand(SocketClient *cli, 512 int argc, char **argv) { 513 int rc = 0, flag = 0; 514 515 if (argc < 2) { 516 cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Missing argument", false); 517 return 0; 518 } 519 520 if (!strcmp(argv[1], "start")) { 521 rc = sSoftapCtrl->startSoftap(); 522 } else if (!strcmp(argv[1], "stop")) { 523 rc = sSoftapCtrl->stopSoftap(); 524 } else if (!strcmp(argv[1], "fwreload")) { 525 rc = sSoftapCtrl->fwReloadSoftap(argc, argv); 526 } else if (!strcmp(argv[1], "status")) { 527 char *tmp = NULL; 528 529 asprintf(&tmp, "Softap service %s", 530 (sSoftapCtrl->isSoftapStarted() ? "started" : "stopped")); 531 cli->sendMsg(ResponseCode::SoftapStatusResult, tmp, false); 532 free(tmp); 533 return 0; 534 } else if (!strcmp(argv[1], "set")) { 535 rc = sSoftapCtrl->setSoftap(argc, argv); 536 } else { 537 cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Unknown cmd", false); 538 return 0; 539 } 540 541 if (!rc) { 542 cli->sendMsg(ResponseCode::CommandOkay, "Softap operation succeeded", false); 543 } else { 544 cli->sendMsg(ResponseCode::OperationFailed, "Softap operation failed", true); 545 } 546 547 return 0; 548} 549 550CommandListener::UsbCmd::UsbCmd() : 551 NetdCommand("usb") { 552} 553 554int CommandListener::UsbCmd::runCommand(SocketClient *cli, int argc, char **argv) { 555 int rc = 0; 556 557 if (argc < 2) { 558 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usb Missing argument", false); 559 return 0; 560 } 561 562 if (!strcmp(argv[1], "startrndis")) { 563 rc = sUsbCtrl->startRNDIS(); 564 } else if (!strcmp(argv[1], "stoprndis")) { 565 rc = sUsbCtrl->stopRNDIS(); 566 } else if (!strcmp(argv[1], "rndisstatus")) { 567 char *tmp = NULL; 568 569 asprintf(&tmp, "Usb RNDIS %s", 570 (sUsbCtrl->isRNDISStarted() ? "started" : "stopped")); 571 cli->sendMsg(ResponseCode::UsbRNDISStatusResult, tmp, false); 572 free(tmp); 573 return 0; 574 } else { 575 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usb Unknown cmd", false); 576 return 0; 577 } 578 579 if (!rc) { 580 cli->sendMsg(ResponseCode::CommandOkay, "Usb operation succeeded", false); 581 } else { 582 cli->sendMsg(ResponseCode::OperationFailed, "Softap operation failed", true); 583 } 584 585 return 0; 586} 587