Changes the interface command API from static lib to a dynamic one

Change-Id: I9116491a3f5dfc4590ffab367a224fde37a4fd50
diff --git a/Android.mk b/Android.mk
index 811e875..582f0a6 100644
--- a/Android.mk
+++ b/Android.mk
@@ -42,7 +42,7 @@
 LOCAL_CFLAGS := -Werror=format
 
 LOCAL_SHARED_LIBRARIES := libstlport libsysutils libcutils libnetutils \
-                          libcrypto libhardware_legacy libmdnssd
+                          libcrypto libhardware_legacy libmdnssd libdl
 
 ifeq ($(BOARD_HAVE_BLUETOOTH),true)
   LOCAL_SHARED_LIBRARIES := $(LOCAL_SHARED_LIBRARIES) libbluedroid
diff --git a/InterfaceController.cpp b/InterfaceController.cpp
index a20b13f..25200e9 100644
--- a/InterfaceController.cpp
+++ b/InterfaceController.cpp
@@ -5,7 +5,7 @@
  * 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
+ *	  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,
@@ -19,6 +19,8 @@
 #include <fcntl.h>
 #include <string.h>
 
+#include <dlfcn.h>
+
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
@@ -34,74 +36,66 @@
 
 #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");
+char if_cmd_lib_file_name[] = "/system/lib/libnetcmdiface.so";
+char set_cmd_func_name[] = "net_iface_send_command";
+char set_cmd_init_func_name[] = "net_iface_send_command_init";
+char set_cmd_fini_func_name[] = "net_iface_send_command_fini";
+
+InterfaceController::InterfaceController()
+	: sendCommand_(NULL) {
+	libh_ = dlopen(if_cmd_lib_file_name, RTLD_NOW | RTLD_LOCAL);
+	if (libh_ == NULL) {
+		const char *err_str = dlerror();
+		ALOGE("Error (%s) while opening the net interface command library", err_str ? err_str : "unknown");
+	} else {
+		sendCommandInit_ = (int (*)(void))dlsym(libh_, set_cmd_init_func_name);
+		if (sendCommandInit_ == NULL) {
+			const char *err_str = dlerror();
+			ALOGW("Error (%s) while searching for the interface command init function", err_str ? err_str : "unknown");
+		} else if (sendCommandInit_()) {
+			ALOGE("Can't init the interface command API");
+			return;
+		}
+		sendCommandFini_ = (int (*)(void))dlsym(libh_, set_cmd_fini_func_name);
+		if (sendCommandFini_ == NULL) {
+			const char *err_str = dlerror();
+			ALOGW("Error (%s) while searching for the interface command fini function", err_str ? err_str : "unknown");
+		}
+		sendCommand_ = (int (*)(int, char **, char **))dlsym(libh_, set_cmd_func_name);
+		if (sendCommand_ == NULL) {
+			const char *err_str = dlerror();
+			ALOGE("Error (%s) while searching for the interface command function", err_str ? err_str : "unknown");
+			return;
+		}
+	}
 }
 
 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;
+	if (sendCommandFini_) {
+		if (sendCommandFini_()) {
+			ALOGE("Can't shutdown the interface command API");
+		}
+	}
+	if (libh_) {
+		int err = dlclose(libh_);
+		if (err) {
+			const char *err_str = dlerror();
+			ALOGE("Error (%s) while closing the net interface command library", err_str ? err_str : "unknown");
+		}
+	}
 }
 
 /*
  * Arguments:
- *      argv[2] - wlan interface
- *      argv[3] - command
- *      argv[4] - argument
- *      rbuf    - returned buffer
+ *	  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;
+	int ret = -ENOSYS;
+	if (sendCommand_)
+		ret = sendCommand_(argc, argv, rbuf);
 
-    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;
+	return ret;
 }
diff --git a/InterfaceController.h b/InterfaceController.h
index dbedc13..e31cc11 100644
--- a/InterfaceController.h
+++ b/InterfaceController.h
@@ -5,7 +5,7 @@
  * 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
+ *	  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,
@@ -21,23 +21,24 @@
 #include <net/if.h>
 
 typedef struct android_wifi_priv_cmd {
-    char *buf;
-    int used_len;
-    int total_len;
+	char *buf;
+	int used_len;
+	int total_len;
 } android_wifi_priv_cmd;
 
 #define INTERFACE_MAX_BUFFER_SIZE	256
 
 class InterfaceController {
-    int iSock;
-    char *iBuf;
+ public:
+	InterfaceController();
+	virtual ~InterfaceController();
+	int interfaceCommand(int argc, char *argv[], char **rbuf);
 
-    int sendCommand(char *iface, char *cmd, char *buf, int buf_len);
-public:
-    InterfaceController();
-    virtual ~InterfaceController();
-
-    int interfaceCommand(int argc, char *argv[], char **rbuf);
+ private:
+	void *libh_;
+	int (*sendCommand_)(int argc, char *argv[], char **rbuf);
+	int (*sendCommandInit_)(void);
+	int (*sendCommandFini_)(void);
 };
 
 #endif