android: Determine source address dynamically
authorTobias Brunner <tobias@strongswan.org>
Wed, 10 Oct 2012 10:26:51 +0000 (12:26 +0200)
committerTobias Brunner <tobias@strongswan.org>
Tue, 16 Oct 2012 12:16:17 +0000 (14:16 +0200)
src/frontends/android/jni/libandroidbridge/backend/android_service.c
src/frontends/android/jni/libandroidbridge/backend/android_service.h
src/frontends/android/jni/libandroidbridge/charonservice.c
src/frontends/android/jni/libandroidbridge/charonservice.h
src/frontends/android/jni/libandroidbridge/kernel/android_net.c
src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java

index 0361b86..1e9d246 100644 (file)
@@ -59,11 +59,6 @@ struct private_android_service_t {
        char *type;
 
        /**
-        * local ipv4 address
-        */
-       char *local_address;
-
-       /**
         * gateway
         */
        char *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,
index 52c3dc5..1bfdcf9 100644 (file)
@@ -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_ @}*/
index ef4d42e..96a4da8 100644 (file)
@@ -74,6 +74,11 @@ struct private_charonservice_t {
        vpnservice_builder_t *builder;
 
        /**
+        * NetworkManager instance (accessed via JNI)
+        */
+       network_manager_t *network_manager;
+
+       /**
         * CharonVpnService reference
         */
        jobject vpn_service;
@@ -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);
 }
index 376f550..2d5e8f0 100644 (file)
@@ -32,6 +32,7 @@
 #define CHARONSERVICE_H_
 
 #include "vpnservice_builder.h"
+#include "kernel/network_manager.h"
 
 #include <library.h>
 #include <utils/linked_list.h>
@@ -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);
 };
 
 /**
index e29f955..b68ac10 100644 (file)
@@ -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;
index 1e1556c..b4236f6 100644 (file)
 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<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
-                       while (en.hasMoreElements())
-                       {
-                               NetworkInterface intf = en.nextElement();
-
-                               Enumeration<InetAddress> 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.