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 541ff545d6SKristof Provost void 551ff545d6SKristof Provost common_init_tbl(struct pfr_table *tbl) 561ff545d6SKristof Provost { 571ff545d6SKristof Provost bzero(tbl, sizeof(struct pfr_table)); 581ff545d6SKristof Provost strcpy(tbl->pfrt_anchor, "anchor"); 591ff545d6SKristof Provost strcpy(tbl->pfrt_name, "name"); 601ff545d6SKristof Provost tbl->pfrt_flags = 0; 611ff545d6SKristof Provost tbl->pfrt_fback = 0; 621ff545d6SKristof Provost } 631ff545d6SKristof 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; 69*1bb72c29SKristof Provost struct pfr_table tbls[4]; 7098c5f988SKristof Provost int flags; 7198c5f988SKristof Provost 7298c5f988SKristof Provost COMMON_HEAD(); 7398c5f988SKristof Provost 7498c5f988SKristof Provost flags = 0; 7598c5f988SKristof Provost 7698c5f988SKristof Provost bzero(&io, sizeof(io)); 7798c5f988SKristof Provost io.pfrio_flags = flags; 7898c5f988SKristof Provost io.pfrio_buffer = &tbl; 7998c5f988SKristof Provost io.pfrio_esize = sizeof(tbl); 8098c5f988SKristof Provost 8198c5f988SKristof Provost /* Negative size */ 8298c5f988SKristof Provost io.pfrio_size = -1; 8398c5f988SKristof Provost if (ioctl(dev, DIOCRADDTABLES, &io) == 0) 8498c5f988SKristof Provost atf_tc_fail("Request with size -1 succeeded"); 8598c5f988SKristof Provost 8698c5f988SKristof Provost /* Overly large size */ 8798c5f988SKristof Provost io.pfrio_size = 1 << 24; 8898c5f988SKristof Provost if (ioctl(dev, DIOCRADDTABLES, &io) == 0) 8998c5f988SKristof Provost atf_tc_fail("Request with size 1 << 24 succeeded"); 9098c5f988SKristof Provost 9198c5f988SKristof Provost /* NULL buffer */ 9298c5f988SKristof Provost io.pfrio_size = 1; 9398c5f988SKristof Provost io.pfrio_buffer = NULL; 9498c5f988SKristof Provost if (ioctl(dev, DIOCRADDTABLES, &io) == 0) 9598c5f988SKristof Provost atf_tc_fail("Request with NULL buffer succeeded"); 9698c5f988SKristof Provost 97*1bb72c29SKristof Provost /* This can provoke a memory leak, see r331225. */ 98*1bb72c29SKristof Provost io.pfrio_size = 4; 99*1bb72c29SKristof Provost for (int i = 0; i < io.pfrio_size; i++) 100*1bb72c29SKristof Provost common_init_tbl(&tbls[i]); 101*1bb72c29SKristof Provost 102*1bb72c29SKristof Provost io.pfrio_buffer = &tbls; 103*1bb72c29SKristof Provost ioctl(dev, DIOCRADDTABLES, &io); 104*1bb72c29SKristof Provost 10598c5f988SKristof Provost COMMON_CLEANUP(); 10698c5f988SKristof Provost } 10798c5f988SKristof Provost 10898c5f988SKristof Provost ATF_TC_WITHOUT_HEAD(deltables); 10998c5f988SKristof Provost ATF_TC_BODY(deltables, tc) 11098c5f988SKristof Provost { 11198c5f988SKristof Provost struct pfioc_table io; 11298c5f988SKristof Provost struct pfr_table tbl; 11398c5f988SKristof Provost int flags; 11498c5f988SKristof Provost 11598c5f988SKristof Provost COMMON_HEAD(); 11698c5f988SKristof Provost 11798c5f988SKristof Provost flags = 0; 11898c5f988SKristof Provost 11998c5f988SKristof Provost bzero(&io, sizeof(io)); 12098c5f988SKristof Provost io.pfrio_flags = flags; 12198c5f988SKristof Provost io.pfrio_buffer = &tbl; 12298c5f988SKristof Provost io.pfrio_esize = sizeof(tbl); 12398c5f988SKristof Provost 12498c5f988SKristof Provost /* Negative size */ 12598c5f988SKristof Provost io.pfrio_size = -1; 12698c5f988SKristof Provost if (ioctl(dev, DIOCRDELTABLES, &io) == 0) 12798c5f988SKristof Provost atf_tc_fail("Request with size -1 succeeded"); 12898c5f988SKristof Provost 12998c5f988SKristof Provost /* Overly large size */ 13098c5f988SKristof Provost io.pfrio_size = 1 << 24; 13198c5f988SKristof Provost if (ioctl(dev, DIOCRDELTABLES, &io) == 0) 13298c5f988SKristof Provost atf_tc_fail("Request with size 1 << 24 succeeded"); 13398c5f988SKristof Provost 13498c5f988SKristof Provost /* NULL buffer */ 13598c5f988SKristof Provost io.pfrio_size = 1; 13698c5f988SKristof Provost io.pfrio_buffer = NULL; 13798c5f988SKristof Provost if (ioctl(dev, DIOCRDELTABLES, &io) == 0) 13898c5f988SKristof Provost atf_tc_fail("Request with NULL buffer succeeded"); 13998c5f988SKristof Provost 14098c5f988SKristof Provost COMMON_CLEANUP(); 14198c5f988SKristof Provost } 14298c5f988SKristof Provost 1431ff545d6SKristof Provost ATF_TC_WITHOUT_HEAD(gettables); 1441ff545d6SKristof Provost ATF_TC_BODY(gettables, tc) 1451ff545d6SKristof Provost { 1461ff545d6SKristof Provost struct pfioc_table io; 1471ff545d6SKristof Provost struct pfr_table tbl; 1481ff545d6SKristof Provost int flags; 1491ff545d6SKristof Provost 1501ff545d6SKristof Provost COMMON_HEAD(); 1511ff545d6SKristof Provost 1521ff545d6SKristof Provost flags = 0; 1531ff545d6SKristof Provost 1541ff545d6SKristof Provost bzero(&io, sizeof(io)); 1551ff545d6SKristof Provost io.pfrio_flags = flags; 1561ff545d6SKristof Provost io.pfrio_buffer = &tbl; 1571ff545d6SKristof Provost io.pfrio_esize = sizeof(tbl); 1581ff545d6SKristof Provost 1591ff545d6SKristof Provost /* Negative size. This will succeed, because the kernel will not copy 1601ff545d6SKristof Provost * tables than it has. */ 1611ff545d6SKristof Provost io.pfrio_size = -1; 1621ff545d6SKristof Provost if (ioctl(dev, DIOCRGETTABLES, &io) != 0) 1631ff545d6SKristof Provost atf_tc_fail("Request with size -1 failed"); 1641ff545d6SKristof Provost 1651ff545d6SKristof Provost /* Overly large size. See above. */ 1661ff545d6SKristof Provost io.pfrio_size = 1 << 24; 1671ff545d6SKristof Provost if (ioctl(dev, DIOCRGETTABLES, &io) != 0) 1681ff545d6SKristof Provost atf_tc_fail("Request with size 1 << 24 failed"); 1691ff545d6SKristof Provost 1701ff545d6SKristof Provost COMMON_CLEANUP(); 1711ff545d6SKristof Provost } 1721ff545d6SKristof Provost 1731ff545d6SKristof Provost ATF_TC_WITHOUT_HEAD(gettstats); 1741ff545d6SKristof Provost ATF_TC_BODY(gettstats, tc) 1751ff545d6SKristof Provost { 1761ff545d6SKristof Provost struct pfioc_table io; 1771ff545d6SKristof Provost struct pfr_tstats stats; 1781ff545d6SKristof Provost int flags; 1791ff545d6SKristof Provost 1801ff545d6SKristof Provost COMMON_HEAD(); 1811ff545d6SKristof Provost 1821ff545d6SKristof Provost flags = 0; 1831ff545d6SKristof Provost 1841ff545d6SKristof Provost bzero(&io, sizeof(io)); 1851ff545d6SKristof Provost io.pfrio_flags = flags; 1861ff545d6SKristof Provost io.pfrio_buffer = &stats; 1871ff545d6SKristof Provost io.pfrio_esize = sizeof(stats); 1881ff545d6SKristof Provost 1891ff545d6SKristof Provost /* Negative size. This will succeed, because the kernel will not copy 1901ff545d6SKristof Provost * tables than it has. */ 1911ff545d6SKristof Provost io.pfrio_size = -1; 1921ff545d6SKristof Provost if (ioctl(dev, DIOCRGETTSTATS, &io) != 0) 1931ff545d6SKristof Provost atf_tc_fail("Request with size -1 failed"); 1941ff545d6SKristof Provost 1951ff545d6SKristof Provost /* Overly large size. See above. */ 1961ff545d6SKristof Provost io.pfrio_size = 1 << 24; 1971ff545d6SKristof Provost if (ioctl(dev, DIOCRGETTSTATS, &io) != 0) 1981ff545d6SKristof Provost atf_tc_fail("Request with size 1 << 24 failed"); 1991ff545d6SKristof Provost 2001ff545d6SKristof Provost COMMON_CLEANUP(); 2011ff545d6SKristof Provost } 2021ff545d6SKristof Provost 2031ff545d6SKristof Provost ATF_TC_WITHOUT_HEAD(clrtstats); 2041ff545d6SKristof Provost ATF_TC_BODY(clrtstats, tc) 2051ff545d6SKristof Provost { 2061ff545d6SKristof Provost struct pfioc_table io; 2071ff545d6SKristof Provost struct pfr_table tbl; 2081ff545d6SKristof Provost int flags; 2091ff545d6SKristof Provost 2101ff545d6SKristof Provost COMMON_HEAD(); 2111ff545d6SKristof Provost 2121ff545d6SKristof Provost flags = 0; 2131ff545d6SKristof Provost 2141ff545d6SKristof Provost common_init_tbl(&tbl); 2151ff545d6SKristof Provost 2161ff545d6SKristof Provost bzero(&io, sizeof(io)); 2171ff545d6SKristof Provost io.pfrio_flags = flags; 2181ff545d6SKristof Provost io.pfrio_buffer = &tbl; 2191ff545d6SKristof Provost io.pfrio_esize = sizeof(tbl); 2201ff545d6SKristof Provost 2211ff545d6SKristof Provost /* Negative size. This will succeed, because the kernel will not copy 2221ff545d6SKristof Provost * tables than it has. */ 2231ff545d6SKristof Provost io.pfrio_size = -1; 2241ff545d6SKristof Provost if (ioctl(dev, DIOCRCLRTSTATS, &io) != 0) 2251ff545d6SKristof Provost atf_tc_fail("Request with size -1 failed "); 2261ff545d6SKristof Provost 2271ff545d6SKristof Provost /* Overly large size. See above. */ 2281ff545d6SKristof Provost io.pfrio_size = 1 << 24; 2291ff545d6SKristof Provost if (ioctl(dev, DIOCRCLRTSTATS, &io) != 0) 2301ff545d6SKristof Provost atf_tc_fail("Request with size 1 << 24 failed"); 2311ff545d6SKristof Provost 2321ff545d6SKristof Provost COMMON_CLEANUP(); 2331ff545d6SKristof Provost } 2341ff545d6SKristof Provost 2351ff545d6SKristof Provost ATF_TC_WITHOUT_HEAD(settflags); 2361ff545d6SKristof Provost ATF_TC_BODY(settflags, tc) 2371ff545d6SKristof Provost { 2381ff545d6SKristof Provost struct pfioc_table io; 2391ff545d6SKristof Provost struct pfr_table tbl; 2401ff545d6SKristof Provost int flags; 2411ff545d6SKristof Provost 2421ff545d6SKristof Provost COMMON_HEAD(); 2431ff545d6SKristof Provost 2441ff545d6SKristof Provost flags = 0; 2451ff545d6SKristof Provost 2461ff545d6SKristof Provost common_init_tbl(&tbl); 2471ff545d6SKristof Provost 2481ff545d6SKristof Provost bzero(&io, sizeof(io)); 2491ff545d6SKristof Provost io.pfrio_flags = flags; 2501ff545d6SKristof Provost io.pfrio_buffer = &tbl; 2511ff545d6SKristof Provost io.pfrio_esize = sizeof(tbl); 2521ff545d6SKristof Provost 2531ff545d6SKristof Provost /* Negative size. This will succeed, because the kernel will not copy 2541ff545d6SKristof Provost * tables than it has. */ 2551ff545d6SKristof Provost io.pfrio_size = -1; 2561ff545d6SKristof Provost if (ioctl(dev, DIOCRSETTFLAGS, &io) != 0) 2571ff545d6SKristof Provost atf_tc_fail("Request with size -1 failed"); 2581ff545d6SKristof Provost 2591ff545d6SKristof Provost /* Overly large size. See above. */ 2601ff545d6SKristof Provost io.pfrio_size = 1 << 28; 2611ff545d6SKristof Provost if (ioctl(dev, DIOCRSETTFLAGS, &io) != 0) 2621ff545d6SKristof Provost atf_tc_fail("Request with size 1 << 24 failed"); 2631ff545d6SKristof Provost 2641ff545d6SKristof Provost COMMON_CLEANUP(); 2651ff545d6SKristof Provost } 2661ff545d6SKristof Provost 2678e748b94SKristof Provost ATF_TC_WITHOUT_HEAD(igetifaces); 2688e748b94SKristof Provost ATF_TC_BODY(igetifaces, tc) 2698e748b94SKristof Provost { 2708e748b94SKristof Provost struct pfioc_iface io; 2718e748b94SKristof Provost struct pfi_kif kif; 2728e748b94SKristof Provost 2738e748b94SKristof Provost COMMON_HEAD(); 2748e748b94SKristof Provost 2758e748b94SKristof Provost bzero(&io, sizeof(io)); 2768e748b94SKristof Provost io.pfiio_flags = 0; 2778e748b94SKristof Provost io.pfiio_buffer = &kif; 2788e748b94SKristof Provost io.pfiio_esize = sizeof(kif); 2798e748b94SKristof Provost 2808e748b94SKristof Provost /* Negative size */ 2818e748b94SKristof Provost io.pfiio_size = -1; 2828e748b94SKristof Provost if (ioctl(dev, DIOCIGETIFACES, &io) == 0) 2838e748b94SKristof Provost atf_tc_fail("request with size -1 succeeded"); 2848e748b94SKristof Provost 2858e748b94SKristof Provost /* Overflow size */ 2868e748b94SKristof Provost io.pfiio_size = 1 << 31; 2878e748b94SKristof Provost if (ioctl(dev, DIOCIGETIFACES, &io) == 0) 2888e748b94SKristof Provost atf_tc_fail("request with size 1 << 31 succeeded"); 2898e748b94SKristof Provost 2908e748b94SKristof Provost COMMON_CLEANUP(); 2918e748b94SKristof Provost } 2928e748b94SKristof Provost 2938e748b94SKristof Provost ATF_TC_WITHOUT_HEAD(commit); 2948e748b94SKristof Provost ATF_TC_BODY(commit, tc) 2958e748b94SKristof Provost { 2968e748b94SKristof Provost struct pfioc_trans io; 2978e748b94SKristof Provost struct pfioc_trans_e ioe; 2988e748b94SKristof Provost 2998e748b94SKristof Provost COMMON_HEAD(); 3008e748b94SKristof Provost 3018e748b94SKristof Provost bzero(&io, sizeof(io)); 3028e748b94SKristof Provost io.esize = sizeof(ioe); 3038e748b94SKristof Provost io.array = &ioe; 3048e748b94SKristof Provost 3058e748b94SKristof Provost /* Negative size */ 3068e748b94SKristof Provost io.size = -1; 3078e748b94SKristof Provost if (ioctl(dev, DIOCXCOMMIT, &io) == 0) 3088e748b94SKristof Provost atf_tc_fail("request with size -1 succeeded"); 3098e748b94SKristof Provost 3108e748b94SKristof Provost /* Overflow size */ 3118e748b94SKristof Provost io.size = 1 << 30; 3128e748b94SKristof Provost if (ioctl(dev, DIOCXCOMMIT, &io) == 0) 3138e748b94SKristof Provost atf_tc_fail("request with size 1 << 30 succeeded"); 3148e748b94SKristof Provost 3158e748b94SKristof Provost /* NULL buffer */ 3168e748b94SKristof Provost io.size = 1; 3178e748b94SKristof Provost io.array = NULL; 3188e748b94SKristof Provost if (ioctl(dev, DIOCXCOMMIT, &io) == 0) 3198e748b94SKristof Provost atf_tc_fail("request with size -1 succeeded"); 3208e748b94SKristof Provost 3218e748b94SKristof Provost COMMON_CLEANUP(); 3228e748b94SKristof Provost } 3238e748b94SKristof Provost 32498c5f988SKristof Provost ATF_TP_ADD_TCS(tp) 32598c5f988SKristof Provost { 32698c5f988SKristof Provost ATF_TP_ADD_TC(tp, addtables); 32798c5f988SKristof Provost ATF_TP_ADD_TC(tp, deltables); 3281ff545d6SKristof Provost ATF_TP_ADD_TC(tp, gettables); 3291ff545d6SKristof Provost ATF_TP_ADD_TC(tp, gettstats); 3301ff545d6SKristof Provost ATF_TP_ADD_TC(tp, clrtstats); 3311ff545d6SKristof Provost ATF_TP_ADD_TC(tp, settflags); 3328e748b94SKristof Provost ATF_TP_ADD_TC(tp, igetifaces); 3338e748b94SKristof Provost ATF_TP_ADD_TC(tp, commit); 33498c5f988SKristof Provost 33598c5f988SKristof Provost return (atf_no_error()); 33698c5f988SKristof Provost } 337