From 2eab1f762badb7ba46b95716e62ea4548a979903 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Thu, 26 Jul 2012 16:08:02 -0700 Subject: [PATCH] netd: Add initial interface driver command support Change-Id: I1d34e43fc6a3336d0cd06e9db1069467382f210f Signed-off-by: Dmitry Shmidt --- Android.mk | 1 + CommandListener.cpp | 19 +++++++++ CommandListener.h | 2 + InterfaceController.cpp | 107 ++++++++++++++++++++++++++++++++++++++++++++++++ InterfaceController.h | 43 +++++++++++++++++++ 5 files changed, 172 insertions(+) create mode 100644 InterfaceController.cpp create mode 100644 InterfaceController.h diff --git a/Android.mk b/Android.mk index 4e6c6f3..811e875 100644 --- a/Android.mk +++ b/Android.mk @@ -8,6 +8,7 @@ LOCAL_SRC_FILES:= \ DnsProxyListener.cpp \ FirewallController.cpp \ IdletimerController.cpp \ + InterfaceController.cpp \ MDnsSdListener.cpp \ NatController.cpp \ NetdCommand.cpp \ diff --git a/CommandListener.cpp b/CommandListener.cpp index a6d2048..df44549 100644 --- a/CommandListener.cpp +++ b/CommandListener.cpp @@ -50,6 +50,7 @@ PanController *CommandListener::sPanCtrl = NULL; SoftapController *CommandListener::sSoftapCtrl = NULL; BandwidthController * CommandListener::sBandwidthCtrl = NULL; IdletimerController * CommandListener::sIdletimerCtrl = NULL; +InterfaceController *CommandListener::sInterfaceCtrl = NULL; ResolverController *CommandListener::sResolverCtrl = NULL; SecondaryTableController *CommandListener::sSecondaryTableCtrl = NULL; FirewallController *CommandListener::sFirewallCtrl = NULL; @@ -158,6 +159,8 @@ CommandListener::CommandListener() : sResolverCtrl = new ResolverController(); if (!sFirewallCtrl) sFirewallCtrl = new FirewallController(); + if (!sInterfaceCtrl) + sInterfaceCtrl = new InterfaceController(); /* * This is the only time we touch top-level chains in iptables; controllers @@ -317,6 +320,22 @@ int CommandListener::InterfaceCmd::runCommand(SocketClient *cli, cli->sendMsg(ResponseCode::CommandOkay, "Interface throttling set", false); } return 0; + } else if (!strcmp(argv[1], "driver")) { + int rc; + char *rbuf; + + if (argc < 4) { + cli->sendMsg(ResponseCode::CommandSyntaxError, + "Usage: interface driver ", false); + return 0; + } + rc = sInterfaceCtrl->interfaceCommand(argc, argv, &rbuf); + if (rc) { + cli->sendMsg(ResponseCode::OperationFailed, "Failed to execute command", true); + } else { + cli->sendMsg(ResponseCode::CommandOkay, rbuf, false); + } + return 0; } else { /* * These commands take a minimum of 3 arguments diff --git a/CommandListener.h b/CommandListener.h index e52b440..faf0c21 100644 --- a/CommandListener.h +++ b/CommandListener.h @@ -27,6 +27,7 @@ #include "SoftapController.h" #include "BandwidthController.h" #include "IdletimerController.h" +#include "InterfaceController.h" #include "ResolverController.h" #include "SecondaryTableController.h" #include "FirewallController.h" @@ -39,6 +40,7 @@ class CommandListener : public FrameworkListener { static SoftapController *sSoftapCtrl; static BandwidthController *sBandwidthCtrl; static IdletimerController *sIdletimerCtrl; + static InterfaceController *sInterfaceCtrl; static ResolverController *sResolverCtrl; static SecondaryTableController *sSecondaryTableCtrl; static FirewallController *sFirewallCtrl; diff --git a/InterfaceController.cpp b/InterfaceController.cpp new file mode 100644 index 0000000..a20b13f --- /dev/null +++ b/InterfaceController.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#define LOG_TAG "InterfaceController" +#include +#include +#include + +#include "InterfaceController.h" + +InterfaceController::InterfaceController() { + iSock = socket(AF_INET, SOCK_DGRAM, 0); + if (iSock < 0) + ALOGE("Failed to open socket"); + iBuf = (char *)malloc(INTERFACE_MAX_BUFFER_SIZE); + if (!iBuf) + ALOGE("Failed to allocate buffer"); +} + +InterfaceController::~InterfaceController() { + if (iSock >= 0) + close(iSock); + if (iBuf) + free(iBuf); +} + +int InterfaceController::sendCommand(char *iface, char *cmd, char *buf, int buf_len) { + struct ifreq ifr; + android_wifi_priv_cmd priv_cmd; + int ret; + + if (!iface || !cmd) + return -1; + + memset(&ifr, 0, sizeof(ifr)); + memset(&priv_cmd, 0, sizeof(priv_cmd)); + strncpy(ifr.ifr_name, iface, IFNAMSIZ); + memcpy(buf, cmd, strlen(cmd) + 1); + + priv_cmd.buf = buf; + priv_cmd.used_len = buf_len; + priv_cmd.total_len = buf_len; + ifr.ifr_data = &priv_cmd; + + if ((ret = ioctl(iSock, SIOCDEVPRIVATE + 1, &ifr)) < 0) { + ALOGE("Failed to execute command: %s", cmd); + } else { + if (buf[0] == '\0') { + snprintf(buf, buf_len, "OK"); + } + } + return ret; +} + +/* + * Arguments: + * argv[2] - wlan interface + * argv[3] - command + * argv[4] - argument + * rbuf - returned buffer + */ +int InterfaceController::interfaceCommand(int argc, char *argv[], char **rbuf) { + char cmd[INTERFACE_MAX_BUFFER_SIZE]; + unsigned int bc = 0; + int ret; + int i; + + if ((iSock < 0) || !iBuf || (argc < 4)) + return -1; + + for (i=3; i < argc; i++) { + bc += snprintf(&cmd[bc], sizeof(cmd) - bc, "%s ", argv[i]); + } + if (bc >= sizeof(cmd)) + bc = sizeof(cmd) - 1; + cmd[bc] = '\0'; + ret = sendCommand(argv[2], cmd, iBuf, INTERFACE_MAX_BUFFER_SIZE); + if (rbuf) + *rbuf = iBuf; + return ret; +} diff --git a/InterfaceController.h b/InterfaceController.h new file mode 100644 index 0000000..dbedc13 --- /dev/null +++ b/InterfaceController.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _INTERFACE_CONTROLLER_H +#define _INTERFACE_CONTROLLER_H + +#include +#include + +typedef struct android_wifi_priv_cmd { + char *buf; + int used_len; + int total_len; +} android_wifi_priv_cmd; + +#define INTERFACE_MAX_BUFFER_SIZE 256 + +class InterfaceController { + int iSock; + char *iBuf; + + int sendCommand(char *iface, char *cmd, char *buf, int buf_len); +public: + InterfaceController(); + virtual ~InterfaceController(); + + int interfaceCommand(int argc, char *argv[], char **rbuf); +}; + +#endif -- 2.11.0