1# 2# SPDX-License-Identifier: BSD-2-Clause 3# 4# Copyright (c) 2024 Igor Ostapenko <pm@igoro.pro> 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25# SUCH DAMAGE. 26 27. $(atf_get_srcdir)/utils.subr 28 29dummymbuf_init() 30{ 31 if ! kldstat -q -m dummymbuf; then 32 atf_skip "This test requires dummymbuf" 33 fi 34} 35 36atf_test_case "inet_in_mbuf_len" "cleanup" 37inet_in_mbuf_len_head() 38{ 39 atf_set descr 'Test that pf can handle inbound with the first mbuf with m_len < sizeof(struct ip)' 40 atf_set require.user root 41} 42inet_in_mbuf_len_body() 43{ 44 pft_init 45 dummymbuf_init 46 47 epair=$(vnet_mkepair) 48 ifconfig ${epair}a 192.0.2.1/24 up 49 50 # Set up a simple jail with one interface 51 vnet_mkjail alcatraz ${epair}b 52 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 53 54 # Sanity check 55 atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 56 57 # Should be denied 58 jexec alcatraz pfctl -e 59 pft_set_rules alcatraz \ 60 "block" 61 atf_check -s not-exit:0 -o ignore ping -c1 -t1 192.0.2.2 62 63 # Should be allowed by from/to addresses 64 pft_set_rules alcatraz \ 65 "block" \ 66 "pass in from 192.0.2.1 to 192.0.2.2" 67 atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 68 69 # Should still work for m_len=0 70 jexec alcatraz pfilctl link -i dummymbuf:inet inet 71 jexec alcatraz sysctl net.dummymbuf.rules="inet in ${epair}b pull-head 0;" 72 atf_check_equal '0' '$(jexec alcatraz sysctl -n net.dummymbuf.hits)' 73 atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 74 atf_check_equal '1' '$(jexec alcatraz sysctl -n net.dummymbuf.hits)' 75 76 # m_len=1 77 jexec alcatraz sysctl net.dummymbuf.rules="inet in ${epair}b pull-head 1;" 78 jexec alcatraz sysctl net.dummymbuf.hits=0 79 atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 80 atf_check_equal '1' '$(jexec alcatraz sysctl -n net.dummymbuf.hits)' 81 82 # m_len=19 83 # provided IPv4 basic header is 20 bytes long, it should impact the dst addr 84 jexec alcatraz sysctl net.dummymbuf.rules="inet in ${epair}b pull-head 19;" 85 jexec alcatraz sysctl net.dummymbuf.hits=0 86 atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 87 atf_check_equal '1' '$(jexec alcatraz sysctl -n net.dummymbuf.hits)' 88} 89inet_in_mbuf_len_cleanup() 90{ 91 pft_cleanup 92} 93 94atf_test_case "inet6_in_mbuf_len" "cleanup" 95inet6_in_mbuf_len_head() 96{ 97 atf_set descr 'Test that pf can handle inbound with the first mbuf with m_len < sizeof(struct ip6_hdr)' 98 atf_set require.user root 99} 100inet6_in_mbuf_len_body() 101{ 102 pft_init 103 dummymbuf_init 104 105 epair=$(vnet_mkepair) 106 ifconfig ${epair}a inet6 2001:db8::1/64 up no_dad 107 108 # Ensure we don't unintentionally send MLD packets to alcatraz 109 pfctl -e 110 echo "block 111 pass out inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv, echoreq, echorep } 112 " | pfctl -g -f - 113 114 # Set up a simple jail with one interface 115 vnet_mkjail alcatraz ${epair}b 116 jexec alcatraz ifconfig ${epair}b inet6 2001:db8::2/64 up no_dad 117 118 # Sanity check 119 atf_check -s exit:0 -o ignore ping -c1 2001:db8::2 120 121 # Should be denied 122 jexec alcatraz pfctl -e 123 pft_set_rules alcatraz \ 124 "block" \ 125 "pass quick inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" 126 atf_check -s not-exit:0 -o ignore ping -c1 -t1 2001:db8::2 127 128 # Avoid redundant ICMPv6 packets to avoid false positives during 129 # counting of net.dummymbuf.hits. 130 ndp -i ${epair}a -- -nud 131 jexec alcatraz ndp -i ${epair}b -- -nud 132 133 # Should be allowed by from/to addresses 134 pft_set_rules alcatraz \ 135 "block" \ 136 "pass quick inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \ 137 "pass in inet6 from 2001:db8::1 to 2001:db8::2" 138 atf_check -s exit:0 -o ignore ping -c1 2001:db8::2 139 140 # Should still work for m_len=0 141 jexec alcatraz pfilctl link -i dummymbuf:inet6 inet6 142 jexec alcatraz sysctl net.dummymbuf.rules="inet6 in ${epair}b pull-head 0;" 143 atf_check_equal '0' '$(jexec alcatraz sysctl -n net.dummymbuf.hits)' 144 atf_check -s exit:0 -o ignore ping -c1 2001:db8::2 145 atf_check_equal '1' '$(jexec alcatraz sysctl -n net.dummymbuf.hits)' 146 147 # m_len=1 148 jexec alcatraz sysctl net.dummymbuf.rules="inet6 in ${epair}b pull-head 1;" 149 jexec alcatraz sysctl net.dummymbuf.hits=0 150 atf_check -s exit:0 -o ignore ping -c1 2001:db8::2 151 atf_check_equal '1' '$(jexec alcatraz sysctl -n net.dummymbuf.hits)' 152 153 # m_len=39 154 # provided IPv6 basic header is 40 bytes long, it should impact the dst addr 155 jexec alcatraz sysctl net.dummymbuf.rules="inet6 in ${epair}b pull-head 39;" 156 jexec alcatraz sysctl net.dummymbuf.hits=0 157 atf_check -s exit:0 -o ignore ping -c1 2001:db8::2 158 atf_check_equal '1' '$(jexec alcatraz sysctl -n net.dummymbuf.hits)' 159} 160inet6_in_mbuf_len_cleanup() 161{ 162 pft_cleanup 163} 164 165atf_test_case "ethernet_in_mbuf_len" "cleanup" 166ethernet_in_mbuf_len_head() 167{ 168 atf_set descr 'Test that pf can handle inbound with the first mbuf with m_len < sizeof(struct ether_header)' 169 atf_set require.user root 170} 171ethernet_in_mbuf_len_body() 172{ 173 pft_init 174 dummymbuf_init 175 176 epair=$(vnet_mkepair) 177 epair_a_mac=$(ifconfig ${epair}a ether | awk '/ether/ { print $2; }') 178 ifconfig ${epair}a 192.0.2.1/24 up 179 180 # Set up a simple jail with one interface 181 vnet_mkjail alcatraz ${epair}b 182 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 183 epair_b_mac=$(jexec alcatraz ifconfig ${epair}b ether | awk '/ether/ { print $2; }') 184 185 # Sanity check 186 atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 187 188 # Should be denied 189 jexec alcatraz pfctl -e 190 pft_set_rules alcatraz \ 191 "ether block" \ 192 "pass" 193 atf_check -s not-exit:0 -o ignore ping -c1 -t1 192.0.2.2 194 195 # Should be allowed by from/to addresses 196 echo $epair_a_mac 197 echo $epair_b_mac 198 pft_set_rules alcatraz \ 199 "ether block" \ 200 "ether pass in from ${epair_a_mac} to ${epair_b_mac}" \ 201 "ether pass out from ${epair_b_mac} to ${epair_a_mac}" \ 202 "pass" 203 atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 204 205 # Should still work for m_len=0 206 jexec alcatraz pfilctl link -i dummymbuf:ethernet ethernet 207 jexec alcatraz sysctl net.dummymbuf.rules="ethernet in ${epair}b pull-head 0;" 208 atf_check_equal '0' '$(jexec alcatraz sysctl -n net.dummymbuf.hits)' 209 atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 210 atf_check_equal '1' '$(jexec alcatraz sysctl -n net.dummymbuf.hits)' 211 212 # m_len=1 213 jexec alcatraz sysctl net.dummymbuf.rules="ethernet in ${epair}b pull-head 1;" 214 jexec alcatraz sysctl net.dummymbuf.hits=0 215 atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 216 atf_check_equal '1' '$(jexec alcatraz sysctl -n net.dummymbuf.hits)' 217 218 # m_len=11 219 # for the simplest L2 Ethernet frame it should impact src field 220 jexec alcatraz sysctl net.dummymbuf.rules="ethernet in ${epair}b pull-head 11;" 221 jexec alcatraz sysctl net.dummymbuf.hits=0 222 atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 223 atf_check_equal '1' '$(jexec alcatraz sysctl -n net.dummymbuf.hits)' 224 225 # m_len=13 226 # provided L2 Ethernet simplest header is 14 bytes long, it should impact ethertype field 227 jexec alcatraz sysctl net.dummymbuf.rules="ethernet in ${epair}b pull-head 13;" 228 jexec alcatraz sysctl net.dummymbuf.hits=0 229 atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 230 atf_check_equal '1' '$(jexec alcatraz sysctl -n net.dummymbuf.hits)' 231} 232ethernet_in_mbuf_len_cleanup() 233{ 234 pft_cleanup 235} 236 237atf_init_test_cases() 238{ 239 atf_add_test_case "inet_in_mbuf_len" 240 atf_add_test_case "inet6_in_mbuf_len" 241 atf_add_test_case "ethernet_in_mbuf_len" 242} 243