From 31a47f52cd6b2c0794f288a7ca046ecfd4aef66d Mon Sep 17 00:00:00 2001 From: Ziver Koc Date: Mon, 18 Apr 2016 17:41:55 +0200 Subject: [PATCH] Added DNS packet TC --- src/zutil/net/dns/DNSPacket.java | 76 ++++++++++++++++--- src/zutil/net/dns/DNSPacketQuestion.java | 75 ++++++++++++++++-- src/zutil/net/dns/DNSPacketResource.java | 45 +++++++++++ .../binary/BinaryStructOutputStream.java | 1 + test/zutil/net/dns/DNSPacketTest.java | 55 +++++++++++++- 5 files changed, 232 insertions(+), 20 deletions(-) diff --git a/src/zutil/net/dns/DNSPacket.java b/src/zutil/net/dns/DNSPacket.java index 868933a..1a1fc9b 100755 --- a/src/zutil/net/dns/DNSPacket.java +++ b/src/zutil/net/dns/DNSPacket.java @@ -1,17 +1,19 @@ package zutil.net.dns; +import zutil.parser.binary.BinaryStructInputStream; import zutil.parser.binary.BinaryStructOutputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; +import java.util.Collections; +import java.util.List; /** * This class is a general wrapper for a whole DNS packet. * - * Created by ezivkoc on 2016-04-11. + * Created by Ziver on 2016-04-11. */ public class DNSPacket { private DNSPacketHeader header; @@ -30,23 +32,77 @@ public class DNSPacket { } - public static DNSPacket read(InputStream in){ - return null; + public DNSPacketHeader getHeader(){ + return header; + } + public List getQuestions(){ + return Collections.unmodifiableList(questions); + } + public List getAnswerRecords(){ + return Collections.unmodifiableList(answerRecords); + } + public List getNameServers(){ + return Collections.unmodifiableList(nameServers); + } + public List getAdditionalRecords(){ + return Collections.unmodifiableList(additionalRecords); + } + + + public void addQuestion(DNSPacketQuestion question){ + questions.add(question); + header.countQuestion = questions.size(); + } + public void addAnswerRecord(DNSPacketResource resource){ + answerRecords.add(resource); + header.countAnswerRecord = answerRecords.size(); + } + public void addNameServer(DNSPacketResource resource){ + nameServers.add(resource); + header.countNameServer = nameServers.size(); + } + public void addAdditionalRecord(DNSPacketResource resource){ + additionalRecords.add(resource); + header.countAdditionalRecord = additionalRecords.size(); + } + + + public static DNSPacket read(InputStream in) throws IOException { + BinaryStructInputStream structIn = new BinaryStructInputStream(in); + DNSPacket packet = new DNSPacket(); + structIn.read(packet.header); + + for (int i=0; i list) throws IOException { + for (int i=0; i { @@ -101,7 +164,7 @@ public class DNSPacketQuestion implements BinaryStruct { public void write(OutputStream out, String domain, BinaryFieldData field) throws IOException { if (domain != null){ - String[] labels = domain.split("."); + String[] labels = domain.split("\\."); for (String label : labels) { out.write(label.length()); out.write(label.getBytes()); diff --git a/src/zutil/net/dns/DNSPacketResource.java b/src/zutil/net/dns/DNSPacketResource.java index 6080803..810faa0 100755 --- a/src/zutil/net/dns/DNSPacketResource.java +++ b/src/zutil/net/dns/DNSPacketResource.java @@ -33,6 +33,51 @@ import zutil.parser.binary.BinaryStruct; */ public class DNSPacketResource implements BinaryStruct { + /** a host address */ + public static final int TYPE_A = 1; + /** an authoritative name server */ + public static final int TYPE_NS = 2; + /** a mail destination (Obsolete - use MX) */ + public static final int TYPE_MD = 3; + /** a mail forwarder (Obsolete - use MX) */ + public static final int TYPE_MF = 4; + /** the canonical name for an alias */ + public static final int TYPE_CNAME = 5; + /** marks the start of a zone of authority */ + public static final int TYPE_SOA = 6; + /** a mailbox domain name (EXPERIMENTAL) */ + public static final int TYPE_MB = 7; + /** a mail group member (EXPERIMENTAL) */ + public static final int TYPE_MG = 8; + /** a mail rename domain name (EXPERIMENTAL) */ + public static final int TYPE_MR = 9; + /** a null RR (EXPERIMENTAL) */ + public static final int TYPE_NULL = 10; + /** a well known service description */ + public static final int TYPE_WKS = 11; + /** a domain name pointer */ + public static final int TYPE_PTR = 12; + /** host information */ + public static final int TYPE_HINFO = 13; + /** mailbox or mail list information */ + public static final int TYPE_MINFO = 14; + /** mail exchange */ + public static final int TYPE_MX = 15; + /** text strings */ + public static final int TYPE_TXT = 16; + + /** the Internet */ + public static final int CLASS_IN = 1; + /** the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */ + public static final int CLASS_CS = 2; + /** the CHAOS class */ + public static final int CLASS_CH = 3; + /** Hesiod [Dyer 87] */ + public static final int CLASS_HS = 4; + + + + /* The answer, authority, and additional sections all share the same format: a variable number of resource records, where the number of diff --git a/src/zutil/parser/binary/BinaryStructOutputStream.java b/src/zutil/parser/binary/BinaryStructOutputStream.java index f903773..0bb2d2a 100755 --- a/src/zutil/parser/binary/BinaryStructOutputStream.java +++ b/src/zutil/parser/binary/BinaryStructOutputStream.java @@ -96,6 +96,7 @@ public class BinaryStructOutputStream { } } } + localFlush(); } diff --git a/test/zutil/net/dns/DNSPacketTest.java b/test/zutil/net/dns/DNSPacketTest.java index b9e97f2..87938a5 100755 --- a/test/zutil/net/dns/DNSPacketTest.java +++ b/test/zutil/net/dns/DNSPacketTest.java @@ -26,9 +26,12 @@ package zutil.net.dns; import org.junit.Test; import zutil.parser.binary.BinaryStructOutputStream; +import static zutil.net.dns.DNSPacketQuestion.*; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; /** @@ -37,7 +40,7 @@ import static org.junit.Assert.assertEquals; public class DNSPacketTest { @Test - public void headerQueryTest() throws IOException { + public void writeHeaderTest() throws IOException { DNSPacketHeader header = new DNSPacketHeader(); header.setDefaultQueryData(); header.countQuestion = 1; @@ -51,16 +54,60 @@ public class DNSPacketTest { } @Test - public void headerResponseTest() throws IOException { + public void readHheaderTest() throws IOException { DNSPacketHeader header = new DNSPacketHeader(); header.setDefaultResponseData(); header.countAnswerRecord = 1; byte[] data = BinaryStructOutputStream.serialize(header); assertEquals("header length", 12, data.length); - assertEquals("Flag byte1", (byte)0x84, data[2]); - assertEquals("Flag byte2", (byte)0x00, data[3]); + assertEquals("Flag byte1", (byte) 0x84, data[2]); + assertEquals("Flag byte2", (byte) 0x00, data[3]); assertEquals("Answer count byte1", 0x00, data[6]); assertEquals("Answer count byte2", 0x01, data[7]); } + + @Test + public void writeDnsPacketHeaderTest() throws IOException { + DNSPacket packet = new DNSPacket(); + packet.getHeader().setDefaultQueryData(); + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + packet.write(buffer); + byte[] data = buffer.toByteArray(); + + byte[] expected = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, // QDCOUNT + 0x00, 0x00, // ANCOUNT + 0x00, 0x00, // NSCOUNT + 0x00, 0x00, // ARCOUNT + }; + assertArrayEquals(expected, data); + } + + @Test + public void writeDnsPacketTest() throws IOException { + DNSPacket packet = new DNSPacket(); + packet.getHeader().setDefaultQueryData(); + packet.addQuestion(new DNSPacketQuestion("appletv.local", QTYPE_A, QCLASS_IN)); + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + packet.write(buffer); + byte[] data = buffer.toByteArray(); + + byte[] expected = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, // QDCOUNT + 0x00, 0x00, // ANCOUNT + 0x00, 0x00, // NSCOUNT + 0x00, 0x00, // ARCOUNT + 0x07, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x74, 0x76, // "apple" + 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, // "local" + 0x00, // NULL + 0x00, 0x01, // QTYPE + 0x00, 0x01 // QCLASS + }; + assertArrayEquals(expected, data); + } }