Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 348297ab authored by Robert Greenwalt's avatar Robert Greenwalt Committed by Android (Google) Code Review
Browse files

Merge "Start using IP tool for advanced routing." into ics-mr0

parents ca250167 3b28e9a3
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -104,6 +104,18 @@ interface INetworkManagementService
     */
    void removeRoute(String iface, in RouteInfo route);

    /**
     * Add the specified route to a secondary interface
     * This will go into a special route table to be accessed
     * via ip rules
     */
    void addSecondaryRoute(String iface, in RouteInfo route);

    /**
     * Remove the specified secondary route.
     */
    void removeSecondaryRoute(String iface, in RouteInfo route);

    /**
     * Shuts down the service
     */
+50 −27
Original line number Diff line number Diff line
@@ -171,6 +171,12 @@ public class ConnectivityService extends IConnectivityManager.Stub {
    private static final int ENABLED  = 1;
    private static final int DISABLED = 0;

    private static final boolean ADD = true;
    private static final boolean REMOVE = false;

    private static final boolean TO_DEFAULT_TABLE = true;
    private static final boolean TO_SECONDARY_TABLE = false;

    // Share the event space with NetworkStateTracker (which can't see this
    // internal class but sends us events).  If you change these, change
    // NetworkStateTracker.java too.
@@ -501,7 +507,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
        INetworkManagementService nmService = INetworkManagementService.Stub.asInterface(b);

        mTethering = new Tethering(mContext, nmService, statsService, mHandler.getLooper());
        mTethering = new Tethering(mContext, nmService, statsService, this, mHandler.getLooper());
        mTetheringConfigValid = ((mTethering.getTetherableUsbRegexs().length != 0 ||
                                  mTethering.getTetherableWifiRegexs().length != 0 ||
                                  mTethering.getTetherableBluetoothRegexs().length != 0) &&
@@ -1146,23 +1152,24 @@ public class ConnectivityService extends IConnectivityManager.Stub {
        return false;
    }

    private boolean addRoute(LinkProperties p, RouteInfo r) {
        return modifyRoute(p.getInterfaceName(), p, r, 0, true);
    private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) {
        return modifyRoute(p.getInterfaceName(), p, r, 0, ADD, toDefaultTable);
    }

    private boolean removeRoute(LinkProperties p, RouteInfo r) {
        return modifyRoute(p.getInterfaceName(), p, r, 0, false);
    private boolean removeRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) {
        return modifyRoute(p.getInterfaceName(), p, r, 0, REMOVE, toDefaultTable);
    }

    private boolean addRouteToAddress(LinkProperties lp, InetAddress addr) {
        return modifyRouteToAddress(lp, addr, true);
        return modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE);
    }

    private boolean removeRouteToAddress(LinkProperties lp, InetAddress addr) {
        return modifyRouteToAddress(lp, addr, false);
        return modifyRouteToAddress(lp, addr, REMOVE, TO_DEFAULT_TABLE);
    }

    private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd) {
    private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd,
            boolean toDefaultTable) {
        RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), addr);
        if (bestRoute == null) {
            bestRoute = RouteInfo.makeHostRoute(addr);
@@ -1176,15 +1183,15 @@ public class ConnectivityService extends IConnectivityManager.Stub {
                bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway());
            }
        }
        return modifyRoute(lp.getInterfaceName(), lp, bestRoute, 0, doAdd);
        return modifyRoute(lp.getInterfaceName(), lp, bestRoute, 0, doAdd, toDefaultTable);
    }

    private boolean modifyRoute(String ifaceName, LinkProperties lp, RouteInfo r, int cycleCount,
            boolean doAdd) {
            boolean doAdd, boolean toDefaultTable) {
        if ((ifaceName == null) || (lp == null) || (r == null)) return false;

        if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) {
            loge("Error adding route - too much recursion");
            loge("Error modifying route - too much recursion");
            return false;
        }

@@ -1199,14 +1206,18 @@ public class ConnectivityService extends IConnectivityManager.Stub {
                    // route to it's gateway
                    bestRoute = RouteInfo.makeHostRoute(r.getGateway(), bestRoute.getGateway());
                }
                modifyRoute(ifaceName, lp, bestRoute, cycleCount+1, doAdd);
                modifyRoute(ifaceName, lp, bestRoute, cycleCount+1, doAdd, toDefaultTable);
            }
        }
        if (doAdd) {
            if (VDBG) log("Adding " + r + " for interface " + ifaceName);
            mAddedRoutes.add(r);
            try {
                if (toDefaultTable) {
                    mAddedRoutes.add(r);  // only track default table - only one apps can effect
                    mNetd.addRoute(ifaceName, r);
                } else {
                    mNetd.addSecondaryRoute(ifaceName, r);
                }
            } catch (Exception e) {
                // never crash - catch them all
                if (VDBG) loge("Exception trying to add a route: " + e);
@@ -1215,6 +1226,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
        } else {
            // 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) {
                mAddedRoutes.remove(r);
                if (mAddedRoutes.contains(r) == false) {
                    if (VDBG) log("Removing " + r + " for interface " + ifaceName);
@@ -1228,6 +1240,16 @@ 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 {
                    mNetd.removeSecondaryRoute(ifaceName, r);
                } catch (Exception e) {
                    // never crash - catch them all
                    if (VDBG) loge("Exception trying to remove a route: " + e);
                    return false;
                }
            }
        }
        return true;
    }
