diff options
author | Yuichi Ito <ito.yuichi0@gmail.com> | 2013-11-06 17:16:04 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2013-11-08 10:44:29 +0900 |
commit | 1d1cdeea99c35344414871b7d36a30aeefc9741a (patch) | |
tree | 189b5a102e47dcb2506ed680127892893e3c945b | |
parent | 42942c7c5dac2913a682e2c62641b29df502b357 (diff) |
packet lib: icmpv6: support default parameters and the auto calculation of lengths
Signed-off-by: Yuichi Ito <ito.yuichi0@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r-- | ryu/lib/packet/icmpv6.py | 35 | ||||
-rw-r--r-- | ryu/tests/unit/packet/test_icmpv6.py | 421 |
2 files changed, 443 insertions, 13 deletions
diff --git a/ryu/lib/packet/icmpv6.py b/ryu/lib/packet/icmpv6.py index bcf1fff7..d4bb00b9 100644 --- a/ryu/lib/packet/icmpv6.py +++ b/ryu/lib/packet/icmpv6.py @@ -102,7 +102,7 @@ class icmpv6(packet_base.PacketBase): return cls return _register_icmpv6_type - def __init__(self, type_, code, csum, data=None): + def __init__(self, type_=0, code=0, csum=0, data=None): super(icmpv6, self).__init__() self.type_ = type_ self.code = code @@ -180,7 +180,7 @@ class nd_neighbor(stringify.StringifyMixin): return cls return _register_nd_option_type(args[0]) - def __init__(self, res, dst, option=None): + def __init__(self, res=0, dst='::', option=None): self.res = res self.dst = dst self.option = option @@ -252,7 +252,7 @@ class nd_router_solicit(stringify.StringifyMixin): return cls return _register_nd_option_type(args[0]) - def __init__(self, res, option=None): + def __init__(self, res=0, option=None): self.res = res self.option = option @@ -326,7 +326,7 @@ class nd_router_advert(stringify.StringifyMixin): return cls return _register_nd_option_type(args[0]) - def __init__(self, ch_l, res, rou_l, rea_t, ret_t, options=None): + def __init__(self, ch_l=0, res=0, rou_l=0, rea_t=0, ret_t=0, options=None): self.ch_l = ch_l self.res = res self.rou_l = rou_l @@ -430,6 +430,9 @@ class nd_option_la(nd_option): mod = len(buf) % 8 if mod: buf.extend(bytearray(8 - mod)) + if 0 == self.length: + self.length = len(buf) / 8 + struct.pack_into('!B', buf, 1, self.length) return str(buf) def __len__(self): @@ -459,7 +462,8 @@ class nd_option_sla(nd_option_la): ============== ==================== Attribute Description ============== ==================== - length length of the option. + length length of the option. \ + (0 means automatically-calculate when encoding) hw_src Link-Layer Address. \ NOTE: If the address is longer than 6 octets this contains \ the first 6 octets in the address. \ @@ -476,7 +480,7 @@ class nd_option_sla(nd_option_la): def option_type(cls): return ND_OPTION_SLA - def __init__(self, length, hw_src, data=None): + def __init__(self, length=0, hw_src='00:00:00:00:00:00', data=None): super(nd_option_sla, self).__init__(length, hw_src, data) @@ -496,7 +500,8 @@ class nd_option_tla(nd_option_la): ============== ==================== Attribute Description ============== ==================== - length length of the option. + length length of the option. \ + (0 means automatically-calculate when encoding) hw_src Link-Layer Address. \ NOTE: If the address is longer than 6 octets this contains \ the first 6 octets in the address. \ @@ -513,7 +518,7 @@ class nd_option_tla(nd_option_la): def option_type(cls): return ND_OPTION_TLA - def __init__(self, length, hw_src, data=None): + def __init__(self, length=0, hw_src='00:00:00:00:00:00', data=None): super(nd_option_tla, self).__init__(length, hw_src, data) @@ -533,7 +538,8 @@ class nd_option_pi(nd_option): ============== ==================== Attribute Description ============== ==================== - length length of the option. + length length of the option. \ + (0 means automatically-calculate when encoding) pl Prefix Length. res1 L,A,R\* Flags for Prefix Information. val_l Valid Lifetime. @@ -552,7 +558,8 @@ class nd_option_pi(nd_option): def option_type(cls): return ND_OPTION_PI - def __init__(self, length, pl, res1, val_l, pre_l, res2, prefix): + def __init__(self, length=0, pl=0, res1=0, val_l=0, pre_l=0, res2=0, + prefix='::'): super(nd_option_pi, self).__init__(self.option_type(), length) self.pl = pl self.res1 = res1 @@ -576,8 +583,10 @@ class nd_option_pi(nd_option): self._PACK_STR, self.option_type(), self.length, self.pl, res1, self.val_l, self.pre_l, self.res2, addrconv.ipv6.text_to_bin(self.prefix))) - - return hdr + if 0 == self.length: + self.length = len(hdr) / 8 + struct.pack_into('!B', hdr, 1, self.length) + return str(hdr) @icmpv6.register_icmpv6_type(ICMPV6_ECHO_REPLY, ICMPV6_ECHO_REQUEST) @@ -604,7 +613,7 @@ class echo(stringify.StringifyMixin): _PACK_STR = '!HH' _MIN_LEN = struct.calcsize(_PACK_STR) - def __init__(self, id_, seq, data=None): + def __init__(self, id_=0, seq=0, data=None): self.id = id_ self.seq = seq self.data = data diff --git a/ryu/tests/unit/packet/test_icmpv6.py b/ryu/tests/unit/packet/test_icmpv6.py index 43ba8c4e..21167c92 100644 --- a/ryu/tests/unit/packet/test_icmpv6.py +++ b/ryu/tests/unit/packet/test_icmpv6.py @@ -89,6 +89,17 @@ class Test_icmpv6_header(unittest.TestCase): m_short_buf = self.buf[1:self.icmp._MIN_LEN] self.icmp.parser(m_short_buf) + def test_default_args(self): + prev = ipv6(nxt=inet.IPPROTO_ICMPV6) + ic = icmpv6.icmpv6() + prev.serialize(ic, None) + buf = ic.serialize(bytearray(), prev) + res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf)) + + eq_(res[0], 0) + eq_(res[1], 0) + eq_(res[2], icmpv6_csum(prev, buf)) + class Test_icmpv6_echo_request(unittest.TestCase): type_ = 128 @@ -182,6 +193,23 @@ class Test_icmpv6_echo_request(unittest.TestCase): eq_(str(ic), ic_str) eq_(repr(ic), ic_str) + def test_default_args(self): + prev = ipv6(nxt=inet.IPPROTO_ICMPV6) + ic = icmpv6.icmpv6( + type_=icmpv6.ICMPV6_ECHO_REQUEST, data=icmpv6.echo()) + prev.serialize(ic, None) + buf = ic.serialize(bytearray(), prev) + res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) + + eq_(res[0], icmpv6.ICMPV6_ECHO_REQUEST) + eq_(res[1], 0) + eq_(res[2], icmpv6_csum(prev, buf)) + + res = struct.unpack(icmpv6.echo._PACK_STR, str(buf[4:])) + + eq_(res[0], 0) + eq_(res[1], 0) + class Test_icmpv6_echo_reply(Test_icmpv6_echo_request): def setUp(self): @@ -189,6 +217,23 @@ class Test_icmpv6_echo_reply(Test_icmpv6_echo_request): self.csum = 0xa472 self.buf = '\x81\x00\xa4\x72\x76\x20\x00\x00' + def test_default_args(self): + prev = ipv6(nxt=inet.IPPROTO_ICMPV6) + ic = icmpv6.icmpv6( + type_=icmpv6.ICMPV6_ECHO_REPLY, data=icmpv6.echo()) + prev.serialize(ic, None) + buf = ic.serialize(bytearray(), prev) + res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) + + eq_(res[0], icmpv6.ICMPV6_ECHO_REPLY) + eq_(res[1], 0) + eq_(res[2], icmpv6_csum(prev, buf)) + + res = struct.unpack(icmpv6.echo._PACK_STR, str(buf[4:])) + + eq_(res[0], 0) + eq_(res[1], 0) + class Test_icmpv6_neighbor_solicit(unittest.TestCase): type_ = 135 @@ -317,6 +362,48 @@ class Test_icmpv6_neighbor_solicit(unittest.TestCase): eq_(str(ic), ic_str) eq_(repr(ic), ic_str) + def test_default_args(self): + prev = ipv6(nxt=inet.IPPROTO_ICMPV6) + ic = icmpv6.icmpv6( + type_=icmpv6.ND_NEIGHBOR_SOLICIT, data=icmpv6.nd_neighbor()) + prev.serialize(ic, None) + buf = ic.serialize(bytearray(), prev) + res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) + + eq_(res[0], icmpv6.ND_NEIGHBOR_SOLICIT) + eq_(res[1], 0) + eq_(res[2], icmpv6_csum(prev, buf)) + + res = struct.unpack(icmpv6.nd_neighbor._PACK_STR, str(buf[4:])) + + eq_(res[0], 0) + eq_(res[1], addrconv.ipv6.text_to_bin('::')) + + # with nd_option_sla + prev = ipv6(nxt=inet.IPPROTO_ICMPV6) + ic = icmpv6.icmpv6( + type_=icmpv6.ND_NEIGHBOR_SOLICIT, + data=icmpv6.nd_neighbor( + option=icmpv6.nd_option_sla())) + prev.serialize(ic, None) + buf = ic.serialize(bytearray(), prev) + res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) + + eq_(res[0], icmpv6.ND_NEIGHBOR_SOLICIT) + eq_(res[1], 0) + eq_(res[2], icmpv6_csum(prev, buf)) + + res = struct.unpack(icmpv6.nd_neighbor._PACK_STR, str(buf[4:24])) + + eq_(res[0], 0) + eq_(res[1], addrconv.ipv6.text_to_bin('::')) + + res = struct.unpack(icmpv6.nd_option_sla._PACK_STR, str(buf[24:])) + + eq_(res[0], icmpv6.ND_OPTION_SLA) + eq_(res[1], len(icmpv6.nd_option_sla()) / 8) + eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00')) + class Test_icmpv6_neighbor_advert(Test_icmpv6_neighbor_solicit): def setUp(self): @@ -390,6 +477,48 @@ class Test_icmpv6_neighbor_advert(Test_icmpv6_neighbor_solicit): eq_(str(ic), ic_str) eq_(repr(ic), ic_str) + def test_default_args(self): + prev = ipv6(nxt=inet.IPPROTO_ICMPV6) + ic = icmpv6.icmpv6( + type_=icmpv6.ND_NEIGHBOR_ADVERT, data=icmpv6.nd_neighbor()) + prev.serialize(ic, None) + buf = ic.serialize(bytearray(), prev) + res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) + + eq_(res[0], icmpv6.ND_NEIGHBOR_ADVERT) + eq_(res[1], 0) + eq_(res[2], icmpv6_csum(prev, buf)) + + res = struct.unpack(icmpv6.nd_neighbor._PACK_STR, str(buf[4:])) + + eq_(res[0], 0) + eq_(res[1], addrconv.ipv6.text_to_bin('::')) + + # with nd_option_tla + prev = ipv6(nxt=inet.IPPROTO_ICMPV6) + ic = icmpv6.icmpv6( + type_=icmpv6.ND_NEIGHBOR_ADVERT, + data=icmpv6.nd_neighbor( + option=icmpv6.nd_option_tla())) + prev.serialize(ic, None) + buf = ic.serialize(bytearray(), prev) + res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) + + eq_(res[0], icmpv6.ND_NEIGHBOR_ADVERT) + eq_(res[1], 0) + eq_(res[2], icmpv6_csum(prev, buf)) + + res = struct.unpack(icmpv6.nd_neighbor._PACK_STR, str(buf[4:24])) + + eq_(res[0], 0) + eq_(res[1], addrconv.ipv6.text_to_bin('::')) + + res = struct.unpack(icmpv6.nd_option_tla._PACK_STR, str(buf[24:])) + + eq_(res[0], icmpv6.ND_OPTION_TLA) + eq_(res[1], len(icmpv6.nd_option_tla()) / 8) + eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00')) + class Test_icmpv6_router_solicit(unittest.TestCase): type_ = 133 @@ -509,3 +638,295 @@ class Test_icmpv6_router_solicit(unittest.TestCase): eq_(str(ic), ic_str) eq_(repr(ic), ic_str) + + def test_default_args(self): + prev = ipv6(nxt=inet.IPPROTO_ICMPV6) + ic = icmpv6.icmpv6( + type_=icmpv6.ND_ROUTER_SOLICIT, data=icmpv6.nd_router_solicit()) + prev.serialize(ic, None) + buf = ic.serialize(bytearray(), prev) + res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) + + eq_(res[0], icmpv6.ND_ROUTER_SOLICIT) + eq_(res[1], 0) + eq_(res[2], icmpv6_csum(prev, buf)) + + res = struct.unpack(icmpv6.nd_router_solicit._PACK_STR, str(buf[4:])) + + eq_(res[0], 0) + + # with nd_option_sla + prev = ipv6(nxt=inet.IPPROTO_ICMPV6) + ic = icmpv6.icmpv6( + type_=icmpv6.ND_ROUTER_SOLICIT, + data=icmpv6.nd_router_solicit( + option=icmpv6.nd_option_sla())) + prev.serialize(ic, None) + buf = ic.serialize(bytearray(), prev) + res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) + + eq_(res[0], icmpv6.ND_ROUTER_SOLICIT) + eq_(res[1], 0) + eq_(res[2], icmpv6_csum(prev, buf)) + + res = struct.unpack(icmpv6.nd_router_solicit._PACK_STR, str(buf[4:8])) + + eq_(res[0], 0) + + res = struct.unpack(icmpv6.nd_option_sla._PACK_STR, str(buf[8:])) + + eq_(res[0], icmpv6.ND_OPTION_SLA) + eq_(res[1], len(icmpv6.nd_option_sla()) / 8) + eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00')) + + +class Test_icmpv6_router_advert(unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_default_args(self): + prev = ipv6(nxt=inet.IPPROTO_ICMPV6) + ic = icmpv6.icmpv6( + type_=icmpv6.ND_ROUTER_ADVERT, data=icmpv6.nd_router_advert()) + prev.serialize(ic, None) + buf = ic.serialize(bytearray(), prev) + res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) + + eq_(res[0], icmpv6.ND_ROUTER_ADVERT) + eq_(res[1], 0) + eq_(res[2], icmpv6_csum(prev, buf)) + + res = struct.unpack(icmpv6.nd_router_advert._PACK_STR, str(buf[4:])) + + eq_(res[0], 0) + eq_(res[1], 0) + eq_(res[2], 0) + eq_(res[3], 0) + eq_(res[4], 0) + + # with nd_option_sla + prev = ipv6(nxt=inet.IPPROTO_ICMPV6) + ic = icmpv6.icmpv6( + type_=icmpv6.ND_ROUTER_ADVERT, + data=icmpv6.nd_router_advert( + options=[icmpv6.nd_option_sla()])) + prev.serialize(ic, None) + buf = ic.serialize(bytearray(), prev) + res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) + + eq_(res[0], icmpv6.ND_ROUTER_ADVERT) + eq_(res[1], 0) + eq_(res[2], icmpv6_csum(prev, buf)) + + res = struct.unpack(icmpv6.nd_router_advert._PACK_STR, str(buf[4:16])) + + eq_(res[0], 0) + eq_(res[1], 0) + eq_(res[2], 0) + eq_(res[3], 0) + eq_(res[4], 0) + + res = struct.unpack(icmpv6.nd_option_sla._PACK_STR, str(buf[16:])) + + eq_(res[0], icmpv6.ND_OPTION_SLA) + eq_(res[1], len(icmpv6.nd_option_sla()) / 8) + eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00')) + + # with nd_option_pi + prev = ipv6(nxt=inet.IPPROTO_ICMPV6) + ic = icmpv6.icmpv6( + type_=icmpv6.ND_ROUTER_ADVERT, + data=icmpv6.nd_router_advert( + options=[icmpv6.nd_option_pi()])) + prev.serialize(ic, None) + buf = ic.serialize(bytearray(), prev) + res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) + + eq_(res[0], icmpv6.ND_ROUTER_ADVERT) + eq_(res[1], 0) + eq_(res[2], icmpv6_csum(prev, buf)) + + res = struct.unpack(icmpv6.nd_router_advert._PACK_STR, str(buf[4:16])) + + eq_(res[0], 0) + eq_(res[1], 0) + eq_(res[2], 0) + eq_(res[3], 0) + eq_(res[4], 0) + + res = struct.unpack(icmpv6.nd_option_pi._PACK_STR, str(buf[16:])) + + eq_(res[0], icmpv6.ND_OPTION_PI) + eq_(res[1], 4) + eq_(res[2], 0) + eq_(res[3], 0) + eq_(res[4], 0) + eq_(res[5], 0) + eq_(res[6], 0) + eq_(res[7], addrconv.ipv6.text_to_bin('::')) + + # with nd_option_sla and nd_option_pi + prev = ipv6(nxt=inet.IPPROTO_ICMPV6) + ic = icmpv6.icmpv6( + type_=icmpv6.ND_ROUTER_ADVERT, + data=icmpv6.nd_router_advert( + options=[icmpv6.nd_option_sla(), icmpv6.nd_option_pi()])) + prev.serialize(ic, None) + buf = ic.serialize(bytearray(), prev) + res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) + + eq_(res[0], icmpv6.ND_ROUTER_ADVERT) + eq_(res[1], 0) + eq_(res[2], icmpv6_csum(prev, buf)) + + res = struct.unpack(icmpv6.nd_router_advert._PACK_STR, str(buf[4:16])) + + eq_(res[0], 0) + eq_(res[1], 0) + eq_(res[2], 0) + eq_(res[3], 0) + eq_(res[4], 0) + + res = struct.unpack(icmpv6.nd_option_sla._PACK_STR, str(buf[16:24])) + + eq_(res[0], icmpv6.ND_OPTION_SLA) + eq_(res[1], len(icmpv6.nd_option_sla()) / 8) + eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00')) + + res = struct.unpack(icmpv6.nd_option_pi._PACK_STR, str(buf[24:])) + + eq_(res[0], icmpv6.ND_OPTION_PI) + eq_(res[1], len(icmpv6.nd_option_pi()) / 8) + eq_(res[2], 0) + eq_(res[3], 0) + eq_(res[4], 0) + eq_(res[5], 0) + eq_(res[6], 0) + eq_(res[7], addrconv.ipv6.text_to_bin('::')) + + +class Test_icmpv6_nd_option_la(unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_default_args(self): + la = icmpv6.nd_option_sla() + buf = la.serialize() + res = struct.unpack(icmpv6.nd_option_sla._PACK_STR, str(buf)) + + eq_(res[0], icmpv6.ND_OPTION_SLA) + eq_(res[1], len(icmpv6.nd_option_sla()) / 8) + eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00')) + + # with nd_neighbor + prev = ipv6(nxt=inet.IPPROTO_ICMPV6) + ic = icmpv6.icmpv6( + type_=icmpv6.ND_NEIGHBOR_ADVERT, + data=icmpv6.nd_neighbor( + option=icmpv6.nd_option_tla())) + prev.serialize(ic, None) + buf = ic.serialize(bytearray(), prev) + res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) + + eq_(res[0], icmpv6.ND_NEIGHBOR_ADVERT) + eq_(res[1], 0) + eq_(res[2], icmpv6_csum(prev, buf)) + + res = struct.unpack(icmpv6.nd_neighbor._PACK_STR, str(buf[4:24])) + + eq_(res[0], 0) + eq_(res[1], addrconv.ipv6.text_to_bin('::')) + + res = struct.unpack(icmpv6.nd_option_tla._PACK_STR, str(buf[24:])) + + eq_(res[0], icmpv6.ND_OPTION_TLA) + eq_(res[1], len(icmpv6.nd_option_tla()) / 8) + eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00')) + + # with nd_router_solicit + prev = ipv6(nxt=inet.IPPROTO_ICMPV6) + ic = icmpv6.icmpv6( + type_=icmpv6.ND_ROUTER_SOLICIT, + data=icmpv6.nd_router_solicit( + option=icmpv6.nd_option_sla())) + prev.serialize(ic, None) + buf = ic.serialize(bytearray(), prev) + res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) + + eq_(res[0], icmpv6.ND_ROUTER_SOLICIT) + eq_(res[1], 0) + eq_(res[2], icmpv6_csum(prev, buf)) + + res = struct.unpack(icmpv6.nd_router_solicit._PACK_STR, str(buf[4:8])) + + eq_(res[0], 0) + + res = struct.unpack(icmpv6.nd_option_sla._PACK_STR, str(buf[8:])) + + eq_(res[0], icmpv6.ND_OPTION_SLA) + eq_(res[1], len(icmpv6.nd_option_sla()) / 8) + eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00')) + + +class Test_icmpv6_nd_option_pi(unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_default_args(self): + pi = icmpv6.nd_option_pi() + buf = pi.serialize() + res = struct.unpack(icmpv6.nd_option_pi._PACK_STR, str(buf)) + + eq_(res[0], icmpv6.ND_OPTION_PI) + eq_(res[1], len(icmpv6.nd_option_pi()) / 8) + eq_(res[2], 0) + eq_(res[3], 0) + eq_(res[4], 0) + eq_(res[5], 0) + eq_(res[6], 0) + eq_(res[7], addrconv.ipv6.text_to_bin('::')) + + # with nd_router_advert + prev = ipv6(nxt=inet.IPPROTO_ICMPV6) + ic = icmpv6.icmpv6( + type_=icmpv6.ND_ROUTER_ADVERT, + data=icmpv6.nd_router_advert( + options=[icmpv6.nd_option_pi()])) + prev.serialize(ic, None) + buf = ic.serialize(bytearray(), prev) + res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) + + eq_(res[0], icmpv6.ND_ROUTER_ADVERT) + eq_(res[1], 0) + eq_(res[2], icmpv6_csum(prev, buf)) + + res = struct.unpack(icmpv6.nd_router_advert._PACK_STR, str(buf[4:16])) + + eq_(res[0], 0) + eq_(res[1], 0) + eq_(res[2], 0) + eq_(res[3], 0) + eq_(res[4], 0) + + res = struct.unpack(icmpv6.nd_option_pi._PACK_STR, str(buf[16:])) + + eq_(res[0], icmpv6.ND_OPTION_PI) + eq_(res[1], 4) + eq_(res[2], 0) + eq_(res[3], 0) + eq_(res[4], 0) + eq_(res[5], 0) + eq_(res[6], 0) + eq_(res[7], addrconv.ipv6.text_to_bin('::')) |