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