diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/openvpn/init.c | 19 | ||||
-rw-r--r-- | src/openvpn/manage.c | 28 | ||||
-rw-r--r-- | src/openvpn/manage.h | 5 | ||||
-rw-r--r-- | src/openvpn/tun.c | 29 |
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); |