diff options
author | Cedric Berger <cedric@cvs.openbsd.org> | 2003-07-03 09:13:07 +0000 |
---|---|---|
committer | Cedric Berger <cedric@cvs.openbsd.org> | 2003-07-03 09:13:07 +0000 |
commit | 7e91f812e08632f0bb7ac90fdc35423bee97e1fb (patch) | |
tree | 09d5093be7465755788d22ef06b2d5ca44718425 /sbin/pfctl | |
parent | b3181fe2641a38a929abe88ab2535cad85ff9f02 (diff) |
This patch finally cleanup pfctl_table.c. No more global buffer,
and a couple of parsing functions moved to parse.y or pfctl_parser
where they belong.
I also took the opportunity to replace "void" functions with exit(1)
or err() inside by "int" functions, with the caller checking the
return value for errors (much cleaner and an old request from Theo)
ok dhartmei@ henning@
Diffstat (limited to 'sbin/pfctl')
-rw-r--r-- | sbin/pfctl/parse.y | 40 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.c | 6 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.h | 7 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.c | 70 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.h | 11 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_radix.c | 33 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_table.c | 351 |
7 files changed, 262 insertions, 256 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index dd22ff8bcfd..224a0e3339e 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.393 2003/06/19 22:08:35 deraadt Exp $ */ +/* $OpenBSD: parse.y,v 1.394 2003/07/03 09:13:05 cedric Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -855,10 +855,14 @@ tabledef : TABLE '<' STRING '>' table_opts { PF_TABLE_NAME_SIZE - 1); YYERROR; } - pfctl_define_table($3, $5.flags, $5.init_addr, + if (pfctl_define_table($3, $5.flags, $5.init_addr, (pf->opts & PF_OPT_NOACTION) || !(pf->loadopt & (PFCTL_FLAG_TABLE | PFCTL_FLAG_ALL)), - pf->anchor, pf->ruleset); + pf->anchor, pf->ruleset, pf->ab)) { + yyerror("cannot define table %s: %s", $3, + pfr_strerror(errno)); + YYERROR; + } } ; @@ -889,7 +893,12 @@ table_opt : STRING } | '{' tableaddrs '}' { table_opts.init_addr = 1; } | FILENAME STRING { - pfctl_append_file($2); + if(pfr_buf_load(pf->ab, $2, 0, append_addr)) { + if (errno) + yyerror("cannot load %s: %s", $2, + pfr_strerror(errno)); + YYERROR; + } table_opts.init_addr = 1; } ; @@ -898,10 +907,29 @@ tableaddrs : /* empty */ | tableaddrs tableaddr comma tableaddr : not STRING { - pfctl_append_addr($2, -1, $1); + if (append_addr_not(pf->ab, $2, 0, $1)) { + if (errno) + yyerror("cannot add %s: %s", $2, + pfr_strerror(errno)); + YYERROR; + } } | not STRING '/' number { - pfctl_append_addr($2, $4, $1); + char *buf = NULL; + + if (asprintf(&buf, "%s/%d", $2, $4) < 0) { + if (errno) + yyerror("cannot add %s/%d: %s", $2, $4, + strerror(errno)); + YYERROR; + } else if (append_addr_not(pf->ab, buf, 0, $1)) { + if (errno) + yyerror("cannot add %s: %s", buf, + pfr_strerror(errno)); + free(buf); + YYERROR; + } + free(buf); } ; diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c index 8ef20339e6e..57e313bc4fd 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl.c,v 1.178 2003/06/29 12:22:39 dhartmei Exp $ */ +/* $OpenBSD: pfctl.c,v 1.179 2003/07/03 09:13:06 cedric Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -918,10 +918,13 @@ pfctl_rules(int dev, char *filename, int opts, char *anchorname, struct pfioc_rule pr[PF_RULESET_MAX]; struct pfioc_altq pa; struct pfctl pf; + struct pfr_buffer ab; int i; memset(&pa, 0, sizeof(pa)); memset(&pf, 0, sizeof(pf)); + memset(&ab, 0, sizeof(ab)); + ab.pfrb_type = PFRB_ADDRS; for (i = 0; i < PF_RULESET_MAX; i++) { memset(&pr[i], 0, sizeof(pr[i])); memcpy(pr[i].anchor, anchorname, sizeof(pr[i].anchor)); @@ -970,6 +973,7 @@ pfctl_rules(int dev, char *filename, int opts, char *anchorname, pf.opts = opts; pf.loadopt = loadopt; pf.paltq = &pa; + pf.ab = &ab; for (i = 0; i < PF_RULESET_MAX; i++) { pf.prule[i] = &pr[i]; } diff --git a/sbin/pfctl/pfctl.h b/sbin/pfctl/pfctl.h index 64116781700..3e4cbc1f202 100644 --- a/sbin/pfctl/pfctl.h +++ b/sbin/pfctl/pfctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl.h,v 1.21 2003/06/30 20:02:46 cedric Exp $ */ +/* $OpenBSD: pfctl.h,v 1.22 2003/07/03 09:13:06 cedric Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -38,7 +38,7 @@ struct pfr_buffer { int pfrb_type; /* type of content, see enum above */ int pfrb_size; /* number of objects in buffer */ int pfrb_msize; /* maximum number of objects in buffer */ - caddr_t pfrb_caddr; /* malloc'ated memory area */ + void *pfrb_caddr; /* malloc'ated memory area */ }; #define PFRB_FOREACH(var, buf) \ for((var) = pfr_buf_next((buf), NULL); \ @@ -71,7 +71,8 @@ void pfr_buf_clear(struct pfr_buffer *); int pfr_buf_add(struct pfr_buffer *, const void *); void *pfr_buf_next(struct pfr_buffer *, const void *); int pfr_buf_grow(struct pfr_buffer *, int); -void pfr_buf_load(char *, int, void (*)(char *, int)); +int pfr_buf_load(struct pfr_buffer *, char *, int, + int (*)(struct pfr_buffer *, char *, int)); char *pfr_strerror(int); int pfctl_clear_tables(const char *, const char *, int); diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index 78553943946..707ff7de860 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.c,v 1.164 2003/06/12 09:40:33 henning Exp $ */ +/* $OpenBSD: pfctl_parser.c,v 1.165 2003/07/03 09:13:06 cedric Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -1170,3 +1170,71 @@ host_dns(const char *s, int v4mask, int v6mask) return (h); } + +/* + * convert a hostname to a list of addresses and put them in the given buffer. + * test: + * if set to 1, only simple addresses are accepted (no netblock, no "!"). + */ +int +append_addr(struct pfr_buffer *b, char *s, int test) +{ + return append_addr_not(b, s, test, 0); +} + +/* + * same as previous function, but with the ability to "negate" the result. + * not: + * setting it to 1 is equivalent to adding "!" in front of parameter s. + */ +int +append_addr_not(struct pfr_buffer *b, char *s, int test, int not) +{ + char buf[256], *r; + int bits; + struct node_host *n, *h; + struct pfr_addr addr; + + for (r = s; *r == '!'; r++) + not = !not; + if (strlcpy(buf, r, sizeof(buf)) >= sizeof(buf)) { + errno = EINVAL; + return (-1); + } + if ((n = host(buf)) == NULL) { + errno = 0; + return (-1); + } + do { + bzero(&addr, sizeof(addr)); + addr.pfra_not = not; + addr.pfra_af = n->af; + addr.pfra_net = unmask(&n->addr.v.a.mask, n->af); + switch (n->af) { + case AF_INET: + addr.pfra_ip4addr.s_addr = n->addr.v.a.addr.addr32[0]; + bits = 32; + break; + case AF_INET6: + memcpy(&addr.pfra_ip6addr, &n->addr.v.a.addr.v6, + sizeof(struct in6_addr)); + bits = 128; + break; + default: + errno = EINVAL; + return (-1); + } + if ((test && (not || addr.pfra_net != bits)) || + addr.pfra_net > bits) { + errno = EINVAL; + return (-1); + } + if (pfr_buf_add(b, &addr)) + return (-1); + h = n; + n = n->next; + free(h); + } while (n != NULL); + + return (0); +} diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h index 6754df4e023..faea7e1ccbc 100644 --- a/sbin/pfctl/pfctl_parser.h +++ b/sbin/pfctl/pfctl_parser.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.h,v 1.61 2003/05/19 20:21:53 henning Exp $ */ +/* $OpenBSD: pfctl_parser.h,v 1.62 2003/07/03 09:13:06 cedric Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -65,6 +65,7 @@ struct pfctl { struct pfioc_rule *prule[PF_RULESET_MAX]; struct pfioc_altq *paltq; struct pfioc_queue *pqueue; + struct pfr_buffer *ab; /* address buffer */ const char *anchor; const char *ruleset; }; @@ -154,9 +155,8 @@ void print_queue(const struct pf_altq *, unsigned, struct node_queue_bw *, int, struct node_queue_opt *); void pfctl_begin_table(void); -void pfctl_append_addr(char *, int, int); -void pfctl_append_file(char *); -void pfctl_define_table(char *, int, int, int, const char *, const char *); +int pfctl_define_table(char *, int, int, int, const char *, const char *, + struct pfr_buffer *); void pfctl_commit_table(void); struct icmptypeent { @@ -196,4 +196,7 @@ struct node_host *ifa_exists(const char *); struct node_host *ifa_lookup(const char *, enum pfctl_iflookup_mode); struct node_host *host(const char *); +int append_addr(struct pfr_buffer *, char *, int); +int append_addr_not(struct pfr_buffer *, char *, int, int); + #endif /* _PFCTL_PARSER_H_ */ diff --git a/sbin/pfctl/pfctl_radix.c b/sbin/pfctl/pfctl_radix.c index 15bf44d7426..64a2fc187f8 100644 --- a/sbin/pfctl/pfctl_radix.c +++ b/sbin/pfctl/pfctl_radix.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_radix.c,v 1.16 2003/06/30 20:02:46 cedric Exp $ */ +/* $OpenBSD: pfctl_radix.c,v 1.17 2003/07/03 09:13:06 cedric Exp $ */ /* * Copyright (c) 2002 Cedric Berger @@ -473,7 +473,7 @@ pfr_buf_add(struct pfr_buffer *b, const void *e) if (b->pfrb_size == b->pfrb_msize) if (pfr_buf_grow(b, 0)) return (-1); - memcpy(b->pfrb_caddr + bs * b->pfrb_size, e, bs); + memcpy(((caddr_t)b->pfrb_caddr) + bs * b->pfrb_size, e, bs); b->pfrb_size++; return (0); } @@ -494,7 +494,7 @@ pfr_buf_next(struct pfr_buffer *b, const void *prev) if (prev == NULL) return (b->pfrb_caddr); bs = buf_esize[b->pfrb_type]; - if ((((caddr_t)prev) - b->pfrb_caddr) / bs >= b->pfrb_size - 1) + if ((((caddr_t)prev)-((caddr_t)b->pfrb_caddr)) / bs >= b->pfrb_size-1) return (NULL); return (((caddr_t)prev) + bs); } @@ -538,7 +538,8 @@ pfr_buf_grow(struct pfr_buffer *b, int minsize) b->pfrb_caddr = realloc(b->pfrb_caddr, b->pfrb_msize * bs); if (b->pfrb_caddr == NULL) return (-1); - bzero(b->pfrb_caddr + omsize * bs, (b->pfrb_msize-omsize) * bs); + bzero(((caddr_t)b->pfrb_caddr) + omsize * bs, + (b->pfrb_msize-omsize) * bs); } return (0); } @@ -557,25 +558,31 @@ pfr_buf_clear(struct pfr_buffer *b) b->pfrb_size = b->pfrb_msize = 0; } -void -pfr_buf_load(char *file, int nonetwork, void (*append_addr)(char *, int)) +int +pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork, + int (*append_addr)(struct pfr_buffer *, char *, int)) { FILE *fp; char buf[BUF_SIZE]; + int rv; if (file == NULL) - return; + return (0); if (!strcmp(file, "-")) fp = stdin; else { fp = fopen(file, "r"); if (fp == NULL) - err(1, "%s", file); + return (-1); } - while (pfr_next_token(buf, fp)) - append_addr(buf, nonetwork); + while ((rv = pfr_next_token(buf, fp)) == 1) + if (append_addr(b, buf, nonetwork)) { + rv = -1; + break; + } if (fp != stdin) fclose(fp); + return (rv); } int @@ -607,8 +614,10 @@ pfr_next_token(char buf[BUF_SIZE], FILE *fp) buf[i++] = next_ch; next_ch = fgetc(fp); } while (!feof(fp) && !isspace(next_ch)); - if (i >= BUF_SIZE) - errx(1, "address too long (%d bytes)", i); + if (i >= BUF_SIZE) { + errno = EINVAL; + return (-1); + } buf[i] = '\0'; return (1); } diff --git a/sbin/pfctl/pfctl_table.c b/sbin/pfctl/pfctl_table.c index 0d5167b1f74..afd45a8c090 100644 --- a/sbin/pfctl/pfctl_table.c +++ b/sbin/pfctl/pfctl_table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_table.c,v 1.45 2003/06/29 12:22:39 dhartmei Exp $ */ +/* $OpenBSD: pfctl_table.c,v 1.46 2003/07/03 09:13:06 cedric Exp $ */ /* * Copyright (c) 2002 Cedric Berger @@ -51,31 +51,19 @@ #include "pfctl_parser.h" #include "pfctl.h" -#define BUF_SIZE 256 - extern void usage(void); static int pfctl_table(int, char *[], char *, const char *, char *, const char *, const char *, int); -static void grow_buffer(size_t, int); static void print_table(struct pfr_table *, int, int); static void print_tstats(struct pfr_tstats *, int); -static void load_addr(int, char *[], char *, int); -static void append_addr(char *, int); +static int load_addr(struct pfr_buffer *, int, char *[], char *, int); static void print_addrx(struct pfr_addr *, struct pfr_addr *, int); static void print_astats(struct pfr_astats *, int); static void radix_perror(void); static void inactive_cleanup(void); static void xprintf(int, const char *, ...); -static union { - caddr_t caddr; - struct pfr_table *tables; - struct pfr_addr *addrs; - struct pfr_tstats *tstats; - struct pfr_astats *astats; -} buffer, buffer2; - -static int size, msize, ticket, inactive; +static int ticket, inactive; extern char *__progname; static const char *stats_text[PFR_DIR_MAX][PFR_OP_TABLE_MAX] = { @@ -88,7 +76,7 @@ static const char *stats_text[PFR_DIR_MAX][PFR_OP_TABLE_MAX] = { (opts & PF_OPT_DUMMYACTION)) && \ (fct)) { \ radix_perror(); \ - return (1); \ + goto _error; \ } \ } while (0) @@ -131,13 +119,19 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command, char *file, const char *anchor, const char *ruleset, int opts) { struct pfr_table table; + struct pfr_buffer b, b2; + struct pfr_addr *a, *a2; int nadd = 0, ndel = 0, nchange = 0, nzero = 0; - int i, flags = 0, nmatch = 0; + int rv = 0, flags = 0, nmatch = 0; + void *p; if (command == NULL) usage(); if (opts & PF_OPT_NOACTION) flags |= PFR_FLAG_DUMMY; + + bzero(&b, sizeof(b)); + bzero(&b2, sizeof(b2)); bzero(&table, sizeof(table)); if (tname != NULL) { if (strlen(tname) >= PF_TABLE_NAME_SIZE) @@ -151,36 +145,34 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command, strlcpy(table.pfrt_ruleset, ruleset, sizeof(table.pfrt_ruleset)) >= sizeof(table.pfrt_ruleset)) errx(1, "pfctl_table: strlcpy"); + if (!strcmp(command, "-F")) { if (argc || file != NULL) usage(); RVTEST(pfr_clr_tables(&table, &ndel, flags)); xprintf(opts, "%d tables deleted", ndel); } else if (!strcmp(command, "-s")) { + b.pfrb_type = (opts & PF_OPT_VERBOSE2) ? + PFRB_TSTATS : PFRB_TABLES; if (argc || file != NULL) usage(); for (;;) { - if (opts & PF_OPT_VERBOSE2) { - grow_buffer(sizeof(struct pfr_tstats), size); - size = msize; - RVTEST(pfr_get_tstats(&table, buffer.tstats, - &size, flags)); - } else { - grow_buffer(sizeof(struct pfr_table), size); - size = msize; - RVTEST(pfr_get_tables(&table, buffer.tables, - &size, flags)); - } - if (size <= msize) + pfr_buf_grow(&b, b.pfrb_size); + b.pfrb_size = b.pfrb_msize; + if (opts & PF_OPT_VERBOSE2) + RVTEST(pfr_get_tstats(&table, + b.pfrb_caddr, &b.pfrb_size, flags)); + else + RVTEST(pfr_get_tables(&table, + b.pfrb_caddr, &b.pfrb_size, flags)); + if (b.pfrb_size <= b.pfrb_msize) break; } - for (i = 0; i < size; i++) + PFRB_FOREACH(p, &b) if (opts & PF_OPT_VERBOSE2) - print_tstats(buffer.tstats+i, - opts & PF_OPT_DEBUG); + print_tstats(p, opts & PF_OPT_DEBUG); else - print_table(buffer.tables+i, - opts & PF_OPT_VERBOSE, + print_table(p, opts & PF_OPT_VERBOSE, opts & PF_OPT_DEBUG); } else if (!strcmp(command, "kill")) { if (argc || file != NULL) @@ -193,47 +185,51 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command, RVTEST(pfr_clr_addrs(&table, &ndel, flags)); xprintf(opts, "%d addresses deleted", ndel); } else if (!strcmp(command, "add")) { - load_addr(argc, argv, file, 0); + b.pfrb_type = PFRB_ADDRS; + if (load_addr(&b, argc, argv, file, 0)) + goto _error; CREATE_TABLE; if (opts & PF_OPT_VERBOSE) flags |= PFR_FLAG_FEEDBACK; - RVTEST(pfr_add_addrs(&table, buffer.addrs, size, &nadd, - flags)); - xprintf(opts, "%d/%d addresses added", nadd, size); + RVTEST(pfr_add_addrs(&table, b.pfrb_caddr, b.pfrb_size, + &nadd, flags)); + xprintf(opts, "%d/%d addresses added", nadd, b.pfrb_size); if (opts & PF_OPT_VERBOSE) - for (i = 0; i < size; i++) - if ((opts & PF_OPT_VERBOSE2) || - buffer.addrs[i].pfra_fback) - print_addrx(buffer.addrs+i, NULL, + PFRB_FOREACH(a, &b) + if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback) + print_addrx(a, NULL, opts & PF_OPT_USEDNS); } else if (!strcmp(command, "delete")) { - load_addr(argc, argv, file, 0); + b.pfrb_type = PFRB_ADDRS; + if (load_addr(&b, argc, argv, file, 0)) + goto _error; if (opts & PF_OPT_VERBOSE) flags |= PFR_FLAG_FEEDBACK; - RVTEST(pfr_del_addrs(&table, buffer.addrs, size, &nadd, - flags)); - xprintf(opts, "%d/%d addresses deleted", nadd, size); + RVTEST(pfr_del_addrs(&table, b.pfrb_caddr, b.pfrb_size, + &ndel, flags)); + xprintf(opts, "%d/%d addresses deleted", ndel, b.pfrb_size); if (opts & PF_OPT_VERBOSE) - for (i = 0; i < size; i++) - if ((opts & PF_OPT_VERBOSE2) || - buffer.addrs[i].pfra_fback) - print_addrx(buffer.addrs+i, NULL, + PFRB_FOREACH(a, &b) + if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback) + print_addrx(a, NULL, opts & PF_OPT_USEDNS); } else if (!strcmp(command, "replace")) { - load_addr(argc, argv, file, 0); + b.pfrb_type = PFRB_ADDRS; + if (load_addr(&b, argc, argv, file, 0)) + goto _error; CREATE_TABLE; if (opts & PF_OPT_VERBOSE) flags |= PFR_FLAG_FEEDBACK; for (;;) { - int size2 = msize; + int sz2 = b.pfrb_msize; - RVTEST(pfr_set_addrs(&table, buffer.addrs, size, - &size2, &nadd, &ndel, &nchange, flags)); - if (size2 <= msize) { - size = size2; + RVTEST(pfr_set_addrs(&table, b.pfrb_caddr, b.pfrb_size, + &sz2, &nadd, &ndel, &nchange, flags)); + if (sz2 <= b.pfrb_msize) { + b.pfrb_size = sz2; break; } else - grow_buffer(sizeof(struct pfr_addr), size2); + pfr_buf_grow(&b, sz2); } if (nadd) xprintf(opts, "%d addresses added", nadd); @@ -244,63 +240,61 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command, if (!nadd && !ndel && !nchange) xprintf(opts, "no changes"); if (opts & PF_OPT_VERBOSE) - for (i = 0; i < size; i++) - if ((opts & PF_OPT_VERBOSE2) || - buffer.addrs[i].pfra_fback) - print_addrx(buffer.addrs+i, NULL, + PFRB_FOREACH(a, &b) + if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback) + print_addrx(a, NULL, opts & PF_OPT_USEDNS); } else if (!strcmp(command, "show")) { + b.pfrb_type = (opts & PF_OPT_VERBOSE) ? + PFRB_ASTATS : PFRB_ADDRS; if (argc || file != NULL) usage(); for (;;) { - if (opts & PF_OPT_VERBOSE) { - grow_buffer(sizeof(struct pfr_astats), size); - size = msize; - RVTEST(pfr_get_astats(&table, buffer.astats, - &size, flags)); - } else { - grow_buffer(sizeof(struct pfr_addr), size); - size = msize; - RVTEST(pfr_get_addrs(&table, buffer.addrs, - &size, flags)); - } - if (size <= msize) + pfr_buf_grow(&b, b.pfrb_size); + b.pfrb_size = b.pfrb_msize; + if (opts & PF_OPT_VERBOSE) + RVTEST(pfr_get_astats(&table, b.pfrb_caddr, + &b.pfrb_size, flags)); + else + RVTEST(pfr_get_addrs(&table, b.pfrb_caddr, + &b.pfrb_size, flags)); + if (b.pfrb_size <= b.pfrb_msize) break; } - for (i = 0; i < size; i++) - if (opts & PF_OPT_VERBOSE) { - print_astats(buffer.astats+i, - opts & PF_OPT_USEDNS); - } else { - print_addrx(buffer.addrs+i, NULL, - opts & PF_OPT_USEDNS); - } + PFRB_FOREACH(p, &b) + if (opts & PF_OPT_VERBOSE) + print_astats(p, opts & PF_OPT_USEDNS); + else + print_addrx(p, NULL, opts & PF_OPT_USEDNS); } else if (!strcmp(command, "test")) { - load_addr(argc, argv, file, 1); + b.pfrb_type = PFRB_ADDRS; + b2.pfrb_type = PFRB_ADDRS; + + if (load_addr(&b, argc, argv, file, 1)) + goto _error; if (opts & PF_OPT_VERBOSE2) { flags |= PFR_FLAG_REPLACE; - buffer2.caddr = calloc(sizeof(buffer.addrs[0]), size); - if (buffer2.caddr == NULL) - err(1, "calloc"); - memcpy(buffer2.addrs, buffer.addrs, size * - sizeof(buffer.addrs[0])); + PFRB_FOREACH(a, &b) + if (pfr_buf_add(&b2, a)) + err(1, "duplicate buffer"); } - RVTEST(pfr_tst_addrs(&table, buffer.addrs, size, &nmatch, - flags)); - xprintf(opts, "%d/%d addresses match", nmatch, size); + RVTEST(pfr_tst_addrs(&table, b.pfrb_caddr, b.pfrb_size, + &nmatch, flags)); + xprintf(opts, "%d/%d addresses match", nmatch, b.pfrb_size); if (opts & PF_OPT_VERBOSE && !(opts & PF_OPT_VERBOSE2)) - for (i = 0; i < size; i++) - if (buffer.addrs[i].pfra_fback == PFR_FB_MATCH) - print_addrx(buffer.addrs+i, NULL, + PFRB_FOREACH(a, &b) + if (a->pfra_fback == PFR_FB_MATCH) + print_addrx(a, NULL, opts & PF_OPT_USEDNS); if (opts & PF_OPT_VERBOSE2) { - for (i = 0; i < size; i++) - print_addrx(buffer2.addrs+i, buffer.addrs+i, - opts & PF_OPT_USEDNS); - free(buffer2.addrs); + a2 = NULL; + PFRB_FOREACH(a, &b) { + a2 = pfr_buf_next(&b2, a2); + print_addrx(a2, a, opts & PF_OPT_USEDNS); + } } - if (nmatch < size) - return (2); + if (nmatch < b.pfrb_size) + rv = 2; } else if (!strcmp(command, "zero")) { if (argc || file != NULL) usage(); @@ -309,39 +303,14 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command, xprintf(opts, "%d table/stats cleared", nzero); } else warnx("pfctl_table: unknown command '%s'", command); - if (buffer.caddr) - free(buffer.caddr); - size = msize = 0; - return (0); -} - -void -grow_buffer(size_t bs, int minsize) -{ - if (minsize != 0 && minsize <= msize) { - warnx("grow_buffer: superfluous call"); - return; - } - if (!msize) { - msize = minsize; - if (msize < 64) - msize = 64; - buffer.caddr = calloc(bs, msize); - if (buffer.caddr == NULL) - err(1, "calloc"); - } else { - int omsize = msize; - if (minsize == 0) - msize *= 2; - else - msize = minsize; - if (msize < 0 || msize >= SIZE_T_MAX / bs) - errx(1, "msize overflow"); - buffer.caddr = realloc(buffer.caddr, msize * bs); - if (buffer.caddr == NULL) - err(1, "realloc"); - bzero(buffer.caddr + omsize * bs, (msize-omsize) * bs); - } + goto _cleanup; + +_error: + rv = -1; +_cleanup: + pfr_buf_clear(&b); + pfr_buf_clear(&b2); + return (rv); } void @@ -391,73 +360,27 @@ print_tstats(struct pfr_tstats *ts, int debug) ts->pfrts_bytes[dir][op]); } -void -load_addr(int argc, char *argv[], char *file, int nonetwork) +int +load_addr(struct pfr_buffer *b, int argc, char *argv[], char *file, + int nonetwork) { while (argc--) - append_addr(*argv++, nonetwork); - pfr_buf_load(file, nonetwork, append_addr); -} - -void -append_addr(char *s, int test) -{ - char buf[BUF_SIZE], *r; - int not = 0; - struct node_host *n, *h; - - for (r = s; *r == '!'; r++) - not = !not; - if (strlcpy(buf, r, sizeof(buf)) >= sizeof(buf)) - errx(1, "address too long"); - - if ((n = host(buf)) == NULL) - exit (1); - - do { - if (size >= msize) - grow_buffer(sizeof(struct pfr_addr), 0); - buffer.addrs[size].pfra_not = not; - switch (n->af) { - case AF_INET: - buffer.addrs[size].pfra_af = AF_INET; - buffer.addrs[size].pfra_ip4addr.s_addr = - n->addr.v.a.addr.addr32[0]; - buffer.addrs[size].pfra_net = - unmask(&n->addr.v.a.mask, AF_INET); - if (test && (not || buffer.addrs[size].pfra_net != 32)) - errx(1, "illegal test address"); - if (buffer.addrs[size].pfra_net > 32) - errx(1, "illegal netmask %d", - buffer.addrs[size].pfra_net); - break; - case AF_INET6: - buffer.addrs[size].pfra_af = AF_INET6; - memcpy(&buffer.addrs[size].pfra_ip6addr, - &n->addr.v.a.addr.v6, sizeof(struct in6_addr)); - buffer.addrs[size].pfra_net = - unmask(&n->addr.v.a.mask, AF_INET6); - if (test && (not || buffer.addrs[size].pfra_net != 128)) - errx(1, "illegal test address"); - if (buffer.addrs[size].pfra_net > 128) - errx(1, "illegal netmask %d", - buffer.addrs[size].pfra_net); - break; - default: - errx(1, "unknown address family %d", n->af); - break; + if (append_addr(b, *argv++, nonetwork)) { + if (errno) + warn("cannot decode %s", argv[-1]); + return (-1); } - size++; - h = n; - n = n->next; - free(h); - } while (n != NULL); + if (pfr_buf_load(b, file, nonetwork, append_addr)) { + warn("cannot load %s", file); + return (-1); + } + return (0); } void print_addrx(struct pfr_addr *ad, struct pfr_addr *rad, int dns) { - char ch, buf[BUF_SIZE] = "{error}"; + char ch, buf[256] = "{error}"; char fb[] = { ' ', 'M', 'A', 'D', 'C', 'Z', 'X', ' ', 'Y' }; unsigned int fback, hostnet; @@ -536,41 +459,12 @@ pfctl_begin_table(void) } } -void -pfctl_append_addr(char *addr, int net, int neg) -{ - char *p = NULL; - int rval; - - if (net < 0 && !neg) { - append_addr(addr, 0); - return; - } - if (net >= 0 && !neg) - rval = asprintf(&p, "%s/%d", addr, net); - else if (net < 0) - rval = asprintf(&p, "!%s", addr); - else - rval = asprintf(&p, "!%s/%d", addr, net); - if (rval == -1 || p == NULL) { - radix_perror(); - exit(1); - } - append_addr(p, 0); - free(p); -} - -void -pfctl_append_file(char *file) -{ - load_addr(0, NULL, file, 0); -} - -void +int pfctl_define_table(char *name, int flags, int addrs, int noaction, - const char *anchor, const char *ruleset) + const char *anchor, const char *ruleset, struct pfr_buffer *ab) { struct pfr_table tbl; + int rv = 0; if (!noaction) { bzero(&tbl, sizeof(tbl)); @@ -584,14 +478,13 @@ pfctl_define_table(char *name, int flags, int addrs, int noaction, tbl.pfrt_flags = flags; inactive = 1; - if (pfr_ina_define(&tbl, buffer.addrs, size, NULL, NULL, - ticket, addrs ? PFR_FLAG_ADDRSTOO : 0) != 0) { - radix_perror(); - exit(1); + if (pfr_ina_define(&tbl, ab->pfrb_caddr, ab->pfrb_size, NULL, + NULL, ticket, addrs ? PFR_FLAG_ADDRSTOO : 0) != 0) { + rv = -1; } } - bzero(buffer.addrs, size * sizeof(buffer.addrs[0])); - size = 0; + pfr_buf_clear(ab); + return (rv); } void |