diff options
author | Tobias Brunner <tobias@strongswan.org> | 2012-10-11 18:48:17 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2012-10-16 14:16:17 +0200 |
commit | 45885ca613d419185b9079de8dd5c7f4808343cc (patch) | |
tree | 8155a418b58e45d73854cde5dc51ee135e9594c3 /src | |
parent | 9167ca8b2bc3d7d6f5502d50fb094dc13db709ca (diff) | |
download | strongswan-45885ca613d419185b9079de8dd5c7f4808343cc.tar.bz2 strongswan-45885ca613d419185b9079de8dd5c7f4808343cc.tar.xz |
android: Bypass/protect previously bypassed sockets if connectivity changes
Diffstat (limited to 'src')
3 files changed, 30 insertions, 4 deletions
diff --git a/src/frontends/android/jni/libandroidbridge/charonservice.c b/src/frontends/android/jni/libandroidbridge/charonservice.c index 591ca90ec..c6360528b 100644 --- a/src/frontends/android/jni/libandroidbridge/charonservice.c +++ b/src/frontends/android/jni/libandroidbridge/charonservice.c @@ -82,6 +82,11 @@ struct private_charonservice_t { * CharonVpnService reference */ jobject vpn_service; + + /** + * Sockets that were bypassed and we keep track for + */ + linked_list_t *sockets; }; /** @@ -177,8 +182,10 @@ failed: return success; } -METHOD(charonservice_t, bypass_socket, bool, - private_charonservice_t *this, int fd, int family) +/** + * Bypass a single socket + */ +static bool bypass_single_socket(intptr_t fd, private_charonservice_t *this) { JNIEnv *env; jmethodID method_id; @@ -193,7 +200,7 @@ METHOD(charonservice_t, bypass_socket, bool, } if (!(*env)->CallBooleanMethod(env, this->vpn_service, method_id, fd)) { - DBG1(DBG_CFG, "VpnService.protect() failed"); + DBG2(DBG_KNL, "VpnService.protect() failed"); goto failed; } androidjni_detach_thread(); @@ -205,6 +212,19 @@ failed: return FALSE; } +METHOD(charonservice_t, bypass_socket, bool, + private_charonservice_t *this, int fd, int family) +{ + if (fd >= 0) + { + this->sockets->insert_last(this->sockets, (void*)(intptr_t)fd); + return bypass_single_socket((intptr_t)fd, this); + } + this->sockets->invoke_function(this->sockets, (void*)bypass_single_socket, + this); + return TRUE; +} + /** * Converts the given Java array of byte arrays (byte[][]) to a linked list * of chunk_t objects. @@ -415,6 +435,7 @@ static void charonservice_init(JNIEnv *env, jobject service, jobject builder) .creds = android_creds_create(), .builder = vpnservice_builder_create(builder), .network_manager = network_manager_create(service), + .sockets = linked_list_create(), .vpn_service = (*env)->NewGlobalRef(env, service), ); charonservice = &this->public; @@ -451,6 +472,7 @@ static void charonservice_deinit(JNIEnv *env) private_charonservice_t *this = (private_charonservice_t*)charonservice; this->network_manager->destroy(this->network_manager); + this->sockets->destroy(this->sockets); this->builder->destroy(this->builder); this->creds->destroy(this->creds); this->attr->destroy(this->attr); diff --git a/src/frontends/android/jni/libandroidbridge/charonservice.h b/src/frontends/android/jni/libandroidbridge/charonservice.h index 2d5e8f082..4b5839f5e 100644 --- a/src/frontends/android/jni/libandroidbridge/charonservice.h +++ b/src/frontends/android/jni/libandroidbridge/charonservice.h @@ -70,7 +70,9 @@ struct charonservice_t { /** * Install a bypass policy for the given socket using the protect() Method - * of the Android VpnService interface + * of the Android VpnService interface. + * + * Use -1 as fd to re-bypass previously bypassed sockets. * * @param fd socket file descriptor * @param family socket protocol family diff --git a/src/frontends/android/jni/libandroidbridge/kernel/android_net.c b/src/frontends/android/jni/libandroidbridge/kernel/android_net.c index ce6229418..710bee545 100644 --- a/src/frontends/android/jni/libandroidbridge/kernel/android_net.c +++ b/src/frontends/android/jni/libandroidbridge/kernel/android_net.c @@ -53,6 +53,8 @@ struct private_kernel_android_net_t { */ static job_requeue_t roam_event() { + /* this will fail if no connection is up */ + charonservice->bypass_socket(charonservice, -1, 0); hydra->kernel_interface->roam(hydra->kernel_interface, TRUE); return JOB_REQUEUE_NONE; } |