Fixed a DNS bug and added IPv6 entry
This commit is contained in:
parent
e42d25fa99
commit
946f5f5133
5 changed files with 157 additions and 19 deletions
|
|
@ -92,7 +92,7 @@ public class MulticastDnsServer extends ThreadedUDPNetwork implements ThreadedUD
|
|||
resource.name = name;
|
||||
resource.type = type;
|
||||
resource.clazz = clazz;
|
||||
//resource.ttl = 10; ???
|
||||
resource.ttl = 120; // client can cache the record for 2 min
|
||||
resource.length = data.length;
|
||||
resource.data = new String(data, StandardCharsets.ISO_8859_1);
|
||||
|
||||
|
|
@ -118,6 +118,7 @@ public class MulticastDnsServer extends ThreadedUDPNetwork implements ThreadedUD
|
|||
// Just handle queries and no responses
|
||||
if (! dnsPacket.getHeader().flagQueryResponse) {
|
||||
DnsPacket response = handleReceivedPacket(packet.getAddress(), dnsPacket);
|
||||
|
||||
if (response != null) {
|
||||
ByteArrayOutputStream outBuffer = new ByteArrayOutputStream();
|
||||
BinaryStructOutputStream out = new BinaryStructOutputStream(outBuffer);
|
||||
|
|
@ -139,6 +140,7 @@ public class MulticastDnsServer extends ThreadedUDPNetwork implements ThreadedUD
|
|||
protected DnsPacket handleReceivedPacket(InetAddress address, DnsPacket request) {
|
||||
DnsPacket response = new DnsPacket();
|
||||
response.getHeader().setDefaultResponseData();
|
||||
|
||||
for (DnsPacketQuestion question : request.getQuestions()) {
|
||||
if (question.name == null) continue;
|
||||
|
||||
|
|
@ -148,8 +150,9 @@ public class MulticastDnsServer extends ThreadedUDPNetwork implements ThreadedUD
|
|||
// ------------------------------------------
|
||||
|
||||
case DnsConstants.TYPE.A:
|
||||
case DnsConstants.TYPE.AAAA:
|
||||
if (entries.containsKey(question.name)) {
|
||||
logger.finer("Received request for domain: '" + question.name + "' from source: " + address);
|
||||
logger.finer("Received request for IPv4 domain: '" + question.name + "' from source: " + address);
|
||||
response.addAnswerRecord(entries.get(question.name));
|
||||
} else {
|
||||
logger.finest("Received request for unknown domain: '" + question.name + "' from source: " + address);
|
||||
|
|
@ -175,7 +178,7 @@ public class MulticastDnsServer extends ThreadedUDPNetwork implements ThreadedUD
|
|||
logger.finer("Received request for service: '" + question.name + "' from source: " + address);
|
||||
response.addAnswerRecord(entries.get(question.name));
|
||||
} else {
|
||||
logger.finer("Received request for unknown pointer: '" + question.name + "' from source: " + address);
|
||||
logger.finest("Received request for unknown pointer: '" + question.name + "' from source: " + address);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ public final class DnsConstants {
|
|||
|
||||
|
||||
public static final class TYPE {
|
||||
/** a host address */
|
||||
/** a IPv4 host address */
|
||||
public static final int A = 1;
|
||||
/** an authoritative name server */
|
||||
public static final int NS = 2;
|
||||
|
|
@ -111,6 +111,8 @@ public final class DnsConstants {
|
|||
public static final int MX = 15;
|
||||
/** text strings */
|
||||
public static final int TXT = 16;
|
||||
/** a IPv6 host address */
|
||||
public static final int AAAA = 28;
|
||||
/** service location record in format {Instance}.{Service}.{Domain}*/
|
||||
public static final int SRV = 33;
|
||||
/** A request for a transfer of an entire zone */
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ public class DnsPacketQuestion implements BinaryStruct {
|
|||
*
|
||||
* @see DnsConstants.TYPE
|
||||
*/
|
||||
@BinaryField(index=10, length=16)
|
||||
@BinaryField(index=20, length=16)
|
||||
public int type;
|
||||
|
||||
/**
|
||||
|
|
@ -77,7 +77,7 @@ public class DnsPacketQuestion implements BinaryStruct {
|
|||
*
|
||||
* @see DnsConstants.CLASS
|
||||
*/
|
||||
@BinaryField(index=20, length=16)
|
||||
@BinaryField(index=30, length=16)
|
||||
public int clazz;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -38,22 +38,22 @@ public class FQDNStringSerializer implements BinaryFieldSerializer<String> {
|
|||
|
||||
public String read(InputStream in, BinaryFieldData field) throws IOException {
|
||||
StringBuilder str = new StringBuilder();
|
||||
int c = 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) {
|
||||
int c;
|
||||
|
||||
while ((c=in.read()) > 0) {
|
||||
if (str.length() > 0) // Don't add dot to first loop
|
||||
str.append('.');
|
||||
|
||||
if ((c & 0b1100_0000) == 0b1100_0000) {
|
||||
// This a pointer
|
||||
int offset = (c & 0b0011_1111) << 8;
|
||||
offset |= in.read() & 0b1111_1111;
|
||||
str.append(offset);
|
||||
} else {
|
||||
// Normal String
|
||||
for (int i = 0; i < c; ++i) {
|
||||
str.append((char) in.read());
|
||||
}
|
||||
c = in.read();
|
||||
if (c > 0)
|
||||
str.append('.');
|
||||
}
|
||||
}
|
||||
return str.toString();
|
||||
|
|
|
|||
|
|
@ -332,4 +332,137 @@ Domain Name System (response)
|
|||
assertEquals("CLASS", DnsConstants.CLASS.IN, answer.clazz);
|
||||
assertEquals("TTL", 227, answer.ttl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rawIphoneQuery() throws IOException {
|
||||
/*
|
||||
0000 00 00 00 00 00 06 00 00 00 00 00 01 0f 5f 63 6f ............._co
|
||||
0010 6d 70 61 6e 69 6f 6e 2d 6c 69 6e 6b 04 5f 74 63 mpanion-link._tc
|
||||
0020 70 05 6c 6f 63 61 6c 00 00 0c 00 01 08 5f 68 6f p.local......_ho
|
||||
0030 6d 65 6b 69 74 c0 1c 00 0c 00 01 03 68 61 6c c0 mekit.......hal.
|
||||
0040 21 00 41 00 01 c0 3b 00 1c 00 01 c0 3b 00 01 00 !.A...;.....;...
|
||||
0050 01 0c 5f 73 6c 65 65 70 2d 70 72 6f 78 79 04 5f .._sleep-proxy._
|
||||
0060 75 64 70 c0 21 00 0c 00 01 00 00 29 05 a0 00 00 udp.!......)....
|
||||
0070 11 94 00 12 00 04 00 0e 00 65 7a e6 ba 29 34 00 .........ez..)4.
|
||||
0080 d6 07 3a f2 2e e7 ..:...
|
||||
|
||||
|
||||
|
||||
Multicast Domain Name System (query)
|
||||
Transaction ID: 0x0000
|
||||
Flags: 0x0000 Standard query
|
||||
Questions: 6
|
||||
Answer RRs: 0
|
||||
Authority RRs: 0
|
||||
Additional RRs: 1
|
||||
Queries
|
||||
_companion-link._tcp.local: type PTR, class IN, "QM" question
|
||||
Name: _companion-link._tcp.local
|
||||
[Name Length: 26]
|
||||
[Label Count: 3]
|
||||
Type: PTR (domain name PoinTeR) (12)
|
||||
.000 0000 0000 0001 = Class: IN (0x0001)
|
||||
0... .... .... .... = "QU" question: False
|
||||
_homekit._tcp.local: type PTR, class IN, "QM" question
|
||||
Name: _homekit._tcp.local
|
||||
[Name Length: 19]
|
||||
[Label Count: 3]
|
||||
Type: PTR (domain name PoinTeR) (12)
|
||||
.000 0000 0000 0001 = Class: IN (0x0001)
|
||||
0... .... .... .... = "QU" question: False
|
||||
hal.local: type Unknown (65), class IN, "QM" question
|
||||
Name: hal.local
|
||||
[Name Length: 9]
|
||||
[Label Count: 2]
|
||||
Type: Unknown (65)
|
||||
.000 0000 0000 0001 = Class: IN (0x0001)
|
||||
0... .... .... .... = "QU" question: False
|
||||
hal.local: type AAAA, class IN, "QM" question
|
||||
Name: hal.local
|
||||
[Name Length: 9]
|
||||
[Label Count: 2]
|
||||
Type: AAAA (IPv6 Address) (28)
|
||||
.000 0000 0000 0001 = Class: IN (0x0001)
|
||||
0... .... .... .... = "QU" question: False
|
||||
hal.local: type A, class IN, "QM" question
|
||||
Name: hal.local
|
||||
[Name Length: 9]
|
||||
[Label Count: 2]
|
||||
Type: A (Host Address) (1)
|
||||
.000 0000 0000 0001 = Class: IN (0x0001)
|
||||
0... .... .... .... = "QU" question: False
|
||||
_sleep-proxy._udp.local: type PTR, class IN, "QM" question
|
||||
Name: _sleep-proxy._udp.local
|
||||
[Name Length: 23]
|
||||
[Label Count: 3]
|
||||
Type: PTR (domain name PoinTeR) (12)
|
||||
.000 0000 0000 0001 = Class: IN (0x0001)
|
||||
0... .... .... .... = "QU" question: False
|
||||
Additional records
|
||||
<Root>: type OPT
|
||||
Name: <Root>
|
||||
Type: OPT (41)
|
||||
.000 0101 1010 0000 = UDP payload size: 0x05a0
|
||||
0... .... .... .... = Cache flush: False
|
||||
Higher bits in extended RCODE: 0x00
|
||||
EDNS0 version: 0
|
||||
Z: 0x1194
|
||||
0... .... .... .... = DO bit: Cannot handle DNSSEC security RRs
|
||||
.001 0001 1001 0100 = Reserved: 0x1194
|
||||
Data length: 18
|
||||
Option: Owner (reserved)
|
||||
*/
|
||||
|
||||
byte[] input = Converter.hexToByte((
|
||||
"00 00 00 00 00 06 00 00 00 00 00 01" + // Header
|
||||
"0f 5f 63 6f 6d 70 61 6e 69 6f 6e 2d 6c 69 6e 6b 04 5f 74 63 70 05 6c 6f 63 61 6c 00 00 0c 00 01" + // Query PTR: _companion-link._tcp.local
|
||||
"08 5f 68 6f 6d 65 6b 69 74 c0 1c 00 0c 00 01" + // Query PTR: _homekit._tcp.local
|
||||
"03 68 61 6c c0 21 00 41 00 01" + // Query Unknown: hal.local
|
||||
"c0 3b 00 1c 00 01" + // Query IPv6: hal.local
|
||||
"c0 3b 00 01 00 01" + // Query IPv4: hal.local
|
||||
"0c 5f 73 6c 65 65 70 2d 70 72 6f 78 79 04 5f 75 64 70 c0 21 00 0c 00 01" + // Query PTR: _sleep-proxy._udp.local
|
||||
"00 00 29 05 a0 00 00 11 94 00 12 00 04 00 0e 00 65 7a e6 ba 29 34 00 d6 07 3a f2 2e e7" // Additional records
|
||||
).replace(" ", ""));
|
||||
ByteArrayInputStream buffer = new ByteArrayInputStream(input);
|
||||
BinaryStructInputStream in = new BinaryStructInputStream(buffer);
|
||||
DnsPacket packet = DnsPacket.read(in);
|
||||
|
||||
assertEquals("id", 0x00, packet.getHeader().id);
|
||||
assertFalse("flagQueryResponse", packet.getHeader().flagQueryResponse);
|
||||
assertEquals("No Of Question records", 6, packet.getHeader().countQuestion);
|
||||
assertEquals("No Of Answer records", 0, packet.getHeader().countAnswerRecord);
|
||||
assertEquals("No Of NameServer records", 0, packet.getHeader().countNameServer);
|
||||
assertEquals("No Of Additional records", 1, packet.getHeader().countAdditionalRecord);
|
||||
|
||||
// Query
|
||||
DnsPacketQuestion question1 = packet.getQuestions().get(0);
|
||||
assertEquals("qNAME", "_companion-link._tcp.local", question1.name);
|
||||
assertEquals("type", DnsConstants.TYPE.PTR, question1.type);
|
||||
assertEquals("clazz", DnsConstants.CLASS.IN, question1.clazz);
|
||||
|
||||
DnsPacketQuestion question2 = packet.getQuestions().get(1);
|
||||
//assertEquals("qNAME", "_homekit._tcp.local", question2.name);
|
||||
assertEquals("qNAME", "_homekit.28", question2.name); // TODO: Fix support for string pointers
|
||||
assertEquals("type", DnsConstants.TYPE.PTR, question2.type);
|
||||
assertEquals("clazz", DnsConstants.CLASS.IN, question2.clazz);
|
||||
|
||||
DnsPacketQuestion question3 = packet.getQuestions().get(2);
|
||||
assertEquals("qNAME", "hal.local", question3.name);
|
||||
assertEquals("clazz", DnsConstants.CLASS.IN, question3.clazz);
|
||||
|
||||
DnsPacketQuestion question4 = packet.getQuestions().get(3);
|
||||
assertEquals("qNAME", "hal.local", question4.name);
|
||||
assertEquals("type", DnsConstants.TYPE.AAAA, question4.type);
|
||||
assertEquals("clazz", DnsConstants.CLASS.IN, question4.clazz);
|
||||
|
||||
DnsPacketQuestion question5 = packet.getQuestions().get(4);
|
||||
assertEquals("qNAME", "hal.local", question5.name);
|
||||
assertEquals("type", DnsConstants.TYPE.A, question5.type);
|
||||
assertEquals("clazz", DnsConstants.CLASS.IN, question5.clazz);
|
||||
|
||||
DnsPacketQuestion question6 = packet.getQuestions().get(5);
|
||||
assertEquals("qNAME", "_sleep-proxy._udp.local", question6.name);
|
||||
assertEquals("type", DnsConstants.TYPE.PTR, question6.type);
|
||||
assertEquals("clazz", DnsConstants.CLASS.IN, question6.clazz);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue