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

org.pcap4j.packet.DnsResourceRecord Maven / Gradle / Ivy

/*_##########################################################################
  _##
  _##  Copyright (C) 2016-2019 Pcap4J.org
  _##
  _##########################################################################
*/

package org.pcap4j.packet;

import static org.pcap4j.util.ByteArrays.INT_SIZE_IN_BYTES;
import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES;

import java.io.Serializable;
import org.pcap4j.packet.factory.PacketFactories;
import org.pcap4j.packet.namednumber.DnsClass;
import org.pcap4j.packet.namednumber.DnsResourceRecordType;
import org.pcap4j.util.ByteArrays;

/**
 * DNS Resource record
 *
 * 
 *                                 1  1  1  1  1  1
 *   0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 * |                                               |
 * /                                               /
 * /                      NAME                     /
 * |                                               |
 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 * |                      TYPE                     |
 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 * |                     CLASS                     |
 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 * |                      TTL                      |
 * |                                               |
 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 * |                   RDLENGTH                    |
 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
 * /                     RDATA                     /
 * /                                               /
 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 * 
* * @see RFC 1035 * @author Kaito Yamada * @since pcap4j 1.7.1 */ public final class DnsResourceRecord implements Serializable { /** */ private static final long serialVersionUID = 4951400991563055073L; private final DnsDomainName name; private final DnsResourceRecordType dataType; private final DnsClass dataClass; private final int ttl; private final short rdLength; private final DnsRData rData; /** * A static factory method. This method validates the arguments by {@link * ByteArrays#validateBounds(byte[], int, int)}, which may throw exceptions undocumented here. * * @param rawData rawData * @param offset offset * @param length length * @return a new DnsResourceRecord object. * @throws IllegalRawDataException if parsing the raw data fails. */ public static DnsResourceRecord newInstance(byte[] rawData, int offset, int length) throws IllegalRawDataException { ByteArrays.validateBounds(rawData, offset, length); return new DnsResourceRecord(rawData, offset, length); } private DnsResourceRecord(byte[] rawData, int offset, int length) throws IllegalRawDataException { int cursor = 0; this.name = DnsDomainName.newInstance(rawData, offset, length); cursor += name.length(); if (length - cursor < SHORT_SIZE_IN_BYTES * 3 + INT_SIZE_IN_BYTES) { StringBuilder sb = new StringBuilder(200); sb.append( "The data is too short to build type, class, ttl, and rdlength of DnsResourceRecord. " + "data: ") .append(ByteArrays.toHexString(rawData, " ")) .append(", offset: ") .append(offset) .append(", length: ") .append(length) .append(", cursor: ") .append(cursor); throw new IllegalRawDataException(sb.toString()); } this.dataType = DnsResourceRecordType.getInstance(ByteArrays.getShort(rawData, offset + cursor)); cursor += SHORT_SIZE_IN_BYTES; this.dataClass = DnsClass.getInstance(ByteArrays.getShort(rawData, offset + cursor)); cursor += SHORT_SIZE_IN_BYTES; this.ttl = ByteArrays.getInt(rawData, offset + cursor); cursor += INT_SIZE_IN_BYTES; this.rdLength = ByteArrays.getShort(rawData, offset + cursor); cursor += SHORT_SIZE_IN_BYTES; int rdLen = getRdLengthAsInt(); if (length - cursor < rdLen) { StringBuilder sb = new StringBuilder(200); sb.append("The data is too short to build rData of DnsResourceRecord (") .append(rdLen) .append(" bytes). data: ") .append(ByteArrays.toHexString(rawData, " ")) .append(", offset: ") .append(offset) .append(", length: ") .append(length) .append(", cursor: ") .append(cursor) .append(", dataType: ") .append(dataType); throw new IllegalRawDataException(sb.toString()); } if (rdLen != 0) { this.rData = PacketFactories.getFactory(DnsRData.class, DnsResourceRecordType.class) .newInstance(rawData, offset + cursor, rdLen, dataType); } else { this.rData = null; } } private DnsResourceRecord(Builder builder) { if (builder == null || builder.name == null || builder.dataType == null || builder.dataClass == null) { StringBuilder sb = new StringBuilder(); sb.append("builder") .append(builder) .append(" builder.name: ") .append(builder.name) .append(" builder.dataType: ") .append(builder.dataType) .append(" builder.dataClass: ") .append(builder.dataClass); throw new NullPointerException(sb.toString()); } this.name = builder.name; this.dataType = builder.dataType; this.dataClass = builder.dataClass; this.ttl = builder.ttl; this.rData = builder.rData; if (builder.correctLengthAtBuild) { int rdLen = rData == null ? 0 : rData.length(); if ((rdLen & 0xFFFF0000) != 0) { throw new IllegalArgumentException( "(rData.length() & 0xFFFF0000) must be zero. rData: " + rData); } this.rdLength = (short) rdLen; } else { this.rdLength = builder.rdLength; } } /** @return name */ public DnsDomainName getName() { return name; } /** @return dataType */ public DnsResourceRecordType getDataType() { return dataType; } /** @return dataClass */ public DnsClass getDataClass() { return dataClass; } /** @return ttl */ public int getTtl() { return ttl; } /** @return ttl */ public long getTtlAsLong() { return ttl & 0xFFFFFFFFL; } /** @return rdLength */ public short getRdLength() { return rdLength; } /** @return rdLength */ public int getRdLengthAsInt() { return rdLength & 0xFFFF; } /** @return rData. May be null. */ public DnsRData getRData() { return rData; } /** @return a new Builder object populated with this object's fields. */ public Builder getBuilder() { return new Builder(this); } /** @return the raw data. */ public byte[] getRawData() { byte[] data = new byte[length()]; int cursor = 0; byte[] rawName = name.getRawData(); System.arraycopy(rawName, 0, data, 0, rawName.length); cursor += rawName.length; System.arraycopy( ByteArrays.toByteArray(dataType.value()), 0, data, cursor, SHORT_SIZE_IN_BYTES); cursor += SHORT_SIZE_IN_BYTES; System.arraycopy( ByteArrays.toByteArray(dataClass.value()), 0, data, cursor, SHORT_SIZE_IN_BYTES); cursor += SHORT_SIZE_IN_BYTES; System.arraycopy(ByteArrays.toByteArray(ttl), 0, data, cursor, INT_SIZE_IN_BYTES); cursor += INT_SIZE_IN_BYTES; System.arraycopy(ByteArrays.toByteArray(rdLength), 0, data, cursor, SHORT_SIZE_IN_BYTES); if (rData != null) { cursor += SHORT_SIZE_IN_BYTES; byte[] rawRData = rData.getRawData(); System.arraycopy(rawRData, 0, data, cursor, rawRData.length); } return data; } /** @return length */ public int length() { int rDataLen = rData == null ? 0 : rData.length(); return name.length() + SHORT_SIZE_IN_BYTES * 3 + INT_SIZE_IN_BYTES + rDataLen; } @Override public String toString() { return convertToString("", null); } /** * @param indent indent * @return String representation of this object. */ public String toString(String indent) { return convertToString(indent, null); } /** * @param indent indent * @param headerRawData the raw data of the DNS header including this resource record. * @return String representation of this object. */ public String toString(String indent, byte[] headerRawData) { if (headerRawData == null) { throw new NullPointerException("headerRawData is null."); } return convertToString(indent, headerRawData); } private String convertToString(String indent, byte[] headerRawData) { StringBuilder sb = new StringBuilder(); String ls = System.getProperty("line.separator"); sb.append(indent) .append("NAME: ") .append(headerRawData != null ? name.toString(headerRawData) : name) .append(ls) .append(indent) .append("TYPE: ") .append(dataType) .append(ls) .append(indent) .append("CLASS: ") .append(dataClass) .append(ls) .append(indent) .append("TTL: ") .append(getTtlAsLong()) .append(ls) .append(indent) .append("RDLENGTH: ") .append(getRdLengthAsInt()) .append(ls); if (rData != null) { sb.append(indent) .append("RDATA:") .append(ls) .append( headerRawData != null ? rData.toString(indent + " ", headerRawData) : rData.toString(indent + " ")); } return sb.toString(); } @Override public int hashCode() { int result = name.hashCode(); result = 31 * result + dataType.hashCode(); result = 31 * result + dataClass.hashCode(); result = 31 * result + ttl; result = 31 * result + (int) rdLength; result = 31 * result + (rData != null ? rData.hashCode() : 0); return result; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } DnsResourceRecord that = (DnsResourceRecord) o; if (ttl != that.ttl) { return false; } if (rdLength != that.rdLength) { return false; } if (!name.equals(that.name)) { return false; } if (!dataType.equals(that.dataType)) { return false; } if (!dataClass.equals(that.dataClass)) { return false; } return rData != null ? rData.equals(that.rData) : that.rData == null; } /** * @author Kaito Yamada * @since pcap4j 1.7.1 */ public static final class Builder implements LengthBuilder { private DnsDomainName name; private DnsResourceRecordType dataType; private DnsClass dataClass; private int ttl; private short rdLength; private DnsRData rData; private boolean correctLengthAtBuild = false; /** */ public Builder() {} private Builder(DnsResourceRecord obj) { this.name = obj.name; this.dataType = obj.dataType; this.dataClass = obj.dataClass; this.ttl = obj.ttl; this.rdLength = obj.rdLength; this.rData = obj.rData; } /** * @param name name * @return this Builder object for method chaining. */ public Builder name(DnsDomainName name) { this.name = name; return this; } /** * @param dataType dataType * @return this Builder object for method chaining. */ public Builder dataType(DnsResourceRecordType dataType) { this.dataType = dataType; return this; } /** * @param dataClass dataClass * @return this Builder object for method chaining. */ public Builder dataClass(DnsClass dataClass) { this.dataClass = dataClass; return this; } /** * @param ttl ttl * @return this Builder object for method chaining. */ public Builder ttl(int ttl) { this.ttl = ttl; return this; } /** * @param rdLength rdLength * @return this Builder object for method chaining. */ public Builder rdLength(short rdLength) { this.rdLength = rdLength; return this; } /** * @param rData rData * @return this Builder object for method chaining. */ public Builder rData(DnsRData rData) { this.rData = rData; return this; } @Override public LengthBuilder correctLengthAtBuild(boolean correctLengthAtBuild) { this.correctLengthAtBuild = correctLengthAtBuild; return this; } /** @return a new DnsResourceRecord object. */ @Override public DnsResourceRecord build() { return new DnsResourceRecord(this); } } /** * The interface representing an RDATA. If you use {@link * org.pcap4j.packet.factory.propertiesbased.PropertiesBasedPacketFactory * PropertiesBasedPacketFactory}, classes which implement this interface must implement the * following method: {@code public static IpV4Option newInstance(byte[] rawData, int offset, int * length) throws IllegalRawDataException} * * @author Kaito Yamada * @since pcap4j 1.7.1 */ public interface DnsRData extends Serializable { /** @return length */ public int length(); /** @return raw data */ public byte[] getRawData(); /** * @param indent indent * @return String representation of this object. */ public String toString(String indent); /** * @param indent indent * @param headerRawData the raw data of the DNS header including this RDATA. * @return String representation of this object. */ public String toString(String indent, byte[] headerRawData); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy