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

Commit e1aa745f authored by Xiao Ma's avatar Xiao Ma Committed by Gerrit Code Review
Browse files

Merge "Add captive portal info to DhcpClient output"

parents 13fc7dee 2a738929
Loading
Loading
Loading
Loading
+0 −2
Original line number Original line Diff line number Diff line
@@ -23,7 +23,6 @@ import android.os.Build;
import android.os.RemoteException;
import android.os.RemoteException;


import androidx.annotation.NonNull;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;


import org.json.JSONException;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONObject;
@@ -70,7 +69,6 @@ public class CaptivePortalDataShimImpl
                .build());
                .build());
    }
    }


    @VisibleForTesting
    public static boolean isSupported() {
    public static boolean isSupported() {
        return ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q);
        return ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q);
    }
    }
+26 −6
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package android.net.dhcp;
package android.net.dhcp;


import static android.net.dhcp.DhcpPacket.DHCP_BROADCAST_ADDRESS;
import static android.net.dhcp.DhcpPacket.DHCP_BROADCAST_ADDRESS;
import static android.net.dhcp.DhcpPacket.DHCP_CAPTIVE_PORTAL;
import static android.net.dhcp.DhcpPacket.DHCP_DNS_SERVER;
import static android.net.dhcp.DhcpPacket.DHCP_DNS_SERVER;
import static android.net.dhcp.DhcpPacket.DHCP_DOMAIN_NAME;
import static android.net.dhcp.DhcpPacket.DHCP_DOMAIN_NAME;
import static android.net.dhcp.DhcpPacket.DHCP_LEASE_TIME;
import static android.net.dhcp.DhcpPacket.DHCP_LEASE_TIME;
@@ -95,6 +96,7 @@ import com.android.internal.util.StateMachine;
import com.android.internal.util.TrafficStatsConstants;
import com.android.internal.util.TrafficStatsConstants;
import com.android.internal.util.WakeupMessage;
import com.android.internal.util.WakeupMessage;
import com.android.networkstack.R;
import com.android.networkstack.R;
import com.android.networkstack.apishim.CaptivePortalDataShimImpl;
import com.android.networkstack.apishim.SocketUtilsShimImpl;
import com.android.networkstack.apishim.SocketUtilsShimImpl;
import com.android.networkstack.arp.ArpPacket;
import com.android.networkstack.arp.ArpPacket;


