FileDocCategorySizeDatePackage
DhcpPacket.javaAPI DocAndroid 5.1 API30293Thu Mar 12 22:22:10 GMT 2015android.net.dhcp

DhcpPacket

public abstract class DhcpPacket extends Object
Defines basic data and operations needed to build and use packets for the DHCP protocol. Subclasses create the specific packets used at each stage of the negotiation.

Fields Summary
protected static final String
TAG
public static final int
ENCAP_L2
Packet encapsulations.
public static final int
ENCAP_L3
public static final int
ENCAP_BOOTP
private static final byte
IP_TYPE_UDP
IP layer definitions.
private static final byte
IP_VERSION_HEADER_LEN
IP: Version 4, Header Length 20 bytes
private static final short
IP_FLAGS_OFFSET
IP: Flags 0, Fragment Offset 0, Don't Fragment
private static final byte
IP_TOS_LOWDELAY
IP: TOS
private static final byte
IP_TTL
IP: TTL -- use default 64 from RFC1340
static final short
DHCP_CLIENT
The client DHCP port.
static final short
DHCP_SERVER
The server DHCP port.
protected static final byte
DHCP_BOOTREQUEST
The message op code indicating a request from a client.
protected static final byte
DHCP_BOOTREPLY
The message op code indicating a response from the server.
protected static final byte
CLIENT_ID_ETHER
The code type used to identify an Ethernet MAC address in the Client-ID field.
protected static final int
MAX_LENGTH
The maximum length of a packet that can be constructed.
protected static final byte
DHCP_SUBNET_MASK
DHCP Optional Type: DHCP Subnet Mask
protected InetAddress
mSubnetMask
protected static final byte
DHCP_ROUTER
DHCP Optional Type: DHCP Router
protected InetAddress
mGateway
protected static final byte
DHCP_DNS_SERVER
DHCP Optional Type: DHCP DNS Server
protected List
mDnsServers
protected static final byte
DHCP_HOST_NAME
DHCP Optional Type: DHCP Host Name
protected String
mHostName
protected static final byte
DHCP_DOMAIN_NAME
DHCP Optional Type: DHCP DOMAIN NAME
protected String
mDomainName
protected static final byte
DHCP_BROADCAST_ADDRESS
DHCP Optional Type: DHCP BROADCAST ADDRESS
protected InetAddress
mBroadcastAddress
protected static final byte
DHCP_REQUESTED_IP
DHCP Optional Type: DHCP Requested IP Address
protected InetAddress
mRequestedIp
protected static final byte
DHCP_LEASE_TIME
DHCP Optional Type: DHCP Lease Time
protected Integer
mLeaseTime
protected static final byte
DHCP_MESSAGE_TYPE
DHCP Optional Type: DHCP Message Type
protected static final byte
DHCP_MESSAGE_TYPE_DISCOVER
protected static final byte
DHCP_MESSAGE_TYPE_OFFER
protected static final byte
DHCP_MESSAGE_TYPE_REQUEST
protected static final byte
DHCP_MESSAGE_TYPE_DECLINE
protected static final byte
DHCP_MESSAGE_TYPE_ACK
protected static final byte
DHCP_MESSAGE_TYPE_NAK
protected static final byte
DHCP_MESSAGE_TYPE_INFORM
protected static final byte
DHCP_SERVER_IDENTIFIER
DHCP Optional Type: DHCP Server Identifier
protected InetAddress
mServerIdentifier
protected static final byte
DHCP_PARAMETER_LIST
DHCP Optional Type: DHCP Parameter List
protected byte[]
mRequestedParams
protected static final byte
DHCP_MESSAGE
DHCP Optional Type: DHCP MESSAGE
protected String
mMessage
protected static final byte
DHCP_RENEWAL_TIME
DHCP Optional Type: DHCP Renewal Time Value
protected static final byte
DHCP_VENDOR_CLASS_ID
DHCP Optional Type: Vendor Class Identifier
protected static final byte
DHCP_CLIENT_IDENTIFIER
DHCP Optional Type: DHCP Client Identifier
protected final int
mTransId
The transaction identifier used in this particular DHCP negotiation
protected final InetAddress
mClientIp
The IP address of the client host. This address is typically proposed by the client (from an earlier DHCP negotiation) or supplied by the server.
protected final InetAddress
mYourIp
private final InetAddress
mNextIp
private final InetAddress
mRelayIp
protected boolean
mBroadcast
Does the client request a broadcast response?
protected final byte[]
mClientMac
The six-octet MAC of the client.
Constructors Summary
protected DhcpPacket(int transId, InetAddress clientIp, InetAddress yourIp, InetAddress nextIp, InetAddress relayIp, byte[] clientMac, boolean broadcast)


                                 
        

                       
          
         

                           
       

          
                            
                             
        mTransId = transId;
        mClientIp = clientIp;
        mYourIp = yourIp;
        mNextIp = nextIp;
        mRelayIp = relayIp;
        mClientMac = clientMac;
        mBroadcast = broadcast;
    
