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
42static 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
54static void
55common_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
64ATF_TC_WITH_CLEANUP(addtables);
65ATF_TC_HEAD(addtables, tc)
66{
67	atf_tc_set_md_var(tc, "require.user", "root");
68}
69
70ATF_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
111ATF_TC_CLEANUP(addtables, tc)
112{
113	COMMON_CLEANUP();
114}
115
116ATF_TC_WITH_CLEANUP(deltables);
117ATF_TC_HEAD(deltables, tc)
118{
119	atf_tc_set_md_var(tc, "require.user", "root");
120}
121
122ATF_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
154ATF_TC_CLEANUP(deltables, tc)
155{
156	COMMON_CLEANUP();
157}
158
159ATF_TC_WITH_CLEANUP(gettables);
160ATF_TC_HEAD(gettables, tc)
161{
162	atf_tc_set_md_var(tc, "require.user", "root");
163}
164
165ATF_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
192ATF_TC_CLEANUP(gettables, tc)
193{
194	COMMON_CLEANUP();
195}
196
197ATF_TC_WITH_CLEANUP(gettstats);
198ATF_TC_HEAD(gettstats, tc)
199{
200	atf_tc_set_md_var(tc, "require.user", "root");
201}
202
203ATF_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
230ATF_TC_CLEANUP(gettstats, tc)
231{
232	COMMON_CLEANUP();
233}
234
235ATF_TC_WITH_CLEANUP(clrtstats);
236ATF_TC_HEAD(clrtstats, tc)
237{
238	atf_tc_set_md_var(tc, "require.user", "root");
239}
240
241ATF_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
275ATF_TC_CLEANUP(clrtstats, tc)
276{
277	COMMON_CLEANUP();
278}
279
280ATF_TC_WITH_CLEANUP(settflags);
281ATF_TC_HEAD(settflags, tc)
282{
283	atf_tc_set_md_var(tc, "require.user", "root");
284}
285
286ATF_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
320ATF_TC_CLEANUP(settflags, tc)
321{
322	COMMON_CLEANUP();
323}
324
325ATF_TC_WITH_CLEANUP(addaddrs);
326ATF_TC_HEAD(addaddrs, tc)
327{
328	atf_tc_set_md_var(tc, "require.user", "root");
329}
330
331ATF_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
355ATF_TC_CLEANUP(addaddrs, tc)
356{
357	COMMON_CLEANUP();
358}
359
360ATF_TC_WITH_CLEANUP(deladdrs);
361ATF_TC_HEAD(deladdrs, tc)
362{
363	atf_tc_set_md_var(tc, "require.user", "root");
364}
365
366ATF_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
390ATF_TC_CLEANUP(deladdrs, tc)
391{
392	COMMON_CLEANUP();
393}
394
395ATF_TC_WITH_CLEANUP(setaddrs);
396ATF_TC_HEAD(setaddrs, tc)
397{
398	atf_tc_set_md_var(tc, "require.user", "root");
399}
400
401ATF_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
425ATF_TC_CLEANUP(setaddrs, tc)
426{
427	COMMON_CLEANUP();
428}
429
430ATF_TC_WITH_CLEANUP(getaddrs);
431ATF_TC_HEAD(getaddrs, tc)
432{
433	atf_tc_set_md_var(tc, "require.user", "root");
434}
435
436ATF_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
462ATF_TC_CLEANUP(getaddrs, tc)
463{
464	COMMON_CLEANUP();
465}
466
467ATF_TC_WITH_CLEANUP(getastats);
468ATF_TC_HEAD(getastats, tc)
469{
470	atf_tc_set_md_var(tc, "require.user", "root");
471}
472
473ATF_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
499ATF_TC_CLEANUP(getastats, tc)
500{
501	COMMON_CLEANUP();
502}
503
504ATF_TC_WITH_CLEANUP(clrastats);
505ATF_TC_HEAD(clrastats, tc)
506{
507	atf_tc_set_md_var(tc, "require.user", "root");
508}
509
510ATF_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
536ATF_TC_CLEANUP(clrastats, tc)
537{
538	COMMON_CLEANUP();
539}
540
541ATF_TC_WITH_CLEANUP(tstaddrs);
542ATF_TC_HEAD(tstaddrs, tc)
543{
544	atf_tc_set_md_var(tc, "require.user", "root");
545}
546
547ATF_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
573ATF_TC_CLEANUP(tstaddrs, tc)
574{
575	COMMON_CLEANUP();
576}
577
578ATF_TC_WITH_CLEANUP(inadefine);
579ATF_TC_HEAD(inadefine, tc)
580{
581	atf_tc_set_md_var(tc, "require.user", "root");
582}
583
584ATF_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
610ATF_TC_CLEANUP(inadefine, tc)
611{
612	COMMON_CLEANUP();
613}
614
615ATF_TC_WITH_CLEANUP(igetifaces);
616ATF_TC_HEAD(igetifaces, tc)
617{
618	atf_tc_set_md_var(tc, "require.user", "root");
619}
620
621ATF_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
644ATF_TC_CLEANUP(igetifaces, tc)
645{
646	COMMON_CLEANUP();
647}
648
649ATF_TC_WITH_CLEANUP(cxbegin);
650ATF_TC_HEAD(cxbegin, tc)
651{
652	atf_tc_set_md_var(tc, "require.user", "root");
653}
654
655ATF_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
683ATF_TC_CLEANUP(cxbegin, tc)
684{
685	COMMON_CLEANUP();
686}
687
688ATF_TC_WITH_CLEANUP(cxrollback);
689ATF_TC_HEAD(cxrollback, tc)
690{
691	atf_tc_set_md_var(tc, "require.user", "root");
692}
693
694ATF_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
722ATF_TC_CLEANUP(cxrollback, tc)
723{
724	COMMON_CLEANUP();
725}
726
727ATF_TC_WITH_CLEANUP(commit);
728ATF_TC_HEAD(commit, tc)
729{
730	atf_tc_set_md_var(tc, "require.user", "root");
731}
732
733ATF_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
761ATF_TC_CLEANUP(commit, tc)
762{
763	COMMON_CLEANUP();
764}
765
766ATF_TC_WITH_CLEANUP(getsrcnodes);
767ATF_TC_HEAD(getsrcnodes, tc)
768{
769	atf_tc_set_md_var(tc, "require.user", "root");
770}
771
772ATF_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
793ATF_TC_CLEANUP(getsrcnodes, tc)
794{
795	COMMON_CLEANUP();
796}
797
798ATF_TC_WITH_CLEANUP(tag);
799ATF_TC_HEAD(tag, tc)
800{
801	atf_tc_set_md_var(tc, "require.user", "root");
802}
803
804ATF_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
830ATF_TC_CLEANUP(tag, tc)
831{
832	COMMON_CLEANUP();
833}
834
835ATF_TP_ADD_TCS(tp)
836{
837	ATF_TP_ADD_TC(tp, addtables);
838	ATF_TP_ADD_TC(tp, deltables);
839	ATF_TP_ADD_TC(tp, gettables);
840	ATF_TP_ADD_TC(tp, getastats);
841	ATF_TP_ADD_TC(tp, gettstats);
842	ATF_TP_ADD_TC(tp, clrtstats);
843	ATF_TP_ADD_TC(tp, settflags);
844	ATF_TP_ADD_TC(tp, addaddrs);
845	ATF_TP_ADD_TC(tp, deladdrs);
846	ATF_TP_ADD_TC(tp, setaddrs);
847	ATF_TP_ADD_TC(tp, getaddrs);
848	ATF_TP_ADD_TC(tp, clrastats);
849	ATF_TP_ADD_TC(tp, tstaddrs);
850	ATF_TP_ADD_TC(tp, inadefine);
851	ATF_TP_ADD_TC(tp, igetifaces);
852	ATF_TP_ADD_TC(tp, cxbegin);
853	ATF_TP_ADD_TC(tp, cxrollback);
854	ATF_TP_ADD_TC(tp, commit);
855	ATF_TP_ADD_TC(tp, getsrcnodes);
856	ATF_TP_ADD_TC(tp, tag);
857
858	return (atf_no_error());
859}
860