summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/openvpn/init.c19
-rw-r--r--src/openvpn/manage.c28
-rw-r--r--src/openvpn/manage.h5
-rw-r--r--src/openvpn/tun.c29
4 files changed, 68 insertions, 13 deletions
diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index c50b5c2..21e3052 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -1426,10 +1426,10 @@ do_open_tun (struct context *c)
#ifdef TARGET_ANDROID
/* If we emulate persist-tun on android we still have to open a new tun and
- then close the old */
+ * then close the old */
int oldtunfd=-1;
if (c->c1.tuntap)
- oldtunfd = c->c1.tuntap->fd;
+ oldtunfd = c->c1.tuntap->fd;
#endif
/* initialize (but do not open) tun/tap object */
@@ -1463,14 +1463,14 @@ do_open_tun (struct context *c)
do_route (&c->options, c->c1.route_list, c->c1.route_ipv6_list,
c->c1.tuntap, c->plugins, c->c2.es);
}
-
+#ifdef TARGET_ANDROID
+ /* Store the old fd inside the fd so open_tun can use it */
+ c->c1.tuntap->fd = oldtunfd;
+#endif
/* open the tun device */
open_tun (c->options.dev, c->options.dev_type, c->options.dev_node,
c->c1.tuntap);
-#ifdef TARGET_ANDROID
- if (oldtunfd>=0)
- close(oldtunfd);
-#endif
+
/* set the hardware address */
if (c->options.lladdr)
set_lladdr(c->c1.tuntap->actual_name, c->options.lladdr, c->c2.es);
@@ -3767,7 +3767,10 @@ close_context (struct context *c, int sig, unsigned int flags)
{
if ((flags & CC_USR1_TO_HUP)
|| (c->sig->source == SIG_SOURCE_HARD && (flags & CC_HARD_USR1_TO_HUP)))
- c->sig->signal_received = SIGHUP;
+ {
+ c->sig->signal_received = SIGHUP;
+ c->sig->signal_text = "close_context usr1 to hup";
+ }
}
if (!(flags & CC_NO_CLOSE))
diff --git a/src/openvpn/manage.c b/src/openvpn/manage.c
index 22dbe13..8097905 100644
--- a/src/openvpn/manage.c
+++ b/src/openvpn/manage.c
@@ -1864,6 +1864,34 @@ bool management_android_control (struct management *man, const char *command, co
management_query_user_pass(management, &up , command, GET_USER_PASS_NEED_OK,(void*) 0);
return strcmp ("ok", up.password)==0;
}
+
+/*
+ * In Android 4.4 it is not possible to open a new tun device and then close the
+ * old tun device without breaking the whole VPNService stack until the device
+ * is rebooted. This management method ask the UI what method should be taken to
+ * ensure the optimal solution for the situation
+ */
+int managment_android_persisttun_action (struct management *man)
+{
+ struct user_pass up;
+ CLEAR(up);
+ strcpy(up.username,"tunmethod");
+ management_query_user_pass(management, &up , "PERSIST_TUN_ACTION",
+ GET_USER_PASS_NEED_OK,(void*) 0);
+ if (!strcmp("NOACTION", up.password))
+ return ANDROID_KEEP_OLD_TUN;
+ else if (!strcmp ("OPEN_AFTER_CLOSE", up.password))
+ return ANDROID_OPEN_AFTER_CLOSE;
+ else if (!strcmp ("OPEN_BEFORE_CLOSE", up.password))
+ return ANDROID_OPEN_BEFORE_CLOSE;
+ else
+ msg (M_ERR, "Got unrecognised '%s' from management for PERSIST_TUN_ACTION query", up.password);
+
+ ASSERT(0);
+ return ANDROID_OPEN_AFTER_CLOSE;
+}
+
+
#endif
static int
diff --git a/src/openvpn/manage.h b/src/openvpn/manage.h
index 962b5bc..1c8dda6 100644
--- a/src/openvpn/manage.h
+++ b/src/openvpn/manage.h
@@ -378,6 +378,11 @@ bool management_query_user_pass (struct management *man,
#ifdef TARGET_ANDROID
bool management_android_control (struct management *man, const char *command, const char *msg);
+
+#define ANDROID_KEEP_OLD_TUN 1
+#define ANDROID_OPEN_AFTER_CLOSE 2
+#define ANDROID_OPEN_BEFORE_CLOSE 3
+int managment_android_persisttun_action (struct management *man);
#endif
bool management_should_daemonize (struct management *man);
diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c
index 672486e..4df271d 100644
--- a/src/openvpn/tun.c
+++ b/src/openvpn/tun.c
@@ -1501,19 +1501,38 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
struct gc_arena gc = gc_new ();
bool opentun;
+ int oldtunfd = tt->fd;
+
for (i = 0; i < tt->options.dns_len; ++i) {
management_android_control (management, "DNSSERVER",
- print_in_addr_t(tt->options.dns[i], 0, &gc));
+ 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);
+ int android_method = managment_android_persisttun_action (management);
+
+ /* Android 4.4 workaround */
+ if (oldtunfd >=0 && android_method == ANDROID_OPEN_AFTER_CLOSE)
+ {
+ close(oldtunfd);
+ openvpn_sleep(2);
+ }
+
+ if (oldtunfd >=0 && android_method == ANDROID_KEEP_OLD_TUN) {
+ /* keep the old fd */
+ opentun = true;
+ } else {
+ 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;
+ }
- /* Pick up the fd from management interface after calling the OPENTUN command */
- tt->fd = management->connection.lastfdreceived;
- management->connection.lastfdreceived=-1;
+ if (oldtunfd>=0 && android_method == ANDROID_OPEN_BEFORE_CLOSE)
+ close(oldtunfd);
/* Set the actual name to a dummy name */
tt->actual_name = string_alloc (ANDROID_TUNNAME, NULL);