xref: /freebsd/sbin/pfctl/pfctl_radix.c (revision 3b3a8eb937bf8045231e8364bfd1b94cd4a95979)
1*3b3a8eb9SGleb Smirnoff /*	$OpenBSD: pfctl_radix.c,v 1.27 2005/05/21 21:03:58 henning Exp $ */
2*3b3a8eb9SGleb Smirnoff 
3*3b3a8eb9SGleb Smirnoff /*
4*3b3a8eb9SGleb Smirnoff  * Copyright (c) 2002 Cedric Berger
5*3b3a8eb9SGleb Smirnoff  * All rights reserved.
6*3b3a8eb9SGleb Smirnoff  *
7*3b3a8eb9SGleb Smirnoff  * Redistribution and use in source and binary forms, with or without
8*3b3a8eb9SGleb Smirnoff  * modification, are permitted provided that the following conditions
9*3b3a8eb9SGleb Smirnoff  * are met:
10*3b3a8eb9SGleb Smirnoff  *
11*3b3a8eb9SGleb Smirnoff  *    - Redistributions of source code must retain the above copyright
12*3b3a8eb9SGleb Smirnoff  *      notice, this list of conditions and the following disclaimer.
13*3b3a8eb9SGleb Smirnoff  *    - Redistributions in binary form must reproduce the above
14*3b3a8eb9SGleb Smirnoff  *      copyright notice, this list of conditions and the following
15*3b3a8eb9SGleb Smirnoff  *      disclaimer in the documentation and/or other materials provided
16*3b3a8eb9SGleb Smirnoff  *      with the distribution.
17*3b3a8eb9SGleb Smirnoff  *
18*3b3a8eb9SGleb Smirnoff  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19*3b3a8eb9SGleb Smirnoff  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20*3b3a8eb9SGleb Smirnoff  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21*3b3a8eb9SGleb Smirnoff  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22*3b3a8eb9SGleb Smirnoff  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23*3b3a8eb9SGleb Smirnoff  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24*3b3a8eb9SGleb Smirnoff  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25*3b3a8eb9SGleb Smirnoff  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26*3b3a8eb9SGleb Smirnoff  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*3b3a8eb9SGleb Smirnoff  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28*3b3a8eb9SGleb Smirnoff  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*3b3a8eb9SGleb Smirnoff  * POSSIBILITY OF SUCH DAMAGE.
30*3b3a8eb9SGleb Smirnoff  *
31*3b3a8eb9SGleb Smirnoff  */
32*3b3a8eb9SGleb Smirnoff 
33*3b3a8eb9SGleb Smirnoff #include <sys/cdefs.h>
34*3b3a8eb9SGleb Smirnoff __FBSDID("$FreeBSD$");
35*3b3a8eb9SGleb Smirnoff 
36*3b3a8eb9SGleb Smirnoff #include <sys/types.h>
37*3b3a8eb9SGleb Smirnoff #include <sys/ioctl.h>
38*3b3a8eb9SGleb Smirnoff #include <sys/socket.h>
39*3b3a8eb9SGleb Smirnoff 
40*3b3a8eb9SGleb Smirnoff #include <net/if.h>
41*3b3a8eb9SGleb Smirnoff #include <net/pfvar.h>
42*3b3a8eb9SGleb Smirnoff 
43*3b3a8eb9SGleb Smirnoff #include <errno.h>
44*3b3a8eb9SGleb Smirnoff #include <string.h>
45*3b3a8eb9SGleb Smirnoff #include <ctype.h>
46*3b3a8eb9SGleb Smirnoff #include <stdio.h>
47*3b3a8eb9SGleb Smirnoff #include <stdlib.h>
48*3b3a8eb9SGleb Smirnoff #include <limits.h>
49*3b3a8eb9SGleb Smirnoff #include <err.h>
50*3b3a8eb9SGleb Smirnoff 
51*3b3a8eb9SGleb Smirnoff #include "pfctl.h"
52*3b3a8eb9SGleb Smirnoff 
53*3b3a8eb9SGleb Smirnoff #define BUF_SIZE 256
54*3b3a8eb9SGleb Smirnoff 
55*3b3a8eb9SGleb Smirnoff extern int dev;
56*3b3a8eb9SGleb Smirnoff 
57*3b3a8eb9SGleb Smirnoff static int	 pfr_next_token(char buf[], FILE *);
58*3b3a8eb9SGleb Smirnoff 
59*3b3a8eb9SGleb Smirnoff 
60*3b3a8eb9SGleb Smirnoff int
61*3b3a8eb9SGleb Smirnoff pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
62*3b3a8eb9SGleb Smirnoff {
63*3b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
64*3b3a8eb9SGleb Smirnoff 
65*3b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
66*3b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
67*3b3a8eb9SGleb Smirnoff 	if (filter != NULL)
68*3b3a8eb9SGleb Smirnoff 		io.pfrio_table = *filter;
69*3b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRCLRTABLES, &io))
70*3b3a8eb9SGleb Smirnoff 		return (-1);
71*3b3a8eb9SGleb Smirnoff 	if (ndel != NULL)
72*3b3a8eb9SGleb Smirnoff 		*ndel = io.pfrio_ndel;
73*3b3a8eb9SGleb Smirnoff 	return (0);
74*3b3a8eb9SGleb Smirnoff }
75*3b3a8eb9SGleb Smirnoff 
76*3b3a8eb9SGleb Smirnoff int
77*3b3a8eb9SGleb Smirnoff pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
78*3b3a8eb9SGleb Smirnoff {
79*3b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
80*3b3a8eb9SGleb Smirnoff 
81*3b3a8eb9SGleb Smirnoff 	if (size < 0 || (size && tbl == NULL)) {
82*3b3a8eb9SGleb Smirnoff 		errno = EINVAL;
83*3b3a8eb9SGleb Smirnoff 		return (-1);
84*3b3a8eb9SGleb Smirnoff 	}
85*3b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
86*3b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
87*3b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = tbl;
88*3b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*tbl);
89*3b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
90*3b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRADDTABLES, &io))
91*3b3a8eb9SGleb Smirnoff 		return (-1);
92*3b3a8eb9SGleb Smirnoff 	if (nadd != NULL)
93*3b3a8eb9SGleb Smirnoff 		*nadd = io.pfrio_nadd;
94*3b3a8eb9SGleb Smirnoff 	return (0);
95*3b3a8eb9SGleb Smirnoff }
96*3b3a8eb9SGleb Smirnoff 
97*3b3a8eb9SGleb Smirnoff int
98*3b3a8eb9SGleb Smirnoff pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
99*3b3a8eb9SGleb Smirnoff {
100*3b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
101*3b3a8eb9SGleb Smirnoff 
102*3b3a8eb9SGleb Smirnoff 	if (size < 0 || (size && tbl == NULL)) {
103*3b3a8eb9SGleb Smirnoff 		errno = EINVAL;
104*3b3a8eb9SGleb Smirnoff 		return (-1);
105*3b3a8eb9SGleb Smirnoff 	}
106*3b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
107*3b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
108*3b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = tbl;
109*3b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*tbl);
110*3b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
111*3b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRDELTABLES, &io))
112*3b3a8eb9SGleb Smirnoff 		return (-1);
113*3b3a8eb9SGleb Smirnoff 	if (ndel != NULL)
114*3b3a8eb9SGleb Smirnoff 		*ndel = io.pfrio_ndel;
115*3b3a8eb9SGleb Smirnoff 	return (0);
116*3b3a8eb9SGleb Smirnoff }
117*3b3a8eb9SGleb Smirnoff 
118*3b3a8eb9SGleb Smirnoff int
119*3b3a8eb9SGleb Smirnoff pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
120*3b3a8eb9SGleb Smirnoff 	int flags)
121*3b3a8eb9SGleb Smirnoff {
122*3b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
123*3b3a8eb9SGleb Smirnoff 
124*3b3a8eb9SGleb Smirnoff 	if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
125*3b3a8eb9SGleb Smirnoff 		errno = EINVAL;
126*3b3a8eb9SGleb Smirnoff 		return (-1);
127*3b3a8eb9SGleb Smirnoff 	}
128*3b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
129*3b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
130*3b3a8eb9SGleb Smirnoff 	if (filter != NULL)
131*3b3a8eb9SGleb Smirnoff 		io.pfrio_table = *filter;
132*3b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = tbl;
133*3b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*tbl);
134*3b3a8eb9SGleb Smirnoff 	io.pfrio_size = *size;
135*3b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRGETTABLES, &io))
136*3b3a8eb9SGleb Smirnoff 		return (-1);
137*3b3a8eb9SGleb Smirnoff 	*size = io.pfrio_size;
138*3b3a8eb9SGleb Smirnoff 	return (0);
139*3b3a8eb9SGleb Smirnoff }
140*3b3a8eb9SGleb Smirnoff 
141*3b3a8eb9SGleb Smirnoff int
142*3b3a8eb9SGleb Smirnoff pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
143*3b3a8eb9SGleb Smirnoff 	int flags)
144*3b3a8eb9SGleb Smirnoff {
145*3b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
146*3b3a8eb9SGleb Smirnoff 
147*3b3a8eb9SGleb Smirnoff 	if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
148*3b3a8eb9SGleb Smirnoff 		errno = EINVAL;
149*3b3a8eb9SGleb Smirnoff 		return (-1);
150*3b3a8eb9SGleb Smirnoff 	}
151*3b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
152*3b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
153*3b3a8eb9SGleb Smirnoff 	if (filter != NULL)
154*3b3a8eb9SGleb Smirnoff 		io.pfrio_table = *filter;
155*3b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = tbl;
156*3b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*tbl);
157*3b3a8eb9SGleb Smirnoff 	io.pfrio_size = *size;
158*3b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRGETTSTATS, &io))
159*3b3a8eb9SGleb Smirnoff 		return (-1);
160*3b3a8eb9SGleb Smirnoff 	*size = io.pfrio_size;
161*3b3a8eb9SGleb Smirnoff 	return (0);
162*3b3a8eb9SGleb Smirnoff }
163*3b3a8eb9SGleb Smirnoff 
164*3b3a8eb9SGleb Smirnoff int
165*3b3a8eb9SGleb Smirnoff pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
166*3b3a8eb9SGleb Smirnoff {
167*3b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
168*3b3a8eb9SGleb Smirnoff 
169*3b3a8eb9SGleb Smirnoff 	if (tbl == NULL) {
170*3b3a8eb9SGleb Smirnoff 		errno = EINVAL;
171*3b3a8eb9SGleb Smirnoff 		return (-1);
172*3b3a8eb9SGleb Smirnoff 	}
173*3b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
174*3b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
175*3b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
176*3b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRCLRADDRS, &io))
177*3b3a8eb9SGleb Smirnoff 		return (-1);
178*3b3a8eb9SGleb Smirnoff 	if (ndel != NULL)
179*3b3a8eb9SGleb Smirnoff 		*ndel = io.pfrio_ndel;
180*3b3a8eb9SGleb Smirnoff 	return (0);
181*3b3a8eb9SGleb Smirnoff }
182*3b3a8eb9SGleb Smirnoff 
183*3b3a8eb9SGleb Smirnoff int
184*3b3a8eb9SGleb Smirnoff pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
185*3b3a8eb9SGleb Smirnoff     int *nadd, int flags)
186*3b3a8eb9SGleb Smirnoff {
187*3b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
188*3b3a8eb9SGleb Smirnoff 
189*3b3a8eb9SGleb Smirnoff 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
190*3b3a8eb9SGleb Smirnoff 		errno = EINVAL;
191*3b3a8eb9SGleb Smirnoff 		return (-1);
192*3b3a8eb9SGleb Smirnoff 	}
193*3b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
194*3b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
195*3b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
196*3b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = addr;
197*3b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*addr);
198*3b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
199*3b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRADDADDRS, &io))
200*3b3a8eb9SGleb Smirnoff 		return (-1);
201*3b3a8eb9SGleb Smirnoff 	if (nadd != NULL)
202*3b3a8eb9SGleb Smirnoff 		*nadd = io.pfrio_nadd;
203*3b3a8eb9SGleb Smirnoff 	return (0);
204*3b3a8eb9SGleb Smirnoff }
205*3b3a8eb9SGleb Smirnoff 
206*3b3a8eb9SGleb Smirnoff int
207*3b3a8eb9SGleb Smirnoff pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
208*3b3a8eb9SGleb Smirnoff     int *ndel, int flags)
209*3b3a8eb9SGleb Smirnoff {
210*3b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
211*3b3a8eb9SGleb Smirnoff 
212*3b3a8eb9SGleb Smirnoff 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
213*3b3a8eb9SGleb Smirnoff 		errno = EINVAL;
214*3b3a8eb9SGleb Smirnoff 		return (-1);
215*3b3a8eb9SGleb Smirnoff 	}
216*3b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
217*3b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
218*3b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
219*3b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = addr;
220*3b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*addr);
221*3b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
222*3b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRDELADDRS, &io))
223*3b3a8eb9SGleb Smirnoff 		return (-1);
224*3b3a8eb9SGleb Smirnoff 	if (ndel != NULL)
225*3b3a8eb9SGleb Smirnoff 		*ndel = io.pfrio_ndel;
226*3b3a8eb9SGleb Smirnoff 	return (0);
227*3b3a8eb9SGleb Smirnoff }
228*3b3a8eb9SGleb Smirnoff 
229*3b3a8eb9SGleb Smirnoff int
230*3b3a8eb9SGleb Smirnoff pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
231*3b3a8eb9SGleb Smirnoff     int *size2, int *nadd, int *ndel, int *nchange, int flags)
232*3b3a8eb9SGleb Smirnoff {
233*3b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
234*3b3a8eb9SGleb Smirnoff 
235*3b3a8eb9SGleb Smirnoff 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
236*3b3a8eb9SGleb Smirnoff 		errno = EINVAL;
237*3b3a8eb9SGleb Smirnoff 		return (-1);
238*3b3a8eb9SGleb Smirnoff 	}
239*3b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
240*3b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
241*3b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
242*3b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = addr;
243*3b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*addr);
244*3b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
245*3b3a8eb9SGleb Smirnoff 	io.pfrio_size2 = (size2 != NULL) ? *size2 : 0;
246*3b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRSETADDRS, &io))
247*3b3a8eb9SGleb Smirnoff 		return (-1);
248*3b3a8eb9SGleb Smirnoff 	if (nadd != NULL)
249*3b3a8eb9SGleb Smirnoff 		*nadd = io.pfrio_nadd;
250*3b3a8eb9SGleb Smirnoff 	if (ndel != NULL)
251*3b3a8eb9SGleb Smirnoff 		*ndel = io.pfrio_ndel;
252*3b3a8eb9SGleb Smirnoff 	if (nchange != NULL)
253*3b3a8eb9SGleb Smirnoff 		*nchange = io.pfrio_nchange;
254*3b3a8eb9SGleb Smirnoff 	if (size2 != NULL)
255*3b3a8eb9SGleb Smirnoff 		*size2 = io.pfrio_size2;
256*3b3a8eb9SGleb Smirnoff 	return (0);
257*3b3a8eb9SGleb Smirnoff }
258*3b3a8eb9SGleb Smirnoff 
259*3b3a8eb9SGleb Smirnoff int
260*3b3a8eb9SGleb Smirnoff pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
261*3b3a8eb9SGleb Smirnoff     int flags)
262*3b3a8eb9SGleb Smirnoff {
263*3b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
264*3b3a8eb9SGleb Smirnoff 
265*3b3a8eb9SGleb Smirnoff 	if (tbl == NULL || size == NULL || *size < 0 ||
266*3b3a8eb9SGleb Smirnoff 	    (*size && addr == NULL)) {
267*3b3a8eb9SGleb Smirnoff 		errno = EINVAL;
268*3b3a8eb9SGleb Smirnoff 		return (-1);
269*3b3a8eb9SGleb Smirnoff 	}
270*3b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
271*3b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
272*3b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
273*3b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = addr;
274*3b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*addr);
275*3b3a8eb9SGleb Smirnoff 	io.pfrio_size = *size;
276*3b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRGETADDRS, &io))
277*3b3a8eb9SGleb Smirnoff 		return (-1);
278*3b3a8eb9SGleb Smirnoff 	*size = io.pfrio_size;
279*3b3a8eb9SGleb Smirnoff 	return (0);
280*3b3a8eb9SGleb Smirnoff }
281*3b3a8eb9SGleb Smirnoff 
282*3b3a8eb9SGleb Smirnoff int
283*3b3a8eb9SGleb Smirnoff pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
284*3b3a8eb9SGleb Smirnoff     int flags)
285*3b3a8eb9SGleb Smirnoff {
286*3b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
287*3b3a8eb9SGleb Smirnoff 
288*3b3a8eb9SGleb Smirnoff 	if (tbl == NULL || size == NULL || *size < 0 ||
289*3b3a8eb9SGleb Smirnoff 	    (*size && addr == NULL)) {
290*3b3a8eb9SGleb Smirnoff 		errno = EINVAL;
291*3b3a8eb9SGleb Smirnoff 		return (-1);
292*3b3a8eb9SGleb Smirnoff 	}
293*3b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
294*3b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
295*3b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
296*3b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = addr;
297*3b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*addr);
298*3b3a8eb9SGleb Smirnoff 	io.pfrio_size = *size;
299*3b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRGETASTATS, &io))
300*3b3a8eb9SGleb Smirnoff 		return (-1);
301*3b3a8eb9SGleb Smirnoff 	*size = io.pfrio_size;
302*3b3a8eb9SGleb Smirnoff 	return (0);
303*3b3a8eb9SGleb Smirnoff }
304*3b3a8eb9SGleb Smirnoff 
305*3b3a8eb9SGleb Smirnoff int
306*3b3a8eb9SGleb Smirnoff pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
307*3b3a8eb9SGleb Smirnoff {
308*3b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
309*3b3a8eb9SGleb Smirnoff 
310*3b3a8eb9SGleb Smirnoff 	if (size < 0 || (size && !tbl)) {
311*3b3a8eb9SGleb Smirnoff 		errno = EINVAL;
312*3b3a8eb9SGleb Smirnoff 		return (-1);
313*3b3a8eb9SGleb Smirnoff 	}
314*3b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
315*3b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
316*3b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = tbl;
317*3b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*tbl);
318*3b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
319*3b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRCLRTSTATS, &io))
320*3b3a8eb9SGleb Smirnoff 		return (-1);
321*3b3a8eb9SGleb Smirnoff 	if (nzero)
322*3b3a8eb9SGleb Smirnoff 		*nzero = io.pfrio_nzero;
323*3b3a8eb9SGleb Smirnoff 	return (0);
324*3b3a8eb9SGleb Smirnoff }
325*3b3a8eb9SGleb Smirnoff 
326*3b3a8eb9SGleb Smirnoff int
327*3b3a8eb9SGleb Smirnoff pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
328*3b3a8eb9SGleb Smirnoff     int *nmatch, int flags)
329*3b3a8eb9SGleb Smirnoff {
330*3b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
331*3b3a8eb9SGleb Smirnoff 
332*3b3a8eb9SGleb Smirnoff 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
333*3b3a8eb9SGleb Smirnoff 		errno = EINVAL;
334*3b3a8eb9SGleb Smirnoff 		return (-1);
335*3b3a8eb9SGleb Smirnoff 	}
336*3b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
337*3b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
338*3b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
339*3b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = addr;
340*3b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*addr);
341*3b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
342*3b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRTSTADDRS, &io))
343*3b3a8eb9SGleb Smirnoff 		return (-1);
344*3b3a8eb9SGleb Smirnoff 	if (nmatch)
345*3b3a8eb9SGleb Smirnoff 		*nmatch = io.pfrio_nmatch;
346*3b3a8eb9SGleb Smirnoff 	return (0);
347*3b3a8eb9SGleb Smirnoff }
348*3b3a8eb9SGleb Smirnoff 
349*3b3a8eb9SGleb Smirnoff int
350*3b3a8eb9SGleb Smirnoff pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
351*3b3a8eb9SGleb Smirnoff     int *nadd, int *naddr, int ticket, int flags)
352*3b3a8eb9SGleb Smirnoff {
353*3b3a8eb9SGleb Smirnoff 	struct pfioc_table io;
354*3b3a8eb9SGleb Smirnoff 
355*3b3a8eb9SGleb Smirnoff 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
356*3b3a8eb9SGleb Smirnoff 		errno = EINVAL;
357*3b3a8eb9SGleb Smirnoff 		return (-1);
358*3b3a8eb9SGleb Smirnoff 	}
359*3b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
360*3b3a8eb9SGleb Smirnoff 	io.pfrio_flags = flags;
361*3b3a8eb9SGleb Smirnoff 	io.pfrio_table = *tbl;
362*3b3a8eb9SGleb Smirnoff 	io.pfrio_buffer = addr;
363*3b3a8eb9SGleb Smirnoff 	io.pfrio_esize = sizeof(*addr);
364*3b3a8eb9SGleb Smirnoff 	io.pfrio_size = size;
365*3b3a8eb9SGleb Smirnoff 	io.pfrio_ticket = ticket;
366*3b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCRINADEFINE, &io))
367*3b3a8eb9SGleb Smirnoff 		return (-1);
368*3b3a8eb9SGleb Smirnoff 	if (nadd != NULL)
369*3b3a8eb9SGleb Smirnoff 		*nadd = io.pfrio_nadd;
370*3b3a8eb9SGleb Smirnoff 	if (naddr != NULL)
371*3b3a8eb9SGleb Smirnoff 		*naddr = io.pfrio_naddr;
372*3b3a8eb9SGleb Smirnoff 	return (0);
373*3b3a8eb9SGleb Smirnoff }
374*3b3a8eb9SGleb Smirnoff 
375*3b3a8eb9SGleb Smirnoff /* interface management code */
376*3b3a8eb9SGleb Smirnoff 
377*3b3a8eb9SGleb Smirnoff int
378*3b3a8eb9SGleb Smirnoff pfi_get_ifaces(const char *filter, struct pfi_kif *buf, int *size)
379*3b3a8eb9SGleb Smirnoff {
380*3b3a8eb9SGleb Smirnoff 	struct pfioc_iface io;
381*3b3a8eb9SGleb Smirnoff 
382*3b3a8eb9SGleb Smirnoff 	if (size == NULL || *size < 0 || (*size && buf == NULL)) {
383*3b3a8eb9SGleb Smirnoff 		errno = EINVAL;
384*3b3a8eb9SGleb Smirnoff 		return (-1);
385*3b3a8eb9SGleb Smirnoff 	}
386*3b3a8eb9SGleb Smirnoff 	bzero(&io, sizeof io);
387*3b3a8eb9SGleb Smirnoff 	if (filter != NULL)
388*3b3a8eb9SGleb Smirnoff 		if (strlcpy(io.pfiio_name, filter, sizeof(io.pfiio_name)) >=
389*3b3a8eb9SGleb Smirnoff 		    sizeof(io.pfiio_name)) {
390*3b3a8eb9SGleb Smirnoff 			errno = EINVAL;
391*3b3a8eb9SGleb Smirnoff 			return (-1);
392*3b3a8eb9SGleb Smirnoff 		}
393*3b3a8eb9SGleb Smirnoff 	io.pfiio_buffer = buf;
394*3b3a8eb9SGleb Smirnoff 	io.pfiio_esize = sizeof(*buf);
395*3b3a8eb9SGleb Smirnoff 	io.pfiio_size = *size;
396*3b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCIGETIFACES, &io))
397*3b3a8eb9SGleb Smirnoff 		return (-1);
398*3b3a8eb9SGleb Smirnoff 	*size = io.pfiio_size;
399*3b3a8eb9SGleb Smirnoff 	return (0);
400*3b3a8eb9SGleb Smirnoff }
401*3b3a8eb9SGleb Smirnoff 
402*3b3a8eb9SGleb Smirnoff /* buffer management code */
403*3b3a8eb9SGleb Smirnoff 
404*3b3a8eb9SGleb Smirnoff size_t buf_esize[PFRB_MAX] = { 0,
405*3b3a8eb9SGleb Smirnoff 	sizeof(struct pfr_table), sizeof(struct pfr_tstats),
406*3b3a8eb9SGleb Smirnoff 	sizeof(struct pfr_addr), sizeof(struct pfr_astats),
407*3b3a8eb9SGleb Smirnoff 	sizeof(struct pfi_kif), sizeof(struct pfioc_trans_e)
408*3b3a8eb9SGleb Smirnoff };
409*3b3a8eb9SGleb Smirnoff 
410*3b3a8eb9SGleb Smirnoff /*
411*3b3a8eb9SGleb Smirnoff  * add one element to the buffer
412*3b3a8eb9SGleb Smirnoff  */
413*3b3a8eb9SGleb Smirnoff int
414*3b3a8eb9SGleb Smirnoff pfr_buf_add(struct pfr_buffer *b, const void *e)
415*3b3a8eb9SGleb Smirnoff {
416*3b3a8eb9SGleb Smirnoff 	size_t bs;
417*3b3a8eb9SGleb Smirnoff 
418*3b3a8eb9SGleb Smirnoff 	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX ||
419*3b3a8eb9SGleb Smirnoff 	    e == NULL) {
420*3b3a8eb9SGleb Smirnoff 		errno = EINVAL;
421*3b3a8eb9SGleb Smirnoff 		return (-1);
422*3b3a8eb9SGleb Smirnoff 	}
423*3b3a8eb9SGleb Smirnoff 	bs = buf_esize[b->pfrb_type];
424*3b3a8eb9SGleb Smirnoff 	if (b->pfrb_size == b->pfrb_msize)
425*3b3a8eb9SGleb Smirnoff 		if (pfr_buf_grow(b, 0))
426*3b3a8eb9SGleb Smirnoff 			return (-1);
427*3b3a8eb9SGleb Smirnoff 	memcpy(((caddr_t)b->pfrb_caddr) + bs * b->pfrb_size, e, bs);
428*3b3a8eb9SGleb Smirnoff 	b->pfrb_size++;
429*3b3a8eb9SGleb Smirnoff 	return (0);
430*3b3a8eb9SGleb Smirnoff }
431*3b3a8eb9SGleb Smirnoff 
432*3b3a8eb9SGleb Smirnoff /*
433*3b3a8eb9SGleb Smirnoff  * return next element of the buffer (or first one if prev is NULL)
434*3b3a8eb9SGleb Smirnoff  * see PFRB_FOREACH macro
435*3b3a8eb9SGleb Smirnoff  */
436*3b3a8eb9SGleb Smirnoff void *
437*3b3a8eb9SGleb Smirnoff pfr_buf_next(struct pfr_buffer *b, const void *prev)
438*3b3a8eb9SGleb Smirnoff {
439*3b3a8eb9SGleb Smirnoff 	size_t bs;
440*3b3a8eb9SGleb Smirnoff 
441*3b3a8eb9SGleb Smirnoff 	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX)
442*3b3a8eb9SGleb Smirnoff 		return (NULL);
443*3b3a8eb9SGleb Smirnoff 	if (b->pfrb_size == 0)
444*3b3a8eb9SGleb Smirnoff 		return (NULL);
445*3b3a8eb9SGleb Smirnoff 	if (prev == NULL)
446*3b3a8eb9SGleb Smirnoff 		return (b->pfrb_caddr);
447*3b3a8eb9SGleb Smirnoff 	bs = buf_esize[b->pfrb_type];
448*3b3a8eb9SGleb Smirnoff 	if ((((caddr_t)prev)-((caddr_t)b->pfrb_caddr)) / bs >= b->pfrb_size-1)
449*3b3a8eb9SGleb Smirnoff 		return (NULL);
450*3b3a8eb9SGleb Smirnoff 	return (((caddr_t)prev) + bs);
451*3b3a8eb9SGleb Smirnoff }
452*3b3a8eb9SGleb Smirnoff 
453*3b3a8eb9SGleb Smirnoff /*
454*3b3a8eb9SGleb Smirnoff  * minsize:
455*3b3a8eb9SGleb Smirnoff  *    0: make the buffer somewhat bigger
456*3b3a8eb9SGleb Smirnoff  *    n: make room for "n" entries in the buffer
457*3b3a8eb9SGleb Smirnoff  */
458*3b3a8eb9SGleb Smirnoff int
459*3b3a8eb9SGleb Smirnoff pfr_buf_grow(struct pfr_buffer *b, int minsize)
460*3b3a8eb9SGleb Smirnoff {
461*3b3a8eb9SGleb Smirnoff 	caddr_t p;
462*3b3a8eb9SGleb Smirnoff 	size_t bs;
463*3b3a8eb9SGleb Smirnoff 
464*3b3a8eb9SGleb Smirnoff 	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX) {
465*3b3a8eb9SGleb Smirnoff 		errno = EINVAL;
466*3b3a8eb9SGleb Smirnoff 		return (-1);
467*3b3a8eb9SGleb Smirnoff 	}
468*3b3a8eb9SGleb Smirnoff 	if (minsize != 0 && minsize <= b->pfrb_msize)
469*3b3a8eb9SGleb Smirnoff 		return (0);
470*3b3a8eb9SGleb Smirnoff 	bs = buf_esize[b->pfrb_type];
471*3b3a8eb9SGleb Smirnoff 	if (!b->pfrb_msize) {
472*3b3a8eb9SGleb Smirnoff 		if (minsize < 64)
473*3b3a8eb9SGleb Smirnoff 			minsize = 64;
474*3b3a8eb9SGleb Smirnoff 		b->pfrb_caddr = calloc(bs, minsize);
475*3b3a8eb9SGleb Smirnoff 		if (b->pfrb_caddr == NULL)
476*3b3a8eb9SGleb Smirnoff 			return (-1);
477*3b3a8eb9SGleb Smirnoff 		b->pfrb_msize = minsize;
478*3b3a8eb9SGleb Smirnoff 	} else {
479*3b3a8eb9SGleb Smirnoff 		if (minsize == 0)
480*3b3a8eb9SGleb Smirnoff 			minsize = b->pfrb_msize * 2;
481*3b3a8eb9SGleb Smirnoff 		if (minsize < 0 || minsize >= SIZE_T_MAX / bs) {
482*3b3a8eb9SGleb Smirnoff 			/* msize overflow */
483*3b3a8eb9SGleb Smirnoff 			errno = ENOMEM;
484*3b3a8eb9SGleb Smirnoff 			return (-1);
485*3b3a8eb9SGleb Smirnoff 		}
486*3b3a8eb9SGleb Smirnoff 		p = realloc(b->pfrb_caddr, minsize * bs);
487*3b3a8eb9SGleb Smirnoff 		if (p == NULL)
488*3b3a8eb9SGleb Smirnoff 			return (-1);
489*3b3a8eb9SGleb Smirnoff 		bzero(p + b->pfrb_msize * bs, (minsize - b->pfrb_msize) * bs);
490*3b3a8eb9SGleb Smirnoff 		b->pfrb_caddr = p;
491*3b3a8eb9SGleb Smirnoff 		b->pfrb_msize = minsize;
492*3b3a8eb9SGleb Smirnoff 	}
493*3b3a8eb9SGleb Smirnoff 	return (0);
494*3b3a8eb9SGleb Smirnoff }
495*3b3a8eb9SGleb Smirnoff 
496*3b3a8eb9SGleb Smirnoff /*
497*3b3a8eb9SGleb Smirnoff  * reset buffer and free memory.
498*3b3a8eb9SGleb Smirnoff  */
499*3b3a8eb9SGleb Smirnoff void
500*3b3a8eb9SGleb Smirnoff pfr_buf_clear(struct pfr_buffer *b)
501*3b3a8eb9SGleb Smirnoff {
502*3b3a8eb9SGleb Smirnoff 	if (b == NULL)
503*3b3a8eb9SGleb Smirnoff 		return;
504*3b3a8eb9SGleb Smirnoff 	if (b->pfrb_caddr != NULL)
505*3b3a8eb9SGleb Smirnoff 		free(b->pfrb_caddr);
506*3b3a8eb9SGleb Smirnoff 	b->pfrb_caddr = NULL;
507*3b3a8eb9SGleb Smirnoff 	b->pfrb_size = b->pfrb_msize = 0;
508*3b3a8eb9SGleb Smirnoff }
509*3b3a8eb9SGleb Smirnoff 
510*3b3a8eb9SGleb Smirnoff int
511*3b3a8eb9SGleb Smirnoff pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork,
512*3b3a8eb9SGleb Smirnoff     int (*append_addr)(struct pfr_buffer *, char *, int))
513*3b3a8eb9SGleb Smirnoff {
514*3b3a8eb9SGleb Smirnoff 	FILE	*fp;
515*3b3a8eb9SGleb Smirnoff 	char	 buf[BUF_SIZE];
516*3b3a8eb9SGleb Smirnoff 	int	 rv;
517*3b3a8eb9SGleb Smirnoff 
518*3b3a8eb9SGleb Smirnoff 	if (file == NULL)
519*3b3a8eb9SGleb Smirnoff 		return (0);
520*3b3a8eb9SGleb Smirnoff 	if (!strcmp(file, "-"))
521*3b3a8eb9SGleb Smirnoff 		fp = stdin;
522*3b3a8eb9SGleb Smirnoff 	else {
523*3b3a8eb9SGleb Smirnoff 		fp = pfctl_fopen(file, "r");
524*3b3a8eb9SGleb Smirnoff 		if (fp == NULL)
525*3b3a8eb9SGleb Smirnoff 			return (-1);
526*3b3a8eb9SGleb Smirnoff 	}
527*3b3a8eb9SGleb Smirnoff 	while ((rv = pfr_next_token(buf, fp)) == 1)
528*3b3a8eb9SGleb Smirnoff 		if (append_addr(b, buf, nonetwork)) {
529*3b3a8eb9SGleb Smirnoff 			rv = -1;
530*3b3a8eb9SGleb Smirnoff 			break;
531*3b3a8eb9SGleb Smirnoff 		}
532*3b3a8eb9SGleb Smirnoff 	if (fp != stdin)
533*3b3a8eb9SGleb Smirnoff 		fclose(fp);
534*3b3a8eb9SGleb Smirnoff 	return (rv);
535*3b3a8eb9SGleb Smirnoff }
536*3b3a8eb9SGleb Smirnoff 
537*3b3a8eb9SGleb Smirnoff int
538*3b3a8eb9SGleb Smirnoff pfr_next_token(char buf[BUF_SIZE], FILE *fp)
539*3b3a8eb9SGleb Smirnoff {
540*3b3a8eb9SGleb Smirnoff 	static char	next_ch = ' ';
541*3b3a8eb9SGleb Smirnoff 	int		i = 0;
542*3b3a8eb9SGleb Smirnoff 
543*3b3a8eb9SGleb Smirnoff 	for (;;) {
544*3b3a8eb9SGleb Smirnoff 		/* skip spaces */
545*3b3a8eb9SGleb Smirnoff 		while (isspace(next_ch) && !feof(fp))
546*3b3a8eb9SGleb Smirnoff 			next_ch = fgetc(fp);
547*3b3a8eb9SGleb Smirnoff 		/* remove from '#' until end of line */
548*3b3a8eb9SGleb Smirnoff 		if (next_ch == '#')
549*3b3a8eb9SGleb Smirnoff 			while (!feof(fp)) {
550*3b3a8eb9SGleb Smirnoff 				next_ch = fgetc(fp);
551*3b3a8eb9SGleb Smirnoff 				if (next_ch == '\n')
552*3b3a8eb9SGleb Smirnoff 					break;
553*3b3a8eb9SGleb Smirnoff 			}
554*3b3a8eb9SGleb Smirnoff 		else
555*3b3a8eb9SGleb Smirnoff 			break;
556*3b3a8eb9SGleb Smirnoff 	}
557*3b3a8eb9SGleb Smirnoff 	if (feof(fp)) {
558*3b3a8eb9SGleb Smirnoff 		next_ch = ' ';
559*3b3a8eb9SGleb Smirnoff 		return (0);
560*3b3a8eb9SGleb Smirnoff 	}
561*3b3a8eb9SGleb Smirnoff 	do {
562*3b3a8eb9SGleb Smirnoff 		if (i < BUF_SIZE)
563*3b3a8eb9SGleb Smirnoff 			buf[i++] = next_ch;
564*3b3a8eb9SGleb Smirnoff 		next_ch = fgetc(fp);
565*3b3a8eb9SGleb Smirnoff 	} while (!feof(fp) && !isspace(next_ch));
566*3b3a8eb9SGleb Smirnoff 	if (i >= BUF_SIZE) {
567*3b3a8eb9SGleb Smirnoff 		errno = EINVAL;
568*3b3a8eb9SGleb Smirnoff 		return (-1);
569*3b3a8eb9SGleb Smirnoff 	}
570*3b3a8eb9SGleb Smirnoff 	buf[i] = '\0';
571*3b3a8eb9SGleb Smirnoff 	return (1);
572*3b3a8eb9SGleb Smirnoff }
573*3b3a8eb9SGleb Smirnoff 
574*3b3a8eb9SGleb Smirnoff char *
575*3b3a8eb9SGleb Smirnoff pfr_strerror(int errnum)
576*3b3a8eb9SGleb Smirnoff {
577*3b3a8eb9SGleb Smirnoff 	switch (errnum) {
578*3b3a8eb9SGleb Smirnoff 	case ESRCH:
579*3b3a8eb9SGleb Smirnoff 		return "Table does not exist";
580*3b3a8eb9SGleb Smirnoff 	case ENOENT:
581*3b3a8eb9SGleb Smirnoff 		return "Anchor or Ruleset does not exist";
582*3b3a8eb9SGleb Smirnoff 	default:
583*3b3a8eb9SGleb Smirnoff 		return strerror(errnum);
584*3b3a8eb9SGleb Smirnoff 	}
585*3b3a8eb9SGleb Smirnoff }
586