diff options
Diffstat (limited to 'sbin/pfctl/pfctl_table.c')
-rw-r--r-- | sbin/pfctl/pfctl_table.c | 351 |
1 files changed, 122 insertions, 229 deletions
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 |