Merge "Add Syscalls wrapper for writev() and use in XfrmController"
am: 98799798dc

Change-Id: I6b2c6e5d169da7017caad9ac1f155edbf8990289
diff --git a/netutils_wrappers/Android.mk b/netutils_wrappers/Android.mk
new file mode 100644
index 0000000..ed1af34
--- /dev/null
+++ b/netutils_wrappers/Android.mk
@@ -0,0 +1,47 @@
+# Copyright (C) 2017 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.
+
+LOCAL_PATH := $(call my-dir)
+
+###
+### Wrapper binary.
+###
+include $(CLEAR_VARS)
+
+LOCAL_CFLAGS := -Wall -Werror
+LOCAL_CLANG := true
+LOCAL_MODULE := netutils-wrapper-1.0
+LOCAL_SHARED_LIBRARIES := libbase liblog
+LOCAL_SRC_FILES := NetUtilsWrapper-1.0.cpp main.cpp
+LOCAL_MODULE_SYMLINKS := \
+    iptables-wrapper-1.0 \
+    ip6tables-wrapper-1.0 \
+    ndc-wrapper-1.0 \
+    tc-wrapper-1.0 \
+    ip-wrapper-1.0
+
+include $(BUILD_EXECUTABLE)
+
+###
+### Wrapper unit tests.
+###
+include $(CLEAR_VARS)
+
+LOCAL_CFLAGS := -Wall -Werror
+LOCAL_CLANG := true
+LOCAL_MODULE := netutils_wrapper_test
+LOCAL_SHARED_LIBRARIES := libbase liblog
+LOCAL_SRC_FILES := NetUtilsWrapper-1.0.cpp NetUtilsWrapperTest-1.0.cpp
+
+include $(BUILD_NATIVE_TEST)
diff --git a/netutils_wrappers/NetUtilsWrapper-1.0.cpp b/netutils_wrappers/NetUtilsWrapper-1.0.cpp
new file mode 100644
index 0000000..a9fbf3f
--- /dev/null
+++ b/netutils_wrappers/NetUtilsWrapper-1.0.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2017 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 <regex>
+#include <string>
+
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <android-base/strings.h>
+
+#define LOG_TAG "NetUtilsWrapper"
+#include <cutils/log.h>
+
+#include "NetUtilsWrapper.h"
+
+#define SYSTEM_DIRNAME  "/system/bin/"
+
+#define OEM_IFACE "[^ ]*oem[0-9]+"
+#define RMNET_IFACE "(r_)?rmnet_(data)?[0-9]+"
+#define VENDOR_IFACE "(" OEM_IFACE "|" RMNET_IFACE ")"
+#define VENDOR_CHAIN "(oem_.*|nm_.*|qcom_.*)"
+
+// List of net utils wrapped by this program
+// The list MUST be in descending order of string length
+const char *netcmds[] = {
+    "ip6tables",
+    "iptables",
+    "ndc",
+    "tc",
+    "ip",
+    NULL,
+};
+
+// List of regular expressions of expected commands.
+const char *EXPECTED_REGEXPS[] = {
+#define CMD "^" SYSTEM_DIRNAME
+    // Create, delete, and manage OEM networks.
+    CMD "ndc network (create|destroy) oem[0-9]+( |$)",
+    CMD "ndc network interface (add|remove) oem[0-9]+ " VENDOR_IFACE,
+    CMD "ndc network route (add|remove) oem[0-9]+ ",
+    CMD "ndc ipfwd (enable|disable) ",
+    CMD "ndc ipfwd (add|remove) .*" VENDOR_IFACE,
+
+    // Manage vendor iptables rules.
+    CMD "ip(6)?tables -w.* (-A|-D|-F|-I|-N|-X) " VENDOR_CHAIN,
+    CMD "ip(6)?tables -w.* (-i|-o) " VENDOR_IFACE,
+
+    // Manage IPsec state.
+    CMD "ip xfrm .*",
+
+    // Manage vendor interfaces.
+    CMD "tc .* dev " VENDOR_IFACE,
+    CMD "ip( -4| -6)? (addr|address) (add|del|delete|flush).* dev " VENDOR_IFACE,
+
+    // Other activities observed on current devices. In future releases, these should be supported
+    // in a way that is less likely to interfere with general Android networking behaviour.
+    CMD "tc qdisc del dev root",
+    CMD "ip( -4| -6)? rule .* goto 13000 prio 11999",
+    CMD "ip( -4| -6)? rule .* prio 25000",
+    CMD "ip(6)?tables -w .* -j " VENDOR_CHAIN,
+    CMD "iptables -w -t mangle -[AD] PREROUTING -m socket --nowildcard --restore-skmark -j ACCEPT",
+    CMD "ndc network interface (add|remove) oem[0-9]+$",  // Invalid command: no interface removed.
+#undef CMD
+};
+
+bool checkExpectedCommand(int argc, char **argv) {
+    static bool loggedError = false;
+    std::vector<const char*> allArgs(argc);
+    for (int i = 0; i < argc; i++) {
+        allArgs[i] = argv[i];
+    }
+    std::string fullCmd = android::base::Join(allArgs, ' ');
+    for (size_t i = 0; i < ARRAY_SIZE(EXPECTED_REGEXPS); i++) {
+        const std::regex expectedRegexp(EXPECTED_REGEXPS[i], std::regex_constants::extended);
+        if (std::regex_search(fullCmd, expectedRegexp)) {
+            return true;
+        }
+    }
+    if (!loggedError) {
+        ALOGI("Unexpected command: %s", fullCmd.c_str());
+        fprintf(stderr, LOG_TAG ": Unexpected command: %s\n", fullCmd.c_str());
+        loggedError = true;
+    }
+    return false;
+}
+
+
+// This is the only gateway for vendor programs to reach net utils.
+int doMain(int argc, char **argv) {
+    char *progname = argv[0];
+    char *basename = NULL;
+
+    basename = strrchr(progname, '/');
+    basename = basename ? basename + 1 : progname;
+
+    for (int i = 0; netcmds[i]; ++i) {
+        size_t len = strlen(netcmds[i]);
+        if (!strncmp(basename, netcmds[i], len)) {
+            // truncate to match netcmds[i]
+            basename[len] = '\0';
+
+            // hardcode the path to /system so it cannot be overwritten
+            char *cmd;
+            if (asprintf(&cmd, "%s%s", SYSTEM_DIRNAME, basename) == -1) {
+                perror("asprintf");
+                exit(EXIT_FAILURE);
+            }
+            argv[0] = cmd;
+            if (checkExpectedCommand(argc, argv)) {
+                execv(cmd, argv);
+            }
+        }
+    }
+
+    // Invalid command. Reject and fail.
+    exit(EXIT_FAILURE);
+}
diff --git a/netutils_wrappers/NetUtilsWrapper.h b/netutils_wrappers/NetUtilsWrapper.h
new file mode 100644
index 0000000..127addc
--- /dev/null
+++ b/netutils_wrappers/NetUtilsWrapper.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#define ARRAY_SIZE(x) (sizeof((x)) / (sizeof(((x)[0]))))
+
+int doMain(int argc, char *argv[]);
+bool checkExpectedCommand(int argc, char **argv);
diff --git a/netutils_wrappers/NetUtilsWrapperTest-1.0.cpp b/netutils_wrappers/NetUtilsWrapperTest-1.0.cpp
new file mode 100644
index 0000000..a32cc3b
--- /dev/null
+++ b/netutils_wrappers/NetUtilsWrapperTest-1.0.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2017 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 <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include <android-base/strings.h>
+
+#include "NetUtilsWrapper.h"
+
+#define MAX_ARGS 128
+#define VALID true
+#define INVALID false
+
+struct Command {
+    bool valid;
+    std::string cmdString;
+};
+
+std::vector<Command> COMMANDS = {
+    {INVALID, "tc qdisc del dev root"},
+    {VALID,   "/system/bin/tc qdisc del dev root"},
+    {VALID,   "/system/bin/ip -6 addr add dev r_rmnet_data6 2001:db8::/64"},
+    {INVALID, "/system/bin/ip -6 addr add dev wlan2 2001:db8::/64"},
+    {VALID,   "/system/bin/ip6tables -w -A INPUT -j qcom_foo"},
+    {INVALID, "/system/bin/ip6tables -w -A INPUT -j routectrl_MANGLE_INPUT"},
+    {VALID,   "/system/bin/ip6tables -w -A INPUT -i rmnet_data9 -j routectrl_MANGLE_INPUT"},
+    {VALID,   "/system/bin/ip6tables -w -F nm_pre_ip4"},
+    {INVALID, "/system/bin/ip6tables -w -F INPUT"},
+    {VALID,   "/system/bin/ndc network interface add oem10"},
+    {VALID,   "/system/bin/ndc network interface add oem10 v_oem9"},
+    {VALID,   "/system/bin/ndc network interface add oem10 oem9"},
+    {INVALID, "/system/bin/ndc network interface add 100 v_oem9"},
+    {VALID,   "/system/bin/ndc network interface add oem10 r_rmnet_data0"},
+    {VALID,   "/system/bin/ip xfrm state"},
+};
+
+TEST(NetUtilsWrapperTest10, TestCommands) {
+    // Overwritten by each test case.
+    char *argv[MAX_ARGS];
+
+    for (const Command& cmd : COMMANDS) {
+        std::vector<std::string> pieces = android::base::Split(cmd.cmdString, " ");
+        ASSERT_LE(pieces.size(), ARRAY_SIZE(argv));
+        for (size_t i = 0; i < pieces.size(); i++) {
+            argv[i] = const_cast<char*>(pieces[i].c_str());
+        }
+        EXPECT_EQ(cmd.valid, checkExpectedCommand(pieces.size(), argv)) <<
+            "Expected command to be " <<
+            (cmd.valid ? "valid" : "invalid") << ", but was " <<
+            (cmd.valid ? "invalid" : "valid") << ": '" << cmd.cmdString << "'";
+    }
+}
diff --git a/netutils_wrappers/main.cpp b/netutils_wrappers/main.cpp
new file mode 100644
index 0000000..e2072a3
--- /dev/null
+++ b/netutils_wrappers/main.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2017 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 "NetUtilsWrapper.h"
+
+int main(int argc, char *argv[]) {
+    return doMain(argc, argv);
+}
diff --git a/tests/benchmarks/Android.mk b/tests/benchmarks/Android.mk
index bfcf600..c67d40e 100644
--- a/tests/benchmarks/Android.mk
+++ b/tests/benchmarks/Android.mk
@@ -13,40 +13,32 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-#
-# Note: netd benchmark can't build on nyc-mr2-dev, because google-benchmark project is out of date
-#       and won't be backported, and thus the content of this file is commented out to disable it.
-#       In order to run netd benchmark locally you can uncomment the content of this file and follow
-#       instructions in ag/1673408 (checkout that commit and build external/google-benchmark and
-#       system/netd locally and then run the benchmark locally)
-#
-#
-#LOCAL_PATH := $(call my-dir)
-#
-## APCT build target for metrics tests
-#include $(CLEAR_VARS)
-#LOCAL_MODULE := netd_benchmark
-#LOCAL_CFLAGS := -Wall -Werror -Wunused-parameter
-## Bug: http://b/29823425 Disable -Wvarargs for Clang update to r271374
-#LOCAL_CFLAGS += -Wno-varargs
+LOCAL_PATH := $(call my-dir)
 
