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

Commit 08cc0305 authored by markchien's avatar markchien
Browse files

[Tether03] Migrate IpServer into module

Add IpServer which is used to serve ip configuration, dhcp, dns proxy
and nat for downstream interface.

Bug: 136040414
Test: -build, flash, boot
      -atest TetheringTests
      -atest FrameworksNetTests

Change-Id: I23652ae0b9509abe7d38da96d523eb22ab00a343
parent a6ba54d5
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ java_defaults {
    ],
    static_libs: [
        "androidx.annotation_annotation",
        "netd_aidl_interface-java",
        "networkstack-aidl-interfaces-java",
        "tethering-client",
    ],
    manifest: "AndroidManifestBase.xml",
@@ -68,5 +70,10 @@ filegroup {
    name: "tethering-services-srcs",
    srcs: [
        "src/com/android/server/connectivity/tethering/TetheringConfiguration.java",
        "src/android/net/dhcp/DhcpServerCallbacks.java",
        "src/android/net/dhcp/DhcpServingParamsParcelExt.java",
        "src/android/net/ip/IpServer.java",
        "src/android/net/ip/RouterAdvertisementDaemon.java",
        "src/android/net/util/InterfaceSet.java",
    ],
}
+50 −19
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@

package android.net.ip;

import static android.net.NetworkUtils.numericToInetAddress;
import static android.net.InetAddresses.parseNumericAddress;
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
import static android.net.util.NetworkConstants.FF;
import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH;
@@ -77,6 +77,7 @@ public class IpServer extends StateMachine {
    public static final int STATE_TETHERED    = 2;
    public static final int STATE_LOCAL_ONLY  = 3;

    /** Get string name of |state|.*/
    public static String getStateString(int state) {
        switch (state) {
            case STATE_UNAVAILABLE: return "UNAVAILABLE";
@@ -103,15 +104,16 @@ public class IpServer extends StateMachine {
    // TODO: have this configurable
    private static final int DHCP_LEASE_TIME_SECS = 3600;

    private final static String TAG = "IpServer";
    private final static boolean DBG = false;
    private final static boolean VDBG = false;
    private static final Class[] messageClasses = {
    private static final String TAG = "IpServer";
    private static final boolean DBG = false;
    private static final boolean VDBG = false;
    private static final Class[] sMessageClasses = {
            IpServer.class
    };
    private static final SparseArray<String> sMagicDecoderRing =
            MessageUtils.findMessageNames(messageClasses);
            MessageUtils.findMessageNames(sMessageClasses);

    /** IpServer callback. */
    public static class Callback {
        /**
         * Notify that |who| has changed its tethering state.
@@ -131,11 +133,14 @@ public class IpServer extends StateMachine {
        public void updateLinkProperties(IpServer who, LinkProperties newLp) {}
    }

    /** Capture IpServer dependencies, for injection. */
    public static class Dependencies {
        /** Create a RouterAdvertisementDaemon instance to be used by IpServer.*/
        public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
            return new RouterAdvertisementDaemon(ifParams);
        }

        /** Get |ifName|'s interface information.*/
        public InterfaceParams getInterfaceParams(String ifName) {
            return InterfaceParams.getByName(ifName);
        }
@@ -244,25 +249,51 @@ public class IpServer extends StateMachine {
        setInitialState(mInitialState);
    }

    public String interfaceName() { return mIfaceName; }

    public int interfaceType() { return mInterfaceType; }
    /** Interface name which IpServer served.*/
    public String interfaceName() {
        return mIfaceName;
    }

    public int lastError() { return mLastError; }
    /**
     * Tethering downstream type. It would be one of ConnectivityManager#TETHERING_*.
     */
    public int interfaceType() {
        return mInterfaceType;
    }

    public int servingMode() { return mServingMode; }
    /** Last error from this IpServer. */
    public int lastError() {
        return mLastError;
    }

    public LinkProperties linkProperties() { return new LinkProperties(mLinkProperties); }
    /** Serving mode is the current state of IpServer state machine. */
    public int servingMode() {
        return mServingMode;
    }

    public void stop() { sendMessage(CMD_INTERFACE_DOWN); }
    /** The properties of the network link which IpServer is serving. */
    public LinkProperties linkProperties() {
        return new LinkProperties(mLinkProperties);
    }

    public void unwanted() { sendMessage(CMD_TETHER_UNREQUESTED); }
    /** Stop this IpServer. After this is called this IpServer should not be used any more. */
    public void stop() {
        sendMessage(CMD_INTERFACE_DOWN);
    }

    /**
     * Internals.
     * Tethering is canceled. IpServer state machine will be available and wait for
     * next tethering request.
     */
    public void unwanted() {
        sendMessage(CMD_TETHER_UNREQUESTED);
    }

    /** Internals. */

    private boolean startIPv4() { return configureIPv4(true); }
    private boolean startIPv4() {
        return configureIPv4(true);
    }

    /**
     * Convenience wrapper around INetworkStackStatusCallback to run callbacks on the IpServer
@@ -410,7 +441,7 @@ public class IpServer extends StateMachine {
            prefixLen = WIFI_P2P_IFACE_PREFIX_LENGTH;
        } else {
            // BT configures the interface elsewhere: only start DHCP.
            final Inet4Address srvAddr = (Inet4Address) numericToInetAddress(BLUETOOTH_IFACE_ADDR);
            final Inet4Address srvAddr = (Inet4Address) parseNumericAddress(BLUETOOTH_IFACE_ADDR);
            return configureDhcp(enabled, srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH);
        }

@@ -422,7 +453,7 @@ public class IpServer extends StateMachine {
                return false;
            }

            InetAddress addr = numericToInetAddress(ipAsString);
            InetAddress addr = parseNumericAddress(ipAsString);
            linkAddr = new LinkAddress(addr, prefixLen);
            ifcg.setLinkAddress(linkAddr);
            if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
@@ -473,7 +504,7 @@ public class IpServer extends StateMachine {

    private String getRandomWifiIPv4Address() {
        try {
            byte[] bytes = numericToInetAddress(WIFI_HOST_IFACE_ADDR).getAddress();
            byte[] bytes = parseNumericAddress(WIFI_HOST_IFACE_ADDR).getAddress();
            bytes[3] = getRandomSanitizedByte(DOUG_ADAMS, asByte(0), asByte(1), FF);
            return InetAddress.getByAddress(bytes).getHostAddress();
        } catch (Exception e) {
+86 −69
Original line number Diff line number Diff line
@@ -119,6 +119,7 @@ public class RouterAdvertisementDaemon {
    private volatile MulticastTransmitter mMulticastTransmitter;
    private volatile UnicastResponder mUnicastResponder;

    /** Encapsulate the RA parameters for RouterAdvertisementDaemon.*/
    public static class RaParams {
        // Tethered traffic will have the hop limit properly decremented.
        // Consequently, set the hoplimit greater by one than the upstream
@@ -150,10 +151,12 @@ public class RouterAdvertisementDaemon {
            dnses = (HashSet) other.dnses.clone();
        }

        // Returns the subset of RA parameters that become deprecated when
        // moving from announcing oldRa to announcing newRa.
        //
        // Currently only tracks differences in |prefixes| and |dnses|.
        /**
         * Returns the subset of RA parameters that become deprecated when
         * moving from announcing oldRa to announcing newRa.
         *
         * Currently only tracks differences in |prefixes| and |dnses|.
         */
        public static RaParams getDeprecatedRaParams(RaParams oldRa, RaParams newRa) {
            RaParams newlyDeprecated = new RaParams();

@@ -179,7 +182,9 @@ public class RouterAdvertisementDaemon {
        private final HashMap<IpPrefix, Integer> mPrefixes = new HashMap<>();
        private final HashMap<Inet6Address, Integer> mDnses = new HashMap<>();

        Set<IpPrefix> getPrefixes() { return mPrefixes.keySet(); }
        Set<IpPrefix> getPrefixes() {
            return mPrefixes.keySet();
        }

        void putPrefixes(Set<IpPrefix> prefixes) {
            for (IpPrefix ipp : prefixes) {
@@ -193,7 +198,9 @@ public class RouterAdvertisementDaemon {
            }
        }

        Set<Inet6Address> getDnses() { return mDnses.keySet(); }
        Set<Inet6Address> getDnses() {
            return mDnses.keySet();
        }

        void putDnses(Set<Inet6Address> dnses) {
            for (Inet6Address dns : dnses) {
@@ -207,7 +214,9 @@ public class RouterAdvertisementDaemon {
            }
        }

        boolean isEmpty() { return mPrefixes.isEmpty() && mDnses.isEmpty(); }
        boolean isEmpty() {
            return mPrefixes.isEmpty() && mDnses.isEmpty();
        }

        private boolean decrementCounters() {
            boolean removed = decrementCounter(mPrefixes);
@@ -240,6 +249,7 @@ public class RouterAdvertisementDaemon {
        mDeprecatedInfoTracker = new DeprecatedInfoTracker();
    }

    /** Build new RA.*/
    public void buildNewRa(RaParams deprecatedParams, RaParams newParams) {
        synchronized (mLock) {
            if (deprecatedParams != null) {
@@ -260,6 +270,7 @@ public class RouterAdvertisementDaemon {
        maybeNotifyMulticastTransmitter();
    }

    /** Start router advertisement daemon. */
    public boolean start() {
        if (!createSocket()) {
            return false;
@@ -274,6 +285,7 @@ public class RouterAdvertisementDaemon {
        return true;
    }

    /** Stop router advertisement daemon. */
    public void stop() {
        closeSocket();
        // Wake up mMulticastTransmitter thread to interrupt a potential 1 day sleep before
@@ -362,8 +374,12 @@ public class RouterAdvertisementDaemon {
        }
    }

    private static byte asByte(int value) { return (byte) value; }
    private static short asShort(int value) { return (short) value; }
    private static byte asByte(int value) {
        return (byte) value;
    }
    private static short asShort(int value) {
        return (short) value;
    }

    private static void putHeader(ByteBuffer ra, boolean hasDefaultRoute, byte hopLimit) {
        /**
@@ -408,10 +424,11 @@ public class RouterAdvertisementDaemon {
            // Only IEEE 802.3 6-byte addresses are supported.
            return;
        }
        final byte ND_OPTION_SLLA = 1;
        final byte SLLA_NUM_8OCTETS = 1;
        ra.put(ND_OPTION_SLLA)
          .put(SLLA_NUM_8OCTETS)

        final byte nd_option_slla = 1;
        final byte slla_num_8octets = 1;
        ra.put(nd_option_slla)
            .put(slla_num_8octets)
            .put(slla);
    }

@@ -428,11 +445,11 @@ public class RouterAdvertisementDaemon {
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         */

        final byte ND_OPTION_EFO = 26;
        final byte EFO_NUM_8OCTETS = 1;
        final byte nd_option__efo = 26;
        final byte efo_num_8octets = 1;

        ra.put(ND_OPTION_EFO)
          .put(EFO_NUM_8OCTETS)
        ra.put(nd_option__efo)
            .put(efo_num_8octets)
            .putShort(asShort(0))
            .putInt(0);
    }
@@ -449,10 +466,10 @@ public class RouterAdvertisementDaemon {
            |                              MTU                              |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        */
        final byte ND_OPTION_MTU = 5;
        final byte MTU_NUM_8OCTETS = 1;
        ra.put(ND_OPTION_MTU)
          .put(MTU_NUM_8OCTETS)
        final byte nd_option_mtu = 5;
        final byte mtu_num_8octs = 1;
        ra.put(nd_option_mtu)
            .put(mtu_num_8octs)
            .putShort(asShort(0))
            .putInt((mtu < IPV6_MIN_MTU) ? IPV6_MIN_MTU : mtu);
    }
@@ -486,16 +503,16 @@ public class RouterAdvertisementDaemon {
        if (prefixLength != 64) {
            return;
        }
        final byte ND_OPTION_PIO = 3;
        final byte PIO_NUM_8OCTETS = 4;
        final byte nd_option_pio = 3;
        final byte pio_num_8octets = 4;

        if (validTime < 0) validTime = 0;
        if (preferredTime < 0) preferredTime = 0;
        if (preferredTime > validTime) preferredTime = validTime;

        final byte[] addr = ipp.getAddress().getAddress();
        ra.put(ND_OPTION_PIO)
          .put(PIO_NUM_8OCTETS)
        ra.put(nd_option_pio)
            .put(pio_num_8octets)
            .put(asByte(prefixLength))
            .put(asByte(0xc0)) /* L & A set */
            .putInt(validTime)
@@ -524,13 +541,13 @@ public class RouterAdvertisementDaemon {
        if (prefixLength > 64) {
            return;
        }
        final byte ND_OPTION_RIO = 24;
        final byte RIO_NUM_8OCTETS = asByte(
        final byte nd_option_rio = 24;
        final byte rio_num_8octets = asByte(
                (prefixLength == 0) ? 1 : (prefixLength <= 8) ? 2 : 3);

        final byte[] addr = ipp.getAddress().getAddress();
        ra.put(ND_OPTION_RIO)
          .put(RIO_NUM_8OCTETS)
        ra.put(nd_option_rio)
            .put(rio_num_8octets)
            .put(asByte(prefixLength))
            .put(asByte(0x18))
            .putInt(DEFAULT_LIFETIME);
@@ -566,10 +583,10 @@ public class RouterAdvertisementDaemon {
        }
        if (filteredDnses.isEmpty()) return;

        final byte ND_OPTION_RDNSS = 25;
        final byte RDNSS_NUM_8OCTETS = asByte(dnses.size() * 2 + 1);
        ra.put(ND_OPTION_RDNSS)
          .put(RDNSS_NUM_8OCTETS)
        final byte nd_option_rdnss = 25;
        final byte rdnss_num_8octets = asByte(dnses.size() * 2 + 1);
        ra.put(nd_option_rdnss)
            .put(rdnss_num_8octets)
            .putShort(asShort(0))
            .putInt(lifetime);

@@ -585,7 +602,7 @@ public class RouterAdvertisementDaemon {
    }

    private boolean createSocket() {
        final int SEND_TIMEOUT_MS = 300;
        final int send_timout_ms = 300;

        final int oldTag = TrafficStats.getAndSetThreadStatsTag(
                TrafficStatsConstants.TAG_SYSTEM_NEIGHBOR);
@@ -593,7 +610,7 @@ public class RouterAdvertisementDaemon {
            mSocket = Os.socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
            // Setting SNDTIMEO is purely for defensive purposes.
            Os.setsockoptTimeval(
                    mSocket, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(SEND_TIMEOUT_MS));
                    mSocket, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(send_timout_ms));
            Os.setsockoptIfreq(mSocket, SOL_SOCKET, SO_BINDTODEVICE, mInterface.name);
            NetworkUtils.protectFromVpn(mSocket);
            NetworkUtils.setupRaSocket(mSocket, mInterface.index);
@@ -627,9 +644,9 @@ public class RouterAdvertisementDaemon {
        }

        final InetAddress destip = dest.getAddress();
        return (destip instanceof Inet6Address) &&
                destip.isLinkLocalAddress() &&
               (((Inet6Address) destip).getScopeId() == mInterface.index);
        return (destip instanceof Inet6Address)
               && destip.isLinkLocalAddress()
               && (((Inet6Address) destip).getScopeId() == mInterface.index);
    }

    private void maybeSendRA(InetSocketAddress dest) {
@@ -654,11 +671,11 @@ public class RouterAdvertisementDaemon {
    }

    private final class UnicastResponder extends Thread {
        private final InetSocketAddress solicitor = new InetSocketAddress();
        private final InetSocketAddress mSolicitor = new InetSocketAddress();
        // The recycled buffer for receiving Router Solicitations from clients.
        // If the RS is larger than IPV6_MIN_MTU the packets are truncated.
        // This is fine since currently only byte 0 is examined anyway.
        private final byte mSolication[] = new byte[IPV6_MIN_MTU];
        private final byte[] mSolicitation = new byte[IPV6_MIN_MTU];

        @Override
        public void run() {
@@ -666,9 +683,9 @@ public class RouterAdvertisementDaemon {
                try {
                    // Blocking receive.
                    final int rval = Os.recvfrom(
                            mSocket, mSolication, 0, mSolication.length, 0, solicitor);
                            mSocket, mSolicitation, 0, mSolicitation.length, 0, mSolicitor);
                    // Do the least possible amount of validation.
                    if (rval < 1 || mSolication[0] != ICMPV6_ND_ROUTER_SOLICIT) {
                    if (rval < 1 || mSolicitation[0] != ICMPV6_ND_ROUTER_SOLICIT) {
                        continue;
                    }
                } catch (ErrnoException | SocketException e) {
@@ -678,7 +695,7 @@ public class RouterAdvertisementDaemon {
                    continue;
                }

                maybeSendRA(solicitor);
                maybeSendRA(mSolicitor);
            }
        }
    }
Loading