xref: /freebsd/sbin/pfctl/pfctl_radix.c (revision a8a95277363be2c92b3c06bd9cd1a32d1c6c6ecd)
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_clr_tables(struct pfr_table *filter, int *ndel, int flags)
783b3a8eb9SGleb Smirnoff {
793b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
803b3a8eb9SGleb Smirnoff 
813b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
823b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
833b3a8eb9SGleb Smirnoff 	if (filter != NULL)
843b3a8eb9SGleb Smirnoff 		io.pfrio_table = *filter;
853b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRCLRTABLES, &io))
863b3a8eb9SGleb Smirnoff 		return (-1);
873b3a8eb9SGleb Smirnoff 	if (ndel != NULL)
883b3a8eb9SGleb Smirnoff 		*ndel = io.pfrio_ndel;
893b3a8eb9SGleb Smirnoff 	return (0);
903b3a8eb9SGleb Smirnoff }
913b3a8eb9SGleb Smirnoff 
923b3a8eb9SGleb Smirnoff int
933b3a8eb9SGleb Smirnoff pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
943b3a8eb9SGleb Smirnoff {
953b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
963b3a8eb9SGleb Smirnoff 
973b3a8eb9SGleb Smirnoff 	if (size < 0 || (size && tbl == NULL)) {
983b3a8eb9SGleb Smirnoff 		errno = EINVAL;
993b3a8eb9SGleb Smirnoff 		return (-1);
1003b3a8eb9SGleb Smirnoff 	}
1013b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
1023b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
1033b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = tbl;
1043b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*tbl);
1053b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
1063c7fbb06SKristof Provost 	if (ioctl(dev, DIOCRADDTABLES, &io)) {
1073c7fbb06SKristof Provost 		pfr_report_error(tbl, &io, "add table");
1083b3a8eb9SGleb Smirnoff 		return (-1);
1093c7fbb06SKristof Provost 	}
1103b3a8eb9SGleb Smirnoff 	if (nadd != NULL)
1113b3a8eb9SGleb Smirnoff 		*nadd = io.pfrio_nadd;
1123b3a8eb9SGleb Smirnoff 	return (0);
1133b3a8eb9SGleb Smirnoff }
1143b3a8eb9SGleb Smirnoff 
1153b3a8eb9SGleb Smirnoff int
1163b3a8eb9SGleb Smirnoff pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
1173b3a8eb9SGleb Smirnoff {
1183b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
1193b3a8eb9SGleb Smirnoff 
1203b3a8eb9SGleb Smirnoff 	if (size < 0 || (size && tbl == NULL)) {
1213b3a8eb9SGleb Smirnoff 		errno = EINVAL;
1223b3a8eb9SGleb Smirnoff 		return (-1);
1233b3a8eb9SGleb Smirnoff 	}
1243b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
1253b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
1263b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = tbl;
1273b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*tbl);
1283b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
1293c7fbb06SKristof Provost 	if (ioctl(dev, DIOCRDELTABLES, &io)) {
1303c7fbb06SKristof Provost 		pfr_report_error(tbl, &io, "delete table");
1313b3a8eb9SGleb Smirnoff 		return (-1);
1323c7fbb06SKristof Provost 	}
1333b3a8eb9SGleb Smirnoff 	if (ndel != NULL)
1343b3a8eb9SGleb Smirnoff 		*ndel = io.pfrio_ndel;
1353b3a8eb9SGleb Smirnoff 	return (0);
1363b3a8eb9SGleb Smirnoff }
1373b3a8eb9SGleb Smirnoff 
1383b3a8eb9SGleb Smirnoff int
1393b3a8eb9SGleb Smirnoff pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
1403b3a8eb9SGleb Smirnoff 	int flags)
1413b3a8eb9SGleb Smirnoff {
1423b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
1433b3a8eb9SGleb Smirnoff 
1443b3a8eb9SGleb Smirnoff 	if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
1453b3a8eb9SGleb Smirnoff 		errno = EINVAL;
1463b3a8eb9SGleb Smirnoff 		return (-1);
1473b3a8eb9SGleb Smirnoff 	}
1483b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
1493b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
1503b3a8eb9SGleb Smirnoff 	if (filter != NULL)
1513b3a8eb9SGleb Smirnoff 		io.pfrio_table = *filter;
1523b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = tbl;
1533b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*tbl);
1543b3a8eb9SGleb Smirnoff 	io.pfrio_size = *size;
1553c7fbb06SKristof Provost 	if (ioctl(dev, DIOCRGETTABLES, &io)) {
1563c7fbb06SKristof Provost 		pfr_report_error(tbl, &io, "get table");
1573b3a8eb9SGleb Smirnoff 		return (-1);
1583c7fbb06SKristof Provost 	}
1593b3a8eb9SGleb Smirnoff 	*size = io.pfrio_size;
1603b3a8eb9SGleb Smirnoff 	return (0);
1613b3a8eb9SGleb Smirnoff }
1623b3a8eb9SGleb Smirnoff 
1633b3a8eb9SGleb Smirnoff int
1643b3a8eb9SGleb Smirnoff pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
1653b3a8eb9SGleb Smirnoff 	int flags)
1663b3a8eb9SGleb Smirnoff {
1673b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
1683b3a8eb9SGleb Smirnoff 
1693b3a8eb9SGleb Smirnoff 	if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
1703b3a8eb9SGleb Smirnoff 		errno = EINVAL;
1713b3a8eb9SGleb Smirnoff 		return (-1);
1723b3a8eb9SGleb Smirnoff 	}
1733b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
1743b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
1753b3a8eb9SGleb Smirnoff 	if (filter != NULL)
1763b3a8eb9SGleb Smirnoff 		io.pfrio_table = *filter;
1773b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = tbl;
1783b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*tbl);
1793b3a8eb9SGleb Smirnoff 	io.pfrio_size = *size;
1803c7fbb06SKristof Provost 	if (ioctl(dev, DIOCRGETTSTATS, &io)) {
1813c7fbb06SKristof Provost 		pfr_report_error(filter, &io, "get tstats for");
1823b3a8eb9SGleb Smirnoff 		return (-1);
1833c7fbb06SKristof Provost 	}
1843b3a8eb9SGleb Smirnoff 	*size = io.pfrio_size;
1853b3a8eb9SGleb Smirnoff 	return (0);
1863b3a8eb9SGleb Smirnoff }
1873b3a8eb9SGleb Smirnoff 
1883b3a8eb9SGleb Smirnoff int
1893b3a8eb9SGleb Smirnoff pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
1903b3a8eb9SGleb Smirnoff {
1913b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
1923b3a8eb9SGleb Smirnoff 
1933b3a8eb9SGleb Smirnoff 	if (tbl == NULL) {
1943b3a8eb9SGleb Smirnoff 		errno = EINVAL;
1953b3a8eb9SGleb Smirnoff 		return (-1);
1963b3a8eb9SGleb Smirnoff 	}
1973b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
1983b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
1993b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
2003b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRCLRADDRS, &io))
2013b3a8eb9SGleb Smirnoff 		return (-1);
2023b3a8eb9SGleb Smirnoff 	if (ndel != NULL)
2033b3a8eb9SGleb Smirnoff 		*ndel = io.pfrio_ndel;
2043b3a8eb9SGleb Smirnoff 	return (0);
2053b3a8eb9SGleb Smirnoff }
2063b3a8eb9SGleb Smirnoff 
2073b3a8eb9SGleb Smirnoff int
2083b3a8eb9SGleb Smirnoff pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
2093b3a8eb9SGleb Smirnoff     int *nadd, int flags)
2103b3a8eb9SGleb Smirnoff {
2114823489aSReid Linnemann 	int ret;
2123b3a8eb9SGleb Smirnoff 
2134823489aSReid Linnemann 	ret = pfctl_table_add_addrs(dev, tbl, addr, size, nadd, flags);
2144823489aSReid Linnemann 	if (ret) {
2154823489aSReid Linnemann 		errno = ret;
2163b3a8eb9SGleb Smirnoff 		return (-1);
2173b3a8eb9SGleb Smirnoff 	}
2183b3a8eb9SGleb Smirnoff 	return (0);
2193b3a8eb9SGleb Smirnoff }
2203b3a8eb9SGleb Smirnoff 
2213b3a8eb9SGleb Smirnoff int
2223b3a8eb9SGleb Smirnoff pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
2233b3a8eb9SGleb Smirnoff     int *ndel, int flags)
2243b3a8eb9SGleb Smirnoff {
2254823489aSReid Linnemann 	int ret;
2263b3a8eb9SGleb Smirnoff 
2274823489aSReid Linnemann 	ret = pfctl_table_del_addrs(dev, tbl, addr, size, ndel, flags);
2284823489aSReid Linnemann 	if (ret) {
2294823489aSReid Linnemann 		errno = ret;
2303b3a8eb9SGleb Smirnoff 		return (-1);
2313b3a8eb9SGleb Smirnoff 	}
2323b3a8eb9SGleb Smirnoff 	return (0);
2333b3a8eb9SGleb Smirnoff }
2343b3a8eb9SGleb Smirnoff 
2353b3a8eb9SGleb Smirnoff int
2363b3a8eb9SGleb Smirnoff pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
2373b3a8eb9SGleb Smirnoff     int *size2, int *nadd, int *ndel, int *nchange, int flags)
2383b3a8eb9SGleb Smirnoff {
2394823489aSReid Linnemann 	int ret;
2403b3a8eb9SGleb Smirnoff 
2414823489aSReid Linnemann 	ret = pfctl_table_set_addrs(dev, tbl, addr, size, size2, nadd, ndel,
2424823489aSReid Linnemann 	    nchange, flags);
2434823489aSReid Linnemann 	if (ret) {
2444823489aSReid Linnemann 		errno = ret;
2453b3a8eb9SGleb Smirnoff 		return (-1);
2463b3a8eb9SGleb Smirnoff 	}
2473b3a8eb9SGleb Smirnoff 	return (0);
2483b3a8eb9SGleb Smirnoff }
2493b3a8eb9SGleb Smirnoff 
2503b3a8eb9SGleb Smirnoff int
2513b3a8eb9SGleb Smirnoff pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
2523b3a8eb9SGleb Smirnoff     int flags)
2533b3a8eb9SGleb Smirnoff {
2544823489aSReid Linnemann 	int ret;
2553b3a8eb9SGleb Smirnoff 
2564823489aSReid Linnemann 	ret = pfctl_table_get_addrs(dev, tbl, addr, size, flags);
2574823489aSReid Linnemann 	if (ret) {
2584823489aSReid Linnemann 		errno = ret;
2593b3a8eb9SGleb Smirnoff 		return (-1);
2603b3a8eb9SGleb Smirnoff 	}
2613b3a8eb9SGleb Smirnoff 	return (0);
2623b3a8eb9SGleb Smirnoff }
2633b3a8eb9SGleb Smirnoff 
2643b3a8eb9SGleb Smirnoff int
2653b3a8eb9SGleb Smirnoff pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
2663b3a8eb9SGleb Smirnoff     int flags)
2673b3a8eb9SGleb Smirnoff {
2683b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
2693b3a8eb9SGleb Smirnoff 
2703b3a8eb9SGleb Smirnoff 	if (tbl == NULL || size == NULL || *size < 0 ||
2713b3a8eb9SGleb Smirnoff 	    (*size && addr == NULL)) {
2723b3a8eb9SGleb Smirnoff 		errno = EINVAL;
2733b3a8eb9SGleb Smirnoff 		return (-1);
2743b3a8eb9SGleb Smirnoff 	}
2753b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
2763b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
2773b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
2783b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = addr;
2793b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*addr);
2803b3a8eb9SGleb Smirnoff 	io.pfrio_size = *size;
2813c7fbb06SKristof Provost 	if (ioctl(dev, DIOCRGETASTATS, &io)) {
2823c7fbb06SKristof Provost 		pfr_report_error(tbl, &io, "get astats from");
2833b3a8eb9SGleb Smirnoff 		return (-1);
2843c7fbb06SKristof Provost 	}
2853b3a8eb9SGleb Smirnoff 	*size = io.pfrio_size;
2863b3a8eb9SGleb Smirnoff 	return (0);
2873b3a8eb9SGleb Smirnoff }
2883b3a8eb9SGleb Smirnoff 
2893b3a8eb9SGleb Smirnoff int
2903b3a8eb9SGleb Smirnoff pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
2913b3a8eb9SGleb Smirnoff {
2923b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
2933b3a8eb9SGleb Smirnoff 
2943b3a8eb9SGleb Smirnoff 	if (size < 0 || (size && !tbl)) {
2953b3a8eb9SGleb Smirnoff 		errno = EINVAL;
2963b3a8eb9SGleb Smirnoff 		return (-1);
2973b3a8eb9SGleb Smirnoff 	}
2983b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
2993b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
3003b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = tbl;
3013b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*tbl);
3023b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
3033c7fbb06SKristof Provost 	if (ioctl(dev, DIOCRCLRTSTATS, &io)) {
3043c7fbb06SKristof Provost 		pfr_report_error(tbl, &io, "clear tstats from");
3053b3a8eb9SGleb Smirnoff 		return (-1);
3063c7fbb06SKristof Provost 	}
3073b3a8eb9SGleb Smirnoff 	if (nzero)
3083b3a8eb9SGleb Smirnoff 		*nzero = io.pfrio_nzero;
3093b3a8eb9SGleb Smirnoff 	return (0);
3103b3a8eb9SGleb Smirnoff }
3113b3a8eb9SGleb Smirnoff 
3123b3a8eb9SGleb Smirnoff int
3133b3a8eb9SGleb Smirnoff pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
3143b3a8eb9SGleb Smirnoff     int *nmatch, int flags)
3153b3a8eb9SGleb Smirnoff {
3163b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
3173b3a8eb9SGleb Smirnoff 
3183b3a8eb9SGleb Smirnoff 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
3193b3a8eb9SGleb Smirnoff 		errno = EINVAL;
3203b3a8eb9SGleb Smirnoff 		return (-1);
3213b3a8eb9SGleb Smirnoff 	}
3223b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
3233b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
3243b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
3253b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = addr;
3263b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*addr);
3273b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
3283c7fbb06SKristof Provost 	if (ioctl(dev, DIOCRTSTADDRS, &io)) {
3293c7fbb06SKristof Provost 		pfr_report_error(tbl, &io, "test addresses in");
3303b3a8eb9SGleb Smirnoff 		return (-1);
3313c7fbb06SKristof Provost 	}
3323b3a8eb9SGleb Smirnoff 	if (nmatch)
3333b3a8eb9SGleb Smirnoff 		*nmatch = io.pfrio_nmatch;
3343b3a8eb9SGleb Smirnoff 	return (0);
3353b3a8eb9SGleb Smirnoff }
3363b3a8eb9SGleb Smirnoff 
3373b3a8eb9SGleb Smirnoff int
3383b3a8eb9SGleb Smirnoff pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
3393b3a8eb9SGleb Smirnoff     int *nadd, int *naddr, int ticket, int flags)
3403b3a8eb9SGleb Smirnoff {
3413b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
3423b3a8eb9SGleb Smirnoff 
3433b3a8eb9SGleb Smirnoff 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
3443b3a8eb9SGleb Smirnoff 		errno = EINVAL;
3453b3a8eb9SGleb Smirnoff 		return (-1);
3463b3a8eb9SGleb Smirnoff 	}
3473b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
3483b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
3493b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
3503b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = addr;
3513b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*addr);
3523b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
3533b3a8eb9SGleb Smirnoff 	io.pfrio_ticket = ticket;
3543c7fbb06SKristof Provost 	if (ioctl(dev, DIOCRINADEFINE, &io)) {
3553c7fbb06SKristof Provost 		pfr_report_error(tbl, &io, "define inactive set table");
3563b3a8eb9SGleb Smirnoff 		return (-1);
3573c7fbb06SKristof Provost 	}
3583b3a8eb9SGleb Smirnoff 	if (nadd != NULL)
3593b3a8eb9SGleb Smirnoff 		*nadd = io.pfrio_nadd;
3603b3a8eb9SGleb Smirnoff 	if (naddr != NULL)
3613b3a8eb9SGleb Smirnoff 		*naddr = io.pfrio_naddr;
3623b3a8eb9SGleb Smirnoff 	return (0);
3633b3a8eb9SGleb Smirnoff }
3643b3a8eb9SGleb Smirnoff 
3653b3a8eb9SGleb Smirnoff /* interface management code */
3663b3a8eb9SGleb Smirnoff 
3673b3a8eb9SGleb Smirnoff int
3683b3a8eb9SGleb Smirnoff pfi_get_ifaces(const char *filter, struct pfi_kif *buf, int *size)
3693b3a8eb9SGleb Smirnoff {
3703b3a8eb9SGleb Smirnoff 	struct pfioc_iface io;
3713b3a8eb9SGleb Smirnoff 
3723b3a8eb9SGleb Smirnoff 	if (size == NULL || *size < 0 || (*size && buf == NULL)) {
3733b3a8eb9SGleb Smirnoff 		errno = EINVAL;
3743b3a8eb9SGleb Smirnoff 		return (-1);
3753b3a8eb9SGleb Smirnoff 	}
3763b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
3773b3a8eb9SGleb Smirnoff 	if (filter != NULL)
3783b3a8eb9SGleb Smirnoff 		if (strlcpy(io.pfiio_name, filter, sizeof(io.pfiio_name)) >=
3793b3a8eb9SGleb Smirnoff 		    sizeof(io.pfiio_name)) {
3803b3a8eb9SGleb Smirnoff 			errno = EINVAL;
3813b3a8eb9SGleb Smirnoff 			return (-1);
3823b3a8eb9SGleb Smirnoff 		}
3833b3a8eb9SGleb Smirnoff 	io.pfiio_buffer = buf;
3843b3a8eb9SGleb Smirnoff 	io.pfiio_esize = sizeof(*buf);
3853b3a8eb9SGleb Smirnoff 	io.pfiio_size = *size;
3863b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCIGETIFACES, &io))
3873b3a8eb9SGleb Smirnoff 		return (-1);
3883b3a8eb9SGleb Smirnoff 	*size = io.pfiio_size;
3893b3a8eb9SGleb Smirnoff 	return (0);
3903b3a8eb9SGleb Smirnoff }
3913b3a8eb9SGleb Smirnoff 
3923b3a8eb9SGleb Smirnoff /* buffer management code */
3933b3a8eb9SGleb Smirnoff 
39472a3cf0fSKristof Provost const size_t buf_esize[PFRB_MAX] = { 0,
3953b3a8eb9SGleb Smirnoff 	sizeof(struct pfr_table), sizeof(struct pfr_tstats),
3963b3a8eb9SGleb Smirnoff 	sizeof(struct pfr_addr), sizeof(struct pfr_astats),
3973b3a8eb9SGleb Smirnoff 	sizeof(struct pfi_kif), sizeof(struct pfioc_trans_e)
3983b3a8eb9SGleb Smirnoff };
3993b3a8eb9SGleb Smirnoff 
4003b3a8eb9SGleb Smirnoff /*
4013b3a8eb9SGleb Smirnoff  * add one element to the buffer
4023b3a8eb9SGleb Smirnoff  */
4033b3a8eb9SGleb Smirnoff int
4043b3a8eb9SGleb Smirnoff pfr_buf_add(struct pfr_buffer *b, const void *e)
4053b3a8eb9SGleb Smirnoff {
4063b3a8eb9SGleb Smirnoff 	size_t bs;
4073b3a8eb9SGleb Smirnoff 
4083b3a8eb9SGleb Smirnoff 	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX ||
4093b3a8eb9SGleb Smirnoff 	    e == NULL) {
4103b3a8eb9SGleb Smirnoff 		errno = EINVAL;
4113b3a8eb9SGleb Smirnoff 		return (-1);
4123b3a8eb9SGleb Smirnoff 	}
4133b3a8eb9SGleb Smirnoff 	bs = buf_esize[b->pfrb_type];
4143b3a8eb9SGleb Smirnoff 	if (b->pfrb_size == b->pfrb_msize)
4153b3a8eb9SGleb Smirnoff 		if (pfr_buf_grow(b, 0))
4163b3a8eb9SGleb Smirnoff 			return (-1);
4173b3a8eb9SGleb Smirnoff 	memcpy(((caddr_t)b->pfrb_caddr) + bs * b->pfrb_size, e, bs);
4183b3a8eb9SGleb Smirnoff 	b->pfrb_size++;
4193b3a8eb9SGleb Smirnoff 	return (0);
4203b3a8eb9SGleb Smirnoff }
4213b3a8eb9SGleb Smirnoff 
4223b3a8eb9SGleb Smirnoff /*
4233b3a8eb9SGleb Smirnoff  * return next element of the buffer (or first one if prev is NULL)
4243b3a8eb9SGleb Smirnoff  * see PFRB_FOREACH macro
4253b3a8eb9SGleb Smirnoff  */
4263b3a8eb9SGleb Smirnoff void *
4273b3a8eb9SGleb Smirnoff pfr_buf_next(struct pfr_buffer *b, const void *prev)
4283b3a8eb9SGleb Smirnoff {
4293b3a8eb9SGleb Smirnoff 	size_t bs;
4303b3a8eb9SGleb Smirnoff 
4313b3a8eb9SGleb Smirnoff 	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX)
4323b3a8eb9SGleb Smirnoff 		return (NULL);
4333b3a8eb9SGleb Smirnoff 	if (b->pfrb_size == 0)
4343b3a8eb9SGleb Smirnoff 		return (NULL);
4353b3a8eb9SGleb Smirnoff 	if (prev == NULL)
4363b3a8eb9SGleb Smirnoff 		return (b->pfrb_caddr);
4373b3a8eb9SGleb Smirnoff 	bs = buf_esize[b->pfrb_type];
4383b3a8eb9SGleb Smirnoff 	if ((((caddr_t)prev)-((caddr_t)b->pfrb_caddr)) / bs >= b->pfrb_size-1)
4393b3a8eb9SGleb Smirnoff 		return (NULL);
4403b3a8eb9SGleb Smirnoff 	return (((caddr_t)prev) + bs);
4413b3a8eb9SGleb Smirnoff }
4423b3a8eb9SGleb Smirnoff 
4433b3a8eb9SGleb Smirnoff /*
4443b3a8eb9SGleb Smirnoff  * minsize:
4453b3a8eb9SGleb Smirnoff  *    0: make the buffer somewhat bigger
4463b3a8eb9SGleb Smirnoff  *    n: make room for "n" entries in the buffer
4473b3a8eb9SGleb Smirnoff  */
4483b3a8eb9SGleb Smirnoff int
4493b3a8eb9SGleb Smirnoff pfr_buf_grow(struct pfr_buffer *b, int minsize)
4503b3a8eb9SGleb Smirnoff {
4513b3a8eb9SGleb Smirnoff 	caddr_t p;
4523b3a8eb9SGleb Smirnoff 	size_t bs;
4533b3a8eb9SGleb Smirnoff 
4543b3a8eb9SGleb Smirnoff 	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX) {
4553b3a8eb9SGleb Smirnoff 		errno = EINVAL;
4563b3a8eb9SGleb Smirnoff 		return (-1);
4573b3a8eb9SGleb Smirnoff 	}
4583b3a8eb9SGleb Smirnoff 	if (minsize != 0 && minsize <= b->pfrb_msize)
4593b3a8eb9SGleb Smirnoff 		return (0);
4603b3a8eb9SGleb Smirnoff 	bs = buf_esize[b->pfrb_type];
4613b3a8eb9SGleb Smirnoff 	if (!b->pfrb_msize) {
4623b3a8eb9SGleb Smirnoff 		if (minsize < 64)
4633b3a8eb9SGleb Smirnoff 			minsize = 64;
4643b3a8eb9SGleb Smirnoff 		b->pfrb_caddr = calloc(bs, minsize);
4653b3a8eb9SGleb Smirnoff 		if (b->pfrb_caddr == NULL)
4663b3a8eb9SGleb Smirnoff 			return (-1);
4673b3a8eb9SGleb Smirnoff 		b->pfrb_msize = minsize;
4683b3a8eb9SGleb Smirnoff 	} else {
4693b3a8eb9SGleb Smirnoff 		if (minsize == 0)
4703b3a8eb9SGleb Smirnoff 			minsize = b->pfrb_msize * 2;
4713b3a8eb9SGleb Smirnoff 		if (minsize < 0 || minsize >= SIZE_T_MAX / bs) {
4723b3a8eb9SGleb Smirnoff 			/* msize overflow */
4733b3a8eb9SGleb Smirnoff 			errno = ENOMEM;
4743b3a8eb9SGleb Smirnoff 			return (-1);
4753b3a8eb9SGleb Smirnoff 		}
4763b3a8eb9SGleb Smirnoff 		p = realloc(b->pfrb_caddr, minsize * bs);
4773b3a8eb9SGleb Smirnoff 		if (p == NULL)
4783b3a8eb9SGleb Smirnoff 			return (-1);
4793b3a8eb9SGleb Smirnoff 		bzero(p + b->pfrb_msize * bs, (minsize - b->pfrb_msize) * bs);
4803b3a8eb9SGleb Smirnoff 		b->pfrb_caddr = p;
4813b3a8eb9SGleb Smirnoff 		b->pfrb_msize = minsize;
4823b3a8eb9SGleb Smirnoff 	}
4833b3a8eb9SGleb Smirnoff 	return (0);
4843b3a8eb9SGleb Smirnoff }
4853b3a8eb9SGleb Smirnoff 
4863b3a8eb9SGleb Smirnoff /*
4873b3a8eb9SGleb Smirnoff  * reset buffer and free memory.
4883b3a8eb9SGleb Smirnoff  */
4893b3a8eb9SGleb Smirnoff void
4903b3a8eb9SGleb Smirnoff pfr_buf_clear(struct pfr_buffer *b)
4913b3a8eb9SGleb Smirnoff {
4923b3a8eb9SGleb Smirnoff 	if (b == NULL)
4933b3a8eb9SGleb Smirnoff 		return;
4943b3a8eb9SGleb Smirnoff 	if (b->pfrb_caddr != NULL)
4953b3a8eb9SGleb Smirnoff 		free(b->pfrb_caddr);
4963b3a8eb9SGleb Smirnoff 	b->pfrb_caddr = NULL;
4973b3a8eb9SGleb Smirnoff 	b->pfrb_size = b->pfrb_msize = 0;
4983b3a8eb9SGleb Smirnoff }
4993b3a8eb9SGleb Smirnoff 
5003b3a8eb9SGleb Smirnoff int
5013b3a8eb9SGleb Smirnoff pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork,
5023b3a8eb9SGleb Smirnoff     int (*append_addr)(struct pfr_buffer *, char *, int))
5033b3a8eb9SGleb Smirnoff {
5043b3a8eb9SGleb Smirnoff 	FILE	*fp;
5053b3a8eb9SGleb Smirnoff 	char	 buf[BUF_SIZE];
5063b3a8eb9SGleb Smirnoff 	int	 rv;
5073b3a8eb9SGleb Smirnoff 
5083b3a8eb9SGleb Smirnoff 	if (file == NULL)
5093b3a8eb9SGleb Smirnoff 		return (0);
5103b3a8eb9SGleb Smirnoff 	if (!strcmp(file, "-"))
5113b3a8eb9SGleb Smirnoff 		fp = stdin;
5123b3a8eb9SGleb Smirnoff 	else {
5133b3a8eb9SGleb Smirnoff 		fp = pfctl_fopen(file, "r");
5143b3a8eb9SGleb Smirnoff 		if (fp == NULL)
5153b3a8eb9SGleb Smirnoff 			return (-1);
5163b3a8eb9SGleb Smirnoff 	}
5173b3a8eb9SGleb Smirnoff 	while ((rv = pfr_next_token(buf, fp)) == 1)
5183b3a8eb9SGleb Smirnoff 		if (append_addr(b, buf, nonetwork)) {
5193b3a8eb9SGleb Smirnoff 			rv = -1;
5203b3a8eb9SGleb Smirnoff 			break;
5213b3a8eb9SGleb Smirnoff 		}
5223b3a8eb9SGleb Smirnoff 	if (fp != stdin)
5233b3a8eb9SGleb Smirnoff 		fclose(fp);
5243b3a8eb9SGleb Smirnoff 	return (rv);
5253b3a8eb9SGleb Smirnoff }
5263b3a8eb9SGleb Smirnoff 
5273b3a8eb9SGleb Smirnoff int
5283b3a8eb9SGleb Smirnoff pfr_next_token(char buf[BUF_SIZE], FILE *fp)
5293b3a8eb9SGleb Smirnoff {
5303b3a8eb9SGleb Smirnoff 	static char	next_ch = ' ';
5313b3a8eb9SGleb Smirnoff 	int		i = 0;
5323b3a8eb9SGleb Smirnoff 
5333b3a8eb9SGleb Smirnoff 	for (;;) {
5343b3a8eb9SGleb Smirnoff 		/* skip spaces */
5353b3a8eb9SGleb Smirnoff 		while (isspace(next_ch) && !feof(fp))
5363b3a8eb9SGleb Smirnoff 			next_ch = fgetc(fp);
537*a8a95277SJuraj Lutter 		/* remove from '#' or ';' until end of line */
538*a8a95277SJuraj Lutter 		if (next_ch == '#' || next_ch == ';')
5393b3a8eb9SGleb Smirnoff 			while (!feof(fp)) {
5403b3a8eb9SGleb Smirnoff 				next_ch = fgetc(fp);
5413b3a8eb9SGleb Smirnoff 				if (next_ch == '\n')
5423b3a8eb9SGleb Smirnoff 					break;
5433b3a8eb9SGleb Smirnoff 			}
5443b3a8eb9SGleb Smirnoff 		else
5453b3a8eb9SGleb Smirnoff 			break;
5463b3a8eb9SGleb Smirnoff 	}
5473b3a8eb9SGleb Smirnoff 	if (feof(fp)) {
5483b3a8eb9SGleb Smirnoff 		next_ch = ' ';
5493b3a8eb9SGleb Smirnoff 		return (0);
5503b3a8eb9SGleb Smirnoff 	}
5513b3a8eb9SGleb Smirnoff 	do {
5523b3a8eb9SGleb Smirnoff 		if (i < BUF_SIZE)
5533b3a8eb9SGleb Smirnoff 			buf[i++] = next_ch;
5543b3a8eb9SGleb Smirnoff 		next_ch = fgetc(fp);
5553b3a8eb9SGleb Smirnoff 	} while (!feof(fp) && !isspace(next_ch));
5563b3a8eb9SGleb Smirnoff 	if (i >= BUF_SIZE) {
5573b3a8eb9SGleb Smirnoff 		errno = EINVAL;
5583b3a8eb9SGleb Smirnoff 		return (-1);
5593b3a8eb9SGleb Smirnoff 	}
5603b3a8eb9SGleb Smirnoff 	buf[i] = '\0';
5613b3a8eb9SGleb Smirnoff 	return (1);
5623b3a8eb9SGleb Smirnoff }
5633b3a8eb9SGleb Smirnoff 
5643b3a8eb9SGleb Smirnoff char *
5653b3a8eb9SGleb Smirnoff pfr_strerror(int errnum)
5663b3a8eb9SGleb Smirnoff {
5673b3a8eb9SGleb Smirnoff 	switch (errnum) {
5683b3a8eb9SGleb Smirnoff 	case ESRCH:
5693b3a8eb9SGleb Smirnoff 		return "Table does not exist";
5703b3a8eb9SGleb Smirnoff 	case ENOENT:
5713b3a8eb9SGleb Smirnoff 		return "Anchor or Ruleset does not exist";
5723b3a8eb9SGleb Smirnoff 	default:
5733b3a8eb9SGleb Smirnoff 		return strerror(errnum);
5743b3a8eb9SGleb Smirnoff 	}
5753b3a8eb9SGleb Smirnoff }
576