Added DNS message compression, it does not handle it right now
This commit is contained in:
parent
e69ab31dd2
commit
e8e3deb056
5 changed files with 174 additions and 9 deletions
|
|
@ -128,8 +128,9 @@ public class Converter {
|
|||
*
|
||||
* @param hex is the hex value
|
||||
* @return a byte that corresponds to the hex
|
||||
* @throws IllegalArgumentException if hex is not a valid hex character
|
||||
*/
|
||||
public static byte hexToByte( char hex ){
|
||||
public static byte hexToByte( char hex ) throws IllegalArgumentException{
|
||||
switch( Character.toLowerCase(hex) ){
|
||||
case '0': return 0x00;
|
||||
case '1': return 0x01;
|
||||
|
|
@ -147,8 +148,9 @@ public class Converter {
|
|||
case 'd': return 0x0d;
|
||||
case 'e': return 0x0e;
|
||||
case 'f': return 0x0f;
|
||||
default:
|
||||
throw new IllegalArgumentException("'"+hex+"' is an illegal hex character only 0-9 and a-f characters allowed");
|
||||
}
|
||||
return (byte)0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ import java.util.List;
|
|||
/**
|
||||
* This class is a general wrapper for a whole DNS packet.
|
||||
*
|
||||
* Created by Ziver on 2016-04-11.
|
||||
* @see <a href="https://tools.ietf.org/html/rfc1035">rfc1035</a>
|
||||
* @author Ziver on 2016-04-11.
|
||||
*/
|
||||
public class DNSPacket {
|
||||
private DNSPacketHeader header;
|
||||
|
|
|
|||
|
|
@ -151,14 +151,23 @@ public class DNSPacketQuestion implements BinaryStruct {
|
|||
public String read(InputStream in, BinaryFieldData field) throws IOException {
|
||||
StringBuilder str = new StringBuilder();
|
||||
int c = in.read();
|
||||
while (c > 0){
|
||||
for (int i=0; i<c; ++i){
|
||||
str.append((char)in.read());
|
||||
// Is this a pointer
|
||||
if ((c & 0b1100_0000) == 0b1100_0000 ){
|
||||
int offset = (c & 0b0011_1111) << 8;
|
||||
offset |= in.read() & 0b1111_1111;
|
||||
str.append(offset);
|
||||
}
|
||||
// Normal Domain String
|
||||
else {
|
||||
while (c > 0) {
|
||||
for (int i = 0; i < c; ++i) {
|
||||
str.append((char) in.read());
|
||||
}
|
||||
c = in.read();
|
||||
if (c > 0)
|
||||
str.append('.');
|
||||
}
|
||||
}
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -156,4 +156,18 @@ public class BinaryFieldData {
|
|||
public BinaryFieldSerializer getSerializer(){
|
||||
return serializer;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return field.getDeclaringClass().getSimpleName() + "::" + field.getName() +
|
||||
" (" +
|
||||
(lengthField != null ?
|
||||
"LengthField: " + lengthField +", LengthMultiplier: "+lengthMultiplier :
|
||||
length+" bits") +
|
||||
(serializer != null ?
|
||||
", Serializer: " + serializer.getClass().getName() : "") +
|
||||
")";
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -173,4 +173,143 @@ public class DNSPacketTest {
|
|||
assertEquals("IPv4", new String(new char[]{0x99, 0x6d, 0x07, 0x5a}), answer.data);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void rawQuery() throws IOException {
|
||||
/*
|
||||
Source: http://serverfault.com/questions/173187/what-does-a-dns-request-look-like
|
||||
The DNS part starts with 24 1a:
|
||||
0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ........ ......E.
|
||||
0010 00 3c 51 e3 40 00 40 11 ea cb 7f 00 00 01 7f 00 .<Q.@.@. ........
|
||||
0020 00 01 ec ed 00 35 00 28 fe 3b 24 1a 01 00 00 01 .....5.( .;$.....
|
||||
0030 00 00 00 00 00 00 03 77 77 77 06 67 6f 6f 67 6c .......w ww.googl
|
||||
0040 65 03 63 6f 6d 00 00 01 00 01 e.com... ..
|
||||
|
||||
Domain Name System (query)
|
||||
[Response In: 1852]
|
||||
Transaction ID: 0x241a
|
||||
Flags: 0x0100 (Standard query)
|
||||
0... .... .... .... = Response: Message is a query
|
||||
.000 0... .... .... = Opcode: Standard query (0)
|
||||
.... ..0. .... .... = Truncated: Message is not truncated
|
||||
.... ...1 .... .... = Recursion desired: Do query recursively
|
||||
.... .... .0.. .... = Z: reserved (0)
|
||||
.... .... ...0 .... = Non-authenticated data OK: Non-authenticated data is unacceptable
|
||||
Questions: 1
|
||||
Answer RRs: 0
|
||||
Authority RRs: 0
|
||||
Additional RRs: 0
|
||||
Queries
|
||||
www.google.com: type A, class IN
|
||||
Name: www.google.com
|
||||
Type: A (Host address)
|
||||
Class: IN (0x0001)
|
||||
*/
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rawMultiAnswer() throws IOException {
|
||||
/*
|
||||
Source: http://serverfault.com/questions/173187/what-does-a-dns-request-look-like
|
||||
the repsonse, again starting at 24 1a:
|
||||
0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ........ ......E.
|
||||
0010 00 7a 00 00 40 00 40 11 3c 71 7f 00 00 01 7f 00 .z..@.@. <q......
|
||||
0020 00 01 00 35 ec ed 00 66 fe 79 24 1a 81 80 00 01 ...5...f .y$.....
|
||||
0030 00 03 00 00 00 00 03 77 77 77 06 67 6f 6f 67 6c .......w ww.googl
|
||||
0040 65 03 63 6f 6d 00 00 01 00 01 c0 0c 00 05 00 01 e.com... ........
|
||||
0050 00 05 28 39 00 12 03 77 77 77 01 6c 06 67 6f 6f ..(9...w ww.l.goo
|
||||
0060 67 6c 65 03 63 6f 6d 00 c0 2c 00 01 00 01 00 00 gle.com. .,......
|
||||
0070 00 e3 00 04 42 f9 59 63 c0 2c 00 01 00 01 00 00 ....B.Yc .,......
|
||||
0080 00 e3 00 04 42 f9 59 68 ....B.Yh
|
||||
|
||||
Domain Name System (response)
|
||||
[Request In: 1851]
|
||||
[Time: 0.000125000 seconds]
|
||||
Transaction ID: 0x241a
|
||||
Flags: 0x8180 (Standard query response, No error)
|
||||
1... .... .... .... = Response: Message is a response
|
||||
.000 0... .... .... = Opcode: Standard query (0)
|
||||
.... .0.. .... .... = Authoritative: Server is not an authority for domain
|
||||
.... ..0. .... .... = Truncated: Message is not truncated
|
||||
.... ...1 .... .... = Recursion desired: Do query recursively
|
||||
.... .... 1... .... = Recursion available: Server can do recursive queries
|
||||
.... .... .0.. .... = Z: reserved (0)
|
||||
.... .... ..0. .... = Answer authenticated: Answer/authority portion was not authenticated by the server
|
||||
.... .... .... 0000 = Reply code: No error (0)
|
||||
Questions: 1
|
||||
Answer RRs: 3
|
||||
Authority RRs: 0
|
||||
Additional RRs: 0
|
||||
Queries
|
||||
www.google.com: type A, class IN
|
||||
Name: www.google.com
|
||||
Type: A (Host address)
|
||||
Class: IN (0x0001)
|
||||
Answers
|
||||
www.google.com: type CNAME, class IN, cname www.l.google.com
|
||||
Name: www.google.com
|
||||
Type: CNAME (Canonical name for an alias)
|
||||
Class: IN (0x0001)
|
||||
Time to live: 3 days, 21 hours, 52 minutes, 57 seconds
|
||||
Data length: 18
|
||||
Primary name: www.l.google.com
|
||||
www.l.google.com: type A, class IN, addr 66.249.89.99
|
||||
Name: www.l.google.com
|
||||
Type: A (Host address)
|
||||
Class: IN (0x0001)
|
||||
Time to live: 3 minutes, 47 seconds
|
||||
Data length: 4
|
||||
Addr: 66.249.89.99
|
||||
www.l.google.com: type A, class IN, addr 66.249.89.104
|
||||
Name: www.l.google.com
|
||||
Type: A (Host address)
|
||||
Class: IN (0x0001)
|
||||
Time to live: 3 minutes, 47 seconds
|
||||
Data length: 4
|
||||
Addr: 66.249.89.104
|
||||
*/
|
||||
byte[] input = Converter.hexToByte((
|
||||
"24 1a 81 80 00 01 00 03 00 00 00 00" + // Header
|
||||
"03 77 77 77 06 67 6f 6f 67 6c 65 03 63 6f 6d 00 0001 0001" + // Question
|
||||
"c00c 0005 0001 00052839 0012 03 77 77 77 01 6c 06 67 6f 6f 67 6c 65 03 63 6f 6d 00" + // Answer1
|
||||
"c02c 0001 0001 000000e3 0004 42 f9 59 63" + // Answer2
|
||||
"c02c 0001 0001 000000e3 0004 42 f9 59 68" // Answer3
|
||||
).replace(" ", ""));
|
||||
ByteArrayInputStream buffer = new ByteArrayInputStream(input);
|
||||
BinaryStructInputStream in = new BinaryStructInputStream(buffer);
|
||||
DNSPacket packet = DNSPacket.read(in);
|
||||
|
||||
assertEquals("id", 0x241a, packet.getHeader().id);
|
||||
assertTrue("flagQueryResponse", packet.getHeader().flagQueryResponse);
|
||||
assertEquals("No Of Question records", 1, packet.getHeader().countQuestion);
|
||||
assertEquals("No Of Answer records", 3, packet.getHeader().countAnswerRecord);
|
||||
assertEquals("No Of NameServer records", 0, packet.getHeader().countNameServer);
|
||||
assertEquals("No Of Additional records", 0, packet.getHeader().countAdditionalRecord);
|
||||
|
||||
// Query
|
||||
DNSPacketQuestion question = packet.getQuestions().get(0);
|
||||
assertEquals("qNAME", "www.google.com", question.qName);
|
||||
assertEquals("qType", DNSPacketQuestion.QTYPE_A, question.qType);
|
||||
assertEquals("qClass", DNSPacketQuestion.QCLASS_IN, question.qClass);
|
||||
|
||||
// Answer
|
||||
DNSPacketResource answer = packet.getAnswerRecords().get(0);
|
||||
assertEquals("NAME", "12", answer.name);
|
||||
assertEquals("TYPE", TYPE_CNAME, answer.type);
|
||||
assertEquals("CLASS", CLASS_IN, answer.clazz);
|
||||
assertEquals("TTL", 337977, answer.ttl);
|
||||
|
||||
answer = packet.getAnswerRecords().get(1);
|
||||
assertEquals("NAME", "44", answer.name);
|
||||
assertEquals("TYPE", TYPE_A, answer.type);
|
||||
assertEquals("CLASS", CLASS_IN, answer.clazz);
|
||||
assertEquals("TTL", 227, answer.ttl);
|
||||
|
||||
answer = packet.getAnswerRecords().get(2);
|
||||
assertEquals("NAME", "44", answer.name);
|
||||
assertEquals("TYPE", TYPE_A, answer.type);
|
||||
assertEquals("CLASS", CLASS_IN, answer.clazz);
|
||||
assertEquals("TTL", 227, answer.ttl);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue