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

Commit f52fa0ea authored by markchien's avatar markchien
Browse files

[Tether09] Add RouteUtils and NetdUtils

Add RouteUtils and NetdUtils file to NetworkStack module shared
folder. And it would statically linked into framework and
tethering module.

Bug: 136040414
Test: -build, flash, boot
      -atest TetheringTest

Change-Id: I8c2781597b410d12407ddb743f1621bf92d2a852
parent c1eaeb31
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -19,3 +19,16 @@ filegroup {
    name: "net-module-utils-srcs",
    srcs: ["src/**/*.java"],
}

// Shared utility sources to be used by tethering modules
filegroup {
    name: "tethering-module-utils-srcs",
    srcs: [
        "src/android/net/ip/InterfaceController.java",
        "src/android/net/netlink/*.java",
        "src/android/net/shared/NetdUtils.java",
        "src/android/net/shared/RouteUtils.java",
        "src/android/net/util/InterfaceParams.java",
        "src/android/net/util/SharedLog.java"
    ],
}
+28 −10
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package android.net.ip;

import static android.net.INetd.IF_STATE_DOWN;
import static android.net.INetd.IF_STATE_UP;

import android.net.INetd;
import android.net.InterfaceConfigurationParcel;
import android.net.LinkAddress;
@@ -48,13 +51,31 @@ public class InterfaceController {
        mLog = log;
    }

    private boolean setInterfaceAddress(LinkAddress addr) {
    /**
     * Set the IPv4 address and also optionally bring the interface up or down.
     */
    public boolean setInterfaceConfiguration(final LinkAddress ipv4Addr,
            final Boolean setIfaceUp) {
        if (!(ipv4Addr.getAddress() instanceof Inet4Address)) {
            throw new IllegalArgumentException("Invalid or mismatched Inet4Address");
        }
        // Note: currently netd only support INetd#IF_STATE_UP and #IF_STATE_DOWN.
        // Other flags would be ignored.

        final InterfaceConfigurationParcel ifConfig = new InterfaceConfigurationParcel();
        ifConfig.ifName = mIfName;
        ifConfig.ipv4Addr = addr.getAddress().getHostAddress();
        ifConfig.prefixLength = addr.getPrefixLength();
        ifConfig.ipv4Addr = ipv4Addr.getAddress().getHostAddress();
        ifConfig.prefixLength = ipv4Addr.getPrefixLength();
        // Netd ignores hwaddr in interfaceSetCfg.
        ifConfig.hwAddr = "";
        if (setIfaceUp == null) {
            // Empty array means no change.
            ifConfig.flags = new String[0];
        } else {
            // Netd ignores any flag that's not IF_STATE_UP or IF_STATE_DOWN in interfaceSetCfg.
            ifConfig.flags = setIfaceUp.booleanValue()
                    ? new String[] {IF_STATE_UP} : new String[] {IF_STATE_DOWN};
        }
        try {
            mNetd.interfaceSetCfg(ifConfig);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -68,18 +89,15 @@ public class InterfaceController {
    /**
     * Set the IPv4 address of the interface.
     */
    public boolean setIPv4Address(LinkAddress address) {
        if (!(address.getAddress() instanceof Inet4Address)) {
            return false;
        }
        return setInterfaceAddress(address);
    public boolean setIPv4Address(final LinkAddress address) {
        return setInterfaceConfiguration(address, null);
    }

    /**
     * Clear the IPv4Address of the interface.
     */
    public boolean clearIPv4Address() {
        return setInterfaceAddress(new LinkAddress("0.0.0.0/0"));
        return setIPv4Address(new LinkAddress("0.0.0.0/0"));
    }

    private boolean setEnableIPv6(boolean enabled) {
+65 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net.shared;

import static android.net.RouteInfo.RTN_UNICAST;

import android.net.INetd;
import android.net.IpPrefix;
import android.net.RouteInfo;
import android.net.TetherConfigParcel;
import android.os.RemoteException;
import android.os.ServiceSpecificException;

import java.util.ArrayList;
import java.util.List;

/**
 * Implements common operations on INetd
 * @hide
 */
public class NetdUtils {
    /** Start tethering. */
    public static void tetherStart(final INetd netd, final boolean usingLegacyDnsProxy,
            final String[] dhcpRange) throws RemoteException, ServiceSpecificException {
        final TetherConfigParcel config = new TetherConfigParcel();
        config.usingLegacyDnsProxy = usingLegacyDnsProxy;
        config.dhcpRanges = dhcpRange;
        netd.tetherStartWithConfiguration(config);
    }

    /** Setup interface for tethering. */
    public static void tetherInterface(final INetd netd, final String iface, final IpPrefix dest)
            throws RemoteException, ServiceSpecificException {
        netd.tetherInterfaceAdd(iface);

        netd.networkAddInterface(INetd.LOCAL_NET_ID, iface);
        List<RouteInfo> routes = new ArrayList<>();
        routes.add(new RouteInfo(dest, null, iface, RTN_UNICAST));
        RouteUtils.addRoutesToLocalNetwork(netd, iface, routes);
    }

    /** Reset interface for tethering. */
    public static void untetherInterface(final INetd netd, String iface)
            throws RemoteException, ServiceSpecificException {
        try {
            netd.tetherInterfaceRemove(iface);
        } finally {
            netd.networkRemoveInterface(INetd.LOCAL_NET_ID, iface);
        }
    }
}
+115 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package android.net.shared;

import static android.net.RouteInfo.RTN_THROW;
import static android.net.RouteInfo.RTN_UNICAST;
import static android.net.RouteInfo.RTN_UNREACHABLE;

import android.net.INetd;
import android.net.IpPrefix;
import android.net.RouteInfo;
import android.os.RemoteException;
import android.os.ServiceSpecificException;

import java.util.List;

/** @hide*/
public class RouteUtils {

    /** Used to modify the specified route. */
    public enum ModifyOperation {
        ADD,
        REMOVE,
    }

    private static String findNextHop(final RouteInfo route) {
        final String nextHop;
        switch (route.getType()) {
            case RTN_UNICAST:
                if (route.hasGateway()) {
                    nextHop = route.getGateway().getHostAddress();
                } else {
                    nextHop = INetd.NEXTHOP_NONE;
                }
                break;
            case RTN_UNREACHABLE:
                nextHop = INetd.NEXTHOP_UNREACHABLE;
                break;
            case RTN_THROW:
                nextHop = INetd.NEXTHOP_THROW;
                break;
            default:
                nextHop = INetd.NEXTHOP_NONE;
                break;
        }
        return nextHop;
    }

    /** Add |routes| to local network. */
    public static void addRoutesToLocalNetwork(final INetd netd, final String iface,
            final List<RouteInfo> routes) {

        for (RouteInfo route : routes) {
            if (!route.isDefaultRoute()) {
                modifyRoute(netd, ModifyOperation.ADD, INetd.LOCAL_NET_ID, route);
            }
        }

        // IPv6 link local should be activated always.
        modifyRoute(netd, ModifyOperation.ADD, INetd.LOCAL_NET_ID,
                new RouteInfo(new IpPrefix("fe80::/64"), null, iface, RTN_UNICAST));
    }

    /** Remove routes from local network. */
    public static int removeRoutesFromLocalNetwork(final INetd netd, final List<RouteInfo> routes) {
        int failures = 0;

        for (RouteInfo route : routes) {
            try {
                modifyRoute(netd, ModifyOperation.REMOVE, INetd.LOCAL_NET_ID, route);
            } catch (IllegalStateException e) {
                failures++;
            }
        }

        return failures;
    }

    /** Add or remove |route|. */
    public static void modifyRoute(final INetd netd, final ModifyOperation op, final int netId,
            final RouteInfo route) {
        final String ifName = route.getInterface();
        final String dst = route.getDestination().toString();
        final String nextHop = findNextHop(route);

        try {
            switch(op) {
                case ADD:
                    netd.networkAddRoute(netId, ifName, dst, nextHop);
                    break;
                case REMOVE:
                    netd.networkRemoveRoute(netId, ifName, dst, nextHop);
                    break;
                default:
                    throw new IllegalStateException("Unsupported modify operation:" + op);
            }
        } catch (RemoteException | ServiceSpecificException e) {
            throw new IllegalStateException(e);
        }
    }

}