All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.markusbernhardt.proxy.search.wpad.dhcp.DHCPMessage Maven / Gradle / Ivy

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); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy