Add a netd interface command to disable ND offload.

This will be used to support 464xlat on wifi and IPv6 tethering.

Bug: 12111730
Change-Id: I3b97f4dfb787b2c5d5021811c6da51850bdc70d1
diff --git a/server/InterfaceController.cpp b/server/InterfaceController.cpp
index 061060f..b38c137 100644
--- a/server/InterfaceController.cpp
+++ b/server/InterfaceController.cpp
@@ -18,6 +18,7 @@
 
 #define LOG_TAG "InterfaceController"
 #include <cutils/log.h>
+#include <logwrap/logwrap.h>
 
 #include "InterfaceController.h"
 #include "RouteController.h"
@@ -26,6 +27,8 @@
 
 const char sys_net_path[] = "/sys/class/net";
 
+const char wl_util_path[] = "/system/xbin/wlutil";
+
 InterfaceController::InterfaceController() {
 	// Initial IPv6 settings.
 	// By default, accept_ra is set to 1 (accept RAs unless forwarding is on) on all interfaces.
@@ -66,6 +69,29 @@
 	return writeIPv6ProcPath(interface, "use_tempaddr", on ? "2" : "0");
 }
 
+// Enables or disables IPv6 ND offload. This is useful for 464xlat on wifi, IPv6 tethering, and
+// generally implementing IPv6 neighbour discovery and duplicate address detection properly.
+// TODO: This should be implemented in wpa_supplicant via driver commands instead.
+int InterfaceController::setIPv6NdOffload(char* interface, const int on) {
+    // Only supported on Broadcom chipsets via wlutil for now.
+    if (access(wl_util_path, X_OK) == 0) {
+        const char *argv[] = {
+            wl_util_path,
+            "-a",
+            interface,
+            "ndoe",
+            on ? "1" : "0"
+        };
+        int ret = android_fork_execvp(ARRAY_SIZE(argv), const_cast<char**>(argv), NULL,
+                                      false, false);
+        ALOGD("%s ND offload on %s: %d (%s)",
+              (on ? "enabling" : "disabling"), interface, ret, strerror(errno));
+        return ret;
+    } else {
+        return 0;
+    }
+}
+
 int InterfaceController::isInterfaceName(const char *name) {
 	return strcmp(name, ".") &&
 		strcmp(name, "..") &&