ipsec-tools: create a TUN interface for internal network.

Assume that the interface with default route is eth0. There are at
least three different ways to setup internal network.

1. Set internal IP and routes with default gateway on eth0:1.
2. Add a host route on eth0. Set internal IP and direct routes on eth0:1.
3. Add a host route on eth0. Set internal IP and direct routes on tun0.

SPD is set to send all packets from internel IP through the tunnel. Packets
are encapsulated and the final destination is always the VPN server. The
kernel will re-route the packets after re-writing them.

In the first method, the kernel always gets the default gateway as all the
routing rules are added with it. In the second method, internal routes do
not need a gateway since packets will hit the host route after re-routing.
The third method pushes even further since packet will never reach tun0.

In Android, we use the third method for two reasons, easier to clean up
and monitor. The first method has the advantage of not using a host route.
However, it cannot be cleaned up by simply shutting down eth0:1 because
routing rules might stay. The other methods do not have this problem. They
need to handle the host route, but that is much easier. When racoon dies,
tun0 goes away and posts an netlink event, but eth0:1 does not. Therefore,
the third method is much easier to monitor since it gives us the same
behavior with other VPN types.

Change-Id: I0a6eeef471b5a64de39a907f4f4428e86c0b2484
diff --git a/main.c b/main.c
index 1f1b402..097b9c2 100644
--- a/main.c
+++ b/main.c
@@ -20,15 +20,6 @@
 #include <signal.h>
 #include <poll.h>
 
-#ifdef ANDROID_CHANGES
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <android/log.h>
-#include <cutils/sockets.h>
-#include <private/android_filesystem_config.h>
-#endif
-
 #include "config.h"
 #include "gcmalloc.h"
 #include "session.h"
@@ -37,6 +28,20 @@
 
 #ifdef ANDROID_CHANGES
 
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+
+#include <android/log.h>
+#include <cutils/sockets.h>
+#include <private/android_filesystem_config.h>
+
 static int get_control_and_arguments(int *argc, char ***argv)
 {
     static char *args[32];
@@ -87,6 +92,27 @@
     return control;
 }
 
+void android_setenv(char ***envp)
+{
+    int tun = open("/dev/tun", 0);
+    struct ifreq ifr = {.ifr_flags = IFF_TUN};
+    char env[16 + sizeof(ifr.ifr_name)];
+    int i = 0;
+
+    if (ioctl(tun, TUNSETIFF, &ifr)) {
+        do_plog(LLV_ERROR, "Cannot allocate TUN: %s\n", strerror(errno));
+        exit(1);
+    }
+    snprintf(env, sizeof(env), "INTERFACE=%s", ifr.ifr_name);
+
+    while ((*envp)[i]) {
+        ++i;
+    }
+    *envp = racoon_realloc(*envp, sizeof(char *) * (i + 1));
+    (*envp)[i] = racoon_strdup(env);
+    (*envp)[i + 1] = NULL;
+}
+
 #endif
 
 extern void setup(int argc, char **argv);
diff --git a/setup.c b/setup.c
index 0900144..2c85e3c 100644
--- a/setup.c
+++ b/setup.c
@@ -328,7 +328,7 @@
 
 static vchar_t *strtovchar(char *string)
 {
-    vchar_t *vchar = string ? vmalloc(strlen(string)) : NULL;
+    vchar_t *vchar = string ? vmalloc(strlen(string) + 1) : NULL;
     if (vchar) {
         memcpy(vchar->v, string, vchar->l);
     }
@@ -341,10 +341,8 @@
         char *username, char *password, char *phase1_up, char *script_arg)
 {
     struct xauth_rmconf *xauth = racoon_calloc(1, sizeof(struct xauth_rmconf));
-    xauth->login = vmalloc(strlen(username) + 1);
-    memcpy(xauth->login->v, username, xauth->login->l);
-    xauth->pass = vmalloc(strlen(password) + 1);
-    memcpy(xauth->pass->v, password, xauth->pass->l);
+    xauth->login = strtovchar(username);
+    xauth->pass = strtovchar(password);
     remoteconf->xauth = xauth;
     remoteconf->mode_cfg = TRUE;
     remoteconf->script[SCRIPT_PHASE1_UP] = strtovchar(phase1_up);
@@ -550,6 +548,8 @@
     return *envp ? &(*envp)[length + 1] : "";
 }
 
+extern void android_setenv(char ***envp);
+
 int privsep_script_exec(char *script, int name, char * const *envp)
 {
     /* Racoon ignores INTERNAL_IP6_ADDRESS, so we only do IPv4. */
@@ -560,6 +560,9 @@
             get_env(envp, "REMOTE_PORT"));
 
     if (addr4 && local && remote) {
+#ifdef ANDROID_CHANGES
+        android_setenv((char ***)&envp);
+#endif
         spdadd(addr4, NULL, IPPROTO_IP, local, remote);
     } else {
         do_plog(LLV_ERROR, "Cannot find parameters to generate SPD policy.\n");