Use value types for class and type in DNS entries to make them immune to parameter order bugs

Motivation:

DNS class and type were represented as integers rather than an enum or a
similar dedicated value type.  This can be a potential source of a
parameter order bug which might be difficult to track down.

Modifications:

Add DnsClass and DnsType to replace integer parameters

Result:

Type safety and less error-proneness
This commit is contained in:
Tim Boudreau 2014-07-22 03:02:58 -04:00 committed by Trustin Lee
parent 4816533638
commit 9734170b7d
10 changed files with 725 additions and 312 deletions

View File

@ -0,0 +1,136 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.handler.codec.dns;
import java.util.Arrays;
/**
* Represents a class field in DNS protocol
*/
public class DnsClass {
/**
* Default class for DNS entries.
*/
public static final DnsClass IN = new DnsClass(0x0001, "IN");
public static final DnsClass CSNET = new DnsClass(0x0002, "CSNET");
public static final DnsClass CHAOS = new DnsClass(0x0003, "CHAOS");
public static final DnsClass HESIOD = new DnsClass(0x0004, "HESIOD");
public static final DnsClass NONE = new DnsClass(0x00fe, "NONE");
public static final DnsClass ANY = new DnsClass(0x00ff, "ANY");
/**
* The protocol value of this DNS class
*/
private final int clazz;
/**
* The name of this DNS class
*/
private final String name;
DnsClass(int clazz, String name) {
this.clazz = clazz;
this.name = name;
}
/**
* Returns the name of this class as used in bind config files
*/
public final String name() {
return name;
}
/**
* Returns the protocol value represented by this class
*/
public final int clazz() {
return clazz;
}
/**
* Returns an instance of DnsClass for a custom type.
*
* @param clazz The class
* @param name The name
*/
public static DnsClass create(int clazz, String name) {
return new DnsClass(clazz, name);
}
/**
* Returns true if this class is valid with respect to DNS protocol
*/
public boolean isValid() {
if (clazz < 1 || clazz > 4 && clazz != NONE.clazz && clazz != ANY.clazz) {
return false;
}
return true;
}
public static DnsClass forName(String name) {
if (IN.name.equals(name)) {
return IN;
} else if (NONE.name().equals(name)) {
return NONE;
} else if (ANY.name().equals(name)) {
return ANY;
} else if (CSNET.name().equals(name)) {
return CSNET;
} else if (CHAOS.name().equals(name)) {
return CHAOS;
} else if (HESIOD.name().equals(name)) {
return HESIOD;
}
throw new IllegalArgumentException("name: " + name + " (expected: "
+ "IN, ANY, CSNET, CHAOS, HESIOD)");
}
public static DnsClass valueOf(int clazz) {
switch (clazz) {
case 0x0001:
return IN;
case 0x0002:
return CSNET;
case 0x0003:
return CHAOS;
case 0x0004:
return HESIOD;
case 0x00fe:
return NONE;
case 0x00ff:
return ANY;
default:
throw new IllegalArgumentException("clazz: " + clazz + " (expected: "
+ Arrays.asList(new Integer[] {IN.clazz, CSNET.clazz,
CHAOS.clazz, HESIOD.clazz, NONE.clazz, ANY.clazz}) + ")");
}
}
@Override
public final int hashCode() {
return clazz;
}
@Override
public final boolean equals(Object o) {
return o instanceof DnsClass && ((DnsClass) o).clazz == clazz;
}
@Override
public final String toString() {
return name;
}
}

View File

