diff options
author | Tobias Brunner <tobias@strongswan.org> | 2015-06-22 17:15:33 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2015-07-28 13:27:33 +0200 |
commit | 5da31733de79baf9249b45be1132c1e2f7203f4e (patch) | |
tree | 55f5b02978b84f86856e60958ef7fc55196ca486 | |
parent | 1082372448d8055b9ab2cd296a011b2f71eee3fe (diff) | |
download | strongswan-5da31733de79baf9249b45be1132c1e2f7203f4e.tar.bz2 strongswan-5da31733de79baf9249b45be1132c1e2f7203f4e.tar.xz |
android: Fix kernel-net implementation on Android 4.3 and earlier
Before fwmarks were used protected sockets were bound to the outbound
interface via SO_BINDTODEVICE. This does not always seem to work well
together with our connect()/getsockname() trick if the server is covered
by the traffic selectors. Calling protect() again after disconnecting
the socket seems to help, but if there is no connectivity at all we still
get the virtual IP back (maybe protect() does not bind the socket to any
interface then).
-rw-r--r-- | src/frontends/android/jni/libandroidbridge/android_jni.h | 2 | ||||
-rw-r--r-- | src/frontends/android/jni/libandroidbridge/kernel/android_net.c | 34 |
2 files changed, 36 insertions, 0 deletions
diff --git a/src/frontends/android/jni/libandroidbridge/android_jni.h b/src/frontends/android/jni/libandroidbridge/android_jni.h index 99c0bc2cd..b08670f7e 100644 --- a/src/frontends/android/jni/libandroidbridge/android_jni.h +++ b/src/frontends/android/jni/libandroidbridge/android_jni.h @@ -54,6 +54,8 @@ typedef enum { ANDROID_ICE_CREAM_SANDWICH = 14, ANDROID_ICE_CREAM_SANDWICH_MR1 = 15, ANDROID_JELLY_BEAN = 16, + ANDROID_JELLY_BEAN_MR1 = 17, + ANDROID_JELLY_BEAN_MR2 = 18, } android_sdk_version_t; /** diff --git a/src/frontends/android/jni/libandroidbridge/kernel/android_net.c b/src/frontends/android/jni/libandroidbridge/kernel/android_net.c index 9cab74e13..73322ad76 100644 --- a/src/frontends/android/jni/libandroidbridge/kernel/android_net.c +++ b/src/frontends/android/jni/libandroidbridge/kernel/android_net.c @@ -18,6 +18,7 @@ #include "android_net.h" +#include "../android_jni.h" #include "../charonservice.h" #include <hydra.h> #include <processing/jobs/callback_job.h> @@ -114,6 +115,11 @@ METHOD(kernel_net_t, get_source_addr, host_t*, DBG1(DBG_KNL, "failed to disconnect socket: %s", strerror(errno)); return NULL; } + if (android_sdk_version <= ANDROID_JELLY_BEAN_MR2) + { /* this seems to help avoiding the VIP, unless there is no connectivity + * at all */ + charonservice->bypass_socket(charonservice, -1, 0); + } if (connect(this->socket_v4, dest->get_sockaddr(dest), addrlen) < 0) { /* don't report an error if we are not connected (ENETUNREACH) */ @@ -131,6 +137,29 @@ METHOD(kernel_net_t, get_source_addr, host_t*, return host_create_from_sockaddr((sockaddr_t*)&addr); } +METHOD(kernel_net_t, get_source_addr_old, host_t*, + private_android_net_t *this, host_t *dest, host_t *src) +{ + host_t *host; + + /* on older Android versions we might get the virtual IP back because + * the protect() implementation there and connect() don't properly work + * together, on newer releases (using fwmarks) that's not a problem */ + host = get_source_addr(this, dest, src); + if (host) + { + this->mutex->lock(this->mutex); + if (this->vips->find_first(this->vips, (void*)host->ip_equals, + NULL, host) == SUCCESS) + { + host->destroy(host); + host = NULL; + } + this->mutex->unlock(this->mutex); + } + return host; +} + METHOD(kernel_net_t, get_nexthop, host_t*, private_android_net_t *this, host_t *dest, int prefix, host_t *src) { @@ -233,6 +262,11 @@ kernel_net_t *kernel_android_net_create() ); timerclear(&this->next_roam); + if (android_sdk_version <= ANDROID_JELLY_BEAN_MR2) + { + this->public.get_source_addr = _get_source_addr_old; + } + this->socket_v4 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (this->socket_v4 < 0) { |