Methods Summary
protected voidaddTlv(java.nio.ByteBuffer buf, byte type, byte[] payload)
Adds an optional parameter containing an array of bytes.

        if (payload != null) {
            buf.put(type);
            buf.put((byte) payload.length);
            buf.put(payload);
        }
    
protected voidaddTlv(java.nio.ByteBuffer buf, byte type, java.net.InetAddress addr)
Adds an optional parameter containing an IP address.

        if (addr != null) {
            addTlv(buf, type, addr.getAddress());
        }
    
protected voidaddTlv(java.nio.ByteBuffer buf, byte type, java.util.List addrs)
Adds an optional parameter containing a list of IP addresses.

        if (addrs != null && addrs.size() > 0) {
            buf.put(type);
            buf.put((byte)(4 * addrs.size()));

            for (InetAddress addr : addrs) {
                buf.put(addr.getAddress());
            }
        }
    
protected voidaddTlv(java.nio.ByteBuffer buf, byte type, java.lang.Integer value)
Adds an optional parameter containing a simple integer

        if (value != null) {
            buf.put(type);
            buf.put((byte) 4);
            buf.putInt(value.intValue());
        }
    
protected voidaddTlv(java.nio.ByteBuffer buf, byte type, java.lang.String str)
Adds an optional parameter containing and ASCII string.

        if (str != null) {
            buf.put(type);
            buf.put((byte) str.length());

            for (int i = 0; i < str.length(); i++) {
                buf.put((byte) str.charAt(i));
            }
        }
    
protected voidaddTlv(java.nio.ByteBuffer buf, byte type, byte value)
Adds an optional parameter containing a single byte value.

        buf.put(type);
        buf.put((byte) 1);
        buf.put(value);
    
protected voidaddTlvEnd(java.nio.ByteBuffer buf)
Adds the special end-of-optional-parameters indicator.

        buf.put((byte) 0xFF);
    
public static java.nio.ByteBufferbuildAckPacket(int encap, int transactionId, boolean broadcast, java.net.InetAddress serverIpAddr, java.net.InetAddress clientIpAddr, byte[] mac, java.lang.Integer timeout, java.net.InetAddress netMask, java.net.InetAddress bcAddr, java.net.InetAddress gateway, java.util.List dnsServers, java.net.InetAddress dhcpServerIdentifier, java.lang.String domainName)
Builds a DHCP-ACK packet from the required specified parameters.

        DhcpPacket pkt = new DhcpAckPacket(
            transactionId, broadcast, serverIpAddr, clientIpAddr, mac);
        pkt.mGateway = gateway;
        pkt.mDnsServers = dnsServers;
        pkt.mLeaseTime = timeout;
        pkt.mDomainName = domainName;
        pkt.mSubnetMask = netMask;
        pkt.mServerIdentifier = dhcpServerIdentifier;
        pkt.mBroadcastAddress = bcAddr;
        return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER);
    
public static java.nio.ByteBufferbuildDiscoverPacket(int encap, int transactionId, byte[] clientMac, boolean broadcast, byte[] expectedParams)
Builds a DHCP-DISCOVER packet from the required specified parameters.

        DhcpPacket pkt = new DhcpDiscoverPacket(
            transactionId, clientMac, broadcast);
        pkt.mRequestedParams = expectedParams;
        return pkt.buildPacket(encap, DHCP_SERVER, DHCP_CLIENT);
    
public static java.nio.ByteBufferbuildNakPacket(int encap, int transactionId, java.net.InetAddress serverIpAddr, java.net.InetAddress clientIpAddr, byte[] mac)
Builds a DHCP-NAK packet from the required specified parameters.

        DhcpPacket pkt = new DhcpNakPacket(transactionId, clientIpAddr,
            serverIpAddr, serverIpAddr, serverIpAddr, mac);
        pkt.mMessage = "requested address not available";
        pkt.mRequestedIp = clientIpAddr;
        return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER);
    
public static java.nio.ByteBufferbuildOfferPacket(int encap, int transactionId, boolean broadcast, java.net.InetAddress serverIpAddr, java.net.InetAddress clientIpAddr, byte[] mac, java.lang.Integer timeout, java.net.InetAddress netMask, java.net.InetAddress bcAddr, java.net.InetAddress gateway, java.util.List dnsServers, java.net.InetAddress dhcpServerIdentifier, java.lang.String domainName)
Builds a DHCP-OFFER packet from the required specified parameters.

        DhcpPacket pkt = new DhcpOfferPacket(
            transactionId, broadcast, serverIpAddr, clientIpAddr, mac);
        pkt.mGateway = gateway;
        pkt.mDnsServers = dnsServers;
        pkt.mLeaseTime = timeout;
        pkt.mDomainName = domainName;
        pkt.mServerIdentifier = dhcpServerIdentifier;
        pkt.mSubnetMask = netMask;
        pkt.mBroadcastAddress = bcAddr;
        return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER);
    
public abstract java.nio.ByteBufferbuildPacket(int encap, short destUdp, short srcUdp)
Asks the packet object to create a ByteBuffer serialization of the packet for transmission.

public static java.nio.ByteBufferbuildRequestPacket(int encap, int transactionId, java.net.InetAddress clientIp, boolean broadcast, byte[] clientMac, java.net.InetAddress requestedIpAddress, java.net.InetAddress serverIdentifier, byte[] requestedParams, java.lang.String hostName)
Builds a DHCP-REQUEST packet from the required specified parameters.

        DhcpPacket pkt = new DhcpRequestPacket(transactionId, clientIp,
            clientMac, broadcast);
        pkt.mRequestedIp = requestedIpAddress;
        pkt.mServerIdentifier = serverIdentifier;
        pkt.mHostName = hostName;
        pkt.mRequestedParams = requestedParams;
        ByteBuffer result = pkt.buildPacket(encap, DHCP_SERVER, DHCP_CLIENT);
        return result;
    
private intchecksum(java.nio.ByteBuffer buf, int seed, int start, int end)
Performs an IP checksum (used in IP header and across UDP payload) on the specified portion of a ByteBuffer. The seed allows the checksum to commence with a specified value.

        int sum = seed;
        int bufPosition = buf.position();

        // set position of original ByteBuffer, so that the ShortBuffer
        // will be correctly initialized
        buf.position(start);
        ShortBuffer shortBuf = buf.asShortBuffer();

        // re-set ByteBuffer position
        buf.position(bufPosition);

        short[] shortArray = new short[(end - start) / 2];
        shortBuf.get(shortArray);

        for (short s : shortArray) {
            sum += intAbs(s);
        }

        start += shortArray.length * 2;

        // see if a singleton byte remains
        if (end != start) {
            short b = buf.get(start);

            // make it unsigned
            if (b < 0) {
                b += 256;
            }

            sum += b * 256;
        }

        sum = ((sum >> 16) & 0xFFFF) + (sum & 0xFFFF);
        sum = ((sum + ((sum >> 16) & 0xFFFF)) & 0xFFFF);
        int negated = ~sum;
        return intAbs((short) negated);
    
