CommandListener.cpp revision 5af38c360587ca2eef0badf6137ccf018f8cd4aa
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; 48 49CommandListener::CommandListener() : 50 FrameworkListener("netd") { 51 registerCmd(new InterfaceCmd()); 52 registerCmd(new IpFwdCmd()); 53 registerCmd(new TetherCmd()); 54 registerCmd(new NatCmd()); 55 registerCmd(new ListTtysCmd()); 56 registerCmd(new PppdCmd()); 57 registerCmd(new PanCmd()); 58 registerCmd(new SoftapCmd()); 59 60 if (!sTetherCtrl) 61 sTetherCtrl = new TetherController(); 62 if (!sNatCtrl) 63 sNatCtrl = new NatController(); 64 if (!sPppCtrl) 65 sPppCtrl = new PppController(); 66 if (!sPanCtrl) 67 sPanCtrl = new PanController(); 68 if (!sSoftapCtrl) 69 sSoftapCtrl = new SoftapController(); 70} 71 72CommandListener::InterfaceCmd::InterfaceCmd() : 73 NetdCommand("interface") { 74} 75 76int CommandListener::InterfaceCmd::runCommand(SocketClient *cli, 77 int argc, char **argv) { 78 if (argc < 2) { 79 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 80 return 0; 81 } 82 83 if (!strcmp(argv[1], "list")) { 84 DIR *d; 85 struct dirent *de; 86 87 if (!(d = opendir("/sys/class/net"))) { 88 cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true); 89 return 0; 90 } 91 92 while((de = readdir(d))) { 93 if (de->d_name[0] == '.') 94 continue; 95 cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false); 96 } 97 closedir(d); 98 cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false); 99 return 0; 100 } else { 101 /* 102 * These commands take a minimum of 3 arguments 103 */ 104 if (argc < 3) { 105 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 106 return 0; 107 } 108 if (!strcmp(argv[1], "getcfg")) { 109 struct in_addr addr, mask; 110 unsigned char hwaddr[6]; 111 unsigned flags = 0; 112 113 ifc_init(); 114 memset(hwaddr, 0, sizeof(hwaddr)); 115 116 if (ifc_get_info(argv[2], &addr.s_addr, &mask.s_addr, &flags)) { 117 cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true); 118 return 0; 119 } 120 121 if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) { 122 LOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno)); 123 } 124 125 char *addr_s = strdup(inet_ntoa(addr)); 126 char *mask_s = strdup(inet_ntoa(mask)); 127 const char *updown, *brdcst, *loopbk, *ppp, *running, *multi; 128 129 updown = (flags & IFF_UP) ? "up" : "down"; 130 brdcst = (flags & IFF_BROADCAST) ? " broadcast" : ""; 131 loopbk = (flags & IFF_LOOPBACK) ? " loopback" : ""; 132 ppp = (flags & IFF_POINTOPOINT) ? " point-to-point" : ""; 133 running = (flags & IFF_RUNNING) ? " running" : ""; 134 multi = (flags & IFF_MULTICAST) ? " multicast" : ""; 135 136 char *flag_s; 137 138 asprintf(&flag_s, "[%s%s%s%s%s%s]\n", updown, brdcst, loopbk, ppp, running, multi); 139 140 char *msg = NULL; 141 asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %s %s", 142 hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5], 143 addr_s, mask_s, flag_s); 144 145 cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false); 146 147 free(addr_s); 148 free(mask_s); 149 free(flag_s); 150 free(msg); 151 return 0; 152 } else if (!strcmp(argv[1], "setcfg")) { 153 if (argc < 5) { 154 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 155 return 0; 156 } 157 158 struct in_addr addr, mask; 159 unsigned flags = 0; 160 161 if (!inet_aton(argv[3], &addr)) { 162 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false); 163 return 0; 164 } 165 166 if (!inet_aton(argv[4], &mask)) { 167 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid netmask", false); 168 return 0; 169 } 170 171 ifc_init(); 172 if (ifc_set_addr(argv[2], addr.s_addr)) { 173 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true); 174 return 0; 175 } 176 177 if (ifc_set_mask(argv[2], mask.s_addr)) { 178 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set netmask", true); 179 return 0; 180 } 181 182 /* Process flags */ 183 for (int i = 5; i < argc; i++) { 184 if (!strcmp(argv[i], "up")) { 185 if (ifc_up(argv[2])) { 186 LOGE("Error upping interface"); 187 cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true); 188 return 0; 189 } 190 } else if (!strcmp(argv[i], "down")) { 191 if (ifc_down(argv[2])) { 192 LOGE("Error downing interface"); 193 cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true); 194 return 0; 195 } 196 } else { 197 cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false); 198 return 0; 199 } 200 } 201 cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false); 202 return 0; 203 } else { 204 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false); 205 return 0; 206 } 207 } 208 return 0; 209} 210 211CommandListener::ListTtysCmd::ListTtysCmd() : 212 NetdCommand("list_ttys") { 213} 214 215int CommandListener::ListTtysCmd::runCommand(SocketClient *cli, 216 int argc, char **argv) { 217 TtyCollection *tlist = sPppCtrl->getTtyList(); 218 TtyCollection::iterator it; 219 220 for (it = tlist->begin(); it != tlist->end(); ++it) { 221 cli->sendMsg(ResponseCode::TtyListResult, *it, false); 222 } 223 224 cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false); 225 return 0; 226} 227 228CommandListener::IpFwdCmd::IpFwdCmd() : 229 NetdCommand("ipfwd") { 230} 231 232int CommandListener::IpFwdCmd::runCommand(SocketClient *cli, 233 int argc, char **argv) { 234 int rc = 0; 235 236 if (argc < 2) { 237 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 238 return 0; 239 } 240 241 if (!strcmp(argv[1], "status")) { 242 char *tmp = NULL; 243 244 asprintf(&tmp, "Forwarding %s", (sTetherCtrl->getIpFwdEnabled() ? "enabled" : "disabled")); 245 cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false); 246 free(tmp); 247 return 0; 248 } else if (!strcmp(argv[1], "enable")) { 249 rc = sTetherCtrl->setIpFwdEnabled(true); 250 } else if (!strcmp(argv[1], "disable")) { 251 rc = sTetherCtrl->setIpFwdEnabled(false); 252 } else { 253 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false); 254 return 0; 255 } 256 257 if (!rc) { 258 cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false); 259 } else { 260 cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true); 261 } 262 263 return 0; 264} 265 266CommandListener::TetherCmd::TetherCmd() : 267 NetdCommand("tether") { 268} 269 270int CommandListener::TetherCmd::runCommand(SocketClient *cli, 271 int argc, char **argv) { 272 int rc = 0; 273 274 if (argc < 2) { 275 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 276 return 0; 277 } 278 279 if (!strcmp(argv[1], "stop")) { 280 rc = sTetherCtrl->stopTethering(); 281 } else if (!strcmp(argv[1], "status")) { 282 char *tmp = NULL; 283 284 asprintf(&tmp, "Tethering services %s", 285 (sTetherCtrl->isTetheringStarted() ? "started" : "stopped")); 286 cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false); 287 free(tmp); 288 return 0; 289 } else { 290 /* 291 * These commands take a minimum of 4 arguments 292 */ 293 if (argc < 4) { 294 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 295 return 0; 296 } 297 298 if (!strcmp(argv[1], "start")) { 299 struct in_addr s, e; 300 301 if (!inet_aton(argv[2], &s)) { 302 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid start address", false); 303 return 0; 304 } 305 if (!inet_aton(argv[3], &e)) { 306 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid end address", false); 307 return 0; 308 } 309 rc = sTetherCtrl->startTethering(s, e); 310 } else if (!strcmp(argv[1], "interface")) { 311 if (!strcmp(argv[2], "add")) { 312 rc = sTetherCtrl->tetherInterface(argv[3]); 313 } else if (!strcmp(argv[2], "remove")) { 314 rc = sTetherCtrl->untetherInterface(argv[3]); 315 } else if (!strcmp(argv[2], "list")) { 316 InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList(); 317 InterfaceCollection::iterator it; 318 319 for (it = ilist->begin(); it != ilist->end(); ++it) { 320 cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false); 321 } 322 } else { 323 cli->sendMsg(ResponseCode::CommandParameterError, 324 "Unknown tether interface operation", false); 325 return 0; 326 } 327 } else if (!strcmp(argv[1], "dns")) { 328 if (!strcmp(argv[2], "set")) { 329 rc = sTetherCtrl->setDnsForwarders(&argv[3], argc - 3); 330 } else if (!strcmp(argv[2], "list")) { 331 NetAddressCollection *dlist = sTetherCtrl->getDnsForwarders(); 332 NetAddressCollection::iterator it; 333 334 for (it = dlist->begin(); it != dlist->end(); ++it) { 335 cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, inet_ntoa(*it), false); 336 } 337 } else { 338 cli->sendMsg(ResponseCode::CommandParameterError, 339 "Unknown tether interface operation", false); 340 return 0; 341 } 342 } else { 343 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false); 344 return 0; 345 } 346 } 347 348 if (!rc) { 349 cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false); 350 } else { 351 cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true); 352 } 353 354 return 0; 355} 356 357CommandListener::NatCmd::NatCmd() : 358 NetdCommand("nat") { 359} 360 361int CommandListener::NatCmd::runCommand(SocketClient *cli, 362 int argc, char **argv) { 363 int rc = 0; 364 365 if (argc < 3) { 366 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 367 return 0; 368 } 369 370 if (!strcmp(argv[1], "enable")) { 371 rc = sNatCtrl->enableNat(argv[2], argv[3]); 372 } else if (!strcmp(argv[1], "disable")) { 373 rc = sNatCtrl->disableNat(argv[2], argv[3]); 374 } else { 375 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false); 376 return 0; 377 } 378 379 if (!rc) { 380 cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false); 381 } else { 382 cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true); 383 } 384 385 return 0; 386} 387 388CommandListener::PppdCmd::PppdCmd() : 389 NetdCommand("pppd") { 390} 391 392int CommandListener::PppdCmd::runCommand(SocketClient *cli, 393 int argc, char **argv) { 394 int rc = 0; 395 396 if (argc < 3) { 397 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 398 return 0; 399 } 400 401 if (!strcmp(argv[1], "attach")) { 402 struct in_addr l, r, dns1, dns2; 403 404 memset(&dns1, sizeof(struct in_addr), 0); 405 memset(&dns2, sizeof(struct in_addr), 0); 406 407 if (!inet_aton(argv[3], &l)) { 408 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false); 409 return 0; 410 } 411 if (!inet_aton(argv[4], &r)) { 412 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false); 413 return 0; 414 } 415 if ((argc > 3) && (!inet_aton(argv[5], &dns1))) { 416 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false); 417 return 0; 418 } 419 if ((argc > 4) && (!inet_aton(argv[6], &dns2))) { 420 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false); 421 return 0; 422 } 423 rc = sPppCtrl->attachPppd(argv[2], l, r, dns1, dns2); 424 } else if (!strcmp(argv[1], "detach")) { 425 rc = sPppCtrl->detachPppd(argv[2]); 426 } else { 427 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false); 428 return 0; 429 } 430 431 if (!rc) { 432 cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false); 433 } else { 434 cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true); 435 } 436 437 return 0; 438} 439 440CommandListener::PanCmd::PanCmd() : 441 NetdCommand("pan") { 442} 443 444int CommandListener::PanCmd::runCommand(SocketClient *cli, 445 int argc, char **argv) { 446 int rc = 0; 447 448 if (argc < 2) { 449 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); 450 return 0; 451 } 452 453 if (!strcmp(argv[1], "start")) { 454 rc = sPanCtrl->startPan(); 455 } else if (!strcmp(argv[1], "stop")) { 456 rc = sPanCtrl->stopPan(); 457 } else if (!strcmp(argv[1], "status")) { 458 char *tmp = NULL; 459 460 asprintf(&tmp, "Pan services %s", 461 (sPanCtrl->isPanStarted() ? "started" : "stopped")); 462 cli->sendMsg(ResponseCode::PanStatusResult, tmp, false); 463 free(tmp); 464 return 0; 465 } else { 466 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pan cmd", false); 467 return 0; 468 } 469 470 if (!rc) { 471 cli->sendMsg(ResponseCode::CommandOkay, "Pan operation succeeded", false); 472 } else { 473 cli->sendMsg(ResponseCode::OperationFailed, "Pan operation failed", true); 474 } 475 476 return 0; 477} 478 479CommandListener::SoftapCmd::SoftapCmd() : 480 NetdCommand("softap") { 481} 482 483int CommandListener::SoftapCmd::runCommand(SocketClient *cli, 484 int argc, char **argv) { 485 int rc = 0; 486 487 if (argc < 2) { 488 cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Missing argument", false); 489 return 0; 490 } 491 492 if (!strcmp(argv[1], "start")) { 493 rc = sSoftapCtrl->startSoftap(); 494 } else if (!strcmp(argv[1], "stop")) { 495 rc = sSoftapCtrl->stopSoftap(); 496 } else if (!strcmp(argv[1], "status")) { 497 char *tmp = NULL; 498 499 asprintf(&tmp, "Softap service %s", 500 (sSoftapCtrl->isSoftapStarted() ? "started" : "stopped")); 501 cli->sendMsg(ResponseCode::SoftapStatusResult, tmp, false); 502 free(tmp); 503 return 0; 504 } else if (!strcmp(argv[1], "set")) { 505 rc = sSoftapCtrl->setSoftap(argc, argv); 506 } else { 507 cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Unknown cmd", false); 508 return 0; 509 } 510 511 if (!rc) { 512 cli->sendMsg(ResponseCode::CommandOkay, "Softap operation succeeded", false); 513 } else { 514 cli->sendMsg(ResponseCode::OperationFailed, "Softap operation failed", true); 515 } 516 517 return 0; 518} 519