def test_empty_duplicate_hop_by_hop_opt(child, iface, hw_dst, ll_dst, ll_src): # Try sending two empty hop-by-hop-option header p = srp1(Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) / IPv6ExtHdrHopByHop() / IPv6ExtHdrHopByHop() / UDP() / "\x03\x04", iface=iface, timeout=1, verbose=0) # should return parameter problem message assert (p is not None) assert (ICMPv6ParamProblem in p) assert (p[ICMPv6ParamProblem].code == 1) # unrecognized next header assert (p[ICMPv6ParamProblem].ptr >= 40) # after IPv6 header pktbuf_empty(child)
def test_forward_uncomp_not_first_ext_hdr(child, iface, hw_dst, ll_dst, ll_src): dummy = "affe::1" hl = random.randint(2, 255) # sniffing for packets to dummy sniffer.start_sniff(lambda p: p[Ether].src == hw_dst) # add dummy IPv6 address dst_iface = get_first_interface(child) hw_src = get_host_hwaddr(iface) add_neighbor(child, dst_iface, dummy, hw_src) sendp(Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src, hlim=hl) / IPv6ExtHdrHopByHop() / IPv6ExtHdrRouting(type=3, segleft=1, addresses=[dummy]), iface=iface, verbose=0) ps = sniffer.wait_for_sniff_results() p = [p for p in ps if p[Ether].src == hw_dst] assert (len(p) > 0) p = p[0] assert (IPv6 in p) assert (IPv6ExtHdrRouting in p) assert (p[IPv6].src == ll_src) assert (p[IPv6].dst == dummy) assert (p[IPv6].hlim == (hl - 1)) assert (p[IPv6ExtHdrRouting].type == 3) assert (p[IPv6ExtHdrRouting].segleft == 0) pktbuf_empty(child) del_neighbor(child, dst_iface, dummy)
def test_empty_mixed2_w_rt_hdr_registered(child, iface, hw_dst, ll_dst, ll_src): # Register to routing header register_protnum(child, EXT_HDR_NH[IPv6ExtHdrRouting]) # Try sending a packet with a number of extension headers in not recommended # (but legal) order sendp(Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) / IPv6ExtHdrHopByHop() / IPv6ExtHdrRouting() / IPv6ExtHdrDestOpt() / IPv6ExtHdrFragment() / UDP() / "\x01\x02", iface=iface, verbose=0) # Routing header with payload child.expect(r"~~ SNIP 0 - size:\s+(\d+) byte, type: NETTYPE_\w+ \(\d+\)") ipv6_payload_len = int(child.match.group(1)) # NH = IPv6ExtHdrDestOpt, len = 0x00, routing type = 0, segments left = 0 # NH = IPv6ExtHdrFragment, len = 0x00, PadN option (0x01) of length 0x04 child.expect(r"00000000 {:02X} 00 00 00 00 00 00 00 " r"{:02X} 00 01 04 00 00 00 00".format( EXT_HDR_NH[IPv6ExtHdrDestOpt], EXT_HDR_NH[IPv6ExtHdrFragment])) # NH = 17 (UDP), reserved = 0x00, fragment offset = 0, res = 0, M = 0 child.expect(r"00000010 11 00 00 00 00 00 00 00") # Hop-by-hop-option child.expect(r"~~ SNIP 1 - size:\s+(\d+) byte, type: NETTYPE_\w+ \(\d+\)") ipv6_payload_len += int(child.match.group(1)) # NH = IPv6ExtHdrRouting, len = 0x00, PadN option (0x01) of length 0x04 child.expect(r"00000000 {:02X} 00 01 04 00 00 00 00".format( EXT_HDR_NH[IPv6ExtHdrRouting])) # IPv6 header child.expect(r"~~ SNIP 2 - size:\s+40 byte, type: NETTYPE_IPV6 \(\d+\)") child.expect_exact(r"length: {} next header: {}".format( ipv6_payload_len, EXT_HDR_NH[IPv6ExtHdrHopByHop])) child.expect_exact(r"destination address: {}".format(ll_dst)) pktbuf_empty(child) unregister(child)
def test_hop_by_hop_opt_discard_unknown_5_mcast(child, iface, hw_dst, ll_dst, ll_src): # Register to hop-by-hop-option header register_protnum(child, EXT_HDR_NH[UDP]) # sniff for parameter problem as with multicast srp1 does not work sniffer = StartCheckAsyncSniffer(iface=iface, count=1, filter="icmp6[0] == 4") sniffer.start() sniffer.wait_for_started() sendp(Ether(dst=HW_MCAST) / IPv6(dst=MCAST, src=ll_src) / IPv6ExtHdrHopByHop(options=HBHOptUnknown( otype=TEST_OPTION_TYPES["ACTION_DISCARD_ERROR"], optlen=4, optdata="\x11\x22\x33\x44")) / UDP() / "\x01\x02", iface=iface, verbose=0) sniffer.join(RECV_TIMEOUT) ps = sniffer.results assert ps is None res = child.expect( # the packet should be not received at all [r"PKTDUMP: data received:", TIMEOUT], timeout=RECV_TIMEOUT) assert res > 0 pktbuf_empty(child) unregister(child)
def test_empty_duplicate_non_first_hop_by_hop_opt(child, iface, hw_dst, ll_dst, ll_src): # Try sending empty hop-by-hop-option header after destination option # header and another hop-by-hop-option header p = srp1(Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) / IPv6ExtHdrHopByHop() / IPv6ExtHdrDestOpt() / IPv6ExtHdrHopByHop() / UDP() / "\x07\x08", iface=iface, timeout=RECV_TIMEOUT, verbose=0) # should return parameter problem message assert p is not None assert ICMPv6ParamProblem in p assert p[ICMPv6ParamProblem].code == 1 # unrecognized next header assert p[ICMPv6ParamProblem].ptr >= 48 # after IPv6 header and HopByHopOpt pktbuf_empty(child)
def test_hop_by_hop_opt_discard_unknown_5(child, iface, hw_dst, ll_dst, ll_src): # Register to hop-by-hop-option header register_protnum(child, EXT_HDR_NH[UDP]) p = srp1(Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) / IPv6ExtHdrHopByHop(options=HBHOptUnknown( otype=TEST_OPTION_TYPES["ACTION_DISCARD_ERROR"], optlen=4, optdata="\x11\x22\x33\x44")) / UDP() / "\x01\x02", iface=iface, verbose=0, timeout=RECV_TIMEOUT) assert p is not None assert ICMPv6ParamProblem in p # unrecognized IPv6 option encountered assert p[ICMPv6ParamProblem].code == 2 # first after IPv6 header + extension header => 40 + 2 = 42 assert p[ICMPv6ParamProblem].ptr == 42 res = child.expect( # the packet should be not received at all [r"PKTDUMP: data received:", TIMEOUT], timeout=RECV_TIMEOUT) assert res > 0 pktbuf_empty(child) unregister(child)
def run(self): """Sends Multicast Listener Discovery Queries to all nodes on the network. Received Multicast Listener Reports are processed by a SniffThread. """ while True: send(IPv6(dst=self._MULTICAST_DEST, hlim=self._HOP_LIMIT) / IPv6ExtHdrHopByHop(options=RouterAlert()) / ICMPv6MLQuery(), iface=self.interface) time.sleep(self._SLEEP)
def test_empty_hop_by_hop_opt_wo_register(child, iface, hw_dst, ll_dst, ll_src): # Try sending an empty hop-by-hop-option header sendp(Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) / IPv6ExtHdrHopByHop() / UDP(), iface=iface, verbose=0) pktbuf_empty(child)
def test_empty_hop_by_hop_opt_large_hdr_len(child, iface, hw_dst, ll_dst, ll_src): # Register to hop-by-hop-option header register_protnum(child, EXT_HDR_NH[IPv6ExtHdrHopByHop]) # Try sending an empty hop-by-hop-option header with too big header length sendp(Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) / IPv6ExtHdrHopByHop(len=20) / UDP() / "\x01\x02", iface=iface, verbose=0) pktbuf_empty(child) unregister(child)
def test_hop_by_hop_opt_7_pad1(child, iface, hw_dst, ll_dst, ll_src): # Register to hop-by-hop-option header register_protnum(child, EXT_HDR_NH[UDP]) sendp( Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) / # autopad=0 already introduces one Pad1 option and doesn't work with # options parameter IPv6ExtHdrHopByHop(nh=EXT_HDR_NH[UDP], autopad=0) / Pad1() / Pad1() / Pad1() / Pad1() / Pad1() / Pad1() / UDP() / "\x01\x02", iface=iface, verbose=0) child.expect(r"~~ SNIP 0 - size: 10 byte, type: NETTYPE_UNDEF \(\d+\)") pktbuf_empty(child) unregister(child)
def test_hop_by_hop_opt_skip_unknown(child, iface, hw_dst, ll_dst, ll_src): # Register to hop-by-hop-option header register_protnum(child, EXT_HDR_NH[UDP]) p = srp1(Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) / IPv6ExtHdrHopByHop( options=HBHOptUnknown(otype=TEST_OPTION_TYPES["ACTION_SKIP"], optlen=4, optdata="\x11\x22\x33\x44")) / UDP() / "\x01\x02", iface=iface, verbose=0, timeout=RECV_TIMEOUT) assert p is None child.expect(r"~~ SNIP 0 - size: 10 byte, type: NETTYPE_UNDEF \(\d+\)") pktbuf_empty(child) unregister(child)
def test_empty_hop_by_hop_opt_w_register(child, iface, hw_dst, ll_dst, ll_src): # Register to hop-by-hop-option header register_protnum(child, EXT_HDR_NH[IPv6ExtHdrHopByHop]) # Try sending an empty hop-by-hop-option header sendp(Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) / IPv6ExtHdrHopByHop() / UDP() / "\x01\x02", iface=iface, verbose=0) child.expect(r"~~ SNIP 0 - size:\s+(\d+) byte, type: NETTYPE_\w+ \(\d+\)") ipv6_payload_len = int(child.match.group(1)) # NH = 17 (UDP), len = 0x00, PadN option (0x01) of length 0x04 child.expect(r"00000000 11 00 01 04 00 00 00 00") child.expect(r"~~ SNIP 1 - size:\s+40 byte, type: NETTYPE_IPV6 \(\d+\)") child.expect_exact(r"length: {} next header: {}".format( ipv6_payload_len, EXT_HDR_NH[IPv6ExtHdrHopByHop])) child.expect_exact(r"destination address: {}".format(ll_dst)) pktbuf_empty(child) unregister(child)
def test_hop_by_hop_opt_broken_padn(child, iface, hw_dst, ll_dst, ll_src): # Register to hop-by-hop-option header register_protnum(child, EXT_HDR_NH[UDP]) sendp( Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) / # autopad=0 doesn't work with options parameter IPv6ExtHdrHopByHop(nh=EXT_HDR_NH[UDP], autopad=0) / PadN(optlen=7, optdata="\x11\x22\x33\x44\x55\x66\x77") / UDP() / "\x01\x02", iface=iface, verbose=0) res = child.expect( # 10 bytes == UDP header plus 2 byte payload [r"~~ SNIP 0 - size: 10 byte, type: NETTYPE_UNDEF \(\d+\)", TIMEOUT], timeout=RECV_TIMEOUT) # We expect the header parsing to be messed up assert res > 0 pktbuf_empty(child) unregister(child)
def test_hop_by_hop_opt_only_one_pad1(child, iface, hw_dst, ll_dst, ll_src): # Register to hop-by-hop-option header register_protnum(child, EXT_HDR_NH[UDP]) # send malformed packet with only one Pad1 option sendp( Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) / # autopad=0 already introduces one Pad1 option and doesn't work with # options parameter IPv6ExtHdrHopByHop(autopad=0) / UDP() / "\x01\x02", iface=iface, verbose=0) res = child.expect( # 10 bytes == UDP header plus 2 byte payload [r"~~ SNIP 0 - size: 10 byte, type: NETTYPE_UNDEF \(\d+\)", TIMEOUT], timeout=RECV_TIMEOUT) # We expect the header parsing to be messed up assert res > 0 pktbuf_empty(child) unregister(child)
def test_hop_by_hop_opt_discard_unknown_1(child, iface, hw_dst, ll_dst, ll_src): # Register to hop-by-hop-option header register_protnum(child, EXT_HDR_NH[UDP]) p = srp1( Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) / IPv6ExtHdrHopByHop( options=HBHOptUnknown(otype=TEST_OPTION_TYPES["ACTION_DISCARD"], optlen=4, optdata="\x11\x22\x33\x44")) / UDP() / "\x01\x02", iface=iface, verbose=0, timeout=RECV_TIMEOUT) assert p is None res = child.expect( # the packet should be not received at all [r"PKTDUMP: data received:", TIMEOUT], timeout=RECV_TIMEOUT) assert res > 0 pktbuf_empty(child) unregister(child)
def test_empty_mixed1_w_dest_opt_registered(child, iface, hw_dst, ll_dst, ll_src): # Register to destination-option header register_protnum(child, EXT_HDR_NH[IPv6ExtHdrDestOpt]) # Try sending a packet with a number of extension headers in recommended # order: https://tools.ietf.org/html/rfc8200#section-4.1 sendp(Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) / IPv6ExtHdrHopByHop() / IPv6ExtHdrDestOpt() / IPv6ExtHdrRouting() / IPv6ExtHdrFragment() / IPv6ExtHdrDestOpt() / UDP() / "\x01\x02", iface=iface, verbose=0) # IPv6ExtHdrDestOpt is two times in the packet so pktdump will it print two # times # 1st print parsed up to the first IPv6ExtHdrDestOpt # Destination option 1 with payload child.expect(r"~~ SNIP 0 - size:\s+(\d+) byte, type: NETTYPE_\w+ \(\d+\)") ipv6_payload_len = int(child.match.group(1)) # NH = IPv6ExtHdrRouting, len = 0x00, PadN option (0x01) of length 0x04 # NH = IPv6ExtHdrFragment, len = 0x00, routing type = 0, segments left = 0 child.expect(r"00000000 {:02X} 00 01 04 00 00 00 00 " r"{:02X} 00 00 00 00 00 00 00".format( EXT_HDR_NH[IPv6ExtHdrRouting], EXT_HDR_NH[IPv6ExtHdrFragment])) # NH = IPv6ExtHdrDestOpt, reserved = 0x00, fragment offset = 0, res = 0, M = 0 # NH = 17 (UDP), len = 0x00, PadN option (0x01) of length 0x04 child.expect(r"00000010 {:02X} 00 00 00 00 00 00 00 " r"11 00 01 04 00 00 00 00".format( EXT_HDR_NH[IPv6ExtHdrDestOpt])) # Hop-by-hop option child.expect(r"~~ SNIP 1 - size:\s+(\d+) byte, type: NETTYPE_\w+ \(\d+\)") ipv6_payload_len += int(child.match.group(1)) # NH = IPv6ExtHdrDestOpt, len = 0x00, PadN option (0x01) of length 0x04 child.expect(r"00000000 {:02X} 00 01 04 00 00 00 00".format( EXT_HDR_NH[IPv6ExtHdrDestOpt])) # IPv6 header child.expect(r"~~ SNIP 2 - size:\s+40 byte, type: NETTYPE_IPV6 \(\d+\)") child.expect_exact(r"length: {} next header: {}".format( ipv6_payload_len, EXT_HDR_NH[IPv6ExtHdrHopByHop])) child.expect_exact(r"destination address: {}".format(ll_dst)) # 2nd print parsed up to the second IPv6ExtHdrHopByHop # Destination option 2 with payload child.expect(r"~~ SNIP 0 - size:\s+(\d+) byte, type: NETTYPE_\w+ \(\d+\)") ipv6_payload_len = int(child.match.group(1)) # NH = 17 (UDP), len = 0x00, PadN option (0x01) of length 0x04 child.expect(r"00000000 11 00 01 04 00 00 00 00") # Fragment header child.expect(r"~~ SNIP 1 - size:\s+(\d+) byte, type: NETTYPE_\w+ \(\d+\)") ipv6_payload_len += int(child.match.group(1)) # NH = IPv6ExtHdrDestOpt, reserved = 0x00, fragment offset = 0, res = 0, M = 0 child.expect(r"00000000 {:02X} 00 00 00 00 00 00 00".format( EXT_HDR_NH[IPv6ExtHdrDestOpt])) # Routing header child.expect(r"~~ SNIP 2 - size:\s+(\d+) byte, type: NETTYPE_\w+ \(\d+\)") ipv6_payload_len += int(child.match.group(1)) # NH = IPv6ExtHdrFragment, len = 0x00, routing type = 0, segments left = 0 child.expect(r"00000000 {:02X} 00 00 00 00 00 00 00".format( EXT_HDR_NH[IPv6ExtHdrFragment])) # Destination option 1 child.expect(r"~~ SNIP 3 - size:\s+(\d+) byte, type: NETTYPE_\w+ \(\d+\)") ipv6_payload_len += int(child.match.group(1)) # NH = IPv6ExtHdrRouting, len = 0x00, PadN option (0x01) of length 0x04 child.expect(r"00000000 {:02X} 00 01 04 00 00 00 00".format( EXT_HDR_NH[IPv6ExtHdrRouting])) # Hop-by-hop option child.expect(r"~~ SNIP 4 - size:\s+(\d+) byte, type: NETTYPE_\w+ \(\d+\)") ipv6_payload_len += int(child.match.group(1)) # NH = IPv6ExtHdrDestOpt, len = 0x00, PadN option (0x01) of length 0x04 child.expect(r"00000000 {:02X} 00 01 04 00 00 00 00".format( EXT_HDR_NH[IPv6ExtHdrDestOpt])) # IPv6 header child.expect(r"~~ SNIP 5 - size:\s+40 byte, type: NETTYPE_IPV6 \(\d+\)") child.expect_exact(r"length: {} next header: {}".format( ipv6_payload_len, EXT_HDR_NH[IPv6ExtHdrHopByHop])) child.expect_exact(r"destination address: {}".format(ll_dst)) pktbuf_empty(child) unregister(child)