def test_empty_mixed1_w_hop_opt_registered(child, iface, hw_dst, ll_dst, ll_src): # Register to hop-by-hop-option header register_protnum(child, EXT_HDR_NH[IPv6ExtHdrHopByHop]) # 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) # Hop-by-hop option 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, PadN option (0x01) of length 0x04 # NH = IPv6ExtHdrRouting, len = 0x00, PadN option (0x01) of length 0x04 child.expect(r"00000000 {:02X} 00 01 04 00 00 00 00 " r"{:02X} 00 01 04 00 00 00 00".format( EXT_HDR_NH[IPv6ExtHdrDestOpt], EXT_HDR_NH[IPv6ExtHdrRouting])) # NH = IPv6ExtHdrFragment, len = 0x00, routing type = 0, segments left = 0 # NH = IPv6ExtHdrDestOpt, reserved = 0x00, fragment offset = 0, res = 0, M = 0 child.expect(r"00000010 {:02X} 00 00 00 00 00 00 00 " r"{:02X} 00 00 00 00 00 00 00".format( EXT_HDR_NH[IPv6ExtHdrFragment], EXT_HDR_NH[IPv6ExtHdrDestOpt])) # NH = 17 (UDP), len = 0x00, PadN option (0x01) of length 0x04 child.expect(r"00000020 11 00 01 04 00 00 00 00") # IPv6 header 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_empty_dest_opt_wo_register(child, iface, hw_dst, ll_dst, ll_src): # Try sending an empty Destination-Option header sendp(Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) / IPv6ExtHdrDestOpt() / UDP(), iface=iface, verbose=0) pktbuf_empty(child)
def test_empty_dst_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[IPv6ExtHdrDestOpt]) # 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) / IPv6ExtHdrDestOpt(len=20) / UDP() / "\x01\x02", iface=iface, verbose=0) pktbuf_empty(child) unregister(child)
def test_dst_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) / IPv6ExtHdrDestOpt(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+\)", timeout=RECV_TIMEOUT) pktbuf_empty(child) unregister(child)
def test_empty_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 p = srp1(Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) / IPv6ExtHdrDestOpt() / IPv6ExtHdrHopByHop() / UDP() / "\x05\x06", 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_dst_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) / IPv6ExtHdrDestOpt(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_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_dst_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) / IPv6ExtHdrDestOpt(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_empty_dest_opt_w_register(child, iface, hw_dst, ll_dst, ll_src): # Register to Destination-Option header register_protnum(child, EXT_HDR_NH[IPv6ExtHdrDestOpt]) # Try sending an empty Destination-Option header sendp(Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) / IPv6ExtHdrDestOpt() / 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[IPv6ExtHdrDestOpt])) child.expect_exact(r"destination address: {}".format(ll_dst)) pktbuf_empty(child) unregister(child)