From: Tobias Brunner Date: Wed, 10 Oct 2012 10:26:51 +0000 (+0200) Subject: android: Determine source address dynamically X-Git-Tag: 5.0.2dr4~351^2~20 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=38bbca587fab96550005fc06eaabecd2d4dd0507;p=thirdparty%2Fstrongswan.git android: Determine source address dynamically --- diff --git a/src/frontends/android/jni/libandroidbridge/backend/android_service.c b/src/frontends/android/jni/libandroidbridge/backend/android_service.c index 0361b86dab..1e9d246ce4 100644 --- a/src/frontends/android/jni/libandroidbridge/backend/android_service.c +++ b/src/frontends/android/jni/libandroidbridge/backend/android_service.c @@ -58,11 +58,6 @@ struct private_android_service_t { */ char *type; - /** - * local ipv4 address - */ - char *local_address; - /** * gateway */ @@ -480,7 +475,7 @@ static job_requeue_t initiate(private_android_service_t *this) } }; - ike_cfg = ike_cfg_create(TRUE, TRUE, this->local_address, FALSE, + ike_cfg = ike_cfg_create(TRUE, TRUE, "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE), this->gateway, FALSE, IKEV2_UDP_PORT); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); @@ -591,7 +586,6 @@ METHOD(android_service_t, destroy, void, close_tun_device(this); this->lock->destroy(this->lock); free(this->type); - free(this->local_address); free(this->gateway); free(this->username); if (this->password) @@ -606,8 +600,8 @@ METHOD(android_service_t, destroy, void, * See header */ android_service_t *android_service_create(android_creds_t *creds, char *type, - char *local_address, char *gateway, - char *username, char *password) + char *gateway, char *username, + char *password) { private_android_service_t *this; @@ -624,7 +618,6 @@ android_service_t *android_service_create(android_creds_t *creds, char *type, .destroy = _destroy, }, .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), - .local_address = local_address, .username = username, .password = password, .gateway = gateway, diff --git a/src/frontends/android/jni/libandroidbridge/backend/android_service.h b/src/frontends/android/jni/libandroidbridge/backend/android_service.h index 52c3dc5c88..1bfdcf994f 100644 --- a/src/frontends/android/jni/libandroidbridge/backend/android_service.h +++ b/src/frontends/android/jni/libandroidbridge/backend/android_service.h @@ -53,13 +53,12 @@ struct android_service_t { * * @param creds Android specific credential set * @param type VPN type (see VpnType.java) - * @param local_address local ip address * @param gateway gateway address * @param username user name (local identity) * @param password password (if any) */ android_service_t *android_service_create(android_creds_t *creds, char *type, - char *local_address, char *gateway, - char *username, char *password); + char *gateway, char *username, + char *password); #endif /** ANDROID_SERVICE_H_ @}*/ diff --git a/src/frontends/android/jni/libandroidbridge/charonservice.c b/src/frontends/android/jni/libandroidbridge/charonservice.c index ef4d42edfb..96a4da8f33 100644 --- a/src/frontends/android/jni/libandroidbridge/charonservice.c +++ b/src/frontends/android/jni/libandroidbridge/charonservice.c @@ -73,6 +73,11 @@ struct private_charonservice_t { */ vpnservice_builder_t *builder; + /** + * NetworkManager instance (accessed via JNI) + */ + network_manager_t *network_manager; + /** * CharonVpnService reference */ @@ -330,22 +335,26 @@ METHOD(charonservice_t, get_vpnservice_builder, vpnservice_builder_t*, return this->builder; } +METHOD(charonservice_t, get_network_manager, network_manager_t*, + private_charonservice_t *this) +{ + return this->network_manager; +} + /** * Initiate a new connection * - * @param local local ip address (gets owned) * @param gateway gateway address (gets owned) * @param username username (gets owned) * @param password password (gets owned) */ -static void initiate(char *type, char *local, char *gateway, - char *username, char *password) +static void initiate(char *type, char *gateway, char *username, char *password) { private_charonservice_t *this = (private_charonservice_t*)charonservice; this->creds->clear(this->creds); DESTROY_IF(this->service); - this->service = android_service_create(this->creds, type, local, gateway, + this->service = android_service_create(this->creds, type, gateway, username, password); } @@ -400,10 +409,12 @@ static void charonservice_init(JNIEnv *env, jobject service, jobject builder) .get_user_certificate = _get_user_certificate, .get_user_key = _get_user_key, .get_vpnservice_builder = _get_vpnservice_builder, + .get_network_manager = _get_network_manager, }, .attr = android_attr_create(), .creds = android_creds_create(), .builder = vpnservice_builder_create(builder), + .network_manager = network_manager_create(), .vpn_service = (*env)->NewGlobalRef(env, service), ); charonservice = &this->public; @@ -439,6 +450,7 @@ static void charonservice_deinit(JNIEnv *env) { private_charonservice_t *this = (private_charonservice_t*)charonservice; + this->network_manager->destroy(this->network_manager); this->builder->destroy(this->builder); this->creds->destroy(this->creds); this->attr->destroy(this->attr); @@ -555,16 +567,14 @@ JNI_METHOD(CharonVpnService, deinitializeCharon, void) * Initiate SA */ JNI_METHOD(CharonVpnService, initiate, void, - jstring jtype, jstring jlocal_address, jstring jgateway, jstring jusername, - jstring jpassword) + jstring jtype, jstring jgateway, jstring jusername, jstring jpassword) { - char *type, *local_address, *gateway, *username, *password; + char *type, *gateway, *username, *password; type = androidjni_convert_jstring(env, jtype); - local_address = androidjni_convert_jstring(env, jlocal_address); gateway = androidjni_convert_jstring(env, jgateway); username = androidjni_convert_jstring(env, jusername); password = androidjni_convert_jstring(env, jpassword); - initiate(type, local_address, gateway, username, password); + initiate(type, gateway, username, password); } diff --git a/src/frontends/android/jni/libandroidbridge/charonservice.h b/src/frontends/android/jni/libandroidbridge/charonservice.h index 376f55014d..2d5e8f082a 100644 --- a/src/frontends/android/jni/libandroidbridge/charonservice.h +++ b/src/frontends/android/jni/libandroidbridge/charonservice.h @@ -32,6 +32,7 @@ #define CHARONSERVICE_H_ #include "vpnservice_builder.h" +#include "kernel/network_manager.h" #include #include @@ -111,6 +112,12 @@ struct charonservice_t { */ vpnservice_builder_t *(*get_vpnservice_builder)(charonservice_t *this); + /** + * Get the current network_manager_t object + * + * @return NetworkManager instance + */ + network_manager_t *(*get_network_manager)(charonservice_t *this); }; /** diff --git a/src/frontends/android/jni/libandroidbridge/kernel/android_net.c b/src/frontends/android/jni/libandroidbridge/kernel/android_net.c index e29f955104..b68ac10c02 100644 --- a/src/frontends/android/jni/libandroidbridge/kernel/android_net.c +++ b/src/frontends/android/jni/libandroidbridge/kernel/android_net.c @@ -14,6 +14,8 @@ #include "android_net.h" +#include "../charonservice.h" + typedef struct private_kernel_android_net_t private_kernel_android_net_t; struct private_kernel_android_net_t { @@ -22,8 +24,20 @@ struct private_kernel_android_net_t { * Public kernel interface */ kernel_android_net_t public; + + /** + * Reference to NetworkManager object + */ + network_manager_t *network_manager; }; +METHOD(kernel_net_t, get_source_addr, host_t*, + private_kernel_android_net_t *this, host_t *dest, host_t *src) +{ + return this->network_manager->get_local_address(this->network_manager, + dest->get_family(dest) == AF_INET); +} + METHOD(kernel_net_t, add_ip, status_t, private_kernel_android_net_t *this, host_t *virtual_ip, host_t *iface_ip) { @@ -47,7 +61,7 @@ kernel_android_net_t *kernel_android_net_create() INIT(this, .public = { .interface = { - .get_source_addr = (void*)return_null, + .get_source_addr = _get_source_addr, .get_nexthop = (void*)return_null, .get_interface = (void*)return_null, .create_address_enumerator = (void*)enumerator_create_empty, @@ -58,6 +72,7 @@ kernel_android_net_t *kernel_android_net_create() .destroy = _destroy, }, }, + .network_manager = charonservice->get_network_manager(charonservice), ); return &this->public; diff --git a/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java b/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java index 1e1556c70c..b4236f6c7e 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java +++ b/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java @@ -18,14 +18,10 @@ package org.strongswan.android.logic; import java.io.File; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.SocketException; import java.security.PrivateKey; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.ArrayList; -import java.util.Enumeration; import org.strongswan.android.data.VpnProfile; import org.strongswan.android.data.VpnProfileDataSource; @@ -218,9 +214,7 @@ public class CharonVpnService extends VpnService implements Runnable initializeCharon(builder, mLogFile); Log.i(TAG, "charon started"); - String local_address = getLocalIPv4Address(); initiate(mCurrentProfile.getVpnType().getIdentifier(), - local_address != null ? local_address : "0.0.0.0", mCurrentProfile.getGateway(), mCurrentProfile.getUsername(), mCurrentProfile.getPassword()); } @@ -486,41 +480,7 @@ public class CharonVpnService extends VpnService implements Runnable /** * Initiate VPN, provided by libandroidbridge.so */ - public native void initiate(String type, String local_address, String gateway, - String username, String password); - - /** - * Helper function that retrieves a local IPv4 address. - * - * @return string representation of an IPv4 address, or null if none found - */ - private static String getLocalIPv4Address() - { - try - { - Enumeration en = NetworkInterface.getNetworkInterfaces(); - while (en.hasMoreElements()) - { - NetworkInterface intf = en.nextElement(); - - Enumeration enumIpAddr = intf.getInetAddresses(); - while (enumIpAddr.hasMoreElements()) - { - InetAddress inetAddress = enumIpAddr.nextElement(); - if (!inetAddress.isLoopbackAddress() && inetAddress.getAddress().length == 4) - { - return inetAddress.getHostAddress().toString(); - } - } - } - } - catch (SocketException ex) - { - ex.printStackTrace(); - return null; - } - return null; - } + public native void initiate(String type, String gateway, String username, String password); /** * Adapter for VpnService.Builder which is used to access it safely via JNI.