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:
Thomas Devanneaux 2017-11-28 10:20:42 -08:00 committed by Norman Maurer
parent 3c8f4b81d7
commit 32746c53c1
2 changed files with 12 additions and 10 deletions

View File

@ -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:

View File

@ -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);