1171169Smlaier/*	$OpenBSD: pfctl_radix.c,v 1.27 2005/05/21 21:03:58 henning Exp $ */
2126353Smlaier
3126353Smlaier/*
4126353Smlaier * Copyright (c) 2002 Cedric Berger
5126353Smlaier * All rights reserved.
6126353Smlaier *
7126353Smlaier * Redistribution and use in source and binary forms, with or without
8126353Smlaier * modification, are permitted provided that the following conditions
9126353Smlaier * are met:
10126353Smlaier *
11126353Smlaier *    - Redistributions of source code must retain the above copyright
12126353Smlaier *      notice, this list of conditions and the following disclaimer.
13126353Smlaier *    - Redistributions in binary form must reproduce the above
14126353Smlaier *      copyright notice, this list of conditions and the following
15126353Smlaier *      disclaimer in the documentation and/or other materials provided
16126353Smlaier *      with the distribution.
17126353Smlaier *
18126353Smlaier * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19126353Smlaier * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20126353Smlaier * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21126353Smlaier * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22126353Smlaier * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23126353Smlaier * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24126353Smlaier * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25126353Smlaier * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26126353Smlaier * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27126353Smlaier * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28126353Smlaier * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29126353Smlaier * POSSIBILITY OF SUCH DAMAGE.
30126353Smlaier *
31126353Smlaier */
32126353Smlaier
33223637Sbz#include <sys/cdefs.h>
34223637Sbz__FBSDID("$FreeBSD$");
35223637Sbz
36126353Smlaier#include <sys/types.h>
37126353Smlaier#include <sys/ioctl.h>
38126353Smlaier#include <sys/socket.h>
39126353Smlaier
40126353Smlaier#include <net/if.h>
41126353Smlaier#include <net/pfvar.h>
42126353Smlaier
43126353Smlaier#include <errno.h>
44126353Smlaier#include <string.h>
45126353Smlaier#include <ctype.h>
46126353Smlaier#include <stdio.h>
47126353Smlaier#include <stdlib.h>
48126353Smlaier#include <limits.h>
49126353Smlaier#include <err.h>
50126353Smlaier
51126353Smlaier#include "pfctl.h"
52126353Smlaier
53126353Smlaier#define BUF_SIZE 256
54126353Smlaier
55126353Smlaierextern int dev;
56126353Smlaier
57126353Smlaierstatic int	 pfr_next_token(char buf[], FILE *);
58126353Smlaier
59126353Smlaier
60126353Smlaierint
61126353Smlaierpfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
62126353Smlaier{
63126353Smlaier	struct pfioc_table io;
64126353Smlaier
65126353Smlaier	bzero(&io, sizeof io);
66126353Smlaier	io.pfrio_flags = flags;
67126353Smlaier	if (filter != NULL)
68126353Smlaier		io.pfrio_table = *filter;
69126353Smlaier	if (ioctl(dev, DIOCRCLRTABLES, &io))
70126353Smlaier		return (-1);
71126353Smlaier	if (ndel != NULL)
72126353Smlaier		*ndel = io.pfrio_ndel;
73126353Smlaier	return (0);
74126353Smlaier}
75126353Smlaier
76126353Smlaierint
77126353Smlaierpfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
78126353Smlaier{
79126353Smlaier	struct pfioc_table io;
80126353Smlaier
81126353Smlaier	if (size < 0 || (size && tbl == NULL)) {
82126353Smlaier		errno = EINVAL;
83126353Smlaier		return (-1);
84126353Smlaier	}
85126353Smlaier	bzero(&io, sizeof io);
86126353Smlaier	io.pfrio_flags = flags;
87126353Smlaier	io.pfrio_buffer = tbl;
88126353Smlaier	io.pfrio_esize = sizeof(*tbl);
89126353Smlaier	io.pfrio_size = size;
90126353Smlaier	if (ioctl(dev, DIOCRADDTABLES, &io))
91126353Smlaier		return (-1);
92126353Smlaier	if (nadd != NULL)
93126353Smlaier		*nadd = io.pfrio_nadd;
94126353Smlaier	return (0);
95126353Smlaier}
96126353Smlaier
97126353Smlaierint
98126353Smlaierpfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
99126353Smlaier{
100126353Smlaier	struct pfioc_table io;
101126353Smlaier
102126353Smlaier	if (size < 0 || (size && tbl == NULL)) {
103126353Smlaier		errno = EINVAL;
104126353Smlaier		return (-1);
105126353Smlaier	}
106126353Smlaier	bzero(&io, sizeof io);
107126353Smlaier	io.pfrio_flags = flags;
108126353Smlaier	io.pfrio_buffer = tbl;
109126353Smlaier	io.pfrio_esize = sizeof(*tbl);
110126353Smlaier	io.pfrio_size = size;
111126353Smlaier	if (ioctl(dev, DIOCRDELTABLES, &io))
112126353Smlaier		return (-1);
113126353Smlaier	if (ndel != NULL)
114126353Smlaier		*ndel = io.pfrio_ndel;
115126353Smlaier	return (0);
116126353Smlaier}
117126353Smlaier
118126353Smlaierint
119126353Smlaierpfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
120126353Smlaier	int flags)
121126353Smlaier{
122126353Smlaier	struct pfioc_table io;
123126353Smlaier
124126353Smlaier	if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
125126353Smlaier		errno = EINVAL;
126126353Smlaier		return (-1);
127126353Smlaier	}
128126353Smlaier	bzero(&io, sizeof io);
129126353Smlaier	io.pfrio_flags = flags;
130126353Smlaier	if (filter != NULL)
131126353Smlaier		io.pfrio_table = *filter;
132126353Smlaier	io.pfrio_buffer = tbl;
133126353Smlaier	io.pfrio_esize = sizeof(*tbl);
134126353Smlaier	io.pfrio_size = *size;
135126353Smlaier	if (ioctl(dev, DIOCRGETTABLES, &io))
136126353Smlaier		return (-1);
137126353Smlaier	*size = io.pfrio_size;
138126353Smlaier	return (0);
139126353Smlaier}
140126353Smlaier
141126353Smlaierint
142126353Smlaierpfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
143126353Smlaier	int flags)
144126353Smlaier{
145126353Smlaier	struct pfioc_table io;
146126353Smlaier
147126353Smlaier	if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
148126353Smlaier		errno = EINVAL;
149126353Smlaier		return (-1);
150126353Smlaier	}
151126353Smlaier	bzero(&io, sizeof io);
152126353Smlaier	io.pfrio_flags = flags;
153126353Smlaier	if (filter != NULL)
154126353Smlaier		io.pfrio_table = *filter;
155126353Smlaier	io.pfrio_buffer = tbl;
156126353Smlaier	io.pfrio_esize = sizeof(*tbl);
157126353Smlaier	io.pfrio_size = *size;
158126353Smlaier	if (ioctl(dev, DIOCRGETTSTATS, &io))
159126353Smlaier		return (-1);
160126353Smlaier	*size = io.pfrio_size;
161126353Smlaier	return (0);
162126353Smlaier}
163126353Smlaier
164126353Smlaierint
165126353Smlaierpfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
166126353Smlaier{
167126353Smlaier	struct pfioc_table io;
168126353Smlaier
169126353Smlaier	if (tbl == NULL) {
170126353Smlaier		errno = EINVAL;
171126353Smlaier		return (-1);
172126353Smlaier	}
173126353Smlaier	bzero(&io, sizeof io);
174126353Smlaier	io.pfrio_flags = flags;
175126353Smlaier	io.pfrio_table = *tbl;
176126353Smlaier	if (ioctl(dev, DIOCRCLRADDRS, &io))
177126353Smlaier		return (-1);
178126353Smlaier	if (ndel != NULL)
179126353Smlaier		*ndel = io.pfrio_ndel;
180126353Smlaier	return (0);
181126353Smlaier}
182126353Smlaier
183126353Smlaierint
184126353Smlaierpfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
185126353Smlaier    int *nadd, int flags)
186126353Smlaier{
187126353Smlaier	struct pfioc_table io;
188126353Smlaier
189126353Smlaier	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
190126353Smlaier		errno = EINVAL;
191126353Smlaier		return (-1);
192126353Smlaier	}
193126353Smlaier	bzero(&io, sizeof io);
194126353Smlaier	io.pfrio_flags = flags;
195126353Smlaier	io.pfrio_table = *tbl;
196126353Smlaier	io.pfrio_buffer = addr;
197126353Smlaier	io.pfrio_esize = sizeof(*addr);
198126353Smlaier	io.pfrio_size = size;
199126353Smlaier	if (ioctl(dev, DIOCRADDADDRS, &io))
200126353Smlaier		return (-1);
201126353Smlaier	if (nadd != NULL)
202126353Smlaier		*nadd = io.pfrio_nadd;
203126353Smlaier	return (0);
204126353Smlaier}
205126353Smlaier
206126353Smlaierint
207126353Smlaierpfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
208126353Smlaier    int *ndel, int flags)
209126353Smlaier{
210126353Smlaier	struct pfioc_table io;
211126353Smlaier
212126353Smlaier	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
213126353Smlaier		errno = EINVAL;
214126353Smlaier		return (-1);
215126353Smlaier	}
216126353Smlaier	bzero(&io, sizeof io);
217126353Smlaier	io.pfrio_flags = flags;
218126353Smlaier	io.pfrio_table = *tbl;
219126353Smlaier	io.pfrio_buffer = addr;
220126353Smlaier	io.pfrio_esize = sizeof(*addr);
221126353Smlaier	io.pfrio_size = size;
222126353Smlaier	if (ioctl(dev, DIOCRDELADDRS, &io))
223126353Smlaier		return (-1);
224126353Smlaier	if (ndel != NULL)
225126353Smlaier		*ndel = io.pfrio_ndel;
226126353Smlaier	return (0);
227126353Smlaier}
228126353Smlaier
229126353Smlaierint
230126353Smlaierpfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
231126353Smlaier    int *size2, int *nadd, int *ndel, int *nchange, int flags)
232126353Smlaier{
233126353Smlaier	struct pfioc_table io;
234126353Smlaier
235126353Smlaier	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
236126353Smlaier		errno = EINVAL;
237126353Smlaier		return (-1);
238126353Smlaier	}
239126353Smlaier	bzero(&io, sizeof io);
240126353Smlaier	io.pfrio_flags = flags;
241126353Smlaier	io.pfrio_table = *tbl;
242126353Smlaier	io.pfrio_buffer = addr;
243126353Smlaier	io.pfrio_esize = sizeof(*addr);
244126353Smlaier	io.pfrio_size = size;
245126353Smlaier	io.pfrio_size2 = (size2 != NULL) ? *size2 : 0;
246126353Smlaier	if (ioctl(dev, DIOCRSETADDRS, &io))
247126353Smlaier		return (-1);
248126353Smlaier	if (nadd != NULL)
249126353Smlaier		*nadd = io.pfrio_nadd;
250126353Smlaier	if (ndel != NULL)
251126353Smlaier		*ndel = io.pfrio_ndel;
252126353Smlaier	if (nchange != NULL)
253126353Smlaier		*nchange = io.pfrio_nchange;
254126353Smlaier	if (size2 != NULL)
255126353Smlaier		*size2 = io.pfrio_size2;
256126353Smlaier	return (0);
257126353Smlaier}
258126353Smlaier
259126353Smlaierint
260126353Smlaierpfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
261126353Smlaier    int flags)
262126353Smlaier{
263126353Smlaier	struct pfioc_table io;
264126353Smlaier
265130614Smlaier	if (tbl == NULL || size == NULL || *size < 0 ||
266130614Smlaier	    (*size && addr == NULL)) {
267126353Smlaier		errno = EINVAL;
268126353Smlaier		return (-1);
269126353Smlaier	}
270126353Smlaier	bzero(&io, sizeof io);
271126353Smlaier	io.pfrio_flags = flags;
272126353Smlaier	io.pfrio_table = *tbl;
273126353Smlaier	io.pfrio_buffer = addr;
274126353Smlaier	io.pfrio_esize = sizeof(*addr);
275126353Smlaier	io.pfrio_size = *size;
276126353Smlaier	if (ioctl(dev, DIOCRGETADDRS, &io))
277126353Smlaier		return (-1);
278126353Smlaier	*size = io.pfrio_size;
279126353Smlaier	return (0);
280126353Smlaier}
281126353Smlaier
282126353Smlaierint
283126353Smlaierpfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
284126353Smlaier    int flags)
285126353Smlaier{
286126353Smlaier	struct pfioc_table io;
287126353Smlaier
288130614Smlaier	if (tbl == NULL || size == NULL || *size < 0 ||
289130614Smlaier	    (*size && addr == NULL)) {
290126353Smlaier		errno = EINVAL;
291126353Smlaier		return (-1);
292126353Smlaier	}
293126353Smlaier	bzero(&io, sizeof io);
294126353Smlaier	io.pfrio_flags = flags;
295126353Smlaier	io.pfrio_table = *tbl;
296126353Smlaier	io.pfrio_buffer = addr;
297126353Smlaier	io.pfrio_esize = sizeof(*addr);
298126353Smlaier	io.pfrio_size = *size;
299126353Smlaier	if (ioctl(dev, DIOCRGETASTATS, &io))
300126353Smlaier		return (-1);
301126353Smlaier	*size = io.pfrio_size;
302126353Smlaier	return (0);
303126353Smlaier}
304126353Smlaier
305126353Smlaierint
306126353Smlaierpfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
307126353Smlaier{
308126353Smlaier	struct pfioc_table io;
309126353Smlaier
310126353Smlaier	if (size < 0 || (size && !tbl)) {
311126353Smlaier		errno = EINVAL;
312126353Smlaier		return (-1);
313126353Smlaier	}
314126353Smlaier	bzero(&io, sizeof io);
315126353Smlaier	io.pfrio_flags = flags;
316126353Smlaier	io.pfrio_buffer = tbl;
317126353Smlaier	io.pfrio_esize = sizeof(*tbl);
318126353Smlaier	io.pfrio_size = size;
319126353Smlaier	if (ioctl(dev, DIOCRCLRTSTATS, &io))
320126353Smlaier		return (-1);
321126353Smlaier	if (nzero)
322126353Smlaier		*nzero = io.pfrio_nzero;
323126353Smlaier	return (0);
324126353Smlaier}
325126353Smlaier
326126353Smlaierint
327126353Smlaierpfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
328126353Smlaier    int *nmatch, int flags)
329126353Smlaier{
330126353Smlaier	struct pfioc_table io;
331126353Smlaier
332126353Smlaier	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
333126353Smlaier		errno = EINVAL;
334126353Smlaier		return (-1);
335126353Smlaier	}
336126353Smlaier	bzero(&io, sizeof io);
337126353Smlaier	io.pfrio_flags = flags;
338126353Smlaier	io.pfrio_table = *tbl;
339126353Smlaier	io.pfrio_buffer = addr;
340126353Smlaier	io.pfrio_esize = sizeof(*addr);
341126353Smlaier	io.pfrio_size = size;
342126353Smlaier	if (ioctl(dev, DIOCRTSTADDRS, &io))
343126353Smlaier		return (-1);
344126353Smlaier	if (nmatch)
345126353Smlaier		*nmatch = io.pfrio_nmatch;
346126353Smlaier	return (0);
347126353Smlaier}
348126353Smlaier
349126353Smlaierint
350126353Smlaierpfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
351126353Smlaier    int *nadd, int *naddr, int ticket, int flags)
352126353Smlaier{
353126353Smlaier	struct pfioc_table io;
354126353Smlaier
355126353Smlaier	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
356126353Smlaier		errno = EINVAL;
357126353Smlaier		return (-1);
358126353Smlaier	}
359126353Smlaier	bzero(&io, sizeof io);
360126353Smlaier	io.pfrio_flags = flags;
361126353Smlaier	io.pfrio_table = *tbl;
362126353Smlaier	io.pfrio_buffer = addr;
363126353Smlaier	io.pfrio_esize = sizeof(*addr);
364126353Smlaier	io.pfrio_size = size;
365126353Smlaier	io.pfrio_ticket = ticket;
366126353Smlaier	if (ioctl(dev, DIOCRINADEFINE, &io))
367126353Smlaier		return (-1);
368126353Smlaier	if (nadd != NULL)
369126353Smlaier		*nadd = io.pfrio_nadd;
370126353Smlaier	if (naddr != NULL)
371126353Smlaier		*naddr = io.pfrio_naddr;
372126353Smlaier	return (0);
373126353Smlaier}
374126353Smlaier
375130614Smlaier/* interface management code */
376130614Smlaier
377130614Smlaierint
378171169Smlaierpfi_get_ifaces(const char *filter, struct pfi_kif *buf, int *size)
379130614Smlaier{
380130614Smlaier	struct pfioc_iface io;
381130614Smlaier
382130614Smlaier	if (size == NULL || *size < 0 || (*size && buf == NULL)) {
383130614Smlaier		errno = EINVAL;
384130614Smlaier		return (-1);
385130614Smlaier	}
386130614Smlaier	bzero(&io, sizeof io);
387130614Smlaier	if (filter != NULL)
388130614Smlaier		if (strlcpy(io.pfiio_name, filter, sizeof(io.pfiio_name)) >=
389130614Smlaier		    sizeof(io.pfiio_name)) {
390130614Smlaier			errno = EINVAL;
391130614Smlaier			return (-1);
392130614Smlaier		}
393130614Smlaier	io.pfiio_buffer = buf;
394130614Smlaier	io.pfiio_esize = sizeof(*buf);
395130614Smlaier	io.pfiio_size = *size;
396130614Smlaier	if (ioctl(dev, DIOCIGETIFACES, &io))
397130614Smlaier		return (-1);
398130614Smlaier	*size = io.pfiio_size;
399130614Smlaier	return (0);
400130614Smlaier}
401130614Smlaier
402126353Smlaier/* buffer management code */
403126353Smlaier
404126353Smlaiersize_t buf_esize[PFRB_MAX] = { 0,
405126353Smlaier	sizeof(struct pfr_table), sizeof(struct pfr_tstats),
406126353Smlaier	sizeof(struct pfr_addr), sizeof(struct pfr_astats),
407171169Smlaier	sizeof(struct pfi_kif), sizeof(struct pfioc_trans_e)
408126353Smlaier};
409126353Smlaier
410126353Smlaier/*
411126353Smlaier * add one element to the buffer
412126353Smlaier */
413126353Smlaierint
414126353Smlaierpfr_buf_add(struct pfr_buffer *b, const void *e)
415126353Smlaier{
416126353Smlaier	size_t bs;
417126353Smlaier
418126353Smlaier	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX ||
419126353Smlaier	    e == NULL) {
420126353Smlaier		errno = EINVAL;
421126353Smlaier		return (-1);
422126353Smlaier	}
423126353Smlaier	bs = buf_esize[b->pfrb_type];
424126353Smlaier	if (b->pfrb_size == b->pfrb_msize)
425126353Smlaier		if (pfr_buf_grow(b, 0))
426126353Smlaier			return (-1);
427126353Smlaier	memcpy(((caddr_t)b->pfrb_caddr) + bs * b->pfrb_size, e, bs);
428126353Smlaier	b->pfrb_size++;
429126353Smlaier	return (0);
430126353Smlaier}
431126353Smlaier
432126353Smlaier/*
433126353Smlaier * return next element of the buffer (or first one if prev is NULL)
434126353Smlaier * see PFRB_FOREACH macro
435126353Smlaier */
436126353Smlaiervoid *
437126353Smlaierpfr_buf_next(struct pfr_buffer *b, const void *prev)
438126353Smlaier{
439126353Smlaier	size_t bs;
440126353Smlaier
441126353Smlaier	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX)
442126353Smlaier		return (NULL);
443126353Smlaier	if (b->pfrb_size == 0)
444126353Smlaier		return (NULL);
445126353Smlaier	if (prev == NULL)
446126353Smlaier		return (b->pfrb_caddr);
447126353Smlaier	bs = buf_esize[b->pfrb_type];
448126353Smlaier	if ((((caddr_t)prev)-((caddr_t)b->pfrb_caddr)) / bs >= b->pfrb_size-1)
449126353Smlaier		return (NULL);
450126353Smlaier	return (((caddr_t)prev) + bs);
451126353Smlaier}
452126353Smlaier
453126353Smlaier/*
454126353Smlaier * minsize:
455126353Smlaier *    0: make the buffer somewhat bigger
456126353Smlaier *    n: make room for "n" entries in the buffer
457126353Smlaier */
458126353Smlaierint
459126353Smlaierpfr_buf_grow(struct pfr_buffer *b, int minsize)
460126353Smlaier{
461126353Smlaier	caddr_t p;
462126353Smlaier	size_t bs;
463126353Smlaier
464126353Smlaier	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX) {
465126353Smlaier		errno = EINVAL;
466126353Smlaier		return (-1);
467126353Smlaier	}
468126353Smlaier	if (minsize != 0 && minsize <= b->pfrb_msize)
469126353Smlaier		return (0);
470126353Smlaier	bs = buf_esize[b->pfrb_type];
471126353Smlaier	if (!b->pfrb_msize) {
472126353Smlaier		if (minsize < 64)
473126353Smlaier			minsize = 64;
474126353Smlaier		b->pfrb_caddr = calloc(bs, minsize);
475126353Smlaier		if (b->pfrb_caddr == NULL)
476126353Smlaier			return (-1);
477126353Smlaier		b->pfrb_msize = minsize;
478126353Smlaier	} else {
479126353Smlaier		if (minsize == 0)
480126353Smlaier			minsize = b->pfrb_msize * 2;
481126353Smlaier		if (minsize < 0 || minsize >= SIZE_T_MAX / bs) {
482126353Smlaier			/* msize overflow */
483126353Smlaier			errno = ENOMEM;
484126353Smlaier			return (-1);
485126353Smlaier		}
486126353Smlaier		p = realloc(b->pfrb_caddr, minsize * bs);
487126353Smlaier		if (p == NULL)
488126353Smlaier			return (-1);
489126353Smlaier		bzero(p + b->pfrb_msize * bs, (minsize - b->pfrb_msize) * bs);
490126353Smlaier		b->pfrb_caddr = p;
491126353Smlaier		b->pfrb_msize = minsize;
492126353Smlaier	}
493126353Smlaier	return (0);
494126353Smlaier}
495126353Smlaier
496126353Smlaier/*
497126353Smlaier * reset buffer and free memory.
498126353Smlaier */
499126353Smlaiervoid
500126353Smlaierpfr_buf_clear(struct pfr_buffer *b)
501126353Smlaier{
502126353Smlaier	if (b == NULL)
503126353Smlaier		return;
504126353Smlaier	if (b->pfrb_caddr != NULL)
505126353Smlaier		free(b->pfrb_caddr);
506126353Smlaier	b->pfrb_caddr = NULL;
507126353Smlaier	b->pfrb_size = b->pfrb_msize = 0;
508126353Smlaier}
509126353Smlaier
510126353Smlaierint
511126353Smlaierpfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork,
512126353Smlaier    int (*append_addr)(struct pfr_buffer *, char *, int))
513126353Smlaier{
514126353Smlaier	FILE	*fp;
515126353Smlaier	char	 buf[BUF_SIZE];
516126353Smlaier	int	 rv;
517126353Smlaier
518126353Smlaier	if (file == NULL)
519126353Smlaier		return (0);
520126353Smlaier	if (!strcmp(file, "-"))
521126353Smlaier		fp = stdin;
522126353Smlaier	else {
523145837Smlaier		fp = pfctl_fopen(file, "r");
524126353Smlaier		if (fp == NULL)
525126353Smlaier			return (-1);
526126353Smlaier	}
527126353Smlaier	while ((rv = pfr_next_token(buf, fp)) == 1)
528126353Smlaier		if (append_addr(b, buf, nonetwork)) {
529126353Smlaier			rv = -1;
530126353Smlaier			break;
531126353Smlaier		}
532126353Smlaier	if (fp != stdin)
533126353Smlaier		fclose(fp);
534126353Smlaier	return (rv);
535126353Smlaier}
536126353Smlaier
537126353Smlaierint
538126353Smlaierpfr_next_token(char buf[BUF_SIZE], FILE *fp)
539126353Smlaier{
540126353Smlaier	static char	next_ch = ' ';
541126353Smlaier	int		i = 0;
542126353Smlaier
543126353Smlaier	for (;;) {
544126353Smlaier		/* skip spaces */
545126353Smlaier		while (isspace(next_ch) && !feof(fp))
546126353Smlaier			next_ch = fgetc(fp);
547126353Smlaier		/* remove from '#' until end of line */
548126353Smlaier		if (next_ch == '#')
549126353Smlaier			while (!feof(fp)) {
550126353Smlaier				next_ch = fgetc(fp);
551126353Smlaier				if (next_ch == '\n')
552126353Smlaier					break;
553126353Smlaier			}
554126353Smlaier		else
555126353Smlaier			break;
556126353Smlaier	}
557126353Smlaier	if (feof(fp)) {
558126353Smlaier		next_ch = ' ';
559126353Smlaier		return (0);
560126353Smlaier	}
561126353Smlaier	do {
562126353Smlaier		if (i < BUF_SIZE)
563126353Smlaier			buf[i++] = next_ch;
564126353Smlaier		next_ch = fgetc(fp);
565126353Smlaier	} while (!feof(fp) && !isspace(next_ch));
566126353Smlaier	if (i >= BUF_SIZE) {
567126353Smlaier		errno = EINVAL;
568126353Smlaier		return (-1);
569126353Smlaier	}
570126353Smlaier	buf[i] = '\0';
571126353Smlaier	return (1);
572126353Smlaier}
573126353Smlaier
574126353Smlaierchar *
575126353Smlaierpfr_strerror(int errnum)
576126353Smlaier{
577126353Smlaier	switch (errnum) {
578126353Smlaier	case ESRCH:
579126353Smlaier		return "Table does not exist";
580126353Smlaier	case ENOENT:
581126353Smlaier		return "Anchor or Ruleset does not exist";
582126353Smlaier	default:
583126353Smlaier		return strerror(errnum);
584126353Smlaier	}
585126353Smlaier}
586