netd: Add initial interface driver command support
Change-Id: I1d34e43fc6a3336d0cd06e9db1069467382f210f
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/Android.mk b/Android.mk
index 4e6c6f3..811e875 100644
--- a/Android.mk
+++ b/Android.mk
@@ -8,6 +8,7 @@
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 @@
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 @@
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 @@
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 <interface> <cmd> <args>", 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 @@
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 <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#define LOG_TAG "InterfaceController"
+#include <cutils/log.h>
+#include <netutils/ifc.h>
+#include <private/android_filesystem_config.h>
+
+#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 <linux/in.h>
+#include <net/if.h>
+
+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