diff options
Diffstat (limited to 'main/src')
| -rw-r--r-- | main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java | 208 | 
1 files changed, 107 insertions, 101 deletions
| diff --git a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java index edc36e9a..5b59a907 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -87,17 +87,27 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac      private static final int PRIORITY_DEFAULT = 0;      private static final int PRIORITY_MAX = 2;      private static boolean mNotificationAlwaysVisible = false; -    private final Vector<String> mDnslist = new Vector<>(); -    private final NetworkSpace mRoutes = new NetworkSpace(); -    private final NetworkSpace mRoutesv6 = new NetworkSpace(); + +    static class TunConfig { +        private final Vector<String> mDnslist = new Vector<>(); +        private final NetworkSpace mRoutes = new NetworkSpace(); +        private final NetworkSpace mRoutesv6 = new NetworkSpace(); +        private String mDomain = null; +        private CIDRIP mLocalIP = null; +        private int mMtu; +        private String mLocalIPv6 = null; + +        private ProxyInfo mProxyInfo; +    }; + +    private TunConfig tunConfig = new TunConfig(); +      private final Object mProcessLock = new Object();      private String lastChannel;      private Thread mProcessThread = null;      private VpnProfile mProfile; -    private String mDomain = null; -    private CIDRIP mLocalIP = null; -    private int mMtu; -    private String mLocalIPv6 = null; + +      private DeviceStateReceiver mDeviceStateReceiver;      private boolean mDisplayBytecount = false;      private boolean mStarting = false; @@ -138,12 +148,11 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac      }; -    private String mLastTunCfg; +    private TunConfig mLastTunCfg;      private String mRemoteGW;      private Handler guiHandler;      private Toast mlastToast;      private Runnable mOpenVPNThread; -    private ProxyInfo mProxyInfo;      private HandlerThread mCommandHandlerThread;      private Handler mCommandHandler; @@ -747,27 +756,35 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac          VpnStatus.flushLog();      } -    private String getTunConfigString() { +    private static String getTunConfigString(TunConfig tc) {          // The format of the string is not important, only that          // two identical configurations produce the same result          String cfg = "TUNCFG UNQIUE STRING ips:"; -        if (mLocalIP != null) -            cfg += mLocalIP.toString(); -        if (mLocalIPv6 != null) -            cfg += mLocalIPv6; +        if (tc.mLocalIP != null) +            cfg += tc.mLocalIP.toString(); +        if (tc.mLocalIPv6 != null) +            cfg += tc.mLocalIPv6; -        cfg += "routes: " + TextUtils.join("|", mRoutes.getNetworks(true)) + TextUtils.join("|", mRoutesv6.getNetworks(true)); -        cfg += "excl. routes:" + TextUtils.join("|", mRoutes.getNetworks(false)) + TextUtils.join("|", mRoutesv6.getNetworks(false)); -        cfg += "dns: " + TextUtils.join("|", mDnslist); -        cfg += "domain: " + mDomain; -        cfg += "mtu: " + mMtu; -        cfg += "proxyInfo: " + mProxyInfo; +        cfg += "routes: " + TextUtils.join("|", tc.mRoutes.getNetworks(true)) + TextUtils.join("|", tc.mRoutesv6.getNetworks(true)); +        cfg += "excl. routes:" + TextUtils.join("|", tc.mRoutes.getNetworks(false)) + TextUtils.join("|", tc.mRoutesv6.getNetworks(false)); +        cfg += "dns: " + TextUtils.join("|", tc.mDnslist); +        cfg += "domain: " + tc.mDomain; +        cfg += "mtu: " + tc.mMtu; +        cfg += "proxyInfo: " + tc.mProxyInfo;          return cfg;      }      public ParcelFileDescriptor openTun() { +        ParcelFileDescriptor pfd = openTun(tunConfig); + +        // Reset information +        mLastTunCfg = tunConfig; +        tunConfig = new TunConfig(); +        return pfd; +    } +    private ParcelFileDescriptor openTun(TunConfig tc) {          //Debug.startMethodTracing(getExternalFilesDir(null).toString() + "/opentun.trace", 40* 1024 * 1024); @@ -786,36 +803,36 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac              allowAllAFFamilies(builder);          } -        if (mLocalIP == null && mLocalIPv6 == null) { +        if (tc.mLocalIP == null && tc.mLocalIPv6 == null) {              VpnStatus.logError(getString(R.string.opentun_no_ipaddr));              return null;          } -        if (mLocalIP != null) { +        if (tc.mLocalIP != null) {              // OpenVPN3 manages excluded local networks by callback              if (!VpnProfile.doUseOpenVPN3(this)) -                addLocalNetworksToRoutes(); +                addLocalNetworksToRoutes(tc);              try { -                builder.addAddress(mLocalIP.mIp, mLocalIP.len); +                builder.addAddress(tc.mLocalIP.mIp, tc.mLocalIP.len);              } catch (IllegalArgumentException iae) { -                VpnStatus.logError(R.string.dns_add_error, mLocalIP, iae.getLocalizedMessage()); +                VpnStatus.logError(R.string.dns_add_error, tc.mLocalIP, iae.getLocalizedMessage());                  return null;              }          } -        if (mLocalIPv6 != null) { -            String[] ipv6parts = mLocalIPv6.split("/"); +        if (tc.mLocalIPv6 != null) { +            String[] ipv6parts = tc.mLocalIPv6.split("/");              try {                  builder.addAddress(ipv6parts[0], Integer.parseInt(ipv6parts[1]));              } catch (IllegalArgumentException iae) { -                VpnStatus.logError(R.string.ip_add_error, mLocalIPv6, iae.getLocalizedMessage()); +                VpnStatus.logError(R.string.ip_add_error, tc.mLocalIPv6, iae.getLocalizedMessage());                  return null;              }          } -        for (String dns : mDnslist) { +        for (String dns : tc.mDnslist) {              try {                  builder.addDnsServer(dns);              } catch (IllegalArgumentException iae) { @@ -824,15 +841,15 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac          }          String release = Build.VERSION.RELEASE; -        builder.setMtu(mMtu); +        builder.setMtu(tc.mMtu); -        Collection<IpAddress> positiveIPv4Routes = mRoutes.getPositiveIPList(); -        Collection<IpAddress> positiveIPv6Routes = mRoutesv6.getPositiveIPList(); +        Collection<IpAddress> positiveIPv4Routes = tc.mRoutes.getPositiveIPList(); +        Collection<IpAddress> positiveIPv6Routes = tc.mRoutesv6.getPositiveIPList(); -        if ("samsung".equals(Build.BRAND) && mDnslist.size() >= 1) { +        if ("samsung".equals(Build.BRAND) && tc.mDnslist.size() >= 1) {              // Check if the first DNS Server is in the VPN range              try { -                IpAddress dnsServer = new IpAddress(new CIDRIP(mDnslist.get(0), 32), true); +                IpAddress dnsServer = new IpAddress(new CIDRIP(tc.mDnslist.get(0), 32), true);                  boolean dnsIncluded = false;                  for (IpAddress net : positiveIPv4Routes) {                      if (net.containsNet(dnsServer)) { @@ -840,28 +857,28 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac                      }                  }                  if (!dnsIncluded) { -                    String samsungwarning = String.format("Warning Samsung Android 5.0+ devices ignore DNS servers outside the VPN range. To enable DNS resolution a route to your DNS Server (%s) has been added.", mDnslist.get(0)); +                    String samsungwarning = String.format("Warning Samsung Android 5.0+ devices ignore DNS servers outside the VPN range. To enable DNS resolution a route to your DNS Server (%s) has been added.", tc.mDnslist.get(0));                      VpnStatus.logWarning(samsungwarning);                      positiveIPv4Routes.add(dnsServer);                  }              } catch (Exception e) {                  // If it looks like IPv6 ignore error -                if (!mDnslist.get(0).contains(":")) -                    VpnStatus.logError("Error parsing DNS Server IP: " + mDnslist.get(0)); +                if (!tc.mDnslist.get(0).contains(":")) +                    VpnStatus.logError("Error parsing DNS Server IP: " + tc.mDnslist.get(0));              }          }          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { -            installRoutesExcluded(builder, mRoutes); -            installRoutesExcluded(builder, mRoutesv6); +            installRoutesExcluded(builder, tc.mRoutes); +            installRoutesExcluded(builder, tc.mRoutesv6);          } else {              installRoutesPostiveOnly(builder, positiveIPv4Routes, positiveIPv6Routes);          } -        if (mDomain != null) -            builder.addSearchDomain(mDomain); +        if (tc.mDomain != null) +            builder.addSearchDomain(tc.mDomain);          String ipv4info;          String ipv6info; @@ -874,27 +891,27 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac          }          int ipv4len; -        if (mLocalIP != null) { -            ipv4len = mLocalIP.len; -            ipv4info = mLocalIP.mIp; +        if (tc.mLocalIP != null) { +            ipv4len = tc.mLocalIP.len; +            ipv4info = tc.mLocalIP.mIp;          } else {              ipv4len = -1;          } -        if (mLocalIPv6 != null) { -            ipv6info = mLocalIPv6; +        if (tc.mLocalIPv6 != null) { +            ipv6info = tc.mLocalIPv6;          } -        if ((!mRoutes.getNetworks(false).isEmpty() || !mRoutesv6.getNetworks(false).isEmpty()) && isLockdownEnabledCompat()) { +        if ((!tc.mRoutes.getNetworks(false).isEmpty() || !tc.mRoutesv6.getNetworks(false).isEmpty()) && isLockdownEnabledCompat()) {              VpnStatus.logInfo("VPN lockdown enabled (do not allow apps to bypass VPN) enabled. Route exclusion will not allow apps to bypass VPN (e.g. bypass VPN for local networks)");          } -        VpnStatus.logInfo(R.string.local_ip_info, ipv4info, ipv4len, ipv6info, mMtu); -        VpnStatus.logInfo(R.string.dns_server_info, TextUtils.join(", ", mDnslist), mDomain); -        VpnStatus.logInfo(R.string.routes_info_incl, TextUtils.join(", ", mRoutes.getNetworks(true)), TextUtils.join(", ", mRoutesv6.getNetworks(true))); -        VpnStatus.logInfo(R.string.routes_info_excl, TextUtils.join(", ", mRoutes.getNetworks(false)), TextUtils.join(", ", mRoutesv6.getNetworks(false))); -        if (mProxyInfo != null) { -            VpnStatus.logInfo(R.string.proxy_info, mProxyInfo.getHost(), mProxyInfo.getPort()); +        VpnStatus.logInfo(R.string.local_ip_info, ipv4info, ipv4len, ipv6info, tc.mMtu); +        VpnStatus.logInfo(R.string.dns_server_info, TextUtils.join(", ", tc.mDnslist), tc.mDomain); +        VpnStatus.logInfo(R.string.routes_info_incl, TextUtils.join(", ", tc.mRoutes.getNetworks(true)), TextUtils.join(", ", tc.mRoutesv6.getNetworks(true))); +        VpnStatus.logInfo(R.string.routes_info_excl, TextUtils.join(", ", tc.mRoutes.getNetworks(false)), TextUtils.join(", ", tc.mRoutesv6.getNetworks(false))); +        if (tc.mProxyInfo != null) { +            VpnStatus.logInfo(R.string.proxy_info, tc.mProxyInfo.getHost(), tc.mProxyInfo.getPort());          }          if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {              /* On Tiramisu we install the routes exactly like promised */ @@ -915,31 +932,20 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac          }          String session = mProfile.mName; -        if (mLocalIP != null && mLocalIPv6 != null) -            session = getString(R.string.session_ipv6string, session, mLocalIP, mLocalIPv6); -        else if (mLocalIP != null) -            session = getString(R.string.session_ipv4string, session, mLocalIP); +        if (tc.mLocalIP != null && tc.mLocalIPv6 != null) +            session = getString(R.string.session_ipv6string, session, tc.mLocalIP, tc.mLocalIPv6); +        else if (tc.mLocalIP != null) +            session = getString(R.string.session_ipv4string, session, tc.mLocalIP);          else -            session = getString(R.string.session_ipv4string, session, mLocalIPv6); +            session = getString(R.string.session_ipv4string, session, tc.mLocalIPv6);          builder.setSession(session);          // No DNS Server, log a warning -        if (mDnslist.size() == 0) +        if (tc.mDnslist.size() == 0)              VpnStatus.logInfo(R.string.warn_no_dns); -        setHttpProxy(builder); - -        mLastTunCfg = getTunConfigString(); - -        // Reset information -        mDnslist.clear(); -        mRoutes.clear(); -        mRoutesv6.clear(); -        mLocalIP = null; -        mLocalIPv6 = null; -        mDomain = null; -        mProxyInfo = null; +        setHttpProxy(builder, tc);          builder.setConfigureIntent(getGraphPendingIntent()); @@ -1000,10 +1006,10 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac          }      } -    private void setHttpProxy(Builder builder) { -        if (mProxyInfo != null && Build.VERSION.SDK_INT >= 29) { -            builder.setHttpProxy(mProxyInfo); -        } else if (mProxyInfo != null) { +    private void setHttpProxy(Builder builder, TunConfig tc) { +        if (tc.mProxyInfo != null && Build.VERSION.SDK_INT >= 29) { +            builder.setHttpProxy(tc.mProxyInfo); +        } else if (tc.mProxyInfo != null) {              VpnStatus.logWarning("HTTP Proxy needs Android 10 or later.");          }      } @@ -1023,16 +1029,16 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac          builder.allowFamily(OsConstants.AF_INET6);      } -    private void addLocalNetworksToRoutes() { +    private void addLocalNetworksToRoutes(TunConfig tc) {          for (String net : NetworkUtils.getLocalNetworks(this, false)) {              String[] netparts = net.split("/");              String ipAddr = netparts[0];              int netMask = Integer.parseInt(netparts[1]); -            if (ipAddr.equals(mLocalIP.mIp)) +            if (ipAddr.equals(tc.mLocalIP.mIp))                  continue;              if(mProfile.mAllowLocalLAN) -                mRoutes.addIP(new CIDRIP(ipAddr, netMask), false); +                tc.mRoutes.addIP(new CIDRIP(ipAddr, netMask), false);          }          if (mProfile.mAllowLocalLAN) { @@ -1103,12 +1109,12 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac      }      public void addDNS(String dns) { -        mDnslist.add(dns); +        tunConfig.mDnslist.add(dns);      }      public void setDomain(String domain) { -        if (mDomain == null) { -            mDomain = domain; +        if (tunConfig.mDomain == null) { +            tunConfig.mDomain = domain;          }      } @@ -1116,12 +1122,12 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac       * Route that is always included, used by the v3 core       */      public void addRoute(CIDRIP route, boolean include) { -        mRoutes.addIP(route, include); +        tunConfig.mRoutes.addIP(route, include);      }      public boolean addHttpProxy(String proxy, int port) {          try { -            mProxyInfo = ProxyInfo.buildDirectProxy(proxy, port); +            tunConfig.mProxyInfo = ProxyInfo.buildDirectProxy(proxy, port);          } catch (Exception e) {              VpnStatus.logError("Could not set proxy" + e.getLocalizedMessage());              return false; @@ -1135,11 +1141,11 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac          IpAddress gatewayIP = new IpAddress(new CIDRIP(gateway, 32), false); -        if (mLocalIP == null) { +        if (tunConfig.mLocalIP == null) {              VpnStatus.logError("Local IP address unset and received. Neither pushed server config nor local config specifies an IP addresses. Opening tun device is most likely going to fail.");              return;          } -        IpAddress localNet = new IpAddress(mLocalIP, true); +        IpAddress localNet = new IpAddress(tunConfig.mLocalIP, true);          if (localNet.containsNet(gatewayIP))              include = true; @@ -1155,7 +1161,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac          if (route.normalise())              VpnStatus.logWarning(R.string.route_not_netip, dest, route.len, route.mIp); -        mRoutes.addIP(route, include); +        tunConfig.mRoutes.addIP(route, include);      }      public void addRoutev6(String network, String device) { @@ -1170,7 +1176,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac          try {              Inet6Address ip = (Inet6Address) InetAddress.getAllByName(v6parts[0])[0];              int mask = Integer.parseInt(v6parts[1]); -            mRoutesv6.addIPv6(ip, mask, included); +            tunConfig.mRoutesv6.addIPv6(ip, mask, included);          } catch (UnknownHostException e) {              VpnStatus.logException(e); @@ -1185,21 +1191,21 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac      }      public void setMtu(int mtu) { -        mMtu = mtu; +        tunConfig.mMtu = mtu;      }      public void setLocalIP(CIDRIP cdrip) { -        mLocalIP = cdrip; +        tunConfig.mLocalIP = cdrip;      }      public void setLocalIP(String local, String netmask, int mtu, String mode) { -        mLocalIP = new CIDRIP(local, netmask); -        mMtu = mtu; +        tunConfig.mLocalIP = new CIDRIP(local, netmask); +        tunConfig.mMtu = mtu;          mRemoteGW = null;          long netMaskAsInt = CIDRIP.getInt(netmask); -        if (mLocalIP.len == 32 && !netmask.equals("255.255.255.255")) { +        if (tunConfig.mLocalIP.len == 32 && !netmask.equals("255.255.255.255")) {              // get the netmask as IP              int masklen; @@ -1213,22 +1219,22 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac              }              // Netmask is Ip address +/-1, assume net30/p2p with small net -            if ((netMaskAsInt & mask) == (mLocalIP.getInt() & mask)) { -                mLocalIP.len = masklen; +            if ((netMaskAsInt & mask) == (tunConfig.mLocalIP.getInt() & mask)) { +                tunConfig.mLocalIP.len = masklen;              } else { -                mLocalIP.len = 32; +                tunConfig.mLocalIP.len = 32;                  if (!"p2p".equals(mode))                      VpnStatus.logWarning(R.string.ip_not_cidr, local, netmask, mode);              }          } -        if (("p2p".equals(mode) && mLocalIP.len < 32) || ("net30".equals(mode) && mLocalIP.len < 30)) { +        if (("p2p".equals(mode) && tunConfig.mLocalIP.len < 32) || ("net30".equals(mode) && tunConfig.mLocalIP.len < 30)) {              VpnStatus.logWarning(R.string.ip_looks_like_subnet, local, netmask, mode);          }          /* Workaround for Lollipop and higher, it does not route traffic to the VPNs own network mask */ -        if (mLocalIP.len <= 31) { -            CIDRIP interfaceRoute = new CIDRIP(mLocalIP.mIp, mLocalIP.len); +        if (tunConfig.mLocalIP.len <= 31) { +            CIDRIP interfaceRoute = new CIDRIP(tunConfig.mLocalIP.mIp, tunConfig.mLocalIP.len);              interfaceRoute.normalise();              addRoute(interfaceRoute, true);          } @@ -1239,7 +1245,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac      }      public void setLocalIPv6(String ipv6addr) { -        mLocalIPv6 = ipv6addr; +        tunConfig.mLocalIPv6 = ipv6addr;      }      @Override @@ -1317,8 +1323,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac      }      public String getTunReopenStatus() { -        String currentConfiguration = getTunConfigString(); -        if (currentConfiguration.equals(mLastTunCfg)) { +        String currentConfiguration = getTunConfigString(mLastTunCfg); +        if (currentConfiguration.equals(getTunConfigString(mLastTunCfg))) {              return "NOACTION";          } else {              return "OPEN_BEFORE_CLOSE"; | 
