109b7a038SIgor Ostapenko# 209b7a038SIgor Ostapenko# SPDX-License-Identifier: BSD-2-Clause 309b7a038SIgor Ostapenko# 409b7a038SIgor Ostapenko# Copyright (c) 2024 Igor Ostapenko <pm@igoro.pro> 509b7a038SIgor Ostapenko# 609b7a038SIgor Ostapenko# Redistribution and use in source and binary forms, with or without 709b7a038SIgor Ostapenko# modification, are permitted provided that the following conditions 809b7a038SIgor Ostapenko# are met: 909b7a038SIgor Ostapenko# 1. Redistributions of source code must retain the above copyright 1009b7a038SIgor Ostapenko# notice, this list of conditions and the following disclaimer. 1109b7a038SIgor Ostapenko# 2. Redistributions in binary form must reproduce the above copyright 1209b7a038SIgor Ostapenko# notice, this list of conditions and the following disclaimer in the 1309b7a038SIgor Ostapenko# documentation and/or other materials provided with the distribution. 1409b7a038SIgor Ostapenko# 1509b7a038SIgor Ostapenko# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1609b7a038SIgor Ostapenko# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1709b7a038SIgor Ostapenko# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1809b7a038SIgor Ostapenko# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1909b7a038SIgor Ostapenko# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2009b7a038SIgor Ostapenko# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2109b7a038SIgor Ostapenko# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2209b7a038SIgor Ostapenko# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2309b7a038SIgor Ostapenko# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2409b7a038SIgor Ostapenko# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2509b7a038SIgor Ostapenko# SUCH DAMAGE. 2609b7a038SIgor Ostapenko 2709b7a038SIgor Ostapenko. $(atf_get_srcdir)/utils.subr 2809b7a038SIgor Ostapenko 2909b7a038SIgor Ostapenkodummymbuf_init() 3009b7a038SIgor Ostapenko{ 3109b7a038SIgor Ostapenko if ! kldstat -q -m dummymbuf; then 3209b7a038SIgor Ostapenko atf_skip "This test requires dummymbuf" 3309b7a038SIgor Ostapenko fi 3409b7a038SIgor Ostapenko} 3509b7a038SIgor Ostapenko 3609b7a038SIgor Ostapenkoatf_test_case "inet_in_mbuf_len" "cleanup" 3709b7a038SIgor Ostapenkoinet_in_mbuf_len_head() 3809b7a038SIgor Ostapenko{ 3909b7a038SIgor Ostapenko atf_set descr 'Test that pf can handle inbound with the first mbuf with m_len < sizeof(struct ip)' 4009b7a038SIgor Ostapenko atf_set require.user root 4109b7a038SIgor Ostapenko} 4209b7a038SIgor Ostapenkoinet_in_mbuf_len_body() 4309b7a038SIgor Ostapenko{ 4409b7a038SIgor Ostapenko pft_init 4509b7a038SIgor Ostapenko dummymbuf_init 4609b7a038SIgor Ostapenko 4709b7a038SIgor Ostapenko epair=$(vnet_mkepair) 4809b7a038SIgor Ostapenko ifconfig ${epair}a 192.0.2.1/24 up 4909b7a038SIgor Ostapenko 5009b7a038SIgor Ostapenko # Set up a simple jail with one interface 5109b7a038SIgor Ostapenko vnet_mkjail alcatraz ${epair}b 5209b7a038SIgor Ostapenko jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 5309b7a038SIgor Ostapenko 5409b7a038SIgor Ostapenko # Sanity check 5509b7a038SIgor Ostapenko atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 5609b7a038SIgor Ostapenko 5709b7a038SIgor Ostapenko # Should be denied 5809b7a038SIgor Ostapenko jexec alcatraz pfctl -e 5909b7a038SIgor Ostapenko pft_set_rules alcatraz \ 6009b7a038SIgor Ostapenko "block" 6109b7a038SIgor Ostapenko atf_check -s not-exit:0 -o ignore ping -c1 -t1 192.0.2.2 6209b7a038SIgor Ostapenko 6309b7a038SIgor Ostapenko # Should be allowed by from/to addresses 6409b7a038SIgor Ostapenko pft_set_rules alcatraz \ 6509b7a038SIgor Ostapenko "block" \ 6609b7a038SIgor Ostapenko "pass in from 192.0.2.1 to 192.0.2.2" 6709b7a038SIgor Ostapenko atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 6809b7a038SIgor Ostapenko 6909b7a038SIgor Ostapenko # Should still work for m_len=0 7009b7a038SIgor Ostapenko jexec alcatraz pfilctl link -i dummymbuf:inet inet 7109b7a038SIgor Ostapenko jexec alcatraz sysctl net.dummymbuf.rules="inet in ${epair}b pull-head 0;" 7209b7a038SIgor Ostapenko atf_check_equal "0" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)" 7309b7a038SIgor Ostapenko atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 7409b7a038SIgor Ostapenko atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)" 7509b7a038SIgor Ostapenko 7609b7a038SIgor Ostapenko # m_len=1 7709b7a038SIgor Ostapenko jexec alcatraz sysctl net.dummymbuf.rules="inet in ${epair}b pull-head 1;" 7809b7a038SIgor Ostapenko jexec alcatraz sysctl net.dummymbuf.hits=0 7909b7a038SIgor Ostapenko atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 8009b7a038SIgor Ostapenko atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)" 8109b7a038SIgor Ostapenko 8209b7a038SIgor Ostapenko # m_len=19 8309b7a038SIgor Ostapenko # provided IPv4 basic header is 20 bytes long, it should impact the dst addr 8409b7a038SIgor Ostapenko jexec alcatraz sysctl net.dummymbuf.rules="inet in ${epair}b pull-head 19;" 8509b7a038SIgor Ostapenko jexec alcatraz sysctl net.dummymbuf.hits=0 8609b7a038SIgor Ostapenko atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 8709b7a038SIgor Ostapenko atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)" 8809b7a038SIgor Ostapenko} 8909b7a038SIgor Ostapenkoinet_in_mbuf_len_cleanup() 9009b7a038SIgor Ostapenko{ 9109b7a038SIgor Ostapenko pft_cleanup 9209b7a038SIgor Ostapenko} 9309b7a038SIgor Ostapenko 9422a632c3SIgor Ostapenkoatf_test_case "inet6_in_mbuf_len" "cleanup" 9522a632c3SIgor Ostapenkoinet6_in_mbuf_len_head() 9622a632c3SIgor Ostapenko{ 9722a632c3SIgor Ostapenko atf_set descr 'Test that pf can handle inbound with the first mbuf with m_len < sizeof(struct ip6_hdr)' 9822a632c3SIgor Ostapenko atf_set require.user root 9922a632c3SIgor Ostapenko} 10022a632c3SIgor Ostapenkoinet6_in_mbuf_len_body() 10122a632c3SIgor Ostapenko{ 10222a632c3SIgor Ostapenko pft_init 10322a632c3SIgor Ostapenko dummymbuf_init 10422a632c3SIgor Ostapenko 10522a632c3SIgor Ostapenko epair=$(vnet_mkepair) 10622a632c3SIgor Ostapenko ifconfig ${epair}a inet6 2001:db8::1/64 up no_dad 10722a632c3SIgor Ostapenko 10822a632c3SIgor Ostapenko # Set up a simple jail with one interface 10922a632c3SIgor Ostapenko vnet_mkjail alcatraz ${epair}b 11022a632c3SIgor Ostapenko jexec alcatraz ifconfig ${epair}b inet6 2001:db8::2/64 up no_dad 11122a632c3SIgor Ostapenko 11222a632c3SIgor Ostapenko # Sanity check 11322a632c3SIgor Ostapenko atf_check -s exit:0 -o ignore ping -c1 2001:db8::2 11422a632c3SIgor Ostapenko 11522a632c3SIgor Ostapenko # Should be denied 11622a632c3SIgor Ostapenko jexec alcatraz pfctl -e 11722a632c3SIgor Ostapenko pft_set_rules alcatraz \ 11822a632c3SIgor Ostapenko "block" \ 11922a632c3SIgor Ostapenko "pass quick inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" 12022a632c3SIgor Ostapenko atf_check -s not-exit:0 -o ignore ping -c1 -t1 2001:db8::2 12122a632c3SIgor Ostapenko 122*8829d4cbSIgor Ostapenko # Avoid redundant ICMPv6 packets to avoid false positives during 123*8829d4cbSIgor Ostapenko # counting of net.dummymbuf.hits. 124*8829d4cbSIgor Ostapenko ndp -i ${epair}a -- -nud 125*8829d4cbSIgor Ostapenko jexec alcatraz ndp -i ${epair}b -- -nud 126*8829d4cbSIgor Ostapenko 12722a632c3SIgor Ostapenko # Should be allowed by from/to addresses 12822a632c3SIgor Ostapenko pft_set_rules alcatraz \ 12922a632c3SIgor Ostapenko "block" \ 13022a632c3SIgor Ostapenko "pass quick inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \ 13122a632c3SIgor Ostapenko "pass in inet6 from 2001:db8::1 to 2001:db8::2" 13222a632c3SIgor Ostapenko atf_check -s exit:0 -o ignore ping -c1 2001:db8::2 13322a632c3SIgor Ostapenko 13422a632c3SIgor Ostapenko # Should still work for m_len=0 13522a632c3SIgor Ostapenko jexec alcatraz pfilctl link -i dummymbuf:inet6 inet6 13622a632c3SIgor Ostapenko jexec alcatraz sysctl net.dummymbuf.rules="inet6 in ${epair}b pull-head 0;" 13722a632c3SIgor Ostapenko atf_check_equal "0" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)" 13822a632c3SIgor Ostapenko atf_check -s exit:0 -o ignore ping -c1 2001:db8::2 13922a632c3SIgor Ostapenko atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)" 14022a632c3SIgor Ostapenko 14122a632c3SIgor Ostapenko # m_len=1 14222a632c3SIgor Ostapenko jexec alcatraz sysctl net.dummymbuf.rules="inet6 in ${epair}b pull-head 1;" 14322a632c3SIgor Ostapenko jexec alcatraz sysctl net.dummymbuf.hits=0 14422a632c3SIgor Ostapenko atf_check -s exit:0 -o ignore ping -c1 2001:db8::2 14522a632c3SIgor Ostapenko atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)" 14622a632c3SIgor Ostapenko 14722a632c3SIgor Ostapenko # m_len=39 14822a632c3SIgor Ostapenko # provided IPv6 basic header is 40 bytes long, it should impact the dst addr 14922a632c3SIgor Ostapenko jexec alcatraz sysctl net.dummymbuf.rules="inet6 in ${epair}b pull-head 39;" 15022a632c3SIgor Ostapenko jexec alcatraz sysctl net.dummymbuf.hits=0 15122a632c3SIgor Ostapenko atf_check -s exit:0 -o ignore ping -c1 2001:db8::2 15222a632c3SIgor Ostapenko atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)" 15322a632c3SIgor Ostapenko} 15422a632c3SIgor Ostapenkoinet6_in_mbuf_len_cleanup() 15522a632c3SIgor Ostapenko{ 15622a632c3SIgor Ostapenko pft_cleanup 15722a632c3SIgor Ostapenko} 15822a632c3SIgor Ostapenko 159e7f9171bSIgor Ostapenkoatf_test_case "ethernet_in_mbuf_len" "cleanup" 160e7f9171bSIgor Ostapenkoethernet_in_mbuf_len_head() 161e7f9171bSIgor Ostapenko{ 162e7f9171bSIgor Ostapenko atf_set descr 'Test that pf can handle inbound with the first mbuf with m_len < sizeof(struct ether_header)' 163e7f9171bSIgor Ostapenko atf_set require.user root 164e7f9171bSIgor Ostapenko} 165e7f9171bSIgor Ostapenkoethernet_in_mbuf_len_body() 166e7f9171bSIgor Ostapenko{ 167e7f9171bSIgor Ostapenko pft_init 168e7f9171bSIgor Ostapenko dummymbuf_init 169e7f9171bSIgor Ostapenko 170e7f9171bSIgor Ostapenko epair=$(vnet_mkepair) 171e7f9171bSIgor Ostapenko epair_a_mac=$(ifconfig ${epair}a ether | awk '/ether/ { print $2; }') 172e7f9171bSIgor Ostapenko ifconfig ${epair}a 192.0.2.1/24 up 173e7f9171bSIgor Ostapenko 174e7f9171bSIgor Ostapenko # Set up a simple jail with one interface 175e7f9171bSIgor Ostapenko vnet_mkjail alcatraz ${epair}b 176e7f9171bSIgor Ostapenko jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 177e7f9171bSIgor Ostapenko epair_b_mac=$(jexec alcatraz ifconfig ${epair}b ether | awk '/ether/ { print $2; }') 178e7f9171bSIgor Ostapenko 179e7f9171bSIgor Ostapenko # Sanity check 180e7f9171bSIgor Ostapenko atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 181e7f9171bSIgor Ostapenko 182e7f9171bSIgor Ostapenko # Should be denied 183e7f9171bSIgor Ostapenko jexec alcatraz pfctl -e 184e7f9171bSIgor Ostapenko pft_set_rules alcatraz \ 185e7f9171bSIgor Ostapenko "ether block" \ 186e7f9171bSIgor Ostapenko "pass" 187e7f9171bSIgor Ostapenko atf_check -s not-exit:0 -o ignore ping -c1 -t1 192.0.2.2 188e7f9171bSIgor Ostapenko 189e7f9171bSIgor Ostapenko # Should be allowed by from/to addresses 190e7f9171bSIgor Ostapenko echo $epair_a_mac 191e7f9171bSIgor Ostapenko echo $epair_b_mac 192e7f9171bSIgor Ostapenko pft_set_rules alcatraz \ 193e7f9171bSIgor Ostapenko "ether block" \ 194e7f9171bSIgor Ostapenko "ether pass in from ${epair_a_mac} to ${epair_b_mac}" \ 195e7f9171bSIgor Ostapenko "ether pass out from ${epair_b_mac} to ${epair_a_mac}" \ 196e7f9171bSIgor Ostapenko "pass" 197e7f9171bSIgor Ostapenko atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 198e7f9171bSIgor Ostapenko 199e7f9171bSIgor Ostapenko # Should still work for m_len=0 200e7f9171bSIgor Ostapenko jexec alcatraz pfilctl link -i dummymbuf:ethernet ethernet 201e7f9171bSIgor Ostapenko jexec alcatraz sysctl net.dummymbuf.rules="ethernet in ${epair}b pull-head 0;" 202e7f9171bSIgor Ostapenko atf_check_equal "0" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)" 203e7f9171bSIgor Ostapenko atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 204e7f9171bSIgor Ostapenko atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)" 205e7f9171bSIgor Ostapenko 206e7f9171bSIgor Ostapenko # m_len=1 207e7f9171bSIgor Ostapenko jexec alcatraz sysctl net.dummymbuf.rules="ethernet in ${epair}b pull-head 1;" 208e7f9171bSIgor Ostapenko jexec alcatraz sysctl net.dummymbuf.hits=0 209e7f9171bSIgor Ostapenko atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 210e7f9171bSIgor Ostapenko atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)" 211e7f9171bSIgor Ostapenko 212e7f9171bSIgor Ostapenko # m_len=11 213e7f9171bSIgor Ostapenko # for the simplest L2 Ethernet frame it should impact src field 214e7f9171bSIgor Ostapenko jexec alcatraz sysctl net.dummymbuf.rules="ethernet in ${epair}b pull-head 11;" 215e7f9171bSIgor Ostapenko jexec alcatraz sysctl net.dummymbuf.hits=0 216e7f9171bSIgor Ostapenko atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 217e7f9171bSIgor Ostapenko atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)" 218e7f9171bSIgor Ostapenko 219e7f9171bSIgor Ostapenko # m_len=13 220e7f9171bSIgor Ostapenko # provided L2 Ethernet simplest header is 14 bytes long, it should impact ethertype field 221e7f9171bSIgor Ostapenko jexec alcatraz sysctl net.dummymbuf.rules="ethernet in ${epair}b pull-head 13;" 222e7f9171bSIgor Ostapenko jexec alcatraz sysctl net.dummymbuf.hits=0 223e7f9171bSIgor Ostapenko atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 224e7f9171bSIgor Ostapenko atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)" 225e7f9171bSIgor Ostapenko} 226e7f9171bSIgor Ostapenkoethernet_in_mbuf_len_cleanup() 227e7f9171bSIgor Ostapenko{ 228e7f9171bSIgor Ostapenko pft_cleanup 229e7f9171bSIgor Ostapenko} 230e7f9171bSIgor Ostapenko 23109b7a038SIgor Ostapenkoatf_init_test_cases() 23209b7a038SIgor Ostapenko{ 23309b7a038SIgor Ostapenko atf_add_test_case "inet_in_mbuf_len" 23422a632c3SIgor Ostapenko atf_add_test_case "inet6_in_mbuf_len" 235e7f9171bSIgor Ostapenko atf_add_test_case "ethernet_in_mbuf_len" 23609b7a038SIgor Ostapenko} 237