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