1# 2# SPDX-License-Identifier: BSD-2-Clause 3# 4# Copyright (c) 2023 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# 28# ipfw divert action test cases 29# 30# -----------| |-- |----| ----| |----------- 31# ( ) inbound |ipfw| ) -> |host| -> ( ) |ipfw| outbound ) 32# -----------| | |-- |----| ----| | |----------- 33# | | 34# \|/ \|/ 35# |------| |------| 36# |divapp| |divapp| 37# |------| |------| 38# 39# The basic cases: 40# - inbound > diverted | divapp terminated 41# - inbound > diverted > inbound | host terminated 42# - inbound > diverted > outbound | network terminated 43# - outbound > diverted | divapp terminated 44# - outbound > diverted > outbound | network terminated 45# - outbound > diverted > inbound | e.g. host terminated 46# 47# When a packet is diverted, forwarded, and possibly diverted again: 48# - inbound > diverted > inbound > forwarded 49# > outbound | network terminated 50# - inbound > diverted > inbound > forwarded 51# > outbound > diverted > outbound | network terminated 52# 53# Test case naming legend: 54# in - inbound 55# div - diverted 56# out - outbound 57# fwd - forwarded 58# 59 60. $(atf_get_srcdir)/../common/utils.subr 61 62divert_init() 63{ 64 if ! kldstat -q -m ipdivert; then 65 atf_skip "This test requires ipdivert" 66 fi 67} 68 69atf_test_case "in_div" "cleanup" 70in_div_head() 71{ 72 atf_set descr 'Test inbound > diverted | divapp terminated' 73 atf_set require.user root 74} 75in_div_body() 76{ 77 firewall_init "ipfw" 78 divert_init 79 80 epair=$(vnet_mkepair) 81 vnet_mkjail div ${epair}b 82 ifconfig ${epair}a 192.0.2.1/24 up 83 jexec div ifconfig ${epair}b 192.0.2.2/24 up 84 jexec div ipfw add 65534 allow all from any to any 85 86 # Sanity check 87 atf_check -s exit:0 -o ignore ping -c3 192.0.2.2 88 89 jexec div ipfw add 100 divert 2000 icmp from any to any in icmptypes 8 90 91 jexec div $(atf_get_srcdir)/../common/divapp 2000 & 92 divapp_pid=$! 93 # Wait for the divapp to be ready 94 sleep 1 95 96 # divapp is expected to "eat" the packet 97 atf_check -s not-exit:0 -o ignore ping -c1 -t1 192.0.2.2 98 99 wait $divapp_pid 100} 101in_div_cleanup() 102{ 103 firewall_cleanup "ipfw" 104} 105 106atf_test_case "in_div_in" "cleanup" 107in_div_in_head() 108{ 109 atf_set descr 'Test inbound > diverted > inbound | host terminated' 110 atf_set require.user root 111} 112in_div_in_body() 113{ 114 firewall_init "ipfw" 115 divert_init 116 117 epair=$(vnet_mkepair) 118 vnet_mkjail div ${epair}b 119 ifconfig ${epair}a 192.0.2.1/24 up 120 jexec div ifconfig ${epair}b 192.0.2.2/24 up 121 jexec div ipfw add 65534 allow all from any to any 122 123 # Sanity check 124 atf_check -s exit:0 -o ignore ping -c3 192.0.2.2 125 126 jexec div ipfw add 100 divert 2000 icmp from any to any in icmptypes 8 127 128 jexec div $(atf_get_srcdir)/../common/divapp 2000 divert-back & 129 divapp_pid=$! 130 # Wait for the divapp to be ready 131 sleep 1 132 133 # divapp is NOT expected to "eat" the packet 134 atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 135 136 wait $divapp_pid 137} 138in_div_in_cleanup() 139{ 140 firewall_cleanup "ipfw" 141} 142 143atf_test_case "out_div" "cleanup" 144out_div_head() 145{ 146 atf_set descr 'Test outbound > diverted | divapp terminated' 147 atf_set require.user root 148} 149out_div_body() 150{ 151 firewall_init "ipfw" 152 divert_init 153 154 epair=$(vnet_mkepair) 155 vnet_mkjail div ${epair}b 156 ifconfig ${epair}a 192.0.2.1/24 up 157 jexec div ifconfig ${epair}b 192.0.2.2/24 up 158 jexec div ipfw add 65534 allow all from any to any 159 160 # Sanity check 161 atf_check -s exit:0 -o ignore ping -c3 192.0.2.2 162 163 jexec div ipfw add 100 divert 2000 icmp from any to any out icmptypes 0 164 165 jexec div $(atf_get_srcdir)/../common/divapp 2000 & 166 divapp_pid=$! 167 # Wait for the divapp to be ready 168 sleep 1 169 170 # divapp is expected to "eat" the packet 171 atf_check -s not-exit:0 -o ignore ping -c1 -t1 192.0.2.2 172 173 wait $divapp_pid 174} 175out_div_cleanup() 176{ 177 firewall_cleanup "ipfw" 178} 179 180atf_test_case "out_div_out" "cleanup" 181out_div_out_head() 182{ 183 atf_set descr 'Test outbound > diverted > outbound | network terminated' 184 atf_set require.user root 185} 186out_div_out_body() 187{ 188 firewall_init "ipfw" 189 divert_init 190 191 epair=$(vnet_mkepair) 192 vnet_mkjail div ${epair}b 193 ifconfig ${epair}a 192.0.2.1/24 up 194 jexec div ifconfig ${epair}b 192.0.2.2/24 up 195 jexec div ipfw add 65534 allow all from any to any 196 197 # Sanity check 198 atf_check -s exit:0 -o ignore ping -c3 192.0.2.2 199 200 jexec div ipfw add 100 divert 2000 icmp from any to any out icmptypes 0 201 202 jexec div $(atf_get_srcdir)/../common/divapp 2000 divert-back & 203 divapp_pid=$! 204 # Wait for the divapp to be ready 205 sleep 1 206 207 # divapp is NOT expected to "eat" the packet 208 atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 209 210 wait $divapp_pid 211} 212out_div_out_cleanup() 213{ 214 firewall_cleanup "ipfw" 215} 216 217atf_test_case "in_div_in_fwd_out_div_out" "cleanup" 218in_div_in_fwd_out_div_out_head() 219{ 220 atf_set descr 'Test inbound > diverted > inbound > forwarded > outbound > diverted > outbound | network terminated' 221 atf_set require.user root 222} 223in_div_in_fwd_out_div_out_body() 224{ 225 firewall_init "ipfw" 226 divert_init 227 228 # host <a--epair0--b> router <a--epair1--b> site 229 epair0=$(vnet_mkepair) 230 epair1=$(vnet_mkepair) 231 232 vnet_mkjail router ${epair0}b ${epair1}a 233 ifconfig ${epair0}a 192.0.2.1/24 up 234 jexec router sysctl net.inet.ip.forwarding=1 235 jexec router ifconfig ${epair0}b 192.0.2.2/24 up 236 jexec router ifconfig ${epair1}a 198.51.100.1/24 up 237 jexec router ipfw add 65534 allow all from any to any 238 239 vnet_mkjail site ${epair1}b 240 jexec site ifconfig ${epair1}b 198.51.100.2/24 up 241 jexec site ipfw add 65534 allow all from any to any 242 jexec site route add default 198.51.100.1 243 244 route add -net 198.51.100.0/24 192.0.2.2 245 246 # Sanity check 247 atf_check -s exit:0 -o ignore ping -c3 192.0.2.2 248 249 # Should be routed without diversion 250 atf_check -s exit:0 -o ignore ping -c3 198.51.100.2 251 252 jexec router ipfw add 100 divert 2001 icmp from any to any in icmptypes 8 253 jexec router ipfw add 200 divert 2002 icmp from any to any out icmptypes 8 254 255 jexec router $(atf_get_srcdir)/../common/divapp 2001 divert-back & 256 indivapp_pid=$! 257 jexec router $(atf_get_srcdir)/../common/divapp 2002 divert-back & 258 outdivapp_pid=$! 259 # Wait for the divappS to be ready 260 sleep 1 261 262 # Both divappS are NOT expected to "eat" the packet 263 atf_check -s exit:0 -o ignore ping -c1 198.51.100.2 264 265 wait $indivapp_pid && wait $outdivapp_pid 266} 267in_div_in_fwd_out_div_out_cleanup() 268{ 269 firewall_cleanup "ipfw" 270} 271 272atf_init_test_cases() 273{ 274 atf_add_test_case "in_div" 275 atf_add_test_case "in_div_in" 276 277 atf_add_test_case "out_div" 278 atf_add_test_case "out_div_out" 279 280 atf_add_test_case "in_div_in_fwd_out_div_out" 281} 282