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>
... | ... |
@@ -1849,6 +1849,20 @@ static ssize_t man_recv_with_fd (int fd, void *ptr, size_t nbytes, int flags, in |
1849 | 1849 |
|
1850 | 1850 |
return (n); |
1851 | 1851 |
} |
1852 |
+ |
|
1853 |
+/* |
|
1854 |
+ * The android control method will instruct the GUI part of openvpn to do |
|
1855 |
+ * the route/ifconfig/open tun command. See doc/android.txt for details. |
|
1856 |
+ */ |
|
1857 |
+bool management_android_control (struct management *man, const char *command, const char *msg) |
|
1858 |
+{ |
|
1859 |
+ struct user_pass up; |
|
1860 |
+ CLEAR(up); |
|
1861 |
+ strncpy (up.username, msg, sizeof(up.username)-1); |
|
1862 |
+ |
|
1863 |
+ management_query_user_pass(management, &up , command, GET_USER_PASS_NEED_OK,(void*) 0); |
|
1864 |
+ return strcmp ("ok", up.password)==0; |
|
1865 |
+} |
|
1852 | 1866 |
#endif |
1853 | 1867 |
|
1854 | 1868 |
static int |
... | ... |
@@ -376,6 +376,10 @@ bool management_query_user_pass (struct management *man, |
376 | 376 |
const unsigned int flags, |
377 | 377 |
const char *static_challenge); |
378 | 378 |
|
379 |
+#ifdef TARGET_ANDROID |
|
380 |
+bool management_android_control (struct management *man, const char *command, const char *msg); |
|
381 |
+#endif |
|
382 |
+ |
|
379 | 383 |
bool management_should_daemonize (struct management *man); |
380 | 384 |
bool management_would_hold (struct management *man); |
381 | 385 |
bool management_hold (struct management *man); |
... | ... |
@@ -1125,7 +1125,9 @@ show_tuntap_options (const struct tuntap_options *o) |
1125 | 1125 |
} |
1126 | 1126 |
|
1127 | 1127 |
#endif |
1128 |
+#endif |
|
1128 | 1129 |
|
1130 |
+#if defined(WIN32) || defined(TARGET_ANDROID) |
|
1129 | 1131 |
static void |
1130 | 1132 |
dhcp_option_address_parse (const char *name, const char *parm, in_addr_t *array, int *len, int msglevel) |
1131 | 1133 |
{ |
... | ... |
@@ -5935,6 +5937,8 @@ add_option (struct options *options, |
5935 | 5935 |
to->ip_win32_type = index; |
5936 | 5936 |
to->ip_win32_defined = true; |
5937 | 5937 |
} |
5938 |
+#endif |
|
5939 |
+#if defined(WIN32) || defined(TARGET_ANDROID) |
|
5938 | 5940 |
else if (streq (p[0], "dhcp-option") && p[1]) |
5939 | 5941 |
{ |
5940 | 5942 |
struct tuntap_options *o = &options->tuntap_options; |
... | ... |
@@ -5986,6 +5990,8 @@ add_option (struct options *options, |
5986 | 5986 |
} |
5987 | 5987 |
o->dhcp_options = true; |
5988 | 5988 |
} |
5989 |
+#endif |
|
5990 |
+#ifdef WIN32 |
|
5989 | 5991 |
else if (streq (p[0], "show-adapters")) |
5990 | 5992 |
{ |
5991 | 5993 |
VERIFY_PERMISSION (OPT_P_GENERAL); |
... | ... |
@@ -1342,6 +1342,12 @@ add_route (struct route *r, |
1342 | 1342 |
argv_msg (D_ROUTE, &argv); |
1343 | 1343 |
status = openvpn_execve_check (&argv, es, 0, "ERROR: Linux route add command failed"); |
1344 | 1344 |
|
1345 |
+#elif defined (TARGET_ANDROID) |
|
1346 |
+ struct buffer out = alloc_buf_gc (64, &gc); |
|
1347 |
+ |
|
1348 |
+ buf_printf (&out, "%s %s", network, netmask); |
|
1349 |
+ management_android_control (management, "ROUTE", buf_bptr(&out)); |
|
1350 |
+ |
|
1345 | 1351 |
#elif defined (WIN32) |
1346 | 1352 |
{ |
1347 | 1353 |
DWORD ai = TUN_ADAPTER_INDEX_INVALID; |
... | ... |
@@ -1616,6 +1622,13 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int fla |
1616 | 1616 |
argv_msg (D_ROUTE, &argv); |
1617 | 1617 |
status = openvpn_execve_check (&argv, es, 0, "ERROR: Linux route -6/-A inet6 add command failed"); |
1618 | 1618 |
|
1619 |
+#elif defined (TARGET_ANDROID) |
|
1620 |
+ struct buffer out = alloc_buf_gc (64, &gc); |
|
1621 |
+ |
|
1622 |
+ buf_printf (&out, "%s/%d", network, r6->netbits); |
|
1623 |
+ |
|
1624 |
+ management_android_control (management, "ROUTE6", buf_bptr(&out)); |
|
1625 |
+ |
|
1619 | 1626 |
#elif defined (WIN32) |
1620 | 1627 |
|
1621 | 1628 |
/* netsh interface ipv6 add route 2001:db8::/32 MyTunDevice */ |
... | ... |
@@ -1875,7 +1888,8 @@ delete_route (struct route *r, |
1875 | 1875 |
|
1876 | 1876 |
argv_msg (D_ROUTE, &argv); |
1877 | 1877 |
openvpn_execve_check (&argv, es, 0, "ERROR: OpenBSD/NetBSD route delete command failed"); |
1878 |
- |
|
1878 |
+#elif defined(TARGET_ANDROID) |
|
1879 |
+ msg (M_NONFATAL, "Sorry, deleting routes on Android is not possible. The VpnService API allows routes to be set on connect only."); |
|
1879 | 1880 |
#else |
1880 | 1881 |
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"); |
1881 | 1882 |
#endif |
... | ... |
@@ -2425,7 +2439,7 @@ show_routes (int msglev) |
2425 | 2425 |
gc_free (&gc); |
2426 | 2426 |
} |
2427 | 2427 |
|
2428 |
-#elif defined(TARGET_LINUX) |
|
2428 |
+#elif defined(TARGET_LINUX) || defined(TARGET_ANDROID) |
|
2429 | 2429 |
|
2430 | 2430 |
void |
2431 | 2431 |
get_default_gateway (struct route_gateway_info *rgi) |
... | ... |
@@ -38,6 +38,7 @@ |
38 | 38 |
#include "ps.h" |
39 | 39 |
#include "manage.h" |
40 | 40 |
#include "misc.h" |
41 |
+#include "manage.h" |
|
41 | 42 |
|
42 | 43 |
#include "memdbg.h" |
43 | 44 |
|
... | ... |
@@ -725,6 +726,15 @@ create_socket (struct link_socket *sock) |
725 | 725 |
{ |
726 | 726 |
ASSERT (0); |
727 | 727 |
} |
728 |
+#ifdef TARGET_ANDROID |
|
729 |
+ /* pass socket FD to management interface to pass on to VPNService API |
|
730 |
+ * as "protected socket" (exempt from being routed into tunnel) |
|
731 |
+ */ |
|
732 |
+ |
|
733 |
+ management->connection.fdtosend = sock->sd; |
|
734 |
+ management_android_control (management, "PROTECTFD", __func__); |
|
735 |
+#endif |
|
736 |
+ |
|
728 | 737 |
} |
729 | 738 |
|
730 | 739 |
/* |
... | ... |
@@ -1797,6 +1797,8 @@ push_peer_info(struct buffer *buf, struct tls_session *session) |
1797 | 1797 |
buf_printf (&out, "IV_PLAT=netbsd\n"); |
1798 | 1798 |
#elif defined(TARGET_FREEBSD) |
1799 | 1799 |
buf_printf (&out, "IV_PLAT=freebsd\n"); |
1800 |
+#elif defined(TARGET_ANDROID) |
|
1801 |
+ buf_printf (&out, "IV_PLAT=android\n"); |
|
1800 | 1802 |
#elif defined(WIN32) |
1801 | 1803 |
buf_printf (&out, "IV_PLAT=win\n"); |
1802 | 1804 |
#endif |
... | ... |
@@ -48,6 +48,7 @@ |
48 | 48 |
#include "win32.h" |
49 | 49 |
|
50 | 50 |
#include "memdbg.h" |
51 |
+#include <string.h> |
|
51 | 52 |
|
52 | 53 |
#ifdef WIN32 |
53 | 54 |
|
... | ... |
@@ -764,6 +765,34 @@ do_ifconfig (struct tuntap *tt, |
764 | 764 |
tt->did_ifconfig = true; |
765 | 765 |
|
766 | 766 |
#endif /*ENABLE_IPROUTE*/ |
767 |
+#elif defined(TARGET_ANDROID) |
|
768 |
+ |
|
769 |
+ if (do_ipv6) { |
|
770 |
+ struct buffer out6 = alloc_buf_gc (64, &gc); |
|
771 |
+ buf_printf (&out6, "%s/%d", ifconfig_ipv6_local,tt->netbits_ipv6); |
|
772 |
+ management_android_control(management, "IFCONFIG6",buf_bptr(&out6)); |
|
773 |
+ } |
|
774 |
+ |
|
775 |
+ struct buffer out = alloc_buf_gc (64, &gc); |
|
776 |
+ |
|
777 |
+ char* top; |
|
778 |
+ switch(tt->topology) { |
|
779 |
+ case TOP_NET30: |
|
780 |
+ top="net30"; |
|
781 |
+ break; |
|
782 |
+ case TOP_P2P: |
|
783 |
+ top="p2p"; |
|
784 |
+ break; |
|
785 |
+ case TOP_SUBNET: |
|
786 |
+ top="subnet"; |
|
787 |
+ break; |
|
788 |
+ default: |
|
789 |
+ top="undef"; |
|
790 |
+ } |
|
791 |
+ |
|
792 |
+ buf_printf (&out, "%s %s %d %s", ifconfig_local, ifconfig_remote_netmask, tun_mtu, top); |
|
793 |
+ management_android_control (management, "IFCONFIG", buf_bptr(&out)); |
|
794 |
+ |
|
767 | 795 |
#elif defined(TARGET_SOLARIS) |
768 | 796 |
|
769 | 797 |
/* Solaris 2.6 (and 7?) cannot set all parameters in one go... |
... | ... |
@@ -1368,8 +1397,62 @@ close_tun_generic (struct tuntap *tt) |
1368 | 1368 |
|
1369 | 1369 |
#endif |
1370 | 1370 |
|
1371 |
-#if defined(TARGET_LINUX) |
|
1371 |
+#if defined (TARGET_ANDROID) |
|
1372 |
+void |
|
1373 |
+open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt) |
|
1374 |
+{ |
|
1375 |
+#define ANDROID_TUNNAME "vpnservice-tun" |
|
1376 |
+ int i; |
|
1377 |
+ struct user_pass up; |
|
1378 |
+ struct gc_arena gc = gc_new (); |
|
1379 |
+ bool opentun; |
|
1380 |
+ |
|
1381 |
+ for (i = 0; i < tt->options.dns_len; ++i) { |
|
1382 |
+ management_android_control (management, "DNSSERVER", |
|
1383 |
+ print_in_addr_t(tt->options.dns[i], 0, &gc)); |
|
1384 |
+ } |
|
1385 |
+ |
|
1386 |
+ if(tt->options.domain) |
|
1387 |
+ management_android_control (management, "DNSDOMAIN", tt->options.domain); |
|
1388 |
+ |
|
1389 |
+ opentun = management_android_control (management, "OPENTUN", dev); |
|
1390 |
+ |
|
1391 |
+ /* Pick up the fd from management interface after calling the OPENTUN command */ |
|
1392 |
+ tt->fd = management->connection.lastfdreceived; |
|
1393 |
+ management->connection.lastfdreceived=-1; |
|
1394 |
+ |
|
1395 |
+ /* Set the actual name to a dummy name */ |
|
1396 |
+ tt->actual_name = string_alloc (ANDROID_TUNNAME, NULL); |
|
1397 |
+ |
|
1398 |
+ if ((tt->fd < 0) || !opentun) |
|
1399 |
+ msg (M_ERR, "ERROR: Cannot open TUN"); |
|
1400 |
+ |
|
1401 |
+ gc_free (&gc); |
|
1402 |
+} |
|
1403 |
+ |
|
1404 |
+void |
|
1405 |
+close_tun (struct tuntap *tt) |
|
1406 |
+{ |
|
1407 |
+ if (tt) |
|
1408 |
+ { |
|
1409 |
+ close_tun_generic (tt); |
|
1410 |
+ free (tt); |
|
1411 |
+ } |
|
1412 |
+} |
|
1413 |
+ |
|
1414 |
+int |
|
1415 |
+write_tun (struct tuntap* tt, uint8_t *buf, int len) |
|
1416 |
+{ |
|
1417 |
+ return write (tt->fd, buf, len); |
|
1418 |
+} |
|
1419 |
+ |
|
1420 |
+int |
|
1421 |
+read_tun (struct tuntap* tt, uint8_t *buf, int len) |
|
1422 |
+{ |
|
1423 |
+ return read (tt->fd, buf, len); |
|
1424 |
+} |
|
1372 | 1425 |
|
1426 |
+#elif defined(TARGET_LINUX) |
|
1373 | 1427 |
#ifdef HAVE_LINUX_IF_TUN_H /* New driver support */ |
1374 | 1428 |
|
1375 | 1429 |
#ifndef HAVE_LINUX_SOCKIOS_H |
... | ... |
@@ -38,7 +38,7 @@ |
38 | 38 |
#include "proto.h" |
39 | 39 |
#include "misc.h" |
40 | 40 |
|
41 |
-#ifdef WIN32 |
|
41 |
+#if defined(WIN32) || defined(TARGET_ANDROID) |
|
42 | 42 |
|
43 | 43 |
#define TUN_ADAPTER_INDEX_INVALID ((DWORD)-1) |
44 | 44 |
|
... | ... |
@@ -292,6 +292,8 @@ ifconfig_order(void) |
292 | 292 |
return IFCONFIG_AFTER_TUN_OPEN; |
293 | 293 |
#elif defined(WIN32) |
294 | 294 |
return IFCONFIG_BEFORE_TUN_OPEN; |
295 |
+#elif defined(TARGET_ANDROID) |
|
296 |
+ return IFCONFIG_BEFORE_TUN_OPEN; |
|
295 | 297 |
#else |
296 | 298 |
return IFCONFIG_DEFAULT; |
297 | 299 |
#endif |
... | ... |
@@ -304,7 +306,11 @@ ifconfig_order(void) |
304 | 304 |
static inline int |
305 | 305 |
route_order(void) |
306 | 306 |
{ |
307 |
+#if defined(TARGET_ANDROID) |
|
308 |
+ return ROUTE_BEFORE_TUN; |
|
309 |
+#else |
|
307 | 310 |
return ROUTE_ORDER_DEFAULT; |
311 |
+#endif |
|
308 | 312 |
} |
309 | 313 |
|
310 | 314 |
|