public static android.net.dhcp.DhcpPacketdecodeFullPacket(java.nio.ByteBuffer packet, int pktType)
Creates a concrete DhcpPacket from the supplied ByteBuffer. The buffer may have an L2 encapsulation (which is the full EthernetII format starting with the source-address MAC) or an L3 encapsulation (which starts with the IP header).
A subset of the optional parameters are parsed and are stored in object fields.

        // bootp parameters
        int transactionId;
        InetAddress clientIp;
        InetAddress yourIp;
        InetAddress nextIp;
        InetAddress relayIp;
        byte[] clientMac;
        List<InetAddress> dnsServers = new ArrayList<InetAddress>();
        InetAddress gateway = null; // aka router
        Integer leaseTime = null;
        InetAddress serverIdentifier = null;
        InetAddress netMask = null;
        String message = null;
        String vendorId = null;
        byte[] expectedParams = null;
        String hostName = null;
        String domainName = null;
        InetAddress ipSrc = null;
        InetAddress ipDst = null;
        InetAddress bcAddr = null;
        InetAddress requestedIp = null;

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

        packet.order(ByteOrder.BIG_ENDIAN);

        // 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];

            packet.get(l2dst);
            packet.get(l2src);

            short l2type = packet.getShort();

            if (l2type != 0x0800)
                return null;
        }

        if ((pktType == ENCAP_L2) || (pktType == ENCAP_L3)) {
            // assume l2type is 0x0800, i.e. IP
            byte ipType = packet.get();
            // System.out.println("ipType is " + ipType);
            byte ipDiffServicesField = packet.get();
            short ipTotalLength = packet.getShort();
            short ipIdentification = packet.getShort();
            byte ipFlags = packet.get();
            byte ipFragOffset = packet.get();
            byte ipTTL = packet.get();
            byte ipProto = packet.get();
            short ipChksm = packet.getShort();

            ipSrc = readIpAddress(packet);
            ipDst = readIpAddress(packet);

            if (ipProto != IP_TYPE_UDP) // UDP
                return null;

            // assume UDP
            short udpSrcPort = packet.getShort();
            short udpDstPort = packet.getShort();
            short udpLen = packet.getShort();
            short udpChkSum = packet.getShort();

            if ((udpSrcPort != DHCP_SERVER) && (udpSrcPort != DHCP_CLIENT))
                return null;
        }

        // assume bootp
        byte type = packet.get();
        byte hwType = packet.get();
        byte addrLen = packet.get();
        byte hops = packet.get();
        transactionId = packet.getInt();
        short elapsed = packet.getShort();
        short bootpFlags = packet.getShort();
        boolean broadcast = (bootpFlags & 0x8000) != 0;
        byte[] ipv4addr = new byte[4];

        try {
            packet.get(ipv4addr);
            clientIp = InetAddress.getByAddress(ipv4addr);
            packet.get(ipv4addr);
            yourIp = InetAddress.getByAddress(ipv4addr);
            packet.get(ipv4addr);
            nextIp = InetAddress.getByAddress(ipv4addr);
            packet.get(ipv4addr);
            relayIp = InetAddress.getByAddress(ipv4addr);
        } catch (UnknownHostException ex) {
            return null;
        }

        clientMac = new byte[addrLen];
        packet.get(clientMac);

        // skip over address padding (16 octets allocated)
        packet.position(packet.position() + (16 - addrLen)
                        + 64    // skip server host name (64 chars)
                        + 128); // skip boot file name (128 chars)

        int dhcpMagicCookie = packet.getInt();

        if (dhcpMagicCookie !=  0x63825363)
            return null;

        // parse options
        boolean notFinishedOptions = true;

        while ((packet.position() < packet.limit()) && notFinishedOptions) {
            byte optionType = packet.get();

            if (optionType == (byte) 0xFF) {
                notFinishedOptions = false;
            } else {
                byte optionLen = packet.get();
                int expectedLen = 0;

                switch(optionType) {
                    case DHCP_SUBNET_MASK:
                        netMask = readIpAddress(packet);
                        expectedLen = 4;
                        break;
                    case DHCP_ROUTER:
                        gateway = readIpAddress(packet);
                        expectedLen = 4;
                        break;
                    case DHCP_DNS_SERVER:
                        expectedLen = 0;

                        for (expectedLen = 0; expectedLen < optionLen;
                             expectedLen += 4) {
                            dnsServers.add(readIpAddress(packet));
                        }
                        break;
                    case DHCP_HOST_NAME:
                        expectedLen = optionLen;
                        hostName = readAsciiString(packet, optionLen);
                        break;
                    case DHCP_DOMAIN_NAME:
                        expectedLen = optionLen;
                        domainName = readAsciiString(packet, optionLen);
                        break;
                    case DHCP_BROADCAST_ADDRESS:
                        bcAddr = readIpAddress(packet);
                        expectedLen = 4;
                        break;
                    case DHCP_REQUESTED_IP:
                        requestedIp = readIpAddress(packet);
                        expectedLen = 4;
                        break;
                    case DHCP_LEASE_TIME:
                        leaseTime = Integer.valueOf(packet.getInt());
                        expectedLen = 4;
                        break;
                    case DHCP_MESSAGE_TYPE:
                        dhcpType = packet.get();
                        expectedLen = 1;
                        break;
                    case DHCP_SERVER_IDENTIFIER:
                        serverIdentifier = readIpAddress(packet);
                        expectedLen = 4;
                        break;
                    case DHCP_PARAMETER_LIST:
                        expectedParams = new byte[optionLen];
                        packet.get(expectedParams);
                        expectedLen = optionLen;
                        break;
                    case DHCP_MESSAGE:
                        expectedLen = optionLen;
                        message = readAsciiString(packet, optionLen);
                        break;
                    case DHCP_VENDOR_CLASS_ID:
                        expectedLen = optionLen;
                        vendorId = readAsciiString(packet, optionLen);
                        break;
                    case DHCP_CLIENT_IDENTIFIER: { // Client identifier
                        byte[] id = new byte[optionLen];
                        packet.get(id);
                        expectedLen = optionLen;
                    } break;
                    default:
                        // ignore any other parameters
                        for (int i = 0; i < optionLen; i++) {
                            expectedLen++;
                            byte throwaway = packet.get();
                        }
                }

                if (expectedLen != optionLen) {
                    return null;
                }
            }
        }

        DhcpPacket newPacket;

        switch(dhcpType) {
            case -1: return null;
            case DHCP_MESSAGE_TYPE_DISCOVER:
                newPacket = new DhcpDiscoverPacket(
                    transactionId, clientMac, broadcast);
                break;
            case DHCP_MESSAGE_TYPE_OFFER:
                newPacket = new DhcpOfferPacket(
                    transactionId, broadcast, ipSrc, yourIp, clientMac);
                break;
            case DHCP_MESSAGE_TYPE_REQUEST:
                newPacket = new DhcpRequestPacket(
                    transactionId, clientIp, clientMac, broadcast);
                break;
            case DHCP_MESSAGE_TYPE_DECLINE:
                newPacket = new DhcpDeclinePacket(
                    transactionId, clientIp, yourIp, nextIp, relayIp,
                    clientMac);
                break;
            case DHCP_MESSAGE_TYPE_ACK:
                newPacket = new DhcpAckPacket(
                    transactionId, broadcast, ipSrc, yourIp, clientMac);
                break;
            case DHCP_MESSAGE_TYPE_NAK:
                newPacket = new DhcpNakPacket(
                    transactionId, clientIp, yourIp, nextIp, relayIp,
                    clientMac);
                break;
            case DHCP_MESSAGE_TYPE_INFORM:
                newPacket = new DhcpInformPacket(
                    transactionId, clientIp, yourIp, nextIp, relayIp,
                    clientMac);
                break;
            default:
                System.out.println("Unimplemented type: " + dhcpType);
                return null;
        }

        newPacket.mBroadcastAddress = bcAddr;
        newPacket.mDnsServers = dnsServers;
        newPacket.mDomainName = domainName;
        newPacket.mGateway = gateway;
        newPacket.mHostName = hostName;
        newPacket.mLeaseTime = leaseTime;
        newPacket.mMessage = message;
        newPacket.mRequestedIp = requestedIp;
        newPacket.mRequestedParams = expectedParams;
        newPacket.mServerIdentifier = serverIdentifier;
        newPacket.mSubnetMask = netMask;
        return newPacket;
    
