]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Android platform specific changes.
authorArne Schwabe <arne@rfc2549.org>
Tue, 30 Apr 2013 19:29:11 +0000 (21:29 +0200)
committerGert Doering <gert@greenie.muc.de>
Wed, 1 May 2013 10:25:23 +0000 (12:25 +0200)
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

Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <1367350151-23089-1-git-send-email-arne@rfc2549.org>
URL: http://article.gmane.org/gmane.network.openvpn.devel/7570
Signed-off-by: Gert Doering <gert@greenie.muc.de>
src/openvpn/manage.c
src/openvpn/manage.h
src/openvpn/options.c
src/openvpn/route.c
src/openvpn/socket.c
src/openvpn/ssl.c
src/openvpn/syshead.h
src/openvpn/tun.c
src/openvpn/tun.h

index f8258b5975dea11a3ccc5384475bf231f26b73ea..5d2c36c56b89b81750d3e5ed8f8951abe0069323 100644 (file)
@@ -1849,6 +1849,20 @@ static ssize_t man_recv_with_fd (int fd, void *ptr, size_t nbytes, int flags, in
 
   return (n);
 }
+
+/*
+ * The android control method will instruct the GUI part of openvpn to do
+ * the route/ifconfig/open tun command.   See doc/android.txt for details.
+ */
+bool management_android_control (struct management *man, const char *command, const char *msg)
+{
+  struct user_pass up;
+  CLEAR(up);
+  strncpy (up.username, msg, sizeof(up.username)-1);
+
+  management_query_user_pass(management, &up , command, GET_USER_PASS_NEED_OK,(void*) 0);
+  return strcmp ("ok", up.password)==0;
+}
 #endif
 
 static int
index f5d776ef918b96a2c43ba7081dc43cdca39c56b1..b08bb78e89a7545083c4a50f9742d2a8882338a4 100644 (file)
@@ -376,6 +376,10 @@ bool management_query_user_pass (struct management *man,
                                 const unsigned int flags,
                                 const char *static_challenge);
 
+#ifdef TARGET_ANDROID
+bool management_android_control (struct management *man, const char *command, const char *msg);
+#endif
+
 bool management_should_daemonize (struct management *man);
 bool management_would_hold (struct management *man);
 bool management_hold (struct management *man);
index 05c6da2daa62007304538254becdb97c96ba9dec..a8712c81c959a5f498e61b4f4bc406971b1bc3cd 100644 (file)
@@ -1124,8 +1124,10 @@ show_tuntap_options (const struct tuntap_options *o)
   show_dhcp_option_addrs ("NBDD", o->nbdd, o->nbdd_len);
 }
 
+#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);
index 4c1e14e91d8c2692c12b19bc33c6c929d281394c..f5b5efa1ed95b0732f62bc9a9d1c70f50883c203 100644 (file)
@@ -1342,6 +1342,12 @@ 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 buffer out = alloc_buf_gc (64, &gc);
+
+  buf_printf (&out, "%s %s", network, netmask);
+  management_android_control (management, "ROUTE", buf_bptr(&out));
+
 #elif defined (WIN32)
   {
     DWORD ai = TUN_ADAPTER_INDEX_INVALID;
@@ -1616,6 +1622,13 @@ 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 buffer out = alloc_buf_gc (64, &gc);
+
+    buf_printf (&out, "%s/%d", network, r6->netbits);
+
+    management_android_control (management, "ROUTE6", buf_bptr(&out));
+
 #elif defined (WIN32)
 
   /* netsh interface ipv6 add route 2001:db8::/32 MyTunDevice */
@@ -1875,7 +1888,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 +2439,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)
index 8eb112bf319bd2085f630879e21615cb69a5b70c..94d2b1030fb75f64cf58e6f14187bea14a40157e 100644 (file)
@@ -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
+  /* pass socket FD to management interface to pass on to VPNService API
+   * as "protected socket" (exempt from being routed into tunnel)
+   */
+
+  management->connection.fdtosend = sock->sd;
+  management_android_control (management, "PROTECTFD", __func__);
+#endif
+
 }
 
 /*
index 43b398040a2faa8a524a9ed3077632379d093559..09cf3001958a7e6b58a0850e56f5b9d7c2a11747 100644 (file)
@@ -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
index 4db29cc311fde77e822a804e7b1bbf1999dc80fa..0c3e4ee5798e071d664d909f48f10a6beb089f4a 100644 (file)
 #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>
index a3612332a0d129dbb17ea9c5ad5f6d4842ffc6ea..f7443b4ab226c656053d32c732084e9483dd19cd 100644 (file)
@@ -48,6 +48,7 @@
 #include "win32.h"
 
 #include "memdbg.h"
+#include <string.h>
 
 #ifdef WIN32
 
@@ -764,6 +765,34 @@ do_ifconfig (struct tuntap *tt,
       tt->did_ifconfig = true;
 
 #endif /*ENABLE_IPROUTE*/
+#elif defined(TARGET_ANDROID)
+
+      if (do_ipv6) {
+          struct buffer out6 = alloc_buf_gc (64, &gc);
+          buf_printf (&out6, "%s/%d", ifconfig_ipv6_local,tt->netbits_ipv6);
+          management_android_control(management, "IFCONFIG6",buf_bptr(&out6));
+      }
+
+      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);
+      management_android_control (management, "IFCONFIG", buf_bptr(&out));
+
 #elif defined(TARGET_SOLARIS)
 
       /* Solaris 2.6 (and 7?) cannot set all parameters in one go...
@@ -1368,8 +1397,62 @@ 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 ();
+  bool opentun;
+
+  for (i = 0; i < tt->options.dns_len; ++i) {
+    management_android_control (management, "DNSSERVER",
+                                print_in_addr_t(tt->options.dns[i], 0, &gc));
+  }
+
+  if(tt->options.domain)
+    management_android_control (management, "DNSDOMAIN", tt->options.domain);
+
+  opentun = management_android_control (management, "OPENTUN", dev);
+
+  /* Pick up the fd from management interface after calling the OPENTUN command */
+  tt->fd = management->connection.lastfdreceived;
+  management->connection.lastfdreceived=-1;
+
+  /* Set the actual name to a dummy name */
+  tt->actual_name = string_alloc (ANDROID_TUNNAME, NULL);
+
+  if ((tt->fd < 0) || !opentun)
+    msg (M_ERR, "ERROR: Cannot open TUN");
+
+  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
index 63e4b5c833c66417e26936255453f13e2afe89db..956ad8d822aaee7a49a4f04d6f5e46a67093403c 100644 (file)
@@ -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
 }