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