Home | History | Annotate | Line # | Download | only in pfctl
pfctl_radix.c revision 1.1
      1 /*	$OpenBSD: pfctl_radix.c,v 1.24 2004/02/10 18:29:30 henning Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2002 Cedric Berger
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  *
     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.
     17  *
     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.
     30  *
     31  */
     32 
     33 #include <sys/types.h>
     34 #include <sys/ioctl.h>
     35 #include <sys/socket.h>
     36 
     37 #include <net/if.h>
     38 #include <net/pfvar.h>
     39 
     40 #include <errno.h>
     41 #include <string.h>
     42 #include <ctype.h>
     43 #include <stdio.h>
     44 #include <stdlib.h>
     45 #include <limits.h>
     46 #include <err.h>
     47 
     48 #include "pfctl.h"
     49 
     50 #define BUF_SIZE 256
     51 
     52 extern int dev;
     53 
     54 static int	 pfr_next_token(char buf[], FILE *);
     55 
     56 
     57 int
     58 pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
     59 {
     60 	struct pfioc_table io;
     61 
     62 	bzero(&io, sizeof io);
     63 	io.pfrio_flags = flags;
     64 	if (filter != NULL)
     65 		io.pfrio_table = *filter;
     66 	if (ioctl(dev, DIOCRCLRTABLES, &io))
     67 		return (-1);
     68 	if (ndel != NULL)
     69 		*ndel = io.pfrio_ndel;
     70 	return (0);
     71 }
     72 
     73 int
     74 pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
     75 {
     76 	struct pfioc_table io;
     77 
     78 	if (size < 0 || (size && tbl == NULL)) {
     79 		errno = EINVAL;
     80 		return (-1);
     81 	}
     82 	bzero(&io, sizeof io);
     83 	io.pfrio_flags = flags;
     84 	io.pfrio_buffer = tbl;
     85 	io.pfrio_esize = sizeof(*tbl);
     86 	io.pfrio_size = size;
     87 	if (ioctl(dev, DIOCRADDTABLES, &io))
     88 		return (-1);
     89 	if (nadd != NULL)
     90 		*nadd = io.pfrio_nadd;
     91 	return (0);
     92 }
     93 
     94 int
     95 pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
     96 {
     97 	struct pfioc_table io;
     98 
     99 	if (size < 0 || (size && tbl == NULL)) {
    100 		errno = EINVAL;
    101 		return (-1);
    102 	}
    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, DIOCRDELTABLES, &io))
    109 		return (-1);
    110 	if (ndel != NULL)
    111 		*ndel = io.pfrio_ndel;
    112 	return (0);
    113 }
    114 
    115 int
    116 pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
    117 	int flags)
    118 {
    119 	struct pfioc_table io;
    120 
    121 	if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
    122 		errno = EINVAL;
    123 		return (-1);
    124 	}
    125 	bzero(&io, sizeof io);
    126 	io.pfrio_flags = flags;
    127 	if (filter != NULL)
    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, DIOCRGETTABLES, &io))
    133 		return (-1);
    134 	*size = io.pfrio_size;
    135 	return (0);
    136 }
    137 
    138 int
    139 pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
    140 	int flags)
    141 {
    142 	struct pfioc_table io;
    143 
    144 	if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
    145 		errno = EINVAL;
    146 		return (-1);
    147 	}
    148 	bzero(&io, sizeof io);
    149 	io.pfrio_flags = flags;
    150 	if (filter != NULL)
    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, DIOCRGETTSTATS, &io))
    156 		return (-1);
    157 	*size = io.pfrio_size;
    158 	return (0);
    159 }
    160 
    161 int
    162 pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
    163 {
    164 	struct pfioc_table io;
    165 
    166 	if (tbl == NULL) {
    167 		errno = EINVAL;
    168 		return (-1);
    169 	}
    170 	bzero(&io, sizeof io);
    171 	io.pfrio_flags = flags;
    172 	io.pfrio_table = *tbl;
    173 	if (ioctl(dev, DIOCRCLRADDRS, &io))
    174 		return (-1);
    175 	if (ndel != NULL)
    176 		*ndel = io.pfrio_ndel;
    177 	return (0);
    178 }
    179 
    180 int
    181 pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
    182     int *nadd, int flags)
    183 {
    184 	struct pfioc_table io;
    185 
    186 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
    187 		errno = EINVAL;
    188 		return (-1);
    189 	}
    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, DIOCRADDADDRS, &io))
    197 		return (-1);
    198 	if (nadd != NULL)
    199 		*nadd = io.pfrio_nadd;
    200 	return (0);
    201 }
    202 
    203 int
    204 pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
    205     int *ndel, int flags)
    206 {
    207 	struct pfioc_table io;
    208 
    209 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
    210 		errno = EINVAL;
    211 		return (-1);
    212 	}
    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, DIOCRDELADDRS, &io))
    220 		return (-1);
    221 	if (ndel != NULL)
    222 		*ndel = io.pfrio_ndel;
    223 	return (0);
    224 }
    225 
    226 int
    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)
    229 {
    230 	struct pfioc_table io;
    231 
    232 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
    233 		errno = EINVAL;
    234 		return (-1);
    235 	}
    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, DIOCRSETADDRS, &io))
    244 		return (-1);
    245 	if (nadd != NULL)
    246 		*nadd = io.pfrio_nadd;
    247 	if (ndel != NULL)
    248 		*ndel = io.pfrio_ndel;
    249 	if (nchange != NULL)
    250 		*nchange = io.pfrio_nchange;
    251 	if (size2 != NULL)
    252 		*size2 = io.pfrio_size2;
    253 	return (0);
    254 }
    255 
    256 int
    257 pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
    258     int flags)
    259 {
    260 	struct pfioc_table io;
    261 
    262 	if (tbl == NULL || size == NULL || *size < 0 ||
    263 	    (*size && addr == NULL)) {
    264 		errno = EINVAL;
    265 		return (-1);
    266 	}
    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, DIOCRGETADDRS, &io))
    274 		return (-1);
    275 	*size = io.pfrio_size;
    276 	return (0);
    277 }
    278 
    279 int
    280 pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
    281     int flags)
    282 {
    283 	struct pfioc_table io;
    284 
    285 	if (tbl == NULL || size == NULL || *size < 0 ||
    286 	    (*size && addr == NULL)) {
    287 		errno = EINVAL;
    288 		return (-1);
    289 	}
    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, DIOCRGETASTATS, &io))
    297 		return (-1);
    298 	*size = io.pfrio_size;
    299 	return (0);
    300 }
    301 
    302 int
    303 pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
    304     int *nzero, int flags)
    305 {
    306 	struct pfioc_table io;
    307 
    308 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
    309 		errno = EINVAL;
    310 		return (-1);
    311 	}
    312 	bzero(&io, sizeof io);
    313 	io.pfrio_flags = flags;
    314 	io.pfrio_table = *tbl;
    315 	io.pfrio_buffer = addr;
    316 	io.pfrio_esize = sizeof(*addr);
    317 	io.pfrio_size = size;
    318 	if (ioctl(dev, DIOCRCLRASTATS, &io))
    319 		return (-1);
    320 	if (nzero != NULL)
    321 		*nzero = io.pfrio_nzero;
    322 	return (0);
    323 }
    324 
    325 int
    326 pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
    327 {
    328 	struct pfioc_table io;
    329 
    330 	if (size < 0 || (size && !tbl)) {
    331 		errno = EINVAL;
    332 		return (-1);
    333 	}
    334 	bzero(&io, sizeof io);
    335 	io.pfrio_flags = flags;
    336 	io.pfrio_buffer = tbl;
    337 	io.pfrio_esize = sizeof(*tbl);
    338 	io.pfrio_size = size;
    339 	if (ioctl(dev, DIOCRCLRTSTATS, &io))
    340 		return (-1);
    341 	if (nzero)
    342 		*nzero = io.pfrio_nzero;
    343 	return (0);
    344 }
    345 
    346 int
    347 pfr_set_tflags(struct pfr_table *tbl, int size, int setflag, int clrflag,
    348     int *nchange, int *ndel, int flags)
    349 {
    350 	struct pfioc_table io;
    351 
    352 	if (size < 0 || (size && !tbl)) {
    353 		errno = EINVAL;
    354 		return (-1);
    355 	}
    356 	bzero(&io, sizeof io);
    357 	io.pfrio_flags = flags;
    358 	io.pfrio_buffer = tbl;
    359 	io.pfrio_esize = sizeof(*tbl);
    360 	io.pfrio_size = size;
    361 	io.pfrio_setflag = setflag;
    362 	io.pfrio_clrflag = clrflag;
    363 	if (ioctl(dev, DIOCRSETTFLAGS, &io))
    364 		return (-1);
    365 	if (nchange)
    366 		*nchange = io.pfrio_nchange;
    367 	if (ndel)
    368 		*ndel = io.pfrio_ndel;
    369 	return (0);
    370 }
    371 
    372 int
    373 pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
    374     int *nmatch, int flags)
    375 {
    376 	struct pfioc_table io;
    377 
    378 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
    379 		errno = EINVAL;
    380 		return (-1);
    381 	}
    382 	bzero(&io, sizeof io);
    383 	io.pfrio_flags = flags;
    384 	io.pfrio_table = *tbl;
    385 	io.pfrio_buffer = addr;
    386 	io.pfrio_esize = sizeof(*addr);
    387 	io.pfrio_size = size;
    388 	if (ioctl(dev, DIOCRTSTADDRS, &io))
    389 		return (-1);
    390 	if (nmatch)
    391 		*nmatch = io.pfrio_nmatch;
    392 	return (0);
    393 }
    394 
    395 int
    396 pfr_ina_begin(struct pfr_table *trs, int *ticket, int *ndel, int flags)
    397 {
    398 	struct pfioc_table io;
    399 
    400 	bzero(&io, sizeof io);
    401 	if (trs != NULL)
    402 		io.pfrio_table = *trs;
    403 	io.pfrio_flags = flags;
    404 	if (ioctl(dev, DIOCRINABEGIN, &io))
    405 		return (-1);
    406 	if (ndel != NULL)
    407 		*ndel = io.pfrio_ndel;
    408 	if (ticket != NULL)
    409 		*ticket = io.pfrio_ticket;
    410 	return (0);
    411 }
    412 
    413 int
    414 pfr_ina_commit(struct pfr_table *trs, int ticket, int *nadd, int *nchange,
    415     int flags)
    416 {
    417 	struct pfioc_table io;
    418 
    419 	bzero(&io, sizeof io);
    420 	if (trs != NULL)
    421 		io.pfrio_table = *trs;
    422 	io.pfrio_flags = flags;
    423 	io.pfrio_ticket = ticket;
    424 	if (ioctl(dev, DIOCRINACOMMIT, &io))
    425 		return (-1);
    426 	if (nadd != NULL)
    427 		*nadd = io.pfrio_nadd;
    428 	if (nchange != NULL)
    429 		*nchange = io.pfrio_nchange;
    430 	return (0);
    431 }
    432 
    433 int
    434 pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
    435     int *nadd, int *naddr, int ticket, int flags)
    436 {
    437 	struct pfioc_table io;
    438 
    439 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
    440 		errno = EINVAL;
    441 		return (-1);
    442 	}
    443 	bzero(&io, sizeof io);
    444 	io.pfrio_flags = flags;
    445 	io.pfrio_table = *tbl;
    446 	io.pfrio_buffer = addr;
    447 	io.pfrio_esize = sizeof(*addr);
    448 	io.pfrio_size = size;
    449 	io.pfrio_ticket = ticket;
    450 	if (ioctl(dev, DIOCRINADEFINE, &io))
    451 		return (-1);
    452 	if (nadd != NULL)
    453 		*nadd = io.pfrio_nadd;
    454 	if (naddr != NULL)
    455 		*naddr = io.pfrio_naddr;
    456 	return (0);
    457 }
    458 
    459 /* interface management code */
    460 
    461 int
    462 pfi_get_ifaces(const char *filter, struct pfi_if *buf, int *size, int flags)
    463 {
    464 	struct pfioc_iface io;
    465 
    466 	if (size == NULL || *size < 0 || (*size && buf == NULL)) {
    467 		errno = EINVAL;
    468 		return (-1);
    469 	}
    470 	bzero(&io, sizeof io);
    471 	io.pfiio_flags = flags;
    472 	if (filter != NULL)
    473 		if (strlcpy(io.pfiio_name, filter, sizeof(io.pfiio_name)) >=
    474 		    sizeof(io.pfiio_name)) {
    475 			errno = EINVAL;
    476 			return (-1);
    477 		}
    478 	io.pfiio_buffer = buf;
    479 	io.pfiio_esize = sizeof(*buf);
    480 	io.pfiio_size = *size;
    481 	if (ioctl(dev, DIOCIGETIFACES, &io))
    482 		return (-1);
    483 	*size = io.pfiio_size;
    484 	return (0);
    485 }
    486 
    487 /* buffer management code */
    488 
    489 size_t buf_esize[PFRB_MAX] = { 0,
    490 	sizeof(struct pfr_table), sizeof(struct pfr_tstats),
    491 	sizeof(struct pfr_addr), sizeof(struct pfr_astats),
    492 	sizeof(struct pfi_if), sizeof(struct pfioc_trans_e)
    493 };
    494 
    495 /*
    496  * add one element to the buffer
    497  */
    498 int
    499 pfr_buf_add(struct pfr_buffer *b, const void *e)
    500 {
    501 	size_t bs;
    502 
    503 	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX ||
    504 	    e == NULL) {
    505 		errno = EINVAL;
    506 		return (-1);
    507 	}
    508 	bs = buf_esize[b->pfrb_type];
    509 	if (b->pfrb_size == b->pfrb_msize)
    510 		if (pfr_buf_grow(b, 0))
    511 			return (-1);
    512 	memcpy(((caddr_t)b->pfrb_caddr) + bs * b->pfrb_size, e, bs);
    513 	b->pfrb_size++;
    514 	return (0);
    515 }
    516 
    517 /*
    518  * return next element of the buffer (or first one if prev is NULL)
    519  * see PFRB_FOREACH macro
    520  */
    521 void *
    522 pfr_buf_next(struct pfr_buffer *b, const void *prev)
    523 {
    524 	size_t bs;
    525 
    526 	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX)
    527 		return (NULL);
    528 	if (b->pfrb_size == 0)
    529 		return (NULL);
    530 	if (prev == NULL)
    531 		return (b->pfrb_caddr);
    532 	bs = buf_esize[b->pfrb_type];
    533 	if ((((caddr_t)prev)-((caddr_t)b->pfrb_caddr)) / bs >= b->pfrb_size-1)
    534 		return (NULL);
    535 	return (((caddr_t)prev) + bs);
    536 }
    537 
    538 /*
    539  * minsize:
    540  *    0: make the buffer somewhat bigger
    541  *    n: make room for "n" entries in the buffer
    542  */
    543 int
    544 pfr_buf_grow(struct pfr_buffer *b, int minsize)
    545 {
    546 	caddr_t p;
    547 	size_t bs;
    548 
    549 	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX) {
    550 		errno = EINVAL;
    551 		return (-1);
    552 	}
    553 	if (minsize != 0 && minsize <= b->pfrb_msize)
    554 		return (0);
    555 	bs = buf_esize[b->pfrb_type];
    556 	if (!b->pfrb_msize) {
    557 		if (minsize < 64)
    558 			minsize = 64;
    559 		b->pfrb_caddr = calloc(bs, minsize);
    560 		if (b->pfrb_caddr == NULL)
    561 			return (-1);
    562 		b->pfrb_msize = minsize;
    563 	} else {
    564 		if (minsize == 0)
    565 			minsize = b->pfrb_msize * 2;
    566 		if (minsize < 0 || minsize >= SIZE_T_MAX / bs) {
    567 			/* msize overflow */
    568 			errno = ENOMEM;
    569 			return (-1);
    570 		}
    571 		p = realloc(b->pfrb_caddr, minsize * bs);
    572 		if (p == NULL)
    573 			return (-1);
    574 		bzero(p + b->pfrb_msize * bs, (minsize - b->pfrb_msize) * bs);
    575 		b->pfrb_caddr = p;
    576 		b->pfrb_msize = minsize;
    577 	}
    578 	return (0);
    579 }
    580 
    581 /*
    582  * reset buffer and free memory.
    583  */
    584 void
    585 pfr_buf_clear(struct pfr_buffer *b)
    586 {
    587 	if (b == NULL)
    588 		return;
    589 	if (b->pfrb_caddr != NULL)
    590 		free(b->pfrb_caddr);
    591 	b->pfrb_caddr = NULL;
    592 	b->pfrb_size = b->pfrb_msize = 0;
    593 }
    594 
    595 int
    596 pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork,
    597     int (*append_addr)(struct pfr_buffer *, char *, int))
    598 {
    599 	FILE	*fp;
    600 	char	 buf[BUF_SIZE];
    601 	int	 rv;
    602 
    603 	if (file == NULL)
    604 		return (0);
    605 	if (!strcmp(file, "-"))
    606 		fp = stdin;
    607 	else {
    608 		fp = fopen(file, "r");
    609 		if (fp == NULL)
    610 			return (-1);
    611 	}
    612 	while ((rv = pfr_next_token(buf, fp)) == 1)
    613 		if (append_addr(b, buf, nonetwork)) {
    614 			rv = -1;
    615 			break;
    616 		}
    617 	if (fp != stdin)
    618 		fclose(fp);
    619 	return (rv);
    620 }
    621 
    622 int
    623 pfr_next_token(char buf[BUF_SIZE], FILE *fp)
    624 {
    625 	static char	next_ch = ' ';
    626 	int		i = 0;
    627 
    628 	for (;;) {
    629 		/* skip spaces */
    630 		while (isspace(next_ch) && !feof(fp))
    631 			next_ch = fgetc(fp);
    632 		/* remove from '#' until end of line */
    633 		if (next_ch == '#')
    634 			while (!feof(fp)) {
    635 				next_ch = fgetc(fp);
    636 				if (next_ch == '\n')
    637 					break;
    638 			}
    639 		else
    640 			break;
    641 	}
    642 	if (feof(fp)) {
    643 		next_ch = ' ';
    644 		return (0);
    645 	}
    646 	do {
    647 		if (i < BUF_SIZE)
    648 			buf[i++] = next_ch;
    649 		next_ch = fgetc(fp);
    650 	} while (!feof(fp) && !isspace(next_ch));
    651 	if (i >= BUF_SIZE) {
    652 		errno = EINVAL;
    653 		return (-1);
    654 	}
    655 	buf[i] = '\0';
    656 	return (1);
    657 }
    658 
    659 char *
    660 pfr_strerror(int errnum)
    661 {
    662 	switch (errnum) {
    663 	case ESRCH:
    664 		return "Table does not exist";
    665 	case ENOENT:
    666 		return "Anchor or Ruleset does not exist";
    667 	default:
    668 		return strerror(errnum);
    669 	}
    670 }
    671