1 /* $OpenBSD: pfctl_radix.c,v 1.28 2007/12/05 12:01:47 chl 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/types.h>
34 #include <sys/ioctl.h>
35 #include <sys/socket.h>
38 #include <net/pf/pfvar.h>
54 static int pfr_next_token(char buf[], FILE *);
58 pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
60 struct pfioc_table io;
62 bzero(&io, sizeof io);
63 io.pfrio_flags = flags;
65 io.pfrio_table = *filter;
66 if (ioctl(dev_fd, DIOCRCLRTABLES, &io))
69 *ndel = io.pfrio_ndel;
74 pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
76 struct pfioc_table io;
78 if (size < 0 || (size && tbl == NULL)) {
82 bzero(&io, sizeof io);
83 io.pfrio_flags = flags;
84 io.pfrio_buffer = tbl;
85 io.pfrio_esize = sizeof(*tbl);
87 if (ioctl(dev_fd, DIOCRADDTABLES, &io))
90 *nadd = io.pfrio_nadd;
95 pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
97 struct pfioc_table io;
99 if (size < 0 || (size && tbl == NULL)) {
103 bzero(&io, sizeof io);
104 io.pfrio_flags = flags;
105 io.pfrio_buffer = tbl;
106 io.pfrio_esize = sizeof(*tbl);
107 io.pfrio_size = size;
108 if (ioctl(dev_fd, DIOCRDELTABLES, &io))
111 *ndel = io.pfrio_ndel;
116 pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
119 struct pfioc_table io;
121 if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
125 bzero(&io, sizeof io);
126 io.pfrio_flags = flags;
128 io.pfrio_table = *filter;
129 io.pfrio_buffer = tbl;
130 io.pfrio_esize = sizeof(*tbl);
131 io.pfrio_size = *size;
132 if (ioctl(dev_fd, DIOCRGETTABLES, &io))
134 *size = io.pfrio_size;
139 pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
142 struct pfioc_table io;
144 if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
148 bzero(&io, sizeof io);
149 io.pfrio_flags = flags;
151 io.pfrio_table = *filter;
152 io.pfrio_buffer = tbl;
153 io.pfrio_esize = sizeof(*tbl);
154 io.pfrio_size = *size;
155 if (ioctl(dev_fd, DIOCRGETTSTATS, &io))
157 *size = io.pfrio_size;
162 pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
164 struct pfioc_table io;
170 bzero(&io, sizeof io);
171 io.pfrio_flags = flags;
172 io.pfrio_table = *tbl;
173 if (ioctl(dev_fd, DIOCRCLRADDRS, &io))
176 *ndel = io.pfrio_ndel;
181 pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
182 int *nadd, int flags)
184 struct pfioc_table io;
186 if (tbl == NULL || size < 0 || (size && addr == NULL)) {
190 bzero(&io, sizeof io);
191 io.pfrio_flags = flags;
192 io.pfrio_table = *tbl;
193 io.pfrio_buffer = addr;
194 io.pfrio_esize = sizeof(*addr);
195 io.pfrio_size = size;
196 if (ioctl(dev_fd, DIOCRADDADDRS, &io))
199 *nadd = io.pfrio_nadd;
204 pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
205 int *ndel, int flags)
207 struct pfioc_table io;
209 if (tbl == NULL || size < 0 || (size && addr == NULL)) {
213 bzero(&io, sizeof io);
214 io.pfrio_flags = flags;
215 io.pfrio_table = *tbl;
216 io.pfrio_buffer = addr;
217 io.pfrio_esize = sizeof(*addr);
218 io.pfrio_size = size;
219 if (ioctl(dev_fd, DIOCRDELADDRS, &io))
222 *ndel = io.pfrio_ndel;
227 pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
228 int *size2, int *nadd, int *ndel, int *nchange, int flags)
230 struct pfioc_table io;
232 if (tbl == NULL || size < 0 || (size && addr == NULL)) {
236 bzero(&io, sizeof io);
237 io.pfrio_flags = flags;
238 io.pfrio_table = *tbl;
239 io.pfrio_buffer = addr;
240 io.pfrio_esize = sizeof(*addr);
241 io.pfrio_size = size;
242 io.pfrio_size2 = (size2 != NULL) ? *size2 : 0;
243 if (ioctl(dev_fd, DIOCRSETADDRS, &io))
246 *nadd = io.pfrio_nadd;
248 *ndel = io.pfrio_ndel;
250 *nchange = io.pfrio_nchange;
252 *size2 = io.pfrio_size2;
257 pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
260 struct pfioc_table io;
262 if (tbl == NULL || size == NULL || *size < 0 ||
263 (*size && addr == NULL)) {
267 bzero(&io, sizeof io);
268 io.pfrio_flags = flags;
269 io.pfrio_table = *tbl;
270 io.pfrio_buffer = addr;
271 io.pfrio_esize = sizeof(*addr);
272 io.pfrio_size = *size;
273 if (ioctl(dev_fd, DIOCRGETADDRS, &io))
275 *size = io.pfrio_size;
280 pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
283 struct pfioc_table io;
285 if (tbl == NULL || size == NULL || *size < 0 ||
286 (*size && addr == NULL)) {
290 bzero(&io, sizeof io);
291 io.pfrio_flags = flags;
292 io.pfrio_table = *tbl;
293 io.pfrio_buffer = addr;
294 io.pfrio_esize = sizeof(*addr);
295 io.pfrio_size = *size;
296 if (ioctl(dev_fd, DIOCRGETASTATS, &io))
298 *size = io.pfrio_size;
303 pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
305 struct pfioc_table io;
307 if (size < 0 || (size && !tbl)) {
311 bzero(&io, sizeof io);
312 io.pfrio_flags = flags;
313 io.pfrio_buffer = tbl;
314 io.pfrio_esize = sizeof(*tbl);
315 io.pfrio_size = size;
316 if (ioctl(dev_fd, DIOCRCLRTSTATS, &io))
319 *nzero = io.pfrio_nzero;
324 pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
325 int *nmatch, int flags)
327 struct pfioc_table io;
329 if (tbl == NULL || size < 0 || (size && addr == NULL)) {
333 bzero(&io, sizeof io);
334 io.pfrio_flags = flags;
335 io.pfrio_table = *tbl;
336 io.pfrio_buffer = addr;
337 io.pfrio_esize = sizeof(*addr);
338 io.pfrio_size = size;
339 if (ioctl(dev_fd, DIOCRTSTADDRS, &io))
342 *nmatch = io.pfrio_nmatch;
347 pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
348 int *nadd, int *naddr, int ticket, int flags)
350 struct pfioc_table io;
352 if (tbl == NULL || size < 0 || (size && addr == NULL)) {
356 bzero(&io, sizeof io);
357 io.pfrio_flags = flags;
358 io.pfrio_table = *tbl;
359 io.pfrio_buffer = addr;
360 io.pfrio_esize = sizeof(*addr);
361 io.pfrio_size = size;
362 io.pfrio_ticket = ticket;
363 if (ioctl(dev_fd, DIOCRINADEFINE, &io))
366 *nadd = io.pfrio_nadd;
368 *naddr = io.pfrio_naddr;
372 /* interface management code */
375 pfi_get_ifaces(const char *filter, struct pfi_kif *buf, int *size)
377 struct pfioc_iface io;
379 if (size == NULL || *size < 0 || (*size && buf == NULL)) {
383 bzero(&io, sizeof io);
385 if (strlcpy(io.pfiio_name, filter, sizeof(io.pfiio_name)) >=
386 sizeof(io.pfiio_name)) {
390 io.pfiio_buffer = buf;
391 io.pfiio_esize = sizeof(*buf);
392 io.pfiio_size = *size;
393 if (ioctl(dev_fd, DIOCIGETIFACES, &io))
395 *size = io.pfiio_size;
399 /* buffer management code */
401 size_t buf_esize[PFRB_MAX] = { 0,
402 sizeof(struct pfr_table), sizeof(struct pfr_tstats),
403 sizeof(struct pfr_addr), sizeof(struct pfr_astats),
404 sizeof(struct pfi_kif), sizeof(struct pfioc_trans_e)
408 * add one element to the buffer
411 pfr_buf_add(struct pfr_buffer *b, const void *e)
415 if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX ||
420 bs = buf_esize[b->pfrb_type];
421 if (b->pfrb_size == b->pfrb_msize)
422 if (pfr_buf_grow(b, 0))
424 memcpy(((caddr_t)b->pfrb_caddr) + bs * b->pfrb_size, e, bs);
430 * return next element of the buffer (or first one if prev is NULL)
431 * see PFRB_FOREACH macro
434 pfr_buf_next(struct pfr_buffer *b, const void *prev)
438 if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX)
440 if (b->pfrb_size == 0)
443 return (b->pfrb_caddr);
444 bs = buf_esize[b->pfrb_type];
445 if ((((c_caddr_t)prev)-((c_caddr_t)b->pfrb_caddr)) / bs + 1 >=
446 (size_t)b->pfrb_size)
448 return (((c_caddr_t)prev) + bs);
453 * 0: make the buffer somewhat bigger
454 * n: make room for "n" entries in the buffer
457 pfr_buf_grow(struct pfr_buffer *b, int minsize)
462 if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX) {
466 if (minsize != 0 && minsize <= b->pfrb_msize)
468 bs = buf_esize[b->pfrb_type];
469 if (!b->pfrb_msize) {
472 b->pfrb_caddr = calloc(bs, minsize);
473 if (b->pfrb_caddr == NULL)
475 b->pfrb_msize = minsize;
478 minsize = b->pfrb_msize * 2;
479 if (minsize < 0 || (size_t)minsize >= SIZE_T_MAX / bs) {
484 p = realloc(b->pfrb_caddr, minsize * bs);
487 bzero(p + b->pfrb_msize * bs, (minsize - b->pfrb_msize) * bs);
489 b->pfrb_msize = minsize;
495 * reset buffer and free memory.
498 pfr_buf_clear(struct pfr_buffer *b)
502 if (b->pfrb_caddr != NULL)
504 b->pfrb_caddr = NULL;
505 b->pfrb_size = b->pfrb_msize = 0;
509 pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork,
510 int (*append_addr)(struct pfr_buffer *, char *, int))
518 if (!strcmp(file, "-"))
521 fp = pfctl_fopen(file, "r");
525 while ((rv = pfr_next_token(buf, fp)) == 1)
526 if (append_addr(b, buf, nonetwork)) {
536 pfr_next_token(char buf[BUF_SIZE], FILE *fp)
538 static char next_ch = ' ';
543 while (isspace(next_ch) && !feof(fp))
545 /* remove from '#' until end of line */
563 } while (!feof(fp) && !isspace(next_ch));
573 pfr_strerror(int errnum)
577 return "Table does not exist";
579 return "Anchor or Ruleset does not exist";
581 return strerror(errnum);