xref: /freebsd/tests/sys/netpfil/pf/ioctl/validation.c (revision ae07a5805b1906f29e786f415d67bef334557bd3)
1 /*-
2  * Copyright (c) 2018	Kristof Provost <kp@FreeBSD.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 
26 #include <sys/param.h>
27 #include <sys/module.h>
28 #include <sys/types.h>
29 #include <sys/ioctl.h>
30 #include <sys/socket.h>
31 
32 #include <net/if.h>
33 #include <net/pfvar.h>
34 
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <stdio.h>
38 
39 #include <atf-c.h>
40 
41 static int dev;
42 
43 #define COMMON_HEAD() \
44 	if (modfind("pf") == -1) \
45 		atf_tc_skip("pf not loaded"); \
46 	dev = open("/dev/pf", O_RDWR); \
47 	if (dev == -1) \
48 		atf_tc_skip("Failed to open /dev/pf");
49 
50 #define COMMON_CLEANUP() \
51 	close(dev);
52 
53 static void
54 common_init_tbl(struct pfr_table *tbl)
55 {
56 	bzero(tbl, sizeof(struct pfr_table));
57 	strcpy(tbl->pfrt_anchor, "anchor");
58 	strcpy(tbl->pfrt_name, "name");
59 	tbl->pfrt_flags = 0;
60 	tbl->pfrt_fback = 0;
61 }
62 
63 ATF_TC_WITH_CLEANUP(addtables);
64 ATF_TC_HEAD(addtables, tc)
65 {
66 	atf_tc_set_md_var(tc, "require.user", "root");
67 }
68 
69 ATF_TC_BODY(addtables, tc)
70 {
71 	struct pfioc_table io;
72 	struct pfr_table tbl;
73 	struct pfr_table tbls[4];
74 	int flags;
75 
76 	COMMON_HEAD();
77 
78 	flags = 0;
79 
80 	bzero(&io, sizeof(io));
81 	io.pfrio_flags = flags;
82 	io.pfrio_buffer = &tbl;
83 	io.pfrio_esize = sizeof(tbl);
84 
85 	/* Negative size */
86 	io.pfrio_size = -1;
87 	if (ioctl(dev, DIOCRADDTABLES, &io) == 0)
88 		atf_tc_fail("Request with size -1 succeeded");
89 
90 	/* Overly large size */
91 	io.pfrio_size = 1 << 24;
92 	if (ioctl(dev, DIOCRADDTABLES, &io) == 0)
93 		atf_tc_fail("Request with size 1 << 24 succeeded");
94 
95 	/* NULL buffer */
96 	io.pfrio_size = 1;
97 	io.pfrio_buffer = NULL;
98 	if (ioctl(dev, DIOCRADDTABLES, &io) == 0)
99 		atf_tc_fail("Request with NULL buffer succeeded");
100 
101 	/* This can provoke a memory leak, see r331225. */
102 	io.pfrio_size = 4;
103 	for (int i = 0; i < io.pfrio_size; i++)
104 		common_init_tbl(&tbls[i]);
105 
106 	io.pfrio_buffer = &tbls;
107 	ioctl(dev, DIOCRADDTABLES, &io);
108 }
109 
110 ATF_TC_CLEANUP(addtables, tc)
111 {
112 	COMMON_CLEANUP();
113 }
114 
115 ATF_TC_WITH_CLEANUP(deltables);
116 ATF_TC_HEAD(deltables, tc)
117 {
118 	atf_tc_set_md_var(tc, "require.user", "root");
119 }
120 
121 ATF_TC_BODY(deltables, tc)
122 {
123 	struct pfioc_table io;
124 	struct pfr_table tbl;
125 	int flags;
126 
127 	COMMON_HEAD();
128 
129 	flags = 0;
130 
131 	bzero(&io, sizeof(io));
132 	io.pfrio_flags = flags;
133 	io.pfrio_buffer = &tbl;
134 	io.pfrio_esize = sizeof(tbl);
135 
136 	/* Negative size */
137 	io.pfrio_size = -1;
138 	if (ioctl(dev, DIOCRDELTABLES, &io) == 0)
139 		atf_tc_fail("Request with size -1 succeeded");
140 
141 	/* Overly large size */
142 	io.pfrio_size = 1 << 24;
143 	if (ioctl(dev, DIOCRDELTABLES, &io) == 0)
144 		atf_tc_fail("Request with size 1 << 24 succeeded");
145 
146 	/* NULL buffer */
147 	io.pfrio_size = 1;
148 	io.pfrio_buffer = NULL;
149 	if (ioctl(dev, DIOCRDELTABLES, &io) == 0)
150 		atf_tc_fail("Request with NULL buffer succeeded");
151 }
152 
153 ATF_TC_CLEANUP(deltables, tc)
154 {
155 	COMMON_CLEANUP();
156 }
157 
158 ATF_TC_WITH_CLEANUP(gettables);
159 ATF_TC_HEAD(gettables, tc)
160 {
161 	atf_tc_set_md_var(tc, "require.user", "root");
162 }
163 
164 ATF_TC_BODY(gettables, tc)
165 {
166 	struct pfioc_table io;
167 	struct pfr_table tbl;
168 	int flags;
169 
170 	COMMON_HEAD();
171 
172 	flags = 0;
173 
174 	bzero(&io, sizeof(io));
175 	io.pfrio_flags = flags;
176 	io.pfrio_buffer = &tbl;
177 	io.pfrio_esize = sizeof(tbl);
178 
179 	/* Negative size. This will succeed, because the kernel will not copy
180 	 * tables than it has. */
181 	io.pfrio_size = -1;
182 	if (ioctl(dev, DIOCRGETTABLES, &io) != 0)
183 		atf_tc_fail("Request with size -1 failed");
184 
185 	/* Overly large size. See above. */
186 	io.pfrio_size = 1 << 24;
187 	if (ioctl(dev, DIOCRGETTABLES, &io) != 0)
188 		atf_tc_fail("Request with size 1 << 24 failed");
189 }
190 
191 ATF_TC_CLEANUP(gettables, tc)
192 {
193 	COMMON_CLEANUP();
194 }
195 
196 ATF_TC_WITH_CLEANUP(gettstats);
197 ATF_TC_HEAD(gettstats, tc)
198 {
199 	atf_tc_set_md_var(tc, "require.user", "root");
200 }
201 
202 ATF_TC_BODY(gettstats, tc)
203 {
204 	struct pfioc_table io;
205 	struct pfr_tstats stats;
206 	int flags;
207 
208 	COMMON_HEAD();
209 
210 	flags = 0;
211 
212 	bzero(&io, sizeof(io));
213 	io.pfrio_flags = flags;
214 	io.pfrio_buffer = &stats;
215 	io.pfrio_esize = sizeof(stats);
216 
217 	/* Negative size. This will succeed, because the kernel will not copy
218 	 * tables than it has. */
219 	io.pfrio_size = -1;
220 	if (ioctl(dev, DIOCRGETTSTATS, &io) != 0)
221 		atf_tc_fail("Request with size -1 failed");
222 
223 	/* Overly large size. See above. */
224 	io.pfrio_size = 1 << 24;
225 	if (ioctl(dev, DIOCRGETTSTATS, &io) != 0)
226 		atf_tc_fail("Request with size 1 << 24 failed");
227 }
228 
229 ATF_TC_CLEANUP(gettstats, tc)
230 {
231 	COMMON_CLEANUP();
232 }
233 
234 ATF_TC_WITH_CLEANUP(clrtstats);
235 ATF_TC_HEAD(clrtstats, tc)
236 {
237 	atf_tc_set_md_var(tc, "require.user", "root");
238 }
239 
240 ATF_TC_BODY(clrtstats, tc)
241 {
242 	struct pfioc_table io;
243 	struct pfr_table tbl;
244 	int flags;
245 
246 	COMMON_HEAD();
247 
248 	flags = 0;
249 
250 	common_init_tbl(&tbl);
251 
252 	bzero(&io, sizeof(io));
253 	io.pfrio_flags = flags;
254 	io.pfrio_buffer = &tbl;
255 	io.pfrio_esize = sizeof(tbl);
256 
257 	/* Negative size. This will succeed, because the kernel will not copy
258 	 * tables than it has. */
259 	io.pfrio_size = -1;
260 	if (ioctl(dev, DIOCRCLRTSTATS, &io) != 0)
261 		atf_tc_fail("Request with size -1 failed ");
262 
263 	/* Overly large size. See above. */
264 	io.pfrio_size = 1 << 24;
265 	if (ioctl(dev, DIOCRCLRTSTATS, &io) != 0)
266 		atf_tc_fail("Request with size 1 << 24 failed");
267 
268 	io.pfrio_size = sizeof(tbl);
269 	io.pfrio_buffer = NULL;
270 	if (ioctl(dev, DIOCRCLRTSTATS, &io) == 0)
271 		atf_tc_fail("Request with NULL buffer succeeded");
272 }
273 
274 ATF_TC_CLEANUP(clrtstats, tc)
275 {
276 	COMMON_CLEANUP();
277 }
278 
279 ATF_TC_WITH_CLEANUP(settflags);
280 ATF_TC_HEAD(settflags, tc)
281 {
282 	atf_tc_set_md_var(tc, "require.user", "root");
283 }
284 
285 ATF_TC_BODY(settflags, tc)
286 {
287 	struct pfioc_table io;
288 	struct pfr_table tbl;
289 	int flags;
290 
291 	COMMON_HEAD();
292 
293 	flags = 0;
294 
295 	common_init_tbl(&tbl);
296 
297 	bzero(&io, sizeof(io));
298 	io.pfrio_flags = flags;
299 	io.pfrio_buffer = &tbl;
300 	io.pfrio_esize = sizeof(tbl);
301 
302 	/* Negative size. This will succeed, because the kernel will not copy
303 	 * tables than it has. */
304 	io.pfrio_size = -1;
305 	if (ioctl(dev, DIOCRSETTFLAGS, &io) != 0)
306 		atf_tc_fail("Request with size -1 failed");
307 
308 	/* Overly large size. See above. */
309 	io.pfrio_size = 1 << 28;
310 	if (ioctl(dev, DIOCRSETTFLAGS, &io) != 0)
311 		atf_tc_fail("Request with size 1 << 24 failed");
312 
313 	/* NULL buffer */
314 	io.pfrio_buffer = NULL;
315 	if (ioctl(dev, DIOCRSETTFLAGS, &io) != -1)
316 		atf_tc_fail("Request with NULL buffer succeeded");
317 }
318 
319 ATF_TC_CLEANUP(settflags, tc)
320 {
321 	COMMON_CLEANUP();
322 }
323 
324 ATF_TC_WITH_CLEANUP(addaddrs);
325 ATF_TC_HEAD(addaddrs, tc)
326 {
327 	atf_tc_set_md_var(tc, "require.user", "root");
328 }
329 
330 ATF_TC_BODY(addaddrs, tc)
331 {
332 	struct pfioc_table io;
333 	struct pfr_addr addr;
334 
335 	COMMON_HEAD();
336 
337 	bzero(&addr, sizeof(addr));
338 	bzero(&io, sizeof(io));
339 	io.pfrio_flags = 0;
340 	io.pfrio_buffer = &addr;
341 	io.pfrio_esize = sizeof(addr);
342 
343 	/* Negative size. */
344 	io.pfrio_size = -1;
345 	if (ioctl(dev, DIOCRADDADDRS, &io) == 0)
346 		atf_tc_fail("Request with size -1 succeeded");
347 
348 	/* Overly large size. */
349 	io.pfrio_size = 1 << 28;
350 	if (ioctl(dev, DIOCRADDADDRS, &io) == 0)
351 		atf_tc_fail("Reuqest with size 1 << 28 failed");
352 }
353 
354 ATF_TC_CLEANUP(addaddrs, tc)
355 {
356 	COMMON_CLEANUP();
357 }
358 
359 ATF_TC_WITH_CLEANUP(deladdrs);
360 ATF_TC_HEAD(deladdrs, tc)
361 {
362 	atf_tc_set_md_var(tc, "require.user", "root");
363 }
364 
365 ATF_TC_BODY(deladdrs, tc)
366 {
367 	struct pfioc_table io;
368 	struct pfr_addr addr;
369 
370 	COMMON_HEAD();
371 
372 	bzero(&addr, sizeof(addr));
373 	bzero(&io, sizeof(io));
374 	io.pfrio_flags = 0;
375 	io.pfrio_buffer = &addr;
376 	io.pfrio_esize = sizeof(addr);
377 
378 	/* Negative size. */
379 	io.pfrio_size = -1;
380 	if (ioctl(dev, DIOCRDELADDRS, &io) == 0)
381 		atf_tc_fail("Request with size -1 succeeded");
382 
383 	/* Overly large size. */
384 	io.pfrio_size = 1 << 28;
385 	if (ioctl(dev, DIOCRDELADDRS, &io) == 0)
386 		atf_tc_fail("Reuqest with size 1 << 28 failed");
387 }
388 
389 ATF_TC_CLEANUP(deladdrs, tc)
390 {
391 	COMMON_CLEANUP();
392 }
393 
394 ATF_TC_WITH_CLEANUP(setaddrs);
395 ATF_TC_HEAD(setaddrs, tc)
396 {
397 	atf_tc_set_md_var(tc, "require.user", "root");
398 }
399 
400 ATF_TC_BODY(setaddrs, tc)
401 {
402 	struct pfioc_table io;
403 	struct pfr_addr addr;
404 
405 	COMMON_HEAD();
406 
407 	bzero(&addr, sizeof(addr));
408 	bzero(&io, sizeof(io));
409 	io.pfrio_flags = 0;
410 	io.pfrio_buffer = &addr;
411 	io.pfrio_esize = sizeof(addr);
412 
413 	/* Negative size. */
414 	io.pfrio_size = -1;
415 	if (ioctl(dev, DIOCRSETADDRS, &io) == 0)
416 		atf_tc_fail("Request with size -1 succeeded");
417 
418 	/* Overly large size. */
419 	io.pfrio_size = 1 << 28;
420 	if (ioctl(dev, DIOCRSETADDRS, &io) == 0)
421 		atf_tc_fail("Reuqest with size 1 << 28 failed");
422 }
423 
424 ATF_TC_CLEANUP(setaddrs, tc)
425 {
426 	COMMON_CLEANUP();
427 }
428 
429 ATF_TC_WITH_CLEANUP(getaddrs);
430 ATF_TC_HEAD(getaddrs, tc)
431 {
432 	atf_tc_set_md_var(tc, "require.user", "root");
433 }
434 
435 ATF_TC_BODY(getaddrs, tc)
436 {
437 	struct pfioc_table io;
438 	struct pfr_addr addr;
439 
440 	COMMON_HEAD();
441 
442 	bzero(&addr, sizeof(addr));
443 	bzero(&io, sizeof(io));
444 	io.pfrio_flags = 0;
445 	io.pfrio_buffer = &addr;
446 	io.pfrio_esize = sizeof(addr);
447 
448 	common_init_tbl(&io.pfrio_table);
449 
450 	/* Negative size. */
451 	io.pfrio_size = -1;
452 	if (ioctl(dev, DIOCRGETADDRS, &io) == 0)
453 		atf_tc_fail("Request with size -1 succeeded");
454 
455 	/* Overly large size. */
456 	io.pfrio_size = 1 << 24;
457 	if (ioctl(dev, DIOCRGETADDRS, &io) == 0)
458 		atf_tc_fail("Request with size 1 << 24 failed");
459 }
460 
461 ATF_TC_CLEANUP(getaddrs, tc)
462 {
463 	COMMON_CLEANUP();
464 }
465 
466 ATF_TC_WITH_CLEANUP(getastats);
467 ATF_TC_HEAD(getastats, tc)
468 {
469 	atf_tc_set_md_var(tc, "require.user", "root");
470 }
471 
472 ATF_TC_BODY(getastats, tc)
473 {
474 	struct pfioc_table io;
475 	struct pfr_astats astats;
476 
477 	COMMON_HEAD();
478 
479 	bzero(&astats, sizeof(astats));
480 	bzero(&io, sizeof(io));
481 	io.pfrio_flags = 0;
482 	io.pfrio_buffer = &astats;
483 	io.pfrio_esize = sizeof(astats);
484 
485 	common_init_tbl(&io.pfrio_table);
486 
487 	/* Negative size. */
488 	io.pfrio_size = -1;
489 	if (ioctl(dev, DIOCRGETASTATS, &io) == 0)
490 		atf_tc_fail("Request with size -1 succeeded");
491 
492 	/* Overly large size. */
493 	io.pfrio_size = 1 << 24;
494 	if (ioctl(dev, DIOCRGETASTATS, &io) == 0)
495 		atf_tc_fail("Request with size 1 << 24 failed");
496 }
497 
498 ATF_TC_CLEANUP(getastats, tc)
499 {
500 	COMMON_CLEANUP();
501 }
502 
503 ATF_TC_WITH_CLEANUP(clrastats);
504 ATF_TC_HEAD(clrastats, tc)
505 {
506 	atf_tc_set_md_var(tc, "require.user", "root");
507 }
508 
509 ATF_TC_BODY(clrastats, tc)
510 {
511 	struct pfioc_table io;
512 	struct pfr_addr addr;
513 
514 	COMMON_HEAD();
515 
516 	bzero(&addr, sizeof(addr));
517 	bzero(&io, sizeof(io));
518 	io.pfrio_flags = 0;
519 	io.pfrio_buffer = &addr;
520 	io.pfrio_esize = sizeof(addr);
521 
522 	common_init_tbl(&io.pfrio_table);
523 
524 	/* Negative size. */
525 	io.pfrio_size = -1;
526 	if (ioctl(dev, DIOCRCLRASTATS, &io) == 0)
527 		atf_tc_fail("Request with size -1 succeeded");
528 
529 	/* Overly large size. */
530 	io.pfrio_size = 1 << 24;
531 	if (ioctl(dev, DIOCRCLRASTATS, &io) == 0)
532 		atf_tc_fail("Request with size 1 << 24 failed");
533 }
534 
535 ATF_TC_CLEANUP(clrastats, tc)
536 {
537 	COMMON_CLEANUP();
538 }
539 
540 ATF_TC_WITH_CLEANUP(tstaddrs);
541 ATF_TC_HEAD(tstaddrs, tc)
542 {
543 	atf_tc_set_md_var(tc, "require.user", "root");
544 }
545 
546 ATF_TC_BODY(tstaddrs, tc)
547 {
548 	struct pfioc_table io;
549 	struct pfr_addr addr;
550 
551 	COMMON_HEAD();
552 
553 	bzero(&addr, sizeof(addr));
554 	bzero(&io, sizeof(io));
555 	io.pfrio_flags = 0;
556 	io.pfrio_buffer = &addr;
557 	io.pfrio_esize = sizeof(addr);
558 
559 	common_init_tbl(&io.pfrio_table);
560 
561 	/* Negative size. */
562 	io.pfrio_size = -1;
563 	if (ioctl(dev, DIOCRTSTADDRS, &io) == 0)
564 		atf_tc_fail("Request with size -1 succeeded");
565 
566 	/* Overly large size. */
567 	io.pfrio_size = 1 << 24;
568 	if (ioctl(dev, DIOCRTSTADDRS, &io) == 0)
569 		atf_tc_fail("Request with size 1 << 24 failed");
570 }
571 
572 ATF_TC_CLEANUP(tstaddrs, tc)
573 {
574 	COMMON_CLEANUP();
575 }
576 
577 ATF_TC_WITH_CLEANUP(inadefine);
578 ATF_TC_HEAD(inadefine, tc)
579 {
580 	atf_tc_set_md_var(tc, "require.user", "root");
581 }
582 
583 ATF_TC_BODY(inadefine, tc)
584 {
585 	struct pfioc_table io;
586 	struct pfr_addr addr;
587 
588 	COMMON_HEAD();
589 
590 	bzero(&addr, sizeof(addr));
591 	bzero(&io, sizeof(io));
592 	io.pfrio_flags = 0;
593 	io.pfrio_buffer = &addr;
594 	io.pfrio_esize = sizeof(addr);
595 
596 	common_init_tbl(&io.pfrio_table);
597 
598 	/* Negative size. */
599 	io.pfrio_size = -1;
600 	if (ioctl(dev, DIOCRINADEFINE, &io) == 0)
601 		atf_tc_fail("Request with size -1 succeeded");
602 
603 	/* Overly large size. */
604 	io.pfrio_size = 1 << 24;
605 	if (ioctl(dev, DIOCRINADEFINE, &io) == 0)
606 		atf_tc_fail("Request with size 1 << 24 failed");
607 }
608 
609 ATF_TC_CLEANUP(inadefine, tc)
610 {
611 	COMMON_CLEANUP();
612 }
613 
614 ATF_TC_WITH_CLEANUP(igetifaces);
615 ATF_TC_HEAD(igetifaces, tc)
616 {
617 	atf_tc_set_md_var(tc, "require.user", "root");
618 }
619 
620 ATF_TC_BODY(igetifaces, tc)
621 {
622 	struct pfioc_iface io;
623 	struct pfi_kif kif;
624 
625 	COMMON_HEAD();
626 
627 	bzero(&io, sizeof(io));
628 	io.pfiio_flags = 0;
629 	io.pfiio_buffer = &kif;
630 	io.pfiio_esize = sizeof(kif);
631 
632 	/* Negative size */
633 	io.pfiio_size = -1;
634 	if (ioctl(dev, DIOCIGETIFACES, &io) == 0)
635 		atf_tc_fail("request with size -1 succeeded");
636 
637 	/* Overflow size */
638 	io.pfiio_size = 1 << 31;
639 	if (ioctl(dev, DIOCIGETIFACES, &io) == 0)
640 		atf_tc_fail("request with size 1 << 31 succeeded");
641 }
642 
643 ATF_TC_CLEANUP(igetifaces, tc)
644 {
645 	COMMON_CLEANUP();
646 }
647 
648 ATF_TC_WITH_CLEANUP(cxbegin);
649 ATF_TC_HEAD(cxbegin, tc)
650 {
651 	atf_tc_set_md_var(tc, "require.user", "root");
652 }
653 
654 ATF_TC_BODY(cxbegin, tc)
655 {
656 	struct pfioc_trans io;
657 	struct pfioc_trans_e ioe;
658 
659 	COMMON_HEAD();
660 
661 	bzero(&io, sizeof(io));
662 	io.esize = sizeof(ioe);
663 	io.array = &ioe;
664 
665 	/* Negative size */
666 	io.size = -1;
667 	if (ioctl(dev, DIOCXBEGIN, &io) == 0)
668 		atf_tc_fail("request with size -1 succeeded");
669 
670 	/* Overflow size */
671 	io.size = 1 << 30;
672 	if (ioctl(dev, DIOCXBEGIN, &io) == 0)
673 		atf_tc_fail("request with size 1 << 30 succeeded");
674 
675 	/* NULL buffer */
676 	io.size = 1;
677 	io.array = NULL;
678 	if (ioctl(dev, DIOCXBEGIN, &io) == 0)
679 		atf_tc_fail("request with size -1 succeeded");
680 }
681 
682 ATF_TC_CLEANUP(cxbegin, tc)
683 {
684 	COMMON_CLEANUP();
685 }
686 
687 ATF_TC_WITH_CLEANUP(cxrollback);
688 ATF_TC_HEAD(cxrollback, tc)
689 {
690 	atf_tc_set_md_var(tc, "require.user", "root");
691 }
692 
693 ATF_TC_BODY(cxrollback, tc)
694 {
695 	struct pfioc_trans io;
696 	struct pfioc_trans_e ioe;
697 
698 	COMMON_HEAD();
699 
700 	bzero(&io, sizeof(io));
701 	io.esize = sizeof(ioe);
702 	io.array = &ioe;
703 
704 	/* Negative size */
705 	io.size = -1;
706 	if (ioctl(dev, DIOCXROLLBACK, &io) == 0)
707 		atf_tc_fail("request with size -1 succeeded");
708 
709 	/* Overflow size */
710 	io.size = 1 << 30;
711 	if (ioctl(dev, DIOCXROLLBACK, &io) == 0)
712 		atf_tc_fail("request with size 1 << 30 succeeded");
713 
714 	/* NULL buffer */
715 	io.size = 1;
716 	io.array = NULL;
717 	if (ioctl(dev, DIOCXROLLBACK, &io) == 0)
718 		atf_tc_fail("request with size -1 succeeded");
719 }
720 
721 ATF_TC_CLEANUP(cxrollback, tc)
722 {
723 	COMMON_CLEANUP();
724 }
725 
726 ATF_TC_WITH_CLEANUP(commit);
727 ATF_TC_HEAD(commit, tc)
728 {
729 	atf_tc_set_md_var(tc, "require.user", "root");
730 }
731 
732 ATF_TC_BODY(commit, tc)
733 {
734 	struct pfioc_trans io;
735 	struct pfioc_trans_e ioe;
736 
737 	COMMON_HEAD();
738 
739 	bzero(&io, sizeof(io));
740 	io.esize = sizeof(ioe);
741 	io.array = &ioe;
742 
743 	/* Negative size */
744 	io.size = -1;
745 	if (ioctl(dev, DIOCXCOMMIT, &io) == 0)
746 		atf_tc_fail("request with size -1 succeeded");
747 
748 	/* Overflow size */
749 	io.size = 1 << 30;
750 	if (ioctl(dev, DIOCXCOMMIT, &io) == 0)
751 		atf_tc_fail("request with size 1 << 30 succeeded");
752 
753 	/* NULL buffer */
754 	io.size = 1;
755 	io.array = NULL;
756 	if (ioctl(dev, DIOCXCOMMIT, &io) == 0)
757 		atf_tc_fail("request with size -1 succeeded");
758 }
759 
760 ATF_TC_CLEANUP(commit, tc)
761 {
762 	COMMON_CLEANUP();
763 }
764 
765 ATF_TC_WITH_CLEANUP(getsrcnodes);
766 ATF_TC_HEAD(getsrcnodes, tc)
767 {
768 	atf_tc_set_md_var(tc, "require.user", "root");
769 }
770 
771 ATF_TC_BODY(getsrcnodes, tc)
772 {
773 	struct pfioc_src_nodes psn;
774 
775 	COMMON_HEAD();
776 
777 	bzero(&psn, sizeof(psn));
778 
779 	psn.psn_len = -1;
780 	if (ioctl(dev, DIOCGETSRCNODES, &psn) != 0)
781 		atf_tc_fail("request with size -1 failed");
782 
783 	psn.psn_len = 1 << 30;
784 	if (ioctl(dev, DIOCGETSRCNODES, &psn) != 0)
785 		atf_tc_fail("request with size << 30 failed");
786 
787 	psn.psn_len = 1 << 31;
788 	if (ioctl(dev, DIOCGETSRCNODES, &psn) != 0)
789 		atf_tc_fail("request with size << 30 failed");
790 }
791 
792 ATF_TC_CLEANUP(getsrcnodes, tc)
793 {
794 	COMMON_CLEANUP();
795 }
796 
797 ATF_TC_WITH_CLEANUP(tag);
798 ATF_TC_HEAD(tag, tc)
799 {
800 	atf_tc_set_md_var(tc, "require.user", "root");
801 }
802 
803 ATF_TC_BODY(tag, tc)
804 {
805 	struct pfioc_rule rule;
806 
807 	COMMON_HEAD();
808 
809 	memset(&rule, 0x42, sizeof(rule));
810 
811 	rule.ticket = 0;
812 	rule.pool_ticket = 0;
813 	rule.anchor[0] = 0;
814 
815 	rule.rule.return_icmp = 0;
816 	bzero(&rule.rule.src, sizeof(rule.rule.src));
817 	bzero(&rule.rule.dst, sizeof(rule.rule.dst));
818 
819 	rule.rule.ifname[0] = 0;
820 	rule.rule.action = 0;
821 	rule.rule.rtableid = 0;
822 
823 	rule.rule.tagname[0] = 0;
824 
825 	for (int i = 0; i < 10; i++)
826 		ioctl(dev, DIOCADDRULE, &rule);
827 }
828 
829 ATF_TC_CLEANUP(tag, tc)
830 {
831 	COMMON_CLEANUP();
832 }
833 
834 ATF_TC_WITH_CLEANUP(rpool_mtx);
835 ATF_TC_HEAD(rpool_mtx, tc)
836 {
837 	atf_tc_set_md_var(tc, "require.user", "root");
838 }
839 
840 ATF_TC_BODY(rpool_mtx, tc)
841 {
842 	struct pfioc_rule rule;
843 
844 	COMMON_HEAD();
845 
846 	memset(&rule, 0, sizeof(rule));
847 
848 	rule.ticket = 0;
849 	rule.pool_ticket = 0;
850 	rule.anchor[0] = 0;
851 
852 	rule.rule.return_icmp = 0;
853 	bzero(&rule.rule.src, sizeof(rule.rule.src));
854 	bzero(&rule.rule.dst, sizeof(rule.rule.dst));
855 
856 	rule.rule.ifname[0] = 0;
857 	rule.rule.action = 0;
858 	rule.rule.rtableid = 0;
859 
860 	rule.rule.tagname[0] = 0;
861 	rule.rule.action = 42;
862 
863 	ioctl(dev, DIOCADDRULE, &rule);
864 }
865 
866 ATF_TC_CLEANUP(rpool_mtx, tc)
867 {
868 	COMMON_CLEANUP();
869 }
870 
871 ATF_TC_WITH_CLEANUP(rpool_mtx2);
872 ATF_TC_HEAD(rpool_mtx2, tc)
873 {
874 	atf_tc_set_md_var(tc, "require.user", "root");
875 }
876 
877 ATF_TC_BODY(rpool_mtx2, tc)
878 {
879 	struct pfioc_rule rule;
880 
881 	COMMON_HEAD();
882 
883 	memset(&rule, 0, sizeof(rule));
884 
885 	rule.pool_ticket = 1000000;
886 	rule.action = PF_CHANGE_ADD_HEAD;
887 	rule.rule.af = AF_INET;
888 
889 	ioctl(dev, DIOCCHANGERULE, &rule);
890 }
891 
892 ATF_TC_CLEANUP(rpool_mtx2, tc)
893 {
894 	COMMON_CLEANUP();
895 }
896 
897 ATF_TC_WITH_CLEANUP(natlook);
898 ATF_TC_HEAD(natlook, tc)
899 {
900 	atf_tc_set_md_var(tc, "require.user", "root");
901 }
902 
903 ATF_TC_BODY(natlook, tc)
904 {
905 	struct pfioc_natlook nl = { 0 };
906 
907 	COMMON_HEAD();
908 
909 	nl.af = AF_INET;
910 	nl.proto = IPPROTO_ICMP;
911 	nl.saddr.v4.s_addr = 0x01020304;
912 	nl.daddr.v4.s_addr = 0x05060708;
913 
914 	/* Invalid direction */
915 	nl.direction = 42;
916 
917 	ATF_CHECK_ERRNO(EINVAL, ioctl(dev, DIOCNATLOOK, &nl) == -1);
918 
919 	/* Invalid af */
920 	nl.direction = PF_IN;
921 	nl.af = 99;
922 
923 	ATF_CHECK_ERRNO(EAFNOSUPPORT, ioctl(dev, DIOCNATLOOK, &nl) == -1);
924 }
925 
926 ATF_TC_CLEANUP(natlook, tc)
927 {
928 	COMMON_CLEANUP();
929 }
930 
931 ATF_TP_ADD_TCS(tp)
932 {
933 	ATF_TP_ADD_TC(tp, addtables);
934 	ATF_TP_ADD_TC(tp, deltables);
935 	ATF_TP_ADD_TC(tp, gettables);
936 	ATF_TP_ADD_TC(tp, getastats);
937 	ATF_TP_ADD_TC(tp, gettstats);
938 	ATF_TP_ADD_TC(tp, clrtstats);
939 	ATF_TP_ADD_TC(tp, settflags);
940 	ATF_TP_ADD_TC(tp, addaddrs);
941 	ATF_TP_ADD_TC(tp, deladdrs);
942 	ATF_TP_ADD_TC(tp, setaddrs);
943 	ATF_TP_ADD_TC(tp, getaddrs);
944 	ATF_TP_ADD_TC(tp, clrastats);
945 	ATF_TP_ADD_TC(tp, tstaddrs);
946 	ATF_TP_ADD_TC(tp, inadefine);
947 	ATF_TP_ADD_TC(tp, igetifaces);
948 	ATF_TP_ADD_TC(tp, cxbegin);
949 	ATF_TP_ADD_TC(tp, cxrollback);
950 	ATF_TP_ADD_TC(tp, commit);
951 	ATF_TP_ADD_TC(tp, getsrcnodes);
952 	ATF_TP_ADD_TC(tp, tag);
953 	ATF_TP_ADD_TC(tp, rpool_mtx);
954 	ATF_TP_ADD_TC(tp, rpool_mtx2);
955 	ATF_TP_ADD_TC(tp, natlook);
956 
957 	return (atf_no_error());
958 }
959