Home | History | Annotate | Line # | Download | only in pfctl
pfctl_radix.c revision 1.3
      1 /*	$NetBSD: pfctl_radix.c,v 1.3 2004/10/29 19:46:27 dsl Exp $	*/
      2 /*	$OpenBSD: pfctl_radix.c,v 1.24 2004/02/10 18:29:30 henning Exp $ */
      3 
      4 /*
      5  * Copyright (c) 2002 Cedric Berger
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  *
     12  *    - Redistributions of source code must retain the above copyright
     13  *      notice, this list of conditions and the following disclaimer.
     14  *    - Redistributions in binary form must reproduce the above
     15  *      copyright notice, this list of conditions and the following
     16  *      disclaimer in the documentation and/or other materials provided
     17  *      with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     23  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     27  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30  * POSSIBILITY OF SUCH DAMAGE.
     31  *
     32  */
     33 
     34 #include <sys/types.h>
     35 #include <sys/ioctl.h>
     36 #include <sys/socket.h>
     37 
     38 #ifdef __NetBSD__
     39 #include <netinet/in.h>
     40 #endif
     41 
     42 #include <net/if.h>
     43 #include <net/pfvar.h>
     44 
     45 #include <errno.h>
     46 #include <string.h>
     47 #include <ctype.h>
     48 #include <stdio.h>
     49 #include <stdlib.h>
     50 #include <limits.h>
     51 #include <err.h>
     52 
     53 #include "pfctl.h"
     54 
     55 #define BUF_SIZE 256
     56 
     57 extern int dev;
     58 
     59 static int	 pfr_next_token(char buf[], FILE *);
     60 
     61 
     62 int
     63 pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
     64 {
     65 	struct pfioc_table io;
     66 
     67 	bzero(&io, sizeof io);
     68 	io.pfrio_flags = flags;
     69 	if (filter != NULL)
     70 		io.pfrio_table = *filter;
     71 	if (ioctl(dev, DIOCRCLRTABLES, &io))
     72 		return (-1);
     73 	if (ndel != NULL)
     74 		*ndel = io.pfrio_ndel;
     75 	return (0);
     76 }
     77 
     78 int
     79 pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
     80 {
     81 	struct pfioc_table io;
     82 
     83 	if (size < 0 || (size && tbl == NULL)) {
     84 		errno = EINVAL;
     85 		return (-1);
     86 	}
     87 	bzero(&io, sizeof io);
     88 	io.pfrio_flags = flags;
     89 	io.pfrio_buffer = tbl;
     90 	io.pfrio_esize = sizeof(*tbl);
     91 	io.pfrio_size = size;
     92 	if (ioctl(dev, DIOCRADDTABLES, &io))
     93 		return (-1);
     94 	if (nadd != NULL)
     95 		*nadd = io.pfrio_nadd;
     96 	return (0);
     97 }
     98 
     99 int
    100 pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
    101 {
    102 	struct pfioc_table io;
    103 
    104 	if (size < 0 || (size && tbl == NULL)) {
    105 		errno = EINVAL;
    106 		return (-1);
    107 	}
    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))
    114 		return (-1);
    115 	if (ndel != NULL)
    116 		*ndel = io.pfrio_ndel;
    117 	return (0);
    118 }
    119 
    120 int
    121 pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
    122 	int flags)
    123 {
    124 	struct pfioc_table io;
    125 
    126 	if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
    127 		errno = EINVAL;
    128 		return (-1);
    129 	}
    130 	bzero(&io, sizeof io);
    131 	io.pfrio_flags = flags;
    132 	if (filter != NULL)
    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))
    138 		return (-1);
    139 	*size = io.pfrio_size;
    140 	return (0);
    141 }
    142 
    143 int
    144 pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
    145 	int flags)
    146 {
    147 	struct pfioc_table io;
    148 
    149 	if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
    150 		errno = EINVAL;
    151 		return (-1);
    152 	}
    153 	bzero(&io, sizeof io);
    154 	io.pfrio_flags = flags;
    155 	if (filter != NULL)
    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))
    161 		return (-1);
    162 	*size = io.pfrio_size;
    163 	return (0);
    164 }
    165 
    166 int
    167 pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
    168 {
    169 	struct pfioc_table io;
    170 
    171 	if (tbl == NULL) {
    172 		errno = EINVAL;
    173 		return (-1);
    174 	}
    175 	bzero(&io, sizeof io);
    176 	io.pfrio_flags = flags;
    177 	io.pfrio_table = *tbl;
    178 	if (ioctl(dev, DIOCRCLRADDRS, &io))
    179 		return (-1);
    180 	if (ndel != NULL)
    181 		*ndel = io.pfrio_ndel;
    182 	return (0);
    183 }
    184 
    185 int
    186 pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
    187     int *nadd, int flags)
    188 {
    189 	struct pfioc_table io;
    190 
    191 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
    192 		errno = EINVAL;
    193 		return (-1);
    194 	}
    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))
    202 		return (-1);
    203 	if (nadd != NULL)
    204 		*nadd = io.pfrio_nadd;
    205 	return (0);
    206 }
    207 
    208 int
    209 pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
    210     int *ndel, int flags)
    211 {
    212 	struct pfioc_table io;
    213 
    214 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
    215 		errno = EINVAL;
    216 		return (-1);
    217 	}
    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))
    225 		return (-1);
    226 	if (ndel != NULL)
    227 		*ndel = io.pfrio_ndel;
    228 	return (0);
    229 }
    230 
    231 int
    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)
    234 {
    235 	struct pfioc_table io;
    236 
    237 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
    238 		errno = EINVAL;
    239 		return (-1);
    240 	}
    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))
    249 		return (-1);
    250 	if (nadd != NULL)
    251 		*nadd = io.pfrio_nadd;
    252 	if (ndel != NULL)
    253 		*ndel = io.pfrio_ndel;
    254 	if (nchange != NULL)
    255 		*nchange = io.pfrio_nchange;
    256 	if (size2 != NULL)
    257 		*size2 = io.pfrio_size2;
    258 	return (0);
    259 }
    260 
    261 int
    262 pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
    263     int flags)
    264 {
    265 	struct pfioc_table io;
    266 
    267 	if (tbl == NULL || size == NULL || *size < 0 ||
    268 	    (*size && addr == NULL)) {
    269 		errno = EINVAL;
    270 		return (-1);
    271 	}
    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))
    279 		return (-1);
    280 	*size = io.pfrio_size;
    281 	return (0);
    282 }
    283 
    284 int
    285 pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
    286     int flags)
    287 {
    288 	struct pfioc_table io;
    289 
    290 	if (tbl == NULL || size == NULL || *size < 0 ||
    291 	    (*size && addr == NULL)) {
    292 		errno = EINVAL;
    293 		return (-1);
    294 	}
    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))
    302 		return (-1);
    303 	*size = io.pfrio_size;
    304 	return (0);
    305 }
    306 
    307 int
    308 pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
    309     int *nzero, int flags)
    310 {
    311 	struct pfioc_table io;
    312 
    313 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
    314 		errno = EINVAL;
    315 		return (-1);
    316 	}
    317 	bzero(&io, sizeof io);
    318 	io.pfrio_flags = flags;
    319 	io.pfrio_table = *tbl;
    320 	io.pfrio_buffer = addr;
    321 	io.pfrio_esize = sizeof(*addr);
    322 	io.pfrio_size = size;
    323 	if (ioctl(dev, DIOCRCLRASTATS, &io))
    324 		return (-1);
    325 	if (nzero != NULL)
    326 		*nzero = io.pfrio_nzero;
    327 	return (0);
    328 }
    329 
    330 int
    331 pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
    332 {
    333 	struct pfioc_table io;
    334 
    335 	if (size < 0 || (size && !tbl)) {
    336 		errno = EINVAL;
    337 		return (-1);
    338 	}
    339 	bzero(&io, sizeof io);
    340 	io.pfrio_flags = flags;
    341 	io.pfrio_buffer = tbl;
    342 	io.pfrio_esize = sizeof(*tbl);
    343 	io.pfrio_size = size;
    344 	if (ioctl(dev, DIOCRCLRTSTATS, &io))
    345 		return (-1);
    346 	if (nzero)
    347 		*nzero = io.pfrio_nzero;
    348 	return (0);
    349 }
    350 
    351 int
    352 pfr_set_tflags(struct pfr_table *tbl, int size, int setflag, int clrflag,
    353     int *nchange, int *ndel, int flags)
    354 {
    355 	struct pfioc_table io;
    356 
    357 	if (size < 0 || (size && !tbl)) {
    358 		errno = EINVAL;
    359 		return (-1);
    360 	}
    361 	bzero(&io, sizeof io);
    362 	io.pfrio_flags = flags;
    363 	io.pfrio_buffer = tbl;
    364 	io.pfrio_esize = sizeof(*tbl);
    365 	io.pfrio_size = size;
    366 	io.pfrio_setflag = setflag;
    367 	io.pfrio_clrflag = clrflag;
    368 	if (ioctl(dev, DIOCRSETTFLAGS, &io))
    369 		return (-1);
    370 	if (nchange)
    371 		*nchange = io.pfrio_nchange;
    372 	if (ndel)
    373 		*ndel = io.pfrio_ndel;
    374 	return (0);
    375 }
    376 
    377 int
    378 pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
    379     int *nmatch, int flags)
    380 {
    381 	struct pfioc_table io;
    382 
    383 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
    384 		errno = EINVAL;
    385 		return (-1);
    386 	}
    387 	bzero(&io, sizeof io);
    388 	io.pfrio_flags = flags;
    389 	io.pfrio_table = *tbl;
    390 	io.pfrio_buffer = addr;
    391 	io.pfrio_esize = sizeof(*addr);
    392 	io.pfrio_size = size;
    393 	if (ioctl(dev, DIOCRTSTADDRS, &io))
    394 		return (-1);
    395 	if (nmatch)
    396 		*nmatch = io.pfrio_nmatch;
    397 	return (0);
    398 }
    399 
    400 int
    401 pfr_ina_begin(struct pfr_table *trs, int *ticket, int *ndel, int flags)
    402 {
    403 	struct pfioc_table io;
    404 
    405 	bzero(&io, sizeof io);
    406 	if (trs != NULL)
    407 		io.pfrio_table = *trs;
    408 	io.pfrio_flags = flags;
    409 	if (ioctl(dev, DIOCRINABEGIN, &io))
    410 		return (-1);
    411 	if (ndel != NULL)
    412 		*ndel = io.pfrio_ndel;
    413 	if (ticket != NULL)
    414 		*ticket = io.pfrio_ticket;
    415 	return (0);
    416 }
    417 
    418 int
    419 pfr_ina_commit(struct pfr_table *trs, int ticket, int *nadd, int *nchange,
    420     int flags)
    421 {
    422 	struct pfioc_table io;
    423 
    424 	bzero(&io, sizeof io);
    425 	if (trs != NULL)
    426 		io.pfrio_table = *trs;
    427 	io.pfrio_flags = flags;
    428 	io.pfrio_ticket = ticket;
    429 	if (ioctl(dev, DIOCRINACOMMIT, &io))
    430 		return (-1);
    431 	if (nadd != NULL)
    432 		*nadd = io.pfrio_nadd;
    433 	if (nchange != NULL)
    434 		*nchange = io.pfrio_nchange;
    435 	return (0);
    436 }
    437 
    438 int
    439 pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
    440     int *nadd, int *naddr, int ticket, int flags)
    441 {
    442 	struct pfioc_table io;
    443 
    444 	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
    445 		errno = EINVAL;
    446 		return (-1);
    447 	}
    448 	bzero(&io, sizeof io);
    449 	io.pfrio_flags = flags;
    450 	io.pfrio_table = *tbl;
    451 	io.pfrio_buffer = addr;
    452 	io.pfrio_esize = sizeof(*addr);
    453 	io.pfrio_size = size;
    454 	io.pfrio_ticket = ticket;
    455 	if (ioctl(dev, DIOCRINADEFINE, &io))
    456 		return (-1);
    457 	if (nadd != NULL)
    458 		*nadd = io.pfrio_nadd;
    459 	if (naddr != NULL)
    460 		*naddr = io.pfrio_naddr;
    461 	return (0);
    462 }
    463 
    464 /* interface management code */
    465 
    466 int
    467 pfi_get_ifaces(const char *filter, struct pfi_if *buf, int *size, int flags)
    468 {
    469 	struct pfioc_iface io;
    470 
    471 	if (size == NULL || *size < 0 || (*size && buf == NULL)) {
    472 		errno = EINVAL;
    473 		return (-1);
    474 	}
    475 	bzero(&io, sizeof io);
    476 	io.pfiio_flags = flags;
    477 	if (filter != NULL)
    478 		if (strlcpy(io.pfiio_name, filter, sizeof(io.pfiio_name)) >=
    479 		    sizeof(io.pfiio_name)) {
    480 			errno = EINVAL;
    481 			return (-1);
    482 		}
    483 	io.pfiio_buffer = buf;
    484 	io.pfiio_esize = sizeof(*buf);
    485 	io.pfiio_size = *size;
    486 	if (ioctl(dev, DIOCIGETIFACES, &io))
    487 		return (-1);
    488 	*size = io.pfiio_size;
    489 	return (0);
    490 }
    491 
    492 /* buffer management code */
    493 
    494 size_t buf_esize[PFRB_MAX] = { 0,
    495 	sizeof(struct pfr_table), sizeof(struct pfr_tstats),
    496 	sizeof(struct pfr_addr), sizeof(struct pfr_astats),
    497 	sizeof(struct pfi_if), sizeof(struct pfioc_trans_e)
    498 };
    499 
    500 /*
    501  * add one element to the buffer
    502  */
    503 int
    504 pfr_buf_add(struct pfr_buffer *b, const void *e)
    505 {
    506 	size_t bs;
    507 
    508 	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX ||
    509 	    e == NULL) {
    510 		errno = EINVAL;
    511 		return (-1);
    512 	}
    513 	bs = buf_esize[b->pfrb_type];
    514 	if (b->pfrb_size == b->pfrb_msize)
    515 		if (pfr_buf_grow(b, 0))
    516 			return (-1);
    517 	memcpy(((caddr_t)b->pfrb_caddr) + bs * b->pfrb_size, e, bs);
    518 	b->pfrb_size++;
    519 	return (0);
    520 }
    521 
    522 /*
    523  * return next element of the buffer (or first one if prev is NULL)
    524  * see PFRB_FOREACH macro
    525  */
    526 void *
    527 pfr_buf_next(struct pfr_buffer *b, const void *prev)
    528 {
    529 	size_t bs;
    530 
    531 	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX)
    532 		return (NULL);
    533 	if (b->pfrb_size == 0)
    534 		return (NULL);
    535 	if (prev == NULL)
    536 		return (b->pfrb_caddr);
    537 	bs = buf_esize[b->pfrb_type];
    538 	if ((((caddr_t)prev)-((caddr_t)b->pfrb_caddr)) / bs >= b->pfrb_size-1)
    539 		return (NULL);
    540 	return (((caddr_t)prev) + bs);
    541 }
    542 
    543 /*
    544  * minsize:
    545  *    0: make the buffer somewhat bigger
    546  *    n: make room for "n" entries in the buffer
    547  */
    548 int
    549 pfr_buf_grow(struct pfr_buffer *b, int minsize)
    550 {
    551 	caddr_t p;
    552 	size_t bs;
    553 
    554 	if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX) {
    555 		errno = EINVAL;
    556 		return (-1);
    557 	}
    558 	if (minsize != 0 && minsize <= b->pfrb_msize)
    559 		return (0);
    560 	bs = buf_esize[b->pfrb_type];
    561 	if (!b->pfrb_msize) {
    562 		if (minsize < 64)
    563 			minsize = 64;
    564 		b->pfrb_caddr = calloc(bs, minsize);
    565 		if (b->pfrb_caddr == NULL)
    566 			return (-1);
    567 		b->pfrb_msize = minsize;
    568 	} else {
    569 		if (minsize == 0)
    570 			minsize = b->pfrb_msize * 2;
    571 		if (minsize < 0 || minsize >= SIZE_T_MAX / bs) {
    572 			/* msize overflow */
    573 			errno = ENOMEM;
    574 			return (-1);
    575 		}
    576 		p = realloc(b->pfrb_caddr, minsize * bs);
    577 		if (p == NULL)
    578 			return (-1);
    579 		bzero(p + b->pfrb_msize * bs, (minsize - b->pfrb_msize) * bs);
    580 		b->pfrb_caddr = p;
    581 		b->pfrb_msize = minsize;
    582 	}
    583 	return (0);
    584 }
    585 
    586 /*
    587  * reset buffer and free memory.
    588  */
    589 void
    590 pfr_buf_clear(struct pfr_buffer *b)
    591 {
    592 	if (b == NULL)
    593 		return;
    594 	if (b->pfrb_caddr != NULL)
    595 		free(b->pfrb_caddr);
    596 	b->pfrb_caddr = NULL;
    597 	b->pfrb_size = b->pfrb_msize = 0;
    598 }
    599 
    600 int
    601 pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork,
    602     int (*append_addr)(struct pfr_buffer *, char *, int))
    603 {
    604 	FILE	*fp;
    605 	char	 buf[BUF_SIZE];
    606 	int	 rv;
    607 
    608 	if (file == NULL)
    609 		return (0);
    610 	if (!strcmp(file, "-"))
    611 		fp = stdin;
    612 	else {
    613 		fp = fopen(file, "r");
    614 		if (fp == NULL)
    615 			return (-1);
    616 	}
    617 	while ((rv = pfr_next_token(buf, fp)) == 1)
    618 		if (append_addr(b, buf, nonetwork)) {
    619 			rv = -1;
    620 			break;
    621 		}
    622 	if (fp != stdin)
    623 		fclose(fp);
    624 	return (rv);
    625 }
    626 
    627 int
    628 pfr_next_token(char buf[BUF_SIZE], FILE *fp)
    629 {
    630 	static char	next_ch = ' ';
    631 	int		i = 0;
    632 
    633 	for (;;) {
    634 		/* skip spaces */
    635 		while (isspace((unsigned char)next_ch) && !feof(fp))
    636 			next_ch = fgetc(fp);
    637 		/* remove from '#' until end of line */
    638 		if (next_ch == '#')
    639 			while (!feof(fp)) {
    640 				next_ch = fgetc(fp);
    641 				if (next_ch == '\n')
    642 					break;
    643 			}
    644 		else
    645 			break;
    646 	}
    647 	if (feof(fp)) {
    648 		next_ch = ' ';
    649 		return (0);
    650 	}
    651 	do {
    652 		if (i < BUF_SIZE)
    653 			buf[i++] = next_ch;
    654 		next_ch = fgetc(fp);
    655 	} while (!feof(fp) && !isspace((unsigned char)next_ch));
    656 	if (i >= BUF_SIZE) {
    657 		errno = EINVAL;
    658 		return (-1);
    659 	}
    660 	buf[i] = '\0';
    661 	return (1);
    662 }
    663 
    664 char *
    665 pfr_strerror(int errnum)
    666 {
    667 	switch (errnum) {
    668 	case ESRCH:
    669 		return "Table does not exist";
    670 	case ENOENT:
    671 		return "Anchor or Ruleset does not exist";
    672 	default:
    673 		return strerror(errnum);
    674 	}
    675 }
    676