1# 2# SPDX-License-Identifier: BSD-2-Clause 3# 4# Copyright (c) 2020 Mark Johnston <markj@FreeBSD.org> 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 29TABLE_STATS_ZERO_REGEXP='Packets: 0[[:space:]]*Bytes: 0[[:space:]]' 30TABLE_STATS_NONZERO_REGEXP='Packets: [1-9][0-9]*[[:space:]]*Bytes: [1-9][0-9]*[[:space:]]' 31 32atf_test_case "v4_counters" "cleanup" 33v4_counters_head() 34{ 35 atf_set descr 'Verify per-address counters for v4' 36 atf_set require.user root 37} 38 39v4_counters_body() 40{ 41 pft_init 42 43 epair_send=$(vnet_mkepair) 44 ifconfig ${epair_send}a 192.0.2.1/24 up 45 46 vnet_mkjail alcatraz ${epair_send}b 47 jexec alcatraz ifconfig ${epair_send}b 192.0.2.2/24 up 48 jexec alcatraz pfctl -e 49 50 pft_set_rules alcatraz \ 51 "table <foo> counters { 192.0.2.1 }" \ 52 "block all" \ 53 "pass in from <foo> to any" \ 54 "pass out from any to <foo>" \ 55 "set skip on lo" 56 57 atf_check -s exit:0 -o ignore ping -c 3 192.0.2.2 58 59 atf_check -s exit:0 -e ignore \ 60 -o match:'In/Block:.*'"$TABLE_STATS_ZERO_REGEXP" \ 61 -o match:'In/Pass:.*'"$TABLE_STATS_NONZERO_REGEXP" \ 62 -o match:'Out/Block:.*'"$TABLE_STATS_ZERO_REGEXP" \ 63 -o match:'Out/Pass:.*'"$TABLE_STATS_NONZERO_REGEXP" \ 64 jexec alcatraz pfctl -t foo -T show -vv 65} 66 67v4_counters_cleanup() 68{ 69 pft_cleanup 70} 71 72atf_test_case "v6_counters" "cleanup" 73v6_counters_head() 74{ 75 atf_set descr 'Verify per-address counters for v6' 76 atf_set require.user root 77} 78 79v6_counters_body() 80{ 81 pft_init 82 83 epair_send=$(vnet_mkepair) 84 ifconfig ${epair_send}a inet6 2001:db8:42::1/64 up no_dad -ifdisabled 85 86 vnet_mkjail alcatraz ${epair_send}b 87 jexec alcatraz ifconfig ${epair_send}b inet6 2001:db8:42::2/64 up no_dad 88 jexec alcatraz pfctl -e 89 90 pft_set_rules alcatraz \ 91 "table <foo6> counters { 2001:db8:42::1 }" \ 92 "block all" \ 93 "pass in from <foo6> to any" \ 94 "pass out from any to <foo6>" \ 95 "set skip on lo" 96 97 atf_check -s exit:0 -o ignore ping -6 -c 3 2001:db8:42::2 98 99 atf_check -s exit:0 -e ignore \ 100 -o match:'In/Block:.*'"$TABLE_STATS_ZERO_REGEXP" \ 101 -o match:'In/Pass:.*'"$TABLE_STATS_NONZERO_REGEXP" \ 102 -o match:'Out/Block:.*'"$TABLE_STATS_ZERO_REGEXP" \ 103 -o match:'Out/Pass:.*'"$TABLE_STATS_NONZERO_REGEXP" \ 104 jexec alcatraz pfctl -t foo6 -T show -vv 105} 106 107v6_counters_cleanup() 108{ 109 pft_cleanup 110} 111 112atf_test_case "zero_one" "cleanup" 113zero_one_head() 114{ 115 atf_set descr 'Test zeroing a single address in a table' 116 atf_set require.user root 117} 118 119zero_one_body() 120{ 121 epair_send=$(vnet_mkepair) 122 ifconfig ${epair_send}a 192.0.2.1/24 up 123 ifconfig ${epair_send}a inet alias 192.0.2.3/24 124 125 vnet_mkjail alcatraz ${epair_send}b 126 jexec alcatraz ifconfig ${epair_send}b 192.0.2.2/24 up 127 jexec alcatraz pfctl -e 128 129 pft_set_rules alcatraz \ 130 "table <foo> counters { 192.0.2.1, 192.0.2.3 }" \ 131 "block all" \ 132 "pass in from <foo> to any" \ 133 "pass out from any to <foo>" \ 134 "set skip on lo" 135 136 atf_check -s exit:0 -o ignore ping -c 3 -S 192.0.2.1 192.0.2.2 137 atf_check -s exit:0 -o ignore ping -c 3 -S 192.0.2.3 192.0.2.2 138 139 jexec alcatraz pfctl -t foo -T show -vv 140 141 atf_check -s exit:0 -e ignore \ 142 -o match:'In/Block:.*'"$TABLE_STATS_ZERO_REGEXP" \ 143 -o match:'In/Pass:.*'"$TABLE_STATS_NONZERO_REGEXP" \ 144 -o match:'Out/Block:.*'"$TABLE_STATS_ZERO_REGEXP" \ 145 -o match:'Out/Pass:.*'"$TABLE_STATS_NONZERO_REGEXP" \ 146 jexec alcatraz pfctl -t foo -T show -vv 147 148 atf_check -s exit:0 -e ignore \ 149 jexec alcatraz pfctl -t foo -T zero 192.0.2.3 150 151 # We now have a zeroed and a non-zeroed counter, so both patterns 152 # should match 153 atf_check -s exit:0 -e ignore \ 154 -o match:'In/Pass:.*'"$TABLE_STATS_NONZERO_REGEXP" \ 155 -o match:'Out/Pass:.*'"$TABLE_STATS_NONZERO_REGEXP" \ 156 jexec alcatraz pfctl -t foo -T show -vv 157 atf_check -s exit:0 -e ignore \ 158 -o match:'In/Pass:.*'"$TABLE_STATS_ZERO_REGEXP" \ 159 -o match:'Out/Pass:.*'"$TABLE_STATS_ZERO_REGEXP" \ 160 jexec alcatraz pfctl -t foo -T show -vv 161} 162 163zero_one_cleanup() 164{ 165 pft_cleanup 166} 167 168atf_test_case "reset_nonzero" "cleanup" 169reset_nonzero_head() 170{ 171 atf_set descr 'Test zeroing an address with non-zero counters' 172 atf_set require.user root 173} 174 175reset_nonzero_body() 176{ 177 epair_send=$(vnet_mkepair) 178 ifconfig ${epair_send}a 192.0.2.1/24 up 179 ifconfig ${epair_send}a inet alias 192.0.2.3/24 180 181 vnet_mkjail alcatraz ${epair_send}b 182 jexec alcatraz ifconfig ${epair_send}b 192.0.2.2/24 up 183 jexec alcatraz pfctl -e 184 185 pft_set_rules alcatraz \ 186 "table <foo> counters { 192.0.2.1, 192.0.2.3 }" \ 187 "table <bar> counters { }" \ 188 "block all" \ 189 "pass in from <foo> to any" \ 190 "pass out from any to <foo>" \ 191 "pass on notReallyAnIf from <bar> to <bar>" \ 192 "set skip on lo" 193 194 # Nonexisting table can't be reset, following `-T show`. 195 atf_check -o ignore \ 196 -s not-exit:0 \ 197 -e inline:"pfctl: Table does not exist.\n" \ 198 jexec alcatraz pfctl -t nonexistent -T reset 199 200 atf_check -o ignore \ 201 -s exit:0 \ 202 -e inline:"0/0 stats cleared.\n" \ 203 jexec alcatraz pfctl -t bar -T reset 204 205 # No-op is a valid operation. 206 atf_check -s exit:0 \ 207 -e inline:"0/2 stats cleared.\n" \ 208 jexec alcatraz pfctl -t foo -T reset 209 210 atf_check -s exit:0 -o ignore ping -c 3 -S 192.0.2.3 192.0.2.2 211 212 atf_check -s exit:0 -e ignore \ 213 -o match:'In/Pass:.*'"$TABLE_STATS_ZERO_REGEXP" \ 214 -o match:'In/Pass:.*'"$TABLE_STATS_NONZERO_REGEXP" \ 215 -o match:'Out/Pass:.*'"$TABLE_STATS_ZERO_REGEXP" \ 216 -o match:'Out/Pass:.*'"$TABLE_STATS_NONZERO_REGEXP" \ 217 jexec alcatraz pfctl -t foo -vvT show 218 219 local clrd uniq 220 clrd=`jexec alcatraz pfctl -t foo -vvT show | grep -c Cleared` 221 uniq=`jexec alcatraz pfctl -t foo -vvT show | sort -u | grep -c Cleared` 222 atf_check_equal "$clrd" 2 223 atf_check_equal "$uniq" 1 # time they were added 224 225 atf_check -s exit:0 -e ignore \ 226 -e inline:"1/2 stats cleared.\n" \ 227 jexec alcatraz pfctl -t foo -T reset 228 229 clrd=`jexec alcatraz pfctl -t foo -vvT show | grep -c Cleared` 230 uniq=`jexec alcatraz pfctl -t foo -vvT show | sort -u | grep -c Cleared` 231 atf_check_equal "$clrd" 2 232 atf_check_equal "$uniq" 2 # 192.0.2.3 should get new timestamp 233 234 atf_check -s exit:0 -e ignore \ 235 -o not-match:'In/Pass:.*'"$TABLE_STATS_NONZERO_REGEXP" \ 236 -o not-match:'Out/Pass:.*'"$TABLE_STATS_NONZERO_REGEXP" \ 237 -o match:'In/Pass:.*'"$TABLE_STATS_ZERO_REGEXP" \ 238 -o match:'Out/Pass:.*'"$TABLE_STATS_ZERO_REGEXP" \ 239 jexec alcatraz pfctl -t foo -vvT show 240} 241 242reset_nonzero_cleanup() 243{ 244 pft_cleanup 245} 246 247atf_test_case "pr251414" "cleanup" 248pr251414_head() 249{ 250 atf_set descr 'Test PR 251414' 251 atf_set require.user root 252} 253 254pr251414_body() 255{ 256 pft_init 257 258 epair_send=$(vnet_mkepair) 259 ifconfig ${epair_send}a 192.0.2.1/24 up 260 261 vnet_mkjail alcatraz ${epair_send}b 262 jexec alcatraz ifconfig ${epair_send}b 192.0.2.2/24 up 263 jexec alcatraz pfctl -e 264 265 pft_set_rules alcatraz \ 266 "pass all" \ 267 "table <tab> { self }" \ 268 "pass in log to <tab>" 269 270 pft_set_rules noflush alcatraz \ 271 "pass all" \ 272 "table <tab> counters { self }" \ 273 "pass in log to <tab>" 274 275 atf_check -s exit:0 -o ignore ping -c 3 192.0.2.2 276 277 jexec alcatraz pfctl -t tab -T show -vv 278} 279 280pr251414_cleanup() 281{ 282 pft_cleanup 283} 284 285atf_test_case "automatic" "cleanup" 286automatic_head() 287{ 288 atf_set descr "Test automatic - optimizer generated - tables" 289 atf_set require.user root 290} 291 292automatic_body() 293{ 294 pft_init 295 296 epair=$(vnet_mkepair) 297 ifconfig ${epair}a 192.0.2.1/24 up 298 299 vnet_mkjail alcatraz ${epair}b 300 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 301 jexec alcatraz pfctl -e 302 303 pft_set_rules alcatraz \ 304 "block in" \ 305 "pass in proto icmp from 192.0.2.1" \ 306 "pass in proto icmp from 192.0.2.3" \ 307 "pass in proto icmp from 192.0.2.4" \ 308 "pass in proto icmp from 192.0.2.5" \ 309 "pass in proto icmp from 192.0.2.6" \ 310 "pass in proto icmp from 192.0.2.7" \ 311 "pass in proto icmp from 192.0.2.8" \ 312 "pass in proto icmp from 192.0.2.9" 313 314 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2 315} 316 317automatic_cleanup() 318{ 319 pft_cleanup 320} 321 322atf_test_case "network" "cleanup" 323network_head() 324{ 325 atf_set descr 'Test <ifgroup>:network' 326 atf_set require.user root 327} 328 329network_body() 330{ 331 pft_init 332 333 epair=$(vnet_mkepair) 334 ifconfig ${epair}a 192.0.2.1/24 up 335 336 vnet_mkjail alcatraz ${epair}b 337 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 338 jexec alcatraz pfctl -e 339 340 pft_set_rules alcatraz \ 341 "table <allow> const { epair:network }"\ 342 "block in" \ 343 "pass in from <allow>" 344 345 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2 346} 347 348network_cleanup() 349{ 350 pft_cleanup 351} 352 353atf_test_case "pr259689" "cleanup" 354pr259689_head() 355{ 356 atf_set descr 'Test PR 259689' 357 atf_set require.user root 358} 359 360pr259689_body() 361{ 362 pft_init 363 364 vnet_mkjail alcatraz 365 jexec alcatraz pfctl -e 366 367 pft_set_rules alcatraz \ 368 "pass in" \ 369 "block in inet from { 1.1.1.1, 1.1.1.2, 2.2.2.2, 2.2.2.3, 4.4.4.4, 4.4.4.5 }" 370 371 atf_check -o match:'block drop in inet from <__automatic_.*:6> to any' \ 372 -e ignore \ 373 jexec alcatraz pfctl -sr -vv 374} 375 376pr259689_cleanup() 377{ 378 pft_cleanup 379} 380 381atf_test_case "precreate" "cleanup" 382precreate_head() 383{ 384 atf_set descr 'Test creating a table without counters, then loading rules that add counters' 385 atf_set require.user root 386} 387 388precreate_body() 389{ 390 pft_init 391 392 vnet_mkjail alcatraz 393 394 jexec alcatraz pfctl -t foo -T add 192.0.2.1 395 jexec alcatraz pfctl -t foo -T show 396 397 pft_set_rules noflush alcatraz \ 398 "table <foo> counters persist" \ 399 "pass in from <foo>" 400 401 # Expect all counters to be zero 402 atf_check -s exit:0 -e ignore \ 403 -o match:'In/Block:.*'"$TABLE_STATS_ZERO_REGEXP" \ 404 -o match:'In/Pass:.*'"$TABLE_STATS_ZERO_REGEXP" \ 405 -o match:'Out/Block:.*'"$TABLE_STATS_ZERO_REGEXP" \ 406 -o match:'Out/Pass:.*'"$TABLE_STATS_ZERO_REGEXP" \ 407 jexec alcatraz pfctl -t foo -T show -vv 408 409} 410 411precreate_cleanup() 412{ 413 pft_cleanup 414} 415 416atf_test_case "anchor" "cleanup" 417anchor_head() 418{ 419 atf_set descr 'Test tables in anchors' 420 atf_set require.user root 421} 422 423anchor_body() 424{ 425 pft_init 426 427 epair=$(vnet_mkepair) 428 ifconfig ${epair}a 192.0.2.1/24 up 429 430 vnet_mkjail alcatraz ${epair}b 431 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 432 jexec alcatraz pfctl -e 433 434 (echo "table <testtable> persist" 435 echo "block in quick from <testtable> to any" 436 ) | jexec alcatraz pfctl -a anchorage -f - 437 438 pft_set_rules noflush alcatraz \ 439 "pass" \ 440 "anchor anchorage" 441 442 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2 443 444 # Tables belong to anchors, so this is a different table and won't affect anything 445 jexec alcatraz pfctl -t testtable -T add 192.0.2.1 446 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2 447 448 # But when we add the address to the table in the anchor it does block traffic 449 jexec alcatraz pfctl -a anchorage -t testtable -T add 192.0.2.1 450 atf_check -s exit:2 -o ignore ping -c 1 192.0.2.2 451} 452 453anchor_cleanup() 454{ 455 pft_cleanup 456} 457 458atf_init_test_cases() 459{ 460 atf_add_test_case "v4_counters" 461 atf_add_test_case "v6_counters" 462 atf_add_test_case "zero_one" 463 atf_add_test_case "reset_nonzero" 464 atf_add_test_case "pr251414" 465 atf_add_test_case "automatic" 466 atf_add_test_case "network" 467 atf_add_test_case "pr259689" 468 atf_add_test_case "precreate" 469 atf_add_test_case "anchor" 470} 471