-#EXTRA_LDLIBS := -lpthread
-#LOCAL_SHARED_LIBRARIES += libbase libbinder liblog libnetd_client
-#LOCAL_STATIC_LIBRARIES += libnetd_test_dnsresponder libutils
+# APCT build target for metrics tests
+include $(CLEAR_VARS)
+LOCAL_MODULE := netd_benchmark
+LOCAL_CFLAGS := -Wall -Werror -Wunused-parameter
+# Bug: http://b/29823425 Disable -Wvarargs for Clang update to r271374
+LOCAL_CFLAGS += -Wno-varargs
 
-#LOCAL_AIDL_INCLUDES := system/netd/server/binder
-#LOCAL_C_INCLUDES += system/netd/include \
-#                    system/netd/client \
-#                    system/netd/server \
-#                    system/netd/server/binder \
-#                    system/netd/tests/dns_responder \
-#                    bionic/libc/dns/include
+EXTRA_LDLIBS := -lpthread
+LOCAL_SHARED_LIBRARIES += libbase libbinder liblog libnetd_client
+LOCAL_STATIC_LIBRARIES += libnetd_test_dnsresponder libutils
 
-#LOCAL_SRC_FILES := main.cpp \
-#                   connect_benchmark.cpp \
-#                   dns_benchmark.cpp \
-#                   ../../server/binder/android/net/metrics/INetdEventListener.aidl
+LOCAL_AIDL_INCLUDES := system/netd/server/binder
+LOCAL_C_INCLUDES += system/netd/include \
+                    system/netd/client \
+                    system/netd/server \
+                    system/netd/server/binder \
+                    system/netd/tests/dns_responder \
+                    bionic/libc/dns/include
 
-#LOCAL_MODULE_TAGS := eng tests
+LOCAL_SRC_FILES := main.cpp \
+                   connect_benchmark.cpp \
+                   dns_benchmark.cpp \
+                   ../../server/binder/android/net/metrics/INetdEventListener.aidl
 
-#include $(BUILD_NATIVE_BENCHMARK)
+LOCAL_MODULE_TAGS := eng tests
+
+include $(BUILD_NATIVE_BENCHMARK)