xref: /freebsd/sbin/pfctl/pfctl_radix.c (revision 72a3cf0f4112b92523e993327c2ee58b16fce74d)
13b3a8eb9SGleb Smirnoff /*	$OpenBSD: pfctl_radix.c,v 1.27 2005/05/21 21:03:58 henning Exp $ */
23b3a8eb9SGleb Smirnoff 
33b3a8eb9SGleb Smirnoff /*
43b3a8eb9SGleb Smirnoff  * Copyright (c) 2002 Cedric Berger
53b3a8eb9SGleb Smirnoff  * All rights reserved.
63b3a8eb9SGleb Smirnoff  *
73b3a8eb9SGleb Smirnoff  * Redistribution and use in source and binary forms, with or without
83b3a8eb9SGleb Smirnoff  * modification, are permitted provided that the following conditions
93b3a8eb9SGleb Smirnoff  * are met:
103b3a8eb9SGleb Smirnoff  *
113b3a8eb9SGleb Smirnoff  *    - Redistributions of source code must retain the above copyright
123b3a8eb9SGleb Smirnoff  *      notice, this list of conditions and the following disclaimer.
133b3a8eb9SGleb Smirnoff  *    - Redistributions in binary form must reproduce the above
143b3a8eb9SGleb Smirnoff  *      copyright notice, this list of conditions and the following
153b3a8eb9SGleb Smirnoff  *      disclaimer in the documentation and/or other materials provided
163b3a8eb9SGleb Smirnoff  *      with the distribution.
173b3a8eb9SGleb Smirnoff  *
183b3a8eb9SGleb Smirnoff  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
193b3a8eb9SGleb Smirnoff  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
203b3a8eb9SGleb Smirnoff  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
213b3a8eb9SGleb Smirnoff  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
223b3a8eb9SGleb Smirnoff  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
233b3a8eb9SGleb Smirnoff  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
243b3a8eb9SGleb Smirnoff  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
253b3a8eb9SGleb Smirnoff  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
263b3a8eb9SGleb Smirnoff  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
273b3a8eb9SGleb Smirnoff  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
283b3a8eb9SGleb Smirnoff  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
293b3a8eb9SGleb Smirnoff  * POSSIBILITY OF SUCH DAMAGE.
303b3a8eb9SGleb Smirnoff  *
313b3a8eb9SGleb Smirnoff  */
323b3a8eb9SGleb Smirnoff 
333b3a8eb9SGleb Smirnoff #include <sys/cdefs.h>
343b3a8eb9SGleb Smirnoff __FBSDID("$FreeBSD$");
353b3a8eb9SGleb Smirnoff 
363b3a8eb9SGleb Smirnoff #include <sys/types.h>
373b3a8eb9SGleb Smirnoff #include <sys/ioctl.h>
383b3a8eb9SGleb Smirnoff #include <sys/socket.h>
393b3a8eb9SGleb Smirnoff 
403b3a8eb9SGleb Smirnoff #include <net/if.h>
413b3a8eb9SGleb Smirnoff #include <net/pfvar.h>
423b3a8eb9SGleb Smirnoff 
433b3a8eb9SGleb Smirnoff #include <errno.h>
443b3a8eb9SGleb Smirnoff #include <string.h>
453b3a8eb9SGleb Smirnoff #include <ctype.h>
463b3a8eb9SGleb Smirnoff #include <stdio.h>
473b3a8eb9SGleb Smirnoff #include <stdlib.h>
483b3a8eb9SGleb Smirnoff #include <limits.h>
493b3a8eb9SGleb Smirnoff #include <err.h>
503b3a8eb9SGleb Smirnoff 
513b3a8eb9SGleb Smirnoff #include "pfctl.h"
523b3a8eb9SGleb Smirnoff 
533b3a8eb9SGleb Smirnoff #define BUF_SIZE 256
543b3a8eb9SGleb Smirnoff 
553b3a8eb9SGleb Smirnoff extern int dev;
563b3a8eb9SGleb Smirnoff 
573b3a8eb9SGleb Smirnoff static int	 pfr_next_token(char buf[], FILE *);
583b3a8eb9SGleb Smirnoff 
593b3a8eb9SGleb Smirnoff 
603b3a8eb9SGleb Smirnoff int
613b3a8eb9SGleb Smirnoff pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
623b3a8eb9SGleb Smirnoff {
633b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
643b3a8eb9SGleb Smirnoff 
653b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
663b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
673b3a8eb9SGleb Smirnoff 	if (filter != NULL)
683b3a8eb9SGleb Smirnoff 		io.pfrio_table = *filter;
693b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRCLRTABLES, &io))
703b3a8eb9SGleb Smirnoff 		return (-1);
713b3a8eb9SGleb Smirnoff 	if (ndel != NULL)
723b3a8eb9SGleb Smirnoff 		*ndel = io.pfrio_ndel;
733b3a8eb9SGleb Smirnoff 	return (0);
743b3a8eb9SGleb Smirnoff }
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;
903b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRADDTABLES, &io))
913b3a8eb9SGleb Smirnoff 		return (-1);
923b3a8eb9SGleb Smirnoff 	if (nadd != NULL)
933b3a8eb9SGleb Smirnoff 		*nadd = io.pfrio_nadd;
943b3a8eb9SGleb Smirnoff 	return (0);
953b3a8eb9SGleb Smirnoff }
963b3a8eb9SGleb Smirnoff 
973b3a8eb9SGleb Smirnoff int
983b3a8eb9SGleb Smirnoff pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
993b3a8eb9SGleb Smirnoff {
1003b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
1013b3a8eb9SGleb Smirnoff 
1023b3a8eb9SGleb Smirnoff 	if (size < 0 || (size && tbl == NULL)) {
1033b3a8eb9SGleb Smirnoff 		errno = EINVAL;
1043b3a8eb9SGleb Smirnoff 		return (-1);
1053b3a8eb9SGleb Smirnoff 	}
1063b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
1073b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
1083b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = tbl;
1093b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*tbl);
1103b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
1113b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRDELTABLES, &io))
1123b3a8eb9SGleb Smirnoff 		return (-1);
1133b3a8eb9SGleb Smirnoff 	if (ndel != NULL)
1143b3a8eb9SGleb Smirnoff 		*ndel = io.pfrio_ndel;
1153b3a8eb9SGleb Smirnoff 	return (0);
1163b3a8eb9SGleb Smirnoff }
1173b3a8eb9SGleb Smirnoff 
1183b3a8eb9SGleb Smirnoff int
1193b3a8eb9SGleb Smirnoff pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
1203b3a8eb9SGleb Smirnoff 	int flags)
1213b3a8eb9SGleb Smirnoff {
1223b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
1233b3a8eb9SGleb Smirnoff 
1243b3a8eb9SGleb Smirnoff 	if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
1253b3a8eb9SGleb Smirnoff 		errno = EINVAL;
1263b3a8eb9SGleb Smirnoff 		return (-1);
1273b3a8eb9SGleb Smirnoff 	}
1283b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
1293b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
1303b3a8eb9SGleb Smirnoff 	if (filter != NULL)
1313b3a8eb9SGleb Smirnoff 		io.pfrio_table = *filter;
1323b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = tbl;
1333b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*tbl);
1343b3a8eb9SGleb Smirnoff 	io.pfrio_size = *size;
1353b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRGETTABLES, &io))
1363b3a8eb9SGleb Smirnoff 		return (-1);
1373b3a8eb9SGleb Smirnoff 	*size = io.pfrio_size;
1383b3a8eb9SGleb Smirnoff 	return (0);
1393b3a8eb9SGleb Smirnoff }
1403b3a8eb9SGleb Smirnoff 
1413b3a8eb9SGleb Smirnoff int
1423b3a8eb9SGleb Smirnoff pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *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;
1583b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRGETTSTATS, &io))
1593b3a8eb9SGleb Smirnoff 		return (-1);
1603b3a8eb9SGleb Smirnoff 	*size = io.pfrio_size;
1613b3a8eb9SGleb Smirnoff 	return (0);
1623b3a8eb9SGleb Smirnoff }
1633b3a8eb9SGleb Smirnoff 
1643b3a8eb9SGleb Smirnoff int
1653b3a8eb9SGleb Smirnoff pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
1663b3a8eb9SGleb Smirnoff {
1673b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
1683b3a8eb9SGleb Smirnoff 
1693b3a8eb9SGleb Smirnoff 	if (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 	io.pfrio_table = *tbl;
1763b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRCLRADDRS, &io))
1773b3a8eb9SGleb Smirnoff 		return (-1);
1783b3a8eb9SGleb Smirnoff 	if (ndel != NULL)
1793b3a8eb9SGleb Smirnoff 		*ndel = io.pfrio_ndel;
1803b3a8eb9SGleb Smirnoff 	return (0);
1813b3a8eb9SGleb Smirnoff }
1823b3a8eb9SGleb Smirnoff 
1833b3a8eb9SGleb Smirnoff int
1843b3a8eb9SGleb Smirnoff pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
1853b3a8eb9SGleb Smirnoff     int *nadd, int flags)
1863b3a8eb9SGleb Smirnoff {
1873b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
1883b3a8eb9SGleb Smirnoff 
1893b3a8eb9SGleb Smirnoff 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
1903b3a8eb9SGleb Smirnoff 		errno = EINVAL;
1913b3a8eb9SGleb Smirnoff 		return (-1);
1923b3a8eb9SGleb Smirnoff 	}
1933b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
1943b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
1953b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
1963b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = addr;
1973b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*addr);
1983b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
1993b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRADDADDRS, &io))
2003b3a8eb9SGleb Smirnoff 		return (-1);
2013b3a8eb9SGleb Smirnoff 	if (nadd != NULL)
2023b3a8eb9SGleb Smirnoff 		*nadd = io.pfrio_nadd;
2033b3a8eb9SGleb Smirnoff 	return (0);
2043b3a8eb9SGleb Smirnoff }
2053b3a8eb9SGleb Smirnoff 
2063b3a8eb9SGleb Smirnoff int
2073b3a8eb9SGleb Smirnoff pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
2083b3a8eb9SGleb Smirnoff     int *ndel, int flags)
2093b3a8eb9SGleb Smirnoff {
2103b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
2113b3a8eb9SGleb Smirnoff 
2123b3a8eb9SGleb Smirnoff 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
2133b3a8eb9SGleb Smirnoff 		errno = EINVAL;
2143b3a8eb9SGleb Smirnoff 		return (-1);
2153b3a8eb9SGleb Smirnoff 	}
2163b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
2173b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
2183b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
2193b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = addr;
2203b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*addr);
2213b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
2223b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRDELADDRS, &io))
2233b3a8eb9SGleb Smirnoff 		return (-1);
2243b3a8eb9SGleb Smirnoff 	if (ndel != NULL)
2253b3a8eb9SGleb Smirnoff 		*ndel = io.pfrio_ndel;
2263b3a8eb9SGleb Smirnoff 	return (0);
2273b3a8eb9SGleb Smirnoff }
2283b3a8eb9SGleb Smirnoff 
2293b3a8eb9SGleb Smirnoff int
2303b3a8eb9SGleb Smirnoff pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
2313b3a8eb9SGleb Smirnoff     int *size2, int *nadd, int *ndel, int *nchange, int flags)
2323b3a8eb9SGleb Smirnoff {
2333b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
2343b3a8eb9SGleb Smirnoff 
2353b3a8eb9SGleb Smirnoff 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
2363b3a8eb9SGleb Smirnoff 		errno = EINVAL;
2373b3a8eb9SGleb Smirnoff 		return (-1);
2383b3a8eb9SGleb Smirnoff 	}
2393b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
2403b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
2413b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
2423b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = addr;
2433b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*addr);
2443b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
2453b3a8eb9SGleb Smirnoff 	io.pfrio_size2 = (size2 != NULL) ? *size2 : 0;
2463b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRSETADDRS, &io))
2473b3a8eb9SGleb Smirnoff 		return (-1);
2483b3a8eb9SGleb Smirnoff 	if (nadd != NULL)
2493b3a8eb9SGleb Smirnoff 		*nadd = io.pfrio_nadd;
2503b3a8eb9SGleb Smirnoff 	if (ndel != NULL)
2513b3a8eb9SGleb Smirnoff 		*ndel = io.pfrio_ndel;
2523b3a8eb9SGleb Smirnoff 	if (nchange != NULL)
2533b3a8eb9SGleb Smirnoff 		*nchange = io.pfrio_nchange;
2543b3a8eb9SGleb Smirnoff 	if (size2 != NULL)
2553b3a8eb9SGleb Smirnoff 		*size2 = io.pfrio_size2;
2563b3a8eb9SGleb Smirnoff 	return (0);
2573b3a8eb9SGleb Smirnoff }
2583b3a8eb9SGleb Smirnoff 
2593b3a8eb9SGleb Smirnoff int
2603b3a8eb9SGleb Smirnoff pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
2613b3a8eb9SGleb Smirnoff     int flags)
2623b3a8eb9SGleb Smirnoff {
2633b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
2643b3a8eb9SGleb Smirnoff 
2653b3a8eb9SGleb Smirnoff 	if (tbl == NULL || size == NULL || *size < 0 ||
2663b3a8eb9SGleb Smirnoff 	    (*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 	if (ioctl(dev, DIOCRGETADDRS, &io))
2773b3a8eb9SGleb Smirnoff 		return (-1);
2783b3a8eb9SGleb Smirnoff 	*size = io.pfrio_size;
2793b3a8eb9SGleb Smirnoff 	return (0);
2803b3a8eb9SGleb Smirnoff }
2813b3a8eb9SGleb Smirnoff 
2823b3a8eb9SGleb Smirnoff int
2833b3a8eb9SGleb Smirnoff pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
2843b3a8eb9SGleb Smirnoff     int flags)
2853b3a8eb9SGleb Smirnoff {
2863b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
2873b3a8eb9SGleb Smirnoff 
2883b3a8eb9SGleb Smirnoff 	if (tbl == NULL || size == NULL || *size < 0 ||
2893b3a8eb9SGleb Smirnoff 	    (*size && addr == NULL)) {
2903b3a8eb9SGleb Smirnoff 		errno = EINVAL;
2913b3a8eb9SGleb Smirnoff 		return (-1);
2923b3a8eb9SGleb Smirnoff 	}
2933b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
2943b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
2953b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
2963b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = addr;
2973b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*addr);
2983b3a8eb9SGleb Smirnoff 	io.pfrio_size = *size;
2993b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRGETASTATS, &io))
3003b3a8eb9SGleb Smirnoff 		return (-1);
3013b3a8eb9SGleb Smirnoff 	*size = io.pfrio_size;
3023b3a8eb9SGleb Smirnoff 	return (0);
3033b3a8eb9SGleb Smirnoff }
3043b3a8eb9SGleb Smirnoff 
3053b3a8eb9SGleb Smirnoff int
3063b3a8eb9SGleb Smirnoff pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
3073b3a8eb9SGleb Smirnoff {
3083b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
3093b3a8eb9SGleb Smirnoff 
3103b3a8eb9SGleb Smirnoff 	if (size < 0 || (size && !tbl)) {
3113b3a8eb9SGleb Smirnoff 		errno = EINVAL;
3123b3a8eb9SGleb Smirnoff 		return (-1);
3133b3a8eb9SGleb Smirnoff 	}
3143b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
3153b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
3163b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = tbl;
3173b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*tbl);
3183b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
3193b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRCLRTSTATS, &io))
3203b3a8eb9SGleb Smirnoff 		return (-1);
3213b3a8eb9SGleb Smirnoff 	if (nzero)
3223b3a8eb9SGleb Smirnoff 		*nzero = io.pfrio_nzero;
3233b3a8eb9SGleb Smirnoff 	return (0);
3243b3a8eb9SGleb Smirnoff }
3253b3a8eb9SGleb Smirnoff 
3263b3a8eb9SGleb Smirnoff int
3273b3a8eb9SGleb Smirnoff pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
3283b3a8eb9SGleb Smirnoff     int *nmatch, int flags)
3293b3a8eb9SGleb Smirnoff {
3303b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
3313b3a8eb9SGleb Smirnoff 
3323b3a8eb9SGleb Smirnoff 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
3333b3a8eb9SGleb Smirnoff 		errno = EINVAL;
3343b3a8eb9SGleb Smirnoff 		return (-1);
3353b3a8eb9SGleb Smirnoff 	}
3363b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
3373b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
3383b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
3393b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = addr;
3403b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*addr);
3413b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
3423b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRTSTADDRS, &io))
3433b3a8eb9SGleb Smirnoff 		return (-1);
3443b3a8eb9SGleb Smirnoff 	if (nmatch)
3453b3a8eb9SGleb Smirnoff 		*nmatch = io.pfrio_nmatch;
3463b3a8eb9SGleb Smirnoff 	return (0);
3473b3a8eb9SGleb Smirnoff }
3483b3a8eb9SGleb Smirnoff 
3493b3a8eb9SGleb Smirnoff int
3503b3a8eb9SGleb Smirnoff pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
3513b3a8eb9SGleb Smirnoff     int *nadd, int *naddr, int ticket, int flags)
3523b3a8eb9SGleb Smirnoff {
3533b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
3543b3a8eb9SGleb Smirnoff 
3553b3a8eb9SGleb Smirnoff 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
3563b3a8eb9SGleb Smirnoff 		errno = EINVAL;
3573b3a8eb9SGleb Smirnoff 		return (-1);
3583b3a8eb9SGleb Smirnoff 	}
3593b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
3603b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
3613b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
3623b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = addr;
3633b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*addr);
3643b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
3653b3a8eb9SGleb Smirnoff 	io.pfrio_ticket = ticket;
3663b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRINADEFINE, &io))
3673b3a8eb9SGleb Smirnoff 		return (-1);
3683b3a8eb9SGleb Smirnoff 	if (nadd != NULL)
3693b3a8eb9SGleb Smirnoff 		*nadd = io.pfrio_nadd;
3703b3a8eb9SGleb Smirnoff 	if (naddr != NULL)
3713b3a8eb9SGleb Smirnoff 		*naddr = io.pfrio_naddr;
3723b3a8eb9SGleb Smirnoff 	return (0);
3733b3a8eb9SGleb Smirnoff }
3743b3a8eb9SGleb Smirnoff 
3753b3a8eb9SGleb Smirnoff /* interface management code */
3763b3a8eb9SGleb Smirnoff 
3773b3a8eb9SGleb Smirnoff int
3783b3a8eb9SGleb Smirnoff pfi_get_ifaces(const char *filter, struct pfi_kif *buf, int *size)
3793b3a8eb9SGleb Smirnoff {
3803b3a8eb9SGleb Smirnoff 	struct pfioc_iface io;
3813b3a8eb9SGleb Smirnoff 
3823b3a8eb9SGleb Smirnoff 	if (size == NULL || *size < 0 || (*size && buf == NULL)) {
3833b3a8eb9SGleb Smirnoff 		errno = EINVAL;
3843b3a8eb9SGleb Smirnoff 		return (-1);
3853b3a8eb9SGleb Smirnoff 	}
3863b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
3873b3a8eb9SGleb Smirnoff 	if (filter != NULL)
3883b3a8eb9SGleb Smirnoff 		if (strlcpy(io.pfiio_name, filter, sizeof(io.pfiio_name)) >=
3893b3a8eb9SGleb Smirnoff 		    sizeof(io.pfiio_name)) {
3903b3a8eb9SGleb Smirnoff 			errno = EINVAL;
3913b3a8eb9SGleb Smirnoff 			return (-1);
3923b3a8eb9SGleb Smirnoff 		}
3933b3a8eb9SGleb Smirnoff 	io.pfiio_buffer = buf;
3943b3a8eb9SGleb Smirnoff 	io.pfiio_esize = sizeof(*buf);
3953b3a8eb9SGleb Smirnoff 	io.pfiio_size = *size;
3963b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCIGETIFACES, &io))
3973b3a8eb9SGleb Smirnoff 		return (-1);
3983b3a8eb9SGleb Smirnoff 	*size = io.pfiio_size;
3993b3a8eb9SGleb Smirnoff 	return (0);
4003b3a8eb9SGleb Smirnoff }
4013b3a8eb9SGleb Smirnoff 
4023b3a8eb9SGleb Smirnoff /* buffer management code */
4033b3a8eb9SGleb Smirnoff 
404*72a3cf0fSKristof Provost const size_t buf_esize[PFRB_MAX] = { 0,
4053b3a8eb9SGleb Smirnoff 	sizeof(struct pfr_table), sizeof(struct pfr_tstats),
4063b3a8eb9SGleb Smirnoff 	sizeof(struct pfr_addr), sizeof(struct pfr_astats),
4073b3a8eb9SGleb Smirnoff 	sizeof(struct pfi_kif), sizeof(struct pfioc_trans_e)
4083b3a8eb9SGleb Smirnoff };
4093b3a8eb9SGleb Smirnoff 
4103b3a8eb9SGleb Smirnoff /*
4113b3a8eb9SGleb Smirnoff  * add one element to the buffer
4123b3a8eb9SGleb Smirnoff  */
4133b3a8eb9SGleb Smirnoff int
4143b3a8eb9SGleb Smirnoff pfr_buf_add(struct pfr_buffer *b, const void *e)
4153b3a8eb9SGleb Smirnoff {
4163b3a8eb9SGleb Smirnoff 	size_t bs;
4173b3a8eb9SGleb Smirnoff 
4183b3a8eb9SGleb Smirnoff 	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX ||
4193b3a8eb9SGleb Smirnoff 	    e == NULL) {
4203b3a8eb9SGleb Smirnoff 		errno = EINVAL;
4213b3a8eb9SGleb Smirnoff 		return (-1);
4223b3a8eb9SGleb Smirnoff 	}
4233b3a8eb9SGleb Smirnoff 	bs = buf_esize[b->pfrb_type];
4243b3a8eb9SGleb Smirnoff 	if (b->pfrb_size == b->pfrb_msize)
4253b3a8eb9SGleb Smirnoff 		if (pfr_buf_grow(b, 0))
4263b3a8eb9SGleb Smirnoff 			return (-1);
4273b3a8eb9SGleb Smirnoff 	memcpy(((caddr_t)b->pfrb_caddr) + bs * b->pfrb_size, e, bs);
4283b3a8eb9SGleb Smirnoff 	b->pfrb_size++;
4293b3a8eb9SGleb Smirnoff 	return (0);
4303b3a8eb9SGleb Smirnoff }
4313b3a8eb9SGleb Smirnoff 
4323b3a8eb9SGleb Smirnoff /*
4333b3a8eb9SGleb Smirnoff  * return next element of the buffer (or first one if prev is NULL)
4343b3a8eb9SGleb Smirnoff  * see PFRB_FOREACH macro
4353b3a8eb9SGleb Smirnoff  */
4363b3a8eb9SGleb Smirnoff void *
4373b3a8eb9SGleb Smirnoff pfr_buf_next(struct pfr_buffer *b, const void *prev)
4383b3a8eb9SGleb Smirnoff {
4393b3a8eb9SGleb Smirnoff 	size_t bs;
4403b3a8eb9SGleb Smirnoff 
4413b3a8eb9SGleb Smirnoff 	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX)
4423b3a8eb9SGleb Smirnoff 		return (NULL);
4433b3a8eb9SGleb Smirnoff 	if (b->pfrb_size == 0)
4443b3a8eb9SGleb Smirnoff 		return (NULL);
4453b3a8eb9SGleb Smirnoff 	if (prev == NULL)
4463b3a8eb9SGleb Smirnoff 		return (b->pfrb_caddr);
4473b3a8eb9SGleb Smirnoff 	bs = buf_esize[b->pfrb_type];
4483b3a8eb9SGleb Smirnoff 	if ((((caddr_t)prev)-((caddr_t)b->pfrb_caddr)) / bs >= b->pfrb_size-1)
4493b3a8eb9SGleb Smirnoff 		return (NULL);
4503b3a8eb9SGleb Smirnoff 	return (((caddr_t)prev) + bs);
4513b3a8eb9SGleb Smirnoff }
4523b3a8eb9SGleb Smirnoff 
4533b3a8eb9SGleb Smirnoff /*
4543b3a8eb9SGleb Smirnoff  * minsize:
4553b3a8eb9SGleb Smirnoff  *    0: make the buffer somewhat bigger
4563b3a8eb9SGleb Smirnoff  *    n: make room for "n" entries in the buffer
4573b3a8eb9SGleb Smirnoff  */
4583b3a8eb9SGleb Smirnoff int
4593b3a8eb9SGleb Smirnoff pfr_buf_grow(struct pfr_buffer *b, int minsize)
4603b3a8eb9SGleb Smirnoff {
4613b3a8eb9SGleb Smirnoff 	caddr_t p;
4623b3a8eb9SGleb Smirnoff 	size_t bs;
4633b3a8eb9SGleb Smirnoff 
4643b3a8eb9SGleb Smirnoff 	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX) {
4653b3a8eb9SGleb Smirnoff 		errno = EINVAL;
4663b3a8eb9SGleb Smirnoff 		return (-1);
4673b3a8eb9SGleb Smirnoff 	}
4683b3a8eb9SGleb Smirnoff 	if (minsize != 0 && minsize <= b->pfrb_msize)
4693b3a8eb9SGleb Smirnoff 		return (0);
4703b3a8eb9SGleb Smirnoff 	bs = buf_esize[b->pfrb_type];
4713b3a8eb9SGleb Smirnoff 	if (!b->pfrb_msize) {
4723b3a8eb9SGleb Smirnoff 		if (minsize < 64)
4733b3a8eb9SGleb Smirnoff 			minsize = 64;
4743b3a8eb9SGleb Smirnoff 		b->pfrb_caddr = calloc(bs, minsize);
4753b3a8eb9SGleb Smirnoff 		if (b->pfrb_caddr == NULL)
4763b3a8eb9SGleb Smirnoff 			return (-1);
4773b3a8eb9SGleb Smirnoff 		b->pfrb_msize = minsize;
4783b3a8eb9SGleb Smirnoff 	} else {
4793b3a8eb9SGleb Smirnoff 		if (minsize == 0)
4803b3a8eb9SGleb Smirnoff 			minsize = b->pfrb_msize * 2;
4813b3a8eb9SGleb Smirnoff 		if (minsize < 0 || minsize >= SIZE_T_MAX / bs) {
4823b3a8eb9SGleb Smirnoff 			/* msize overflow */
4833b3a8eb9SGleb Smirnoff 			errno = ENOMEM;
4843b3a8eb9SGleb Smirnoff 			return (-1);
4853b3a8eb9SGleb Smirnoff 		}
4863b3a8eb9SGleb Smirnoff 		p = realloc(b->pfrb_caddr, minsize * bs);
4873b3a8eb9SGleb Smirnoff 		if (p == NULL)
4883b3a8eb9SGleb Smirnoff 			return (-1);
4893b3a8eb9SGleb Smirnoff 		bzero(p + b->pfrb_msize * bs, (minsize - b->pfrb_msize) * bs);
4903b3a8eb9SGleb Smirnoff 		b->pfrb_caddr = p;
4913b3a8eb9SGleb Smirnoff 		b->pfrb_msize = minsize;
4923b3a8eb9SGleb Smirnoff 	}
4933b3a8eb9SGleb Smirnoff 	return (0);
4943b3a8eb9SGleb Smirnoff }
4953b3a8eb9SGleb Smirnoff 
4963b3a8eb9SGleb Smirnoff /*
4973b3a8eb9SGleb Smirnoff  * reset buffer and free memory.
4983b3a8eb9SGleb Smirnoff  */
4993b3a8eb9SGleb Smirnoff void
5003b3a8eb9SGleb Smirnoff pfr_buf_clear(struct pfr_buffer *b)
5013b3a8eb9SGleb Smirnoff {
5023b3a8eb9SGleb Smirnoff 	if (b == NULL)
5033b3a8eb9SGleb Smirnoff 		return;
5043b3a8eb9SGleb Smirnoff 	if (b->pfrb_caddr != NULL)
5053b3a8eb9SGleb Smirnoff 		free(b->pfrb_caddr);
5063b3a8eb9SGleb Smirnoff 	b->pfrb_caddr = NULL;
5073b3a8eb9SGleb Smirnoff 	b->pfrb_size = b->pfrb_msize = 0;
5083b3a8eb9SGleb Smirnoff }
5093b3a8eb9SGleb Smirnoff 
5103b3a8eb9SGleb Smirnoff int
5113b3a8eb9SGleb Smirnoff pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork,
5123b3a8eb9SGleb Smirnoff     int (*append_addr)(struct pfr_buffer *, char *, int))
5133b3a8eb9SGleb Smirnoff {
5143b3a8eb9SGleb Smirnoff 	FILE	*fp;
5153b3a8eb9SGleb Smirnoff 	char	 buf[BUF_SIZE];
5163b3a8eb9SGleb Smirnoff 	int	 rv;
5173b3a8eb9SGleb Smirnoff 
5183b3a8eb9SGleb Smirnoff 	if (file == NULL)
5193b3a8eb9SGleb Smirnoff 		return (0);
5203b3a8eb9SGleb Smirnoff 	if (!strcmp(file, "-"))
5213b3a8eb9SGleb Smirnoff 		fp = stdin;
5223b3a8eb9SGleb Smirnoff 	else {
5233b3a8eb9SGleb Smirnoff 		fp = pfctl_fopen(file, "r");
5243b3a8eb9SGleb Smirnoff 		if (fp == NULL)
5253b3a8eb9SGleb Smirnoff 			return (-1);
5263b3a8eb9SGleb Smirnoff 	}
5273b3a8eb9SGleb Smirnoff 	while ((rv = pfr_next_token(buf, fp)) == 1)
5283b3a8eb9SGleb Smirnoff 		if (append_addr(b, buf, nonetwork)) {
5293b3a8eb9SGleb Smirnoff 			rv = -1;
5303b3a8eb9SGleb Smirnoff 			break;
5313b3a8eb9SGleb Smirnoff 		}
5323b3a8eb9SGleb Smirnoff 	if (fp != stdin)
5333b3a8eb9SGleb Smirnoff 		fclose(fp);
5343b3a8eb9SGleb Smirnoff 	return (rv);
5353b3a8eb9SGleb Smirnoff }
5363b3a8eb9SGleb Smirnoff 
5373b3a8eb9SGleb Smirnoff int
5383b3a8eb9SGleb Smirnoff pfr_next_token(char buf[BUF_SIZE], FILE *fp)
5393b3a8eb9SGleb Smirnoff {
5403b3a8eb9SGleb Smirnoff 	static char	next_ch = ' ';
5413b3a8eb9SGleb Smirnoff 	int		i = 0;
5423b3a8eb9SGleb Smirnoff 
5433b3a8eb9SGleb Smirnoff 	for (;;) {
5443b3a8eb9SGleb Smirnoff 		/* skip spaces */
5453b3a8eb9SGleb Smirnoff 		while (isspace(next_ch) && !feof(fp))
5463b3a8eb9SGleb Smirnoff 			next_ch = fgetc(fp);
5473b3a8eb9SGleb Smirnoff 		/* remove from '#' until end of line */
5483b3a8eb9SGleb Smirnoff 		if (next_ch == '#')
5493b3a8eb9SGleb Smirnoff 			while (!feof(fp)) {
5503b3a8eb9SGleb Smirnoff 				next_ch = fgetc(fp);
5513b3a8eb9SGleb Smirnoff 				if (next_ch == '\n')
5523b3a8eb9SGleb Smirnoff 					break;
5533b3a8eb9SGleb Smirnoff 			}
5543b3a8eb9SGleb Smirnoff 		else
5553b3a8eb9SGleb Smirnoff 			break;
5563b3a8eb9SGleb Smirnoff 	}
5573b3a8eb9SGleb Smirnoff 	if (feof(fp)) {
5583b3a8eb9SGleb Smirnoff 		next_ch = ' ';
5593b3a8eb9SGleb Smirnoff 		return (0);
5603b3a8eb9SGleb Smirnoff 	}
5613b3a8eb9SGleb Smirnoff 	do {
5623b3a8eb9SGleb Smirnoff 		if (i < BUF_SIZE)
5633b3a8eb9SGleb Smirnoff 			buf[i++] = next_ch;
5643b3a8eb9SGleb Smirnoff 		next_ch = fgetc(fp);
5653b3a8eb9SGleb Smirnoff 	} while (!feof(fp) && !isspace(next_ch));
5663b3a8eb9SGleb Smirnoff 	if (i >= BUF_SIZE) {
5673b3a8eb9SGleb Smirnoff 		errno = EINVAL;
5683b3a8eb9SGleb Smirnoff 		return (-1);
5693b3a8eb9SGleb Smirnoff 	}
5703b3a8eb9SGleb Smirnoff 	buf[i] = '\0';
5713b3a8eb9SGleb Smirnoff 	return (1);
5723b3a8eb9SGleb Smirnoff }
5733b3a8eb9SGleb Smirnoff 
5743b3a8eb9SGleb Smirnoff char *
5753b3a8eb9SGleb Smirnoff pfr_strerror(int errnum)
5763b3a8eb9SGleb Smirnoff {
5773b3a8eb9SGleb Smirnoff 	switch (errnum) {
5783b3a8eb9SGleb Smirnoff 	case ESRCH:
5793b3a8eb9SGleb Smirnoff 		return "Table does not exist";
5803b3a8eb9SGleb Smirnoff 	case ENOENT:
5813b3a8eb9SGleb Smirnoff 		return "Anchor or Ruleset does not exist";
5823b3a8eb9SGleb Smirnoff 	default:
5833b3a8eb9SGleb Smirnoff 		return strerror(errnum);
5843b3a8eb9SGleb Smirnoff 	}
5853b3a8eb9SGleb Smirnoff }
586