com.github.markusbernhardt.proxy.search.wpad.dhcp.DHCPMessage Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of proxy-vole Show documentation
Show all versions of proxy-vole Show documentation
Proxy Vole is a Java library to auto detect the platform network proxy settings.
The newest version!
package com.github.markusbernhardt.proxy.search.wpad.dhcp;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* This class represents a DHCP Message.
*
* @author Markus Bernhardt, Copyright 2016
* @author Jason Goldschmidt, Nick Stone and Simon Frankenberger
* @author Bernd Rosstauscher, Copyright 2009
*/
public class DHCPMessage {
// -----------------------------------------------------------
// Constants
// -----------------------------------------------------------
/**
* Operation for a request
*/
public static final byte OP_REQUEST = 1;
/**
* Operation for a reply
*/
public static final byte OP_REPLY = 2;
/**
* Message Code representing a DHCPDISCOVER message
*/
public static final byte DHCPDISCOVER = 1;
/**
* Message Code representing a DHCPOFFER message
*/
public static final byte DHCPOFFER = 2;
/**
* Message Code representing a DHCPREQUEST message
*/
public static final byte DHCPREQUEST = 3;
/**
* Message Code representing a DHCPDECLINE message
*/
public static final byte DHCPDECLINE = 4;
/**
* Message Code representing a DHCPACK message
*/
public static final byte DHCPACK = 5;
/**
* Message Code representing a DHCPNAK message
*/
public static final byte DHCPNAK = 6;
/**
* Message Code representing a DHCPRELEASE message
*/
public static final byte DHCPRELEASE = 7;
/**
* Message Code representing a DHCPINFORM message
*/
public static final byte DHCPINFORM = 8;
/**
* Default DHCP client port
*/
public static final int CLIENT_PORT = 68; // client port (by default)
/**
* Default DHCP server port
*/
public static final int SERVER_PORT = 67; // server port (by default)
/**
* Broadcast Adress to send packets to
*/
public static InetAddress BROADCAST_ADDR = null;
// -----------------------------------------------------------
// Fields defining a dhcp message
// -----------------------------------------------------------
/**
* Operation Code.
*
* Can either be {@link #OP_REQUEST} or {@link #OP_REPLY}.
*/
private byte op;
/**
* Networktype as defined by
* RFC1340 page 54.
*/
private byte htype;
/**
* Hardware address length (e.g. '6' for ethernet).
*/
private byte hlen;
/**
* Client sets to zero, optionally used by relay-agents when booting via a
* relay-agent.
*/
private byte hops;
/**
* Transaction ID, a random number chosen by the client, used by the client
* and server to associate messages and responses between a client and a
* server.
*/
private int xid;
/**
* Filled in by client, seconds elapsed since client started trying to boot.
*/
private short secs;
/**
* Flags for this message.
* The leftmost bit is defined as the BROADCAST (B) flag.
*/
private short flags;
/**
* Client IP address; filled in by client in DHCPREQUEST if verifying
* previously allocated configuration parameters.
*/
private byte ciaddr[] = new byte[4];
/**
* 'your' (client) IP address.
*/
private byte yiaddr[] = new byte[4];
/**
* IP address of next server to use in bootstrap; returned in DHCPOFFER,
* DHCPACK and DHCPNAK by server.
*/
private byte siaddr[] = new byte[4];
/**
* Relay agent IP address, used in booting via a relay-agent.
*/
private byte giaddr[] = new byte[4];
/**
* Client hardware address.
*/
private byte chaddr[] = new byte[16];
/**
* Optional server host name, null terminated string.
*/
private byte sname[] = new byte[64];
/**
* Boot file name, null terminated string; "generic" name or null in
* DHCPDISCOVER, fully qualified directory-path name in DHCPOFFER.
*/
private byte file[] = new byte[128];
/**
* Internal representation of the given DHCP options.
*/
private DHCPOptions optionsList = null;
/**
* global port variable for this message
*/
private int gPort;
/**
* The destination IP-Adress of this message
*/
private InetAddress destination_IP;
static {
try {
BROADCAST_ADDR = InetAddress.getByName("255.255.255.255");
// broadcast address(by default)
} catch (UnknownHostException e) {
// Broadcast address must always exist
}
}
// -----------------------------------------------------------
// Constructors
// -----------------------------------------------------------
/**
* Creates empty DHCPMessage object, initializes the object, sets the host
* to the broadcast address, the local subnet, binds to the default server
* port.
*/
public DHCPMessage() {
initialize();
this.destination_IP = BROADCAST_ADDR;
this.gPort = SERVER_PORT;
}
/**
* Copy constructor creates DHCPMessage from inMessage
*
* @param inMessage
* The message to be copied
*/
public DHCPMessage(DHCPMessage inMessage) {
initialize();
this.destination_IP = BROADCAST_ADDR;
this.gPort = SERVER_PORT;
this.op = inMessage.getOp();
this.htype = inMessage.getHtype();
this.hlen = inMessage.getHlen();
this.hops = inMessage.getHops();
this.xid = inMessage.getXid();
this.secs = inMessage.getSecs();
this.flags = inMessage.getFlags();
this.ciaddr = inMessage.getCiaddr();
this.yiaddr = inMessage.getYiaddr();
this.siaddr = inMessage.getSiaddr();
this.giaddr = inMessage.getGiaddr();
this.chaddr = inMessage.getChaddr();
this.sname = inMessage.getSname();
this.file = inMessage.getFile();
this.optionsList.internalize(inMessage.getOptions());
}
/**
* Copy constructor creates DHCPMessage from inMessage and sets server and
* port.
*
* @param inMessage
* The message to be copied
* @param inServername
* The host name
* @param inPort
* The port number
*/
public DHCPMessage(DHCPMessage inMessage, InetAddress inServername, int inPort) {
initialize();
this.destination_IP = inServername;
this.gPort = inPort;
this.op = inMessage.getOp();
this.htype = inMessage.getHtype();
this.hlen = inMessage.getHlen();
this.hops = inMessage.getHops();
this.xid = inMessage.getXid();
this.secs = inMessage.getSecs();
this.flags = inMessage.getFlags();
this.ciaddr = inMessage.getCiaddr();
this.yiaddr = inMessage.getYiaddr();
this.siaddr = inMessage.getSiaddr();
this.giaddr = inMessage.getGiaddr();
this.chaddr = inMessage.getChaddr();
this.sname = inMessage.getSname();
this.file = inMessage.getFile();
this.optionsList.internalize(inMessage.getOptions());
}
/**
* Copy constructor creates DHCPMessage from inMessage and sets server name.
*
* @param inMessage
* The message to be copied
* @param inServername
* The host name
*/
public DHCPMessage(DHCPMessage inMessage, InetAddress inServername) {
initialize();
this.destination_IP = inServername;
this.gPort = SERVER_PORT;
this.op = inMessage.getOp();
this.htype = inMessage.getHtype();
this.hlen = inMessage.getHlen();
this.hops = inMessage.getHops();
this.xid = inMessage.getXid();
this.secs = inMessage.getSecs();
this.flags = inMessage.getFlags();
this.ciaddr = inMessage.getCiaddr();
this.yiaddr = inMessage.getYiaddr();
this.siaddr = inMessage.getSiaddr();
this.giaddr = inMessage.getGiaddr();
this.chaddr = inMessage.getChaddr();
this.sname = inMessage.getSname();
this.file = inMessage.getFile();
this.optionsList.internalize(inMessage.getOptions());
}
/**
* Creates an empty DHCPMessage object, initializes the object, sets the
* host to a specified host name, and binds to a specified port.
*
* @param inServername
* The host name
* @param inPort
* The port number
*/
public DHCPMessage(InetAddress inServername, int inPort) {
initialize();
this.destination_IP = inServername;
this.gPort = inPort;
}
/**
* Creates an empty DHCPMessage object, initializes the object, sets the
* host to a specified host name, and binds to the default port.
*
* @param inServername
* The host name
*/
public DHCPMessage(InetAddress inServername) {
initialize();
this.destination_IP = inServername;
this.gPort = SERVER_PORT;
}
/**
* Creates an empty DHCPMessage object, initializes the object, sets the
* host to the broadcast address, and binds to a specified port.
*
* @param inPort
* The port number
*/
public DHCPMessage(int inPort) {
initialize();
this.destination_IP = BROADCAST_ADDR;
this.gPort = inPort;
}
/**
* Creates an empty DHCPMessage object, initializes the object with a
* specified byte array containing DHCP message information, sets the host
* to default host name, the local subnet, and bind to the default server
* port.
*
* @param ibuf
* The byte array to initialize DHCPMessage object
*/
public DHCPMessage(byte[] ibuf) {
initialize();
internalize(ibuf);
this.destination_IP = BROADCAST_ADDR;
this.gPort = SERVER_PORT;
}
/**
* Creates an empty DHCPMessage object, initializes the object with a
* specified byte array containing DHCP message information, sets the host
* to specified host name, and binds to the specified port.
*
* @param ibuf
* The byte array to initialize DHCPMessage object
* @param inServername
* The hostname
* @param inPort
* The port number
*/
public DHCPMessage(byte[] ibuf, InetAddress inServername, int inPort) {
initialize();
internalize(ibuf);
this.destination_IP = inServername;
this.gPort = inPort;
}
/**
* Creates an empty DHCPMessage object, initializes the object with a
* specified byte array containing DHCP message information, sets the host
* to broadcast address, and binds to the specified port.
*
* @param ibuf
* The byte array to initialize DHCPMessage object
* @param inPort
* The port number
*/
public DHCPMessage(byte ibuf[], int inPort) {
initialize();
internalize(ibuf);
this.destination_IP = BROADCAST_ADDR;
this.gPort = inPort;
}
/**
* Creates an empty DHCPMessage object, initializes the object with a
* specified byte array containing DHCP message information, sets the host
* to specified host name, and binds to the specified port.
*
* @param ibuf
* The byte array to initialize DHCPMessage object
* @param inServername
* The hostname
*/
public DHCPMessage(byte[] ibuf, InetAddress inServername) {
initialize();
internalize(ibuf);
this.destination_IP = inServername;
this.gPort = SERVER_PORT;
}
/**
* Creates a new DHCPMessage object from the giben DataInputStream.
*
* @param inStream
* The stream to read from
*/
public DHCPMessage(DataInputStream inStream) {
initialize();
try {
this.op = inStream.readByte();
this.htype = inStream.readByte();
this.hlen = inStream.readByte();
this.hops = inStream.readByte();
this.xid = inStream.readInt();
this.secs = inStream.readShort();
this.flags = inStream.readShort();
inStream.readFully(this.ciaddr, 0, 4);
inStream.readFully(this.yiaddr, 0, 4);
inStream.readFully(this.siaddr, 0, 4);
inStream.readFully(this.giaddr, 0, 4);
inStream.readFully(this.chaddr, 0, 16);
inStream.readFully(this.sname, 0, 64);
inStream.readFully(this.file, 0, 128);
byte[] options = new byte[312];
inStream.readFully(options, 0, 312);
this.optionsList.internalize(options);
} catch (IOException e) {
System.err.println(e);
}
}
// -----------------------------------------------------------
// Methods
// -----------------------------------------------------------
/**
* Initializes datamembers in the constructors every empty DHCPMessage
* object will by default contain these params. Initializes options array
* from linked list form.
*/
private void initialize() {
this.optionsList = new DHCPOptions();
}
/**
* Converts a DHCPMessage object to a byte array.
*
* @return A byte array with information from DHCPMessage object, ready to
* send.
*/
public synchronized byte[] externalize() {
ByteArrayOutputStream outBStream = new ByteArrayOutputStream();
DataOutputStream outStream = new DataOutputStream(outBStream);
try {
outStream.writeByte(this.op);
outStream.writeByte(this.htype);
outStream.writeByte(this.hlen);
outStream.writeByte(this.hops);
outStream.writeInt(this.xid);
outStream.writeShort(this.secs);
outStream.writeShort(this.flags);
outStream.write(this.ciaddr, 0, 4);
outStream.write(this.yiaddr, 0, 4);
outStream.write(this.siaddr, 0, 4);
outStream.write(this.giaddr, 0, 4);
outStream.write(this.chaddr, 0, 16);
outStream.write(this.sname, 0, 64);
outStream.write(this.file, 0, 128);
byte[] options = new byte[312];
if (this.optionsList == null) {
initialize();
}
options = this.optionsList.externalize();
outStream.write(options, 0, 312);
} catch (IOException e) {
System.err.println(e);
}
// extract the byte array from the Stream
byte data[] = outBStream.toByteArray();
return data;
}
/**
* Convert a specified byte array containing a DHCP message into a
* DHCPMessage object.
*
* @param ibuff
* Byte array to convert to a DHCPMessage object
* @return A DHCPMessage object with information from byte array.
*/
public synchronized DHCPMessage internalize(byte[] ibuff) {
ByteArrayInputStream inBStream = new ByteArrayInputStream(ibuff, 0, ibuff.length);
DataInputStream inStream = new DataInputStream(inBStream);
try {
this.op = inStream.readByte();
this.htype = inStream.readByte();
this.hlen = inStream.readByte();
this.hops = inStream.readByte();
this.xid = inStream.readInt();
this.secs = inStream.readShort();
this.flags = inStream.readShort();
inStream.readFully(this.ciaddr, 0, 4);
inStream.readFully(this.yiaddr, 0, 4);
inStream.readFully(this.siaddr, 0, 4);
inStream.readFully(this.giaddr, 0, 4);
inStream.readFully(this.chaddr, 0, 16);
inStream.readFully(this.sname, 0, 64);
inStream.readFully(this.file, 0, 128);
byte[] options = new byte[312];
inStream.readFully(options, 0, 312);
if (this.optionsList == null) {
initialize();
}
this.optionsList.internalize(options);
} catch (IOException e) {
System.err.println(e);
} // end catch
return this;
}
/**
* Set message Op code / message type.
*
* @param inOp
* message Op code / message type
*/
public void setOp(byte inOp) {
this.op = inOp;
}
/**
* Set hardware address type.
*
* @param inHtype
* hardware address type
*/
public void setHtype(byte inHtype) {
this.htype = inHtype;
}
/**
* Set hardware address length.
*
* @param inHlen
* hardware address length
*/
public void setHlen(byte inHlen) {
this.hlen = inHlen;
}
/**
* Set hops field.
*
* @param inHops
* hops field
*/
public void setHops(byte inHops) {
this.hops = inHops;
}
/**
* Set transaction ID.
*
* @param inXid
* transactionID
*/
public void setXid(int inXid) {
this.xid = inXid;
}
/**
* Set seconds elapsed since client began address acquisition or renewal
* process.
*
* @param inSecs
* Seconds elapsed since client began address acquisition or
* renewal process
*/
public void setSecs(short inSecs) {
this.secs = inSecs;
}
/**
* Set flags field.
*
* @param inFlags
* flags field
*/
public void setFlags(short inFlags) {
this.flags = inFlags;
}
/**
* Set client IP address.
*
* @param inCiaddr
* client IP address
*/
public void setCiaddr(byte[] inCiaddr) {
this.ciaddr = inCiaddr;
}
/**
* Set 'your' (client) IP address.
*
* @param inYiaddr
* 'your' (client) IP address
*/
public void setYiaddr(byte[] inYiaddr) {
this.yiaddr = inYiaddr;
}
/**
* Set address of next server to use in bootstrap.
*
* @param inSiaddr
* address of next server to use in bootstrap
*/
public void setSiaddr(byte[] inSiaddr) {
this.siaddr = inSiaddr;
}
/**
* Set relay agent IP address.
*
* @param inGiaddr
* relay agent IP address
*/
public void setGiaddr(byte[] inGiaddr) {
this.giaddr = inGiaddr;
}
/**
* Set client harware address.
*
* @param inChaddr
* client hardware address
*/
public void setChaddr(byte[] inChaddr) {
this.chaddr = inChaddr;
}
/**
* Set optional server host name.
*
* @param inSname
* server host name
*/
public void setSname(byte[] inSname) {
this.sname = inSname;
}
/**
* Set boot file name.
*
* @param inFile
* boot file name
*/
public void setFile(byte[] inFile) {
this.file = inFile;
}
/**
* Set message destination port.
*
* @param inPortNum
* port on message destination host
*/
public void setPort(int inPortNum) {
this.gPort = inPortNum;
}
/**
* Set message destination IP
*
* @param inHost
* string representation of message destination IP or hostname
*/
public void setDestinationHost(String inHost) {
try {
this.destination_IP = InetAddress.getByName(inHost);
} catch (Exception e) {
System.err.println(e);
}
}
/**
* @return message Op code / message type.
*/
public byte getOp() {
return this.op;
}
/**
* @return hardware address type.
*/
public byte getHtype() {
return this.htype;
}
/**
* @return hardware address length.
*/
public byte getHlen() {
return this.hlen;
}
/**
* @return hops field.
*/
public byte getHops() {
return this.hops;
}
/**
* @return transaction ID.
*/
public int getXid() {
return this.xid;
}
/**
* @return seconds elapsed since client began address acquisition or renewal
* process.
*/
public short getSecs() {
return this.secs;
}
/**
* @return flags field.
*/
public short getFlags() {
return this.flags;
}
/**
* @return client IP address.
*/
public byte[] getCiaddr() {
return this.ciaddr;
}
/**
* @return 'your' (client) IP address.
*/
public byte[] getYiaddr() {
return this.yiaddr;
}
/**
* @return address of next server to use in bootstrap.
*/
public byte[] getSiaddr() {
return this.siaddr;
}
/**
* @return relay agent IP address.
*/
public byte[] getGiaddr() {
return this.giaddr;
}
/**
* @return client harware address.
*/
public byte[] getChaddr() {
return this.chaddr;
}
/**
* @return optional server host name.
*/
public byte[] getSname() {
return this.sname;
}
/**
* @return boot file name.
*/
public byte[] getFile() {
return this.file;
}
/**
* @return a byte array containing options
*/
public byte[] getOptions() {
if (this.optionsList == null) {
initialize();
}
return this.optionsList.externalize();
}
/**
* @return An interger representation of the message destination port
*/
public int getPort() {
return this.gPort;
}
/**
* Get message destination hostname
*
* @return A string representing the hostname of the message destination
* server
*/
public String getDestinationAddress() {
return this.destination_IP.getHostAddress();
}
/**
* Sets DHCP options in DHCPMessage. If option already exists then remove
* old option and insert a new one.
*
* @param inOptNum
* option number
* @param inOptionData
* option data
*/
public void setOption(int inOptNum, byte[] inOptionData) {
this.optionsList.setOption((byte) inOptNum, inOptionData);
}
/**
* Returns specified DHCP option that matches the input code. Null is
* returned if option is not set.
*
* @param inOptNum
* option number
*
* @return the option matching input code
*/
public byte[] getOption(int inOptNum) {
if (this.optionsList == null) {
initialize();
}
return this.optionsList.getOption((byte) inOptNum);
}
/**
* Removes the specified DHCP option that matches the input code.
*
* @param inOptNum
* option number
*/
public void removeOption(int inOptNum) {
if (this.optionsList == null) {
initialize();
}
this.optionsList.removeOption((byte) inOptNum);
}
/**
* Report whether or not the input option is set.
*
* @param inOptNum
* option number
*
* @return is the given option set?
*/
public boolean IsOptSet(int inOptNum) {
if (this.optionsList == null) {
initialize();
}
return this.optionsList.contains((byte) inOptNum);
}
}