Add EDNS support to DnsQueryEncoder

Motivation:

DnsQueryEncoder does not encode the 'additional resources' section at all, which contains the pseudo-RR as defined in RFC 2671.

Modifications:

- Modify DnsQueryEncoder to encode the additional resources
- Fix a bug in DnsQueryEncoder where an empty name is encoded incorrectly

Result:

A user can send an EDNS query.
This commit is contained in:
Trustin Lee 2014-10-07 14:58:43 +09:00
parent 87c82d4845
commit ab2e80fbb1

View File

@ -40,7 +40,10 @@ public class DnsQueryEncoder extends MessageToMessageEncoder<DnsQuery> {
encodeHeader(query.header(), buf); encodeHeader(query.header(), buf);
List<DnsQuestion> questions = query.questions(); List<DnsQuestion> questions = query.questions();
for (DnsQuestion question : questions) { for (DnsQuestion question : questions) {
encodeQuestion(question, CharsetUtil.UTF_8, buf); encodeQuestion(question, CharsetUtil.US_ASCII, buf);
}
for (DnsResource resource: query.additionalResources()) {
encodeResource(resource, CharsetUtil.US_ASCII, buf);
} }
out.add(new DatagramPacket(buf, query.recipient(), null)); out.add(new DatagramPacket(buf, query.recipient(), null));
} }
@ -62,9 +65,9 @@ public class DnsQueryEncoder extends MessageToMessageEncoder<DnsQuery> {
flags |= header.isRecursionDesired() ? 1 << 8 : 0; flags |= header.isRecursionDesired() ? 1 << 8 : 0;
buf.writeShort(flags); buf.writeShort(flags);
buf.writeShort(header.questionCount()); buf.writeShort(header.questionCount());
buf.writeShort(header.answerCount()); // Must be 0 buf.writeShort(0); // answerCount
buf.writeShort(header.authorityResourceCount()); // Must be 0 buf.writeShort(0); // authorityResourceCount
buf.writeShort(header.additionalResourceCount()); // Must be 0 buf.writeShort(header.additionalResourceCount());
} }
/** /**
@ -79,13 +82,35 @@ public class DnsQueryEncoder extends MessageToMessageEncoder<DnsQuery> {
* the buffer the encoded data should be written to * the buffer the encoded data should be written to
*/ */
private static void encodeQuestion(DnsQuestion question, Charset charset, ByteBuf buf) { private static void encodeQuestion(DnsQuestion question, Charset charset, ByteBuf buf) {
String[] parts = StringUtil.split(question.name(), '.'); encodeName(question.name(), charset, buf);
for (String part: parts) {
buf.writeByte(part.length());
buf.writeBytes(part.getBytes(charset));
}
buf.writeByte(0); // marks end of name field
buf.writeShort(question.type().intValue()); buf.writeShort(question.type().intValue());
buf.writeShort(question.dnsClass().intValue()); buf.writeShort(question.dnsClass().intValue());
} }
private static void encodeResource(DnsResource resource, Charset charset, ByteBuf buf) {
encodeName(resource.name(), charset, buf);
buf.writeShort(resource.type().intValue());
buf.writeShort(resource.dnsClass().intValue());
buf.writeInt((int) resource.timeToLive());
ByteBuf content = resource.content();
int contentLen = content.readableBytes();
buf.writeShort(contentLen);
buf.writeBytes(content, content.readerIndex(), contentLen);
}
private static void encodeName(String name, Charset charset, ByteBuf buf) {
String[] parts = StringUtil.split(name, '.');
for (String part: parts) {
final int partLen = part.length();
if (partLen == 0) {
continue;
}
buf.writeByte(partLen);
buf.writeBytes(part.getBytes(charset));
}
buf.writeByte(0); // marks end of name field
}
} }