EDNS Client Subnet is not encoded correctly when source prefix length is not a multiple of 8.
Motivation: When the ECS source prefix length is not a mutiple of 8, the last byte the address inside the ECS OPT record is not padded properly. Modifications: DefaultDnsRecordEncoder.padWithZeros(...) was modified to add padding from the least significant bits. Result: ECS encoding bug fixed.
This commit is contained in:
parent
3c8f4b81d7
commit
32746c53c1
@ -162,25 +162,24 @@ public class DefaultDnsRecordEncoder implements DnsRecordEncoder {
|
|||||||
buf.writeByte(0); // marks end of name field
|
buf.writeByte(0); // marks end of name field
|
||||||
}
|
}
|
||||||
|
|
||||||
// Package private so it can be reused in the test.
|
private static byte padWithZeros(byte b, int lowOrderBitsToPreserve) {
|
||||||
static byte padWithZeros(byte b, int lowOrderBitsToPreserve) {
|
|
||||||
switch (lowOrderBitsToPreserve) {
|
switch (lowOrderBitsToPreserve) {
|
||||||
case 0:
|
case 0:
|
||||||
return 0;
|
return 0;
|
||||||
case 1:
|
case 1:
|
||||||
return (byte) (0x01 & b);
|
return (byte) (0x80 & b);
|
||||||
case 2:
|
case 2:
|
||||||
return (byte) (0x03 & b);
|
return (byte) (0xC0 & b);
|
||||||
case 3:
|
case 3:
|
||||||
return (byte) (0x07 & b);
|
return (byte) (0xE0 & b);
|
||||||
case 4:
|
case 4:
|
||||||
return (byte) (0x0F & b);
|
return (byte) (0xF0 & b);
|
||||||
case 5:
|
case 5:
|
||||||
return (byte) (0x1F & b);
|
return (byte) (0xF8 & b);
|
||||||
case 6:
|
case 6:
|
||||||
return (byte) (0x3F & b);
|
return (byte) (0xFC & b);
|
||||||
case 7:
|
case 7:
|
||||||
return (byte) (0x7F & b);
|
return (byte) (0xFE & b);
|
||||||
case 8:
|
case 8:
|
||||||
return b;
|
return b;
|
||||||
default:
|
default:
|
||||||
|
@ -71,11 +71,13 @@ public class DefaultDnsRecordEncoderTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testOptEcsRecordIpv4() throws Exception {
|
public void testOptEcsRecordIpv4() throws Exception {
|
||||||
testOptEcsRecordIp(SocketUtils.addressByName("1.2.3.4"));
|
testOptEcsRecordIp(SocketUtils.addressByName("1.2.3.4"));
|
||||||
|
testOptEcsRecordIp(SocketUtils.addressByName("1.2.3.255"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOptEcsRecordIpv6() throws Exception {
|
public void testOptEcsRecordIpv6() throws Exception {
|
||||||
testOptEcsRecordIp(SocketUtils.addressByName("::0"));
|
testOptEcsRecordIp(SocketUtils.addressByName("::0"));
|
||||||
|
testOptEcsRecordIp(SocketUtils.addressByName("::FF"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void testOptEcsRecordIp(InetAddress address) throws Exception {
|
private static void testOptEcsRecordIp(InetAddress address) throws Exception {
|
||||||
@ -95,7 +97,8 @@ public class DefaultDnsRecordEncoderTest {
|
|||||||
// Pad the leftover of the last byte with zeros.
|
// Pad the leftover of the last byte with zeros.
|
||||||
int idx = addressPart.writerIndex() - 1;
|
int idx = addressPart.writerIndex() - 1;
|
||||||
byte lastByte = addressPart.getByte(idx);
|
byte lastByte = addressPart.getByte(idx);
|
||||||
addressPart.setByte(idx, DefaultDnsRecordEncoder.padWithZeros(lastByte, lowOrderBitsToPreserve));
|
int paddingMask = ~((1 << (8 - lowOrderBitsToPreserve)) - 1);
|
||||||
|
addressPart.setByte(idx, lastByte & paddingMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
int payloadSize = nextInt(Short.MAX_VALUE);
|
int payloadSize = nextInt(Short.MAX_VALUE);
|
||||||
|
Loading…
Reference in New Issue
Block a user