blob: 317a9b4faba4b43e9dd8fd3fa6eb9ee63a442def [file] [log] [blame]
package android.net.dhcp;
import android.util.Log;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.List;
/**
* 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.
*/
abstract class DhcpPacket {
protected static final String TAG = "DhcpPacket";
/**
* Packet encapsulations.
*/
public static final int ENCAP_L2 = 0; // EthernetII header included
public static final int ENCAP_L3 = 1; // IP/UDP header included
public static final int ENCAP_BOOTP = 2; // BOOTP contents only
/**
* IP layer definitions.
*/
private static final byte IP_TYPE_UDP = (byte) 0x11;
/**
* IP: Version 4, Header Length 20 bytes
*/
private static final byte IP_VERSION_HEADER_LEN = (byte) 0x45;
/**
* IP: Flags 0, Fragment Offset 0, Don't Fragment
*/
private static final short IP_FLAGS_OFFSET = (short) 0x4000;
/**
* IP: TOS
*/
private static final byte IP_TOS_LOWDELAY = (byte) 0x10;
/**
* IP: TTL -- use default 64 from RFC1340
*/
private static final byte IP_TTL = (byte) 0x40;
/**
* The client DHCP port.
*/
static final short DHCP_CLIENT = (short) 68;
/**
* The server DHCP port.
*/
static final short DHCP_SERVER = (short) 67;
/**
* The message op code indicating a request from a client.
*/
protected static final byte DHCP_BOOTREQUEST = (byte) 1;
/**
* The message op code indicating a response from the server.
*/
protected static final byte DHCP_BOOTREPLY = (byte) 2;
/**
* The code type used to identify an Ethernet MAC address in the
* Client-ID field.
*/
protected static final byte CLIENT_ID_ETHER = (byte) 1;
/**
* The maximum length of a packet that can be constructed.
*/
protected static final int MAX_LENGTH = 1500;
/**
* DHCP Optional Type: DHCP Subnet Mask
*/
protected static final byte DHCP_SUBNET_MASK = 1;
protected InetAddress mSubnetMask;
/**
* DHCP Optional Type: DHCP Router
*/
protected static final byte DHCP_ROUTER = 3;
protected InetAddress mGateway;
/**
* DHCP Optional Type: DHCP DNS Server
*/
protected static final byte DHCP_DNS_SERVER = 6;
protected List<InetAddress> mDnsServers;
/**
* DHCP Optional Type: DHCP Host Name
*/
protected static final byte DHCP_HOST_NAME = 12;
protected String mHostName;
/**
* DHCP Optional Type: DHCP DOMAIN NAME
*/
protected static final byte DHCP_DOMAIN_NAME = 15;
protected String mDomainName;
/**
* DHCP Optional Type: DHCP BROADCAST ADDRESS
*/
protected static final byte DHCP_BROADCAST_ADDRESS = 28;
protected InetAddress mBroadcastAddress;
/**
* DHCP Optional Type: DHCP Requested IP Address
*/
protected static final byte DHCP_REQUESTED_IP = 50;
protected InetAddress mRequestedIp;
/**
* DHCP Optional Type: DHCP Lease Time
*/
protected static final byte DHCP_LEASE_TIME = 51;
protected Integer mLeaseTime;
/**
* DHCP Optional Type: DHCP Message Type
*/
protected static final byte DHCP_MESSAGE_TYPE = 53;
// the actual type values
protected static final byte DHCP_MESSAGE_TYPE_DISCOVER = 1;
protected static final byte DHCP_MESSAGE_TYPE_OFFER = 2;
protected static final byte DHCP_MESSAGE_TYPE_REQUEST = 3;
protected static final byte DHCP_MESSAGE_TYPE_DECLINE = 4;
protected static final byte DHCP_MESSAGE_TYPE_ACK = 5;
protected static final byte DHCP_MESSAGE_TYPE_NAK = 6;
protected static final byte DHCP_MESSAGE_TYPE_INFORM = 8;
/**
* DHCP Optional Type: DHCP Server Identifier
*/
protected static final byte DHCP_SERVER_IDENTIFIER = 54;
protected InetAddress mServerIdentifier;
/**
* DHCP Optional Type: DHCP Parameter List
*/
protected static final byte DHCP_PARAMETER_LIST = 55;
protected byte[] mRequestedParams;
/**
* DHCP Optional Type: DHCP MESSAGE
*/
protected static final byte DHCP_MESSAGE = 56;
protected String mMessage;
/**
* DHCP Optional Type: DHCP Renewal Time Value
*/
protected static final byte DHCP_RENEWAL_TIME = 58;
/**
* DHCP Optional Type: Vendor Class Identifier
*/
protected static final byte DHCP_VENDOR_CLASS_ID = 60;
/**
* DHCP Optional Type: DHCP Client Identifier
*/
protected static final byte DHCP_CLIENT_IDENTIFIER = 61;
/**
* The transaction identifier used in this particular DHCP negotiation
*/
protected final int mTransId;
/**
* 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 mClientIp;
protected final InetAddress mYourIp;
private final InetAddress mNextIp;
private final InetAddress mRelayIp;
/**
* Does the client request a broadcast response?
*/
protected boolean mBroadcast;
/**
* The six-octet MAC of the client.
*/
protected final byte[] mClientMac;
/**
* Asks the packet object to signal the next operation in the DHCP
* protocol. The available actions are methods defined in the
* DhcpStateMachine interface.
*/
public abstract void doNextOp(DhcpStateMachine stateMachine);
/**
* Asks the packet object to create a ByteBuffer serialization of
* the packet for transmission.
*/
public abstract ByteBuffer buildPacket(int encap, short destUdp,
short srcUdp);
/**
* Allows the concrete class to fill in packet-type-specific details,
* typically optional parameters at the end of the packet.
*/
abstract void finishPacket(ByteBuffer buffer);
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;
}
/**
* Returns the transaction ID.
*/
public int getTransactionId() {
return mTransId;
}
/**
* 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.
*/
protected void fillInPacket(int encap, InetAddress destIp,
InetAddress srcIp, short destUdp, short srcUdp, ByteBuffer buf,
byte requestCode, boolean broadcast) {
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));
}
}
/**
* Converts a signed short value to an unsigned int value. Needed
* because Java does not have unsigned types.
*/
private int intAbs(short v) {
if (v < 0) {
int r = v + 65536;
return r;
} else {
return(v);
}
}
/**
* 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.
*/
private int checksum(ByteBuffer buf, int seed, int start, int end) {
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);
}
/**
* Adds an optional parameter containing a single byte value.
*/
protected void addTlv(ByteBuffer buf, byte type, byte value) {
buf.put(type);
buf.put((byte) 1);
buf.put(value);
}
/**
* Adds an optional parameter containing an array of bytes.
*/
protected void addTlv(ByteBuffer buf, byte type, byte[] payload) {
if (payload != null) {
buf.put(type);
buf.put((byte) payload.length);
buf.put(payload);
}
}
/**
* Adds an optional parameter containing an IP address.
*/
protected void addTlv(ByteBuffer buf, byte type, InetAddress addr) {
if (addr != null) {
addTlv(buf, type, addr.getAddress());
}
}
/**
* Adds an optional parameter containing a list of IP addresses.
*/
protected void addTlv(ByteBuffer buf, byte type, List<InetAddress> addrs) {
if (addrs != null && addrs.size() > 0) {
buf.put(type);
buf.put((byte)(4 * addrs.size()));
for (InetAddress addr : addrs) {
buf.put(addr.getAddress());
}
}
}
/**
* Adds an optional parameter containing a simple integer
*/
protected void addTlv(ByteBuffer buf, byte type, Integer value) {
if (value != null) {
buf.put(type);
buf.put((byte) 4);
buf.putInt(value.intValue());
}
}
/**
* Adds an optional parameter containing and ASCII string.
*/
protected void addTlv(ByteBuffer buf, byte type, String str) {
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));
}
}
}
/**
* Adds the special end-of-optional-parameters indicator.
*/
protected void addTlvEnd(ByteBuffer buf) {
buf.put((byte) 0xFF);
}
/**
* Converts a MAC from an array of octets to an ASCII string.
*/
public static String macToString(byte[] mac) {
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;
}
public String toString() {
String macAddr = macToString(mClientMac);
return macAddr;
}
/**
* Reads a four-octet value from a ByteBuffer and construct
* an IPv4 address from that value.
*/
private static InetAddress readIpAddress(ByteBuffer packet) {
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;
}
/**
* Reads a string of specified length from the buffer.
*/
private static String readAsciiString(ByteBuffer buf, int byteCount) {
byte[] bytes = new byte[byteCount];
buf.get(bytes);
return new String(bytes, 0, bytes.length, StandardCharsets.US_ASCII);
}
/**
* 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).
* <br>
* A subset of the optional parameters are parsed and are stored
* in object fields.
*/
public static DhcpPacket decodeFullPacket(ByteBuffer packet, int pktType)
{
// 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;
}
/**
* Parse a packet from an array of bytes.
*/
public static DhcpPacket decodeFullPacket(byte[] packet, int pktType)
{
ByteBuffer buffer = ByteBuffer.wrap(packet).order(ByteOrder.BIG_ENDIAN);
return decodeFullPacket(buffer, pktType);
}
/**
* Builds a DHCP-DISCOVER packet from the required specified
* parameters.
*/
public static ByteBuffer buildDiscoverPacket(int encap, int transactionId,
byte[] clientMac, boolean broadcast, byte[] expectedParams) {
DhcpPacket pkt = new DhcpDiscoverPacket(
transactionId, clientMac, broadcast);
pkt.mRequestedParams = expectedParams;
return pkt.buildPacket(encap, DHCP_SERVER, DHCP_CLIENT);
}
/**
* Builds a DHCP-OFFER packet from the required specified
* parameters.
*/
public static ByteBuffer buildOfferPacket(int encap, int transactionId,
boolean broadcast, InetAddress serverIpAddr, InetAddress clientIpAddr,
byte[] mac, Integer timeout, InetAddress netMask, InetAddress bcAddr,
InetAddress gateway, List<InetAddress> dnsServers,
InetAddress dhcpServerIdentifier, String domainName) {
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);
}
/**
* Builds a DHCP-ACK packet from the required specified parameters.
*/
public static ByteBuffer buildAckPacket(int encap, int transactionId,
boolean broadcast, InetAddress serverIpAddr, InetAddress clientIpAddr,
byte[] mac, Integer timeout, InetAddress netMask, InetAddress bcAddr,
InetAddress gateway, List<InetAddress> dnsServers,
InetAddress dhcpServerIdentifier, String domainName) {
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);
}
/**
* Builds a DHCP-NAK packet from the required specified parameters.
*/
public static ByteBuffer buildNakPacket(int encap, int transactionId,
InetAddress serverIpAddr, InetAddress clientIpAddr, byte[] mac) {
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);
}
/**
* Builds a DHCP-REQUEST packet from the required specified parameters.
*/
public static ByteBuffer buildRequestPacket(int encap,
int transactionId, InetAddress clientIp, boolean broadcast,
byte[] clientMac, InetAddress requestedIpAddress,
InetAddress serverIdentifier, byte[] requestedParams, String hostName) {
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;
}
}