xref: /freebsd/sbin/pfctl/pfctl_radix.c (revision 3c7fbb06a0d440aaeca539be76054a9265f89e40)
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