public static android.net.dhcp.DhcpPacketdecodeFullPacket(byte[] packet, int pktType)
Parse a packet from an array of bytes.

        ByteBuffer buffer = ByteBuffer.wrap(packet).order(ByteOrder.BIG_ENDIAN);
        return decodeFullPacket(buffer, pktType);
    
public abstract voiddoNextOp(DhcpStateMachine stateMachine)
Asks the packet object to signal the next operation in the DHCP protocol. The available actions are methods defined in the DhcpStateMachine interface.

protected voidfillInPacket(int encap, java.net.InetAddress destIp, java.net.InetAddress srcIp, short destUdp, short srcUdp, java.nio.ByteBuffer buf, byte requestCode, boolean broadcast)
Creates a new L3 packet (including IP header) containing the DHCP udp packet. This method relies upon the delegated method finishPacket() to insert the per-packet contents.

        byte[] destIpArray = destIp.getAddress();
        byte[] srcIpArray = srcIp.getAddress();
        int ipLengthOffset = 0;
        int ipChecksumOffset = 0;
        int endIpHeader = 0;
        int udpHeaderOffset = 0;
        int udpLengthOffset = 0;
        int udpChecksumOffset = 0;

        buf.clear();
        buf.order(ByteOrder.BIG_ENDIAN);

        // if a full IP packet needs to be generated, put the IP & UDP
        // headers in place, and pre-populate with artificial values
        // needed to seed the IP checksum.
        if (encap == ENCAP_L3) {
            // fake IP header, used in the IP-header checksum
            buf.put(IP_VERSION_HEADER_LEN);
            buf.put(IP_TOS_LOWDELAY);    // tos: IPTOS_LOWDELAY
            ipLengthOffset = buf.position();
            buf.putShort((short)0);  // length
            buf.putShort((short)0);  // id
            buf.putShort(IP_FLAGS_OFFSET); // ip offset: don't fragment
            buf.put(IP_TTL);    // TTL: use default 64 from RFC1340
            buf.put(IP_TYPE_UDP);
            ipChecksumOffset = buf.position();
            buf.putShort((short) 0); // checksum

            buf.put(srcIpArray);
            buf.put(destIpArray);
            endIpHeader = buf.position();

            // UDP header
            udpHeaderOffset = buf.position();
            buf.putShort(srcUdp);
            buf.putShort(destUdp);
            udpLengthOffset = buf.position();
            buf.putShort((short) 0); // length
            udpChecksumOffset = buf.position();
            buf.putShort((short) 0); // UDP checksum -- initially zero
        }

        // DHCP payload
        buf.put(requestCode);
        buf.put((byte) 1); // Hardware Type: Ethernet
        buf.put((byte) mClientMac.length); // Hardware Address Length
        buf.put((byte) 0); // Hop Count
        buf.putInt(mTransId);  // Transaction ID
        buf.putShort((short) 0); // Elapsed Seconds

        if (broadcast) {
            buf.putShort((short) 0x8000); // Flags
        } else {
            buf.putShort((short) 0x0000); // Flags
        }

        buf.put(mClientIp.getAddress());
        buf.put(mYourIp.getAddress());
        buf.put(mNextIp.getAddress());
        buf.put(mRelayIp.getAddress());
        buf.put(mClientMac);
        buf.position(buf.position() +
                     (16 - mClientMac.length) // pad addr to 16 bytes
                     + 64     // empty server host name (64 bytes)
                     + 128);  // empty boot file name (128 bytes)
        buf.putInt(0x63825363); // magic number
        finishPacket(buf);

        // round up to an even number of octets
        if ((buf.position() & 1) == 1) {
            buf.put((byte) 0);
        }

        // If an IP packet is being built, the IP & UDP checksums must be
        // computed.
        if (encap == ENCAP_L3) {
            // fix UDP header: insert length
            short udpLen = (short)(buf.position() - udpHeaderOffset);
            buf.putShort(udpLengthOffset, udpLen);
            // fix UDP header: checksum
            // checksum for UDP at udpChecksumOffset
            int udpSeed = 0;

            // apply IPv4 pseudo-header.  Read IP address src and destination
            // values from the IP header and accumulate checksum.
            udpSeed += intAbs(buf.getShort(ipChecksumOffset + 2));
            udpSeed += intAbs(buf.getShort(ipChecksumOffset + 4));
            udpSeed += intAbs(buf.getShort(ipChecksumOffset + 6));
            udpSeed += intAbs(buf.getShort(ipChecksumOffset + 8));

            // accumulate extra data for the pseudo-header
            udpSeed += IP_TYPE_UDP;
            udpSeed += udpLen;
            // and compute UDP checksum
            buf.putShort(udpChecksumOffset, (short) checksum(buf, udpSeed,
                                                             udpHeaderOffset,
                                                             buf.position()));
            // fix IP header: insert length
            buf.putShort(ipLengthOffset, (short)buf.position());
            // fixup IP-header checksum
            buf.putShort(ipChecksumOffset,
                         (short) checksum(buf, 0, 0, endIpHeader));
        }
    