@@ -260,8 +262,9 @@ public class DhcpClient extends StateMachine {
    private static final SparseArray<String> sMessageNames =
    private static final SparseArray<String> sMessageNames =
            MessageUtils.findMessageNames(sMessageClasses);
            MessageUtils.findMessageNames(sMessageClasses);


    // DHCP parameters that we request.
    // DHCP parameters that we request by default.
    /* package */ static final byte[] REQUESTED_PARAMS = new byte[] {
    @VisibleForTesting
    /* package */ static final byte[] DEFAULT_REQUESTED_PARAMS = new byte[] {
        DHCP_SUBNET_MASK,
        DHCP_SUBNET_MASK,
        DHCP_ROUTER,
        DHCP_ROUTER,
        DHCP_DNS_SERVER,
        DHCP_DNS_SERVER,
@@ -274,6 +277,21 @@ public class DhcpClient extends StateMachine {
        DHCP_VENDOR_INFO,
        DHCP_VENDOR_INFO,
    };
    };


    @NonNull
    private byte[] getRequestedParams() {
        if (isCapportApiEnabled()) {
            final byte[] params = Arrays.copyOf(DEFAULT_REQUESTED_PARAMS,
                    DEFAULT_REQUESTED_PARAMS.length + 1);
            params[params.length - 1] = DHCP_CAPTIVE_PORTAL;
            return params;
        }
        return DEFAULT_REQUESTED_PARAMS;
    }

    private static boolean isCapportApiEnabled() {
        return CaptivePortalDataShimImpl.isSupported();
    }

    // DHCP flag that means "yes, we support unicast."
    // DHCP flag that means "yes, we support unicast."
    private static final boolean DO_UNICAST   = false;
    private static final boolean DO_UNICAST   = false;


@@ -556,8 +574,10 @@ public class DhcpClient extends StateMachine {
        @Override
        @Override
        protected void handlePacket(byte[] recvbuf, int length) {
        protected void handlePacket(byte[] recvbuf, int length) {
            try {
            try {
                final byte[] optionsToSkip =
                        isCapportApiEnabled() ? new byte[0] : new byte[] { DHCP_CAPTIVE_PORTAL };
                final DhcpPacket packet = DhcpPacket.decodeFullPacket(recvbuf, length,
                final DhcpPacket packet = DhcpPacket.decodeFullPacket(recvbuf, length,
                        DhcpPacket.ENCAP_L2);
                        DhcpPacket.ENCAP_L2, optionsToSkip);
                if (DBG) Log.d(TAG, "Received packet: " + packet);
                if (DBG) Log.d(TAG, "Received packet: " + packet);
                sendMessage(CMD_RECEIVED_PACKET, packet);
                sendMessage(CMD_RECEIVED_PACKET, packet);
            } catch (DhcpPacket.ParseException e) {
            } catch (DhcpPacket.ParseException e) {
@@ -649,7 +669,7 @@ public class DhcpClient extends StateMachine {
    private boolean sendDiscoverPacket() {
    private boolean sendDiscoverPacket() {
        final ByteBuffer packet = DhcpPacket.buildDiscoverPacket(
        final ByteBuffer packet = DhcpPacket.buildDiscoverPacket(
                DhcpPacket.ENCAP_L2, mTransactionId, getSecs(), mHwAddr,
                DhcpPacket.ENCAP_L2, mTransactionId, getSecs(), mHwAddr,
                DO_UNICAST, REQUESTED_PARAMS, isDhcpRapidCommitEnabled(), mHostname);
                DO_UNICAST, getRequestedParams(), isDhcpRapidCommitEnabled(), mHostname);
        return transmitPacket(packet, "DHCPDISCOVER", DhcpPacket.ENCAP_L2, INADDR_BROADCAST);
        return transmitPacket(packet, "DHCPDISCOVER", DhcpPacket.ENCAP_L2, INADDR_BROADCAST);
    }
    }


@@ -663,7 +683,7 @@ public class DhcpClient extends StateMachine {
        final ByteBuffer packet = DhcpPacket.buildRequestPacket(
        final ByteBuffer packet = DhcpPacket.buildRequestPacket(
                encap, mTransactionId, getSecs(), clientAddress,
                encap, mTransactionId, getSecs(), clientAddress,
                DO_UNICAST, mHwAddr, requestedAddress,
                DO_UNICAST, mHwAddr, requestedAddress,
                serverAddress, REQUESTED_PARAMS, mHostname);
                serverAddress, getRequestedParams(), mHostname);
        String serverStr = (serverAddress != null) ? serverAddress.getHostAddress() : null;
        String serverStr = (serverAddress != null) ? serverAddress.getHostAddress() : null;
        String description = "DHCPREQUEST ciaddr=" + clientAddress.getHostAddress() +
        String description = "DHCPREQUEST ciaddr=" + clientAddress.getHostAddress() +
                             " request=" + requestedAddress.getHostAddress() +
                             " request=" + requestedAddress.getHostAddress() +
@@ -1267,7 +1287,7 @@ public class DhcpClient extends StateMachine {
            final Layer2PacketParcelable l2Packet = new Layer2PacketParcelable();
            final Layer2PacketParcelable l2Packet = new Layer2PacketParcelable();
            final ByteBuffer packet = DhcpPacket.buildDiscoverPacket(
            final ByteBuffer packet = DhcpPacket.buildDiscoverPacket(
                    DhcpPacket.ENCAP_L2, mTransactionId, getSecs(), mHwAddr,
                    DhcpPacket.ENCAP_L2, mTransactionId, getSecs(), mHwAddr,
                    DO_UNICAST, REQUESTED_PARAMS, true /* rapid commit */, mHostname);
                    DO_UNICAST, getRequestedParams(), true /* rapid commit */, mHostname);


            l2Packet.dstMacAddress = MacAddress.fromBytes(DhcpPacket.ETHER_BROADCAST);
            l2Packet.dstMacAddress = MacAddress.fromBytes(DhcpPacket.ETHER_BROADCAST);
            l2Packet.payload = Arrays.copyOf(packet.array(), packet.limit());
            l2Packet.payload = Arrays.copyOf(packet.array(), packet.limit());
+52 −12
Original line number Original line Diff line number Diff line
@@ -307,6 +307,10 @@ public abstract class DhcpPacket {
    protected static final byte DHCP_RAPID_COMMIT = 80;
    protected static final byte DHCP_RAPID_COMMIT = 80;
    protected boolean mRapidCommit;
    protected boolean mRapidCommit;


    @VisibleForTesting
    public static final byte DHCP_CAPTIVE_PORTAL = (byte) 114;
    protected String mCaptivePortalUrl;

    /**
    /**
     * DHCP zero-length option code: pad
     * DHCP zero-length option code: pad
     */
     */
@@ -785,6 +789,7 @@ public abstract class DhcpPacket {
        if (mMtu != null && Short.toUnsignedInt(mMtu) >= IPV4_MIN_MTU) {
        if (mMtu != null && Short.toUnsignedInt(mMtu) >= IPV4_MIN_MTU) {
            addTlv(buf, DHCP_MTU, mMtu);
            addTlv(buf, DHCP_MTU, mMtu);
        }
        }
        addTlv(buf, DHCP_CAPTIVE_PORTAL, mCaptivePortalUrl);
    }
    }


    /**
    /**
@@ -871,6 +876,23 @@ public abstract class DhcpPacket {
        }
        }
    }
    }


    private static int skipOption(ByteBuffer packet, int optionLen)
            throws BufferUnderflowException {
        int expectedLen = 0;
        for (int i = 0; i < optionLen; i++) {
            expectedLen++;
            packet.get();
        }
        return expectedLen;
    }

    private static boolean shouldSkipOption(byte optionType, byte[] optionsToSkip) {
        for (byte option : optionsToSkip) {
            if (option == optionType) return true;
        }
        return false;
    }

    /**
    /**
     * Creates a concrete DhcpPacket from the supplied ByteBuffer.  The
     * Creates a concrete DhcpPacket from the supplied ByteBuffer.  The
     * buffer may have an L2 encapsulation (which is the full EthernetII
     * buffer may have an L2 encapsulation (which is the full EthernetII
@@ -881,8 +903,8 @@ public abstract class DhcpPacket {
     * in object fields.
     * in object fields.
     */
     */
    @VisibleForTesting
    @VisibleForTesting
    static DhcpPacket decodeFullPacket(ByteBuffer packet, int pktType) throws ParseException
    static DhcpPacket decodeFullPacket(ByteBuffer packet, int pktType, byte[] optionsToSkip)
    {
            throws ParseException {
        // bootp parameters
        // bootp parameters
        int transactionId;
        int transactionId;
        short secs;
        short secs;
@@ -900,6 +922,7 @@ public abstract class DhcpPacket {
        String vendorId = null;
        String vendorId = null;
        String vendorInfo = null;
        String vendorInfo = null;
        boolean rapidCommit = false;
        boolean rapidCommit = false;
        String captivePortalUrl = null;
        byte[] expectedParams = null;
        byte[] expectedParams = null;
        String hostName = null;
        String hostName = null;
        String domainName = null;
        String domainName = null;
@@ -1080,6 +1103,11 @@ public abstract class DhcpPacket {
                    int optionLen = packet.get() & 0xFF;
                    int optionLen = packet.get() & 0xFF;
                    int expectedLen = 0;
                    int expectedLen = 0;


                    if (shouldSkipOption(optionType, optionsToSkip)) {
                        skipOption(packet, optionLen);
                        continue;
                    }

                    switch(optionType) {
                    switch(optionType) {
                        case DHCP_SUBNET_MASK:
                        case DHCP_SUBNET_MASK:
                            netMask = readIpAddress(packet);
                            netMask = readIpAddress(packet);
@@ -1172,12 +1200,12 @@ public abstract class DhcpPacket {
                            expectedLen = 0;
                            expectedLen = 0;
                            rapidCommit = true;
                            rapidCommit = true;
                            break;
                            break;
                        case DHCP_CAPTIVE_PORTAL:
                            expectedLen = optionLen;
                            captivePortalUrl = readAsciiString(packet, optionLen, true);
                            break;
                        default:
                        default:
                            // ignore any other parameters
                            expectedLen = skipOption(packet, optionLen);
                            for (int i = 0; i < optionLen; i++) {
                                expectedLen++;
                                byte throwaway = packet.get();
                            }
                    }
                    }


                    if (expectedLen != optionLen) {
                    if (expectedLen != optionLen) {
@@ -1263,6 +1291,7 @@ public abstract class DhcpPacket {
        newPacket.mT2 = T2;
        newPacket.mT2 = T2;
        newPacket.mVendorId = vendorId;
        newPacket.mVendorId = vendorId;
        newPacket.mVendorInfo = vendorInfo;
        newPacket.mVendorInfo = vendorInfo;
        newPacket.mCaptivePortalUrl = captivePortalUrl;
        if ((optionOverload & OPTION_OVERLOAD_SNAME) == 0) {
        if ((optionOverload & OPTION_OVERLOAD_SNAME) == 0) {
            newPacket.mServerHostName = serverHostName;
            newPacket.mServerHostName = serverHostName;
        } else {
        } else {
@@ -1274,11 +1303,11 @@ public abstract class DhcpPacket {
    /**
    /**
     * Parse a packet from an array of bytes, stopping at the given length.
     * Parse a packet from an array of bytes, stopping at the given length.
     */
     */
    public static DhcpPacket decodeFullPacket(byte[] packet, int length, int pktType)
    public static DhcpPacket decodeFullPacket(byte[] packet, int length, int pktType,
            throws ParseException {
            byte[] optionsToSkip) throws ParseException {
        ByteBuffer buffer = ByteBuffer.wrap(packet, 0, length).order(ByteOrder.BIG_ENDIAN);
        ByteBuffer buffer = ByteBuffer.wrap(packet, 0, length).order(ByteOrder.BIG_ENDIAN);
        try {
        try {
            return decodeFullPacket(buffer, pktType);
            return decodeFullPacket(buffer, pktType, optionsToSkip);
        } catch (ParseException e) {
        } catch (ParseException e) {
            throw e;
            throw e;
        } catch (Exception e) {
        } catch (Exception e) {
@@ -1286,6 +1315,14 @@ public abstract class DhcpPacket {
        }
        }
    }
    }


    /**
     * Parse a packet from an array of bytes, stopping at the given length.
     */
    public static DhcpPacket decodeFullPacket(byte[] packet, int length, int pktType)
            throws ParseException {
        return decodeFullPacket(packet, length, pktType, new byte[0]);
    }

    /**
    /**
     *  Construct a DhcpResults object from a DHCP reply packet.
     *  Construct a DhcpResults object from a DHCP reply packet.
     */
     */
@@ -1328,6 +1365,7 @@ public abstract class DhcpPacket {
        results.leaseDuration = (mLeaseTime != null) ? mLeaseTime : INFINITE_LEASE;
        results.leaseDuration = (mLeaseTime != null) ? mLeaseTime : INFINITE_LEASE;
        results.mtu = (mMtu != null && MIN_MTU <= mMtu && mMtu <= MAX_MTU) ? mMtu : 0;
        results.mtu = (mMtu != null && MIN_MTU <= mMtu && mMtu <= MAX_MTU) ? mMtu : 0;
        results.serverHostName = mServerHostName;
        results.serverHostName = mServerHostName;
        results.captivePortalApiUrl = mCaptivePortalUrl;


        return results;
        return results;
    }
    }
@@ -1369,7 +1407,7 @@ public abstract class DhcpPacket {
            Inet4Address yourIp, byte[] mac, Integer timeout, Inet4Address netMask,
            Inet4Address yourIp, byte[] mac, Integer timeout, Inet4Address netMask,
            Inet4Address bcAddr, List<Inet4Address> gateways, List<Inet4Address> dnsServers,
            Inet4Address bcAddr, List<Inet4Address> gateways, List<Inet4Address> dnsServers,
            Inet4Address dhcpServerIdentifier, String domainName, String hostname, boolean metered,
            Inet4Address dhcpServerIdentifier, String domainName, String hostname, boolean metered,
            short mtu) {
            short mtu, String captivePortalUrl) {
        DhcpPacket pkt = new DhcpOfferPacket(
        DhcpPacket pkt = new DhcpOfferPacket(
                transactionId, (short) 0, broadcast, serverIpAddr, relayIp,
                transactionId, (short) 0, broadcast, serverIpAddr, relayIp,
                INADDR_ANY /* clientIp */, yourIp, mac);
                INADDR_ANY /* clientIp */, yourIp, mac);
@@ -1382,6 +1420,7 @@ public abstract class DhcpPacket {
        pkt.mSubnetMask = netMask;
        pkt.mSubnetMask = netMask;
        pkt.mBroadcastAddress = bcAddr;
        pkt.mBroadcastAddress = bcAddr;
        pkt.mMtu = mtu;
        pkt.mMtu = mtu;
        pkt.mCaptivePortalUrl = captivePortalUrl;
        if (metered) {
        if (metered) {
            pkt.mVendorInfo = VENDOR_INFO_ANDROID_METERED;
            pkt.mVendorInfo = VENDOR_INFO_ANDROID_METERED;
        }
        }
@@ -1396,7 +1435,7 @@ public abstract class DhcpPacket {
            Inet4Address requestClientIp, byte[] mac, Integer timeout, Inet4Address netMask,
            Inet4Address requestClientIp, byte[] mac, Integer timeout, Inet4Address netMask,
            Inet4Address bcAddr, List<Inet4Address> gateways, List<Inet4Address> dnsServers,
            Inet4Address bcAddr, List<Inet4Address> gateways, List<Inet4Address> dnsServers,
            Inet4Address dhcpServerIdentifier, String domainName, String hostname, boolean metered,
            Inet4Address dhcpServerIdentifier, String domainName, String hostname, boolean metered,
            short mtu, boolean rapidCommit) {
            short mtu, boolean rapidCommit, String captivePortalUrl) {
        DhcpPacket pkt = new DhcpAckPacket(
        DhcpPacket pkt = new DhcpAckPacket(
                transactionId, (short) 0, broadcast, serverIpAddr, relayIp, requestClientIp, yourIp,
                transactionId, (short) 0, broadcast, serverIpAddr, relayIp, requestClientIp, yourIp,
                mac, rapidCommit);
                mac, rapidCommit);
@@ -1409,6 +1448,7 @@ public abstract class DhcpPacket {
        pkt.mServerIdentifier = dhcpServerIdentifier;
        pkt.mServerIdentifier = dhcpServerIdentifier;
        pkt.mBroadcastAddress = bcAddr;
        pkt.mBroadcastAddress = bcAddr;
        pkt.mMtu = mtu;
        pkt.mMtu = mtu;
        pkt.mCaptivePortalUrl = captivePortalUrl;
        if (metered) {
        if (metered) {
            pkt.mVendorInfo = VENDOR_INFO_ANDROID_METERED;
            pkt.mVendorInfo = VENDOR_INFO_ANDROID_METERED;
        }
        }
+5 −2
Original line number Original line Diff line number Diff line
@@ -529,7 +529,9 @@ public class DhcpServer extends IDhcpServer.Stub {
                broadcastAddr, new ArrayList<>(mServingParams.defaultRouters),
                broadcastAddr, new ArrayList<>(mServingParams.defaultRouters),
                new ArrayList<>(mServingParams.dnsServers),
                new ArrayList<>(mServingParams.dnsServers),
                mServingParams.getServerInet4Addr(), null /* domainName */, hostname,
                mServingParams.getServerInet4Addr(), null /* domainName */, hostname,
                mServingParams.metered, (short) mServingParams.linkMtu);
                mServingParams.metered, (short) mServingParams.linkMtu,
                // TODO (b/144402437): advertise the URL if known
                null /* captivePortalApiUrl */);


        return transmitOfferOrAckPacket(offerPacket, request, lease, clientMac, broadcastFlag);
        return transmitOfferOrAckPacket(offerPacket, request, lease, clientMac, broadcastFlag);
    }
    }
@@ -549,7 +551,8 @@ public class DhcpServer extends IDhcpServer.Stub {
                new ArrayList<>(mServingParams.dnsServers),
                new ArrayList<>(mServingParams.dnsServers),
                mServingParams.getServerInet4Addr(), null /* domainName */, hostname,
                mServingParams.getServerInet4Addr(), null /* domainName */, hostname,
                mServingParams.metered, (short) mServingParams.linkMtu,
                mServingParams.metered, (short) mServingParams.linkMtu,
                packet.mRapidCommit && mDhcpRapidCommitEnabled);
                // TODO (b/144402437): advertise the URL if known
                packet.mRapidCommit && mDhcpRapidCommitEnabled, null /* captivePortalApiUrl */);


        return transmitOfferOrAckPacket(ackPacket, packet, lease, clientMac, broadcastFlag);
        return transmitOfferOrAckPacket(ackPacket, packet, lease, clientMac, broadcastFlag);
    }
    }
+11 −0
Original line number Original line Diff line number Diff line
@@ -36,6 +36,7 @@ import android.net.ProvisioningConfigurationParcelable;
import android.net.ProxyInfo;
import android.net.ProxyInfo;
import android.net.RouteInfo;
import android.net.RouteInfo;
import android.net.TcpKeepalivePacketDataParcelable;
import android.net.TcpKeepalivePacketDataParcelable;
import android.net.Uri;
import android.net.apf.ApfCapabilities;
import android.net.apf.ApfCapabilities;
import android.net.apf.ApfFilter;
import android.net.apf.ApfFilter;
import android.net.dhcp.DhcpClient;
import android.net.dhcp.DhcpClient;
@@ -57,6 +58,7 @@ import android.text.TextUtils;
import android.util.LocalLog;
import android.util.LocalLog;
import android.util.Log;
import android.util.Log;
import android.util.Pair;
import android.util.Pair;
import android.util.Patterns;
import android.util.SparseArray;
import android.util.SparseArray;


import androidx.annotation.NonNull;
import androidx.annotation.NonNull;
@@ -1192,6 +1194,15 @@ public class IpClient extends StateMachine {
            if (mDhcpResults.mtu != 0) {
            if (mDhcpResults.mtu != 0) {
                newLp.setMtu(mDhcpResults.mtu);
                newLp.setMtu(mDhcpResults.mtu);
            }
            }

            final String capportUrl = mDhcpResults.captivePortalApiUrl;
            // Uri.parse does no syntax check; do a simple regex check to eliminate garbage.
            // If the URL is still incorrect data fetching will fail later, which is fine.
            if (capportUrl != null && Patterns.WEB_URL.matcher(capportUrl).matches()) {
                NetworkInformationShimImpl.newInstance()
                        .setCaptivePortalApiUrl(newLp, Uri.parse(capportUrl));
            }
            // TODO: also look at the IPv6 RA (netlink) for captive portal URL
        }
        }


        // [4] Add in TCP buffer sizes and HTTP Proxy config, if available.
        // [4] Add in TCP buffer sizes and HTTP Proxy config, if available.
Loading