android: Add method to BuilderAdapter to re-establish without DNS-related data
authorTobias Brunner <tobias@strongswan.org>
Wed, 16 Jul 2014 11:54:57 +0000 (13:54 +0200)
committerTobias Brunner <tobias@strongswan.org>
Tue, 22 Jul 2014 09:10:36 +0000 (11:10 +0200)
Non-DNS data is cached in the BuilderAdapter so the TUN device can be
recreated easily (since the CHILD_SA is gone we couldn't actually gather
that information).

src/frontends/android/jni/libandroidbridge/vpnservice_builder.c
src/frontends/android/jni/libandroidbridge/vpnservice_builder.h
src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java

index 6b10228..c7a6eb6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2013 Tobias Brunner
+ * Copyright (C) 2012-2014 Tobias Brunner
  * Copyright (C) 2012 Giuliano Grassi
  * Copyright (C) 2012 Ralf Sager
  * Hochschule fuer Technik Rapperswil
@@ -197,8 +197,10 @@ failed:
        return FALSE;
 }
 
-METHOD(vpnservice_builder_t, establish, int,
-       private_vpnservice_builder_t *this)
+/**
+ * Establish or reestablish the TUN device
+ */
+static int establish_internal(private_vpnservice_builder_t *this, char *method)
 {
        JNIEnv *env;
        jmethodID method_id;
@@ -209,7 +211,7 @@ METHOD(vpnservice_builder_t, establish, int,
        DBG2(DBG_LIB, "builder: building TUN device");
 
        method_id = (*env)->GetMethodID(env, android_charonvpnservice_builder_class,
-                                                                       "establish", "()I");
+                                                                       method, "()I");
        if (!method_id)
        {
                goto failed;
@@ -229,6 +231,18 @@ failed:
        return -1;
 }
 
+METHOD(vpnservice_builder_t, establish, int,
+       private_vpnservice_builder_t *this)
+{
+       return establish_internal(this, "establish");
+}
+
+METHOD(vpnservice_builder_t, establish_no_dns, int,
+       private_vpnservice_builder_t *this)
+{
+       return establish_internal(this, "establishNoDns");
+}
+
 METHOD(vpnservice_builder_t, destroy, void,
        private_vpnservice_builder_t *this)
 {
@@ -252,6 +266,7 @@ vpnservice_builder_t *vpnservice_builder_create(jobject builder)
                        .add_dns = _add_dns,
                        .set_mtu = _set_mtu,
                        .establish = _establish,
+                       .establish_no_dns = _establish_no_dns,
                        .destroy = _destroy,
                },
        );
index 2090908..08c436d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012-2014 Tobias Brunner
  * Copyright (C) 2012 Giuliano Grassi
  * Copyright (C) 2012 Ralf Sager
  * Hochschule fuer Technik Rapperswil
@@ -78,6 +78,13 @@ struct vpnservice_builder_t {
        int (*establish)(vpnservice_builder_t *this);
 
        /**
+        * Build the TUN device without DNS related data
+        *
+        * @return                                      the TUN file descriptor, -1 if failed
+        */
+       int (*establish_no_dns)(vpnservice_builder_t *this);
+
+       /**
         * Destroy a vpnservice_builder
         */
        void (*destroy)(vpnservice_builder_t *this);
index d53d478..5707f4f 100644 (file)
@@ -22,6 +22,7 @@ import java.security.PrivateKey;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
+import java.util.List;
 
 import org.strongswan.android.data.VpnProfile;
 import org.strongswan.android.data.VpnProfileDataSource;
@@ -526,11 +527,14 @@ public class CharonVpnService extends VpnService implements Runnable
        {
                private final String mName;
                private VpnService.Builder mBuilder;
+               private BuilderCache mCache;
+               private BuilderCache mEstablishedCache;
 
                public BuilderAdapter(String name)
                {
                        mName = name;
                        mBuilder = createBuilder(name);
+                       mCache = new BuilderCache();
                }
 
                private VpnService.Builder createBuilder(String name)
@@ -553,6 +557,7 @@ public class CharonVpnService extends VpnService implements Runnable
                        try
                        {
                                mBuilder.addAddress(address, prefixLength);
+                               mCache.addAddress(address, prefixLength);
                        }
                        catch (IllegalArgumentException ex)
                        {
@@ -579,6 +584,7 @@ public class CharonVpnService extends VpnService implements Runnable
                        try
                        {
                                mBuilder.addRoute(address, prefixLength);
+                               mCache.addRoute(address, prefixLength);
                        }
                        catch (IllegalArgumentException ex)
                        {
@@ -605,6 +611,7 @@ public class CharonVpnService extends VpnService implements Runnable
                        try
                        {
                                mBuilder.setMtu(mtu);
+                               mCache.setMtu(mtu);
                        }
                        catch (IllegalArgumentException ex)
                        {
@@ -632,8 +639,87 @@ public class CharonVpnService extends VpnService implements Runnable
                        /* now that the TUN device is created we don't need the current
                         * builder anymore, but we might need another when reestablishing */
                        mBuilder = createBuilder(mName);
+                       mEstablishedCache = mCache;
+                       mCache = new BuilderCache();
                        return fd.detachFd();
                }
+
+               public synchronized int establishNoDns()
+               {
+                       ParcelFileDescriptor fd;
+
+                       if (mEstablishedCache == null)
+                       {
+                               return -1;
+                       }
+                       try
+                       {
+                               Builder builder = createBuilder(mName);
+                               mEstablishedCache.applyData(builder);
+                               fd = builder.establish();
+                       }
+                       catch (Exception ex)
+                       {
+                               ex.printStackTrace();
+                               return -1;
+                       }
+                       if (fd == null)
+                       {
+                               return -1;
+                       }
+                       return fd.detachFd();
+               }
+       }
+
+       /**
+        * Cache non DNS related information so we can recreate the builder without
+        * that information when reestablishing IKE_SAs
+        */
+       public class BuilderCache
+       {
+               private final List<PrefixedAddress> mAddresses = new ArrayList<PrefixedAddress>();
+               private final List<PrefixedAddress> mRoutes = new ArrayList<PrefixedAddress>();
+               private int mMtu;
+
+               public void addAddress(String address, int prefixLength)
+               {
+                       mAddresses.add(new PrefixedAddress(address, prefixLength));
+               }
+
+               public void addRoute(String address, int prefixLength)
+               {
+                       mRoutes.add(new PrefixedAddress(address, prefixLength));
+               }
+
+               public void setMtu(int mtu)
+               {
+                       mMtu = mtu;
+               }
+
+               public void applyData(VpnService.Builder builder)
+               {
+                       for (PrefixedAddress address : mAddresses)
+                       {
+                               builder.addAddress(address.mAddress, address.mPrefix);
+                       }
+                       for (PrefixedAddress route : mRoutes)
+                       {
+                               builder.addRoute(route.mAddress, route.mPrefix);
+                       }
+                       builder.setMtu(mMtu);
+               }
+
+               private class PrefixedAddress
+               {
+                       public String mAddress;
+                       public int mPrefix;
+
+                       public PrefixedAddress(String address, int prefix)
+                       {
+                               this.mAddress = address;
+                               this.mPrefix = prefix;
+                       }
+               }
        }
 
        /*