summaryrefslogtreecommitdiffstats
path: root/src/main/java/com/btr/proxy/search/wpad/dhcp/DHCPMessage.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/btr/proxy/search/wpad/dhcp/DHCPMessage.java')
-rw-r--r--src/main/java/com/btr/proxy/search/wpad/dhcp/DHCPMessage.java880
1 files changed, 880 insertions, 0 deletions
diff --git a/src/main/java/com/btr/proxy/search/wpad/dhcp/DHCPMessage.java b/src/main/java/com/btr/proxy/search/wpad/dhcp/DHCPMessage.java
new file mode 100644
index 0000000..86323d5
--- /dev/null
+++ b/src/main/java/com/btr/proxy/search/wpad/dhcp/DHCPMessage.java
@@ -0,0 +1,880 @@
+package com.btr.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 Jason Goldschmidt, Nick Stone and Simon Frankenberger
+ */
+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;
+
+ public static final byte OPTION_DHCP_WPAD = (byte) 252;
+
+
+
+ // -----------------------------------------------------------
+ // Fields defining a dhcp message
+ // -----------------------------------------------------------
+ /**
+ * Operation Code.<br>
+ * <br>
+ * Can either be {@link #OP_REQUEST} or {@link #OP_REPLY}.
+ */
+ private byte op;
+
+ /**
+ * Networktype as defined by
+ * <a href="http://tools.ietf.org/html/rfc1340#page-54">RFC1340 page 54</a>.
+ */
+ 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.<br>
+ * 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);
+ }
+}