📄 dhcppacket.java
字号:
// add padding if the packet is too small
int min_padding = minSize - outBStream.size();
if (min_padding > 0) {
byte[] add_padding = new byte[min_padding];
outStream.write(add_padding);
}
// final packet is here
byte[] data = outBStream.toByteArray();
// do some post sanity checks
if (data.length > _DHCP_MAX_MTU) {
throw new DHCPBadPacketException("serialize: packet too big (" + data.length + " greater than max MAX_MTU (" + _DHCP_MAX_MTU + ')');
}
return data;
} catch (IOException e) {
// nomrally impossible with ByteArrayOutputStream
logger.log(Level.SEVERE, "Unexpected Exception", e);
throw new DHCPBadPacketException("IOException raised: "+e.toString());
}
}
// ========================================================================
// debug functions
/**
* Returns a detailed string representation of the DHCP datagram.
*
* <p>This multi-line string details: the static, options and padding parts
* of the object. This is useful for debugging, but not efficient.
*
* @return a string representation of the object.
*/
@Override
public String toString() {
StringBuilder buffer = new StringBuilder(); // output buffer
try {
buffer.append(this.isDhcp ? "DHCP Packet" : "BOOTP Packet")
.append("\ncomment=")
.append(this.comment)
.append("\naddress=")
.append(this.address != null ? this.address.getHostAddress() : "")
.append('(')
.append(this.port)
.append(')')
.append("\nop=");
final Object bootName = _BOOT_NAMES.get(this.op);
if (bootName != null) {
buffer.append(bootName)
.append('(')
.append(this.op)
.append(')');
} else {
buffer.append(this.op);
}
buffer.append("\nhtype=");
final Object htypeName = _HTYPE_NAMES.get(this.htype);
if (htypeName != null) {
buffer.append(htypeName)
.append('(')
.append(this.htype)
.append(')');
} else {
buffer.append(this.htype);
}
buffer.append("\nhlen=")
.append(this.hlen)
.append("\nhops=")
.append(this.hops)
.append("\nxid=0x");
appendHex(buffer, this.xid);
buffer.append("\nsecs=")
.append(this.secs)
.append("\nflags=0x")
.append(Integer.toHexString(this.flags))
.append("\nciaddr=");
appendHostAddress(buffer, InetAddress.getByAddress(this.ciaddr));
buffer.append("\nyiaddr=");
appendHostAddress(buffer, InetAddress.getByAddress(this.yiaddr));
buffer.append("\nsiaddr=");
appendHostAddress(buffer, InetAddress.getByAddress(this.siaddr));
buffer.append("\ngiaddr=");
appendHostAddress(buffer, InetAddress.getByAddress(this.giaddr));
buffer.append("\nchaddr=0x");
this.appendChaddrAsHex(buffer);
buffer.append("\nsname=")
.append(this.getSname())
.append("\nfile=")
.append(this.getFile());
if (this.isDhcp) {
buffer.append("\nOptions follows:");
// parse options in creation order (LinkedHashMap)
for (DHCPOption opt : this.getOptionsCollection()) {
buffer.append('\n');
opt.append(buffer);
}
}
// padding
buffer.append("\npadding[")
.append(this.padding.length)
.append("]=");
appendHex(buffer, this.padding);
} catch (Exception e) {
// what to do ???
}
return buffer.toString();
}
// ========================================================================
// getters and setters
/**
* Returns the comment associated to this packet.
*
* <p>This field can be used freely and has no influence on the real network datagram.
* It can be used to store a transaction number or any other information
*
* @return the _comment field.
*/
public String getComment() {
return this.comment;
}
/**
* Sets the comment associated to this packet.
*
* <p>This field can be used freely and has no influence on the real network datagram.
* It can be used to store a transaction number or any other information
*
* @param comment The comment to set.
*/
public void setComment(String comment) {
this.comment = comment;
}
/**
* Returns the chaddr field (Client hardware address - typically MAC address).
*
* <p>Returns the byte[16] raw buffer. Only the first <tt>hlen</tt> bytes are valid.
*
* @return the chaddr field.
*/
public byte[] getChaddr() {
return this.chaddr.clone();
}
/**
* Appends the chaddr field (Client hardware address - typically MAC address) as
* a hex string to this string buffer.
*
* <p>Only first <tt>hlen</tt> bytes are appended, as uppercase hex string.
*
* @param buffer this string buffer
* @return the string buffer.
*/
private StringBuilder appendChaddrAsHex(StringBuilder buffer) {
appendHex(buffer, this.chaddr, 0, this.hlen & 0xFF);
return buffer;
}
/**
* Return the hardware address (@MAC) as an <tt>HardwareAddress</tt> object.
*
* @return the <tt>HardwareAddress</tt> object
*/
public HardwareAddress getHardwareAddress() {
int len = this.hlen & 0xff;
if (len > 16) {
len = 16;
}
byte[] buf = new byte[len];
System.arraycopy(this.chaddr, 0, buf, 0, len);
return new HardwareAddress(this.htype, buf);
}
/**
* Returns the chaddr field (Client hardware address - typically MAC address) as
* a hex string.
*
* <p>Only first <tt>hlen</tt> bytes are printed, as uppercase hex string.
*
* @return the chaddr field as hex string.
*/
public String getChaddrAsHex() {
return this.appendChaddrAsHex(new StringBuilder(this.hlen & 0xFF)).toString();
}
/**
* Sets the chaddr field (Client hardware address - typically MAC address).
*
* <p>The buffer length should be between 0 and 16, otherwise an
* <tt>IllegalArgumentException</tt> is thrown.
*
* <p>If chaddr is null, the field is filled with zeros.
*
* @param chaddr The chaddr to set.
* @throws IllegalArgumentException chaddr buffer is longer than 16 bytes.
*/
public void setChaddr(byte[] chaddr) {
if (chaddr != null) {
if (chaddr.length > this.chaddr.length) {
throw new IllegalArgumentException("chaddr is too long: " + chaddr.length +
", max is: " + this.chaddr.length);
}
Arrays.fill(this.chaddr, (byte) 0);
System.arraycopy(chaddr, 0, this.chaddr, 0, chaddr.length);
} else {
Arrays.fill(this.chaddr, (byte) 0);
}
}
/**
* Sets the chaddr field - from an hex String.
*
* @param hex the chaddr in hex format
*/
public void setChaddrHex(String hex) {
this.setChaddr(hex2Bytes(hex));
}
/**
* Returns the ciaddr field (Client IP Address).
*
* @return the ciaddr field converted to <tt>InetAddress</tt> object.
*/
public InetAddress getCiaddr() {
try {
return InetAddress.getByAddress(this.getCiaddrRaw());
} catch (UnknownHostException e) {
logger.log(Level.SEVERE, "Unexpected UnknownHostException", e);
return null; // normaly impossible
}
}
/**
* Returns the ciaddr field (Client IP Address).
*
* <p>This is the low-level maximum performance getter for this field.
*
* @return Returns the ciaddr as raw byte[4].
*/
public byte[] getCiaddrRaw() {
return this.ciaddr.clone();
}
/**
* Sets the ciaddr field (Client IP Address).
*
* <p>Ths <tt>ciaddr</tt> field must be of <tt>Inet4Address</tt> class or
* an <tt>IllegalArgumentException</tt> is thrown.
*
* @param ciaddr The ciaddr to set.
*/
public void setCiaddr(InetAddress ciaddr) {
if (!(ciaddr instanceof Inet4Address)) {
throw new IllegalArgumentException("Inet4Address required");
}
this.setCiaddrRaw(ciaddr.getAddress());
}
/**
* Sets the ciaddr field (Client IP Address).
*
* @param ciaddr The ciaddr to set.
* @throws UnknownHostException
*/
public void setCiaddr(String ciaddr) throws UnknownHostException {
this.setCiaddr(InetAddress.getByName(ciaddr));
}
/**
* Sets the ciaddr field (Client IP Address).
*
* <p><tt>ciaddr</tt> must be a 4 bytes array, or an <tt>IllegalArgumentException</tt>
* is thrown.
*
* <p>This is the low-level maximum performance setter for this field.
* The array is internally copied so any further modification to <tt>ciaddr</tt>
* parameter has no side effect.
*
* @param ciaddr The ciaddr to set.
*/
public void setCiaddrRaw(byte[] ciaddr) {
if (ciaddr.length != 4) {
throw new IllegalArgumentException("4-byte array required");
}
System.arraycopy(ciaddr, 0, this.ciaddr, 0, 4);
}
/**
* Returns the file field (Boot File Name).
*
* <p>Returns the raw byte[128] buffer, containing a null terminated string.
*
* <p>This is the low-level maximum performance getter for this field.
*
* @return the file field.
*/
public byte[] getFileRaw() {
return this.file.clone();
}
/**
* Returns the file field (Boot File Name) as String.
*
* @return the file converted to a String (transparent encoding).
*/
public String getFile() {
return bytesToString(this.getFileRaw());
}
/**
* Sets the file field (Boot File Name) as String.
*
* <p>The string is first converted to a byte[] array using transparent
* encoding. If the resulting buffer size is > 128, an <tt>IllegalArgumentException</tt>
* is thrown.
*
* <p>If <tt>file</tt> parameter is null, the buffer is filled with zeros.
*
* @param file The file field to set.
* @throws IllegalArgumentException string too long
*/
public void setFile(String file) {
this.setFileRaw(stringToBytes(file));
}
/**
* Sets the file field (Boot File Name) as String.
*
* <p>If the buffer size is > 128, an <tt>IllegalArgumentException</tt>
* is thrown.
*
* <p>If <tt>file</tt> parameter is null, the buffer is filled with zeros.
*
* <p>This is the low-level maximum performance setter for this field.
*
* @param file The file field to set.
* @throws IllegalArgumentException string too long
*/
public void setFileRaw(byte[] file) {
if (file != null) {
if (file.length > this.file.length) {
throw new IllegalArgumentException("File is too long:" + file.length + " max is:" + this.file.length);
}
Arrays.fill(this.file, (byte) 0);
System.arraycopy(file, 0, this.file, 0, file.length);
} else {
Arrays.fill(this.file, (byte) 0);
}
}
/**
* Returns the flags field.
*
* @return the flags field.
*/
public short getFlags() {
return this.flags;
}
/**
* Sets the flags field.
*
* @param flags The flags field to set.
*/
public void setFlags(short flags) {
this.flags = flags;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -