android: Add method to BuilderAdapter to re-establish without DNS-related data

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).
This commit is contained in:
Tobias Brunner
2014-07-22 11:10:36 +02:00
parent cc1712a8f4
commit 36aab70ab0
3 changed files with 113 additions and 5 deletions
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2012-2013 Tobias Brunner * Copyright (C) 2012-2014 Tobias Brunner
* Copyright (C) 2012 Giuliano Grassi * Copyright (C) 2012 Giuliano Grassi
* Copyright (C) 2012 Ralf Sager * Copyright (C) 2012 Ralf Sager
* Hochschule fuer Technik Rapperswil * Hochschule fuer Technik Rapperswil
@@ -197,8 +197,10 @@ failed:
return FALSE; 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; JNIEnv *env;
jmethodID method_id; jmethodID method_id;
@@ -209,7 +211,7 @@ METHOD(vpnservice_builder_t, establish, int,
DBG2(DBG_LIB, "builder: building TUN device"); DBG2(DBG_LIB, "builder: building TUN device");
method_id = (*env)->GetMethodID(env, android_charonvpnservice_builder_class, method_id = (*env)->GetMethodID(env, android_charonvpnservice_builder_class,
"establish", "()I"); method, "()I");
if (!method_id) if (!method_id)
{ {
goto failed; goto failed;
@@ -229,6 +231,18 @@ failed:
return -1; 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, METHOD(vpnservice_builder_t, destroy, void,
private_vpnservice_builder_t *this) private_vpnservice_builder_t *this)
{ {
@@ -252,6 +266,7 @@ vpnservice_builder_t *vpnservice_builder_create(jobject builder)
.add_dns = _add_dns, .add_dns = _add_dns,
.set_mtu = _set_mtu, .set_mtu = _set_mtu,
.establish = _establish, .establish = _establish,
.establish_no_dns = _establish_no_dns,
.destroy = _destroy, .destroy = _destroy,
}, },
); );
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2012 Tobias Brunner * Copyright (C) 2012-2014 Tobias Brunner
* Copyright (C) 2012 Giuliano Grassi * Copyright (C) 2012 Giuliano Grassi
* Copyright (C) 2012 Ralf Sager * Copyright (C) 2012 Ralf Sager
* Hochschule fuer Technik Rapperswil * Hochschule fuer Technik Rapperswil
@@ -77,6 +77,13 @@ struct vpnservice_builder_t {
*/ */
int (*establish)(vpnservice_builder_t *this); 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 * Destroy a vpnservice_builder
*/ */
@@ -22,6 +22,7 @@ import java.security.PrivateKey;
import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import org.strongswan.android.data.VpnProfile; import org.strongswan.android.data.VpnProfile;
import org.strongswan.android.data.VpnProfileDataSource; import org.strongswan.android.data.VpnProfileDataSource;
@@ -526,11 +527,14 @@ public class CharonVpnService extends VpnService implements Runnable
{ {
private final String mName; private final String mName;
private VpnService.Builder mBuilder; private VpnService.Builder mBuilder;
private BuilderCache mCache;
private BuilderCache mEstablishedCache;
public BuilderAdapter(String name) public BuilderAdapter(String name)
{ {
mName = name; mName = name;
mBuilder = createBuilder(name); mBuilder = createBuilder(name);
mCache = new BuilderCache();
} }
private VpnService.Builder createBuilder(String name) private VpnService.Builder createBuilder(String name)
@@ -553,6 +557,7 @@ public class CharonVpnService extends VpnService implements Runnable
try try
{ {
mBuilder.addAddress(address, prefixLength); mBuilder.addAddress(address, prefixLength);
mCache.addAddress(address, prefixLength);
} }
catch (IllegalArgumentException ex) catch (IllegalArgumentException ex)
{ {
@@ -579,6 +584,7 @@ public class CharonVpnService extends VpnService implements Runnable
try try
{ {
mBuilder.addRoute(address, prefixLength); mBuilder.addRoute(address, prefixLength);
mCache.addRoute(address, prefixLength);
} }
catch (IllegalArgumentException ex) catch (IllegalArgumentException ex)
{ {
@@ -605,6 +611,7 @@ public class CharonVpnService extends VpnService implements Runnable
try try
{ {
mBuilder.setMtu(mtu); mBuilder.setMtu(mtu);
mCache.setMtu(mtu);
} }
catch (IllegalArgumentException ex) 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 /* now that the TUN device is created we don't need the current
* builder anymore, but we might need another when reestablishing */ * builder anymore, but we might need another when reestablishing */
mBuilder = createBuilder(mName); mBuilder = createBuilder(mName);
mEstablishedCache = mCache;
mCache = new BuilderCache();
return fd.detachFd(); 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;
}
}
} }
/* /*