On Android 4.0 (TARGET_ANDROID) the real opening of the tun is handled by the 
(Java) application controlling OpenVPN. Instead of calling ifconfig/route call 
the management to do the work. When running openvpn as root openvpn should be 
compiled as TARGET_LINUX
---
 src/openvpn/options.c |    6 ++++
 src/openvpn/route.c   |   25 ++++++++++++--
 src/openvpn/socket.c  |   10 ++++++
 src/openvpn/ssl.c     |    2 ++
 src/openvpn/syshead.h |    2 +-
 src/openvpn/tun.c     |   92 ++++++++++++++++++++++++++++++++++++++++++++++++-
 src/openvpn/tun.h     |    8 ++++-
 7 files changed, 140 insertions(+), 5 deletions(-)

diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 05c6da2..9fdfd88 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -1125,7 +1125,9 @@ show_tuntap_options (const struct tuntap_options *o)
 }

 #endif
+#endif

+#if defined(WIN32) || defined(TARGET_ANDROID) 
 static void
 dhcp_option_address_parse (const char *name, const char *parm, in_addr_t 
*array, int *len, int msglevel)
 {
@@ -5935,6 +5937,8 @@ add_option (struct options *options,
       to->ip_win32_type = index;
       to->ip_win32_defined = true; 
     }
+#endif
+#if defined(WIN32) || defined(TARGET_ANDROID)
   else if (streq (p[0], "dhcp-option") && p[1])
     {
       struct tuntap_options *o = &options->tuntap_options;
@@ -5986,6 +5990,8 @@ add_option (struct options *options,
        }
       o->dhcp_options = true;
     }
+#endif
+#ifdef WIN32
   else if (streq (p[0], "show-adapters"))
     {
       VERIFY_PERMISSION (OPT_P_GENERAL);
diff --git a/src/openvpn/route.c b/src/openvpn/route.c
index 4c1e14e..f32c1fe 100644
--- a/src/openvpn/route.c
+++ b/src/openvpn/route.c
@@ -1342,6 +1342,17 @@ add_route (struct route *r,
   argv_msg (D_ROUTE, &argv);
   status = openvpn_execve_check (&argv, es, 0, "ERROR: Linux route add command 
failed");

+#elif defined (TARGET_ANDROID)
+
+    struct user_pass up;    
+    struct buffer out = alloc_buf_gc (64, &gc);
+
+    buf_printf (&out, "%s %s", network, netmask);
+
+    strcpy(up.username, buf_bptr(&out));
+    management_query_user_pass(management, &up , "ROUTE", 
GET_USER_PASS_NEED_OK,(void*) 0);
+
+
 #elif defined (WIN32)
   {
     DWORD ai = TUN_ADAPTER_INDEX_INVALID;
@@ -1616,6 +1627,15 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct 
tuntap *tt, unsigned int fla
   argv_msg (D_ROUTE, &argv);
   status = openvpn_execve_check (&argv, es, 0, "ERROR: Linux route -6/-A inet6 
add command failed");

+#elif defined (TARGET_ANDROID)
+    struct user_pass up;    
+    struct buffer out = alloc_buf_gc (64, &gc);
+    
+    buf_printf (&out, "%s/%d", network, r6->netbits);
+    
+    strcpy(up.username, buf_bptr(&out));
+    management_query_user_pass(management, &up , "ROUTE6", 
GET_USER_PASS_NEED_OK,(void*) 0);
+
 #elif defined (WIN32)

   /* netsh interface ipv6 add route 2001:db8::/32 MyTunDevice */
@@ -1875,7 +1895,8 @@ delete_route (struct route *r,

   argv_msg (D_ROUTE, &argv);
   openvpn_execve_check (&argv, es, 0, "ERROR: OpenBSD/NetBSD route delete 
command failed");
-
+#elif defined(TARGET_ANDROID)
+  msg (M_NONFATAL, "Sorry, deleting routes on Android is not possible. The 
VpnService API allows routes to be set on connect only.");
 #else
   msg (M_FATAL, "Sorry, but I don't know how to do 'route' commands on this 
operating system.  Try putting your routes in a --route-up script");
 #endif
@@ -2425,7 +2446,7 @@ show_routes (int msglev)
   gc_free (&gc);
 }

-#elif defined(TARGET_LINUX)
+#elif defined(TARGET_LINUX) || defined(TARGET_ANDROID)

 void
 get_default_gateway (struct route_gateway_info *rgi)
diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c
index 8eb112b..483a04d 100644
--- a/src/openvpn/socket.c
+++ b/src/openvpn/socket.c
@@ -38,6 +38,7 @@
 #include "ps.h"
 #include "manage.h"
 #include "misc.h"
+#include "manage.h"

 #include "memdbg.h"

@@ -725,6 +726,15 @@ create_socket (struct link_socket *sock)
     {
       ASSERT (0);
     }
+#ifdef TARGET_ANDROID
+    struct user_pass up;
+    strcpy(up.username ,__func__);
+    management->connection.fdtosend = sock->sd;
+    management_query_user_pass(management, &up , "PROTECTFD", 
GET_USER_PASS_NEED_OK,(void*) 0);
+
+
+#endif
+    
 }

 /*
diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
index 43b3980..b367386 100644
--- a/src/openvpn/ssl.c
+++ b/src/openvpn/ssl.c
@@ -1797,6 +1797,8 @@ push_peer_info(struct buffer *buf, struct tls_session 
*session)
       buf_printf (&out, "IV_PLAT=netbsd\n");
 #elif defined(TARGET_FREEBSD)
       buf_printf (&out, "IV_PLAT=freebsd\n");
+#elif defined(TARGET_ANDROID)
+      buf_printf(&out, "IV_PLAT=android\n");
 #elif defined(WIN32)
       buf_printf (&out, "IV_PLAT=win\n");
 #endif
diff --git a/src/openvpn/syshead.h b/src/openvpn/syshead.h
index 4db29cc..0c3e4ee 100644
--- a/src/openvpn/syshead.h
+++ b/src/openvpn/syshead.h
@@ -212,7 +212,7 @@
 #include <net/if_tap.h>
 #endif

-#ifdef TARGET_LINUX
+#if defined(TARGET_LINUX) || defined (TARGET_ANDROID)

 #if defined(HAVE_NETINET_IF_ETHER_H)
 #include <netinet/if_ether.h>
diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c
index a361233..3deaba3 100644
--- a/src/openvpn/tun.c
+++ b/src/openvpn/tun.c
@@ -48,6 +48,7 @@
 #include "win32.h"

 #include "memdbg.h"
+#include <string.h>

 #ifdef WIN32

@@ -764,6 +765,40 @@ do_ifconfig (struct tuntap *tt,
       tt->did_ifconfig = true;

 #endif /*ENABLE_IPROUTE*/
+#elif defined(TARGET_ANDROID)
+        
+        
+        if (do_ipv6) {
+            struct user_pass up6;    
+            struct buffer out6 = alloc_buf_gc (64, &gc);
+            buf_printf (&out6, "%s/%d", ifconfig_ipv6_local,tt->netbits_ipv6);
+            strcpy(up6.username, buf_bptr(&out6));
+            management_query_user_pass(management, &up6 , "IFCONFIG6", 
GET_USER_PASS_NEED_OK,(void*) 0);
+        }
+
+        struct user_pass up;    
+        struct buffer out = alloc_buf_gc (64, &gc);
+        char* top;
+        switch(tt->topology) {
+            case TOP_NET30:
+                top = "net30";
+                break;
+            case TOP_P2P:
+                top="p2p";
+                break;
+            case TOP_SUBNET:
+                top="subnet";
+                break;
+            default:
+                top="undef";
+        }
+        
+        buf_printf (&out, "%s %s %d %s", ifconfig_local, 
ifconfig_remote_netmask, tun_mtu,top);
+        strcpy(up.username, buf_bptr(&out));
+        management_query_user_pass(management, &up , "IFCONFIG", 
GET_USER_PASS_NEED_OK,(void*) 0);
+
+
+        
 #elif defined(TARGET_SOLARIS)

       /* Solaris 2.6 (and 7?) cannot set all parameters in one go...
@@ -1368,8 +1403,63 @@ close_tun_generic (struct tuntap *tt)

 #endif

-#if defined(TARGET_LINUX)
+#if defined (TARGET_ANDROID)
+void
+open_tun (const char *dev, const char *dev_type, const char *dev_node, struct 
tuntap *tt)
+{
+#define ANDROID_TUNNAME "vpnservice-tun"
+    int i;
+    struct user_pass up;
+    struct gc_arena gc = gc_new ();
+    
+    for (i = 0; i < tt->options.dns_len; ++i) {
+        strcpy(up.username, print_in_addr_t(tt->options.dns[i], 0, &gc));
+        management_query_user_pass(management, &up , "DNSSERVER", 
GET_USER_PASS_NEED_OK,(void*) 0);
+    }
+
+    if(tt->options.domain) {
+        strcpy(up.username , tt->options.domain);
+        management_query_user_pass(management, &up , "DNSDOMAIN", 
GET_USER_PASS_NEED_OK,(void*) 0);
+    }
+    
+    strcpy(up.username , dev);
+    management_query_user_pass(management, &up , "OPENTUN", 
GET_USER_PASS_NEED_OK,(void*) 0);
+
+    tt->fd = management->connection.lastfdreceived;
+    management->connection.lastfdreceived=-1;
+    
+    if( (tt->fd < 0) || ! (strcmp("ok",up.password)==0)) {
+        msg (M_ERR, "ERROR: Cannot open TUN");
+    }
+    /* Set the actual name to a dummy name to enable scripts */
+    tt->actual_name = malloc(sizeof(ANDROID_TUNNAME));
+    strcpy(tt->actual_name, ANDROID_TUNNAME);
+    gc_free (&gc);
+}
+
+void
+close_tun (struct tuntap *tt)
+{
+    if (tt)
+    {
+        close_tun_generic (tt);
+        free (tt);
+    }
+}
+
+int
+write_tun (struct tuntap* tt, uint8_t *buf, int len)
+{
+    return write (tt->fd, buf, len);
+}
+
+int
+read_tun (struct tuntap* tt, uint8_t *buf, int len)
+{
+    return read (tt->fd, buf, len);
+}

+#elif defined(TARGET_LINUX)
 #ifdef HAVE_LINUX_IF_TUN_H     /* New driver support */

 #ifndef HAVE_LINUX_SOCKIOS_H
diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h
index 63e4b5c..956ad8d 100644
--- a/src/openvpn/tun.h
+++ b/src/openvpn/tun.h
@@ -38,7 +38,7 @@
 #include "proto.h"
 #include "misc.h"

-#ifdef WIN32
+#if defined(WIN32) || defined(TARGET_ANDROID)

 #define TUN_ADAPTER_INDEX_INVALID ((DWORD)-1)

@@ -292,6 +292,8 @@ ifconfig_order(void)
   return IFCONFIG_AFTER_TUN_OPEN;
 #elif defined(WIN32)
   return IFCONFIG_BEFORE_TUN_OPEN;
+#elif defined(TARGET_ANDROID)
+  return IFCONFIG_BEFORE_TUN_OPEN;
 #else
   return IFCONFIG_DEFAULT;
 #endif
@@ -304,7 +306,11 @@ ifconfig_order(void)
 static inline int
 route_order(void)
 {
+#if defined(TARGET_ANDROID)
+    return ROUTE_BEFORE_TUN;
+#else
     return ROUTE_ORDER_DEFAULT;
+#endif
 }


-- 
1.7.9.5


Reply via email to