1 /* $OpenBSD: pfctl_radix.c,v 1.27 2005/05/21 21:03:58 henning Exp $ */
4 * Copyright (c) 2002 Cedric Berger
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * - Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
36 #include <sys/types.h>
37 #include <sys/ioctl.h>
38 #include <sys/socket.h>
41 #include <net/pfvar.h>
57 static int pfr_next_token(char buf[], FILE *);
61 pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
63 struct pfioc_table io;
65 bzero(&io, sizeof io);
66 io.pfrio_flags = flags;
68 io.pfrio_table = *filter;
69 if (ioctl(dev, DIOCRCLRTABLES, &io))
72 *ndel = io.pfrio_ndel;
77 pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
79 struct pfioc_table io;
81 if (size < 0 || (size && tbl == NULL)) {
85 bzero(&io, sizeof io);
86 io.pfrio_flags = flags;
87 io.pfrio_buffer = tbl;
88 io.pfrio_esize = sizeof(*tbl);
90 if (ioctl(dev, DIOCRADDTABLES, &io))
93 *nadd = io.pfrio_nadd;
98 pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
100 struct pfioc_table io;
102 if (size < 0 || (size && tbl == NULL)) {
106 bzero(&io, sizeof io);
107 io.pfrio_flags = flags;
108 io.pfrio_buffer = tbl;
109 io.pfrio_esize = sizeof(*tbl);
110 io.pfrio_size = size;
111 if (ioctl(dev, DIOCRDELTABLES, &io))
114 *ndel = io.pfrio_ndel;
119 pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
122 struct pfioc_table io;
124 if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
128 bzero(&io, sizeof io);
129 io.pfrio_flags = flags;
131 io.pfrio_table = *filter;
132 io.pfrio_buffer = tbl;
133 io.pfrio_esize = sizeof(*tbl);
134 io.pfrio_size = *size;
135 if (ioctl(dev, DIOCRGETTABLES, &io))
137 *size = io.pfrio_size;
142 pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
145 struct pfioc_table io;
147 if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
151 bzero(&io, sizeof io);
152 io.pfrio_flags = flags;
154 io.pfrio_table = *filter;
155 io.pfrio_buffer = tbl;
156 io.pfrio_esize = sizeof(*tbl);
157 io.pfrio_size = *size;
158 if (ioctl(dev, DIOCRGETTSTATS, &io))
160 *size = io.pfrio_size;
165 pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
167 struct pfioc_table io;
173 bzero(&io, sizeof io);
174 io.pfrio_flags = flags;
175 io.pfrio_table = *tbl;
176 if (ioctl(dev, DIOCRCLRADDRS, &io))
179 *ndel = io.pfrio_ndel;
184 pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
185 int *nadd, int flags)
187 struct pfioc_table io;
189 if (tbl == NULL || size < 0 || (size && addr == NULL)) {
193 bzero(&io, sizeof io);
194 io.pfrio_flags = flags;
195 io.pfrio_table = *tbl;
196 io.pfrio_buffer = addr;
197 io.pfrio_esize = sizeof(*addr);
198 io.pfrio_size = size;
199 if (ioctl(dev, DIOCRADDADDRS, &io))
202 *nadd = io.pfrio_nadd;
207 pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
208 int *ndel, int flags)
210 struct pfioc_table io;
212 if (tbl == NULL || size < 0 || (size && addr == NULL)) {
216 bzero(&io, sizeof io);
217 io.pfrio_flags = flags;
218 io.pfrio_table = *tbl;
219 io.pfrio_buffer = addr;
220 io.pfrio_esize = sizeof(*addr);
221 io.pfrio_size = size;
222 if (ioctl(dev, DIOCRDELADDRS, &io))
225 *ndel = io.pfrio_ndel;
230 pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
231 int *size2, int *nadd, int *ndel, int *nchange, int flags)
233 struct pfioc_table io;
235 if (tbl == NULL || size < 0 || (size && addr == NULL)) {
239 bzero(&io, sizeof io);
240 io.pfrio_flags = flags;
241 io.pfrio_table = *tbl;
242 io.pfrio_buffer = addr;
243 io.pfrio_esize = sizeof(*addr);
244 io.pfrio_size = size;
245 io.pfrio_size2 = (size2 != NULL) ? *size2 : 0;
246 if (ioctl(dev, DIOCRSETADDRS, &io))
249 *nadd = io.pfrio_nadd;
251 *ndel = io.pfrio_ndel;
253 *nchange = io.pfrio_nchange;
255 *size2 = io.pfrio_size2;
260 pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
263 struct pfioc_table io;
265 if (tbl == NULL || size == NULL || *size < 0 ||
266 (*size && addr == NULL)) {
270 bzero(&io, sizeof io);
271 io.pfrio_flags = flags;
272 io.pfrio_table = *tbl;
273 io.pfrio_buffer = addr;
274 io.pfrio_esize = sizeof(*addr);
275 io.pfrio_size = *size;
276 if (ioctl(dev, DIOCRGETADDRS, &io))
278 *size = io.pfrio_size;
283 pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
286 struct pfioc_table io;
288 if (tbl == NULL || size == NULL || *size < 0 ||
289 (*size && addr == NULL)) {
293 bzero(&io, sizeof io);
294 io.pfrio_flags = flags;
295 io.pfrio_table = *tbl;
296 io.pfrio_buffer = addr;
297 io.pfrio_esize = sizeof(*addr);
298 io.pfrio_size = *size;
299 if (ioctl(dev, DIOCRGETASTATS, &io))
301 *size = io.pfrio_size;
306 pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
308 struct pfioc_table io;
310 if (size < 0 || (size && !tbl)) {
314 bzero(&io, sizeof io);
315 io.pfrio_flags = flags;
316 io.pfrio_buffer = tbl;
317 io.pfrio_esize = sizeof(*tbl);
318 io.pfrio_size = size;
319 if (ioctl(dev, DIOCRCLRTSTATS, &io))
322 *nzero = io.pfrio_nzero;
327 pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
328 int *nmatch, int flags)
330 struct pfioc_table io;
332 if (tbl == NULL || size < 0 || (size && addr == NULL)) {
336 bzero(&io, sizeof io);
337 io.pfrio_flags = flags;
338 io.pfrio_table = *tbl;
339 io.pfrio_buffer = addr;
340 io.pfrio_esize = sizeof(*addr);
341 io.pfrio_size = size;
342 if (ioctl(dev, DIOCRTSTADDRS, &io))
345 *nmatch = io.pfrio_nmatch;
350 pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
351 int *nadd, int *naddr, int ticket, int flags)
353 struct pfioc_table io;
355 if (tbl == NULL || size < 0 || (size && addr == NULL)) {
359 bzero(&io, sizeof io);
360 io.pfrio_flags = flags;
361 io.pfrio_table = *tbl;
362 io.pfrio_buffer = addr;
363 io.pfrio_esize = sizeof(*addr);
364 io.pfrio_size = size;
365 io.pfrio_ticket = ticket;
366 if (ioctl(dev, DIOCRINADEFINE, &io))
369 *nadd = io.pfrio_nadd;
371 *naddr = io.pfrio_naddr;
375 /* interface management code */
378 pfi_get_ifaces(const char *filter, struct pfi_kif *buf, int *size)
380 struct pfioc_iface io;
382 if (size == NULL || *size < 0 || (*size && buf == NULL)) {
386 bzero(&io, sizeof io);
388 if (strlcpy(io.pfiio_name, filter, sizeof(io.pfiio_name)) >=
389 sizeof(io.pfiio_name)) {
393 io.pfiio_buffer = buf;
394 io.pfiio_esize = sizeof(*buf);
395 io.pfiio_size = *size;
396 if (ioctl(dev, DIOCIGETIFACES, &io))
398 *size = io.pfiio_size;
402 /* buffer management code */
404 size_t buf_esize[PFRB_MAX] = { 0,
405 sizeof(struct pfr_table), sizeof(struct pfr_tstats),
406 sizeof(struct pfr_addr), sizeof(struct pfr_astats),
407 sizeof(struct pfi_kif), sizeof(struct pfioc_trans_e)
411 * add one element to the buffer
414 pfr_buf_add(struct pfr_buffer *b, const void *e)
418 if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX ||
423 bs = buf_esize[b->pfrb_type];
424 if (b->pfrb_size == b->pfrb_msize)
425 if (pfr_buf_grow(b, 0))
427 memcpy(((caddr_t)b->pfrb_caddr) + bs * b->pfrb_size, e, bs);
433 * return next element of the buffer (or first one if prev is NULL)
434 * see PFRB_FOREACH macro
437 pfr_buf_next(struct pfr_buffer *b, const void *prev)
441 if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX)
443 if (b->pfrb_size == 0)
446 return (b->pfrb_caddr);
447 bs = buf_esize[b->pfrb_type];
448 if ((((caddr_t)prev)-((caddr_t)b->pfrb_caddr)) / bs >= b->pfrb_size-1)
450 return (((caddr_t)prev) + bs);
455 * 0: make the buffer somewhat bigger
456 * n: make room for "n" entries in the buffer
459 pfr_buf_grow(struct pfr_buffer *b, int minsize)
464 if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX) {
468 if (minsize != 0 && minsize <= b->pfrb_msize)
470 bs = buf_esize[b->pfrb_type];
471 if (!b->pfrb_msize) {
474 b->pfrb_caddr = calloc(bs, minsize);
475 if (b->pfrb_caddr == NULL)
477 b->pfrb_msize = minsize;
480 minsize = b->pfrb_msize * 2;
481 if (minsize < 0 || minsize >= SIZE_T_MAX / bs) {
486 p = realloc(b->pfrb_caddr, minsize * bs);
489 bzero(p + b->pfrb_msize * bs, (minsize - b->pfrb_msize) * bs);
491 b->pfrb_msize = minsize;
497 * reset buffer and free memory.
500 pfr_buf_clear(struct pfr_buffer *b)
504 if (b->pfrb_caddr != NULL)
506 b->pfrb_caddr = NULL;
507 b->pfrb_size = b->pfrb_msize = 0;
511 pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork,
512 int (*append_addr)(struct pfr_buffer *, char *, int))
520 if (!strcmp(file, "-"))
523 fp = pfctl_fopen(file, "r");
527 while ((rv = pfr_next_token(buf, fp)) == 1)
528 if (append_addr(b, buf, nonetwork)) {
538 pfr_next_token(char buf[BUF_SIZE], FILE *fp)
540 static char next_ch = ' ';
545 while (isspace(next_ch) && !feof(fp))
547 /* remove from '#' until end of line */
565 } while (!feof(fp) && !isspace(next_ch));
575 pfr_strerror(int errnum)
579 return "Table does not exist";
581 return "Anchor or Ruleset does not exist";
583 return strerror(errnum);