From: pascal.bouchareine Date: Tue, 8 Nov 2016 19:09:34 +0000 (-0800) Subject: Clarify ceiling, add tests, fix doc, fix python3 X-Git-Tag: v1.16.0~119^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2613b441f50ada2b60205ea37c4a8abe9594c6ff;p=thirdparty%2Fdnspython.git Clarify ceiling, add tests, fix doc, fix python3 - bad class doc - explicit ceil - python3 encoding issue - improve edns testing --- diff --git a/dns/edns.py b/dns/edns.py index 54f4e121..83b9be68 100644 --- a/dns/edns.py +++ b/dns/edns.py @@ -17,7 +17,9 @@ from __future__ import absolute_import +import math import struct +import sys import dns.inet @@ -145,9 +147,10 @@ class ECSOption(Option): @ivar srclen: prefix length, leftmost number of bits of the address to be used for the lookup. Sent by client, mirrored by server in responses. If not provided at init, will use /24 for v4 and /56 for v6 - @ivar srclen: int + @type srclen: int @ivar scopelen: prefix length, leftmost number of bits of the address that the response covers. 0 in queries, set by server. + @type scopelen: int """ super(ECSOption, self).__init__(ECS) af = dns.inet.af_for_address(address) @@ -167,13 +170,16 @@ class ECSOption(Option): self.scopelen = scopelen self.address = address - self.addrdata = dns.inet.inet_pton(af, address) + addrdata = dns.inet.inet_pton(af, address) + nbytes = int(math.ceil(srclen/8.0)) # Truncate to srclen and pad to the end of the last octet needed # See RFC section 6 - self.addrdata = self.addrdata[:-(-srclen//8)] - last = ord(self.addrdata[-1:]) & (0xff << srclen % 8) - self.addrdata = self.addrdata[:-1] + chr(last).encode('latin1') + self.addrdata = addrdata[:nbytes] + last = chr(ord(self.addrdata[-1:]) & (0xff << srclen % 8)) + if sys.version_info >= (3,): + last = last.encode('latin1') + self.addrdata = self.addrdata[:-1] + last def to_text(self): return "ECS %s/%s scope/%s" % (self.address, self.srclen, @@ -191,7 +197,7 @@ class ECSOption(Option): family, src, scope = struct.unpack('!HBB', wire[cur:cur+4]) cur += 4 - addrlen = -(-src//8) + addrlen = int(math.ceil(src/8.0)) if family == 1: af = dns.inet.AF_INET @@ -202,7 +208,7 @@ class ECSOption(Option): else: raise ValueError('unsupported family') - addr = dns.inet.inet_ntop(af, wire[cur:cur+addrlen] + '\x00' * pad) + addr = dns.inet.inet_ntop(af, wire[cur:cur+addrlen] + b'\x00' * pad) return cls(addr, src, scope) def _cmp(self, other): diff --git a/tests/test_option.py b/tests/test_edns.py similarity index 74% rename from tests/test_option.py rename to tests/test_edns.py index f91485ae..69d88e23 100644 --- a/tests/test_option.py +++ b/tests/test_edns.py @@ -33,6 +33,21 @@ class OptionTestCase(unittest.TestCase): data = io.getvalue() self.assertEqual(data, b'data') + def testECSOption_prefix_length(self): + opt = dns.edns.ECSOption('1.2.255.33', 20) + io = BytesIO() + opt.to_wire(io) + data = io.getvalue() + self.assertEqual(data, b'\x00\x01\x14\x00\x01\x02\xf0') + + def testECSOption_from_wire(self): + opt = dns.edns.option_from_wire(8, b'\x00\x01\x14\x00\x01\x02\xf0', + 0, 7) + self.assertEqual(opt.otype, dns.edns.ECS) + self.assertEqual(opt.address, b'1.2.240.0') + self.assertEqual(opt.srclen, 20) + self.assertEqual(opt.scopelen, 0) + def testECSOption(self): opt = dns.edns.ECSOption('1.2.3.4', 24) io = BytesIO()