Loading core/java/android/net/ConnectivityManager.java +16 −0 Original line number Diff line number Diff line Loading @@ -479,6 +479,22 @@ public class ConnectivityManager { } } /** * Checks if the given network type should be exempt from VPN routing rules * * @hide */ public static boolean isNetworkTypeExempt(int networkType) { switch (networkType) { case TYPE_MOBILE_MMS: case TYPE_MOBILE_SUPL: case TYPE_MOBILE_HIPRI: return true; default: return false; } } /** * Specifies the preferred network type. When the device has more * than one type available the preferred network type will be used. Loading core/java/android/os/INetworkManagementService.aidl +12 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.os; import android.net.InterfaceConfiguration; import android.net.INetworkManagementEventObserver; import android.net.LinkAddress; import android.net.NetworkStats; import android.net.RouteInfo; import android.net.wifi.WifiConfiguration; Loading Loading @@ -387,6 +388,17 @@ interface INetworkManagementService */ void clearMarkedForwardingRoute(String iface, in RouteInfo route); /** * Exempts {@code host} from the routing set up by {@link setMarkedForwardingRoute} * All connects to {@code host} will use the global routing table */ void setHostExemption(in LinkAddress host); /** * Clears an exemption set by {@link setHostExemption} */ void clearHostExemption(in LinkAddress host); /** * Set a process (pid) to use the name servers associated with the specified interface. */ Loading services/java/com/android/server/ConnectivityService.java +70 −37 Original line number Diff line number Diff line Loading @@ -252,6 +252,9 @@ public class ConnectivityService extends IConnectivityManager.Stub { private static final boolean TO_DEFAULT_TABLE = true; private static final boolean TO_SECONDARY_TABLE = false; private static final boolean EXEMPT = true; private static final boolean UNEXEMPT = false; /** * used internally as a delayed event to make us switch back to the * default network Loading Loading @@ -349,10 +352,19 @@ public class ConnectivityService extends IConnectivityManager.Stub { private InetAddress mDefaultDns; // Lock for protecting access to mAddedRoutes and mExemptAddresses private final Object mRoutesLock = new Object(); // this collection is used to refcount the added routes - if there are none left // it's time to remove the route from the route table @GuardedBy("mRoutesLock") private Collection<RouteInfo> mAddedRoutes = new ArrayList<RouteInfo>(); // this collection corresponds to the entries of mAddedRoutes that have routing exemptions // used to handle cleanup of exempt rules @GuardedBy("mRoutesLock") private Collection<LinkAddress> mExemptAddresses = new ArrayList<LinkAddress>(); // used in DBG mode to track inet condition reports private static final int INET_CONDITION_LOG_MAX_SIZE = 15; private ArrayList mInetLog; Loading Loading @@ -1470,7 +1482,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { try { InetAddress addr = InetAddress.getByAddress(hostAddress); LinkProperties lp = tracker.getLinkProperties(); boolean ok = addRouteToAddress(lp, addr); boolean ok = addRouteToAddress(lp, addr, EXEMPT); if (DBG) log("requestRouteToHostAddress ok=" + ok); return ok; } catch (UnknownHostException e) { Loading @@ -1482,24 +1494,25 @@ public class ConnectivityService extends IConnectivityManager.Stub { return false; } private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) { return modifyRoute(p, r, 0, ADD, toDefaultTable); private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable, boolean exempt) { return modifyRoute(p, r, 0, ADD, toDefaultTable, exempt); } private boolean removeRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) { return modifyRoute(p, r, 0, REMOVE, toDefaultTable); return modifyRoute(p, r, 0, REMOVE, toDefaultTable, UNEXEMPT); } private boolean addRouteToAddress(LinkProperties lp, InetAddress addr) { return modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE); private boolean addRouteToAddress(LinkProperties lp, InetAddress addr, boolean exempt) { return modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE, exempt); } private boolean removeRouteToAddress(LinkProperties lp, InetAddress addr) { return modifyRouteToAddress(lp, addr, REMOVE, TO_DEFAULT_TABLE); return modifyRouteToAddress(lp, addr, REMOVE, TO_DEFAULT_TABLE, UNEXEMPT); } private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd, boolean toDefaultTable) { boolean toDefaultTable, boolean exempt) { RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getAllRoutes(), addr); if (bestRoute == null) { bestRoute = RouteInfo.makeHostRoute(addr, lp.getInterfaceName()); Loading @@ -1514,11 +1527,11 @@ public class ConnectivityService extends IConnectivityManager.Stub { bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway(), iface); } } return modifyRoute(lp, bestRoute, 0, doAdd, toDefaultTable); return modifyRoute(lp, bestRoute, 0, doAdd, toDefaultTable, exempt); } private boolean modifyRoute(LinkProperties lp, RouteInfo r, int cycleCount, boolean doAdd, boolean toDefaultTable) { boolean toDefaultTable, boolean exempt) { if ((lp == null) || (r == null)) { if (DBG) log("modifyRoute got unexpected null: " + lp + ", " + r); return false; Loading Loading @@ -1547,15 +1560,25 @@ public class ConnectivityService extends IConnectivityManager.Stub { bestRoute.getGateway(), ifaceName); } modifyRoute(lp, bestRoute, cycleCount+1, doAdd, toDefaultTable); modifyRoute(lp, bestRoute, cycleCount+1, doAdd, toDefaultTable, exempt); } } if (doAdd) { if (VDBG) log("Adding " + r + " for interface " + ifaceName); try { if (toDefaultTable) { mAddedRoutes.add(r); // only track default table - only one apps can effect synchronized (mRoutesLock) { // only track default table - only one apps can effect mAddedRoutes.add(r); mNetd.addRoute(ifaceName, r); if (exempt) { LinkAddress dest = r.getDestination(); if (!mExemptAddresses.contains(dest)) { mNetd.setHostExemption(dest); mExemptAddresses.add(dest); } } } } else { mNetd.addSecondaryRoute(ifaceName, r); } Loading @@ -1568,11 +1591,17 @@ public class ConnectivityService extends IConnectivityManager.Stub { // if we remove this one and there are no more like it, then refcount==0 and // we can remove it from the table if (toDefaultTable) { synchronized (mRoutesLock) { mAddedRoutes.remove(r); if (mAddedRoutes.contains(r) == false) { if (VDBG) log("Removing " + r + " for interface " + ifaceName); try { mNetd.removeRoute(ifaceName, r); LinkAddress dest = r.getDestination(); if (mExemptAddresses.contains(dest)) { mNetd.clearHostExemption(dest); mExemptAddresses.remove(dest); } } catch (Exception e) { // never crash - catch them all if (VDBG) loge("Exception trying to remove a route: " + e); Loading @@ -1581,6 +1610,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { } else { if (VDBG) log("not removing " + r + " as it's still in use"); } } } else { if (VDBG) log("Removing " + r + " for interface " + ifaceName); try { Loading Loading @@ -2260,6 +2290,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { */ private void handleConnectivityChange(int netType, boolean doReset) { int resetMask = doReset ? NetworkUtils.RESET_ALL_ADDRESSES : 0; boolean exempt = ConnectivityManager.isNetworkTypeExempt(netType); /* * If a non-default network is enabled, add the host routes that Loading Loading @@ -2324,7 +2355,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { } } mCurrentLinkProperties[netType] = newLp; boolean resetDns = updateRoutes(newLp, curLp, mNetConfigs[netType].isDefault()); boolean resetDns = updateRoutes(newLp, curLp, mNetConfigs[netType].isDefault(), exempt); if (resetMask != 0 || resetDns) { if (curLp != null) { Loading Loading @@ -2400,7 +2431,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { * returns a boolean indicating the routes changed */ private boolean updateRoutes(LinkProperties newLp, LinkProperties curLp, boolean isLinkDefault) { boolean isLinkDefault, boolean exempt) { Collection<RouteInfo> routesToAdd = null; CompareResult<InetAddress> dnsDiff = new CompareResult<InetAddress>(); CompareResult<RouteInfo> routeDiff = new CompareResult<RouteInfo>(); Loading Loading @@ -2436,7 +2467,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { } if (newLp != null) { for (InetAddress newDns : newLp.getDnses()) { addRouteToAddress(newLp, newDns); addRouteToAddress(newLp, newDns, exempt); } } } else { Loading @@ -2445,22 +2476,23 @@ public class ConnectivityService extends IConnectivityManager.Stub { removeRouteToAddress(curLp, oldDns); } for (InetAddress newDns : dnsDiff.added) { addRouteToAddress(newLp, newDns); addRouteToAddress(newLp, newDns, exempt); } } } for (RouteInfo r : routeDiff.added) { if (isLinkDefault || ! r.isDefaultRoute()) { addRoute(newLp, r, TO_DEFAULT_TABLE); addRoute(newLp, r, TO_DEFAULT_TABLE, exempt); } else { // add to a secondary route table addRoute(newLp, r, TO_SECONDARY_TABLE); addRoute(newLp, r, TO_SECONDARY_TABLE, UNEXEMPT); // many radios add a default route even when we don't want one. // remove the default route unless somebody else has asked for it String ifaceName = newLp.getInterfaceName(); if (TextUtils.isEmpty(ifaceName) == false && mAddedRoutes.contains(r) == false) { synchronized (mRoutesLock) { if (!TextUtils.isEmpty(ifaceName) && !mAddedRoutes.contains(r)) { if (VDBG) log("Removing " + r + " for interface " + ifaceName); try { mNetd.removeRoute(ifaceName, r); Loading @@ -2471,6 +2503,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { } } } } return routesChanged; } Loading services/java/com/android/server/NetworkManagementService.java +20 −0 Original line number Diff line number Diff line Loading @@ -1472,6 +1472,26 @@ public class NetworkManagementService extends INetworkManagementService.Stub } } @Override public void setHostExemption(LinkAddress host) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); try { mConnector.execute("interface", "fwmark", "exempt", "add", host); } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); } } @Override public void clearHostExemption(LinkAddress host) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); try { mConnector.execute("interface", "fwmark", "exempt", "remove", host); } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); } } @Override public void setDnsInterfaceForUidRange(String iface, int uid_start, int uid_end) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); Loading Loading
core/java/android/net/ConnectivityManager.java +16 −0 Original line number Diff line number Diff line Loading @@ -479,6 +479,22 @@ public class ConnectivityManager { } } /** * Checks if the given network type should be exempt from VPN routing rules * * @hide */ public static boolean isNetworkTypeExempt(int networkType) { switch (networkType) { case TYPE_MOBILE_MMS: case TYPE_MOBILE_SUPL: case TYPE_MOBILE_HIPRI: return true; default: return false; } } /** * Specifies the preferred network type. When the device has more * than one type available the preferred network type will be used. Loading
core/java/android/os/INetworkManagementService.aidl +12 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.os; import android.net.InterfaceConfiguration; import android.net.INetworkManagementEventObserver; import android.net.LinkAddress; import android.net.NetworkStats; import android.net.RouteInfo; import android.net.wifi.WifiConfiguration; Loading Loading @@ -387,6 +388,17 @@ interface INetworkManagementService */ void clearMarkedForwardingRoute(String iface, in RouteInfo route); /** * Exempts {@code host} from the routing set up by {@link setMarkedForwardingRoute} * All connects to {@code host} will use the global routing table */ void setHostExemption(in LinkAddress host); /** * Clears an exemption set by {@link setHostExemption} */ void clearHostExemption(in LinkAddress host); /** * Set a process (pid) to use the name servers associated with the specified interface. */ Loading
services/java/com/android/server/ConnectivityService.java +70 −37 Original line number Diff line number Diff line Loading @@ -252,6 +252,9 @@ public class ConnectivityService extends IConnectivityManager.Stub { private static final boolean TO_DEFAULT_TABLE = true; private static final boolean TO_SECONDARY_TABLE = false; private static final boolean EXEMPT = true; private static final boolean UNEXEMPT = false; /** * used internally as a delayed event to make us switch back to the * default network Loading Loading @@ -349,10 +352,19 @@ public class ConnectivityService extends IConnectivityManager.Stub { private InetAddress mDefaultDns; // Lock for protecting access to mAddedRoutes and mExemptAddresses private final Object mRoutesLock = new Object(); // this collection is used to refcount the added routes - if there are none left // it's time to remove the route from the route table @GuardedBy("mRoutesLock") private Collection<RouteInfo> mAddedRoutes = new ArrayList<RouteInfo>(); // this collection corresponds to the entries of mAddedRoutes that have routing exemptions // used to handle cleanup of exempt rules @GuardedBy("mRoutesLock") private Collection<LinkAddress> mExemptAddresses = new ArrayList<LinkAddress>(); // used in DBG mode to track inet condition reports private static final int INET_CONDITION_LOG_MAX_SIZE = 15; private ArrayList mInetLog; Loading Loading @@ -1470,7 +1482,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { try { InetAddress addr = InetAddress.getByAddress(hostAddress); LinkProperties lp = tracker.getLinkProperties(); boolean ok = addRouteToAddress(lp, addr); boolean ok = addRouteToAddress(lp, addr, EXEMPT); if (DBG) log("requestRouteToHostAddress ok=" + ok); return ok; } catch (UnknownHostException e) { Loading @@ -1482,24 +1494,25 @@ public class ConnectivityService extends IConnectivityManager.Stub { return false; } private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) { return modifyRoute(p, r, 0, ADD, toDefaultTable); private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable, boolean exempt) { return modifyRoute(p, r, 0, ADD, toDefaultTable, exempt); } private boolean removeRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) { return modifyRoute(p, r, 0, REMOVE, toDefaultTable); return modifyRoute(p, r, 0, REMOVE, toDefaultTable, UNEXEMPT); } private boolean addRouteToAddress(LinkProperties lp, InetAddress addr) { return modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE); private boolean addRouteToAddress(LinkProperties lp, InetAddress addr, boolean exempt) { return modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE, exempt); } private boolean removeRouteToAddress(LinkProperties lp, InetAddress addr) { return modifyRouteToAddress(lp, addr, REMOVE, TO_DEFAULT_TABLE); return modifyRouteToAddress(lp, addr, REMOVE, TO_DEFAULT_TABLE, UNEXEMPT); } private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd, boolean toDefaultTable) { boolean toDefaultTable, boolean exempt) { RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getAllRoutes(), addr); if (bestRoute == null) { bestRoute = RouteInfo.makeHostRoute(addr, lp.getInterfaceName()); Loading @@ -1514,11 +1527,11 @@ public class ConnectivityService extends IConnectivityManager.Stub { bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway(), iface); } } return modifyRoute(lp, bestRoute, 0, doAdd, toDefaultTable); return modifyRoute(lp, bestRoute, 0, doAdd, toDefaultTable, exempt); } private boolean modifyRoute(LinkProperties lp, RouteInfo r, int cycleCount, boolean doAdd, boolean toDefaultTable) { boolean toDefaultTable, boolean exempt) { if ((lp == null) || (r == null)) { if (DBG) log("modifyRoute got unexpected null: " + lp + ", " + r); return false; Loading Loading @@ -1547,15 +1560,25 @@ public class ConnectivityService extends IConnectivityManager.Stub { bestRoute.getGateway(), ifaceName); } modifyRoute(lp, bestRoute, cycleCount+1, doAdd, toDefaultTable); modifyRoute(lp, bestRoute, cycleCount+1, doAdd, toDefaultTable, exempt); } } if (doAdd) { if (VDBG) log("Adding " + r + " for interface " + ifaceName); try { if (toDefaultTable) { mAddedRoutes.add(r); // only track default table - only one apps can effect synchronized (mRoutesLock) { // only track default table - only one apps can effect mAddedRoutes.add(r); mNetd.addRoute(ifaceName, r); if (exempt) { LinkAddress dest = r.getDestination(); if (!mExemptAddresses.contains(dest)) { mNetd.setHostExemption(dest); mExemptAddresses.add(dest); } } } } else { mNetd.addSecondaryRoute(ifaceName, r); } Loading @@ -1568,11 +1591,17 @@ public class ConnectivityService extends IConnectivityManager.Stub { // if we remove this one and there are no more like it, then refcount==0 and // we can remove it from the table if (toDefaultTable) { synchronized (mRoutesLock) { mAddedRoutes.remove(r); if (mAddedRoutes.contains(r) == false) { if (VDBG) log("Removing " + r + " for interface " + ifaceName); try { mNetd.removeRoute(ifaceName, r); LinkAddress dest = r.getDestination(); if (mExemptAddresses.contains(dest)) { mNetd.clearHostExemption(dest); mExemptAddresses.remove(dest); } } catch (Exception e) { // never crash - catch them all if (VDBG) loge("Exception trying to remove a route: " + e); Loading @@ -1581,6 +1610,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { } else { if (VDBG) log("not removing " + r + " as it's still in use"); } } } else { if (VDBG) log("Removing " + r + " for interface " + ifaceName); try { Loading Loading @@ -2260,6 +2290,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { */ private void handleConnectivityChange(int netType, boolean doReset) { int resetMask = doReset ? NetworkUtils.RESET_ALL_ADDRESSES : 0; boolean exempt = ConnectivityManager.isNetworkTypeExempt(netType); /* * If a non-default network is enabled, add the host routes that Loading Loading @@ -2324,7 +2355,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { } } mCurrentLinkProperties[netType] = newLp; boolean resetDns = updateRoutes(newLp, curLp, mNetConfigs[netType].isDefault()); boolean resetDns = updateRoutes(newLp, curLp, mNetConfigs[netType].isDefault(), exempt); if (resetMask != 0 || resetDns) { if (curLp != null) { Loading Loading @@ -2400,7 +2431,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { * returns a boolean indicating the routes changed */ private boolean updateRoutes(LinkProperties newLp, LinkProperties curLp, boolean isLinkDefault) { boolean isLinkDefault, boolean exempt) { Collection<RouteInfo> routesToAdd = null; CompareResult<InetAddress> dnsDiff = new CompareResult<InetAddress>(); CompareResult<RouteInfo> routeDiff = new CompareResult<RouteInfo>(); Loading Loading @@ -2436,7 +2467,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { } if (newLp != null) { for (InetAddress newDns : newLp.getDnses()) { addRouteToAddress(newLp, newDns); addRouteToAddress(newLp, newDns, exempt); } } } else { Loading @@ -2445,22 +2476,23 @@ public class ConnectivityService extends IConnectivityManager.Stub { removeRouteToAddress(curLp, oldDns); } for (InetAddress newDns : dnsDiff.added) { addRouteToAddress(newLp, newDns); addRouteToAddress(newLp, newDns, exempt); } } } for (RouteInfo r : routeDiff.added) { if (isLinkDefault || ! r.isDefaultRoute()) { addRoute(newLp, r, TO_DEFAULT_TABLE); addRoute(newLp, r, TO_DEFAULT_TABLE, exempt); } else { // add to a secondary route table addRoute(newLp, r, TO_SECONDARY_TABLE); addRoute(newLp, r, TO_SECONDARY_TABLE, UNEXEMPT); // many radios add a default route even when we don't want one. // remove the default route unless somebody else has asked for it String ifaceName = newLp.getInterfaceName(); if (TextUtils.isEmpty(ifaceName) == false && mAddedRoutes.contains(r) == false) { synchronized (mRoutesLock) { if (!TextUtils.isEmpty(ifaceName) && !mAddedRoutes.contains(r)) { if (VDBG) log("Removing " + r + " for interface " + ifaceName); try { mNetd.removeRoute(ifaceName, r); Loading @@ -2471,6 +2503,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { } } } } return routesChanged; } Loading
services/java/com/android/server/NetworkManagementService.java +20 −0 Original line number Diff line number Diff line Loading @@ -1472,6 +1472,26 @@ public class NetworkManagementService extends INetworkManagementService.Stub } } @Override public void setHostExemption(LinkAddress host) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); try { mConnector.execute("interface", "fwmark", "exempt", "add", host); } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); } } @Override public void clearHostExemption(LinkAddress host) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); try { mConnector.execute("interface", "fwmark", "exempt", "remove", host); } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); } } @Override public void setDnsInterfaceForUidRange(String iface, int uid_start, int uid_end) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); Loading