198c5f988SKristof Provost /*- 298c5f988SKristof Provost * Copyright (c) 2018 Kristof Provost <kp@FreeBSD.org> 398c5f988SKristof Provost * 498c5f988SKristof Provost * Redistribution and use in source and binary forms, with or without 598c5f988SKristof Provost * modification, are permitted provided that the following conditions 698c5f988SKristof Provost * are met: 798c5f988SKristof Provost * 1. Redistributions of source code must retain the above copyright 898c5f988SKristof Provost * notice, this list of conditions and the following disclaimer. 998c5f988SKristof Provost * 2. Redistributions in binary form must reproduce the above copyright 1098c5f988SKristof Provost * notice, this list of conditions and the following disclaimer in the 1198c5f988SKristof Provost * documentation and/or other materials provided with the distribution. 1298c5f988SKristof Provost * 1398c5f988SKristof Provost * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1498c5f988SKristof Provost * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1598c5f988SKristof Provost * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1698c5f988SKristof Provost * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1798c5f988SKristof Provost * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1898c5f988SKristof Provost * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1998c5f988SKristof Provost * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2098c5f988SKristof Provost * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2198c5f988SKristof Provost * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2298c5f988SKristof Provost * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2398c5f988SKristof Provost * SUCH DAMAGE. 2498c5f988SKristof Provost * 2598c5f988SKristof Provost * $FreeBSD$ 2698c5f988SKristof Provost */ 2798c5f988SKristof Provost 2898c5f988SKristof Provost #include <sys/param.h> 2998c5f988SKristof Provost #include <sys/module.h> 3098c5f988SKristof Provost #include <sys/types.h> 3198c5f988SKristof Provost #include <sys/ioctl.h> 3298c5f988SKristof Provost #include <sys/socket.h> 3398c5f988SKristof Provost 3498c5f988SKristof Provost #include <net/if.h> 3598c5f988SKristof Provost #include <net/pfvar.h> 3698c5f988SKristof Provost 3798c5f988SKristof Provost #include <fcntl.h> 3898c5f988SKristof Provost #include <stdio.h> 3998c5f988SKristof Provost 4098c5f988SKristof Provost #include <atf-c.h> 4198c5f988SKristof Provost 4298c5f988SKristof Provost static int dev; 4398c5f988SKristof Provost 4498c5f988SKristof Provost #define COMMON_HEAD() \ 4598c5f988SKristof Provost if (modfind("pf") == -1) \ 4698c5f988SKristof Provost atf_tc_skip("pf not loaded"); \ 4798c5f988SKristof Provost dev = open("/dev/pf", O_RDWR); \ 4898c5f988SKristof Provost if (dev == -1) \ 4998c5f988SKristof Provost atf_tc_skip("Failed to open /dev/pf"); 5098c5f988SKristof Provost 5198c5f988SKristof Provost #define COMMON_CLEANUP() \ 5298c5f988SKristof Provost close(dev); 5398c5f988SKristof Provost 54*1ff545d6SKristof Provost void 55*1ff545d6SKristof Provost common_init_tbl(struct pfr_table *tbl) 56*1ff545d6SKristof Provost { 57*1ff545d6SKristof Provost bzero(tbl, sizeof(struct pfr_table)); 58*1ff545d6SKristof Provost strcpy(tbl->pfrt_anchor, "anchor"); 59*1ff545d6SKristof Provost strcpy(tbl->pfrt_name, "name"); 60*1ff545d6SKristof Provost tbl->pfrt_flags = 0; 61*1ff545d6SKristof Provost tbl->pfrt_fback = 0; 62*1ff545d6SKristof Provost } 63*1ff545d6SKristof Provost 6498c5f988SKristof Provost ATF_TC_WITHOUT_HEAD(addtables); 6598c5f988SKristof Provost ATF_TC_BODY(addtables, tc) 6698c5f988SKristof Provost { 6798c5f988SKristof Provost struct pfioc_table io; 6898c5f988SKristof Provost struct pfr_table tbl; 6998c5f988SKristof Provost int flags; 7098c5f988SKristof Provost 7198c5f988SKristof Provost COMMON_HEAD(); 7298c5f988SKristof Provost 7398c5f988SKristof Provost flags = 0; 7498c5f988SKristof Provost 7598c5f988SKristof Provost bzero(&io, sizeof(io)); 7698c5f988SKristof Provost io.pfrio_flags = flags; 7798c5f988SKristof Provost io.pfrio_buffer = &tbl; 7898c5f988SKristof Provost io.pfrio_esize = sizeof(tbl); 7998c5f988SKristof Provost 8098c5f988SKristof Provost /* Negative size */ 8198c5f988SKristof Provost io.pfrio_size = -1; 8298c5f988SKristof Provost if (ioctl(dev, DIOCRADDTABLES, &io) == 0) 8398c5f988SKristof Provost atf_tc_fail("Request with size -1 succeeded"); 8498c5f988SKristof Provost 8598c5f988SKristof Provost /* Overly large size */ 8698c5f988SKristof Provost io.pfrio_size = 1 << 24; 8798c5f988SKristof Provost if (ioctl(dev, DIOCRADDTABLES, &io) == 0) 8898c5f988SKristof Provost atf_tc_fail("Request with size 1 << 24 succeeded"); 8998c5f988SKristof Provost 9098c5f988SKristof Provost /* NULL buffer */ 9198c5f988SKristof Provost io.pfrio_size = 1; 9298c5f988SKristof Provost io.pfrio_buffer = NULL; 9398c5f988SKristof Provost if (ioctl(dev, DIOCRADDTABLES, &io) == 0) 9498c5f988SKristof Provost atf_tc_fail("Request with NULL buffer succeeded"); 9598c5f988SKristof Provost 9698c5f988SKristof Provost COMMON_CLEANUP(); 9798c5f988SKristof Provost } 9898c5f988SKristof Provost 9998c5f988SKristof Provost ATF_TC_WITHOUT_HEAD(deltables); 10098c5f988SKristof Provost ATF_TC_BODY(deltables, tc) 10198c5f988SKristof Provost { 10298c5f988SKristof Provost struct pfioc_table io; 10398c5f988SKristof Provost struct pfr_table tbl; 10498c5f988SKristof Provost int flags; 10598c5f988SKristof Provost 10698c5f988SKristof Provost COMMON_HEAD(); 10798c5f988SKristof Provost 10898c5f988SKristof Provost flags = 0; 10998c5f988SKristof Provost 11098c5f988SKristof Provost bzero(&io, sizeof(io)); 11198c5f988SKristof Provost io.pfrio_flags = flags; 11298c5f988SKristof Provost io.pfrio_buffer = &tbl; 11398c5f988SKristof Provost io.pfrio_esize = sizeof(tbl); 11498c5f988SKristof Provost 11598c5f988SKristof Provost /* Negative size */ 11698c5f988SKristof Provost io.pfrio_size = -1; 11798c5f988SKristof Provost if (ioctl(dev, DIOCRDELTABLES, &io) == 0) 11898c5f988SKristof Provost atf_tc_fail("Request with size -1 succeeded"); 11998c5f988SKristof Provost 12098c5f988SKristof Provost /* Overly large size */ 12198c5f988SKristof Provost io.pfrio_size = 1 << 24; 12298c5f988SKristof Provost if (ioctl(dev, DIOCRDELTABLES, &io) == 0) 12398c5f988SKristof Provost atf_tc_fail("Request with size 1 << 24 succeeded"); 12498c5f988SKristof Provost 12598c5f988SKristof Provost /* NULL buffer */ 12698c5f988SKristof Provost io.pfrio_size = 1; 12798c5f988SKristof Provost io.pfrio_buffer = NULL; 12898c5f988SKristof Provost if (ioctl(dev, DIOCRDELTABLES, &io) == 0) 12998c5f988SKristof Provost atf_tc_fail("Request with NULL buffer succeeded"); 13098c5f988SKristof Provost 13198c5f988SKristof Provost COMMON_CLEANUP(); 13298c5f988SKristof Provost } 13398c5f988SKristof Provost 134*1ff545d6SKristof Provost ATF_TC_WITHOUT_HEAD(gettables); 135*1ff545d6SKristof Provost ATF_TC_BODY(gettables, tc) 136*1ff545d6SKristof Provost { 137*1ff545d6SKristof Provost struct pfioc_table io; 138*1ff545d6SKristof Provost struct pfr_table tbl; 139*1ff545d6SKristof Provost int flags; 140*1ff545d6SKristof Provost 141*1ff545d6SKristof Provost COMMON_HEAD(); 142*1ff545d6SKristof Provost 143*1ff545d6SKristof Provost flags = 0; 144*1ff545d6SKristof Provost 145*1ff545d6SKristof Provost bzero(&io, sizeof(io)); 146*1ff545d6SKristof Provost io.pfrio_flags = flags; 147*1ff545d6SKristof Provost io.pfrio_buffer = &tbl; 148*1ff545d6SKristof Provost io.pfrio_esize = sizeof(tbl); 149*1ff545d6SKristof Provost 150*1ff545d6SKristof Provost /* Negative size. This will succeed, because the kernel will not copy 151*1ff545d6SKristof Provost * tables than it has. */ 152*1ff545d6SKristof Provost io.pfrio_size = -1; 153*1ff545d6SKristof Provost if (ioctl(dev, DIOCRGETTABLES, &io) != 0) 154*1ff545d6SKristof Provost atf_tc_fail("Request with size -1 failed"); 155*1ff545d6SKristof Provost 156*1ff545d6SKristof Provost /* Overly large size. See above. */ 157*1ff545d6SKristof Provost io.pfrio_size = 1 << 24; 158*1ff545d6SKristof Provost if (ioctl(dev, DIOCRGETTABLES, &io) != 0) 159*1ff545d6SKristof Provost atf_tc_fail("Request with size 1 << 24 failed"); 160*1ff545d6SKristof Provost 161*1ff545d6SKristof Provost COMMON_CLEANUP(); 162*1ff545d6SKristof Provost } 163*1ff545d6SKristof Provost 164*1ff545d6SKristof Provost ATF_TC_WITHOUT_HEAD(gettstats); 165*1ff545d6SKristof Provost ATF_TC_BODY(gettstats, tc) 166*1ff545d6SKristof Provost { 167*1ff545d6SKristof Provost struct pfioc_table io; 168*1ff545d6SKristof Provost struct pfr_tstats stats; 169*1ff545d6SKristof Provost int flags; 170*1ff545d6SKristof Provost 171*1ff545d6SKristof Provost COMMON_HEAD(); 172*1ff545d6SKristof Provost 173*1ff545d6SKristof Provost flags = 0; 174*1ff545d6SKristof Provost 175*1ff545d6SKristof Provost bzero(&io, sizeof(io)); 176*1ff545d6SKristof Provost io.pfrio_flags = flags; 177*1ff545d6SKristof Provost io.pfrio_buffer = &stats; 178*1ff545d6SKristof Provost io.pfrio_esize = sizeof(stats); 179*1ff545d6SKristof Provost 180*1ff545d6SKristof Provost /* Negative size. This will succeed, because the kernel will not copy 181*1ff545d6SKristof Provost * tables than it has. */ 182*1ff545d6SKristof Provost io.pfrio_size = -1; 183*1ff545d6SKristof Provost if (ioctl(dev, DIOCRGETTSTATS, &io) != 0) 184*1ff545d6SKristof Provost atf_tc_fail("Request with size -1 failed"); 185*1ff545d6SKristof Provost 186*1ff545d6SKristof Provost /* Overly large size. See above. */ 187*1ff545d6SKristof Provost io.pfrio_size = 1 << 24; 188*1ff545d6SKristof Provost if (ioctl(dev, DIOCRGETTSTATS, &io) != 0) 189*1ff545d6SKristof Provost atf_tc_fail("Request with size 1 << 24 failed"); 190*1ff545d6SKristof Provost 191*1ff545d6SKristof Provost COMMON_CLEANUP(); 192*1ff545d6SKristof Provost } 193*1ff545d6SKristof Provost 194*1ff545d6SKristof Provost ATF_TC_WITHOUT_HEAD(clrtstats); 195*1ff545d6SKristof Provost ATF_TC_BODY(clrtstats, tc) 196*1ff545d6SKristof Provost { 197*1ff545d6SKristof Provost struct pfioc_table io; 198*1ff545d6SKristof Provost struct pfr_table tbl; 199*1ff545d6SKristof Provost int flags; 200*1ff545d6SKristof Provost 201*1ff545d6SKristof Provost COMMON_HEAD(); 202*1ff545d6SKristof Provost 203*1ff545d6SKristof Provost flags = 0; 204*1ff545d6SKristof Provost 205*1ff545d6SKristof Provost common_init_tbl(&tbl); 206*1ff545d6SKristof Provost 207*1ff545d6SKristof Provost bzero(&io, sizeof(io)); 208*1ff545d6SKristof Provost io.pfrio_flags = flags; 209*1ff545d6SKristof Provost io.pfrio_buffer = &tbl; 210*1ff545d6SKristof Provost io.pfrio_esize = sizeof(tbl); 211*1ff545d6SKristof Provost 212*1ff545d6SKristof Provost /* Negative size. This will succeed, because the kernel will not copy 213*1ff545d6SKristof Provost * tables than it has. */ 214*1ff545d6SKristof Provost io.pfrio_size = -1; 215*1ff545d6SKristof Provost if (ioctl(dev, DIOCRCLRTSTATS, &io) != 0) 216*1ff545d6SKristof Provost atf_tc_fail("Request with size -1 failed "); 217*1ff545d6SKristof Provost 218*1ff545d6SKristof Provost /* Overly large size. See above. */ 219*1ff545d6SKristof Provost io.pfrio_size = 1 << 24; 220*1ff545d6SKristof Provost if (ioctl(dev, DIOCRCLRTSTATS, &io) != 0) 221*1ff545d6SKristof Provost atf_tc_fail("Request with size 1 << 24 failed"); 222*1ff545d6SKristof Provost 223*1ff545d6SKristof Provost COMMON_CLEANUP(); 224*1ff545d6SKristof Provost } 225*1ff545d6SKristof Provost 226*1ff545d6SKristof Provost ATF_TC_WITHOUT_HEAD(settflags); 227*1ff545d6SKristof Provost ATF_TC_BODY(settflags, tc) 228*1ff545d6SKristof Provost { 229*1ff545d6SKristof Provost struct pfioc_table io; 230*1ff545d6SKristof Provost struct pfr_table tbl; 231*1ff545d6SKristof Provost int flags; 232*1ff545d6SKristof Provost 233*1ff545d6SKristof Provost COMMON_HEAD(); 234*1ff545d6SKristof Provost 235*1ff545d6SKristof Provost flags = 0; 236*1ff545d6SKristof Provost 237*1ff545d6SKristof Provost common_init_tbl(&tbl); 238*1ff545d6SKristof Provost 239*1ff545d6SKristof Provost bzero(&io, sizeof(io)); 240*1ff545d6SKristof Provost io.pfrio_flags = flags; 241*1ff545d6SKristof Provost io.pfrio_buffer = &tbl; 242*1ff545d6SKristof Provost io.pfrio_esize = sizeof(tbl); 243*1ff545d6SKristof Provost 244*1ff545d6SKristof Provost /* Negative size. This will succeed, because the kernel will not copy 245*1ff545d6SKristof Provost * tables than it has. */ 246*1ff545d6SKristof Provost io.pfrio_size = -1; 247*1ff545d6SKristof Provost if (ioctl(dev, DIOCRSETTFLAGS, &io) != 0) 248*1ff545d6SKristof Provost atf_tc_fail("Request with size -1 failed"); 249*1ff545d6SKristof Provost 250*1ff545d6SKristof Provost /* Overly large size. See above. */ 251*1ff545d6SKristof Provost io.pfrio_size = 1 << 28; 252*1ff545d6SKristof Provost if (ioctl(dev, DIOCRSETTFLAGS, &io) != 0) 253*1ff545d6SKristof Provost atf_tc_fail("Request with size 1 << 24 failed"); 254*1ff545d6SKristof Provost 255*1ff545d6SKristof Provost COMMON_CLEANUP(); 256*1ff545d6SKristof Provost } 257*1ff545d6SKristof Provost 25898c5f988SKristof Provost ATF_TP_ADD_TCS(tp) 25998c5f988SKristof Provost { 26098c5f988SKristof Provost ATF_TP_ADD_TC(tp, addtables); 26198c5f988SKristof Provost ATF_TP_ADD_TC(tp, deltables); 262*1ff545d6SKristof Provost ATF_TP_ADD_TC(tp, gettables); 263*1ff545d6SKristof Provost ATF_TP_ADD_TC(tp, gettstats); 264*1ff545d6SKristof Provost ATF_TP_ADD_TC(tp, clrtstats); 265*1ff545d6SKristof Provost ATF_TP_ADD_TC(tp, settflags); 26698c5f988SKristof Provost 26798c5f988SKristof Provost return (atf_no_error()); 26898c5f988SKristof Provost } 269