13b3a8eb9SGleb Smirnoff /* $OpenBSD: pfctl_radix.c,v 1.27 2005/05/21 21:03:58 henning Exp $ */ 23b3a8eb9SGleb Smirnoff 31de7b4b8SPedro F. Giffuni /*- 41de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause 51de7b4b8SPedro F. Giffuni * 63b3a8eb9SGleb Smirnoff * Copyright (c) 2002 Cedric Berger 73b3a8eb9SGleb Smirnoff * All rights reserved. 83b3a8eb9SGleb Smirnoff * 93b3a8eb9SGleb Smirnoff * Redistribution and use in source and binary forms, with or without 103b3a8eb9SGleb Smirnoff * modification, are permitted provided that the following conditions 113b3a8eb9SGleb Smirnoff * are met: 123b3a8eb9SGleb Smirnoff * 133b3a8eb9SGleb Smirnoff * - Redistributions of source code must retain the above copyright 143b3a8eb9SGleb Smirnoff * notice, this list of conditions and the following disclaimer. 153b3a8eb9SGleb Smirnoff * - Redistributions in binary form must reproduce the above 163b3a8eb9SGleb Smirnoff * copyright notice, this list of conditions and the following 173b3a8eb9SGleb Smirnoff * disclaimer in the documentation and/or other materials provided 183b3a8eb9SGleb Smirnoff * with the distribution. 193b3a8eb9SGleb Smirnoff * 203b3a8eb9SGleb Smirnoff * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 213b3a8eb9SGleb Smirnoff * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 223b3a8eb9SGleb Smirnoff * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 233b3a8eb9SGleb Smirnoff * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 243b3a8eb9SGleb Smirnoff * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 253b3a8eb9SGleb Smirnoff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 263b3a8eb9SGleb Smirnoff * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 273b3a8eb9SGleb Smirnoff * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 283b3a8eb9SGleb Smirnoff * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 293b3a8eb9SGleb Smirnoff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 303b3a8eb9SGleb Smirnoff * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 313b3a8eb9SGleb Smirnoff * POSSIBILITY OF SUCH DAMAGE. 323b3a8eb9SGleb Smirnoff * 333b3a8eb9SGleb Smirnoff */ 343b3a8eb9SGleb Smirnoff 353b3a8eb9SGleb Smirnoff #include <sys/cdefs.h> 363b3a8eb9SGleb Smirnoff __FBSDID("$FreeBSD$"); 373b3a8eb9SGleb Smirnoff 383b3a8eb9SGleb Smirnoff #include <sys/types.h> 393b3a8eb9SGleb Smirnoff #include <sys/ioctl.h> 403b3a8eb9SGleb Smirnoff #include <sys/socket.h> 413b3a8eb9SGleb Smirnoff 423b3a8eb9SGleb Smirnoff #include <net/if.h> 433b3a8eb9SGleb Smirnoff #include <net/pfvar.h> 443b3a8eb9SGleb Smirnoff 453b3a8eb9SGleb Smirnoff #include <errno.h> 463b3a8eb9SGleb Smirnoff #include <string.h> 473b3a8eb9SGleb Smirnoff #include <ctype.h> 483b3a8eb9SGleb Smirnoff #include <stdio.h> 493b3a8eb9SGleb Smirnoff #include <stdlib.h> 503b3a8eb9SGleb Smirnoff #include <limits.h> 513b3a8eb9SGleb Smirnoff #include <err.h> 523b3a8eb9SGleb Smirnoff 533b3a8eb9SGleb Smirnoff #include "pfctl.h" 543b3a8eb9SGleb Smirnoff 553b3a8eb9SGleb Smirnoff #define BUF_SIZE 256 563b3a8eb9SGleb Smirnoff 573b3a8eb9SGleb Smirnoff extern int dev; 583b3a8eb9SGleb Smirnoff 593b3a8eb9SGleb Smirnoff static int pfr_next_token(char buf[], FILE *); 603b3a8eb9SGleb Smirnoff 61*3c7fbb06SKristof Provost static void 62*3c7fbb06SKristof Provost pfr_report_error(struct pfr_table *tbl, struct pfioc_table *io, 63*3c7fbb06SKristof Provost const char *err) 64*3c7fbb06SKristof Provost { 65*3c7fbb06SKristof Provost unsigned long maxcount; 66*3c7fbb06SKristof Provost size_t s; 67*3c7fbb06SKristof Provost 68*3c7fbb06SKristof Provost s = sizeof(maxcount); 69*3c7fbb06SKristof Provost if (sysctlbyname("net.pf.request_maxcount", &maxcount, &s, NULL, 70*3c7fbb06SKristof Provost 0) == -1) 71*3c7fbb06SKristof Provost return; 72*3c7fbb06SKristof Provost 73*3c7fbb06SKristof Provost if (io->pfrio_size > maxcount || io->pfrio_size2 > maxcount) 74*3c7fbb06SKristof Provost fprintf(stderr, "cannot %s %s: too many elements.\n" 75*3c7fbb06SKristof Provost "Consider increasing net.pf.request_maxcount.", 76*3c7fbb06SKristof Provost err, tbl->pfrt_name); 77*3c7fbb06SKristof Provost } 783b3a8eb9SGleb Smirnoff 793b3a8eb9SGleb Smirnoff int 803b3a8eb9SGleb Smirnoff pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags) 813b3a8eb9SGleb Smirnoff { 823b3a8eb9SGleb Smirnoff struct pfioc_table io; 833b3a8eb9SGleb Smirnoff 843b3a8eb9SGleb Smirnoff bzero(&io, sizeof io); 853b3a8eb9SGleb Smirnoff io.pfrio_flags = flags; 863b3a8eb9SGleb Smirnoff if (filter != NULL) 873b3a8eb9SGleb Smirnoff io.pfrio_table = *filter; 883b3a8eb9SGleb Smirnoff if (ioctl(dev, DIOCRCLRTABLES, &io)) 893b3a8eb9SGleb Smirnoff return (-1); 903b3a8eb9SGleb Smirnoff if (ndel != NULL) 913b3a8eb9SGleb Smirnoff *ndel = io.pfrio_ndel; 923b3a8eb9SGleb Smirnoff return (0); 933b3a8eb9SGleb Smirnoff } 943b3a8eb9SGleb Smirnoff 953b3a8eb9SGleb Smirnoff int 963b3a8eb9SGleb Smirnoff pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags) 973b3a8eb9SGleb Smirnoff { 983b3a8eb9SGleb Smirnoff struct pfioc_table io; 993b3a8eb9SGleb Smirnoff 1003b3a8eb9SGleb Smirnoff if (size < 0 || (size && tbl == NULL)) { 1013b3a8eb9SGleb Smirnoff errno = EINVAL; 1023b3a8eb9SGleb Smirnoff return (-1); 1033b3a8eb9SGleb Smirnoff } 1043b3a8eb9SGleb Smirnoff bzero(&io, sizeof io); 1053b3a8eb9SGleb Smirnoff io.pfrio_flags = flags; 1063b3a8eb9SGleb Smirnoff io.pfrio_buffer = tbl; 1073b3a8eb9SGleb Smirnoff io.pfrio_esize = sizeof(*tbl); 1083b3a8eb9SGleb Smirnoff io.pfrio_size = size; 109*3c7fbb06SKristof Provost if (ioctl(dev, DIOCRADDTABLES, &io)) { 110*3c7fbb06SKristof Provost pfr_report_error(tbl, &io, "add table"); 1113b3a8eb9SGleb Smirnoff return (-1); 112*3c7fbb06SKristof Provost } 1133b3a8eb9SGleb Smirnoff if (nadd != NULL) 1143b3a8eb9SGleb Smirnoff *nadd = io.pfrio_nadd; 1153b3a8eb9SGleb Smirnoff return (0); 1163b3a8eb9SGleb Smirnoff } 1173b3a8eb9SGleb Smirnoff 1183b3a8eb9SGleb Smirnoff int 1193b3a8eb9SGleb Smirnoff pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags) 1203b3a8eb9SGleb Smirnoff { 1213b3a8eb9SGleb Smirnoff struct pfioc_table io; 1223b3a8eb9SGleb Smirnoff 1233b3a8eb9SGleb Smirnoff if (size < 0 || (size && tbl == NULL)) { 1243b3a8eb9SGleb Smirnoff errno = EINVAL; 1253b3a8eb9SGleb Smirnoff return (-1); 1263b3a8eb9SGleb Smirnoff } 1273b3a8eb9SGleb Smirnoff bzero(&io, sizeof io); 1283b3a8eb9SGleb Smirnoff io.pfrio_flags = flags; 1293b3a8eb9SGleb Smirnoff io.pfrio_buffer = tbl; 1303b3a8eb9SGleb Smirnoff io.pfrio_esize = sizeof(*tbl); 1313b3a8eb9SGleb Smirnoff io.pfrio_size = size; 132*3c7fbb06SKristof Provost if (ioctl(dev, DIOCRDELTABLES, &io)) { 133*3c7fbb06SKristof Provost pfr_report_error(tbl, &io, "delete table"); 1343b3a8eb9SGleb Smirnoff return (-1); 135*3c7fbb06SKristof Provost } 1363b3a8eb9SGleb Smirnoff if (ndel != NULL) 1373b3a8eb9SGleb Smirnoff *ndel = io.pfrio_ndel; 1383b3a8eb9SGleb Smirnoff return (0); 1393b3a8eb9SGleb Smirnoff } 1403b3a8eb9SGleb Smirnoff 1413b3a8eb9SGleb Smirnoff int 1423b3a8eb9SGleb Smirnoff pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size, 1433b3a8eb9SGleb Smirnoff int flags) 1443b3a8eb9SGleb Smirnoff { 1453b3a8eb9SGleb Smirnoff struct pfioc_table io; 1463b3a8eb9SGleb Smirnoff 1473b3a8eb9SGleb Smirnoff if (size == NULL || *size < 0 || (*size && tbl == NULL)) { 1483b3a8eb9SGleb Smirnoff errno = EINVAL; 1493b3a8eb9SGleb Smirnoff return (-1); 1503b3a8eb9SGleb Smirnoff } 1513b3a8eb9SGleb Smirnoff bzero(&io, sizeof io); 1523b3a8eb9SGleb Smirnoff io.pfrio_flags = flags; 1533b3a8eb9SGleb Smirnoff if (filter != NULL) 1543b3a8eb9SGleb Smirnoff io.pfrio_table = *filter; 1553b3a8eb9SGleb Smirnoff io.pfrio_buffer = tbl; 1563b3a8eb9SGleb Smirnoff io.pfrio_esize = sizeof(*tbl); 1573b3a8eb9SGleb Smirnoff io.pfrio_size = *size; 158*3c7fbb06SKristof Provost if (ioctl(dev, DIOCRGETTABLES, &io)) { 159*3c7fbb06SKristof Provost pfr_report_error(tbl, &io, "get table"); 1603b3a8eb9SGleb Smirnoff return (-1); 161*3c7fbb06SKristof Provost } 1623b3a8eb9SGleb Smirnoff *size = io.pfrio_size; 1633b3a8eb9SGleb Smirnoff return (0); 1643b3a8eb9SGleb Smirnoff } 1653b3a8eb9SGleb Smirnoff 1663b3a8eb9SGleb Smirnoff int 1673b3a8eb9SGleb Smirnoff pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size, 1683b3a8eb9SGleb Smirnoff int flags) 1693b3a8eb9SGleb Smirnoff { 1703b3a8eb9SGleb Smirnoff struct pfioc_table io; 1713b3a8eb9SGleb Smirnoff 1723b3a8eb9SGleb Smirnoff if (size == NULL || *size < 0 || (*size && tbl == NULL)) { 1733b3a8eb9SGleb Smirnoff errno = EINVAL; 1743b3a8eb9SGleb Smirnoff return (-1); 1753b3a8eb9SGleb Smirnoff } 1763b3a8eb9SGleb Smirnoff bzero(&io, sizeof io); 1773b3a8eb9SGleb Smirnoff io.pfrio_flags = flags; 1783b3a8eb9SGleb Smirnoff if (filter != NULL) 1793b3a8eb9SGleb Smirnoff io.pfrio_table = *filter; 1803b3a8eb9SGleb Smirnoff io.pfrio_buffer = tbl; 1813b3a8eb9SGleb Smirnoff io.pfrio_esize = sizeof(*tbl); 1823b3a8eb9SGleb Smirnoff io.pfrio_size = *size; 183*3c7fbb06SKristof Provost if (ioctl(dev, DIOCRGETTSTATS, &io)) { 184*3c7fbb06SKristof Provost pfr_report_error(filter, &io, "get tstats for"); 1853b3a8eb9SGleb Smirnoff return (-1); 186*3c7fbb06SKristof Provost } 1873b3a8eb9SGleb Smirnoff *size = io.pfrio_size; 1883b3a8eb9SGleb Smirnoff return (0); 1893b3a8eb9SGleb Smirnoff } 1903b3a8eb9SGleb Smirnoff 1913b3a8eb9SGleb Smirnoff int 1923b3a8eb9SGleb Smirnoff pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags) 1933b3a8eb9SGleb Smirnoff { 1943b3a8eb9SGleb Smirnoff struct pfioc_table io; 1953b3a8eb9SGleb Smirnoff 1963b3a8eb9SGleb Smirnoff if (tbl == NULL) { 1973b3a8eb9SGleb Smirnoff errno = EINVAL; 1983b3a8eb9SGleb Smirnoff return (-1); 1993b3a8eb9SGleb Smirnoff } 2003b3a8eb9SGleb Smirnoff bzero(&io, sizeof io); 2013b3a8eb9SGleb Smirnoff io.pfrio_flags = flags; 2023b3a8eb9SGleb Smirnoff io.pfrio_table = *tbl; 2033b3a8eb9SGleb Smirnoff if (ioctl(dev, DIOCRCLRADDRS, &io)) 2043b3a8eb9SGleb Smirnoff return (-1); 2053b3a8eb9SGleb Smirnoff if (ndel != NULL) 2063b3a8eb9SGleb Smirnoff *ndel = io.pfrio_ndel; 2073b3a8eb9SGleb Smirnoff return (0); 2083b3a8eb9SGleb Smirnoff } 2093b3a8eb9SGleb Smirnoff 2103b3a8eb9SGleb Smirnoff int 2113b3a8eb9SGleb Smirnoff pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, 2123b3a8eb9SGleb Smirnoff int *nadd, int flags) 2133b3a8eb9SGleb Smirnoff { 2143b3a8eb9SGleb Smirnoff struct pfioc_table io; 2153b3a8eb9SGleb Smirnoff 2163b3a8eb9SGleb Smirnoff if (tbl == NULL || size < 0 || (size && addr == NULL)) { 2173b3a8eb9SGleb Smirnoff errno = EINVAL; 2183b3a8eb9SGleb Smirnoff return (-1); 2193b3a8eb9SGleb Smirnoff } 2203b3a8eb9SGleb Smirnoff bzero(&io, sizeof io); 2213b3a8eb9SGleb Smirnoff io.pfrio_flags = flags; 2223b3a8eb9SGleb Smirnoff io.pfrio_table = *tbl; 2233b3a8eb9SGleb Smirnoff io.pfrio_buffer = addr; 2243b3a8eb9SGleb Smirnoff io.pfrio_esize = sizeof(*addr); 2253b3a8eb9SGleb Smirnoff io.pfrio_size = size; 226*3c7fbb06SKristof Provost if (ioctl(dev, DIOCRADDADDRS, &io)) { 227*3c7fbb06SKristof Provost pfr_report_error(tbl, &io, "add addresses in"); 2283b3a8eb9SGleb Smirnoff return (-1); 229*3c7fbb06SKristof Provost } 2303b3a8eb9SGleb Smirnoff if (nadd != NULL) 2313b3a8eb9SGleb Smirnoff *nadd = io.pfrio_nadd; 2323b3a8eb9SGleb Smirnoff return (0); 2333b3a8eb9SGleb Smirnoff } 2343b3a8eb9SGleb Smirnoff 2353b3a8eb9SGleb Smirnoff int 2363b3a8eb9SGleb Smirnoff pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, 2373b3a8eb9SGleb Smirnoff int *ndel, int flags) 2383b3a8eb9SGleb Smirnoff { 2393b3a8eb9SGleb Smirnoff struct pfioc_table io; 2403b3a8eb9SGleb Smirnoff 2413b3a8eb9SGleb Smirnoff if (tbl == NULL || size < 0 || (size && addr == NULL)) { 2423b3a8eb9SGleb Smirnoff errno = EINVAL; 2433b3a8eb9SGleb Smirnoff return (-1); 2443b3a8eb9SGleb Smirnoff } 2453b3a8eb9SGleb Smirnoff bzero(&io, sizeof io); 2463b3a8eb9SGleb Smirnoff io.pfrio_flags = flags; 2473b3a8eb9SGleb Smirnoff io.pfrio_table = *tbl; 2483b3a8eb9SGleb Smirnoff io.pfrio_buffer = addr; 2493b3a8eb9SGleb Smirnoff io.pfrio_esize = sizeof(*addr); 2503b3a8eb9SGleb Smirnoff io.pfrio_size = size; 251*3c7fbb06SKristof Provost if (ioctl(dev, DIOCRDELADDRS, &io)) { 252*3c7fbb06SKristof Provost pfr_report_error(tbl, &io, "delete addresses in"); 2533b3a8eb9SGleb Smirnoff return (-1); 254*3c7fbb06SKristof Provost } 2553b3a8eb9SGleb Smirnoff if (ndel != NULL) 2563b3a8eb9SGleb Smirnoff *ndel = io.pfrio_ndel; 2573b3a8eb9SGleb Smirnoff return (0); 2583b3a8eb9SGleb Smirnoff } 2593b3a8eb9SGleb Smirnoff 2603b3a8eb9SGleb Smirnoff int 2613b3a8eb9SGleb Smirnoff pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, 2623b3a8eb9SGleb Smirnoff int *size2, int *nadd, int *ndel, int *nchange, int flags) 2633b3a8eb9SGleb Smirnoff { 2643b3a8eb9SGleb Smirnoff struct pfioc_table io; 2653b3a8eb9SGleb Smirnoff 2663b3a8eb9SGleb Smirnoff if (tbl == NULL || size < 0 || (size && addr == NULL)) { 2673b3a8eb9SGleb Smirnoff errno = EINVAL; 2683b3a8eb9SGleb Smirnoff return (-1); 2693b3a8eb9SGleb Smirnoff } 2703b3a8eb9SGleb Smirnoff bzero(&io, sizeof io); 2713b3a8eb9SGleb Smirnoff io.pfrio_flags = flags; 2723b3a8eb9SGleb Smirnoff io.pfrio_table = *tbl; 2733b3a8eb9SGleb Smirnoff io.pfrio_buffer = addr; 2743b3a8eb9SGleb Smirnoff io.pfrio_esize = sizeof(*addr); 2753b3a8eb9SGleb Smirnoff io.pfrio_size = size; 2763b3a8eb9SGleb Smirnoff io.pfrio_size2 = (size2 != NULL) ? *size2 : 0; 277*3c7fbb06SKristof Provost if (ioctl(dev, DIOCRSETADDRS, &io)) { 278*3c7fbb06SKristof Provost pfr_report_error(tbl, &io, "set addresses in"); 2793b3a8eb9SGleb Smirnoff return (-1); 280*3c7fbb06SKristof Provost } 2813b3a8eb9SGleb Smirnoff if (nadd != NULL) 2823b3a8eb9SGleb Smirnoff *nadd = io.pfrio_nadd; 2833b3a8eb9SGleb Smirnoff if (ndel != NULL) 2843b3a8eb9SGleb Smirnoff *ndel = io.pfrio_ndel; 2853b3a8eb9SGleb Smirnoff if (nchange != NULL) 2863b3a8eb9SGleb Smirnoff *nchange = io.pfrio_nchange; 2873b3a8eb9SGleb Smirnoff if (size2 != NULL) 2883b3a8eb9SGleb Smirnoff *size2 = io.pfrio_size2; 2893b3a8eb9SGleb Smirnoff return (0); 2903b3a8eb9SGleb Smirnoff } 2913b3a8eb9SGleb Smirnoff 2923b3a8eb9SGleb Smirnoff int 2933b3a8eb9SGleb Smirnoff pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size, 2943b3a8eb9SGleb Smirnoff int flags) 2953b3a8eb9SGleb Smirnoff { 2963b3a8eb9SGleb Smirnoff struct pfioc_table io; 2973b3a8eb9SGleb Smirnoff 2983b3a8eb9SGleb Smirnoff if (tbl == NULL || size == NULL || *size < 0 || 2993b3a8eb9SGleb Smirnoff (*size && addr == NULL)) { 3003b3a8eb9SGleb Smirnoff errno = EINVAL; 3013b3a8eb9SGleb Smirnoff return (-1); 3023b3a8eb9SGleb Smirnoff } 3033b3a8eb9SGleb Smirnoff bzero(&io, sizeof io); 3043b3a8eb9SGleb Smirnoff io.pfrio_flags = flags; 3053b3a8eb9SGleb Smirnoff io.pfrio_table = *tbl; 3063b3a8eb9SGleb Smirnoff io.pfrio_buffer = addr; 3073b3a8eb9SGleb Smirnoff io.pfrio_esize = sizeof(*addr); 3083b3a8eb9SGleb Smirnoff io.pfrio_size = *size; 309*3c7fbb06SKristof Provost if (ioctl(dev, DIOCRGETADDRS, &io)) { 310*3c7fbb06SKristof Provost pfr_report_error(tbl, &io, "get addresses from"); 3113b3a8eb9SGleb Smirnoff return (-1); 312*3c7fbb06SKristof Provost } 3133b3a8eb9SGleb Smirnoff *size = io.pfrio_size; 3143b3a8eb9SGleb Smirnoff return (0); 3153b3a8eb9SGleb Smirnoff } 3163b3a8eb9SGleb Smirnoff 3173b3a8eb9SGleb Smirnoff int 3183b3a8eb9SGleb Smirnoff pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size, 3193b3a8eb9SGleb Smirnoff int flags) 3203b3a8eb9SGleb Smirnoff { 3213b3a8eb9SGleb Smirnoff struct pfioc_table io; 3223b3a8eb9SGleb Smirnoff 3233b3a8eb9SGleb Smirnoff if (tbl == NULL || size == NULL || *size < 0 || 3243b3a8eb9SGleb Smirnoff (*size && addr == NULL)) { 3253b3a8eb9SGleb Smirnoff errno = EINVAL; 3263b3a8eb9SGleb Smirnoff return (-1); 3273b3a8eb9SGleb Smirnoff } 3283b3a8eb9SGleb Smirnoff bzero(&io, sizeof io); 3293b3a8eb9SGleb Smirnoff io.pfrio_flags = flags; 3303b3a8eb9SGleb Smirnoff io.pfrio_table = *tbl; 3313b3a8eb9SGleb Smirnoff io.pfrio_buffer = addr; 3323b3a8eb9SGleb Smirnoff io.pfrio_esize = sizeof(*addr); 3333b3a8eb9SGleb Smirnoff io.pfrio_size = *size; 334*3c7fbb06SKristof Provost if (ioctl(dev, DIOCRGETASTATS, &io)) { 335*3c7fbb06SKristof Provost pfr_report_error(tbl, &io, "get astats from"); 3363b3a8eb9SGleb Smirnoff return (-1); 337*3c7fbb06SKristof Provost } 3383b3a8eb9SGleb Smirnoff *size = io.pfrio_size; 3393b3a8eb9SGleb Smirnoff return (0); 3403b3a8eb9SGleb Smirnoff } 3413b3a8eb9SGleb Smirnoff 3423b3a8eb9SGleb Smirnoff int 3433b3a8eb9SGleb Smirnoff pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags) 3443b3a8eb9SGleb Smirnoff { 3453b3a8eb9SGleb Smirnoff struct pfioc_table io; 3463b3a8eb9SGleb Smirnoff 3473b3a8eb9SGleb Smirnoff if (size < 0 || (size && !tbl)) { 3483b3a8eb9SGleb Smirnoff errno = EINVAL; 3493b3a8eb9SGleb Smirnoff return (-1); 3503b3a8eb9SGleb Smirnoff } 3513b3a8eb9SGleb Smirnoff bzero(&io, sizeof io); 3523b3a8eb9SGleb Smirnoff io.pfrio_flags = flags; 3533b3a8eb9SGleb Smirnoff io.pfrio_buffer = tbl; 3543b3a8eb9SGleb Smirnoff io.pfrio_esize = sizeof(*tbl); 3553b3a8eb9SGleb Smirnoff io.pfrio_size = size; 356*3c7fbb06SKristof Provost if (ioctl(dev, DIOCRCLRTSTATS, &io)) { 357*3c7fbb06SKristof Provost pfr_report_error(tbl, &io, "clear tstats from"); 3583b3a8eb9SGleb Smirnoff return (-1); 359*3c7fbb06SKristof Provost } 3603b3a8eb9SGleb Smirnoff if (nzero) 3613b3a8eb9SGleb Smirnoff *nzero = io.pfrio_nzero; 3623b3a8eb9SGleb Smirnoff return (0); 3633b3a8eb9SGleb Smirnoff } 3643b3a8eb9SGleb Smirnoff 3653b3a8eb9SGleb Smirnoff int 3663b3a8eb9SGleb Smirnoff pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, 3673b3a8eb9SGleb Smirnoff int *nmatch, int flags) 3683b3a8eb9SGleb Smirnoff { 3693b3a8eb9SGleb Smirnoff struct pfioc_table io; 3703b3a8eb9SGleb Smirnoff 3713b3a8eb9SGleb Smirnoff if (tbl == NULL || size < 0 || (size && addr == NULL)) { 3723b3a8eb9SGleb Smirnoff errno = EINVAL; 3733b3a8eb9SGleb Smirnoff return (-1); 3743b3a8eb9SGleb Smirnoff } 3753b3a8eb9SGleb Smirnoff bzero(&io, sizeof io); 3763b3a8eb9SGleb Smirnoff io.pfrio_flags = flags; 3773b3a8eb9SGleb Smirnoff io.pfrio_table = *tbl; 3783b3a8eb9SGleb Smirnoff io.pfrio_buffer = addr; 3793b3a8eb9SGleb Smirnoff io.pfrio_esize = sizeof(*addr); 3803b3a8eb9SGleb Smirnoff io.pfrio_size = size; 381*3c7fbb06SKristof Provost if (ioctl(dev, DIOCRTSTADDRS, &io)) { 382*3c7fbb06SKristof Provost pfr_report_error(tbl, &io, "test addresses in"); 3833b3a8eb9SGleb Smirnoff return (-1); 384*3c7fbb06SKristof Provost } 3853b3a8eb9SGleb Smirnoff if (nmatch) 3863b3a8eb9SGleb Smirnoff *nmatch = io.pfrio_nmatch; 3873b3a8eb9SGleb Smirnoff return (0); 3883b3a8eb9SGleb Smirnoff } 3893b3a8eb9SGleb Smirnoff 3903b3a8eb9SGleb Smirnoff int 3913b3a8eb9SGleb Smirnoff pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size, 3923b3a8eb9SGleb Smirnoff int *nadd, int *naddr, int ticket, int flags) 3933b3a8eb9SGleb Smirnoff { 3943b3a8eb9SGleb Smirnoff struct pfioc_table io; 3953b3a8eb9SGleb Smirnoff 3963b3a8eb9SGleb Smirnoff if (tbl == NULL || size < 0 || (size && addr == NULL)) { 3973b3a8eb9SGleb Smirnoff errno = EINVAL; 3983b3a8eb9SGleb Smirnoff return (-1); 3993b3a8eb9SGleb Smirnoff } 4003b3a8eb9SGleb Smirnoff bzero(&io, sizeof io); 4013b3a8eb9SGleb Smirnoff io.pfrio_flags = flags; 4023b3a8eb9SGleb Smirnoff io.pfrio_table = *tbl; 4033b3a8eb9SGleb Smirnoff io.pfrio_buffer = addr; 4043b3a8eb9SGleb Smirnoff io.pfrio_esize = sizeof(*addr); 4053b3a8eb9SGleb Smirnoff io.pfrio_size = size; 4063b3a8eb9SGleb Smirnoff io.pfrio_ticket = ticket; 407*3c7fbb06SKristof Provost if (ioctl(dev, DIOCRINADEFINE, &io)) { 408*3c7fbb06SKristof Provost pfr_report_error(tbl, &io, "define inactive set table"); 4093b3a8eb9SGleb Smirnoff return (-1); 410*3c7fbb06SKristof Provost } 4113b3a8eb9SGleb Smirnoff if (nadd != NULL) 4123b3a8eb9SGleb Smirnoff *nadd = io.pfrio_nadd; 4133b3a8eb9SGleb Smirnoff if (naddr != NULL) 4143b3a8eb9SGleb Smirnoff *naddr = io.pfrio_naddr; 4153b3a8eb9SGleb Smirnoff return (0); 4163b3a8eb9SGleb Smirnoff } 4173b3a8eb9SGleb Smirnoff 4183b3a8eb9SGleb Smirnoff /* interface management code */ 4193b3a8eb9SGleb Smirnoff 4203b3a8eb9SGleb Smirnoff int 4213b3a8eb9SGleb Smirnoff pfi_get_ifaces(const char *filter, struct pfi_kif *buf, int *size) 4223b3a8eb9SGleb Smirnoff { 4233b3a8eb9SGleb Smirnoff struct pfioc_iface io; 4243b3a8eb9SGleb Smirnoff 4253b3a8eb9SGleb Smirnoff if (size == NULL || *size < 0 || (*size && buf == NULL)) { 4263b3a8eb9SGleb Smirnoff errno = EINVAL; 4273b3a8eb9SGleb Smirnoff return (-1); 4283b3a8eb9SGleb Smirnoff } 4293b3a8eb9SGleb Smirnoff bzero(&io, sizeof io); 4303b3a8eb9SGleb Smirnoff if (filter != NULL) 4313b3a8eb9SGleb Smirnoff if (strlcpy(io.pfiio_name, filter, sizeof(io.pfiio_name)) >= 4323b3a8eb9SGleb Smirnoff sizeof(io.pfiio_name)) { 4333b3a8eb9SGleb Smirnoff errno = EINVAL; 4343b3a8eb9SGleb Smirnoff return (-1); 4353b3a8eb9SGleb Smirnoff } 4363b3a8eb9SGleb Smirnoff io.pfiio_buffer = buf; 4373b3a8eb9SGleb Smirnoff io.pfiio_esize = sizeof(*buf); 4383b3a8eb9SGleb Smirnoff io.pfiio_size = *size; 4393b3a8eb9SGleb Smirnoff if (ioctl(dev, DIOCIGETIFACES, &io)) 4403b3a8eb9SGleb Smirnoff return (-1); 4413b3a8eb9SGleb Smirnoff *size = io.pfiio_size; 4423b3a8eb9SGleb Smirnoff return (0); 4433b3a8eb9SGleb Smirnoff } 4443b3a8eb9SGleb Smirnoff 4453b3a8eb9SGleb Smirnoff /* buffer management code */ 4463b3a8eb9SGleb Smirnoff 44772a3cf0fSKristof Provost const size_t buf_esize[PFRB_MAX] = { 0, 4483b3a8eb9SGleb Smirnoff sizeof(struct pfr_table), sizeof(struct pfr_tstats), 4493b3a8eb9SGleb Smirnoff sizeof(struct pfr_addr), sizeof(struct pfr_astats), 4503b3a8eb9SGleb Smirnoff sizeof(struct pfi_kif), sizeof(struct pfioc_trans_e) 4513b3a8eb9SGleb Smirnoff }; 4523b3a8eb9SGleb Smirnoff 4533b3a8eb9SGleb Smirnoff /* 4543b3a8eb9SGleb Smirnoff * add one element to the buffer 4553b3a8eb9SGleb Smirnoff */ 4563b3a8eb9SGleb Smirnoff int 4573b3a8eb9SGleb Smirnoff pfr_buf_add(struct pfr_buffer *b, const void *e) 4583b3a8eb9SGleb Smirnoff { 4593b3a8eb9SGleb Smirnoff size_t bs; 4603b3a8eb9SGleb Smirnoff 4613b3a8eb9SGleb Smirnoff if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX || 4623b3a8eb9SGleb Smirnoff e == NULL) { 4633b3a8eb9SGleb Smirnoff errno = EINVAL; 4643b3a8eb9SGleb Smirnoff return (-1); 4653b3a8eb9SGleb Smirnoff } 4663b3a8eb9SGleb Smirnoff bs = buf_esize[b->pfrb_type]; 4673b3a8eb9SGleb Smirnoff if (b->pfrb_size == b->pfrb_msize) 4683b3a8eb9SGleb Smirnoff if (pfr_buf_grow(b, 0)) 4693b3a8eb9SGleb Smirnoff return (-1); 4703b3a8eb9SGleb Smirnoff memcpy(((caddr_t)b->pfrb_caddr) + bs * b->pfrb_size, e, bs); 4713b3a8eb9SGleb Smirnoff b->pfrb_size++; 4723b3a8eb9SGleb Smirnoff return (0); 4733b3a8eb9SGleb Smirnoff } 4743b3a8eb9SGleb Smirnoff 4753b3a8eb9SGleb Smirnoff /* 4763b3a8eb9SGleb Smirnoff * return next element of the buffer (or first one if prev is NULL) 4773b3a8eb9SGleb Smirnoff * see PFRB_FOREACH macro 4783b3a8eb9SGleb Smirnoff */ 4793b3a8eb9SGleb Smirnoff void * 4803b3a8eb9SGleb Smirnoff pfr_buf_next(struct pfr_buffer *b, const void *prev) 4813b3a8eb9SGleb Smirnoff { 4823b3a8eb9SGleb Smirnoff size_t bs; 4833b3a8eb9SGleb Smirnoff 4843b3a8eb9SGleb Smirnoff if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX) 4853b3a8eb9SGleb Smirnoff return (NULL); 4863b3a8eb9SGleb Smirnoff if (b->pfrb_size == 0) 4873b3a8eb9SGleb Smirnoff return (NULL); 4883b3a8eb9SGleb Smirnoff if (prev == NULL) 4893b3a8eb9SGleb Smirnoff return (b->pfrb_caddr); 4903b3a8eb9SGleb Smirnoff bs = buf_esize[b->pfrb_type]; 4913b3a8eb9SGleb Smirnoff if ((((caddr_t)prev)-((caddr_t)b->pfrb_caddr)) / bs >= b->pfrb_size-1) 4923b3a8eb9SGleb Smirnoff return (NULL); 4933b3a8eb9SGleb Smirnoff return (((caddr_t)prev) + bs); 4943b3a8eb9SGleb Smirnoff } 4953b3a8eb9SGleb Smirnoff 4963b3a8eb9SGleb Smirnoff /* 4973b3a8eb9SGleb Smirnoff * minsize: 4983b3a8eb9SGleb Smirnoff * 0: make the buffer somewhat bigger 4993b3a8eb9SGleb Smirnoff * n: make room for "n" entries in the buffer 5003b3a8eb9SGleb Smirnoff */ 5013b3a8eb9SGleb Smirnoff int 5023b3a8eb9SGleb Smirnoff pfr_buf_grow(struct pfr_buffer *b, int minsize) 5033b3a8eb9SGleb Smirnoff { 5043b3a8eb9SGleb Smirnoff caddr_t p; 5053b3a8eb9SGleb Smirnoff size_t bs; 5063b3a8eb9SGleb Smirnoff 5073b3a8eb9SGleb Smirnoff if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX) { 5083b3a8eb9SGleb Smirnoff errno = EINVAL; 5093b3a8eb9SGleb Smirnoff return (-1); 5103b3a8eb9SGleb Smirnoff } 5113b3a8eb9SGleb Smirnoff if (minsize != 0 && minsize <= b->pfrb_msize) 5123b3a8eb9SGleb Smirnoff return (0); 5133b3a8eb9SGleb Smirnoff bs = buf_esize[b->pfrb_type]; 5143b3a8eb9SGleb Smirnoff if (!b->pfrb_msize) { 5153b3a8eb9SGleb Smirnoff if (minsize < 64) 5163b3a8eb9SGleb Smirnoff minsize = 64; 5173b3a8eb9SGleb Smirnoff b->pfrb_caddr = calloc(bs, minsize); 5183b3a8eb9SGleb Smirnoff if (b->pfrb_caddr == NULL) 5193b3a8eb9SGleb Smirnoff return (-1); 5203b3a8eb9SGleb Smirnoff b->pfrb_msize = minsize; 5213b3a8eb9SGleb Smirnoff } else { 5223b3a8eb9SGleb Smirnoff if (minsize == 0) 5233b3a8eb9SGleb Smirnoff minsize = b->pfrb_msize * 2; 5243b3a8eb9SGleb Smirnoff if (minsize < 0 || minsize >= SIZE_T_MAX / bs) { 5253b3a8eb9SGleb Smirnoff /* msize overflow */ 5263b3a8eb9SGleb Smirnoff errno = ENOMEM; 5273b3a8eb9SGleb Smirnoff return (-1); 5283b3a8eb9SGleb Smirnoff } 5293b3a8eb9SGleb Smirnoff p = realloc(b->pfrb_caddr, minsize * bs); 5303b3a8eb9SGleb Smirnoff if (p == NULL) 5313b3a8eb9SGleb Smirnoff return (-1); 5323b3a8eb9SGleb Smirnoff bzero(p + b->pfrb_msize * bs, (minsize - b->pfrb_msize) * bs); 5333b3a8eb9SGleb Smirnoff b->pfrb_caddr = p; 5343b3a8eb9SGleb Smirnoff b->pfrb_msize = minsize; 5353b3a8eb9SGleb Smirnoff } 5363b3a8eb9SGleb Smirnoff return (0); 5373b3a8eb9SGleb Smirnoff } 5383b3a8eb9SGleb Smirnoff 5393b3a8eb9SGleb Smirnoff /* 5403b3a8eb9SGleb Smirnoff * reset buffer and free memory. 5413b3a8eb9SGleb Smirnoff */ 5423b3a8eb9SGleb Smirnoff void 5433b3a8eb9SGleb Smirnoff pfr_buf_clear(struct pfr_buffer *b) 5443b3a8eb9SGleb Smirnoff { 5453b3a8eb9SGleb Smirnoff if (b == NULL) 5463b3a8eb9SGleb Smirnoff return; 5473b3a8eb9SGleb Smirnoff if (b->pfrb_caddr != NULL) 5483b3a8eb9SGleb Smirnoff free(b->pfrb_caddr); 5493b3a8eb9SGleb Smirnoff b->pfrb_caddr = NULL; 5503b3a8eb9SGleb Smirnoff b->pfrb_size = b->pfrb_msize = 0; 5513b3a8eb9SGleb Smirnoff } 5523b3a8eb9SGleb Smirnoff 5533b3a8eb9SGleb Smirnoff int 5543b3a8eb9SGleb Smirnoff pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork, 5553b3a8eb9SGleb Smirnoff int (*append_addr)(struct pfr_buffer *, char *, int)) 5563b3a8eb9SGleb Smirnoff { 5573b3a8eb9SGleb Smirnoff FILE *fp; 5583b3a8eb9SGleb Smirnoff char buf[BUF_SIZE]; 5593b3a8eb9SGleb Smirnoff int rv; 5603b3a8eb9SGleb Smirnoff 5613b3a8eb9SGleb Smirnoff if (file == NULL) 5623b3a8eb9SGleb Smirnoff return (0); 5633b3a8eb9SGleb Smirnoff if (!strcmp(file, "-")) 5643b3a8eb9SGleb Smirnoff fp = stdin; 5653b3a8eb9SGleb Smirnoff else { 5663b3a8eb9SGleb Smirnoff fp = pfctl_fopen(file, "r"); 5673b3a8eb9SGleb Smirnoff if (fp == NULL) 5683b3a8eb9SGleb Smirnoff return (-1); 5693b3a8eb9SGleb Smirnoff } 5703b3a8eb9SGleb Smirnoff while ((rv = pfr_next_token(buf, fp)) == 1) 5713b3a8eb9SGleb Smirnoff if (append_addr(b, buf, nonetwork)) { 5723b3a8eb9SGleb Smirnoff rv = -1; 5733b3a8eb9SGleb Smirnoff break; 5743b3a8eb9SGleb Smirnoff } 5753b3a8eb9SGleb Smirnoff if (fp != stdin) 5763b3a8eb9SGleb Smirnoff fclose(fp); 5773b3a8eb9SGleb Smirnoff return (rv); 5783b3a8eb9SGleb Smirnoff } 5793b3a8eb9SGleb Smirnoff 5803b3a8eb9SGleb Smirnoff int 5813b3a8eb9SGleb Smirnoff pfr_next_token(char buf[BUF_SIZE], FILE *fp) 5823b3a8eb9SGleb Smirnoff { 5833b3a8eb9SGleb Smirnoff static char next_ch = ' '; 5843b3a8eb9SGleb Smirnoff int i = 0; 5853b3a8eb9SGleb Smirnoff 5863b3a8eb9SGleb Smirnoff for (;;) { 5873b3a8eb9SGleb Smirnoff /* skip spaces */ 5883b3a8eb9SGleb Smirnoff while (isspace(next_ch) && !feof(fp)) 5893b3a8eb9SGleb Smirnoff next_ch = fgetc(fp); 5903b3a8eb9SGleb Smirnoff /* remove from '#' until end of line */ 5913b3a8eb9SGleb Smirnoff if (next_ch == '#') 5923b3a8eb9SGleb Smirnoff while (!feof(fp)) { 5933b3a8eb9SGleb Smirnoff next_ch = fgetc(fp); 5943b3a8eb9SGleb Smirnoff if (next_ch == '\n') 5953b3a8eb9SGleb Smirnoff break; 5963b3a8eb9SGleb Smirnoff } 5973b3a8eb9SGleb Smirnoff else 5983b3a8eb9SGleb Smirnoff break; 5993b3a8eb9SGleb Smirnoff } 6003b3a8eb9SGleb Smirnoff if (feof(fp)) { 6013b3a8eb9SGleb Smirnoff next_ch = ' '; 6023b3a8eb9SGleb Smirnoff return (0); 6033b3a8eb9SGleb Smirnoff } 6043b3a8eb9SGleb Smirnoff do { 6053b3a8eb9SGleb Smirnoff if (i < BUF_SIZE) 6063b3a8eb9SGleb Smirnoff buf[i++] = next_ch; 6073b3a8eb9SGleb Smirnoff next_ch = fgetc(fp); 6083b3a8eb9SGleb Smirnoff } while (!feof(fp) && !isspace(next_ch)); 6093b3a8eb9SGleb Smirnoff if (i >= BUF_SIZE) { 6103b3a8eb9SGleb Smirnoff errno = EINVAL; 6113b3a8eb9SGleb Smirnoff return (-1); 6123b3a8eb9SGleb Smirnoff } 6133b3a8eb9SGleb Smirnoff buf[i] = '\0'; 6143b3a8eb9SGleb Smirnoff return (1); 6153b3a8eb9SGleb Smirnoff } 6163b3a8eb9SGleb Smirnoff 6173b3a8eb9SGleb Smirnoff char * 6183b3a8eb9SGleb Smirnoff pfr_strerror(int errnum) 6193b3a8eb9SGleb Smirnoff { 6203b3a8eb9SGleb Smirnoff switch (errnum) { 6213b3a8eb9SGleb Smirnoff case ESRCH: 6223b3a8eb9SGleb Smirnoff return "Table does not exist"; 6233b3a8eb9SGleb Smirnoff case ENOENT: 6243b3a8eb9SGleb Smirnoff return "Anchor or Ruleset does not exist"; 6253b3a8eb9SGleb Smirnoff default: 6263b3a8eb9SGleb Smirnoff return strerror(errnum); 6273b3a8eb9SGleb Smirnoff } 6283b3a8eb9SGleb Smirnoff } 629