1 /* $OpenBSD: pfctl_radix.c,v 1.27 2005/05/21 21:03:58 henning Exp $ */
4 * SPDX-License-Identifier: BSD-2-Clause
6 * Copyright (c) 2002 Cedric Berger
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * - Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
38 #include <sys/types.h>
39 #include <sys/ioctl.h>
40 #include <sys/socket.h>
43 #include <net/pfvar.h>
59 static int pfr_next_token(char buf[], FILE *);
63 pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
65 struct pfioc_table io;
67 bzero(&io, sizeof io);
68 io.pfrio_flags = flags;
70 io.pfrio_table = *filter;
71 if (ioctl(dev, DIOCRCLRTABLES, &io))
74 *ndel = io.pfrio_ndel;
79 pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
81 struct pfioc_table io;
83 if (size < 0 || (size && tbl == NULL)) {
87 bzero(&io, sizeof io);
88 io.pfrio_flags = flags;
89 io.pfrio_buffer = tbl;
90 io.pfrio_esize = sizeof(*tbl);
92 if (ioctl(dev, DIOCRADDTABLES, &io))
95 *nadd = io.pfrio_nadd;
100 pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
102 struct pfioc_table io;
104 if (size < 0 || (size && tbl == NULL)) {
108 bzero(&io, sizeof io);
109 io.pfrio_flags = flags;
110 io.pfrio_buffer = tbl;
111 io.pfrio_esize = sizeof(*tbl);
112 io.pfrio_size = size;
113 if (ioctl(dev, DIOCRDELTABLES, &io))
116 *ndel = io.pfrio_ndel;
121 pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
124 struct pfioc_table io;
126 if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
130 bzero(&io, sizeof io);
131 io.pfrio_flags = flags;
133 io.pfrio_table = *filter;
134 io.pfrio_buffer = tbl;
135 io.pfrio_esize = sizeof(*tbl);
136 io.pfrio_size = *size;
137 if (ioctl(dev, DIOCRGETTABLES, &io))
139 *size = io.pfrio_size;
144 pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
147 struct pfioc_table io;
149 if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
153 bzero(&io, sizeof io);
154 io.pfrio_flags = flags;
156 io.pfrio_table = *filter;
157 io.pfrio_buffer = tbl;
158 io.pfrio_esize = sizeof(*tbl);
159 io.pfrio_size = *size;
160 if (ioctl(dev, DIOCRGETTSTATS, &io))
162 *size = io.pfrio_size;
167 pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
169 struct pfioc_table io;
175 bzero(&io, sizeof io);
176 io.pfrio_flags = flags;
177 io.pfrio_table = *tbl;
178 if (ioctl(dev, DIOCRCLRADDRS, &io))
181 *ndel = io.pfrio_ndel;
186 pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
187 int *nadd, int flags)
189 struct pfioc_table io;
191 if (tbl == NULL || size < 0 || (size && addr == NULL)) {
195 bzero(&io, sizeof io);
196 io.pfrio_flags = flags;
197 io.pfrio_table = *tbl;
198 io.pfrio_buffer = addr;
199 io.pfrio_esize = sizeof(*addr);
200 io.pfrio_size = size;
201 if (ioctl(dev, DIOCRADDADDRS, &io))
204 *nadd = io.pfrio_nadd;
209 pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
210 int *ndel, int flags)
212 struct pfioc_table io;
214 if (tbl == NULL || size < 0 || (size && addr == NULL)) {
218 bzero(&io, sizeof io);
219 io.pfrio_flags = flags;
220 io.pfrio_table = *tbl;
221 io.pfrio_buffer = addr;
222 io.pfrio_esize = sizeof(*addr);
223 io.pfrio_size = size;
224 if (ioctl(dev, DIOCRDELADDRS, &io))
227 *ndel = io.pfrio_ndel;
232 pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
233 int *size2, int *nadd, int *ndel, int *nchange, int flags)
235 struct pfioc_table io;
237 if (tbl == NULL || size < 0 || (size && addr == NULL)) {
241 bzero(&io, sizeof io);
242 io.pfrio_flags = flags;
243 io.pfrio_table = *tbl;
244 io.pfrio_buffer = addr;
245 io.pfrio_esize = sizeof(*addr);
246 io.pfrio_size = size;
247 io.pfrio_size2 = (size2 != NULL) ? *size2 : 0;
248 if (ioctl(dev, DIOCRSETADDRS, &io))
251 *nadd = io.pfrio_nadd;
253 *ndel = io.pfrio_ndel;
255 *nchange = io.pfrio_nchange;
257 *size2 = io.pfrio_size2;
262 pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
265 struct pfioc_table io;
267 if (tbl == NULL || size == NULL || *size < 0 ||
268 (*size && addr == NULL)) {
272 bzero(&io, sizeof io);
273 io.pfrio_flags = flags;
274 io.pfrio_table = *tbl;
275 io.pfrio_buffer = addr;
276 io.pfrio_esize = sizeof(*addr);
277 io.pfrio_size = *size;
278 if (ioctl(dev, DIOCRGETADDRS, &io))
280 *size = io.pfrio_size;
285 pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
288 struct pfioc_table io;
290 if (tbl == NULL || size == NULL || *size < 0 ||
291 (*size && addr == NULL)) {
295 bzero(&io, sizeof io);
296 io.pfrio_flags = flags;
297 io.pfrio_table = *tbl;
298 io.pfrio_buffer = addr;
299 io.pfrio_esize = sizeof(*addr);
300 io.pfrio_size = *size;
301 if (ioctl(dev, DIOCRGETASTATS, &io))
303 *size = io.pfrio_size;
308 pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
310 struct pfioc_table io;
312 if (size < 0 || (size && !tbl)) {
316 bzero(&io, sizeof io);
317 io.pfrio_flags = flags;
318 io.pfrio_buffer = tbl;
319 io.pfrio_esize = sizeof(*tbl);
320 io.pfrio_size = size;
321 if (ioctl(dev, DIOCRCLRTSTATS, &io))
324 *nzero = io.pfrio_nzero;
329 pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
330 int *nmatch, int flags)
332 struct pfioc_table io;
334 if (tbl == NULL || size < 0 || (size && addr == NULL)) {
338 bzero(&io, sizeof io);
339 io.pfrio_flags = flags;
340 io.pfrio_table = *tbl;
341 io.pfrio_buffer = addr;
342 io.pfrio_esize = sizeof(*addr);
343 io.pfrio_size = size;
344 if (ioctl(dev, DIOCRTSTADDRS, &io))
347 *nmatch = io.pfrio_nmatch;
352 pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
353 int *nadd, int *naddr, int ticket, int flags)
355 struct pfioc_table io;
357 if (tbl == NULL || size < 0 || (size && addr == NULL)) {
361 bzero(&io, sizeof io);
362 io.pfrio_flags = flags;
363 io.pfrio_table = *tbl;
364 io.pfrio_buffer = addr;
365 io.pfrio_esize = sizeof(*addr);
366 io.pfrio_size = size;
367 io.pfrio_ticket = ticket;
368 if (ioctl(dev, DIOCRINADEFINE, &io))
371 *nadd = io.pfrio_nadd;
373 *naddr = io.pfrio_naddr;
377 /* interface management code */
380 pfi_get_ifaces(const char *filter, struct pfi_kif *buf, int *size)
382 struct pfioc_iface io;
384 if (size == NULL || *size < 0 || (*size && buf == NULL)) {
388 bzero(&io, sizeof io);
390 if (strlcpy(io.pfiio_name, filter, sizeof(io.pfiio_name)) >=
391 sizeof(io.pfiio_name)) {
395 io.pfiio_buffer = buf;
396 io.pfiio_esize = sizeof(*buf);
397 io.pfiio_size = *size;
398 if (ioctl(dev, DIOCIGETIFACES, &io))
400 *size = io.pfiio_size;
404 /* buffer management code */
406 const size_t buf_esize[PFRB_MAX] = { 0,
407 sizeof(struct pfr_table), sizeof(struct pfr_tstats),
408 sizeof(struct pfr_addr), sizeof(struct pfr_astats),
409 sizeof(struct pfi_kif), sizeof(struct pfioc_trans_e)
413 * add one element to the buffer
416 pfr_buf_add(struct pfr_buffer *b, const void *e)
420 if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX ||
425 bs = buf_esize[b->pfrb_type];
426 if (b->pfrb_size == b->pfrb_msize)
427 if (pfr_buf_grow(b, 0))
429 memcpy(((caddr_t)b->pfrb_caddr) + bs * b->pfrb_size, e, bs);
435 * return next element of the buffer (or first one if prev is NULL)
436 * see PFRB_FOREACH macro
439 pfr_buf_next(struct pfr_buffer *b, const void *prev)
443 if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX)
445 if (b->pfrb_size == 0)
448 return (b->pfrb_caddr);
449 bs = buf_esize[b->pfrb_type];
450 if ((((caddr_t)prev)-((caddr_t)b->pfrb_caddr)) / bs >= b->pfrb_size-1)
452 return (((caddr_t)prev) + bs);
457 * 0: make the buffer somewhat bigger
458 * n: make room for "n" entries in the buffer
461 pfr_buf_grow(struct pfr_buffer *b, int minsize)
466 if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX) {
470 if (minsize != 0 && minsize <= b->pfrb_msize)
472 bs = buf_esize[b->pfrb_type];
473 if (!b->pfrb_msize) {
476 b->pfrb_caddr = calloc(bs, minsize);
477 if (b->pfrb_caddr == NULL)
479 b->pfrb_msize = minsize;
482 minsize = b->pfrb_msize * 2;
483 if (minsize < 0 || minsize >= SIZE_T_MAX / bs) {
488 p = realloc(b->pfrb_caddr, minsize * bs);
491 bzero(p + b->pfrb_msize * bs, (minsize - b->pfrb_msize) * bs);
493 b->pfrb_msize = minsize;
499 * reset buffer and free memory.
502 pfr_buf_clear(struct pfr_buffer *b)
506 if (b->pfrb_caddr != NULL)
508 b->pfrb_caddr = NULL;
509 b->pfrb_size = b->pfrb_msize = 0;
513 pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork,
514 int (*append_addr)(struct pfr_buffer *, char *, int))
522 if (!strcmp(file, "-"))
525 fp = pfctl_fopen(file, "r");
529 while ((rv = pfr_next_token(buf, fp)) == 1)
530 if (append_addr(b, buf, nonetwork)) {
540 pfr_next_token(char buf[BUF_SIZE], FILE *fp)
542 static char next_ch = ' ';
547 while (isspace(next_ch) && !feof(fp))
549 /* remove from '#' until end of line */
567 } while (!feof(fp) && !isspace(next_ch));
577 pfr_strerror(int errnum)
581 return "Table does not exist";
583 return "Anchor or Ruleset does not exist";
585 return strerror(errnum);