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

Commit fe5ffce0 authored by Lorenzo Colitti's avatar Lorenzo Colitti
Browse files

DHCP: protocol changes.

1. Define and add parsing code for MTU, max message size, T1, T2.
2. Add common TLVs (message size, hostname, vendor ID) to all
   packets sent by the client.
3. Don't include requested IP and server ID in renew messages,
   since the RFC says MUST NOT.
4. Don't hardcode the broadcast flag to true in DISCOVER packets,
   use what the caller passed in.
5. Make some methods static.

Bug: 19704592
Change-Id: I42a0997e468b12e19cad9b403b98fe266e6cea73
parent 86bff867
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ class DhcpDiscoverPacket extends DhcpPacket {
    public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
        ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
        fillInPacket(encap, INADDR_BROADCAST, INADDR_ANY, destUdp,
                srcUdp, result, DHCP_BOOTREQUEST, true);
                srcUdp, result, DHCP_BOOTREQUEST, mBroadcast);
        result.flip();
        return result;
    }
@@ -52,6 +52,7 @@ class DhcpDiscoverPacket extends DhcpPacket {
     */
    void finishPacket(ByteBuffer buffer) {
        addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_DISCOVER);
        addCommonClientTlvs(buffer);
        addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams);
        addTlvEnd(buffer);
    }
+81 −14
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ import android.system.OsConstants;

import java.net.Inet4Address;
import java.net.UnknownHostException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
@@ -32,8 +33,6 @@ abstract class DhcpPacket {
            (byte) 0xff, (byte) 0xff, (byte) 0xff,
            (byte) 0xff, (byte) 0xff, (byte) 0xff,
    };
    // Minimum length of a DHCP packet w/o options: Ethernet header, IP header, fixed bootp format.
    public static final int MIN_PACKET_LENGTH_L2 = 14 + 20 + 300;

    /**
     * Packet encapsulations.
@@ -128,6 +127,12 @@ abstract class DhcpPacket {
    protected static final byte DHCP_DOMAIN_NAME = 15;
    protected String mDomainName;

    /**
     * DHCP Optional Type: DHCP Interface MTU
     */
    protected static final byte DHCP_MTU = 26;
    protected Short mMtu;

    /**
     * DHCP Optional Type: DHCP BROADCAST ADDRESS
     */
