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
);