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

Commit d4775347 authored by Automerger Merge Worker's avatar Automerger Merge Worker
Browse files

Merge "Add captive portal info to DhcpClient output" am: e1aa745f

Change-Id: I8b07f3810a9065bca94a831d0edb8540dde72028
parents 46f21971 e1aa745f
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import android.os.Build;
import android.os.RemoteException;

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

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

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

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_DOMAIN_NAME;
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.WakeupMessage;
import com.android.networkstack.R;
import com.android.networkstack.apishim.CaptivePortalDataShimImpl;
import com.android.networkstack.apishim.SocketUtilsShimImpl;
import com.android.networkstack.arp.ArpPacket;

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

    // DHCP parameters that we request.
    /* package */ static final byte[] REQUESTED_PARAMS = new byte[] {
    // DHCP parameters that we request by default.
    @VisibleForTesting
    /* package */ static final byte[] DEFAULT_REQUESTED_PARAMS = new byte[] {
        DHCP_SUBNET_MASK,
        DHCP_ROUTER,
        DHCP_DNS_SERVER,
@@ -274,6 +277,21 @@ public class DhcpClient extends StateMachine {
        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."
    private static final boolean DO_UNICAST   = false;

@@ -556,8 +574,10 @@ public class DhcpClient extends StateMachine {
        @Override
        protected void handlePacket(byte[] recvbuf, int length) {
            try {
                final byte[] optionsToSkip =
                        isCapportApiEnabled() ? new byte[0] : new byte[] { DHCP_CAPTIVE_PORTAL };
                final DhcpPacket packet = DhcpPacket.decodeFullPacket(recvbuf, length,
                        DhcpPacket.ENCAP_L2);
                        DhcpPacket.ENCAP_L2, optionsToSkip);
                if (DBG) Log.d(TAG, "Received packet: " + packet);
                sendMessage(CMD_RECEIVED_PACKET, packet);
            } catch (DhcpPacket.ParseException e) {
@@ -649,7 +669,7 @@ public class DhcpClient extends StateMachine {
    private boolean sendDiscoverPacket() {
        final ByteBuffer packet = DhcpPacket.buildDiscoverPacket(
                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);
    }

@@ -663,7 +683,7 @@ public class DhcpClient extends StateMachine {
        final ByteBuffer packet = DhcpPacket.buildRequestPacket(
                encap, mTransactionId, getSecs(), clientAddress,
                DO_UNICAST, mHwAddr, requestedAddress,
                serverAddress, REQUESTED_PARAMS, mHostname);
                serverAddress, getRequestedParams(), mHostname);
        String serverStr = (serverAddress != null) ? serverAddress.getHostAddress() : null;
        String description = "DHCPREQUEST ciaddr=" + clientAddress.getHostAddress() +
                             " request=" + requestedAddress.getHostAddress() +
@@ -1267,7 +1287,7 @@ public class DhcpClient extends StateMachine {
            final Layer2PacketParcelable l2Packet = new Layer2PacketParcelable();
            final ByteBuffer packet = DhcpPacket.buildDiscoverPacket(
                    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.payload = Arrays.copyOf(packet.array(), packet.limit());
+52 −12
Original line number Diff line number Diff line
@@ -307,6 +307,10 @@ public abstract class DhcpPacket {
    protected static final byte DHCP_RAPID_COMMIT = 80;
    protected boolean mRapidCommit;

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

    /**
     * DHCP zero-length option code: pad
     */
@@ -785,6 +789,7 @@ public abstract class DhcpPacket {
        if (mMtu != null && Short.toUnsignedInt(mMtu) >= IPV4_MIN_MTU) {
            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
     * buffer may have an L2 encapsulation (which is the full EthernetII
@@ -881,8 +903,8 @@ public abstract class DhcpPacket {
     * in object fields.
     */
    @VisibleForTesting
    static DhcpPacket decodeFullPacket(ByteBuffer packet, int pktType) throws ParseException
    {
    static DhcpPacket decodeFullPacket(ByteBuffer packet, int pktType, byte[] optionsToSkip)
            throws ParseException {
        // bootp parameters
        int transactionId;
        short secs;
@@ -900,6 +922,7 @@ public abstract class DhcpPacket {
        String vendorId = null;
        String vendorInfo = null;
        boolean rapidCommit = false;
        String captivePortalUrl = null;
        byte[] expectedParams = null;
        String hostName = null;
        String domainName = null;
@@ -1080,6 +1103,11 @@ public abstract class DhcpPacket {
                    int optionLen = packet.get() & 0xFF;
                    int expectedLen = 0;

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

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

                    if (expectedLen != optionLen) {
@@ -1263,6 +1291,7 @@ public abstract class DhcpPacket {
        newPacket.mT2 = T2;
        newPacket.mVendorId = vendorId;
        newPacket.mVendorInfo = vendorInfo;
        newPacket.mCaptivePortalUrl = captivePortalUrl;
        if ((optionOverload & OPTION_OVERLOAD_SNAME) == 0) {
            newPacket.mServerHostName = serverHostName;
        } else {
@@ -1274,11 +1303,11 @@ 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 {
    public static DhcpPacket decodeFullPacket(byte[] packet, int length, int pktType,
            byte[] optionsToSkip) throws ParseException {
        ByteBuffer buffer = ByteBuffer.wrap(packet, 0, length).order(ByteOrder.BIG_ENDIAN);
        try {
            return decodeFullPacket(buffer, pktType);
            return decodeFullPacket(buffer, pktType, optionsToSkip);
        } catch (ParseException e) {
            throw 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.
     */
@@ -1328,6 +1365,7 @@ public abstract class DhcpPacket {
        results.leaseDuration = (mLeaseTime != null) ? mLeaseTime : INFINITE_LEASE;
        results.mtu = (mMtu != null && MIN_MTU <= mMtu && mMtu <= MAX_MTU) ? mMtu : 0;
        results.serverHostName = mServerHostName;
        results.captivePortalApiUrl = mCaptivePortalUrl;

        return results;
    }
@@ -1369,7 +1407,7 @@ public abstract class DhcpPacket {
            Inet4Address yourIp, byte[] mac, Integer timeout, Inet4Address netMask,
            Inet4Address bcAddr, List<Inet4Address> gateways, List<Inet4Address> dnsServers,
            Inet4Address dhcpServerIdentifier, String domainName, String hostname, boolean metered,
            short mtu) {
            short mtu, String captivePortalUrl) {
        DhcpPacket pkt = new DhcpOfferPacket(
                transactionId, (short) 0, broadcast, serverIpAddr, relayIp,
                INADDR_ANY /* clientIp */, yourIp, mac);
@@ -1382,6 +1420,7 @@ public abstract class DhcpPacket {
        pkt.mSubnetMask = netMask;
        pkt.mBroadcastAddress = bcAddr;
        pkt.mMtu = mtu;
        pkt.mCaptivePortalUrl = captivePortalUrl;
        if (metered) {
            pkt.mVendorInfo = VENDOR_INFO_ANDROID_METERED;
        }
@@ -1396,7 +1435,7 @@ public abstract class DhcpPacket {
            Inet4Address requestClientIp, byte[] mac, Integer timeout, Inet4Address netMask,
            Inet4Address bcAddr, List<Inet4Address> gateways, List<Inet4Address> dnsServers,
            Inet4Address dhcpServerIdentifier, String domainName, String hostname, boolean metered,
            short mtu, boolean rapidCommit) {
            short mtu, boolean rapidCommit, String captivePortalUrl) {
        DhcpPacket pkt = new DhcpAckPacket(
                transactionId, (short) 0, broadcast, serverIpAddr, relayIp, requestClientIp, yourIp,
                mac, rapidCommit);
@@ -1409,6 +1448,7 @@ public abstract class DhcpPacket {
        pkt.mServerIdentifier = dhcpServerIdentifier;
        pkt.mBroadcastAddress = bcAddr;
        pkt.mMtu = mtu;
        pkt.mCaptivePortalUrl = captivePortalUrl;
        if (metered) {
            pkt.mVendorInfo = VENDOR_INFO_ANDROID_METERED;
        }
+5 −2
Original line number Diff line number Diff line
@@ -529,7 +529,9 @@ public class DhcpServer extends IDhcpServer.Stub {
                broadcastAddr, new ArrayList<>(mServingParams.defaultRouters),
                new ArrayList<>(mServingParams.dnsServers),
                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);
    }
@@ -549,7 +551,8 @@ public class DhcpServer extends IDhcpServer.Stub {
                new ArrayList<>(mServingParams.dnsServers),
                mServingParams.getServerInet4Addr(), null /* domainName */, hostname,
                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);
    }
+11 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.net.ProvisioningConfigurationParcelable;
import android.net.ProxyInfo;
import android.net.RouteInfo;
import android.net.TcpKeepalivePacketDataParcelable;
import android.net.Uri;
import android.net.apf.ApfCapabilities;
import android.net.apf.ApfFilter;
import android.net.dhcp.DhcpClient;
@@ -57,6 +58,7 @@ import android.text.TextUtils;
import android.util.LocalLog;
import android.util.Log;
import android.util.Pair;
import android.util.Patterns;
import android.util.SparseArray;

import androidx.annotation.NonNull;
@@ -1192,6 +1194,15 @@ public class IpClient extends StateMachine {
            if (mDhcpResults.mtu != 0) {
                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.
Loading