Index: stable/12/tests/sys/netinet6/Makefile =================================================================== --- stable/12/tests/sys/netinet6/Makefile (revision 356492) +++ stable/12/tests/sys/netinet6/Makefile (revision 356493) @@ -1,7 +1,20 @@ # $FreeBSD$ +PACKAGE= tests + TESTSDIR= ${TESTSBASE}/sys/netinet6 +FILESDIR= ${TESTSDIR} + +ATF_TESTS_SH= \ + exthdr \ + scapyi386 + +${PACKAGE}FILES+= exthdr.py +${PACKAGE}FILES+= scapyi386.py + +${PACKAGE}FILESMODE_exthdr.py= 0555 +${PACKAGE}FILESMODE_scapyi386.py=0555 TESTS_SUBDIRS+= frag6 .include Index: stable/12/tests/sys/netinet6/exthdr.py =================================================================== --- stable/12/tests/sys/netinet6/exthdr.py (nonexistent) +++ stable/12/tests/sys/netinet6/exthdr.py (revision 356493) @@ -0,0 +1,273 @@ +#!/usr/bin/env python +#- +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2019 Netflix, Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +import argparse +import scapy.all as sp +import socket +import sys +import frag6.sniffer as Sniffer +from time import sleep + +def check_icmp6_error_dst_unreach_noport(args, packet): + ip6 = packet.getlayer(sp.IPv6) + if not ip6: + return False + oip6 = sp.IPv6(src=args.src[0], dst=args.to[0]) + if ip6.dst != oip6.src: + return False + icmp6 = packet.getlayer(sp.ICMPv6DestUnreach) + if not icmp6: + return False + # ICMP6_DST_UNREACH_NOPORT 4 + if icmp6.code != 4: + return False + # Should we check the payload as well? + # We are running in a very isolated environment and nothing else + # should trigger an ICMPv6 Dest Unreach / Port Unreach so leave it. + #icmp6.display() + return True + +def check_icmp6_error_paramprob_header(args, packet): + ip6 = packet.getlayer(sp.IPv6) + if not ip6: + return False + oip6 = sp.IPv6(src=args.src[0], dst=args.to[0]) + if ip6.dst != oip6.src: + return False + icmp6 = packet.getlayer(sp.ICMPv6ParamProblem) + if not icmp6: + return False + # ICMP6_PARAMPROB_HEADER 0 + if icmp6.code != 0: + return False + # Should we check the payload as well? + # We are running in a very isolated environment and nothing else + # should trigger an ICMPv6 Param Prob so leave it. + #icmp6.display() + return True + +def check_tcp_rst(args, packet): + ip6 = packet.getlayer(sp.IPv6) + if not ip6: + return False + oip6 = sp.IPv6(src=args.src[0], dst=args.to[0]) + if ip6.dst != oip6.src: + return False + tcp = packet.getlayer(sp.TCP) + if not tcp: + return False + # Is TCP RST? + if tcp.flags & 0x04: + #tcp.display() + return True + return False + +def addExt(ext, h): + if h is None: + return ext + if ext is None: + ext = h + else: + ext = ext / h + return ext + +def getExtHdrs(args): + ext = None + + # XXX-TODO Try to put them in an order which could make sense + # in real life packets and according to the RFCs. + if args.hbh: + hbh = sp.IPv6ExtHdrHopByHop(options = \ + sp.PadN(optdata="\x00\x00\x00\x00\x00\x00")) + ext = addExt(ext, hbh) + + if args.rh: + rh = sp.IPv6ExtHdrRouting(type = 0) + ext = addExt(ext, rh) + + if args.frag6: + frag6 = sp.IPv6ExtHdrFragment(offset=0, m=0, id=0x1234) + ext = addExt(ext, frag6) + + if args.esp: + # XXX TODO + esp = None + ext = addExt(ext, esp) + + if args.ah: + # XXX TODO + ah = None + ext = addExt(ext, ah) + + if args.dest: + dest = sp.IPv6ExtHdrDestOpt(options = \ + sp.PadN(optdata="\x00\x00\x00\x00\x00\x00")) + ext = addExt(ext, dest) + + if args.mobi: + # XXX TODO + mobi = None + ext = addExt(ext, mobi) + + if args.hip: + # XXX TODO + hip = None + ext = addExt(ext, hip) + + if args.shim6: + # XXX TODO + shim6 = None + ext = addExt(ext, shim6) + + if args.proto253: + # XXX TODO + tft = None + ext = addExt(ext, tft) + + if args.proto254: + # XXX TODO + tff = None + ext = addExt(ext, tff) + + if args.hbhbad: + hbhbad = sp.IPv6ExtHdrHopByHop(options = \ + sp.PadN(optdata="\x00\x00\x00\x00\x00\x00")) + ext = addExt(ext, hbhbad) + + return ext + +def main(): + parser = argparse.ArgumentParser("exthdr.py", + description="IPv6 extension header test tool") + parser.add_argument('--sendif', nargs=1, + required=True, + help='The interface through which the packet will be sent') + parser.add_argument('--recvif', nargs=1, + required=True, + help='The interface on which to check for the packet') + parser.add_argument('--src', nargs=1, + required=True, + help='The source IP address') + parser.add_argument('--to', nargs=1, + required=True, + help='The destination IP address') + parser.add_argument('--debug', + required=False, action='store_true', + help='Enable test debugging') + # Extension Headers + # See https://www.iana.org/assignments/ipv6-parameters/ipv6-parameters.xhtml + parser.add_argument('--hbh', + required=False, action='store_true', + help='Add IPv6 Hop-by-Hop Option') + parser.add_argument('--hbhbad', + required=False, action='store_true', + help='Add IPv6 Hop-by-Hop Option at an invalid position') + parser.add_argument('--rh', + required=False, action='store_true', + help='Add Routing Header for IPv6') + parser.add_argument('--frag6', + required=False, action='store_true', + help='Add Fragment Header for IPv6') + parser.add_argument('--esp', + required=False, action='store_true', + help='Add Encapsulating Security Payload') + parser.add_argument('--ah', + required=False, action='store_true', + help='Add Authentication Header') + parser.add_argument('--dest', + required=False, action='store_true', + help='Add Destination Options for IPv6') + parser.add_argument('--mobi', + required=False, action='store_true', + help='Add Mobility Header') + parser.add_argument('--hip', + required=False, action='store_true', + help='Add Host Identity Protocol') + parser.add_argument('--shim6', + required=False, action='store_true', + help='Add Shim6 Protocol') + parser.add_argument('--proto253', + required=False, action='store_true', + help='Use for experimentation and testing (253)') + parser.add_argument('--proto254', + required=False, action='store_true', + help='Use for experimentation and testing (254)') + + args = parser.parse_args() + + if args.hbhbad: + ok = 0 + else: + ok = 1 + + ######################################################################## + # + # Send IPv6 packets with one or more extension headers (combinations + # mmight not always make sense depending what user tells us). + # We are trying to cover the basic loop and passing mbufs on + # and making sure m_pullup() works. + # Try for at least UDP and TCP upper layer payloads. + # + # Expectations: no panics + # We are not testing for any other outcome here. + # + data = "6" * 88 + udp = sp.UDP(dport=3456, sport=6543) / data + tcp = sp.TCP(dport=4567, sport=7654) + ip6 = sp.Ether() / sp.IPv6(src=args.src[0], dst=args.to[0]) + for ulp in [ udp, tcp ]: + ext = getExtHdrs(args) + if ext is not None: + pkt = ip6 / ext / ulp + else: + pkt = ip6 / ulp + if args.debug : + pkt.display() + if not ok: + sc = check_icmp6_error_paramprob_header; + elif ulp == udp: + sc = check_icmp6_error_dst_unreach_noport; + elif ulp == tcp: + sc = check_tcp_rst; + else: + sys.exit(2) + # Start sniffing on recvif + sniffer = Sniffer.Sniffer(args, sc) + sp.sendp(pkt, iface=args.sendif[0], verbose=False) + sleep(0.10) + sniffer.setEnd() + sniffer.join() + if not sniffer.foundCorrectPacket: + sys.exit(not ok) + + sys.exit(0) + +if __name__ == '__main__': + main() Property changes on: stable/12/tests/sys/netinet6/exthdr.py ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/12/tests/sys/netinet6/exthdr.sh =================================================================== --- stable/12/tests/sys/netinet6/exthdr.sh (nonexistent) +++ stable/12/tests/sys/netinet6/exthdr.sh (revision 356493) @@ -0,0 +1,124 @@ +# $FreeBSD$ +#- +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2019 Netflix, Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +. $(atf_get_srcdir)/../common/vnet.subr + +atf_test_case "exthdr" "cleanup" +exthdr_head() { + + atf_set descr 'Test IPv6 extension header code paths' + atf_set require.user root + atf_set require.progs scapy +} + +exthdr_body() { + + ids=65533 + id=`printf "%x" ${ids}` + if [ $$ -gt 65535 ]; then + xl=`printf "%x" $(($$ - 65535))` + yl="1" + else + xl=`printf "%x" $$` + yl="" + fi + + vnet_init + + ip6a="2001:db8:6666:0000:${yl}:${id}:1:${xl}" + ip6b="2001:db8:6666:0000:${yl}:${id}:2:${xl}" + + epair=$(vnet_mkepair) + ifconfig ${epair}a up + ifconfig ${epair}a inet6 ${ip6a}/64 + + jname="v6t-${id}-${yl}-${xl}" + vnet_mkjail ${jname} ${epair}b + jexec ${jname} ifconfig ${epair}b up + jexec ${jname} ifconfig ${epair}b inet6 ${ip6b}/64 + + # Let IPv6 ND do its thing. + #ping6 -q -c 1 ff02::1%${epair}a + #ping6 -q -c 1 ${ip6b} + sleep 3 + + # Clear statistics. + jexec ${jname} netstat -z -s > /dev/null + + # Run extension header tests. + pyname=$(atf_get ident) + pyname=${pyname%*_[0-9]} + + atf_check -s exit:0 $(atf_get_srcdir)/${pyname}.py \ + --sendif ${epair}a --recvif ${epair}a \ + --src ${ip6a} --to ${ip6b} + + atf_check -s exit:0 $(atf_get_srcdir)/${pyname}.py \ + --sendif ${epair}a --recvif ${epair}a \ + --src ${ip6a} --to ${ip6b} \ + --hbh + + atf_check -s exit:0 $(atf_get_srcdir)/${pyname}.py \ + --sendif ${epair}a --recvif ${epair}a \ + --src ${ip6a} --to ${ip6b} \ + --rh + + atf_check -s exit:0 $(atf_get_srcdir)/${pyname}.py \ + --sendif ${epair}a --recvif ${epair}a \ + --src ${ip6a} --to ${ip6b} \ + --frag6 + + atf_check -s exit:0 $(atf_get_srcdir)/${pyname}.py \ + --sendif ${epair}a --recvif ${epair}a \ + --src ${ip6a} --to ${ip6b} \ + --dest + + atf_check -s exit:0 $(atf_get_srcdir)/${pyname}.py \ + --sendif ${epair}a --recvif ${epair}a \ + --src ${ip6a} --to ${ip6b} \ + --hbh --dest + + atf_check -s exit:1 $(atf_get_srcdir)/${pyname}.py \ + --sendif ${epair}a --recvif ${epair}a \ + --src ${ip6a} --to ${ip6b} \ + --dest --hbhbad + +} + +exthdr_cleanup() { + + vnet_cleanup +} + +atf_init_test_cases() +{ + + atf_add_test_case "exthdr" +} + +# end Property changes on: stable/12/tests/sys/netinet6/exthdr.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/12/tests/sys/netinet6/frag6/frag6.subr =================================================================== --- stable/12/tests/sys/netinet6/frag6/frag6.subr (revision 356492) +++ stable/12/tests/sys/netinet6/frag6/frag6.subr (revision 356493) @@ -1,122 +1,122 @@ # $FreeBSD$ #- # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Netflix, Inc. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # . $(atf_get_srcdir)/../../common/vnet.subr frag6_head() { atf_set descr 'Test IPv6 fragmentation code' atf_set require.user root atf_set require.progs scapy } frag6_body() { ids=${1:="65533"} shift id=`printf "%x" ${ids}` if [ $$ -gt 65535 ]; then xl=`printf "%x" $(($$ - 65535))` yl="1" else xl=`printf "%x" $$` yl="" fi vnet_init ip6a="2001:db8:6666:6666:${yl}:${id}:1:${xl}" ip6b="2001:db8:6666:6666:${yl}:${id}:2:${xl}" epair=$(vnet_mkepair) - ifconfig ${epair}a mtu 131071 up + ifconfig ${epair}a up ifconfig ${epair}a inet6 ${ip6a}/64 jname="v6t-${id}-${yl}-${xl}" vnet_mkjail ${jname} ${epair}b - jexec ${jname} ifconfig ${epair}b mtu 131071 up + jexec ${jname} ifconfig ${epair}b up jexec ${jname} ifconfig ${epair}b inet6 ${ip6b}/64 # Let IPv6 ND do its thing. #ping6 -q -c 1 ff02::1%${epair}a #ping6 -q -c 1 ${ip6b} sleep 3 # We need to try to make sure all expiry happened, otherwise there might # be global fragments queued. (This still does not rule out that there # are no other fragments queued anywhere else in the system). i=0 while test $i -lt 60; do nf=`sysctl -n net.inet6.ip6.frag6_nfrags` case ${nf} in 0) break ;; esac sleep 1 i=$((i + 1)) done case ${nf} in 0) ;; *) atf_fail "Global frag6_nfrags count is not zero but ${nf}" ;; esac pretestf=$2 case "${pretestf}" in "") ;; [A-Za-z0-9_]*) eval ${pretestf} "${jname}" "${epair}b" ;; esac # Clear statistics. jexec ${jname} netstat -z -s > /dev/null # Run fragment tests. pyname=$(atf_get ident) pyname=${pyname%*_[0-9]} atf_check -s exit:0 $(atf_get_srcdir)/${pyname}.py \ --sendif ${epair}a \ --recvif ${epair}a \ --src ${ip6a} \ --to ${ip6b} checkf=$1 case "${checkf}" in "") ;; [A-Za-z0-9_]*) eval ${checkf} "${jname}" "${epair}b" ;; esac } frag6_cleanup() { vnet_cleanup } # end Index: stable/12/tests/sys/netinet6/frag6/frag6_02.py =================================================================== --- stable/12/tests/sys/netinet6/frag6/frag6_02.py (revision 356492) +++ stable/12/tests/sys/netinet6/frag6/frag6_02.py (revision 356493) @@ -1,108 +1,109 @@ #!/usr/bin/env python #- # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Netflix, Inc. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # import argparse import scapy.all as sp import socket import sys from sniffer import Sniffer from time import sleep def check_icmp6_error(args, packet): ip6 = packet.getlayer(sp.IPv6) if not ip6: return False oip6 = sp.IPv6(src=args.src[0], dst=args.to[0]) if ip6.dst != oip6.src: return False icmp6 = packet.getlayer(sp.ICMPv6ParamProblem) if not icmp6: return False # ICMP6_PARAMPROB_HEADER 0 if icmp6.code != 0: return False # Should we check the payload as well? # We are running in a very isolated environment and nothing else # should trigger an ICMPv6 Param Prob so leave it. #icmp6.display() return True def main(): parser = argparse.ArgumentParser("frag6.py", description="IPv6 fragementation test tool") parser.add_argument('--sendif', nargs=1, required=True, help='The interface through which the packet will be sent') parser.add_argument('--recvif', nargs=1, required=True, help='The interface on which to check for the packet') parser.add_argument('--src', nargs=1, required=True, help='The source IP address') parser.add_argument('--to', nargs=1, required=True, help='The destination IP address') parser.add_argument('--debug', required=False, action='store_true', help='Enable test debugging') args = parser.parse_args() # Start sniffing on recvif sniffer = Sniffer(args, check_icmp6_error) ######################################################################## # # A single start fragment with payload length not % 8. # # A: Error handling in code. # R: ICMPv6 param problem. # data = "6" * 1287 ip6f01 = sp.Ether() / \ sp.IPv6(src=args.src[0], dst=args.to[0]) / \ sp.IPv6ExtHdrFragment(offset=0, m=1, id=5) / \ sp.UDP(dport=3456, sport=6543) / \ data if args.debug : ip6f01.display() sp.sendp(ip6f01, iface=args.sendif[0], verbose=False) sleep(0.10) + sniffer.setEnd() sniffer.join() if not sniffer.foundCorrectPacket: sys.exit(1) sys.exit(0) if __name__ == '__main__': main() Index: stable/12/tests/sys/netinet6/frag6/frag6_04.py =================================================================== --- stable/12/tests/sys/netinet6/frag6/frag6_04.py (revision 356492) +++ stable/12/tests/sys/netinet6/frag6/frag6_04.py (revision 356493) @@ -1,105 +1,106 @@ #!/usr/bin/env python #- # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Netflix, Inc. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # import argparse import scapy.all as sp import socket import sys from sniffer import Sniffer from time import sleep def check_icmp6_error(args, packet): ip6 = packet.getlayer(sp.IPv6) if not ip6: return False oip6 = sp.IPv6(src=args.src[0], dst=args.to[0]) if ip6.dst != oip6.src: return False icmp6 = packet.getlayer(sp.ICMPv6ParamProblem) if not icmp6: return False # ICMP6_PARAMPROB_HEADER 0 if icmp6.code != 0: return False # Should we check the payload as well? # We are running in a very isolated environment and nothing else # should trigger an ICMPv6 Param Prob so leave it. #icmp6.display() return True def main(): parser = argparse.ArgumentParser("frag6.py", description="IPv6 fragementation test tool") parser.add_argument('--sendif', nargs=1, required=True, help='The interface through which the packet will be sent') parser.add_argument('--recvif', nargs=1, required=True, help='The interface on which to check for the packet') parser.add_argument('--src', nargs=1, required=True, help='The source IP address') parser.add_argument('--to', nargs=1, required=True, help='The destination IP address') parser.add_argument('--debug', required=False, action='store_true', help='Enable test debugging') args = parser.parse_args() # Start sniffing on recvif sniffer = Sniffer(args, check_icmp6_error) ######################################################################## # # 0-byte first fragment. # # A: 0-byte fragment payload not allowed. Discarded. # R: ICMPv6 param prob, paramprob header. # ip6f01 = sp.Ether() / \ sp.IPv6(src=args.src[0], dst=args.to[0]) / \ sp.IPv6ExtHdrFragment(offset=0, m=1, id=4) if args.debug : ip6f01.display() sp.sendp(ip6f01, iface=args.sendif[0], verbose=False) sleep(0.10) + sniffer.setEnd() sniffer.join() if not sniffer.foundCorrectPacket: sys.exit(1) sys.exit(0) if __name__ == '__main__': main() Index: stable/12/tests/sys/netinet6/scapyi386.py =================================================================== --- stable/12/tests/sys/netinet6/scapyi386.py (nonexistent) +++ stable/12/tests/sys/netinet6/scapyi386.py (revision 356493) @@ -0,0 +1,85 @@ +#!/usr/bin/env python +#- +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2019 Netflix, Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +import argparse +import scapy.all as sp +import socket +import sys + +def main(): + parser = argparse.ArgumentParser("scapyi386.py", + description="IPv6 Ethernet Dest MAC test") + parser.add_argument('--sendif', nargs=1, + required=True, + help='The interface through which the packet will be sent') + parser.add_argument('--recvif', nargs=1, + required=True, + help='The interface on which to check for the packet') + parser.add_argument('--src', nargs=1, + required=True, + help='The source IP address') + parser.add_argument('--to', nargs=1, + required=True, + help='The destination IP address') + parser.add_argument('--debug', + required=False, action='store_true', + help='Enable test debugging') + + args = parser.parse_args() + + ######################################################################## + # + # A test case to check that IPv6 packets are sent with a proper + # (resolved) Ethernet Destination MAC address instead of the BCAST one. + # This was needed as test cases did not work properly on i386 due to a + # scapy BPF parsing bug. (See PR 239380 and duplicates). + # + bcmac = sp.Ether(dst="ff:ff:ff:ff:ff:ff").dst + data = "6" * 88 + pkt = sp.Ether() / \ + sp.IPv6(src=args.src[0], dst=args.to[0]) / \ + sp.UDP(dport=3456, sport=6543) / \ + data + sp.sendp(pkt, iface=args.sendif[0], verbose=False) + + eth = pkt.getlayer(sp.Ether) + if eth is None: + print("No Ether in packet") + pkt.display() + sys.exit(1) + if eth.dst == bcmac: + print("Broadcast dMAC on packet") + eth.display() + sys.exit(1) + + sys.exit(0) + +if __name__ == '__main__': + main() Property changes on: stable/12/tests/sys/netinet6/scapyi386.py ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/12/tests/sys/netinet6/scapyi386.sh =================================================================== --- stable/12/tests/sys/netinet6/scapyi386.sh (nonexistent) +++ stable/12/tests/sys/netinet6/scapyi386.sh (revision 356493) @@ -0,0 +1,94 @@ +# $FreeBSD$ +#- +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2019 Netflix, Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +. $(atf_get_srcdir)/../common/vnet.subr + +atf_test_case "scapyi386" "cleanup" +scapyi386_head() { + + atf_set descr 'Test for correct Ethernet Destination MAC address' + atf_set require.user root + atf_set require.progs scapy +} + +scapyi386_body() { + + if [ "$(atf_config_get ci false)" = "true" ] && \ + [ "$(uname -p)" = "i386" ]; then + atf_skip "https://bugs.freebsd.org/239380" + fi + + ids=65533 + id=`printf "%x" ${ids}` + if [ $$ -gt 65535 ]; then + xl=`printf "%x" $(($$ - 65535))` + yl="1" + else + xl=`printf "%x" $$` + yl="" + fi + + vnet_init + + ip6a="2001:db8:6666:0000:${yl}:${id}:1:${xl}" + ip6b="2001:db8:6666:0000:${yl}:${id}:2:${xl}" + + epair=$(vnet_mkepair) + ifconfig ${epair}a up + ifconfig ${epair}a inet6 ${ip6a}/64 + + jname="v6t-${id}-${yl}-${xl}" + vnet_mkjail ${jname} ${epair}b + jexec ${jname} ifconfig ${epair}b up + jexec ${jname} ifconfig ${epair}b inet6 ${ip6b}/64 + + # Let IPv6 ND do its thing. + #ping6 -q -c 1 ff02::1%${epair}a + #ping6 -q -c 1 ${ip6b} + sleep 3 + + pyname=$(atf_get ident) + pyname=${pyname%*_[0-9]} + + atf_check -s exit:0 $(atf_get_srcdir)/${pyname}.py \ + --sendif ${epair}a --recvif ${epair}a \ + --src ${ip6a} --to ${ip6b} +} + +scapyi386_cleanup() { + + vnet_cleanup +} + +atf_init_test_cases() +{ + + atf_add_test_case "scapyi386" +} + +# end Property changes on: stable/12/tests/sys/netinet6/scapyi386.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/12 =================================================================== --- stable/12 (revision 356492) +++ stable/12 (revision 356493) Property changes on: stable/12 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r354357-354358,354390,354395