android: Implement kernel_net_t.get_interface via JNI
authorTobias Brunner <tobias@strongswan.org>
Mon, 14 Jan 2013 16:21:54 +0000 (17:21 +0100)
committerTobias Brunner <tobias@strongswan.org>
Mon, 14 Jan 2013 16:22:56 +0000 (17:22 +0100)
This is now required to properly accept/install a virtual IP address.

Fixes #275.

src/frontends/android/jni/libandroidbridge/kernel/android_net.c
src/frontends/android/jni/libandroidbridge/kernel/network_manager.c
src/frontends/android/jni/libandroidbridge/kernel/network_manager.h
src/frontends/android/src/org/strongswan/android/logic/NetworkManager.java

index bc33959..4b42b55 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012-2013 Tobias Brunner
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -91,6 +91,13 @@ METHOD(kernel_net_t, get_source_addr, host_t*,
                                                                                        dest->get_family(dest) == AF_INET);
 }
 
+METHOD(kernel_net_t, get_interface, bool,
+       private_kernel_android_net_t *this, host_t *host, char **name)
+{
+       return this->network_manager->get_interface(this->network_manager, host,
+                                                                                               name);
+}
+
 METHOD(kernel_net_t, add_ip, status_t,
        private_kernel_android_net_t *this, host_t *virtual_ip, int prefix,
        char *iface)
@@ -120,7 +127,7 @@ kernel_android_net_t *kernel_android_net_create()
                        .interface = {
                                .get_source_addr = _get_source_addr,
                                .get_nexthop = (void*)return_null,
-                               .get_interface = (void*)return_null,
+                               .get_interface = _get_interface,
                                .create_address_enumerator = (void*)enumerator_create_empty,
                                .add_ip = _add_ip,
                                .del_ip = (void*)return_failed,
index 17bde6a..c8950cb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012-2013 Tobias Brunner
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -69,7 +69,7 @@ METHOD(network_manager_t, get_local_address, host_t*,
                goto failed;
        }
        jaddr = (*env)->CallObjectMethod(env, this->obj, method_id, ipv4);
-       if (!jaddr)
+       if (!jaddr || androidjni_exception_occurred(env))
        {
                goto failed;
        }
@@ -85,6 +85,46 @@ failed:
        return NULL;
 }
 
+METHOD(network_manager_t, get_interface, bool,
+       private_network_manager_t *this, host_t *ip, char **name)
+{
+       JNIEnv *env;
+       jmethodID method_id;
+       jbyteArray jaddr;
+       jstring jinterface;
+
+       if (ip->is_anyaddr(ip))
+       {
+               return FALSE;
+       }
+
+       androidjni_attach_thread(&env);
+
+       method_id = (*env)->GetMethodID(env, this->cls, "getInterface",
+                                                                       "([B)Ljava/lang/String;");
+       if (!method_id)
+       {
+               goto failed;
+       }
+       jaddr = byte_array_from_chunk(env, ip->get_address(ip));
+       jinterface = (*env)->CallObjectMethod(env, this->obj, method_id, jaddr);
+       if (!jinterface || androidjni_exception_occurred(env))
+       {
+               goto failed;
+       }
+       if (name)
+       {
+               *name = androidjni_convert_jstring(env, jinterface);
+       }
+       androidjni_detach_thread();
+       return TRUE;
+
+failed:
+       androidjni_exception_occurred(env);
+       androidjni_detach_thread();
+       return FALSE;
+}
+
 JNI_METHOD(NetworkManager, networkChanged, void,
        bool disconnected)
 {
@@ -206,6 +246,7 @@ network_manager_t *network_manager_create(jobject context)
        INIT(this,
                .public = {
                        .get_local_address = _get_local_address,
+                       .get_interface = _get_interface,
                        .add_connectivity_cb = _add_connectivity_cb,
                        .remove_connectivity_cb = _remove_connectivity_cb,
                        .destroy = _destroy,
index a35103b..2638b5a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012-2013 Tobias Brunner
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -56,6 +56,15 @@ struct network_manager_t {
        host_t *(*get_local_address)(network_manager_t *this, bool ipv4);
 
        /**
+        * Get the name of the interface on which the given IP address is installed
+        *
+        * @param ip                            the IP address to look for
+        * @param name                          returns the name of the interface (optional)
+        * @return                                      TRUE if found
+        */
+       bool (*get_interface)(network_manager_t *this, host_t *ip, char **name);
+
+       /**
         * Register a callback that is called if connectivity changes
         *
         * @note Only the first registered callback is currently used
index 160865f..168341a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012-2013 Tobias Brunner
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -20,6 +20,7 @@ import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.NetworkInterface;
 import java.net.SocketException;
+import java.net.UnknownHostException;
 import java.util.Enumeration;
 
 import android.content.BroadcastReceiver;
@@ -110,4 +111,32 @@ public class NetworkManager extends BroadcastReceiver
                }
                return null;
        }
+
+       /**
+        * Search for an interface that has the given address installed.
+        *
+        * @param addr network-order byte encoding of the address to look for
+        * @return name of the interface, or null if not found
+        */
+       public String getInterface(byte[] addr)
+       {
+               try
+               {
+                       InetAddress inetAddress = InetAddress.getByAddress(addr);
+                       NetworkInterface intf = NetworkInterface.getByInetAddress(inetAddress);
+                       if (intf != null)
+                       {
+                               return intf.getName();
+                       }
+               }
+               catch (UnknownHostException e)
+               {
+                       e.printStackTrace();
+               }
+               catch (SocketException e)
+               {
+                       e.printStackTrace();
+               }
+               return null;
+       }
 }