@@ -177,10 +182,23 @@ abstract class DhcpPacket {
    protected static final byte DHCP_MESSAGE = 56;
    protected String mMessage;

    /**
     * DHCP Optional Type: Maximum DHCP Message Size
     */
    protected static final byte DHCP_MAX_MESSAGE_SIZE = 57;
    protected Short mMaxMessageSize;

    /**
     * DHCP Optional Type: DHCP Renewal Time Value
     */
    protected static final byte DHCP_RENEWAL_TIME = 58;
    protected Integer mT1;

    /**
     * DHCP Optional Type: Rebinding Time Value
     */
    protected static final byte DHCP_REBINDING_TIME = 59;
    protected Integer mT2;

    /**
     * DHCP Optional Type: Vendor Class Identifier
@@ -437,7 +455,7 @@ abstract class DhcpPacket {
    /**
     * Adds an optional parameter containing a single byte value.
     */
    protected void addTlv(ByteBuffer buf, byte type, byte value) {
    protected static void addTlv(ByteBuffer buf, byte type, byte value) {
        buf.put(type);
        buf.put((byte) 1);
        buf.put(value);
@@ -446,7 +464,7 @@ abstract class DhcpPacket {
    /**
     * Adds an optional parameter containing an array of bytes.
     */
    protected void addTlv(ByteBuffer buf, byte type, byte[] payload) {
    protected static void addTlv(ByteBuffer buf, byte type, byte[] payload) {
        if (payload != null) {
            buf.put(type);
            buf.put((byte) payload.length);
@@ -457,7 +475,7 @@ abstract class DhcpPacket {
    /**
     * Adds an optional parameter containing an IP address.
     */
    protected void addTlv(ByteBuffer buf, byte type, Inet4Address addr) {
    protected static void addTlv(ByteBuffer buf, byte type, Inet4Address addr) {
        if (addr != null) {
            addTlv(buf, type, addr.getAddress());
        }
@@ -466,7 +484,7 @@ abstract class DhcpPacket {
    /**
     * Adds an optional parameter containing a list of IP addresses.
     */
    protected void addTlv(ByteBuffer buf, byte type, List<Inet4Address> addrs) {
    protected static void addTlv(ByteBuffer buf, byte type, List<Inet4Address> addrs) {
        if (addrs != null && addrs.size() > 0) {
            buf.put(type);
            buf.put((byte)(4 * addrs.size()));
@@ -477,10 +495,21 @@ abstract class DhcpPacket {
        }
    }

    /**
     * Adds an optional parameter containing a short integer
     */
    protected static void addTlv(ByteBuffer buf, byte type, Short value) {
        if (value != null) {
            buf.put(type);
            buf.put((byte) 2);
            buf.putShort(value.shortValue());
        }
    }

    /**
     * Adds an optional parameter containing a simple integer
     */
    protected void addTlv(ByteBuffer buf, byte type, Integer value) {
    protected static void addTlv(ByteBuffer buf, byte type, Integer value) {
        if (value != null) {
            buf.put(type);
            buf.put((byte) 4);
@@ -491,7 +520,7 @@ abstract class DhcpPacket {
    /**
     * Adds an optional parameter containing and ASCII string.
     */
    protected void addTlv(ByteBuffer buf, byte type, String str) {
    protected static void addTlv(ByteBuffer buf, byte type, String str) {
        if (str != null) {
            buf.put(type);
            buf.put((byte) str.length());
@@ -505,10 +534,22 @@ abstract class DhcpPacket {
    /**
     * Adds the special end-of-optional-parameters indicator.
     */
    protected void addTlvEnd(ByteBuffer buf) {
    protected static void addTlvEnd(ByteBuffer buf) {
        buf.put((byte) 0xFF);
    }

    /**
     * Adds common client TLVs.
     *
     * TODO: Does this belong here? The alternative would be to modify all the buildXyzPacket
     * methods to take them.
     */
    protected void addCommonClientTlvs(ByteBuffer buf) {
        addTlv(buf, DHCP_MAX_MESSAGE_SIZE, (short) MAX_LENGTH);
        addTlv(buf, DHCP_VENDOR_CLASS_ID, "android-dhcp-" + Build.VERSION.RELEASE);
        addTlv(buf, DHCP_HOST_NAME, SystemProperties.get("net.hostname"));
    }

    /**
     * Converts a MAC from an array of octets to an ASCII string.
     */
@@ -585,7 +626,6 @@ abstract class DhcpPacket {
        byte[] clientMac;
        List<Inet4Address> dnsServers = new ArrayList<Inet4Address>();
        Inet4Address gateway = null; // aka router
        Integer leaseTime = null;
        Inet4Address serverIdentifier = null;
        Inet4Address netMask = null;
        String message = null;
@@ -598,6 +638,16 @@ abstract class DhcpPacket {
        Inet4Address bcAddr = null;
        Inet4Address requestedIp = null;

        // The following are all unsigned integers. Internally we store them as signed integers of
        // the same length because that way we're guaranteed that they can't be out of the range of
        // the unsigned field in the packet. Callers wanting to pass in an unsigned value will need
        // to cast it.
        Short mtu = null;
        Short maxMessageSize = null;
        Integer leaseTime = null;
        Integer T1 = null;
        Integer T2 = null;

        // dhcp options
        byte dhcpType = (byte) 0xFF;

@@ -605,7 +655,6 @@ abstract class DhcpPacket {

        // check to see if we need to parse L2, IP, and UDP encaps
        if (pktType == ENCAP_L2) {
            // System.out.println("buffer len " + packet.limit());
            byte[] l2dst = new byte[6];
            byte[] l2src = new byte[6];

@@ -618,8 +667,7 @@ abstract class DhcpPacket {
                return null;
        }

        if ((pktType == ENCAP_L2) || (pktType == ENCAP_L3)) {
            // assume l2type is 0x0800, i.e. IP
        if (pktType <= ENCAP_L3) {
            byte ipTypeAndLength = packet.get();
            int ipVersion = (ipTypeAndLength & 0xf0) >> 4;
            if (ipVersion != 4) {
@@ -658,7 +706,6 @@ abstract class DhcpPacket {
                return null;
        }

        // assume bootp
        byte type = packet.get();
        byte hwType = packet.get();
        byte addrLen = packet.get();
@@ -728,6 +775,10 @@ abstract class DhcpPacket {
                        expectedLen = optionLen;
                        hostName = readAsciiString(packet, optionLen);
                        break;
                    case DHCP_MTU:
                        expectedLen = 2;
                        mtu = Short.valueOf(packet.getShort());
                        break;
                    case DHCP_DOMAIN_NAME:
                        expectedLen = optionLen;
                        domainName = readAsciiString(packet, optionLen);
@@ -761,6 +812,18 @@ abstract class DhcpPacket {
                        expectedLen = optionLen;
                        message = readAsciiString(packet, optionLen);
                        break;
                    case DHCP_MAX_MESSAGE_SIZE:
                        expectedLen = 2;
                        maxMessageSize = Short.valueOf(packet.getShort());
                        break;
                    case DHCP_RENEWAL_TIME:
                        expectedLen = 4;
                        T1 = Integer.valueOf(packet.getInt());
                        break;
                    case DHCP_REBINDING_TIME:
                        expectedLen = 4;
                        T2 = Integer.valueOf(packet.getInt());
                        break;
                    case DHCP_VENDOR_CLASS_ID:
                        expectedLen = optionLen;
                        vendorId = readAsciiString(packet, optionLen);
@@ -831,10 +894,14 @@ abstract class DhcpPacket {
        newPacket.mHostName = hostName;
        newPacket.mLeaseTime = leaseTime;
        newPacket.mMessage = message;
        newPacket.mMtu = mtu;
        newPacket.mRequestedIp = requestedIp;
        newPacket.mRequestedParams = expectedParams;
        newPacket.mServerIdentifier = serverIdentifier;
        newPacket.mSubnetMask = netMask;
        newPacket.mMaxMessageSize = maxMessageSize;
        newPacket.mT1 = T1;
        newPacket.mT2 = T2;
        newPacket.mVendorId = vendorId;
        return newPacket;
    }
+8 −3
Original line number Diff line number Diff line
@@ -63,10 +63,15 @@ class DhcpRequestPacket extends DhcpPacket {
        System.arraycopy(mClientMac, 0, clientId, 1, 6);

        addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_REQUEST);
        addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams);
        if (!INADDR_ANY.equals(mRequestedIp)) {
            addTlv(buffer, DHCP_REQUESTED_IP, mRequestedIp);
        }
        if (!INADDR_ANY.equals(mServerIdentifier)) {
            addTlv(buffer, DHCP_SERVER_IDENTIFIER, mServerIdentifier);
        }
        addTlv(buffer, DHCP_CLIENT_IDENTIFIER, clientId);
        addCommonClientTlvs(buffer);
        addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams);
        addTlvEnd(buffer);
    }
}