xref: /freebsd-src/sbin/pfctl/pfctl_radix.c (revision 441d489493e8a1e2658306f1a4c709a0b18cc78b)
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/types.h>
363b3a8eb9SGleb Smirnoff #include <sys/ioctl.h>
373b3a8eb9SGleb Smirnoff #include <sys/socket.h>
383b3a8eb9SGleb Smirnoff 
393b3a8eb9SGleb Smirnoff #include <net/if.h>
403b3a8eb9SGleb Smirnoff #include <net/pfvar.h>
413b3a8eb9SGleb Smirnoff 
423b3a8eb9SGleb Smirnoff #include <errno.h>
433b3a8eb9SGleb Smirnoff #include <string.h>
443b3a8eb9SGleb Smirnoff #include <ctype.h>
453b3a8eb9SGleb Smirnoff #include <stdio.h>
463b3a8eb9SGleb Smirnoff #include <stdlib.h>
473b3a8eb9SGleb Smirnoff #include <limits.h>
483b3a8eb9SGleb Smirnoff #include <err.h>
493b3a8eb9SGleb Smirnoff 
503b3a8eb9SGleb Smirnoff #include "pfctl.h"
513b3a8eb9SGleb Smirnoff 
523b3a8eb9SGleb Smirnoff #define BUF_SIZE 256
533b3a8eb9SGleb Smirnoff 
543b3a8eb9SGleb Smirnoff extern int dev;
553b3a8eb9SGleb Smirnoff 
56d74024a4SJohn Baldwin static int	 pfr_next_token(char buf[BUF_SIZE], FILE *);
573b3a8eb9SGleb Smirnoff 
583c7fbb06SKristof Provost static void
593c7fbb06SKristof Provost pfr_report_error(struct pfr_table *tbl, struct pfioc_table *io,
603c7fbb06SKristof Provost     const char *err)
613c7fbb06SKristof Provost {
623c7fbb06SKristof Provost 	unsigned long maxcount;
633c7fbb06SKristof Provost 	size_t s;
643c7fbb06SKristof Provost 
653c7fbb06SKristof Provost 	s = sizeof(maxcount);
663c7fbb06SKristof Provost 	if (sysctlbyname("net.pf.request_maxcount", &maxcount, &s, NULL,
673c7fbb06SKristof Provost 	    0) == -1)
683c7fbb06SKristof Provost 		return;
693c7fbb06SKristof Provost 
703c7fbb06SKristof Provost 	if (io->pfrio_size > maxcount || io->pfrio_size2 > maxcount)
713c7fbb06SKristof Provost 		fprintf(stderr, "cannot %s %s: too many elements.\n"
723c7fbb06SKristof Provost 		    "Consider increasing net.pf.request_maxcount.",
733c7fbb06SKristof Provost 		    err, tbl->pfrt_name);
743c7fbb06SKristof Provost }
753b3a8eb9SGleb Smirnoff 
763b3a8eb9SGleb Smirnoff int
773b3a8eb9SGleb Smirnoff pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
783b3a8eb9SGleb Smirnoff {
793b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
803b3a8eb9SGleb Smirnoff 
813b3a8eb9SGleb Smirnoff 	if (size < 0 || (size && tbl == NULL)) {
823b3a8eb9SGleb Smirnoff 		errno = EINVAL;
833b3a8eb9SGleb Smirnoff 		return (-1);
843b3a8eb9SGleb Smirnoff 	}
853b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
863b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
873b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = tbl;
883b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*tbl);
893b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
903c7fbb06SKristof Provost 	if (ioctl(dev, DIOCRADDTABLES, &io)) {
913c7fbb06SKristof Provost 		pfr_report_error(tbl, &io, "add table");
923b3a8eb9SGleb Smirnoff 		return (-1);
933c7fbb06SKristof Provost 	}
943b3a8eb9SGleb Smirnoff 	if (nadd != NULL)
953b3a8eb9SGleb Smirnoff 		*nadd = io.pfrio_nadd;
963b3a8eb9SGleb Smirnoff 	return (0);
973b3a8eb9SGleb Smirnoff }
983b3a8eb9SGleb Smirnoff 
993b3a8eb9SGleb Smirnoff int
1003b3a8eb9SGleb Smirnoff pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
1013b3a8eb9SGleb Smirnoff {
1023b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
1033b3a8eb9SGleb Smirnoff 
1043b3a8eb9SGleb Smirnoff 	if (size < 0 || (size && tbl == NULL)) {
1053b3a8eb9SGleb Smirnoff 		errno = EINVAL;
1063b3a8eb9SGleb Smirnoff 		return (-1);
1073b3a8eb9SGleb Smirnoff 	}
1083b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
1093b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
1103b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = tbl;
1113b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*tbl);
1123b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
1133c7fbb06SKristof Provost 	if (ioctl(dev, DIOCRDELTABLES, &io)) {
1143c7fbb06SKristof Provost 		pfr_report_error(tbl, &io, "delete table");
1153b3a8eb9SGleb Smirnoff 		return (-1);
1163c7fbb06SKristof Provost 	}
1173b3a8eb9SGleb Smirnoff 	if (ndel != NULL)
1183b3a8eb9SGleb Smirnoff 		*ndel = io.pfrio_ndel;
1193b3a8eb9SGleb Smirnoff 	return (0);
1203b3a8eb9SGleb Smirnoff }
1213b3a8eb9SGleb Smirnoff 
1223b3a8eb9SGleb Smirnoff int
1233b3a8eb9SGleb Smirnoff pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
1243b3a8eb9SGleb Smirnoff 	int flags)
1253b3a8eb9SGleb Smirnoff {
1263b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
1273b3a8eb9SGleb Smirnoff 
1283b3a8eb9SGleb Smirnoff 	if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
1293b3a8eb9SGleb Smirnoff 		errno = EINVAL;
1303b3a8eb9SGleb Smirnoff 		return (-1);
1313b3a8eb9SGleb Smirnoff 	}
1323b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
1333b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
1343b3a8eb9SGleb Smirnoff 	if (filter != NULL)
1353b3a8eb9SGleb Smirnoff 		io.pfrio_table = *filter;
1363b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = tbl;
1373b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*tbl);
1383b3a8eb9SGleb Smirnoff 	io.pfrio_size = *size;
1393c7fbb06SKristof Provost 	if (ioctl(dev, DIOCRGETTABLES, &io)) {
1403c7fbb06SKristof Provost 		pfr_report_error(tbl, &io, "get table");
1413b3a8eb9SGleb Smirnoff 		return (-1);
1423c7fbb06SKristof Provost 	}
1433b3a8eb9SGleb Smirnoff 	*size = io.pfrio_size;
1443b3a8eb9SGleb Smirnoff 	return (0);
1453b3a8eb9SGleb Smirnoff }
1463b3a8eb9SGleb Smirnoff 
1473b3a8eb9SGleb Smirnoff int
1483b3a8eb9SGleb Smirnoff pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
1493b3a8eb9SGleb Smirnoff 	int flags)
1503b3a8eb9SGleb Smirnoff {
1513b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
1523b3a8eb9SGleb Smirnoff 
1533b3a8eb9SGleb Smirnoff 	if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
1543b3a8eb9SGleb Smirnoff 		errno = EINVAL;
1553b3a8eb9SGleb Smirnoff 		return (-1);
1563b3a8eb9SGleb Smirnoff 	}
1573b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
1583b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
1593b3a8eb9SGleb Smirnoff 	if (filter != NULL)
1603b3a8eb9SGleb Smirnoff 		io.pfrio_table = *filter;
1613b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = tbl;
1623b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*tbl);
1633b3a8eb9SGleb Smirnoff 	io.pfrio_size = *size;
1643c7fbb06SKristof Provost 	if (ioctl(dev, DIOCRGETTSTATS, &io)) {
1653c7fbb06SKristof Provost 		pfr_report_error(filter, &io, "get tstats for");
1663b3a8eb9SGleb Smirnoff 		return (-1);
1673c7fbb06SKristof Provost 	}
1683b3a8eb9SGleb Smirnoff 	*size = io.pfrio_size;
1693b3a8eb9SGleb Smirnoff 	return (0);
1703b3a8eb9SGleb Smirnoff }
1713b3a8eb9SGleb Smirnoff 
1723b3a8eb9SGleb Smirnoff int
1733b3a8eb9SGleb Smirnoff pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
1743b3a8eb9SGleb Smirnoff {
1753b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
1763b3a8eb9SGleb Smirnoff 
1773b3a8eb9SGleb Smirnoff 	if (tbl == NULL) {
1783b3a8eb9SGleb Smirnoff 		errno = EINVAL;
1793b3a8eb9SGleb Smirnoff 		return (-1);
1803b3a8eb9SGleb Smirnoff 	}
1813b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
1823b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
1833b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
1843b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRCLRADDRS, &io))
1853b3a8eb9SGleb Smirnoff 		return (-1);
1863b3a8eb9SGleb Smirnoff 	if (ndel != NULL)
1873b3a8eb9SGleb Smirnoff 		*ndel = io.pfrio_ndel;
1883b3a8eb9SGleb Smirnoff 	return (0);
1893b3a8eb9SGleb Smirnoff }
1903b3a8eb9SGleb Smirnoff 
1913b3a8eb9SGleb Smirnoff int
1923b3a8eb9SGleb Smirnoff pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
1933b3a8eb9SGleb Smirnoff     int *nadd, int flags)
1943b3a8eb9SGleb Smirnoff {
1954823489aSReid Linnemann 	int ret;
1963b3a8eb9SGleb Smirnoff 
1974823489aSReid Linnemann 	ret = pfctl_table_add_addrs(dev, tbl, addr, size, nadd, flags);
1984823489aSReid Linnemann 	if (ret) {
1994823489aSReid Linnemann 		errno = ret;
2003b3a8eb9SGleb Smirnoff 		return (-1);
2013b3a8eb9SGleb Smirnoff 	}
2023b3a8eb9SGleb Smirnoff 	return (0);
2033b3a8eb9SGleb Smirnoff }
2043b3a8eb9SGleb Smirnoff 
2053b3a8eb9SGleb Smirnoff int
2063b3a8eb9SGleb Smirnoff pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
2073b3a8eb9SGleb Smirnoff     int *ndel, int flags)
2083b3a8eb9SGleb Smirnoff {
2094823489aSReid Linnemann 	int ret;
2103b3a8eb9SGleb Smirnoff 
2114823489aSReid Linnemann 	ret = pfctl_table_del_addrs(dev, tbl, addr, size, ndel, flags);
2124823489aSReid Linnemann 	if (ret) {
2134823489aSReid Linnemann 		errno = ret;
2143b3a8eb9SGleb Smirnoff 		return (-1);
2153b3a8eb9SGleb Smirnoff 	}
2163b3a8eb9SGleb Smirnoff 	return (0);
2173b3a8eb9SGleb Smirnoff }
2183b3a8eb9SGleb Smirnoff 
2193b3a8eb9SGleb Smirnoff int
2203b3a8eb9SGleb Smirnoff pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
2213b3a8eb9SGleb Smirnoff     int *size2, int *nadd, int *ndel, int *nchange, int flags)
2223b3a8eb9SGleb Smirnoff {
2234823489aSReid Linnemann 	int ret;
2243b3a8eb9SGleb Smirnoff 
2254823489aSReid Linnemann 	ret = pfctl_table_set_addrs(dev, tbl, addr, size, size2, nadd, ndel,
2264823489aSReid Linnemann 	    nchange, flags);
2274823489aSReid Linnemann 	if (ret) {
2284823489aSReid Linnemann 		errno = ret;
2293b3a8eb9SGleb Smirnoff 		return (-1);
2303b3a8eb9SGleb Smirnoff 	}
2313b3a8eb9SGleb Smirnoff 	return (0);
2323b3a8eb9SGleb Smirnoff }
2333b3a8eb9SGleb Smirnoff 
2343b3a8eb9SGleb Smirnoff int
2353b3a8eb9SGleb Smirnoff pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
2363b3a8eb9SGleb Smirnoff     int flags)
2373b3a8eb9SGleb Smirnoff {
2384823489aSReid Linnemann 	int ret;
2393b3a8eb9SGleb Smirnoff 
2404823489aSReid Linnemann 	ret = pfctl_table_get_addrs(dev, tbl, addr, size, flags);
2414823489aSReid Linnemann 	if (ret) {
2424823489aSReid Linnemann 		errno = ret;
2433b3a8eb9SGleb Smirnoff 		return (-1);
2443b3a8eb9SGleb Smirnoff 	}
2453b3a8eb9SGleb Smirnoff 	return (0);
2463b3a8eb9SGleb Smirnoff }
2473b3a8eb9SGleb Smirnoff 
2483b3a8eb9SGleb Smirnoff int
2493b3a8eb9SGleb Smirnoff pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
2503b3a8eb9SGleb Smirnoff     int flags)
2513b3a8eb9SGleb Smirnoff {
2523b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
2533b3a8eb9SGleb Smirnoff 
2543b3a8eb9SGleb Smirnoff 	if (tbl == NULL || size == NULL || *size < 0 ||
2553b3a8eb9SGleb Smirnoff 	    (*size && addr == NULL)) {
2563b3a8eb9SGleb Smirnoff 		errno = EINVAL;
2573b3a8eb9SGleb Smirnoff 		return (-1);
2583b3a8eb9SGleb Smirnoff 	}
2593b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
2603b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
2613b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
2623b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = addr;
2633b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*addr);
2643b3a8eb9SGleb Smirnoff 	io.pfrio_size = *size;
2653c7fbb06SKristof Provost 	if (ioctl(dev, DIOCRGETASTATS, &io)) {
2663c7fbb06SKristof Provost 		pfr_report_error(tbl, &io, "get astats from");
2673b3a8eb9SGleb Smirnoff 		return (-1);
2683c7fbb06SKristof Provost 	}
2693b3a8eb9SGleb Smirnoff 	*size = io.pfrio_size;
2703b3a8eb9SGleb Smirnoff 	return (0);
2713b3a8eb9SGleb Smirnoff }
2723b3a8eb9SGleb Smirnoff 
2733b3a8eb9SGleb Smirnoff int
2746463b6b5SKristof Provost pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
2756463b6b5SKristof Provost     int *nzero, int flags)
2766463b6b5SKristof Provost {
2776463b6b5SKristof Provost 	struct pfioc_table io;
2786463b6b5SKristof Provost 
279*5b59b0c6SLeonid Evdokimov 	if (size < 0 || !tbl || (size && !addr)) {
2806463b6b5SKristof Provost 		errno = EINVAL;
2816463b6b5SKristof Provost 		return (-1);
2826463b6b5SKristof Provost 	}
2836463b6b5SKristof Provost 	bzero(&io, sizeof io);
2846463b6b5SKristof Provost 	io.pfrio_flags = flags;
2856463b6b5SKristof Provost 	io.pfrio_table = *tbl;
2866463b6b5SKristof Provost 	io.pfrio_buffer = addr;
2876463b6b5SKristof Provost 	io.pfrio_esize = sizeof(*addr);
2886463b6b5SKristof Provost 	io.pfrio_size = size;
2896463b6b5SKristof Provost 	if (ioctl(dev, DIOCRCLRASTATS, &io) == -1)
2906463b6b5SKristof Provost 		return (-1);
2916463b6b5SKristof Provost 	if (nzero)
2926463b6b5SKristof Provost 		*nzero = io.pfrio_nzero;
2936463b6b5SKristof Provost 	return (0);
2946463b6b5SKristof Provost }
2956463b6b5SKristof Provost 
2966463b6b5SKristof Provost int
2973b3a8eb9SGleb Smirnoff pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
2983b3a8eb9SGleb Smirnoff {
2993b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
3003b3a8eb9SGleb Smirnoff 
3013b3a8eb9SGleb Smirnoff 	if (size < 0 || (size && !tbl)) {
3023b3a8eb9SGleb Smirnoff 		errno = EINVAL;
3033b3a8eb9SGleb Smirnoff 		return (-1);
3043b3a8eb9SGleb Smirnoff 	}
3053b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
3063b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
3073b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = tbl;
3083b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*tbl);
3093b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
3103c7fbb06SKristof Provost 	if (ioctl(dev, DIOCRCLRTSTATS, &io)) {
3113c7fbb06SKristof Provost 		pfr_report_error(tbl, &io, "clear tstats from");
3123b3a8eb9SGleb Smirnoff 		return (-1);
3133c7fbb06SKristof Provost 	}
3143b3a8eb9SGleb Smirnoff 	if (nzero)
3153b3a8eb9SGleb Smirnoff 		*nzero = io.pfrio_nzero;
3163b3a8eb9SGleb Smirnoff 	return (0);
3173b3a8eb9SGleb Smirnoff }
3183b3a8eb9SGleb Smirnoff 
3193b3a8eb9SGleb Smirnoff int
3203b3a8eb9SGleb Smirnoff pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
3213b3a8eb9SGleb Smirnoff     int *nmatch, int flags)
3223b3a8eb9SGleb Smirnoff {
3233b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
3243b3a8eb9SGleb Smirnoff 
3253b3a8eb9SGleb Smirnoff 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
3263b3a8eb9SGleb Smirnoff 		errno = EINVAL;
3273b3a8eb9SGleb Smirnoff 		return (-1);
3283b3a8eb9SGleb Smirnoff 	}
3293b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
3303b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
3313b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
3323b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = addr;
3333b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*addr);
3343b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
3353c7fbb06SKristof Provost 	if (ioctl(dev, DIOCRTSTADDRS, &io)) {
3363c7fbb06SKristof Provost 		pfr_report_error(tbl, &io, "test addresses in");
3373b3a8eb9SGleb Smirnoff 		return (-1);
3383c7fbb06SKristof Provost 	}
3393b3a8eb9SGleb Smirnoff 	if (nmatch)
3403b3a8eb9SGleb Smirnoff 		*nmatch = io.pfrio_nmatch;
3413b3a8eb9SGleb Smirnoff 	return (0);
3423b3a8eb9SGleb Smirnoff }
3433b3a8eb9SGleb Smirnoff 
3443b3a8eb9SGleb Smirnoff int
3453b3a8eb9SGleb Smirnoff pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
3463b3a8eb9SGleb Smirnoff     int *nadd, int *naddr, int ticket, int flags)
3473b3a8eb9SGleb Smirnoff {
3483b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
3493b3a8eb9SGleb Smirnoff 
3503b3a8eb9SGleb Smirnoff 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
3513b3a8eb9SGleb Smirnoff 		errno = EINVAL;
3523b3a8eb9SGleb Smirnoff 		return (-1);
3533b3a8eb9SGleb Smirnoff 	}
3543b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
3553b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
3563b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
3573b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = addr;
3583b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*addr);
3593b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
3603b3a8eb9SGleb Smirnoff 	io.pfrio_ticket = ticket;
3613c7fbb06SKristof Provost 	if (ioctl(dev, DIOCRINADEFINE, &io)) {
3623c7fbb06SKristof Provost 		pfr_report_error(tbl, &io, "define inactive set table");
3633b3a8eb9SGleb Smirnoff 		return (-1);
3643c7fbb06SKristof Provost 	}
3653b3a8eb9SGleb Smirnoff 	if (nadd != NULL)
3663b3a8eb9SGleb Smirnoff 		*nadd = io.pfrio_nadd;
3673b3a8eb9SGleb Smirnoff 	if (naddr != NULL)
3683b3a8eb9SGleb Smirnoff 		*naddr = io.pfrio_naddr;
3693b3a8eb9SGleb Smirnoff 	return (0);
3703b3a8eb9SGleb Smirnoff }
3713b3a8eb9SGleb Smirnoff 
3723b3a8eb9SGleb Smirnoff /* interface management code */
3733b3a8eb9SGleb Smirnoff 
3743b3a8eb9SGleb Smirnoff int
3753b3a8eb9SGleb Smirnoff pfi_get_ifaces(const char *filter, struct pfi_kif *buf, int *size)
3763b3a8eb9SGleb Smirnoff {
3773b3a8eb9SGleb Smirnoff 	struct pfioc_iface io;
3783b3a8eb9SGleb Smirnoff 
3793b3a8eb9SGleb Smirnoff 	if (size == NULL || *size < 0 || (*size && buf == NULL)) {
3803b3a8eb9SGleb Smirnoff 		errno = EINVAL;
3813b3a8eb9SGleb Smirnoff 		return (-1);
3823b3a8eb9SGleb Smirnoff 	}
3833b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
3843b3a8eb9SGleb Smirnoff 	if (filter != NULL)
3853b3a8eb9SGleb Smirnoff 		if (strlcpy(io.pfiio_name, filter, sizeof(io.pfiio_name)) >=
3863b3a8eb9SGleb Smirnoff 		    sizeof(io.pfiio_name)) {
3873b3a8eb9SGleb Smirnoff 			errno = EINVAL;
3883b3a8eb9SGleb Smirnoff 			return (-1);
3893b3a8eb9SGleb Smirnoff 		}
3903b3a8eb9SGleb Smirnoff 	io.pfiio_buffer = buf;
3913b3a8eb9SGleb Smirnoff 	io.pfiio_esize = sizeof(*buf);
3923b3a8eb9SGleb Smirnoff 	io.pfiio_size = *size;
3933b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCIGETIFACES, &io))
3943b3a8eb9SGleb Smirnoff 		return (-1);
3953b3a8eb9SGleb Smirnoff 	*size = io.pfiio_size;
3963b3a8eb9SGleb Smirnoff 	return (0);
3973b3a8eb9SGleb Smirnoff }
3983b3a8eb9SGleb Smirnoff 
3993b3a8eb9SGleb Smirnoff /* buffer management code */
4003b3a8eb9SGleb Smirnoff 
40172a3cf0fSKristof Provost const size_t buf_esize[PFRB_MAX] = { 0,
4023b3a8eb9SGleb Smirnoff 	sizeof(struct pfr_table), sizeof(struct pfr_tstats),
4033b3a8eb9SGleb Smirnoff 	sizeof(struct pfr_addr), sizeof(struct pfr_astats),
4043b3a8eb9SGleb Smirnoff 	sizeof(struct pfi_kif), sizeof(struct pfioc_trans_e)
4053b3a8eb9SGleb Smirnoff };
4063b3a8eb9SGleb Smirnoff 
4073b3a8eb9SGleb Smirnoff /*
4083b3a8eb9SGleb Smirnoff  * add one element to the buffer
4093b3a8eb9SGleb Smirnoff  */
4103b3a8eb9SGleb Smirnoff int
4113b3a8eb9SGleb Smirnoff pfr_buf_add(struct pfr_buffer *b, const void *e)
4123b3a8eb9SGleb Smirnoff {
4133b3a8eb9SGleb Smirnoff 	size_t bs;
4143b3a8eb9SGleb Smirnoff 
4153b3a8eb9SGleb Smirnoff 	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX ||
4163b3a8eb9SGleb Smirnoff 	    e == NULL) {
4173b3a8eb9SGleb Smirnoff 		errno = EINVAL;
4183b3a8eb9SGleb Smirnoff 		return (-1);
4193b3a8eb9SGleb Smirnoff 	}
4203b3a8eb9SGleb Smirnoff 	bs = buf_esize[b->pfrb_type];
4213b3a8eb9SGleb Smirnoff 	if (b->pfrb_size == b->pfrb_msize)
4223b3a8eb9SGleb Smirnoff 		if (pfr_buf_grow(b, 0))
4233b3a8eb9SGleb Smirnoff 			return (-1);
4243b3a8eb9SGleb Smirnoff 	memcpy(((caddr_t)b->pfrb_caddr) + bs * b->pfrb_size, e, bs);
4253b3a8eb9SGleb Smirnoff 	b->pfrb_size++;
4263b3a8eb9SGleb Smirnoff 	return (0);
4273b3a8eb9SGleb Smirnoff }
4283b3a8eb9SGleb Smirnoff 
4293b3a8eb9SGleb Smirnoff /*
4303b3a8eb9SGleb Smirnoff  * return next element of the buffer (or first one if prev is NULL)
4313b3a8eb9SGleb Smirnoff  * see PFRB_FOREACH macro
4323b3a8eb9SGleb Smirnoff  */
4333b3a8eb9SGleb Smirnoff void *
4343b3a8eb9SGleb Smirnoff pfr_buf_next(struct pfr_buffer *b, const void *prev)
4353b3a8eb9SGleb Smirnoff {
4363b3a8eb9SGleb Smirnoff 	size_t bs;
4373b3a8eb9SGleb Smirnoff 
4383b3a8eb9SGleb Smirnoff 	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX)
4393b3a8eb9SGleb Smirnoff 		return (NULL);
4403b3a8eb9SGleb Smirnoff 	if (b->pfrb_size == 0)
4413b3a8eb9SGleb Smirnoff 		return (NULL);
4423b3a8eb9SGleb Smirnoff 	if (prev == NULL)
4433b3a8eb9SGleb Smirnoff 		return (b->pfrb_caddr);
4443b3a8eb9SGleb Smirnoff 	bs = buf_esize[b->pfrb_type];
4453b3a8eb9SGleb Smirnoff 	if ((((caddr_t)prev)-((caddr_t)b->pfrb_caddr)) / bs >= b->pfrb_size-1)
4463b3a8eb9SGleb Smirnoff 		return (NULL);
4473b3a8eb9SGleb Smirnoff 	return (((caddr_t)prev) + bs);
4483b3a8eb9SGleb Smirnoff }
4493b3a8eb9SGleb Smirnoff 
4503b3a8eb9SGleb Smirnoff /*
4513b3a8eb9SGleb Smirnoff  * minsize:
4523b3a8eb9SGleb Smirnoff  *    0: make the buffer somewhat bigger
4533b3a8eb9SGleb Smirnoff  *    n: make room for "n" entries in the buffer
4543b3a8eb9SGleb Smirnoff  */
4553b3a8eb9SGleb Smirnoff int
4563b3a8eb9SGleb Smirnoff pfr_buf_grow(struct pfr_buffer *b, int minsize)
4573b3a8eb9SGleb Smirnoff {
4583b3a8eb9SGleb Smirnoff 	caddr_t p;
4593b3a8eb9SGleb Smirnoff 	size_t bs;
4603b3a8eb9SGleb Smirnoff 
4613b3a8eb9SGleb Smirnoff 	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX) {
4623b3a8eb9SGleb Smirnoff 		errno = EINVAL;
4633b3a8eb9SGleb Smirnoff 		return (-1);
4643b3a8eb9SGleb Smirnoff 	}
4653b3a8eb9SGleb Smirnoff 	if (minsize != 0 && minsize <= b->pfrb_msize)
4663b3a8eb9SGleb Smirnoff 		return (0);
4673b3a8eb9SGleb Smirnoff 	bs = buf_esize[b->pfrb_type];
4683b3a8eb9SGleb Smirnoff 	if (!b->pfrb_msize) {
4693b3a8eb9SGleb Smirnoff 		if (minsize < 64)
4703b3a8eb9SGleb Smirnoff 			minsize = 64;
4713b3a8eb9SGleb Smirnoff 		b->pfrb_caddr = calloc(bs, minsize);
4723b3a8eb9SGleb Smirnoff 		if (b->pfrb_caddr == NULL)
4733b3a8eb9SGleb Smirnoff 			return (-1);
4743b3a8eb9SGleb Smirnoff 		b->pfrb_msize = minsize;
4753b3a8eb9SGleb Smirnoff 	} else {
4763b3a8eb9SGleb Smirnoff 		if (minsize == 0)
4773b3a8eb9SGleb Smirnoff 			minsize = b->pfrb_msize * 2;
4783b3a8eb9SGleb Smirnoff 		if (minsize < 0 || minsize >= SIZE_T_MAX / bs) {
4793b3a8eb9SGleb Smirnoff 			/* msize overflow */
4803b3a8eb9SGleb Smirnoff 			errno = ENOMEM;
4813b3a8eb9SGleb Smirnoff 			return (-1);
4823b3a8eb9SGleb Smirnoff 		}
4833b3a8eb9SGleb Smirnoff 		p = realloc(b->pfrb_caddr, minsize * bs);
4843b3a8eb9SGleb Smirnoff 		if (p == NULL)
4853b3a8eb9SGleb Smirnoff 			return (-1);
4863b3a8eb9SGleb Smirnoff 		bzero(p + b->pfrb_msize * bs, (minsize - b->pfrb_msize) * bs);
4873b3a8eb9SGleb Smirnoff 		b->pfrb_caddr = p;
4883b3a8eb9SGleb Smirnoff 		b->pfrb_msize = minsize;
4893b3a8eb9SGleb Smirnoff 	}
4903b3a8eb9SGleb Smirnoff 	return (0);
4913b3a8eb9SGleb Smirnoff }
4923b3a8eb9SGleb Smirnoff 
4933b3a8eb9SGleb Smirnoff /*
4943b3a8eb9SGleb Smirnoff  * reset buffer and free memory.
4953b3a8eb9SGleb Smirnoff  */
4963b3a8eb9SGleb Smirnoff void
4973b3a8eb9SGleb Smirnoff pfr_buf_clear(struct pfr_buffer *b)
4983b3a8eb9SGleb Smirnoff {
4993b3a8eb9SGleb Smirnoff 	if (b == NULL)
5003b3a8eb9SGleb Smirnoff 		return;
5013b3a8eb9SGleb Smirnoff 	if (b->pfrb_caddr != NULL)
5023b3a8eb9SGleb Smirnoff 		free(b->pfrb_caddr);
5033b3a8eb9SGleb Smirnoff 	b->pfrb_caddr = NULL;
5043b3a8eb9SGleb Smirnoff 	b->pfrb_size = b->pfrb_msize = 0;
5053b3a8eb9SGleb Smirnoff }
5063b3a8eb9SGleb Smirnoff 
5073b3a8eb9SGleb Smirnoff int
5083b3a8eb9SGleb Smirnoff pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork,
5093b3a8eb9SGleb Smirnoff     int (*append_addr)(struct pfr_buffer *, char *, int))
5103b3a8eb9SGleb Smirnoff {
5113b3a8eb9SGleb Smirnoff 	FILE	*fp;
5123b3a8eb9SGleb Smirnoff 	char	 buf[BUF_SIZE];
5133b3a8eb9SGleb Smirnoff 	int	 rv;
5143b3a8eb9SGleb Smirnoff 
5153b3a8eb9SGleb Smirnoff 	if (file == NULL)
5163b3a8eb9SGleb Smirnoff 		return (0);
5173b3a8eb9SGleb Smirnoff 	if (!strcmp(file, "-"))
5183b3a8eb9SGleb Smirnoff 		fp = stdin;
5193b3a8eb9SGleb Smirnoff 	else {
5203b3a8eb9SGleb Smirnoff 		fp = pfctl_fopen(file, "r");
5213b3a8eb9SGleb Smirnoff 		if (fp == NULL)
5223b3a8eb9SGleb Smirnoff 			return (-1);
5233b3a8eb9SGleb Smirnoff 	}
5243b3a8eb9SGleb Smirnoff 	while ((rv = pfr_next_token(buf, fp)) == 1)
5253b3a8eb9SGleb Smirnoff 		if (append_addr(b, buf, nonetwork)) {
5263b3a8eb9SGleb Smirnoff 			rv = -1;
5273b3a8eb9SGleb Smirnoff 			break;
5283b3a8eb9SGleb Smirnoff 		}
5293b3a8eb9SGleb Smirnoff 	if (fp != stdin)
5303b3a8eb9SGleb Smirnoff 		fclose(fp);
5313b3a8eb9SGleb Smirnoff 	return (rv);
5323b3a8eb9SGleb Smirnoff }
5333b3a8eb9SGleb Smirnoff 
5343b3a8eb9SGleb Smirnoff int
5353b3a8eb9SGleb Smirnoff pfr_next_token(char buf[BUF_SIZE], FILE *fp)
5363b3a8eb9SGleb Smirnoff {
5373b3a8eb9SGleb Smirnoff 	static char	next_ch = ' ';
5383b3a8eb9SGleb Smirnoff 	int		i = 0;
5393b3a8eb9SGleb Smirnoff 
5403b3a8eb9SGleb Smirnoff 	for (;;) {
5413b3a8eb9SGleb Smirnoff 		/* skip spaces */
5423b3a8eb9SGleb Smirnoff 		while (isspace(next_ch) && !feof(fp))
5433b3a8eb9SGleb Smirnoff 			next_ch = fgetc(fp);
544a8a95277SJuraj Lutter 		/* remove from '#' or ';' until end of line */
545a8a95277SJuraj Lutter 		if (next_ch == '#' || next_ch == ';')
5463b3a8eb9SGleb Smirnoff 			while (!feof(fp)) {
5473b3a8eb9SGleb Smirnoff 				next_ch = fgetc(fp);
5483b3a8eb9SGleb Smirnoff 				if (next_ch == '\n')
5493b3a8eb9SGleb Smirnoff 					break;
5503b3a8eb9SGleb Smirnoff 			}
5513b3a8eb9SGleb Smirnoff 		else
5523b3a8eb9SGleb Smirnoff 			break;
5533b3a8eb9SGleb Smirnoff 	}
5543b3a8eb9SGleb Smirnoff 	if (feof(fp)) {
5553b3a8eb9SGleb Smirnoff 		next_ch = ' ';
5563b3a8eb9SGleb Smirnoff 		return (0);
5573b3a8eb9SGleb Smirnoff 	}
5583b3a8eb9SGleb Smirnoff 	do {
5593b3a8eb9SGleb Smirnoff 		if (i < BUF_SIZE)
5603b3a8eb9SGleb Smirnoff 			buf[i++] = next_ch;
5613b3a8eb9SGleb Smirnoff 		next_ch = fgetc(fp);
5623b3a8eb9SGleb Smirnoff 	} while (!feof(fp) && !isspace(next_ch));
5633b3a8eb9SGleb Smirnoff 	if (i >= BUF_SIZE) {
5643b3a8eb9SGleb Smirnoff 		errno = EINVAL;
5653b3a8eb9SGleb Smirnoff 		return (-1);
5663b3a8eb9SGleb Smirnoff 	}
5673b3a8eb9SGleb Smirnoff 	buf[i] = '\0';
5683b3a8eb9SGleb Smirnoff 	return (1);
5693b3a8eb9SGleb Smirnoff }
5703b3a8eb9SGleb Smirnoff 
5713b3a8eb9SGleb Smirnoff char *
5723b3a8eb9SGleb Smirnoff pfr_strerror(int errnum)
5733b3a8eb9SGleb Smirnoff {
5743b3a8eb9SGleb Smirnoff 	switch (errnum) {
5753b3a8eb9SGleb Smirnoff 	case ESRCH:
5763b3a8eb9SGleb Smirnoff 		return "Table does not exist";
5773b3a8eb9SGleb Smirnoff 	case ENOENT:
5783b3a8eb9SGleb Smirnoff 		return "Anchor or Ruleset does not exist";
5793b3a8eb9SGleb Smirnoff 	default:
5803b3a8eb9SGleb Smirnoff 		return strerror(errnum);
5813b3a8eb9SGleb Smirnoff 	}
5823b3a8eb9SGleb Smirnoff }
583