diff options
| -rw-r--r-- | .DS_Store | bin | 12292 -> 12292 bytes | |||
| -rw-r--r-- | .hgignore | 4 | ||||
| -rw-r--r-- | openvpn/src/openvpn/init.c | 10 | ||||
| -rw-r--r-- | openvpn/src/openvpn/tun.c | 1 | ||||
| -rw-r--r-- | openvpn/src/openvpn/tun.h | 17 | ||||
| -rw-r--r-- | res/values-de/arrays.xml | 6 | ||||
| -rw-r--r-- | res/values/arrays.xml | 10 | ||||
| -rw-r--r-- | res/values/strings.xml | 2 | ||||
| -rw-r--r-- | res/xml/main_headers.xml | 2 | ||||
| -rw-r--r-- | res/xml/vpn_authentification.xml | 15 | ||||
| -rw-r--r-- | res/xml/vpn_ipsettings.xml | 8 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/OpenVPN.java | 16 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/OpenVpnService.java | 69 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/Settings_Authentication.java | 6 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/Settings_IP.java | 11 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/ShowConfigFragment.java | 12 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/VPNPreferences.java | 4 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/VPNProfileList.java | 2 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/VpnProfile.java | 113 | 
19 files changed, 235 insertions, 73 deletions
| Binary files differ @@ -1,4 +1,6 @@  obj  bin  libs -gen
\ No newline at end of file +gen +syntax: regexp +^openvpn/xcopenvpn$
\ No newline at end of file diff --git a/openvpn/src/openvpn/init.c b/openvpn/src/openvpn/init.c index bc7718e4..88d621a4 100644 --- a/openvpn/src/openvpn/init.c +++ b/openvpn/src/openvpn/init.c @@ -1477,6 +1477,13 @@ do_open_tun (struct context *c)  						&gc);  	  do_ifconfig (c->c1.tuntap, guess, TUN_MTU_SIZE (&c->c2.frame), c->c2.es);  	} +         +        /* possibly add routes */ +        if(ifconfig_order() == ROUTE_BEFORE_TUN) { +            if (!c->options.route_delay_defined) +                do_route (&c->options, c->c1.route_list, c->c1.route_ipv6_list, +                          c->c1.tuntap, c->plugins, c->c2.es); +        }        /* open the tun device */        open_tun (c->options.dev, c->options.dev_type, c->options.dev_node, @@ -1509,10 +1516,11 @@ do_open_tun (struct context *c)  		   c->c2.es);        /* possibly add routes */ +        if(ifconfig_order() == ROUTE_AFTER_TUN) {        if (!c->options.route_delay_defined)  	do_route (&c->options, c->c1.route_list, c->c1.route_ipv6_list,  		  c->c1.tuntap, c->plugins, c->c2.es); - +        }        /*         * Did tun/tap driver give us an MTU?         */ diff --git a/openvpn/src/openvpn/tun.c b/openvpn/src/openvpn/tun.c index 58e9bc53..ae372e48 100644 --- a/openvpn/src/openvpn/tun.c +++ b/openvpn/src/openvpn/tun.c @@ -1383,6 +1383,7 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu      for (i = 0; i < tt->options.dns_len; ++i) {          android_set_dns(print_in_addr_t(tt->options.dns[i], 0, &gc));      } +      if(tt->options.domain)          android_set_domain(tt->options.domain);      tt->fd = android_open_tun(); diff --git a/openvpn/src/openvpn/tun.h b/openvpn/src/openvpn/tun.h index 6754c726..095e77eb 100644 --- a/openvpn/src/openvpn/tun.h +++ b/openvpn/src/openvpn/tun.h @@ -300,6 +300,23 @@ ifconfig_order(void)  #endif  } +#define ROUTE_BEFORE_TUN 0 +#define ROUTE_AFTER_TUN 1 +#define ROUTE_ORDER_DEFAULT ROUTE_AFTER_TUN + +static inline int +route_order(void) +{ +#if defined(TARGET_ANDROID) +    return ROUTE_BEFORE_TUN; +#else +    return ROUTE_ORDER_DEFAULT; +#endif +} + + + +  #ifdef WIN32  #define TUN_PASS_BUFFER diff --git a/res/values-de/arrays.xml b/res/values-de/arrays.xml index 80244f3f..06b26fa4 100644 --- a/res/values-de/arrays.xml +++ b/res/values-de/arrays.xml @@ -1,10 +1,8 @@  <?xml version="1.0" encoding="utf-8"?>  <resources> -    <string-array name="tls_directions"> +    <string-array name="tls_directions_entries">          <item>0</item>          <item>1</item> -        <item>Nicht spezifiziert</item>         +        <item>Unspezifiziert</item>      </string-array> -     -  </resources>
\ No newline at end of file diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 51b727e4..f4651fd2 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -17,18 +17,16 @@      </string-array> -    <string-array name="tls_directions"> +    <string-array name="tls_directions_entries">          <item>0</item>          <item>1</item>          <item>Unspecified</item>              </string-array> -    <string-array name="tls_directions_entries"> +    <string-array name="tls_directions_values">          <item>0</item>          <item>1</item> -        <item>GNA</item>         +        <item></item>              </string-array> -     -     -     +          </resources>
\ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 89159094..a837840e 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -101,4 +101,6 @@      <string name="no_error_found">No error found</string>      <string name="config_error_found">Error in Configuration</string>      <string name="config_error_message">An error has been found in your VPN configuration:</string> +    <string name="ipv4_format_error">Cannot parse the IPv4 address</string> +    <string name="custom_route_format_error">Cannot parse the custom routes</string>  </resources> diff --git a/res/xml/main_headers.xml b/res/xml/main_headers.xml index a0c4f432..7ea95848 100644 --- a/res/xml/main_headers.xml +++ b/res/xml/main_headers.xml @@ -3,7 +3,7 @@      <header          android:fragment="de.blinkt.openvpn.VPNProfileList" -        android:summary="List of all VPN, confusing to be here :)" +        android:summary="List of all configured VPNs"          android:title="All your precious VPNs" />      <header          android:fragment="de.blinkt.openvpn.AboutFragment" diff --git a/res/xml/vpn_authentification.xml b/res/xml/vpn_authentification.xml index 0444831b..ceeb514b 100644 --- a/res/xml/vpn_authentification.xml +++ b/res/xml/vpn_authentification.xml @@ -25,16 +25,17 @@          <Preference              android:dependency="useTLSAuth"              android:key="tlsAuthFile" -            android:title="Title Auth File" /> +            android:title="TLS Auth File" />          <ListPreference -            android:dependency="useTLSAuth" -            android:dialogMessage="Select the direction for TLS Auth." -            android:entries="@array/tls_directions" -            android:entryValues="@array/tls_directions_entries" +            android:entries="@array/tls_directions_entries" +                    android:dependency="useTLSAuth" +             +            android:entryValues="@array/tls_directions_values"              android:key="tls_direction" -            android:title="TLS Direction"  -            android:persistent="false"/> +            android:persistent="false" +            android:title="TLS Direction" />      </PreferenceCategory> +/>  </PreferenceScreen>
\ No newline at end of file diff --git a/res/xml/vpn_ipsettings.xml b/res/xml/vpn_ipsettings.xml index 79356e69..a018321f 100644 --- a/res/xml/vpn_ipsettings.xml +++ b/res/xml/vpn_ipsettings.xml @@ -40,8 +40,12 @@      </PreferenceCategory>      <PreferenceCategory android:title="Routing" >          <CheckBoxPreference -            android:defaultValue="true" -            android:dependency="usePull" +			android:title="Ignore pushed routes" +			android:key="routenopull" +			android:summary="Ignore routed pushed by the server." + +            /> +        <CheckBoxPreference              android:disableDependentsState="true"              android:key="useDefaultRoute"              android:summary="Redirects all Traffic over the VPN" diff --git a/src/de/blinkt/openvpn/OpenVPN.java b/src/de/blinkt/openvpn/OpenVPN.java index bca276c9..c3d92a4c 100644 --- a/src/de/blinkt/openvpn/OpenVPN.java +++ b/src/de/blinkt/openvpn/OpenVPN.java @@ -8,7 +8,6 @@ import android.util.Log;  public class OpenVPN {  	private static OpenVpnService mOpenVpnService; -	private static String localip;  	private static final int MAXLOGENTRIES = 500;  	public static native int startOpenVPNThread();  	public static native int startOpenVPNThreadArgs(String argv[]); @@ -32,14 +31,15 @@ public class OpenVPN {  	    }  	 static void addRoute(String dest,String mask, String gw) { -	        Log.i("openvpn" ,"Got Routing information " + dest + " " + mask + "  " + gw  );		  +	        Log.i("openvpn" ,"Got Routing information " + dest + " " + mask + "  " + gw  );	 +	        mOpenVpnService.addRoute(dest,mask);  	 }  	 synchronized static void logMessage(int level,String prefix, String message)  	 { -		 logbuffer.addFirst(prefix + " " + message); +		 logbuffer.addLast(prefix + " " + message);  		 if(logbuffer.size()>MAXLOGENTRIES) -			 logbuffer.removeLast(); +			 logbuffer.removeFirst();  		 // The garbage collector does not collect the String from native  		 // but kills me for logging 100 messages with too many references :( @@ -62,10 +62,10 @@ public class OpenVPN {  	 } -	 static void addInterfaceInfo(int mtu, String local, String remote) +	 static void addInterfaceInfo(int mtu, String local, String netmask)  	 { -		 Log.i("openvpn","Got interface info M"  + mtu + " L: " + local + "R: " + remote); -		 localip=local; +		 Log.i("openvpn","Got interface info M"  + mtu + " L: " + local + "NM: " + netmask); +		 mOpenVpnService.setLocalIP(local,netmask);  	 }  	 static void addDns(String dns) { @@ -96,7 +96,7 @@ public class OpenVPN {  	public static int openTunDevice() {  		Log.d(TAG,"Opening tun device"); -		ParcelFileDescriptor pfd = mOpenVpnService.openTun(localip); +		ParcelFileDescriptor pfd = mOpenVpnService.openTun();  		return pfd.detachFd();  	}  	//! Dummy method being called to force loading of JNI Libraries diff --git a/src/de/blinkt/openvpn/OpenVpnService.java b/src/de/blinkt/openvpn/OpenVpnService.java index 1cc5b2ec..39d73adb 100644 --- a/src/de/blinkt/openvpn/OpenVpnService.java +++ b/src/de/blinkt/openvpn/OpenVpnService.java @@ -21,6 +21,8 @@ import java.net.UnknownHostException;  import java.util.Arrays;  import java.util.Vector; +import de.blinkt.openvpn.OpenVpnService.CIDRIP; +  import android.app.PendingIntent;  import android.content.Intent;  import android.net.LocalSocket; @@ -38,7 +40,8 @@ public class OpenVpnService extends VpnService implements Handler.Callback, Runn      private String[] mArgv;      private Handler mHandler; -    private Thread mThread; +    // Only one VPN, make this thread shared between all instances +    private static Thread mThread;      private ParcelFileDescriptor mInterface; @@ -48,6 +51,36 @@ public class OpenVpnService extends VpnService implements Handler.Callback, Runn  	private String mDomain=null; +	private Vector<CIDRIP> mRoutes=new Vector<CIDRIP>(); + +	private CIDRIP mLocalIP; + +	 +	class CIDRIP{ +		String mIp; +		int len; +		public CIDRIP(String ip, String mask){ +			mIp=ip; +			String[] ipt = mask.split("\\."); +			long netmask=0; +			 +			netmask += Integer.parseInt(ipt[0]); +			netmask += Integer.parseInt(ipt[1])<< 8; +			netmask += Integer.parseInt(ipt[2])<< 16; +			netmask += Integer.parseInt(ipt[3])<< 24; +			 +			len =0; +			while((netmask & 0x1) == 1) { +				len++; +				netmask = netmask >> 1; +			} +		} +		@Override +		public String toString() { +			return String.format("%s/%d",mIp,len); +		} +	} +	      @Override      public void onRevoke() {      	managmentCommand("signal SIGINT\n"); @@ -216,19 +249,31 @@ public class OpenVpnService extends VpnService implements Handler.Callback, Runn      } -	public ParcelFileDescriptor openTun(String localip) { -		// FIXME: hardcoded assumptions +	public ParcelFileDescriptor openTun() {          Builder builder = new Builder(); -        builder.addRoute("0.0.0.0", 0); -        builder.addAddress(localip, 24 ); +         +        builder.addAddress(mLocalIP.mIp, mLocalIP.len); +                  for (String dns : mDnslist ) {              builder.addDnsServer(dns);  		} - +      +         +        for (CIDRIP route:mRoutes) { +        	builder.addRoute(route.mIp, route.len); +        } +                  if(mDomain!=null)          	builder.addSearchDomain(mDomain); -        builder.setSession(mProfile.mName + " - " + localip); + +        mDnslist.clear(); +        mRoutes.clear(); + +         +        builder.setSession(mProfile.mName + " - " + mLocalIP); +         +        // Let the configure Button show the Log          Intent intent = new Intent(getBaseContext(),LogWindow.class);          PendingIntent startLW = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0);          builder.setConfigureIntent(startLW); @@ -248,4 +293,14 @@ public class OpenVpnService extends VpnService implements Handler.Callback, Runn  			mDomain=domain;  		}  	} + + +	public void addRoute(String dest, String mask) { +		mRoutes.add(new CIDRIP(dest, mask)); +	} + + +	public void setLocalIP(String local, String netmask) { +		mLocalIP = new CIDRIP(local, netmask); +	}  } diff --git a/src/de/blinkt/openvpn/Settings_Authentication.java b/src/de/blinkt/openvpn/Settings_Authentication.java index f3ebb36d..4c70344d 100644 --- a/src/de/blinkt/openvpn/Settings_Authentication.java +++ b/src/de/blinkt/openvpn/Settings_Authentication.java @@ -58,7 +58,7 @@ public class Settings_Authentication extends PreferenceFragment implements OnPre  		mUseTLSAuth.setChecked(mProfile.mUseTLSAuth);  		mTLSAuthFile.setSummary(mProfile.mTLSAuthFilename); -		//mTLSAuthDirection.setValue(mProfile.mTLSAuthDirection); +		mTLSAuthDirection.setValue(mProfile.mTLSAuthDirection);  	}  	private void saveSettings() { @@ -72,10 +72,10 @@ public class Settings_Authentication extends PreferenceFragment implements OnPre  		else  			mProfile.mTLSAuthFilename = mTLSAuthFile.getSummary().toString(); -		if(mTLSAuthDirection.getEntry()==null) +		if(mTLSAuthDirection.getValue()==null)  			mProfile.mTLSAuthDirection=null;  		else -			mProfile.mTLSAuthDirection = mTLSAuthDirection.getEntry().toString(); +			mProfile.mTLSAuthDirection = mTLSAuthDirection.getValue().toString();  	}  	@Override diff --git a/src/de/blinkt/openvpn/Settings_IP.java b/src/de/blinkt/openvpn/Settings_IP.java index c2b1ed71..de625d22 100644 --- a/src/de/blinkt/openvpn/Settings_IP.java +++ b/src/de/blinkt/openvpn/Settings_IP.java @@ -19,6 +19,7 @@ public class Settings_IP extends PreferenceFragment implements OnPreferenceChang  		private EditTextPreference mCustomRoutes;  		private CheckBoxPreference mUseDefaultRoute;  		private VpnProfile mProfile; +		private CheckBoxPreference mRouteNoPull;  		@Override  		public void onCreate(Bundle savedInstanceState) { @@ -45,6 +46,7 @@ public class Settings_IP extends PreferenceFragment implements OnPreferenceChang  			mDNS2 = (EditTextPreference) findPreference("dns2");  			mCustomRoutes = (EditTextPreference) findPreference("customRoutes");  			mUseDefaultRoute = (CheckBoxPreference) findPreference("useDefaultRoute"); +			mRouteNoPull = (CheckBoxPreference) findPreference("routenopull");  			mIPv4.setOnPreferenceChangeListener(this);  			mIPv6.setOnPreferenceChangeListener(this); @@ -72,6 +74,7 @@ public class Settings_IP extends PreferenceFragment implements OnPreferenceChang  			mSearchdomain.setText(mProfile.mSearchDomain);  			mUseDefaultRoute.setChecked(mProfile.mUseDefaultRoute);  			mCustomRoutes.setText(mProfile.mCustomRoutes); +			mRouteNoPull.setChecked(mProfile.mRoutenopull);  			// Sets Summary  			onPreferenceChange(mIPv4, mIPv4.getText()); @@ -105,7 +108,7 @@ public class Settings_IP extends PreferenceFragment implements OnPreferenceChang  			mProfile.mSearchDomain = mSearchdomain.getText();  			mProfile.mUseDefaultRoute = mUseDefaultRoute.isChecked();  			mProfile.mCustomRoutes = mCustomRoutes.getText(); -			 +			mProfile.mRoutenopull = mRouteNoPull.isChecked();  		} @@ -120,10 +123,10 @@ public class Settings_IP extends PreferenceFragment implements OnPreferenceChang  				preference.setSummary((String)newValue);  			if(preference== mUsePull || preference == mOverrideDNS) -				if(preference==mOverrideDNS)  +				if(preference==mOverrideDNS) {   					// Set so the function gets the right value  					mOverrideDNS.setChecked((Boolean) newValue); -				 +				}  				setDNSState();  			saveSettings(); @@ -133,6 +136,7 @@ public class Settings_IP extends PreferenceFragment implements OnPreferenceChang  		private void setDNSState() {  			boolean enabled;  			mOverrideDNS.setEnabled(mUsePull.isChecked()); +			mRouteNoPull.setEnabled(mUsePull.isChecked());  			if(!mUsePull.isChecked())  				enabled =true;  			else if (mOverrideDNS.isChecked()) @@ -143,6 +147,7 @@ public class Settings_IP extends PreferenceFragment implements OnPreferenceChang  			mDNS1.setEnabled(enabled);  			mDNS2.setEnabled(enabled);  			mSearchdomain.setEnabled(enabled); +			  		} diff --git a/src/de/blinkt/openvpn/ShowConfigFragment.java b/src/de/blinkt/openvpn/ShowConfigFragment.java index a69d835a..68898e07 100644 --- a/src/de/blinkt/openvpn/ShowConfigFragment.java +++ b/src/de/blinkt/openvpn/ShowConfigFragment.java @@ -13,10 +13,18 @@ public class ShowConfigFragment extends Fragment {  	{  		String profileUUID = getArguments().getString(getActivity().getPackageName() + ".profileUUID");  		VpnProfile vp = ProfileManager.get(profileUUID); -		String cfg=vp.getConfigFile(getActivity().getCacheDir());  		View v=inflater.inflate(R.layout.viewconfig, container,false);  		TextView cv = (TextView) v.findViewById(R.id.configview); -		cv.setText(cfg); +		 +		int check=vp.checkProfile(); +		if(check!=R.string.no_error_found) { +			cv.setText(check); +		} +		else {  +			String cfg=vp.getConfigFile(getActivity().getCacheDir()); + +			cv.setText(cfg); +		}  		return v;  	};  } diff --git a/src/de/blinkt/openvpn/VPNPreferences.java b/src/de/blinkt/openvpn/VPNPreferences.java index 4b1c7377..771cd902 100644 --- a/src/de/blinkt/openvpn/VPNPreferences.java +++ b/src/de/blinkt/openvpn/VPNPreferences.java @@ -44,11 +44,11 @@ public class VPNPreferences extends PreferenceActivity { -		if (hasHeaders()) { +		/* if (hasHeaders()) {  			Button button = new Button(this);  			button.setText("Save");  			setListFooter(button); -		} +		} */  	} diff --git a/src/de/blinkt/openvpn/VPNProfileList.java b/src/de/blinkt/openvpn/VPNProfileList.java index f77c8639..8f4304dc 100644 --- a/src/de/blinkt/openvpn/VPNProfileList.java +++ b/src/de/blinkt/openvpn/VPNProfileList.java @@ -184,7 +184,7 @@ public class VPNProfileList extends PreferenceFragment implements  VpnPreference  			startActivity(startLW); -			OpenVPN.logMessage(0, "", "Building confugration..."); +			OpenVPN.logMessage(0, "", "Building configration...");  			Intent startVPN = mSelectedVPN.prepareIntent(getActivity()); diff --git a/src/de/blinkt/openvpn/VpnProfile.java b/src/de/blinkt/openvpn/VpnProfile.java index e17fb8ff..2df4ec39 100644 --- a/src/de/blinkt/openvpn/VpnProfile.java +++ b/src/de/blinkt/openvpn/VpnProfile.java @@ -12,6 +12,7 @@ import java.security.NoSuchAlgorithmException;  import java.security.PrivateKey;  import java.security.cert.CertificateException;  import java.security.cert.X509Certificate; +import java.util.Collection;  import java.util.Random;  import java.util.UUID;  import java.util.Vector; @@ -35,7 +36,7 @@ public class VpnProfile implements  Serializable{  	static final int TYPE_KEYSTORE=2;  	public static final int TYPE_USERPASS = 3;  	public static final int TYPE_STATICKEYS = 4; -	 +  	private static final String OVPNCONFIGFILE = "android.conf";  	// Keep in order of parceling @@ -71,6 +72,7 @@ public class VpnProfile implements  Serializable{  	public String mRemoteCN="";  	private String mPassword;  	private String mUsername; +	public boolean mRoutenopull=false;  	public int describeContents() { @@ -145,27 +147,27 @@ public class VpnProfile implements  Serializable{  		return mName;  	} -	 +  	public String getConfigFile(File cacheDir)  	{  		String cfg=""; -		 -		 + +  		// TODO  "--remote-cert-eku", "TLS Web Server Authentication" -		 +  		boolean useTLSClient = (mAuthenticationType != TYPE_STATICKEYS); -	 +  		if(useTLSClient && mUsePull)  			cfg+="client\n";  		else if (mUsePull)  			cfg+="pull\n";  		else if(useTLSClient) -			cfg+="tls-client"; -			 -		 +			cfg+="tls-client\n"; + +  		cfg+="verb 2\n"; @@ -240,19 +242,30 @@ public class VpnProfile implements  Serializable{  		// Basic Settings  		if(!mUsePull ) { -			cfg +="ifconfig " + mIPv4Address + " 255.255.255.255\n"; +			cfg +="ifconfig " + cidrToIPAndNetmask(mIPv4Address) + "\n";  		} -		 + +		if(mUsePull && mRoutenopull) +			cfg += "route-nopull\n"; + +		if(mUseDefaultRoute) +			cfg += "route 0.0.0.0 0.0.0.0\n"; +		else +			for(String route:getCustomRoutes()) { +				cfg += "route " + route + "\n"; +			} + +  		if(mOverrideDNS || !mUsePull) {  			if(!mDNS1.equals("") && mDNS1!=null)  				cfg+="dhcp-option DNS " + mDNS1 + "\n";  			if(!mDNS2.equals("") && mDNS2!=null)  				cfg+="dhcp-option DNS " + mDNS2 + "\n"; -			 +  		} -		 -		 + +  		// Authentication  		if(mCheckRemoteCN) {  			if(mRemoteCN == null || mRemoteCN.equals("") ) @@ -262,9 +275,52 @@ public class VpnProfile implements  Serializable{  		}  		if(mExpectTLSCert)  			cfg += "remote-cert-tls server\n"; -		 +  		return cfg;  	} + +	private Collection<String> getCustomRoutes() { +		Vector<String> cidrRoutes=new Vector<String>(); +		for(String route:mCustomRoutes.split("[\n \t]")) { +			if(!route.equals("")) { +				String cidrroute = cidrToIPAndNetmask(route); +				if(cidrRoutes == null) +					return null; +				 +				cidrRoutes.add(cidrroute); +			} +		} +		 +		return cidrRoutes; +	} + +	private String cidrToIPAndNetmask(String route) { +		String[] parts = route.split("/"); + +		// No /xx, return verbatim +		if (parts.length ==1) +			return route; + +		if (parts.length!=2) +			return null; +		int len; +		try {  +			len = Integer.parseInt(parts[1]); +		}	catch(NumberFormatException ne) { +			return null; +		} +		if (len <0 || len >32) +			return null; + + +		long nm = 0xffffffffl; +		nm = (nm << len) & 0xffffffffl; + +		String netmask =String.format("%d.%d.%d.%d", (nm & 0xff000000) >> 24,(nm & 0xff0000) >> 16, (nm & 0xff00) >> 8 ,nm & 0xff  );	 +		return parts[0] + "  " + netmask; +	} + +  	private String[] buildOpenvpnArgv(File cacheDir)  	{ @@ -290,8 +346,8 @@ public class VpnProfile implements  Serializable{  	public Intent prepareIntent(Activity activity) {  		String prefix = activity.getPackageName(); -		 -		 Intent intent = new Intent(activity,OpenVpnService.class); + +		Intent intent = new Intent(activity,OpenVpnService.class);  		intent.putExtra(prefix + ".ARGV" , buildOpenvpnArgv(activity.getCacheDir())); @@ -304,14 +360,14 @@ public class VpnProfile implements  Serializable{  			String pkcs12pw = savePKCS12(activity);  			intent.putExtra(prefix + ".PKCS12PASS", pkcs12pw);  		} -		 +  		if(mAuthenticationType == VpnProfile.TYPE_USERPASS) {  			intent.putExtra(prefix + ".USERNAME", mUsername);  			intent.putExtra(prefix + ".PASSWORD", mPassword);  		} -		 +  		intent.putExtra(prefix + ".profileUUID", mUuid.toString()); -		 +  		try {  			FileWriter cfg = new FileWriter(activity.getCacheDir().getAbsolutePath() + "/" + OVPNCONFIGFILE);  			cfg.write(getConfigFile(activity.getCacheDir())); @@ -320,10 +376,10 @@ public class VpnProfile implements  Serializable{  		} catch (IOException e) {  			e.printStackTrace();  		} -		 +  		return intent;  	} -	 +  	private String getRandomPW() {  		String pw= "";  		// Put enough digits togher to make a password :) @@ -373,11 +429,18 @@ public class VpnProfile implements  Serializable{  	int checkProfile() {  		if(mAuthenticationType==TYPE_KEYSTORE && mAlias==null)   			return R.string.no_keystore_cert_selected; -		 -		 + +		if(!mUsePull) { +			if(mIPv4Address == null || cidrToIPAndNetmask(mIPv4Address) == null) +				return R.string.ipv4_format_error; +			 +		} +		if(!mUseDefaultRoute && getCustomRoutes()==null) +			return R.string.custom_route_format_error; +  		// Everything okay  		return R.string.no_error_found; -		 +  	} | 