@ -21,306 +21,16 @@ package io.netty.handler.codec.dns;
*/ */
public class DnsEntry { public class DnsEntry {
/**
* Address record RFC 1035 Returns a 32-bit IPv4 address, most commonly used
* to map hostnames to an IP address of the host, but also used for DNSBLs,
* storing subnet masks in RFC 1101, etc.
*/
public static final int TYPE_A = 0x0001;
/**
* Name server record RFC 1035 Delegates a DNS zone to use the given
* authoritative name servers
*/
public static final int TYPE_NS = 0x0002;
/**
* Canonical name record RFC 1035 Alias of one name to another: the DNS
* lookup will continue by retrying the lookup with the new name.
*/
public static final int TYPE_CNAME = 0x0005;
/**
* Start of [a zone of] authority record RFC 1035 and RFC 2308 Specifies
* authoritative information about a DNS zone, including the primary name
* server, the email of the domain administrator, the domain serial number,
* and several timers relating to refreshing the zone.
*/
public static final int TYPE_SOA = 0x0006;
/**
* Pointer record RFC 1035 Pointer to a canonical name. Unlike a CNAME, DNS
* processing does NOT proceed, just the name is returned. The most common
* use is for implementing reverse DNS lookups, but other uses include such
* things as DNS-SD.
*/
public static final int TYPE_PTR = 0x000c;
/**
* Mail exchange record RFC 1035 Maps a domain name to a list of message
* transfer agents for that domain.
*/
public static final int TYPE_MX = 0x000f;
/**
* Text record RFC 1035 Originally for arbitrary human-readable text in a
* DNS record. Since the early 1990s, however, this record more often
* carries machine-readable data, such as specified by RFC 1464,
* opportunistic encryption, Sender Policy Framework, DKIM, DMARC DNS-SD,
* etc.
*/
public static final int TYPE_TXT = 0x0010;
/**
* Responsible person record RFC 1183 Information about the responsible
* person(s) for the domain. Usually an email address with the @ replaced by
* a .
*/
public static final int TYPE_RP = 0x0011;
/**
* AFS database record RFC 1183 Location of database servers of an AFS cell.
* This record is commonly used by AFS clients to contact AFS cells outside
* their local domain. A subtype of this record is used by the obsolete
* DCE/DFS file system.
*/
public static final int TYPE_AFSDB = 0x0012;
/**
* Signature record RFC 2535 Signature record used in SIG(0) (RFC 2931) and
* TKEY (RFC 2930). RFC 3755 designated RRSIG as the replacement for SIG for
* use within DNSSEC.
*/
public static final int TYPE_SIG = 0x0018;
/**
* key record RFC 2535 and RFC 2930 Used only for SIG(0) (RFC 2931) and TKEY
* (RFC 2930). RFC 3445 eliminated their use for application keys and
* limited their use to DNSSEC. RFC 3755 designates DNSKEY as the
* replacement within DNSSEC. RFC 4025 designates IPSECKEY as the
* replacement for use with IPsec.
*/
public static final int TYPE_KEY = 0x0019;
/**
* IPv6 address record RFC 3596 Returns a 128-bit IPv6 address, most
* commonly used to map hostnames to an IP address of the host.
*/
public static final int TYPE_AAAA = 0x001c;
/**
* Location record RFC 1876 Specifies a geographical location associated
* with a domain name.
*/
public static final int TYPE_LOC = 0x001d;
/**
* Service locator RFC 2782 Generalized service location record, used for
* newer protocols instead of creating protocol-specific records such as MX.
*/
public static final int TYPE_SRV = 0x0021;
/**
* Naming Authority Pointer record RFC 3403 Allows regular expression based
* rewriting of domain names which can then be used as URIs, further domain
* names to lookups, etc.
*/
public static final int TYPE_NAPTR = 0x0023;
/**
* Key eXchanger record RFC 2230 Used with some cryptographic systems (not
* including DNSSEC) to identify a key management agent for the associated
* domain-name. Note that this has nothing to do with DNS Security. It is
* Informational status, rather than being on the IETF standards-track. It
* has always had limited deployment, but is still in use.
*/
public static final int TYPE_KX = 0x0024;
/**
* Certificate record RFC 4398 Stores PKIX, SPKI, PGP, etc.
*/
public static final int TYPE_CERT = 0x0025;
/**
* Delegation name record RFC 2672 DNAME creates an alias for a name and all
* its subnames, unlike CNAME, which aliases only the exact name in its
* label. Like the CNAME record, the DNS lookup will continue by retrying
* the lookup with the new name.
*/
public static final int TYPE_DNAME = 0x0027;
/**
* Option record RFC 2671 This is a pseudo DNS record type needed to support
* EDNS.
*/
public static final int TYPE_OPT = 0x0029;
/**
* Address Prefix List record RFC 3123 Specify lists of address ranges, e.g.
* in CIDR format, for various address families. Experimental.
*/
public static final int TYPE_APL = 0x002a;
/**
* Delegation signer record RFC 4034 The record used to identify the DNSSEC
* signing key of a delegated zone.
*/
public static final int TYPE_DS = 0x002b;
/**
* SSH Public Key Fingerprint record RFC 4255 Resource record for publishing
* SSH public host key fingerprints in the DNS System, in order to aid in
* verifying the authenticity of the host. RFC 6594 defines ECC SSH keys and
* SHA-256 hashes. See the IANA SSHFP RR parameters registry for details.
*/
public static final int TYPE_SSHFP = 0x002c;
/**
* IPsec Key record RFC 4025 Key record that can be used with IPsec.
*/
public static final int TYPE_IPSECKEY = 0x002d;
/**
* DNSSEC signature record RFC 4034 Signature for a DNSSEC-secured record
* set. Uses the same format as the SIG record.
*/
public static final int TYPE_RRSIG = 0x002e;
/**
* Next-Secure record RFC 4034 Part of DNSSEC, used to prove a name does not
* exist. Uses the same format as the (obsolete) NXT record.
*/
public static final int TYPE_NSEC = 0x002f;
/**
* DNS Key record RFC 4034 The key record used in DNSSEC. Uses the same
* format as the KEY record.
*/
public static final int TYPE_DNSKEY = 0x0030;
/**
* DHCP identifier record RFC 4701 Used in conjunction with the FQDN option
* to DHCP.
*/
public static final int TYPE_DHCID = 0x0031;
/**
* NSEC record version 3 RFC 5155 An extension to DNSSEC that allows proof
* of nonexistence for a name without permitting zonewalking.
*/
public static final int TYPE_NSEC3 = 0x0032;
/**
* NSEC3 parameters record RFC 5155 Parameter record for use with NSEC3.
*/
public static final int TYPE_NSEC3PARAM = 0x0033;
/**
* TLSA certificate association record RFC 6698 A record for DNS-based
* Authentication of Named Entities (DANE). RFC 6698 defines The TLSA DNS
* resource record is used to associate a TLS server certificate or public
* key with the domain name where the record is found, thus forming a 'TLSA
* certificate association'.
*/
public static final int TYPE_TLSA = 0x0034;
/**
* Host Identity Protocol record RFC 5205 Method of separating the end-point
* identifier and locator roles of IP addresses.
*/
public static final int TYPE_HIP = 0x0037;
/**
* Sender Policy Framework record RFC 4408 Specified as part of the SPF
* protocol as an alternative to of storing SPF data in TXT records. Uses
* the same format as the earlier TXT record.
*/
public static final int TYPE_SPF = 0x0063;
/**
* Secret key record RFC 2930 A method of providing keying material to be
* used with TSIG that is encrypted under the public key in an accompanying
* KEY RR..
*/
public static final int TYPE_TKEY = 0x00f9;
/**
* Transaction Signature record RFC 2845 Can be used to authenticate dynamic
* updates as coming from an approved client, or to authenticate responses
* as coming from an approved recursive name server similar to DNSSEC.
*/
public static final int TYPE_TSIG = 0x00fa;
/**
* Incremental Zone Transfer record RFC 1996 Requests a zone transfer of the
* given zone but only differences from a previous serial number. This
* request may be ignored and a full (AXFR) sent in response if the
* authoritative server is unable to fulfill the request due to
* configuration or lack of required deltas.
*/
public static final int TYPE_IXFR = 0x00fb;
/**
* Authoritative Zone Transfer record RFC 1035 Transfer entire zone file
* from the master name server to secondary name servers.
*/
public static final int TYPE_AXFR = 0x00fc;
/**
* All cached records RFC 1035 Returns all records of all types known to the
* name server. If the name server does not have any information on the
* name, the request will be forwarded on. The records returned may not be
* complete. For example, if there is both an A and an MX for a name, but
* the name server has only the A record cached, only the A record will be
* returned. Sometimes referred to as ANY, for example in Windows nslookup
* and Wireshark.
*/
public static final int TYPE_ANY = 0x00ff;
/**
* Certification Authority Authorization record RFC 6844 CA pinning,
* constraining acceptable CAs for a host/domain.
*/
public static final int TYPE_CAA = 0x0101;
/**
* DNSSEC Trust Authorities record N/A Part of a deployment proposal for
* DNSSEC without a signed DNS root. See the IANA database and Weiler Spec
* for details. Uses the same format as the DS record.
*/
public static final int TYPE_TA = 0x8000;
/**
* DNSSEC Lookaside Validation record RFC 4431 For publishing DNSSEC trust
* anchors outside of the DNS delegation chain. Uses the same format as the
* DS record. RFC 5074 describes a way of using these records.
*/
public static final int TYPE_DLV = 0x8001;
/**
* Default class for DNS entries.
*/
public static final int CLASS_IN = 0x0001;
public static final int CLASS_CSNET = 0x0002;
public static final int CLASS_CHAOS = 0x0003;
public static final int CLASS_HESIOD = 0x0004;
public static final int CLASS_NONE = 0x00fe;
public static final int CLASS_ANY = 0x00ff;
private final String name; private final String name;
private final int type; private final DnsType type;
private final int dnsClass; private final DnsClass dnsClass;
// only allow to extend from same package // only allow to extend from same package
DnsEntry(String name, int type, int dnsClass) { DnsEntry(String name, DnsType type, DnsClass dnsClass) {
if (name == null) { if (name == null) {
throw new NullPointerException("name"); throw new NullPointerException("name");
} }
if ((type & 0xffff) != type) { if (!dnsClass.isValid()) {
throw new IllegalArgumentException("type must be an unsigned short.");
}
if (dnsClass < 1 || dnsClass > 4 && dnsClass != CLASS_NONE && dnsClass != CLASS_ANY) {
throw new IllegalArgumentException("an invalid class has been supplied."); throw new IllegalArgumentException("an invalid class has been supplied.");
} }
this.name = name; this.name = name;
@ -338,20 +48,20 @@ public class DnsEntry {
/** /**
* Returns the type of resource record to be received. * Returns the type of resource record to be received.
*/ */
public int type() { public DnsType type() {
return type; return type;
} }
/** /**
* Returns the class for this entry. Default is IN (Internet). * Returns the class for this entry. Default is IN (Internet).
*/ */
public int dnsClass() { public DnsClass dnsClass() {
return dnsClass; return dnsClass;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return (name.hashCode() * 31 + type) * 31 + dnsClass; return (name.hashCode() * 31 + type.hashCode()) * 31 + dnsClass.hashCode();
} }
@Override @Override

View File

@ -85,7 +85,7 @@ public class DnsQueryEncoder extends MessageToMessageEncoder<DnsQuery> {
buf.writeBytes(part.getBytes(charset)); buf.writeBytes(part.getBytes(charset));
} }
buf.writeByte(0); // marks end of name field buf.writeByte(0); // marks end of name field
buf.writeShort(question.type()); buf.writeShort(question.type().type());
buf.writeShort(question.dnsClass()); buf.writeShort(question.dnsClass().clazz());
} }
} }

