summaryrefslogtreecommitdiff
path: root/app/src/main/java/de
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/de')
-rw-r--r--app/src/main/java/de/blinkt/openvpn/LaunchVPN.java32
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java1030
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java13
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java30
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java5
-rw-r--r--app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java2
6 files changed, 553 insertions, 559 deletions
diff --git a/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java b/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java
index 02abd7a1..0eb1d99c 100644
--- a/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java
+++ b/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java
@@ -120,23 +120,23 @@ public class LaunchVPN extends Activity {
@Override
protected void onActivityResult (int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
-
- if(requestCode==START_VPN_PROFILE) {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
- boolean showLogWindow = prefs.getBoolean("showlogwindow", true);
-
- if(!mhideLog && showLogWindow)
- showLogWindow();
- new startOpenVpnThread().start();
- } else if (resultCode == Activity.RESULT_CANCELED) {
- // User does not want us to start, so we just vanish
- VpnStatus.updateStateString("USER_VPN_PERMISSION_CANCELLED", "", R.string.state_user_vpn_permission_cancelled,
- ConnectionStatus.LEVEL_NOTCONNECTED);
-
- finish();
- }
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if(requestCode==START_VPN_PROFILE) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ boolean showlogwindow = prefs.getBoolean("showlogwindow", true);
+
+ if(!mhideLog && showlogwindow)
+ showLogWindow();
+ new startOpenVpnThread().start();
+ } else if (resultCode == Activity.RESULT_CANCELED) {
+ // User does not want us to start, so we just vanish
+ VpnStatus.updateStateString("USER_VPN_PERMISSION_CANCELLED", "", R.string.state_user_vpn_permission_cancelled, ConnectionStatus.LEVEL_NOTCONNECTED);
+
+ finish();
+ }
}
+
void showLogWindow() {
Intent startLW = new Intent(getBaseContext(),LogWindow.class);
diff --git a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
index 5dc96bbc..5f5d486c 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
@@ -28,11 +28,11 @@ import de.blinkt.openvpn.VpnProfile;
public class ConfigParser {
- public static final String CONVERTED_PROFILE = "converted Profile";
- private HashMap<String, Vector<Vector<String>>> options = new HashMap<String, Vector<Vector<String>>>();
- private HashMap<String, Vector<String>> meta = new HashMap<String, Vector<String>>();
+ public static final String CONVERTED_PROFILE = "converted Profile";
+ private HashMap<String, Vector<Vector<String>>> options = new HashMap<String, Vector<Vector<String>>>();
+ private HashMap<String, Vector<String>> meta = new HashMap<String, Vector<String>>();
- public void parseConfig(Reader reader) throws IOException, ConfigParseError {
+ public void parseConfig(Reader reader) throws IOException, ConfigParseError {
BufferedReader br = new BufferedReader(reader);
@@ -75,192 +75,176 @@ public class ConfigParser {
} catch (java.lang.OutOfMemoryError memoryError) {
throw new ConfigParseError("File too large to parse: " + memoryError.getLocalizedMessage());
}
- }
+ }
- private Vector<String> parsemeta(String line) {
- String meta = line.split("#\\sOVPN_ACCESS_SERVER_", 2)[1];
- String[] parts = meta.split("=",2);
- Vector<String> rval = new Vector<String>();
+ private Vector<String> parsemeta(String line) {
+ String meta = line.split("#\\sOVPN_ACCESS_SERVER_", 2)[1];
+ String[] parts = meta.split("=", 2);
+ Vector<String> rval = new Vector<String>();
Collections.addAll(rval, parts);
- return rval;
-
- }
-
- private void checkinlinefile(Vector<String> args, BufferedReader br) throws IOException, ConfigParseError {
- String arg0 = args.get(0).trim();
- // CHeck for <foo>
- if(arg0.startsWith("<") && arg0.endsWith(">")) {
- String argname = arg0.substring(1, arg0.length()-1);
- String inlinefile = VpnProfile.INLINE_TAG;
-
- String endtag = String.format("</%s>",argname);
- do {
- String line = br.readLine();
- if(line==null){
- throw new ConfigParseError(String.format("No endtag </%s> for starttag <%s> found",argname,argname));
- }
- if(line.trim().equals(endtag))
- break;
- else {
- inlinefile+=line;
- inlinefile+= "\n";
- }
- } while(true);
-
- args.clear();
- args.add(argname);
- args.add(inlinefile);
- }
-
- }
-
- enum linestate {
- initial,
- readin_single_quote
- , reading_quoted, reading_unquoted, done}
-
- private boolean space(char c) {
- // I really hope nobody is using zero bytes inside his/her config file
- // to sperate parameter but here we go:
- return Character.isWhitespace(c) || c == '\0';
-
- }
-
- public class ConfigParseError extends Exception {
- private static final long serialVersionUID = -60L;
-
- public ConfigParseError(String msg) {
- super(msg);
- }
- }
-
-
- // adapted openvpn's parse function to java
- private Vector<String> parseline(String line) throws ConfigParseError {
- Vector<String> parameters = new Vector<String>();
-
- if (line.length()==0)
- return parameters;
-
-
- linestate state = linestate.initial;
- boolean backslash = false;
- char out=0;
-
- int pos=0;
- String currentarg="";
-
- do {
- // Emulate the c parsing ...
- char in;
- if(pos < line.length())
- in = line.charAt(pos);
- else
- in = '\0';
-
- if (!backslash && in == '\\' && state != linestate.readin_single_quote)
- {
- backslash = true;
- }
- else
- {
- if (state == linestate.initial)
- {
- if (!space (in))
- {
- if (in == ';' || in == '#') /* comment */
- break;
- if (!backslash && in == '\"')
- state = linestate.reading_quoted;
- else if (!backslash && in == '\'')
- state = linestate.readin_single_quote;
- else
- {
- out = in;
- state = linestate.reading_unquoted;
- }
- }
- }
- else if (state == linestate.reading_unquoted)
- {
- if (!backslash && space (in))
- state = linestate.done;
- else
- out = in;
- }
- else if (state == linestate.reading_quoted)
- {
- if (!backslash && in == '\"')
- state = linestate.done;
- else
- out = in;
- }
- else if (state == linestate.readin_single_quote)
- {
- if (in == '\'')
- state = linestate.done;
- else
- out = in;
- }
-
- if (state == linestate.done)
- {
- /* ASSERT (parm_len > 0); */
- state = linestate.initial;
- parameters.add(currentarg);
- currentarg = "";
- out =0;
- }
-
- if (backslash && out!=0)
- {
- if (!(out == '\\' || out == '\"' || space (out)))
- {
- throw new ConfigParseError("Options warning: Bad backslash ('\\') usage");
- }
- }
- backslash = false;
- }
+ return rval;
+
+ }
+
+ private void checkinlinefile(Vector<String> args, BufferedReader br) throws IOException, ConfigParseError {
+ String arg0 = args.get(0).trim();
+ // CHeck for <foo>
+ if (arg0.startsWith("<") && arg0.endsWith(">")) {
+ String argname = arg0.substring(1, arg0.length() - 1);
+ String inlinefile = VpnProfile.INLINE_TAG;
+
+ String endtag = String.format("</%s>", argname);
+ do {
+ String line = br.readLine();
+ if (line == null) {
+ throw new ConfigParseError(String.format("No endtag </%s> for starttag <%s> found", argname, argname));
+ }
+ if (line.trim().equals(endtag))
+ break;
+ else {
+ inlinefile += line;
+ inlinefile += "\n";
+ }
+ } while (true);
+
+ args.clear();
+ args.add(argname);
+ args.add(inlinefile);
+ }
+
+ }
+
+ enum linestate {
+ initial,
+ readin_single_quote, reading_quoted, reading_unquoted, done
+ }
+
+ private boolean space(char c) {
+ // I really hope nobody is using zero bytes inside his/her config file
+ // to sperate parameter but here we go:
+ return Character.isWhitespace(c) || c == '\0';
+
+ }
+
+ public class ConfigParseError extends Exception {
+ private static final long serialVersionUID = -60L;
+
+ public ConfigParseError(String msg) {
+ super(msg);
+ }
+ }
+
+
+ // adapted openvpn's parse function to java
+ private Vector<String> parseline(String line) throws ConfigParseError {
+ Vector<String> parameters = new Vector<String>();
+
+ if (line.length() == 0)
+ return parameters;
+
+
+ linestate state = linestate.initial;
+ boolean backslash = false;
+ char out = 0;
+
+ int pos = 0;
+ String currentarg = "";
+
+ do {
+ // Emulate the c parsing ...
+ char in;
+ if (pos < line.length())
+ in = line.charAt(pos);
+ else
+ in = '\0';
+
+ if (!backslash && in == '\\' && state != linestate.readin_single_quote) {
+ backslash = true;
+ } else {
+ if (state == linestate.initial) {
+ if (!space(in)) {
+ if (in == ';' || in == '#') /* comment */
+ break;
+ if (!backslash && in == '\"')
+ state = linestate.reading_quoted;
+ else if (!backslash && in == '\'')
+ state = linestate.readin_single_quote;
+ else {
+ out = in;
+ state = linestate.reading_unquoted;
+ }
+ }
+ } else if (state == linestate.reading_unquoted) {
+ if (!backslash && space(in))
+ state = linestate.done;
+ else
+ out = in;
+ } else if (state == linestate.reading_quoted) {
+ if (!backslash && in == '\"')
+ state = linestate.done;
+ else
+ out = in;
+ } else if (state == linestate.readin_single_quote) {
+ if (in == '\'')
+ state = linestate.done;
+ else
+ out = in;
+ }
+
+ if (state == linestate.done) {
+ /* ASSERT (parm_len > 0); */
+ state = linestate.initial;
+ parameters.add(currentarg);
+ currentarg = "";
+ out = 0;
+ }
+
+ if (backslash && out != 0) {
+ if (!(out == '\\' || out == '\"' || space(out))) {
+ throw new ConfigParseError("Options warning: Bad backslash ('\\') usage");
+ }
+ }
+ backslash = false;
+ }
/* store parameter character */
- if (out!=0)
- {
- currentarg+=out;
- }
- } while (pos++ < line.length());
-
- return parameters;
- }
-
-
- final String[] unsupportedOptions = { "config",
- "tls-server"
-
- };
-
- // Ignore all scripts
- // in most cases these won't work and user who wish to execute scripts will
- // figure out themselves
- final String[] ignoreOptions = { "tls-client",
- "askpass",
- "auth-nocache",
- "up",
- "down",
- "route-up",
- "ipchange",
- "route-up",
- "route-pre-down",
- "auth-user-pass-verify",
- "dhcp-release",
- "dhcp-renew",
- "dh",
+ if (out != 0) {
+ currentarg += out;
+ }
+ } while (pos++ < line.length());
+
+ return parameters;
+ }
+
+
+ final String[] unsupportedOptions = {"config",
+ "tls-server"
+
+ };
+
+ // Ignore all scripts
+ // in most cases these won't work and user who wish to execute scripts will
+ // figure out themselves
+ final String[] ignoreOptions = {"tls-client",
+ "askpass",
+ "auth-nocache",
+ "up",
+ "down",
+ "route-up",
+ "ipchange",
+ "route-up",
+ "route-pre-down",
+ "auth-user-pass-verify",
+ "dhcp-release",
+ "dhcp-renew",
+ "dh",
"group",
"ip-win32",
"management-hold",
"management",
"management-client",
"management-query-remote",
- "management-query-passwords",
+ "management-query-passwords",
"management-query-proxy",
"management-external-key",
"management-forget-disconnect",
@@ -269,32 +253,32 @@ public class ConfigParser {
"management-up-down",
"management-client-user",
"management-client-group",
- "pause-exit",
+ "pause-exit",
"plugin",
"machine-readable-output",
- "persist-key",
- "register-dns",
- "route-delay",
- "route-gateway",
- "route-metric",
- "route-method",
- "status",
- "script-security",
- "show-net-up",
- "suppress-timestamps",
- "tmp-dir",
- "tun-ipv6",
- "topology",
+ "persist-key",
+ "register-dns",
+ "route-delay",
+ "route-gateway",
+ "route-metric",
+ "route-method",
+ "status",
+ "script-security",
+ "show-net-up",
+ "suppress-timestamps",
+ "tmp-dir",
+ "tun-ipv6",
+ "topology",
"user",
"win-sys",
-
};
final String[][] ignoreOptionsWithArg =
- {
- {"setenv", "IV_GUI_VER"},
- {"setenv", "IV_OPENVPN_GUI_VERSION"}
- };
+ {
+ {"setenv", "IV_GUI_VER"},
+ {"setenv", "IV_OPENVPN_GUI_VERSION"},
+ {"engine", "dynamic"}
+ };
final String[] connectionOptions = {
"local",
@@ -326,70 +310,67 @@ public class ConfigParser {
// This method is far too long
- @SuppressWarnings("ConstantConditions")
+ @SuppressWarnings("ConstantConditions")
public VpnProfile convertProfile() throws ConfigParseError, IOException {
- boolean noauthtypeset=true;
- VpnProfile np = new VpnProfile(CONVERTED_PROFILE);
- // Pull, client, tls-client
- np.clearDefaults();
-
- if(options.containsKey("client") || options.containsKey("pull")) {
- np.mUsePull=true;
- options.remove("pull");
- options.remove("client");
- }
-
- Vector<String> secret = getOption("secret", 1, 2);
- if(secret!=null)
- {
- np.mAuthenticationType=VpnProfile.TYPE_STATICKEYS;
- noauthtypeset=false;
- np.mUseTLSAuth=true;
- np.mTLSAuthFilename=secret.get(1);
- if(secret.size()==3)
- np.mTLSAuthDirection=secret.get(2);
-
- }
-
- Vector<Vector<String>> routes = getAllOption("route", 1, 4);
- if(routes!=null) {
- String routeopt = "";
+ boolean noauthtypeset = true;
+ VpnProfile np = new VpnProfile(CONVERTED_PROFILE);
+ // Pull, client, tls-client
+ np.clearDefaults();
+
+ if (options.containsKey("client") || options.containsKey("pull")) {
+ np.mUsePull = true;
+ options.remove("pull");
+ options.remove("client");
+ }
+
+ Vector<String> secret = getOption("secret", 1, 2);
+ if (secret != null) {
+ np.mAuthenticationType = VpnProfile.TYPE_STATICKEYS;
+ noauthtypeset = false;
+ np.mUseTLSAuth = true;
+ np.mTLSAuthFilename = secret.get(1);
+ if (secret.size() == 3)
+ np.mTLSAuthDirection = secret.get(2);
+
+ }
+
+ Vector<Vector<String>> routes = getAllOption("route", 1, 4);
+ if (routes != null) {
+ String routeopt = "";
String routeExcluded = "";
- for(Vector<String> route:routes){
- String netmask = "255.255.255.255";
+ for (Vector<String> route : routes) {
+ String netmask = "255.255.255.255";
String gateway = "vpn_gateway";
- if(route.size() >= 3)
- netmask = route.get(2);
+ if (route.size() >= 3)
+ netmask = route.get(2);
if (route.size() >= 4)
gateway = route.get(3);
- String net = route.get(1);
- try {
- CIDRIP cidr = new CIDRIP(net, netmask);
+ String net = route.get(1);
+ try {
+ CIDRIP cidr = new CIDRIP(net, netmask);
if (gateway.equals("net_gateway"))
routeExcluded += cidr.toString() + " ";
else
- routeopt+=cidr.toString() + " ";
- } catch (ArrayIndexOutOfBoundsException aioob) {
- throw new ConfigParseError("Could not parse netmask of route " + netmask);
- } catch (NumberFormatException ne) {
-
-
+ routeopt += cidr.toString() + " ";
+ } catch (ArrayIndexOutOfBoundsException aioob) {
+ throw new ConfigParseError("Could not parse netmask of route " + netmask);
+ } catch (NumberFormatException ne) {
- throw new ConfigParseError("Could not parse netmask of route " + netmask);
- }
+ throw new ConfigParseError("Could not parse netmask of route " + netmask);
+ }
- }
- np.mCustomRoutes=routeopt;
- np.mExcludedRoutes=routeExcluded;
- }
+ }
+ np.mCustomRoutes = routeopt;
+ np.mExcludedRoutes = routeExcluded;
+ }
Vector<Vector<String>> routesV6 = getAllOption("route-ipv6", 1, 4);
- if (routesV6!=null) {
+ if (routesV6 != null) {
String customIPv6Routes = "";
- for (Vector<String> route:routesV6){
+ for (Vector<String> route : routesV6) {
customIPv6Routes += route.get(1) + " ";
}
@@ -397,39 +378,36 @@ public class ConfigParser {
}
// Also recognize tls-auth [inline] direction ...
- Vector<Vector<String>> tlsauthoptions = getAllOption("tls-auth", 1, 2);
- if(tlsauthoptions!=null) {
- for(Vector<String> tlsauth:tlsauthoptions) {
- if(tlsauth!=null)
- {
- if(!tlsauth.get(1).equals("[inline]")) {
- np.mTLSAuthFilename=tlsauth.get(1);
- np.mUseTLSAuth=true;
- }
- if(tlsauth.size()==3)
- np.mTLSAuthDirection=tlsauth.get(2);
- }
- }
- }
-
- Vector<String> direction = getOption("key-direction", 1, 1);
- if(direction!=null)
- np.mTLSAuthDirection=direction.get(1);
+ Vector<Vector<String>> tlsauthoptions = getAllOption("tls-auth", 1, 2);
+ if (tlsauthoptions != null) {
+ for (Vector<String> tlsauth : tlsauthoptions) {
+ if (tlsauth != null) {
+ if (!tlsauth.get(1).equals("[inline]")) {
+ np.mTLSAuthFilename = tlsauth.get(1);
+ np.mUseTLSAuth = true;
+ }
+ if (tlsauth.size() == 3)
+ np.mTLSAuthDirection = tlsauth.get(2);
+ }
+ }
+ }
+
+ Vector<String> direction = getOption("key-direction", 1, 1);
+ if (direction != null)
+ np.mTLSAuthDirection = direction.get(1);
Vector<Vector<String>> defgw = getAllOption("redirect-gateway", 0, 5);
- if(defgw != null)
- {
- np.mUseDefaultRoute=true;
+ if (defgw != null) {
+ np.mUseDefaultRoute = true;
checkRedirectParameters(np, defgw);
}
- Vector<Vector<String>> redirectPrivate = getAllOption("redirect-private",0,5);
- if (redirectPrivate != null)
- {
- checkRedirectParameters(np,redirectPrivate);
+ Vector<Vector<String>> redirectPrivate = getAllOption("redirect-private", 0, 5);
+ if (redirectPrivate != null) {
+ checkRedirectParameters(np, redirectPrivate);
}
- Vector<String> dev =getOption("dev",1,1);
- Vector<String> devtype =getOption("dev-type",1,1);
+ Vector<String> dev = getOption("dev", 1, 1);
+ Vector<String> devtype = getOption("dev-type", 1, 1);
if ((devtype != null && devtype.get(1).equals("tun")) ||
(dev != null && dev.get(1).startsWith("tun")) ||
@@ -437,15 +415,15 @@ public class ConfigParser {
//everything okay
} else {
throw new ConfigParseError("Sorry. Only tun mode is supported. See the FAQ for more detail");
- }
+ }
- Vector<String> mssfix = getOption("mssfix",0,1);
+ Vector<String> mssfix = getOption("mssfix", 0, 1);
- if (mssfix!=null) {
- if (mssfix.size()>=2) {
+ if (mssfix != null) {
+ if (mssfix.size() >= 2) {
try {
- np.mMssFix=Integer.parseInt(mssfix.get(1));
- } catch(NumberFormatException e) {
+ np.mMssFix = Integer.parseInt(mssfix.get(1));
+ } catch (NumberFormatException e) {
throw new ConfigParseError("Argument to --mssfix has to be an integer");
}
} else {
@@ -454,172 +432,171 @@ public class ConfigParser {
}
- Vector<String> mode =getOption("mode",1,1);
- if (mode != null){
- if(!mode.get(1).equals("p2p"))
- throw new ConfigParseError("Invalid mode for --mode specified, need p2p");
- }
-
-
-
- Vector<Vector<String>> dhcpoptions = getAllOption("dhcp-option", 2, 2);
- if(dhcpoptions!=null) {
- for(Vector<String> dhcpoption:dhcpoptions) {
- String type=dhcpoption.get(1);
- String arg = dhcpoption.get(2);
- if(type.equals("DOMAIN")) {
- np.mSearchDomain=dhcpoption.get(2);
- } else if(type.equals("DNS")) {
- np.mOverrideDNS=true;
- if(np.mDNS1.equals(VpnProfile.DEFAULT_DNS1))
- np.mDNS1=arg;
- else
- np.mDNS2=arg;
- }
- }
- }
-
- Vector<String> ifconfig = getOption("ifconfig", 2, 2);
- if(ifconfig!=null) {
- try {
- CIDRIP cidr = new CIDRIP(ifconfig.get(1), ifconfig.get(2));
- np.mIPv4Address=cidr.toString();
- } catch (NumberFormatException nfe) {
- throw new ConfigParseError("Could not pase ifconfig IP address: " + nfe.getLocalizedMessage());
- }
-
- }
-
- if(getOption("remote-random-hostname", 0, 0)!=null)
- np.mUseRandomHostname=true;
-
- if(getOption("float", 0, 0)!=null)
- np.mUseFloat=true;
-
- if(getOption("comp-lzo", 0, 1)!=null)
- np.mUseLzo=true;
-
- Vector<String> cipher = getOption("cipher", 1, 1);
- if(cipher!=null)
- np.mCipher= cipher.get(1);
-
- Vector<String> auth = getOption("auth", 1, 1);
- if(auth!=null)
- np.mAuth = auth.get(1);
-
-
- Vector<String> ca = getOption("ca",1,1);
- if(ca!=null){
- np.mCaFilename = ca.get(1);
- }
-
- Vector<String> cert = getOption("cert",1,1);
- if(cert!=null){
- np.mClientCertFilename = cert.get(1);
- np.mAuthenticationType = VpnProfile.TYPE_CERTIFICATES;
- noauthtypeset=false;
- }
- Vector<String> key= getOption("key",1,1);
- if(key!=null)
- np.mClientKeyFilename=key.get(1);
-
- Vector<String> pkcs12 = getOption("pkcs12",1,1);
- if(pkcs12!=null) {
- np.mPKCS12Filename = pkcs12.get(1);
- np.mAuthenticationType = VpnProfile.TYPE_KEYSTORE;
- noauthtypeset=false;
- }
-
- Vector<String> cryptoapicert = getOption("cryptoapicert",1,1);
- if(cryptoapicert!=null) {
+ Vector<String> mode = getOption("mode", 1, 1);
+ if (mode != null) {
+ if (!mode.get(1).equals("p2p"))
+ throw new ConfigParseError("Invalid mode for --mode specified, need p2p");
+ }
+
+
+ Vector<Vector<String>> dhcpoptions = getAllOption("dhcp-option", 2, 2);
+ if (dhcpoptions != null) {
+ for (Vector<String> dhcpoption : dhcpoptions) {
+ String type = dhcpoption.get(1);
+ String arg = dhcpoption.get(2);
+ if (type.equals("DOMAIN")) {
+ np.mSearchDomain = dhcpoption.get(2);
+ } else if (type.equals("DNS")) {
+ np.mOverrideDNS = true;
+ if (np.mDNS1.equals(VpnProfile.DEFAULT_DNS1))
+ np.mDNS1 = arg;
+ else
+ np.mDNS2 = arg;
+ }
+ }
+ }
+
+ Vector<String> ifconfig = getOption("ifconfig", 2, 2);
+ if (ifconfig != null) {
+ try {
+ CIDRIP cidr = new CIDRIP(ifconfig.get(1), ifconfig.get(2));
+ np.mIPv4Address = cidr.toString();
+ } catch (NumberFormatException nfe) {
+ throw new ConfigParseError("Could not pase ifconfig IP address: " + nfe.getLocalizedMessage());
+ }
+
+ }
+
+ if (getOption("remote-random-hostname", 0, 0) != null)
+ np.mUseRandomHostname = true;
+
+ if (getOption("float", 0, 0) != null)
+ np.mUseFloat = true;
+
+ if (getOption("comp-lzo", 0, 1) != null)
+ np.mUseLzo = true;
+
+ Vector<String> cipher = getOption("cipher", 1, 1);
+ if (cipher != null)
+ np.mCipher = cipher.get(1);
+
+ Vector<String> auth = getOption("auth", 1, 1);
+ if (auth != null)
+ np.mAuth = auth.get(1);
+
+
+ Vector<String> ca = getOption("ca", 1, 1);
+ if (ca != null) {
+ np.mCaFilename = ca.get(1);
+ }
+
+ Vector<String> cert = getOption("cert", 1, 1);
+ if (cert != null) {
+ np.mClientCertFilename = cert.get(1);
+ np.mAuthenticationType = VpnProfile.TYPE_CERTIFICATES;
+ noauthtypeset = false;
+ }
+ Vector<String> key = getOption("key", 1, 1);
+ if (key != null)
+ np.mClientKeyFilename = key.get(1);
+
+ Vector<String> pkcs12 = getOption("pkcs12", 1, 1);
+ if (pkcs12 != null) {
+ np.mPKCS12Filename = pkcs12.get(1);
np.mAuthenticationType = VpnProfile.TYPE_KEYSTORE;
- noauthtypeset=false;
+ noauthtypeset = false;
}
- Vector<String> compatnames = getOption("compat-names",1,2);
- Vector<String> nonameremapping = getOption("no-name-remapping",1,1);
- Vector<String> tlsremote = getOption("tls-remote",1,1);
- if(tlsremote!=null){
- np.mRemoteCN = tlsremote.get(1);
- np.mCheckRemoteCN=true;
- np.mX509AuthType = VpnProfile.X509_VERIFY_TLSREMOTE;
+ Vector<String> cryptoapicert = getOption("cryptoapicert", 1, 1);
+ if (cryptoapicert != null) {
+ np.mAuthenticationType = VpnProfile.TYPE_KEYSTORE;
+ noauthtypeset = false;
+ }
- if((compatnames!=null && compatnames.size() > 2) ||
- (nonameremapping!=null))
- np.mX509AuthType = VpnProfile.X509_VERIFY_TLSREMOTE_COMPAT_NOREMAPPING;
- }
+ Vector<String> compatnames = getOption("compat-names", 1, 2);
+ Vector<String> nonameremapping = getOption("no-name-remapping", 1, 1);
+ Vector<String> tlsremote = getOption("tls-remote", 1, 1);
+ if (tlsremote != null) {
+ np.mRemoteCN = tlsremote.get(1);
+ np.mCheckRemoteCN = true;
+ np.mX509AuthType = VpnProfile.X509_VERIFY_TLSREMOTE;
+
+ if ((compatnames != null && compatnames.size() > 2) ||
+ (nonameremapping != null))
+ np.mX509AuthType = VpnProfile.X509_VERIFY_TLSREMOTE_COMPAT_NOREMAPPING;
+ }
- Vector<String> verifyx509name = getOption("verify-x509-name",1,2);
- if(verifyx509name!=null){
- np.mRemoteCN = verifyx509name.get(1);
- np.mCheckRemoteCN=true;
- if(verifyx509name.size()>2) {
- if (verifyx509name.get(2).equals("name"))
- np.mX509AuthType=VpnProfile.X509_VERIFY_TLSREMOTE_RDN;
- else if (verifyx509name.get(2).equals("name-prefix"))
- np.mX509AuthType=VpnProfile.X509_VERIFY_TLSREMOTE_RDN_PREFIX;
- else
- throw new ConfigParseError("Unknown parameter to x509-verify-name: " + verifyx509name.get(2) );
- } else {
- np.mX509AuthType = VpnProfile.X509_VERIFY_TLSREMOTE_DN;
- }
+ Vector<String> verifyx509name = getOption("verify-x509-name", 1, 2);
+ if (verifyx509name != null) {
+ np.mRemoteCN = verifyx509name.get(1);
+ np.mCheckRemoteCN = true;
+ if (verifyx509name.size() > 2) {
+ if (verifyx509name.get(2).equals("name"))
+ np.mX509AuthType = VpnProfile.X509_VERIFY_TLSREMOTE_RDN;
+ else if (verifyx509name.get(2).equals("name-prefix"))
+ np.mX509AuthType = VpnProfile.X509_VERIFY_TLSREMOTE_RDN_PREFIX;
+ else
+ throw new ConfigParseError("Unknown parameter to x509-verify-name: " + verifyx509name.get(2));
+ } else {
+ np.mX509AuthType = VpnProfile.X509_VERIFY_TLSREMOTE_DN;
+ }
- }
+ }
- Vector<String> verb = getOption("verb",1,1);
- if(verb!=null){
- np.mVerb=verb.get(1);
- }
+ Vector<String> verb = getOption("verb", 1, 1);
+ if (verb != null) {
+ np.mVerb = verb.get(1);
+ }
- if(getOption("nobind", 0, 0) != null)
- np.mNobind=true;
+ if (getOption("nobind", 0, 0) != null)
+ np.mNobind = true;
- if(getOption("persist-tun", 0,0) != null)
- np.mPersistTun=true;
+ if (getOption("persist-tun", 0, 0) != null)
+ np.mPersistTun = true;
- Vector<String> connectretry = getOption("connect-retry", 1, 1);
- if(connectretry!=null)
- np.mConnectRetry =connectretry.get(1);
+ Vector<String> connectretry = getOption("connect-retry", 1, 1);
+ if (connectretry != null)
+ np.mConnectRetry = connectretry.get(1);
- Vector<String> connectretrymax = getOption("connect-retry-max", 1, 1);
- if(connectretrymax!=null)
- np.mConnectRetryMax =connectretrymax.get(1);
+ Vector<String> connectretrymax = getOption("connect-retry-max", 1, 1);
+ if (connectretrymax != null)
+ np.mConnectRetryMax = connectretrymax.get(1);
Vector<Vector<String>> remotetls = getAllOption("remote-cert-tls", 1, 1);
- if(remotetls!=null)
- if(remotetls.get(0).get(1).equals("server"))
- np.mExpectTLSCert=true;
- else
- options.put("remotetls",remotetls);
-
- Vector<String> authuser = getOption("auth-user-pass",0,1);
- if(authuser !=null){
- if(noauthtypeset) {
- np.mAuthenticationType=VpnProfile.TYPE_USERPASS;
- } else if(np.mAuthenticationType==VpnProfile.TYPE_CERTIFICATES) {
- np.mAuthenticationType=VpnProfile.TYPE_USERPASS_CERTIFICATES;
- } else if(np.mAuthenticationType==VpnProfile.TYPE_KEYSTORE) {
- np.mAuthenticationType=VpnProfile.TYPE_USERPASS_KEYSTORE;
- }
- if(authuser.size()>1) {
- // Set option value to password get to embed later.
- np.mUsername=null;
- useEmbbedUserAuth(np, authuser.get(1));
- }
- }
+ if (remotetls != null)
+ if (remotetls.get(0).get(1).equals("server"))
+ np.mExpectTLSCert = true;
+ else
+ options.put("remotetls", remotetls);
+
+ Vector<String> authuser = getOption("auth-user-pass", 0, 1);
+ if (authuser != null) {
+ if (noauthtypeset) {
+ np.mAuthenticationType = VpnProfile.TYPE_USERPASS;
+ } else if (np.mAuthenticationType == VpnProfile.TYPE_CERTIFICATES) {
+ np.mAuthenticationType = VpnProfile.TYPE_USERPASS_CERTIFICATES;
+ } else if (np.mAuthenticationType == VpnProfile.TYPE_KEYSTORE) {
+ np.mAuthenticationType = VpnProfile.TYPE_USERPASS_KEYSTORE;
+ }
+ if (authuser.size() > 1) {
+ // Set option value to password get to embed later.
+ np.mUsername = null;
+ useEmbbedUserAuth(np, authuser.get(1));
+ }
+ }
Pair<Connection, Connection[]> conns = parseConnectionOptions(null);
- np.mConnections =conns.second;
+ np.mConnections = conns.second;
Vector<Vector<String>> connectionBlocks = getAllOption("connection", 1, 1);
- if (np.mConnections.length > 0 && connectionBlocks !=null ) {
- throw new ConfigParseError("Using a <connection> block and --remote is not allowed.");
+ if (np.mConnections.length > 0 && connectionBlocks != null) {
+ throw new ConfigParseError("Using a <connection> block and --remote is not allowed.");
}
- if (connectionBlocks!=null) {
+ if (connectionBlocks != null) {
np.mConnections = new Connection[connectionBlocks.size()];
int connIndex = 0;
@@ -633,43 +610,43 @@ public class ConfigParser {
connIndex++;
}
}
- if(getOption("remote-random", 0, 0) != null)
- np.mRemoteRandom=true;
+ if (getOption("remote-random", 0, 0) != null)
+ np.mRemoteRandom = true;
Vector<String> protoforce = getOption("proto-force", 1, 1);
- if(protoforce!=null) {
+ if (protoforce != null) {
boolean disableUDP;
String protoToDisable = protoforce.get(1);
if (protoToDisable.equals("udp"))
- disableUDP=true;
+ disableUDP = true;
else if (protoToDisable.equals("tcp"))
- disableUDP=false;
+ disableUDP = false;
else
throw new ConfigParseError(String.format("Unknown protocol %s in proto-force", protoToDisable));
- for (Connection conn:np.mConnections)
- if(conn.mUseUdp==disableUDP)
- conn.mEnabled=false;
+ for (Connection conn : np.mConnections)
+ if (conn.mUseUdp == disableUDP)
+ conn.mEnabled = false;
}
// Parse OpenVPN Access Server extra
- Vector<String> friendlyname = meta.get("FRIENDLY_NAME");
- if(friendlyname !=null && friendlyname.size() > 1)
- np.mName=friendlyname.get(1);
+ Vector<String> friendlyname = meta.get("FRIENDLY_NAME");
+ if (friendlyname != null && friendlyname.size() > 1)
+ np.mName = friendlyname.get(1);
- Vector<String> ocusername = meta.get("USERNAME");
- if(ocusername !=null && ocusername.size() > 1)
- np.mUsername=ocusername.get(1);
+ Vector<String> ocusername = meta.get("USERNAME");
+ if (ocusername != null && ocusername.size() > 1)
+ np.mUsername = ocusername.get(1);
checkIgnoreAndInvalidOptions(np);
- fixup(np);
+ fixup(np);
- return np;
- }
+ return np;
+ }
private Pair<Connection, Connection[]> parseConnection(String connection, Connection defaultValues) throws IOException, ConfigParseError {
- // Parse a connection Block as a new configuration file
+ // Parse a connection Block as a new configuration file
ConfigParser connectionParser = new ConfigParser();
@@ -683,7 +660,7 @@ public class ConfigParser {
private Pair<Connection, Connection[]> parseConnectionOptions(Connection connDefault) throws ConfigParseError {
Connection conn;
- if (connDefault!=null)
+ if (connDefault != null)
try {
conn = connDefault.clone();
} catch (CloneNotSupportedException e) {
@@ -693,28 +670,28 @@ public class ConfigParser {
else
conn = new Connection();
- Vector<String> port = getOption("port", 1,1);
- if(port!=null){
+ Vector<String> port = getOption("port", 1, 1);
+ if (port != null) {
conn.mServerPort = port.get(1);
}
- Vector<String> rport = getOption("rport", 1,1);
- if(rport!=null){
+ Vector<String> rport = getOption("rport", 1, 1);
+ if (rport != null) {
conn.mServerPort = rport.get(1);
}
- Vector<String> proto = getOption("proto", 1,1);
- if(proto!=null){
- conn.mUseUdp=isUdpProto(proto.get(1));
+ Vector<String> proto = getOption("proto", 1, 1);
+ if (proto != null) {
+ conn.mUseUdp = isUdpProto(proto.get(1));
}
// Parse remote config
- Vector<Vector<String>> remotes = getAllOption("remote",1,3);
+ Vector<Vector<String>> remotes = getAllOption("remote", 1, 3);
// Assume that we need custom options if connectionDefault are set
- if(connDefault!=null) {
+ if (connDefault != null) {
for (Vector<Vector<String>> option : options.values()) {
conn.mCustomConfiguration += getOptionStrings(option);
@@ -724,14 +701,14 @@ public class ConfigParser {
conn.mUseCustomConfig = true;
}
// Make remotes empty to simplify code
- if (remotes==null)
+ if (remotes == null)
remotes = new Vector<Vector<String>>();
Connection[] connections = new Connection[remotes.size()];
- int i=0;
- for (Vector<String> remote: remotes) {
+ int i = 0;
+ for (Vector<String> remote : remotes) {
try {
connections[i] = conn.clone();
} catch (CloneNotSupportedException e) {
@@ -739,7 +716,7 @@ public class ConfigParser {
}
switch (remote.size()) {
case 4:
- connections[i].mUseUdp=isUdpProto(remote.get(3));
+ connections[i].mUseUdp = isUdpProto(remote.get(3));
case 3:
connections[i].mServerPort = remote.get(2);
case 2:
@@ -752,63 +729,60 @@ public class ConfigParser {
}
private void checkRedirectParameters(VpnProfile np, Vector<Vector<String>> defgw) {
- for (Vector<String> redirect: defgw)
- for (int i=1;i<redirect.size();i++){
+ for (Vector<String> redirect : defgw)
+ for (int i = 1; i < redirect.size(); i++) {
if (redirect.get(i).equals("block-local"))
- np.mAllowLocalLAN=false;
+ np.mAllowLocalLAN = false;
else if (redirect.get(i).equals("unblock-local"))
- np.mAllowLocalLAN=true;
+ np.mAllowLocalLAN = true;
}
}
- private boolean isUdpProto(String proto) throws ConfigParseError {
- boolean isudp;
- if(proto.equals("udp") || proto.equals("udp6"))
- isudp=true;
- else if (proto.equals("tcp-client") ||
- proto.equals("tcp") ||
- proto.equals("tcp6") ||
- proto.endsWith("tcp6-client"))
- isudp =false;
- else
- throw new ConfigParseError("Unsupported option to --proto " + proto);
- return isudp;
- }
-
- static public void useEmbbedUserAuth(VpnProfile np, String inlinedata)
- {
- String data = VpnProfile.getEmbeddedContent(inlinedata);
- String[] parts = data.split("\n");
- if(parts.length >= 2) {
- np.mUsername=parts[0];
- np.mPassword=parts[1];
- }
- }
-
- private void checkIgnoreAndInvalidOptions(VpnProfile np) throws ConfigParseError {
- for(String option:unsupportedOptions)
- if(options.containsKey(option))
- throw new ConfigParseError(String.format("Unsupported Option %s encountered in config file. Aborting",option));
+ private boolean isUdpProto(String proto) throws ConfigParseError {
+ boolean isudp;
+ if (proto.equals("udp") || proto.equals("udp6"))
+ isudp = true;
+ else if (proto.equals("tcp-client") ||
+ proto.equals("tcp") ||
+ proto.equals("tcp6") ||
+ proto.endsWith("tcp6-client"))
+ isudp = false;
+ else
+ throw new ConfigParseError("Unsupported option to --proto " + proto);
+ return isudp;
+ }
- for(String option:ignoreOptions)
- // removing an item which is not in the map is no error
- options.remove(option);
+ static public void useEmbbedUserAuth(VpnProfile np, String inlinedata) {
+ String data = VpnProfile.getEmbeddedContent(inlinedata);
+ String[] parts = data.split("\n");
+ if (parts.length >= 2) {
+ np.mUsername = parts[0];
+ np.mPassword = parts[1];
+ }
+ }
+ private void checkIgnoreAndInvalidOptions(VpnProfile np) throws ConfigParseError {
+ for (String option : unsupportedOptions)
+ if (options.containsKey(option))
+ throw new ConfigParseError(String.format("Unsupported Option %s encountered in config file. Aborting", option));
+ for (String option : ignoreOptions)
+ // removing an item which is not in the map is no error
+ options.remove(option);
- if(options.size()> 0) {
- np.mCustomConfigOptions += "# These Options were found in the config file do not map to config settings:\n";
+ if (options.size() > 0) {
+ np.mCustomConfigOptions += "# These Options were found in the config file do not map to config settings:\n";
- for(Vector<Vector<String>> option:options.values()) {
+ for (Vector<Vector<String>> option : options.values()) {
- np.mCustomConfigOptions += getOptionStrings(option);
+ np.mCustomConfigOptions += getOptionStrings(option);
- }
- np.mUseCustomConfig=true;
+ }
+ np.mUseCustomConfig = true;
- }
- }
+ }
+ }
boolean ignoreThisOption(Vector<String> option) {
@@ -843,35 +817,35 @@ public class ConfigParser {
private void fixup(VpnProfile np) {
- if(np.mRemoteCN.equals(np.mServerName)) {
- np.mRemoteCN="";
- }
- }
-
- private Vector<String> getOption(String option, int minarg, int maxarg) throws ConfigParseError {
- Vector<Vector<String>> alloptions = getAllOption(option, minarg, maxarg);
- if(alloptions==null)
- return null;
- else
- return alloptions.lastElement();
- }
-
-
- private Vector<Vector<String>> getAllOption(String option, int minarg, int maxarg) throws ConfigParseError {
- Vector<Vector<String>> args = options.get(option);
- if(args==null)
- return null;
-
- for(Vector<String> optionline:args)
-
- if(optionline.size()< (minarg+1) || optionline.size() > maxarg+1) {
- String err = String.format(Locale.getDefault(),"Option %s has %d parameters, expected between %d and %d",
- option,optionline.size()-1,minarg,maxarg );
- throw new ConfigParseError(err);
- }
- options.remove(option);
- return args;
- }
+ if (np.mRemoteCN.equals(np.mServerName)) {
+ np.mRemoteCN = "";
+ }
+ }
+
+ private Vector<String> getOption(String option, int minarg, int maxarg) throws ConfigParseError {
+ Vector<Vector<String>> alloptions = getAllOption(option, minarg, maxarg);
+ if (alloptions == null)
+ return null;
+ else
+ return alloptions.lastElement();
+ }
+
+
+ private Vector<Vector<String>> getAllOption(String option, int minarg, int maxarg) throws ConfigParseError {
+ Vector<Vector<String>> args = options.get(option);
+ if (args == null)
+ return null;
+
+ for (Vector<String> optionline : args)
+
+ if (optionline.size() < (minarg + 1) || optionline.size() > maxarg + 1) {
+ String err = String.format(Locale.getDefault(), "Option %s has %d parameters, expected between %d and %d",
+ option, optionline.size() - 1, minarg, maxarg);
+ throw new ConfigParseError(err);
+ }
+ options.remove(option);
+ return args;
+ }
}
diff --git a/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java b/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java
index 26354689..c86f9e44 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java
@@ -172,8 +172,16 @@ public class NetworkSpace {
}
public boolean containsNet(ipAddress network) {
- return getFirstAddress().compareTo(network.getFirstAddress()) != 1 &&
- getLastAddress().compareTo(network.getLastAddress()) != -1;
+ // this.first >= net.first && this.last <= net.last
+ BigInteger ourFirst = getFirstAddress();
+ BigInteger ourLast = getLastAddress();
+ BigInteger netFirst = network.getFirstAddress();
+ BigInteger netLast = network.getLastAddress();
+
+ boolean a = ourFirst.compareTo(netFirst) != 1;
+ boolean b = ourLast.compareTo(netLast) != -1;
+ return a && b;
+
}
}
@@ -320,6 +328,7 @@ public class NetworkSpace {
boolean skipIp=false;
// If there is any smaller net that is excluded we may not add the positive route back
+
for (ipAddress calculatedIp: ipsSorted) {
if(!calculatedIp.included && origIp.containsNet(calculatedIp)) {
skipIp=true;
diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
index 578d95e7..3c1ec064 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -49,14 +49,14 @@ import de.blinkt.openvpn.core.VpnStatus.StateListener;
import static de.blinkt.openvpn.core.NetworkSpace.ipAddress;
import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_CONNECTED;
-import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_NONETWORK;
-import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED;
import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET;
import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT;
+import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED;
+import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_NONETWORK;
+
import se.leap.bitmaskclient.Dashboard;
public class OpenVPNService extends VpnService implements StateListener, Callback, ByteCountListener {
-
public static final String START_SERVICE = "de.blinkt.openvpn.START_SERVICE";
public static final String START_SERVICE_STICKY = "de.blinkt.openvpn.START_SERVICE_STICKY";
public static final String ALWAYS_SHOW_NOTIFICATION = "de.blinkt.openvpn.NOTIFICATION_ALWAYS_VISIBLE";
@@ -126,7 +126,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
synchronized (mProcessLock) {
mProcessThread = null;
}
- mConnecttime = 0;
VpnStatus.removeByteCountListener(this);
unregisterDeviceStateReceiver();
ProfileManager.setConntectedVpnProfileDisconnected(this);
@@ -555,9 +554,15 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
Collection<ipAddress> positiveIPv4Routes = mRoutes.getPositiveIPList();
Collection<ipAddress> positiveIPv6Routes = mRoutesv6.getPositiveIPList();
+ ipAddress multicastRange = new ipAddress(new CIDRIP("224.0.0.0", 3), true);
+
for (NetworkSpace.ipAddress route : positiveIPv4Routes) {
try {
- builder.addRoute(route.getIPv4Address(), route.networkMask);
+
+ if (multicastRange.containsNet(route))
+ VpnStatus.logDebug(R.string.ignore_multicast_route, route.toString());
+ else
+ builder.addRoute(route.getIPv4Address(), route.networkMask);
} catch (IllegalArgumentException ia) {
VpnStatus.logError(getString(R.string.route_rejected) + route + " " + ia.getLocalizedMessage());
}
@@ -610,7 +615,10 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
try {
//Debug.stopMethodTracing();
- return builder.establish();
+ ParcelFileDescriptor tun = builder.establish();
+ if (tun==null)
+ throw new NullPointerException("Android establish() method returned null (Really broken network configuration?)");
+ return tun;
} catch (Exception e) {
VpnStatus.logError(R.string.tun_open_error);
VpnStatus.logError(getString(R.string.error) + e.getLocalizedMessage());
@@ -810,8 +818,11 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
/* Workaround for Lollipop, it does not route traffic to the VPNs own network mask */
- if (mLocalIP.len <= 31 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
- addRoute(mLocalIP);
+ if (mLocalIP.len <= 31 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ CIDRIP interfaceRoute = new CIDRIP(mLocalIP.mIp, mLocalIP.len);
+ interfaceRoute.normalise();
+ addRoute(interfaceRoute);
+ }
// Configurations are sometimes really broken...
@@ -868,7 +879,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
// Does not work :(
String msg = getString(resid);
String ticker = msg;
- showNotification(msg + " " + logmessage, ticker, lowpriority , 0, level);
+ showNotification(msg + " " + logmessage, ticker, lowpriority, 0, level);
+
}
}
diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java
index 298a6c40..d856feb7 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java
@@ -32,7 +32,8 @@ import de.blinkt.openvpn.core.VpnStatus.LogItem;
public class OpenVPNThread implements Runnable {
private static final String DUMP_PATH_STRING = "Dump path: ";
@SuppressLint("SdCardPath")
- private static final String BROKEN_PIE_SUPPORT = "/data/data/de.blinkt.openvpn/cache/pievpn[1]: syntax error:";
+ private static final String BROKEN_PIE_SUPPORT = "/data/data/de.blinkt.openvpn/cache/pievpn";
+ private final static String BROKEN_PIE_SUPPORT2 = "syntax error";
private static final String TAG = "OpenVPN";
public static final int M_FATAL = (1 << 4);
public static final int M_NONFATAL = (1 << 5);
@@ -148,7 +149,7 @@ public class OpenVPNThread implements Runnable {
if (logline.startsWith(DUMP_PATH_STRING))
mDumpPath = logline.substring(DUMP_PATH_STRING.length());
- if (logline.startsWith(BROKEN_PIE_SUPPORT))
+ if (logline.startsWith(BROKEN_PIE_SUPPORT) || logline.contains(BROKEN_PIE_SUPPORT2))
mBrokenPie = true;
diff --git a/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java b/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java
index 199caa63..92bf9ad3 100644
--- a/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java
+++ b/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java
@@ -7,8 +7,6 @@ package de.blinkt.openvpn.fragments;
import se.leap.bitmaskclient.R;
-import se.leap.bitmaskclient.R;
-
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;