@@ -1862,14 +1884,21 @@ public class ConnectivityService extends IConnectivityManager.Stub {

        for (RouteInfo r : routeDiff.removed) {
            if (isLinkDefault || ! r.isDefaultRoute()) {
                removeRoute(curLp, r);
                removeRoute(curLp, r, TO_DEFAULT_TABLE);
            }
            if (isLinkDefault == false) {
                // remove from a secondary route table
                removeRoute(curLp, r, TO_SECONDARY_TABLE);
            }
        }

        for (RouteInfo r :  routeDiff.added) {
            if (isLinkDefault || ! r.isDefaultRoute()) {
                addRoute(newLp, r);
                addRoute(newLp, r, TO_DEFAULT_TABLE);
            } else {
                // add to a secondary route table
                addRoute(newLp, r, TO_SECONDARY_TABLE);

                // 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();
@@ -2450,12 +2479,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
        int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
        boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(),
                Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0);
        // Short term disabling of Tethering if DUN is required.
        // TODO - fix multi-connection tethering using policy-base routing
        int[] upstreamConnTypes = mTethering.getUpstreamIfaceTypes();
        for (int i : upstreamConnTypes) {
            if (i == ConnectivityManager.TYPE_MOBILE_DUN) return false;
        }
        return tetherEnabledInSettings && mTetheringConfigValid;
    }

+48 −11
Original line number Diff line number Diff line
@@ -59,7 +59,11 @@ import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
@@ -77,6 +81,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub
    private static final int ADD = 1;
    private static final int REMOVE = 2;

    private static final String DEFAULT = "default";
    private static final String SECONDARY = "secondary";

    /**
     * Name representing {@link #setGlobalAlert(long)} limit when delivered to
     * {@link INetworkManagementEventObserver#limitReached(String, String)}.
@@ -500,15 +507,25 @@ public class NetworkManagementService extends INetworkManagementService.Stub

    public void addRoute(String interfaceName, RouteInfo route) {
        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
        modifyRoute(interfaceName, ADD, route);
        modifyRoute(interfaceName, ADD, route, DEFAULT);
    }

    public void removeRoute(String interfaceName, RouteInfo route) {
        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
        modifyRoute(interfaceName, REMOVE, route);
        modifyRoute(interfaceName, REMOVE, route, DEFAULT);
    }

    private void modifyRoute(String interfaceName, int action, RouteInfo route) {
    public void addSecondaryRoute(String interfaceName, RouteInfo route) {
        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
        modifyRoute(interfaceName, ADD, route, SECONDARY);
    }

    public void removeSecondaryRoute(String interfaceName, RouteInfo route) {
        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
        modifyRoute(interfaceName, REMOVE, route, SECONDARY);
    }

    private void modifyRoute(String interfaceName, int action, RouteInfo route, String type) {
        ArrayList<String> rsp;

        StringBuilder cmd;
@@ -516,12 +533,12 @@ public class NetworkManagementService extends INetworkManagementService.Stub
        switch (action) {
            case ADD:
            {
                cmd = new StringBuilder("interface route add " + interfaceName);
                cmd = new StringBuilder("interface route add " + interfaceName + " " + type);
                break;
            }
            case REMOVE:
            {
                cmd = new StringBuilder("interface route remove " + interfaceName);
                cmd = new StringBuilder("interface route remove " + interfaceName + " " + type);
                break;
            }
            default:
@@ -828,14 +845,33 @@ public class NetworkManagementService extends INetworkManagementService.Stub
        }
    }

    private void modifyNat(String cmd, String internalInterface, String externalInterface)
            throws SocketException {
        cmd = String.format("nat %s %s %s", cmd, internalInterface, externalInterface);

        NetworkInterface internalNetworkInterface =
                NetworkInterface.getByName(internalInterface);
        Collection<InterfaceAddress>interfaceAddresses =
                internalNetworkInterface.getInterfaceAddresses();
        cmd += " " + interfaceAddresses.size();
        for (InterfaceAddress ia : interfaceAddresses) {
            InetAddress addr = NetworkUtils.getNetworkPart(ia.getAddress(),
                    ia.getNetworkPrefixLength());
            cmd = cmd + " " + addr.getHostAddress() + "/" + ia.getNetworkPrefixLength();
        }

        mConnector.doCommand(cmd);
    }

    public void enableNat(String internalInterface, String externalInterface)
            throws IllegalStateException {
        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
        if (DBG) Log.d(TAG, "enableNat(" + internalInterface + ", " + externalInterface + ")");
        try {
            mConnector.doCommand(
                    String.format("nat enable %s %s", internalInterface, externalInterface));
        } catch (NativeDaemonConnectorException e) {
            modifyNat("enable", internalInterface, externalInterface);
        } catch (Exception e) {
            Log.e(TAG, "enableNat got Exception " + e.toString());
            throw new IllegalStateException(
                    "Unable to communicate to native daemon for enabling NAT interface");
        }
@@ -845,10 +881,11 @@ public class NetworkManagementService extends INetworkManagementService.Stub
            throws IllegalStateException {
        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
        if (DBG) Log.d(TAG, "disableNat(" + internalInterface + ", " + externalInterface + ")");
        try {
            mConnector.doCommand(
                    String.format("nat disable %s %s", internalInterface, externalInterface));
        } catch (NativeDaemonConnectorException e) {
            modifyNat("disable", internalInterface, externalInterface);
        } catch (Exception e) {
            Log.e(TAG, "disableNat got Exception " + e.toString());
            throw new IllegalStateException(
                    "Unable to communicate to native daemon for disabling NAT interface");
        }
+10 −14
Original line number Diff line number Diff line
@@ -91,6 +91,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {

    private final INetworkManagementService mNMService;
    private final INetworkStatsService mStatsService;
    private final IConnectivityManager mConnService;
    private Looper mLooper;
    private HandlerThread mThread;

@@ -127,10 +128,11 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
                                         // when RNDIS is enabled

    public Tethering(Context context, INetworkManagementService nmService,
            INetworkStatsService statsService, Looper looper) {
            INetworkStatsService statsService, IConnectivityManager connService, Looper looper) {
        mContext = context;
        mNMService = nmService;
        mStatsService = statsService;
        mConnService = connService;
        mLooper = looper;

        mIfaces = new HashMap<String, TetherInterfaceSM>();
@@ -347,10 +349,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
    }

    private void sendTetherStateChangedBroadcast() {
        IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
        IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
        try {
            if (!cm.isTetheringSupported()) return;
            if (!mConnService.isTetheringSupported()) return;
        } catch (RemoteException e) {
            return;
        }
@@ -910,6 +910,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
                try {
                    mNMService.tetherInterface(mIfaceName);
                } catch (Exception e) {
                    Log.e(TAG, "Error Tethering: " + e.toString());
                    setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR);

                    transitionTo(mInitialState);
@@ -987,6 +988,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
                            try {
                                mNMService.enableNat(mIfaceName, newUpstreamIfaceName);
                            } catch (Exception e) {
                                Log.e(TAG, "Exception enabling Nat: " + e.toString());
                                try {
                                    mNMService.untetherInterface(mIfaceName);
                                } catch (Exception ee) {}
@@ -1150,13 +1152,11 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
                boolean retValue = true;
                if (apnType == ConnectivityManager.TYPE_NONE) return false;
                if (apnType != mMobileApnReserved) turnOffUpstreamMobileConnection();
                IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
                IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
                int result = Phone.APN_REQUEST_FAILED;
                String enableString = enableString(apnType);
                if (enableString == null) return false;
                try {
                    result = cm.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
                    result = mConnService.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
                            enableString, new Binder());
                } catch (Exception e) {
                }
@@ -1178,10 +1178,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
            }
            protected boolean turnOffUpstreamMobileConnection() {
                if (mMobileApnReserved != ConnectivityManager.TYPE_NONE) {
                    IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
                    IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
                    try {
                        cm.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
                        mConnService.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
                                enableString(mMobileApnReserved));
                    } catch (Exception e) {
                        return false;
@@ -1234,8 +1232,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
            }

            protected void chooseUpstreamType(boolean tryCell) {
                IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
                IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
                int upType = ConnectivityManager.TYPE_NONE;
                String iface = null;

@@ -1251,7 +1247,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
                for (Integer netType : mUpstreamIfaceTypes) {
                    NetworkInfo info = null;
                    try {
                        info = cm.getNetworkInfo(netType.intValue());
                        info = mConnService.getNetworkInfo(netType.intValue());
                    } catch (RemoteException e) { }
                    if ((info != null) && info.isConnected()) {
                        upType = netType.intValue();
@@ -1283,7 +1279,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
                } else {
                    LinkProperties linkProperties = null;
                    try {
                        linkProperties = cm.getLinkProperties(upType);
                        linkProperties = mConnService.getLinkProperties(upType);
                    } catch (RemoteException e) { }
                    if (linkProperties != null) iface = linkProperties.getInterfaceName();
                }