View File

@ -15,6 +15,8 @@
*/ */
package io.netty.handler.codec.dns; package io.netty.handler.codec.dns;
import static io.netty.handler.codec.dns.DnsClass.IN;
/** /**
* The DNS question class which represents a question being sent to a server via * The DNS question class which represents a question being sent to a server via
* a query, or the question being duplicated and sent back in a response. * a query, or the question being duplicated and sent back in a response.
@ -32,8 +34,8 @@ public final class DnsQuestion extends DnsEntry {
* the question type, which represents the type of * the question type, which represents the type of
* {@link DnsResource} record that should be returned * {@link DnsResource} record that should be returned
*/ */
public DnsQuestion(String name, int type) { public DnsQuestion(String name, DnsType type) {
this(name, type, CLASS_IN); this(name, type, IN);
} }
/** /**
@ -47,7 +49,7 @@ public final class DnsQuestion extends DnsEntry {
* @param qClass * @param qClass
* the class of a DNS record * the class of a DNS record
*/ */
public DnsQuestion(String name, int type, int qClass) { public DnsQuestion(String name, DnsType type, DnsClass qClass) {
super(name, type, qClass); super(name, type, qClass);
if (name.isEmpty()) { if (name.isEmpty()) {

View File

@ -41,7 +41,7 @@ public final class DnsResource extends DnsEntry implements ByteBufHolder {
* @param content * @param content
* the data contained in this record * the data contained in this record
*/ */
public DnsResource(String name, int type, int aClass, long ttl, ByteBuf content) { public DnsResource(String name, DnsType type, DnsClass aClass, long ttl, ByteBuf content) {
super(name, type, aClass); super(name, type, aClass);
this.ttl = ttl; this.ttl = ttl;
this.content = content; this.content = content;

View File

@ -126,8 +126,8 @@ public class DnsResponseDecoder extends MessageToMessageDecoder<DatagramPacket>
*/ */
private static DnsQuestion decodeQuestion(ByteBuf buf) { private static DnsQuestion decodeQuestion(ByteBuf buf) {
String name = readName(buf); String name = readName(buf);
int type = buf.readUnsignedShort(); DnsType type = DnsType.valueOf(buf.readUnsignedShort());
int qClass = buf.readUnsignedShort(); DnsClass qClass = DnsClass.valueOf(buf.readUnsignedShort());
return new DnsQuestion(name, type, qClass); return new DnsQuestion(name, type, qClass);
} }
@ -140,8 +140,8 @@ public class DnsResponseDecoder extends MessageToMessageDecoder<DatagramPacket>
*/ */
private static DnsResource decodeResource(ByteBuf buf) { private static DnsResource decodeResource(ByteBuf buf) {
String name = readName(buf); String name = readName(buf);
int type = buf.readUnsignedShort(); DnsType type = DnsType.valueOf(buf.readUnsignedShort());
int aClass = buf.readUnsignedShort(); DnsClass aClass = DnsClass.valueOf(buf.readUnsignedShort());
long ttl = buf.readUnsignedInt(); long ttl = buf.readUnsignedInt();
int len = buf.readUnsignedShort(); int len = buf.readUnsignedShort();

View File

@ -0,0 +1,400 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.handler.codec.dns;
import io.netty.util.collection.IntObjectHashMap;
import java.util.HashMap;
import java.util.Map;
/**
* Represents a DNS record type.
*/
public class DnsType {
/**
* Address record RFC 1035 Returns a 32-bit IPv4 address, most commonly used
* to map hostnames to an IP address of the host, but also used for DNSBLs,
* storing subnet masks in RFC 1101, etc.
*/
public static final DnsType A = new DnsType(0x0001, "A");
/**
* Name server record RFC 1035 Delegates a DNS zone to use the given
* authoritative name servers
*/
public static final DnsType NS = new DnsType(0x0002, "NS");
/**
* Canonical name record RFC 1035 Alias of one name to another: the DNS
* lookup will continue by retrying the lookup with the new name.
*/
public static final DnsType CNAME = new DnsType(0x0005, "CNAME");
/**
* Start of [a zone of] authority record RFC 1035 and RFC 2308 Specifies
* authoritative information about a DNS zone, including the primary name
* server, the email of the domain administrator, the domain serial number,
* and several timers relating to refreshing the zone.
*/
public static final DnsType SOA = new DnsType(0x0006, "SOA");
/**
* Pointer record RFC 1035 Pointer to a canonical name. Unlike a CNAME, DNS
* processing does NOT proceed, just the name is returned. The most common
* use is for implementing reverse DNS lookups, but other uses include such
* things as DNS-SD.
*/
public static final DnsType PTR = new DnsType(0x000c, "PTR");
/**
* Mail exchange record RFC 1035 Maps a domain name to a list of message
* transfer agents for that domain.
*/
public static final DnsType MX = new DnsType(0x000f, "MX");
/**
* Text record RFC 1035 Originally for arbitrary human-readable text in a
* DNS record. Since the early 1990s, however, this record more often
* carries machine-readable data, such as specified by RFC 1464,
* opportunistic encryption, Sender Policy Framework, DKIM, DMARC DNS-SD,
* etc.
*/
public static final DnsType TXT = new DnsType(0x0010, "TXT");
/**
* Responsible person record RFC 1183 Information about the responsible
* person(s) for the domain. Usually an email address with the @ replaced by
* a .
*/
public static final DnsType RP = new DnsType(0x0011, "RP");
/**
* AFS database record RFC 1183 Location of database servers of an AFS cell.
* This record is commonly used by AFS clients to contact AFS cells outside
* their local domain. A subtype of this record is used by the obsolete
* DCE/DFS file system.
*/
public static final DnsType AFSDB = new DnsType(0x0012, "AFSDB");
/**
* Signature record RFC 2535 Signature record used in SIG(0) (RFC 2931) and
* TKEY (RFC 2930). RFC 3755 designated RRSIG as the replacement for SIG for
* use within DNSSEC.
*/
public static final DnsType SIG = new DnsType(0x0018, "SIG");
/**
* key record RFC 2535 and RFC 2930 Used only for SIG(0) (RFC 2931) and TKEY
* (RFC 2930). RFC 3445 eliminated their use for application keys and
* limited their use to DNSSEC. RFC 3755 designates DNSKEY as the
* replacement within DNSSEC. RFC 4025 designates IPSECKEY as the
* replacement for use with IPsec.
*/
public static final DnsType KEY = new DnsType(0x0019, "KEY");
/**
* IPv6 address record RFC 3596 Returns a 128-bit IPv6 address, most
* commonly used to map hostnames to an IP address of the host.
*/
public static final DnsType AAAA = new DnsType(0x001c, "AAAA");
/**
* Location record RFC 1876 Specifies a geographical location associated
* with a domain name.
*/
public static final DnsType LOC = new DnsType(0x001d, "LOC");
/**
* Service locator RFC 2782 Generalized service location record, used for
* newer protocols instead of creating protocol-specific records such as MX.
*/
public static final DnsType SRV = new DnsType(0x0021, "SRV");
/**
* Naming Authority Pointer record RFC 3403 Allows regular expression based
* rewriting of domain names which can then be used as URIs, further domain
* names to lookups, etc.
*/
public static final DnsType NAPTR = new DnsType(0x0023, "NAPTR");
/**
* Key eXchanger record RFC 2230 Used with some cryptographic systems (not
* including DNSSEC) to identify a key management agent for the associated
* domain-name. Note that this has nothing to do with DNS Security. It is
* Informational status, rather than being on the IETF standards-track. It
* has always had limited deployment, but is still in use.
*/
public static final DnsType KX = new DnsType(0x0024, "KX");
/**
* Certificate record RFC 4398 Stores PKIX, SPKI, PGP, etc.
*/
public static final DnsType CERT = new DnsType(0x0025, "CERT");
/**
* Delegation name record RFC 2672 DNAME creates an alias for a name and all
* its subnames, unlike CNAME, which aliases only the exact name in its
* label. Like the CNAME record, the DNS lookup will continue by retrying
* the lookup with the new name.
*/
public static final DnsType DNAME = new DnsType(0x0027, "DNAME");
/**
* Option record RFC 2671 This is a pseudo DNS record type needed to support
* EDNS.
*/
public static final DnsType OPT = new DnsType(0x0029, "OPT");
/**
* Address Prefix List record RFC 3123 Specify lists of address ranges, e.g.
* in CIDR format, for various address families. Experimental.
*/
public static final DnsType APL = new DnsType(0x002a, "APL");
/**
* Delegation signer record RFC 4034 The record used to identify the DNSSEC
* signing key of a delegated zone.
*/
public static final DnsType DS = new DnsType(0x002b, "DS");
/**
* SSH Public Key Fingerprint record RFC 4255 Resource record for publishing
* SSH public host key fingerprints in the DNS System, in order to aid in
* verifying the authenticity of the host. RFC 6594 defines ECC SSH keys and
* SHA-256 hashes. See the IANA SSHFP RR parameters registry for details.
*/
public static final DnsType SSHFP = new DnsType(0x002c, "SSHFP");
/**
* IPsec Key record RFC 4025 Key record that can be used with IPsec.
*/
public static final DnsType IPSECKEY = new DnsType(0x002d, "IPSECKEY");
/**
* DNSSEC signature record RFC 4034 Signature for a DNSSEC-secured record
* set. Uses the same format as the SIG record.
*/
public static final DnsType RRSIG = new DnsType(0x002e, "RRSIG");
/**
* Next-Secure record RFC 4034 Part of DNSSEC, used to prove a name does not
* exist. Uses the same format as the (obsolete) NXT record.
*/
public static final DnsType NSEC = new DnsType(0x002f, "NSEC");
/**
* DNS Key record RFC 4034 The key record used in DNSSEC. Uses the same
* format as the KEY record.
*/
public static final DnsType DNSKEY = new DnsType(0x0030, "DNSKEY");
/**
* DHCP identifier record RFC 4701 Used in conjunction with the FQDN option
* to DHCP.
*/
public static final DnsType DHCID = new DnsType(0x0031, "DHCID");
/**
* NSEC record version 3 RFC 5155 An extension to DNSSEC that allows proof
* of nonexistence for a name without permitting zonewalking.
*/
public static final DnsType NSEC3 = new DnsType(0x0032, "NSEC3");
/**
* NSEC3 parameters record RFC 5155 Parameter record for use with NSEC3.
*/
public static final DnsType NSEC3PARAM = new DnsType(0x0033, "NSEC3PARAM");
/**
* TLSA certificate association record RFC 6698 A record for DNS-based
* Authentication of Named Entities (DANE). RFC 6698 defines The TLSA DNS
* resource record is used to associate a TLS server certificate or public
* key with the domain name where the record is found, thus forming a 'TLSA
* certificate association'.
*/
public static final DnsType TLSA = new DnsType(0x0034, "TLSA");
/**
* Host Identity Protocol record RFC 5205 Method of separating the end-point
* identifier and locator roles of IP addresses.
*/
public static final DnsType HIP = new DnsType(0x0037, "HIP");
/**
* Sender Policy Framework record RFC 4408 Specified as part of the SPF
* protocol as an alternative to of storing SPF data in TXT records. Uses
* the same format as the earlier TXT record.
*/
public static final DnsType SPF = new DnsType(0x0063, "SPF");
/**
* Secret key record RFC 2930 A method of providing keying material to be
* used with TSIG that is encrypted under the public key in an accompanying
* KEY RR..
*/
public static final DnsType TKEY = new DnsType(0x00f9, "TKEY");
/**
* Transaction Signature record RFC 2845 Can be used to authenticate dynamic
* updates as coming from an approved client, or to authenticate responses
* as coming from an approved recursive name server similar to DNSSEC.
*/
public static final DnsType TSIG = new DnsType(0x00fa, "TSIG");
/**
* Incremental Zone Transfer record RFC 1996 Requests a zone transfer of the
* given zone but only differences from a previous serial number. This
* request may be ignored and a full (AXFR) sent in response if the
* authoritative server is unable to fulfill the request due to
* configuration or lack of required deltas.
*/
public static final DnsType IXFR = new DnsType(0x00fb, "IXFR");
/**
* Authoritative Zone Transfer record RFC 1035 Transfer entire zone file
* from the master name server to secondary name servers.
*/
public static final DnsType AXFR = new DnsType(0x00fc, "AXFR");
/**
* All cached records RFC 1035 Returns all records of all types known to the
* name server. If the name server does not have any information on the
* name, the request will be forwarded on. The records returned may not be
* complete. For example, if there is both an A and an MX for a name, but
* the name server has only the A record cached, only the A record will be
* returned. Sometimes referred to as ANY, for example in Windows nslookup
* and Wireshark.
*/
public static final DnsType ANY = new DnsType(0x00ff, "ANY");
/**
* Certification Authority Authorization record RFC 6844 CA pinning,
* constraining acceptable CAs for a host/domain.
*/
public static final DnsType CAA = new DnsType(0x0101, "CAA");
/**
* DNSSEC Trust Authorities record N/A Part of a deployment proposal for
* DNSSEC without a signed DNS root. See the IANA database and Weiler Spec
* for details. Uses the same format as the DS record.
*/
public static final DnsType TA = new DnsType(0x8000, "TA");
/**
* DNSSEC Lookaside Validation record RFC 4431 For publishing DNSSEC trust
* anchors outside of the DNS delegation chain. Uses the same format as the
* DS record. RFC 5074 describes a way of using these records.
*/
public static final DnsType DLV = new DnsType(0x8001, "DLV");
private static final Map<String, DnsType> BY_NAME
= new HashMap<String, DnsType>();
private static final IntObjectHashMap<DnsType> BY_TYPE
= new IntObjectHashMap<DnsType>();
static {
DnsType[] all = {A, NS, CNAME, SOA, PTR, MX,
TXT, RP, AFSDB, SIG, KEY, AAAA, LOC,
SRV, NAPTR, KX, CERT, DNAME, OPT,
APL, DS, SSHFP, IPSECKEY, RRSIG, NSEC,
DNSKEY, DHCID, NSEC3, NSEC3PARAM, TLSA,
HIP, SPF, TKEY, TSIG, IXFR, AXFR,
ANY, CAA, TA, DLV};
for (DnsType type : all) {
BY_NAME.put(type.name(), type);
BY_TYPE.put(type.type(), type);
}
}
private final int type;
private final String name;
DnsType(int type, String name) {
if ((type & 0xffff) != type) {
throw new IllegalArgumentException("type: " + type
+ " (expected: 0 ~ 65535)");
}
this.type = type;
this.name = name;
}
/**
* Returns the name of this type, as seen in bind config files
*/
public final String name() {
return name;
}
/**
* Returns the value of this DnsType as it appears in DNS protocol
*/
public final int type() {
return type;
}
/**
* Returns a new DnsType instance
*/
public static DnsType create(int type, String name) {
return new DnsType(type, name);
}
@Override
public final int hashCode() {
return type;
}
@Override
public final boolean equals(Object o) {
return o instanceof DnsType && ((DnsType) o).type == type;
}
@Override
public final String toString() {
return name;
}
public static DnsType valueOf(int type) {
DnsType result = BY_TYPE.get(type);
if (result == null) {
throw new IllegalArgumentException("type: " + type
+ "(expected: " + keysString() + ")");
}
return result;
}
private static CharSequence keysString() {
// Replace with Objects.toString(BY_TYPE.keys()) when JDK 7 supported
StringBuilder sb = new StringBuilder();
for (int key : BY_TYPE.keys()) {
if (sb.length() > 0) {
sb.append(", ");
}
sb.append(key);
}
return sb;
}
public static DnsType forName(String name) {
DnsType result = BY_NAME.get(name);
if (result == null) {
throw new IllegalArgumentException("name: " + name
+ " (expected: " + BY_NAME.keySet() + ")");
}
return result;
}
}

View File

@ -0,0 +1,84 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.handler.codec.dns;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertSame;
import org.junit.Test;
public class DnsClassTest {
private List<DnsClass> allTypes() throws Exception {
List<DnsClass> result = new ArrayList<DnsClass>();
for (Field field : DnsClass.class.getDeclaredFields()) {
if ((field.getModifiers() & Modifier.STATIC) != 0) {
result.add((DnsClass) field.get(null));
}
}
assertFalse(result.isEmpty());
return result;
}
@Test
public void testSanity() throws Exception {
assertEquals("More than one type has the same int value",
allTypes().size(), new HashSet(allTypes()).size());
}
/**
* Test of hashCode method, of class DnsClass.
*/
@Test
public void testHashCode() throws Exception {
for (DnsClass t : allTypes()) {
assertEquals(t.clazz(), t.hashCode());
}
}
/**
* Test of equals method, of class DnsClass.
*/
@Test
public void testEquals() throws Exception {
for (DnsClass t1 : allTypes()) {
for (DnsClass t2 : allTypes()) {
if (t1 != t2) {
assertNotEquals(t1, t2);
}
}
}
}
/**
* Test of find method, of class DnsClass.
*/
@Test
public void testFind() throws Exception {
for (DnsClass t : allTypes()) {
DnsClass found = DnsClass.valueOf(t.clazz());
assertSame(t, found);
found = DnsClass.forName(t.toString());
assertSame(t.toString(), t, found);
}
}
}

View File

@ -32,11 +32,11 @@ public class DnsQueryTest {
InetSocketAddress addr = new InetSocketAddress(0); InetSocketAddress addr = new InetSocketAddress(0);
EmbeddedChannel embedder = new EmbeddedChannel(new DnsQueryEncoder()); EmbeddedChannel embedder = new EmbeddedChannel(new DnsQueryEncoder());
List<DnsQuery> queries = new ArrayList<DnsQuery>(5); List<DnsQuery> queries = new ArrayList<DnsQuery>(5);
queries.add(new DnsQuery(1, addr).addQuestion(new DnsQuestion("1.0.0.127.in-addr.arpa", DnsEntry.TYPE_PTR))); queries.add(new DnsQuery(1, addr).addQuestion(new DnsQuestion("1.0.0.127.in-addr.arpa", DnsType.PTR)));
queries.add(new DnsQuery(1, addr).addQuestion(new DnsQuestion("www.example.com", DnsEntry.TYPE_A))); queries.add(new DnsQuery(1, addr).addQuestion(new DnsQuestion("www.example.com", DnsType.A)));
queries.add(new DnsQuery(1, addr).addQuestion(new DnsQuestion("example.com", DnsEntry.TYPE_AAAA))); queries.add(new DnsQuery(1, addr).addQuestion(new DnsQuestion("example.com", DnsType.AAAA)));
queries.add(new DnsQuery(1, addr).addQuestion(new DnsQuestion("example.com", DnsEntry.TYPE_MX))); queries.add(new DnsQuery(1, addr).addQuestion(new DnsQuestion("example.com", DnsType.MX)));
queries.add(new DnsQuery(1, addr).addQuestion(new DnsQuestion("example.com", DnsEntry.TYPE_CNAME))); queries.add(new DnsQuery(1, addr).addQuestion(new DnsQuestion("example.com", DnsType.CNAME)));
for (DnsQuery query: queries) { for (DnsQuery query: queries) {
Assert.assertEquals("Invalid question count, expected 1.", 1, query.header().questionCount()); Assert.assertEquals("Invalid question count, expected 1.", 1, query.header().questionCount());

View File

@ -0,0 +1,81 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.handler.codec.dns;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import org.junit.Test;
import static org.junit.Assert.*;
public class DnsTypeTest {
private List<DnsType> allTypes() throws Exception {
List<DnsType> result = new ArrayList<DnsType>();
for (Field field : DnsType.class.getFields()) {
if ((field.getModifiers() & Modifier.STATIC) != 0 && DnsType.class == field.getType()) {
result.add((DnsType) field.get(null));
}
}
assertFalse(result.isEmpty());
return result;
}
@Test
public void testSanity() throws Exception {
assertEquals("More than one type has the same int value",
allTypes().size(), new HashSet(allTypes()).size());
}
/**
* Test of hashCode method, of class DnsType.
*/
@Test
public void testHashCode() throws Exception {
for (DnsType t : allTypes()) {
assertEquals(t.type(), t.hashCode());
}
}
/**
* Test of equals method, of class DnsType.
*/
@Test
public void testEquals() throws Exception {
for (DnsType t1 : allTypes()) {
for (DnsType t2 : allTypes()) {
if (t1 != t2) {
assertNotEquals(t1, t2);
}
}
}
}
/**
* Test of find method, of class DnsType.
*/
@Test
public void testFind() throws Exception {
for (DnsType t : allTypes()) {
DnsType found = DnsType.valueOf(t.type());
assertSame(t, found);
found = DnsType.forName(t.toString());
assertSame(t.toString(), t, found);
}
}
}