public void addRoute(String dest, String mask, String gateway, String device) { CIDRIP route = new CIDRIP(dest, mask); boolean include = isAndroidTunDevice(device); NetworkSpace.ipAddress gatewayIP = new NetworkSpace.ipAddress(new CIDRIP(gateway, 32), false); if (mLocalIP == null) { VpnStatus.logError( "Local IP address unset but adding route?! This is broken! Please contact author with log"); return; } NetworkSpace.ipAddress localNet = new NetworkSpace.ipAddress(mLocalIP, true); if (localNet.containsNet(gatewayIP)) include = true; if (gateway != null && (gateway.equals("255.255.255.255") || gateway.equals(mRemoteGW))) include = true; if (route.len == 32 && !mask.equals("255.255.255.255")) { VpnStatus.logWarning(R.string.route_not_cidr, dest, mask); } if (route.normalise()) VpnStatus.logWarning(R.string.route_not_netip, dest, route.len, route.mIp); mRoutes.addIP(route, include); }
public ParcelFileDescriptor openTun() { // Debug.startMethodTracing(getExternalFilesDir(null).toString() + "/opentun.trace", 40* 1024 * // 1024); Builder builder = new Builder(); VpnStatus.logInfo(R.string.last_openvpn_tun_config); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mProfile.mAllowLocalLAN) { allowAllAFFamilies(builder); } if (mLocalIP == null && mLocalIPv6 == null) { VpnStatus.logError(getString(R.string.opentun_no_ipaddr)); return null; } if (mLocalIP != null) { addLocalNetworksToRoutes(); try { builder.addAddress(mLocalIP.mIp, mLocalIP.len); } catch (IllegalArgumentException iae) { VpnStatus.logError(R.string.dns_add_error, mLocalIP, iae.getLocalizedMessage()); return null; } } if (mLocalIPv6 != null) { String[] ipv6parts = mLocalIPv6.split("/"); try { builder.addAddress(ipv6parts[0], Integer.parseInt(ipv6parts[1])); } catch (IllegalArgumentException iae) { VpnStatus.logError(R.string.ip_add_error, mLocalIPv6, iae.getLocalizedMessage()); return null; } } for (String dns : mDnslist) { try { builder.addDnsServer(dns); } catch (IllegalArgumentException iae) { VpnStatus.logError(R.string.dns_add_error, dns, iae.getLocalizedMessage()); } } String release = Build.VERSION.RELEASE; if ((Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT && !release.startsWith("4.4.3") && !release.startsWith("4.4.4") && !release.startsWith("4.4.5") && !release.startsWith("4.4.6")) && mMtu < 1280) { VpnStatus.logInfo( String.format( Locale.US, "Forcing MTU to 1280 instead of %d to workaround Android Bug #70916", mMtu)); builder.setMtu(1280); } else { builder.setMtu(mMtu); } 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 { 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()); } } for (NetworkSpace.ipAddress route6 : positiveIPv6Routes) { try { builder.addRoute(route6.getIPv6Address(), route6.networkMask); } catch (IllegalArgumentException ia) { VpnStatus.logError( getString(R.string.route_rejected) + route6 + " " + ia.getLocalizedMessage()); } } if ("samsung".equals(Build.BRAND) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && 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); boolean dnsIncluded = false; for (ipAddress net : positiveIPv4Routes) { if (net.containsNet(dnsServer)) { dnsIncluded = true; } } if (!dnsIncluded) { String samsungwarning = String.format( "Warning Samsung Android 5.0+ devices ignore DNS servers outside the VPN range. To enable DNS add a custom route to your DNS Server (%s) or change to a DNS inside your VPN range", mDnslist.get(0)); VpnStatus.logWarning(samsungwarning); } } catch (Exception e) { VpnStatus.logError("Error parsing DNS Server IP: " + mDnslist.get(0)); } } if (mDomain != null) builder.addSearchDomain(mDomain); VpnStatus.logInfo(R.string.local_ip_info, mLocalIP.mIp, mLocalIP.len, mLocalIPv6, 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))); VpnStatus.logDebug( R.string.routes_debug, TextUtils.join(", ", positiveIPv4Routes), TextUtils.join(", ", positiveIPv6Routes)); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { setAllowedVpnPackages(builder); } 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); builder.setSession(session); // No DNS Server, log a warning if (mDnslist.size() == 0) VpnStatus.logInfo(R.string.warn_no_dns); mLastTunCfg = getTunConfigString(); // Reset information mDnslist.clear(); mRoutes.clear(); mRoutesv6.clear(); mLocalIP = null; mLocalIPv6 = null; mDomain = null; builder.setConfigureIntent(getLogPendingIntent()); try { // Debug.stopMethodTracing(); 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()); if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR1) { VpnStatus.logError(R.string.tun_error_helpful); } return null; } }