abstract voidfinishPacket(java.nio.ByteBuffer buffer)
Allows the concrete class to fill in packet-type-specific details, typically optional parameters at the end of the packet.

public intgetTransactionId()
Returns the transaction ID.

        return mTransId;
    
private intintAbs(short v)
Converts a signed short value to an unsigned int value. Needed because Java does not have unsigned types.

        if (v < 0) {
            int r = v + 65536;
            return r;
        } else {
            return(v);
        }
    
public static java.lang.StringmacToString(byte[] mac)
Converts a MAC from an array of octets to an ASCII string.

        String macAddr = "";

        for (int i = 0; i < mac.length; i++) {
            String hexString = "0" + Integer.toHexString(mac[i]);

            // substring operation grabs the last 2 digits: this
            // allows signed bytes to be converted correctly.
            macAddr += hexString.substring(hexString.length() - 2);

            if (i != (mac.length - 1)) {
                macAddr += ":";
            }
        }

        return macAddr;
    
private static java.lang.StringreadAsciiString(java.nio.ByteBuffer buf, int byteCount)
Reads a string of specified length from the buffer.

        byte[] bytes = new byte[byteCount];
        buf.get(bytes);
        return new String(bytes, 0, bytes.length, StandardCharsets.US_ASCII);
    
private static java.net.InetAddressreadIpAddress(java.nio.ByteBuffer packet)
Reads a four-octet value from a ByteBuffer and construct an IPv4 address from that value.

        InetAddress result = null;
        byte[] ipAddr = new byte[4];
        packet.get(ipAddr);

        try {
            result = InetAddress.getByAddress(ipAddr);
        } catch (UnknownHostException ex) {
            // ipAddr is numeric, so this should not be
            // triggered.  However, if it is, just nullify
            result = null;
        }

        return result;
    
public java.lang.StringtoString()

        String macAddr = macToString(mClientMac);

        return macAddr;