Module Name: src Committed By: rmind Date: Wed May 30 21:30:07 UTC 2012
Modified Files: src/usr.sbin/npf/npfctl: Makefile npf.conf.5 npf_data.c npf_disassemble.c npf_ncgen.c npf_parse.y npf_scan.l npf_var.c npfctl.c npfctl.h Log Message: npfctl(8): add show-config command. Also, update syntax. To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.7 src/usr.sbin/npf/npfctl/Makefile \ src/usr.sbin/npf/npfctl/npf_parse.y cvs rdiff -u -r1.9 -r1.10 src/usr.sbin/npf/npfctl/npf.conf.5 cvs rdiff -u -r1.11 -r1.12 src/usr.sbin/npf/npfctl/npf_data.c cvs rdiff -u -r1.3 -r1.4 src/usr.sbin/npf/npfctl/npf_disassemble.c cvs rdiff -u -r1.8 -r1.9 src/usr.sbin/npf/npfctl/npf_ncgen.c cvs rdiff -u -r1.1 -r1.2 src/usr.sbin/npf/npfctl/npf_scan.l cvs rdiff -u -r1.4 -r1.5 src/usr.sbin/npf/npfctl/npf_var.c cvs rdiff -u -r1.10 -r1.11 src/usr.sbin/npf/npfctl/npfctl.c cvs rdiff -u -r1.13 -r1.14 src/usr.sbin/npf/npfctl/npfctl.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.sbin/npf/npfctl/Makefile diff -u src/usr.sbin/npf/npfctl/Makefile:1.6 src/usr.sbin/npf/npfctl/Makefile:1.7 --- src/usr.sbin/npf/npfctl/Makefile:1.6 Sat Mar 10 22:21:50 2012 +++ src/usr.sbin/npf/npfctl/Makefile Wed May 30 21:30:07 2012 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.6 2012/03/10 22:21:50 christos Exp $ +# $NetBSD: Makefile,v 1.7 2012/05/30 21:30:07 rmind Exp $ PROG= npfctl MAN= npfctl.8 npf.conf.5 @@ -9,7 +9,6 @@ SRCS= npfctl.c npf_var.c npf_data.c npf CPPFLAGS+= -I${.CURDIR} SRCS+= npf_scan.l npf_parse.y YHEADER= 1 -YFLAGS+= -v LDADD+= -lnpf -lprop -lutil -ly DPADD+= ${LIBNPF} ${LIBPROP} ${LIBUTIL} Index: src/usr.sbin/npf/npfctl/npf_parse.y diff -u src/usr.sbin/npf/npfctl/npf_parse.y:1.6 src/usr.sbin/npf/npfctl/npf_parse.y:1.7 --- src/usr.sbin/npf/npfctl/npf_parse.y:1.6 Sun Feb 26 22:04:42 2012 +++ src/usr.sbin/npf/npfctl/npf_parse.y Wed May 30 21:30:07 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_parse.y,v 1.6 2012/02/26 22:04:42 christos Exp $ */ +/* $NetBSD: npf_parse.y,v 1.7 2012/05/30 21:30:07 rmind Exp $ */ /*- * Copyright (c) 2011-2012 The NetBSD Foundation, Inc. @@ -95,7 +95,6 @@ yyerror(const char *fmt, ...) %token INET %token INET6 %token INTERFACE -%token KEEP %token MINUS %token NAT %token NAME @@ -108,14 +107,14 @@ yyerror(const char *fmt, ...) %token PROCEDURE %token PROTO %token FAMILY -%token QUICK +%token FINAL %token RDR %token RETURN %token RETURNICMP %token RETURNRST %token SEPLINE %token SLASH -%token STATE +%token STATEFUL %token TABLE %token TCP %token TO @@ -135,9 +134,9 @@ yyerror(const char *fmt, ...) %type <str> addr, iface_name, moduleargname, list_elem, table_store %type <str> opt_apply -%type <num> ifindex, port, opt_quick, on_iface +%type <num> ifindex, port, opt_final, on_iface %type <num> block_or_pass, rule_dir, block_opts, family, opt_family -%type <num> opt_keep_state, icmp_type, table_type +%type <num> opt_stateful, icmp_type, table_type %type <var> addr_or_iface, port_range, icmp_type_and_code %type <var> filt_addr, addr_and_mask, tcp_flags, tcp_flags_and_mask %type <var> modulearg_opts, procs, proc_op, modulearg, moduleargs @@ -421,15 +420,15 @@ rules ; rule - : block_or_pass rule_dir opt_quick on_iface opt_family - opt_proto all_or_filt_opts opt_keep_state opt_apply + : block_or_pass opt_stateful rule_dir opt_final on_iface opt_family + opt_proto all_or_filt_opts opt_apply { /* * Arguments: attributes, interface index, address * family, protocol options, filter options. */ - npfctl_build_rule($1 | $2 | $3 | $8, $4, - $5, &$6, &$7, $9); + npfctl_build_rule($1 | $2 | $3 | $4, $5, + $6, &$7, &$8, $9); } | ; @@ -445,8 +444,8 @@ rule_dir | { $$ = NPF_RULE_IN | NPF_RULE_OUT; } ; -opt_quick - : QUICK { $$ = NPF_RULE_FINAL; } +opt_final + : FINAL { $$ = NPF_RULE_FINAL; } | { $$ = 0; } ; @@ -499,8 +498,8 @@ all_or_filt_opts | filt_opts { $$ = $1; } ; -opt_keep_state - : KEEP STATE { $$ = NPF_RULE_KEEPSTATE; } +opt_stateful + : STATEFUL { $$ = NPF_RULE_KEEPSTATE; } | { $$ = 0; } ; @@ -621,7 +620,7 @@ port_range ; port - : NUM { $$ = htons($1); } + : NUM { $$ = $1; } | IDENTIFIER { $$ = npfctl_portno($1); } ; Index: src/usr.sbin/npf/npfctl/npf.conf.5 diff -u src/usr.sbin/npf/npfctl/npf.conf.5:1.9 src/usr.sbin/npf/npfctl/npf.conf.5:1.10 --- src/usr.sbin/npf/npfctl/npf.conf.5:1.9 Mon Feb 6 00:41:36 2012 +++ src/usr.sbin/npf/npfctl/npf.conf.5 Wed May 30 21:30:07 2012 @@ -1,4 +1,4 @@ -.\" $NetBSD: npf.conf.5,v 1.9 2012/02/06 00:41:36 rmind Exp $ +.\" $NetBSD: npf.conf.5,v 1.10 2012/05/30 21:30:07 rmind Exp $ .\" .\" Copyright (c) 2009-2012 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd February 5, 2012 +.Dd May 27, 2012 .Dt NPF.CONF 5 .Os .Sh NAME @@ -64,13 +64,13 @@ Each rule has a priority, which is set a Rules defined first are accordingly inspected first. All rules in the group are inspected sequentially, and the last matching dictates the action to be taken. -Rules, however, may be explicitly marked as final (that is, "quick"). +Rules, however, may be explicitly marked as final. In such cases, processing stops after encountering the first matching rule marked as final. If there is no matching rule in the custom group, then rules in the default group will be inspected. .Pp -Stateful filtering is supported using the "keep state" keyword. +Stateful filtering is supported using the "stateful" keyword. In such cases, state (a session) is created and any further packets of the connection are tracked. Packets in backwards stream, after having been confirmed to belong to @@ -155,9 +155,9 @@ group-opts = "interface" iface "," [ "in ruleset = "{" rule1 \*[Lt]newline\*[Gt], rule2 \*[Lt]newline\*[Gt], ... "}" -rule = ( "block" block-opts | "pass" ) [ "in" | out" ] [ "quick" ] +rule = ( "block" block-opts | "pass" ) [ "stateful" ] [ "in" | out" ] [ "final" ] [ "on" iface ] [ "family" fam-opt ] [ "proto" \*[Lt]protocol\*[Gt] ] - ( "all" | filt-opts ) [ "keep state" ] [ "apply" rproc ] } + ( "all" | filt-opts ) [ "apply" rproc ] } fam-opt = [ "inet" | "inet6" ] block-opts = [ "return-rst" | "return-icmp" | "return" ] @@ -197,20 +197,20 @@ procedure "rid" { } group (name "external", interface $ext_if) { - block in quick from \*[Lt]1\*[Gt] - pass out quick from $ext_if keep state apply "rid" + block in final from \*[Lt]1\*[Gt] + pass stateful out final from $ext_if apply "rid" - pass in quick family inet proto tcp to $ext_if port ssh apply "log" - pass in quick proto tcp to $ext_if port $services_tcp - pass in quick proto udp to $ext_if port $services_udp - pass in quick proto tcp to $ext_if port 49151-65535 # Passive FTP - pass in quick proto udp to $ext_if port 33434-33600 # Traceroute + pass in final family inet proto tcp to $ext_if port ssh apply "log" + pass in final proto tcp to $ext_if port $services_tcp + pass in final proto udp to $ext_if port $services_udp + pass in final proto tcp to $ext_if port 49151-65535 # Passive FTP + pass in final proto udp to $ext_if port 33434-33600 # Traceroute } group (name "internal", interface $int_if) { block in all - pass in quick from \*[Lt]2\*[Gt] - pass out quick all + pass in final from \*[Lt]2\*[Gt] + pass out final all } group (default) { Index: src/usr.sbin/npf/npfctl/npf_data.c diff -u src/usr.sbin/npf/npfctl/npf_data.c:1.11 src/usr.sbin/npf/npfctl/npf_data.c:1.12 --- src/usr.sbin/npf/npfctl/npf_data.c:1.11 Sun Feb 26 21:50:05 2012 +++ src/usr.sbin/npf/npfctl/npf_data.c Wed May 30 21:30:07 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_data.c,v 1.11 2012/02/26 21:50:05 christos Exp $ */ +/* $NetBSD: npf_data.c,v 1.12 2012/05/30 21:30:07 rmind Exp $ */ /*- * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: npf_data.c,v 1.11 2012/02/26 21:50:05 christos Exp $"); +__RCSID("$NetBSD: npf_data.c,v 1.12 2012/05/30 21:30:07 rmind Exp $"); #include <sys/types.h> #include <sys/null.h> @@ -211,7 +211,7 @@ out: /* * npfctl_parse_port_range: create a port-range variable. Note that the - * passed port numbers are in network byte order. + * passed port numbers should be in host byte order. */ npfvar_t * npfctl_parse_port_range(in_port_t s, in_port_t e) @@ -219,8 +219,8 @@ npfctl_parse_port_range(in_port_t s, in_ npfvar_t *vp = npfvar_create(".port_range"); port_range_t pr; - pr.pr_start = s; - pr.pr_end = e; + pr.pr_start = htons(s); + pr.pr_end = htons(e); if (!npfvar_add_element(vp, NPFVAR_PORT_RANGE, &pr, sizeof(pr))) goto out; @@ -235,14 +235,15 @@ npfvar_t * npfctl_parse_port_range_variable(const char *v) { npfvar_t *vp = npfvar_lookup(v); - in_port_t p; - port_range_t *pr; size_t count = npfvar_get_count(vp); npfvar_t *pvp = npfvar_create(".port_range"); + port_range_t *pr; + in_port_t p; for (size_t i = 0; i < count; i++) { int type = npfvar_get_type(vp, i); void *data = npfvar_get_data(vp, type, i); + switch (type) { case NPFVAR_IDENTIFIER: case NPFVAR_STRING: @@ -261,13 +262,11 @@ npfctl_parse_port_range_variable(const c default: yyerror("wrong variable '%s' type '%s' for port range", v, npfvar_type(type)); - goto out; + npfvar_destroy(pvp); + return NULL; } } return pvp; -out: - npfvar_destroy(pvp); - return NULL; } npfvar_t * @@ -350,7 +349,7 @@ npfctl_parse_cidr(char *cidr) /* * npfctl_portno: convert port identifier (string) to a number. * - * => Returns port number in network byte order. + * => Returns port number in host byte order. */ in_port_t npfctl_portno(const char *port) @@ -383,7 +382,7 @@ npfctl_portno(const char *port) } out: freeaddrinfo(rai); - return p; + return ntohs(p); } npfvar_t * Index: src/usr.sbin/npf/npfctl/npf_disassemble.c diff -u src/usr.sbin/npf/npfctl/npf_disassemble.c:1.3 src/usr.sbin/npf/npfctl/npf_disassemble.c:1.4 --- src/usr.sbin/npf/npfctl/npf_disassemble.c:1.3 Mon Mar 12 15:32:02 2012 +++ src/usr.sbin/npf/npfctl/npf_disassemble.c Wed May 30 21:30:07 2012 @@ -36,9 +36,11 @@ __RCSID("$NetBSD$"); #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <errno.h> #include <err.h> #include <sys/socket.h> #include <netinet/in.h> +#include <net/if.h> #include <util.h> @@ -47,6 +49,21 @@ __RCSID("$NetBSD$"); #include "npfctl.h" +enum { + NPF_SHOW_SRCADDR, + NPF_SHOW_DSTADDR, + NPF_SHOW_SRCPORT, + NPF_SHOW_DSTPORT, + NPF_SHOW_ICMP, + NPF_SHOW_TCPF, + NPF_SHOW_COUNT, +}; + +struct nc_inf { + npfvar_t * nci_vlist[NPF_SHOW_COUNT]; + bool nci_srcdst; +}; + #define ADVANCE(n, rv) \ do { \ if (len < sizeof(*pc) * (n)) { \ @@ -84,10 +101,24 @@ npfctl_ncode_add_target(const uint32_t * return q; } +static void +npfctl_ncode_add_vp(char *buf, nc_inf_t *nci, unsigned idx) +{ + npfvar_t *vl = nci->nci_vlist[idx]; + + if (vl == NULL) { + vl = npfvar_create(".list"); + nci->nci_vlist[idx] = vl; + } + npfvar_t *vp = npfvar_create(".string"); + npfvar_add_element(vp, NPFVAR_STRING, buf, strlen(buf) + 1); + npfvar_add_elements(vl, vp); +} + static const char * npfctl_ncode_operand(char *buf, size_t bufsiz, uint8_t op, const uint32_t *st, const uint32_t *ipc, const uint32_t **pcv, size_t *lenv, - const uint32_t ***t, size_t *l, size_t *m) + const uint32_t ***t, size_t *l, size_t *m, nc_inf_t *nci) { const uint32_t *pc = *pcv; size_t len = *lenv; @@ -99,14 +130,14 @@ npfctl_ncode_operand(char *buf, size_t b case NPF_OPERAND_REGISTER: if (*pc & ~0x3) { - warnx("Bad register operand 0x%x at offset %td", + warnx("invalid register operand 0x%x at offset %td", *pc, pc - st); return NULL; } snprintf(buf, bufsiz, "R%d", *pc); ADVANCE(1, NULL); break; - + case NPF_OPERAND_KEY: snprintf(buf, bufsiz, "key=<0x%x>", *pc); ADVANCE(1, NULL); @@ -119,12 +150,15 @@ npfctl_ncode_operand(char *buf, size_t b case NPF_OPERAND_SD: if (*pc & ~0x1) { - warnx("Bad src/dst operand 0x%x at offset %td", + warnx("invalid src/dst operand 0x%x at offset %td", *pc, pc - st); return NULL; } - snprintf(buf, bufsiz, "%s", *pc == NPF_OPERAND_SD_SRC ? - "SRC" : "DST"); + bool srcdst = (*pc == NPF_OPERAND_SD_SRC); + if (nci) { + nci->nci_srcdst = srcdst; + } + snprintf(buf, bufsiz, "%s", srcdst ? "SRC" : "DST"); ADVANCE(1, NULL); break; @@ -140,8 +174,11 @@ npfctl_ncode_operand(char *buf, size_t b sin->sin_family = AF_INET; sin->sin_port = 0; memcpy(&sin->sin_addr, pc, sizeof(sin->sin_addr)); - sockaddr_snprintf(buf, bufsiz, "%a", (struct sockaddr *)(void *) - sin); + sockaddr_snprintf(buf, bufsiz, "%a", (struct sockaddr *)sin); + if (nci) { + npfctl_ncode_add_vp(buf, nci, nci->nci_srcdst ? + NPF_SHOW_SRCADDR : NPF_SHOW_DSTADDR); + } ADVANCE(sizeof(sin->sin_addr) / sizeof(*pc), NULL); break; } @@ -151,8 +188,11 @@ npfctl_ncode_operand(char *buf, size_t b sin6->sin6_family = AF_INET6; sin6->sin6_port = 0; memcpy(&sin6->sin6_addr, pc, sizeof(sin6->sin6_addr)); - sockaddr_snprintf(buf, bufsiz, "%a", (struct sockaddr *)(void *) - sin6); + sockaddr_snprintf(buf, bufsiz, "%a", (struct sockaddr *)sin6); + if (nci) { + npfctl_ncode_add_vp(buf, nci, nci->nci_srcdst ? + NPF_SHOW_SRCADDR : NPF_SHOW_DSTADDR); + } ADVANCE(sizeof(sin6->sin6_addr) / sizeof(*pc), NULL); break; } @@ -161,47 +201,71 @@ npfctl_ncode_operand(char *buf, size_t b ADVANCE(1, NULL); break; - case NPF_OPERAND_SUBNET: + case NPF_OPERAND_SUBNET: { snprintf(buf, bufsiz, "/%d", *pc); + if (nci) { + npfctl_ncode_add_vp(buf, nci, nci->nci_srcdst ? + NPF_SHOW_SRCADDR : NPF_SHOW_DSTADDR); + } ADVANCE(1, NULL); break; - + } case NPF_OPERAND_LENGTH: snprintf(buf, bufsiz, "length=%d", *pc); ADVANCE(1, NULL); break; case NPF_OPERAND_TABLE_ID: + if (nci) { + snprintf(buf, bufsiz, "<%d>", *pc); + npfctl_ncode_add_vp(buf, nci, nci->nci_srcdst ? + NPF_SHOW_SRCADDR : NPF_SHOW_DSTADDR); + } snprintf(buf, bufsiz, "id=%d", *pc); ADVANCE(1, NULL); break; case NPF_OPERAND_ICMP4_TYPE_CODE: if (*pc & ~0xffff) { - warnx("Bad icmp/type operand 0x%x at offset %td", + warnx("invalid icmp/type operand 0x%x at offset %td", *pc, pc - st); return NULL; } - snprintf(buf, bufsiz, "type=%d, code=%d", *pc >> 8, - *pc & 0xff); + snprintf(buf, bufsiz, "type=%d, code=%d", *pc >> 8, *pc & 0xff); + if (nci) { + npfctl_ncode_add_vp(buf, nci, NPF_SHOW_ICMP); + } ADVANCE(1, NULL); break; case NPF_OPERAND_TCP_FLAGS_MASK: if (*pc & ~0xffff) { - warnx("Bad flags/mask operand 0x%x at offset %td", + warnx("invalid flags/mask operand 0x%x at offset %td", *pc, pc - st); return NULL; } - snprintf(buf, bufsiz, "type=%d, code=%d", *pc >> 8, - *pc & 0xff); + snprintf(buf, bufsiz, "type=%d, code=%d", *pc >> 8, *pc & 0xff); + if (nci) { + npfctl_ncode_add_vp(buf, nci, NPF_SHOW_TCPF); + } ADVANCE(1, NULL); break; - case NPF_OPERAND_PORT_RANGE: - snprintf(buf, bufsiz, "%d-%d", (*pc >> 16), *pc & 0xffff); + case NPF_OPERAND_PORT_RANGE: { + in_port_t p1 = ntohs(*pc >> 16), p2 = ntohs(*pc & 0xffff); + + if (p1 == p2) { + snprintf(buf, bufsiz, "%d", p1); + } else { + snprintf(buf, bufsiz, "%d-%d", p1, p2); + } + if (nci) { + npfctl_ncode_add_vp(buf, nci, nci->nci_srcdst ? + NPF_SHOW_SRCPORT : NPF_SHOW_DSTPORT); + } ADVANCE(1, NULL); break; + } default: warnx("invalid operand %d at offset %td", op, pc - st); return NULL; @@ -213,7 +277,7 @@ npfctl_ncode_operand(char *buf, size_t b } int -npfctl_ncode_disassemble(FILE *fp, const void *v, size_t len) +npfctl_ncode_disassemble(FILE *fp, const void *v, size_t len, nc_inf_t *nci) { const uint32_t *ipc, *pc = v; const uint32_t *st = v; @@ -228,7 +292,7 @@ npfctl_ncode_disassemble(FILE *fp, const while (len) { /* Get the opcode */ if (*pc & ~0xff) { - warnx("bad opcode 0x%x at offset (%td)", *pc, + warnx("invalid opcode 0x%x at offset (%td)", *pc, pc - st); goto out; } @@ -238,26 +302,186 @@ npfctl_ncode_disassemble(FILE *fp, const pc - st); goto out; } + ipc = pc; target = npfctl_ncode_get_target(pc, targ, tlen); - if (target != (size_t)~0) - printf("%zu:", target); - fprintf(fp, "\t%s", ni->name); + if (fp) { + if (target != (size_t)~0) + fprintf(fp, "%zu:", target); + fprintf(fp, "\t%s", ni->name); + } ADVANCE(1, -1); + for (size_t i = 0; i < __arraycount(ni->op); i++) { const char *op; if (ni->op[i] == NPF_OPERAND_NONE) break; op = npfctl_ncode_operand(buf, sizeof(buf), ni->op[i], - st, ipc, &pc, &len, &targ, &tlen, &mlen); + st, ipc, &pc, &len, &targ, &tlen, &mlen, nci); if (op == NULL) goto out; - fprintf(fp, "%s%s", i == 0 ? " " : ", ", op); + if (fp) { + fprintf(fp, "%s%s", i == 0 ? " " : ", ", op); + } + } + if (fp) { + fprintf(fp, "\n"); } - fprintf(fp, "\n"); } error = 0; out: free(targ); return error; } + +static void +npfctl_show_fromto(const char *name, npfvar_t *vl, bool showany) +{ + size_t count = npfvar_get_count(vl), last = count - 1; + bool one = (count == 1); + + if (count == 0) { + if (showany) { + printf("%s all ", name); + } + return; + } + printf("%s%s ", name, one ? "" : " {"); + + for (size_t i = 0; i < count; i++) { + char *s = npfvar_get_data(vl, NPFVAR_STRING, i); + printf("%s%s ", s, i == last ? (one ? "" : " }") : ","); + } + npfvar_destroy(vl); +} + +static void +npfctl_show_ncode(const void *nc, size_t len) +{ + nc_inf_t nci; + + memset(&nci, 0, sizeof(nc_inf_t)); + + if (npfctl_ncode_disassemble(NULL, nc, len, (void *)&nci) == 0) { + npfctl_show_fromto("from", nci.nci_vlist[NPF_SHOW_SRCADDR], true); + npfctl_show_fromto("port", nci.nci_vlist[NPF_SHOW_SRCPORT], false); + npfctl_show_fromto("to", nci.nci_vlist[NPF_SHOW_DSTADDR], true); + npfctl_show_fromto("port", nci.nci_vlist[NPF_SHOW_DSTPORT], false); + } else { + printf("<< ncode >> "); + } +} + +#define NPF_RSTICMP (NPF_RULE_RETRST | NPF_RULE_RETICMP) + +static const struct attr_keyword_mapent { + uint32_t mask; + uint32_t flags; + const char * onmatch; + const char * nomatch; +} attr_keyword_map[] = { + { NPF_RULE_PASS, NPF_RULE_PASS, "pass", "block" }, + { NPF_RSTICMP, NPF_RSTICMP, "return", NULL }, + { NPF_RSTICMP, NPF_RULE_RETRST,"return-rst", NULL }, + { NPF_RSTICMP, NPF_RULE_RETICMP,"return-icmp", NULL }, + { NPF_RULE_KEEPSTATE, NPF_RULE_KEEPSTATE,"stateful", NULL }, + { NPF_RULE_DIMASK, NPF_RULE_IN, "in", NULL }, + { NPF_RULE_DIMASK, NPF_RULE_OUT, "out", NULL }, + { NPF_RULE_FINAL, NPF_RULE_FINAL, "final", NULL }, +}; + +static void +npfctl_show_rule(nl_rule_t *nrl, unsigned nlevel) +{ + rule_group_t rg; + const char *rproc; + const void *nc; + size_t nclen; + + _npf_rule_getinfo(nrl, &rg.rg_name, &rg.rg_attr, &rg.rg_ifnum); + + /* Get the interface, if any. */ + char ifnamebuf[IFNAMSIZ], *ifname = NULL; + if (rg.rg_ifnum) { + ifname = if_indextoname(rg.rg_ifnum, ifnamebuf); + } + + /* + * If zero level, then it is a group. + */ + if (nlevel == 0) { + static bool ingroup = false; + const char *rname = rg.rg_name; + + if (ingroup) { + puts("}"); + } + ingroup = true; + if (rg.rg_attr & NPF_RULE_DEFAULT) { + puts("group (default) {"); + return; + } + printf("group (name \"%s\"", rname == NULL ? "" : rname); + if (ifname) { + printf(", interface %s", ifname); + } + puts(") {"); + return; + } + + /* + * Rule case. First, unparse the attributes. + */ + while (nlevel--) { + printf("\t"); + } + for (unsigned i = 0; i < __arraycount(attr_keyword_map); i++) { + const struct attr_keyword_mapent *ak = &attr_keyword_map[i]; + + if ((rg.rg_attr & ak->mask) == ak->flags) { + printf("%s ", ak->onmatch); + } else if (ak->nomatch) { + printf("%s ", ak->nomatch); + } + } + + if (ifname) { + printf("on %s ", ifname); + } + + nc = _npf_rule_ncode(nrl, &nclen); + if (nc) { + npfctl_show_ncode(nc, nclen); + } else { + printf("all "); + } + /* apply <rproc> */ + + if ((rproc = _npf_rule_rproc(nrl)) != NULL) { + printf("apply \"%s\"", rproc); + } + puts(""); +} + +int +npfctl_config_show(int fd) +{ + nl_config_t *ncf; + bool active, loaded; + int error = 0; + + ncf = npf_config_retrieve(fd, &active, &loaded); + if (ncf == NULL) { + return errno; + } + printf("Filtering:\t%s\nConfiguration:\t%s\n\n", + active ? "active" : "inactive", + loaded ? "loaded" : "empty"); + + if (loaded) { + error = _npf_rule_foreach(ncf, npfctl_show_rule); + puts("}"); + } + npf_config_destroy(ncf); + return error; +} Index: src/usr.sbin/npf/npfctl/npf_ncgen.c diff -u src/usr.sbin/npf/npfctl/npf_ncgen.c:1.8 src/usr.sbin/npf/npfctl/npf_ncgen.c:1.9 --- src/usr.sbin/npf/npfctl/npf_ncgen.c:1.8 Sat Mar 10 22:21:50 2012 +++ src/usr.sbin/npf/npfctl/npf_ncgen.c Wed May 30 21:30:07 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_ncgen.c,v 1.8 2012/03/10 22:21:50 christos Exp $ */ +/* $NetBSD: npf_ncgen.c,v 1.9 2012/05/30 21:30:07 rmind Exp $ */ /*- * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: npf_ncgen.c,v 1.8 2012/03/10 22:21:50 christos Exp $"); +__RCSID("$NetBSD: npf_ncgen.c,v 1.9 2012/05/30 21:30:07 rmind Exp $"); #include <stdlib.h> #include <stddef.h> @@ -388,14 +388,5 @@ npfctl_gennc_tcpfl(nc_ctx_t *ctx, uint8_ void npfctl_ncgen_print(const void *code, size_t len) { -#if 0 - const uint32_t *op = code; - - while (len) { - printf("\t> |0x%02x|\n", (u_int)*op++); - len -= sizeof(*op); - } -#else - npfctl_ncode_disassemble(stdout, code, len); -#endif + npfctl_ncode_disassemble(stdout, code, len, NULL); } Index: src/usr.sbin/npf/npfctl/npf_scan.l diff -u src/usr.sbin/npf/npfctl/npf_scan.l:1.1 src/usr.sbin/npf/npfctl/npf_scan.l:1.2 --- src/usr.sbin/npf/npfctl/npf_scan.l:1.1 Sun Jan 8 21:34:21 2012 +++ src/usr.sbin/npf/npfctl/npf_scan.l Wed May 30 21:30:07 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_scan.l,v 1.1 2012/01/08 21:34:21 rmind Exp $ */ +/* $NetBSD: npf_scan.l,v 1.2 2012/05/30 21:30:07 rmind Exp $ */ /*- * Copyright (c) 2011-2012 The NetBSD Foundation, Inc. @@ -72,10 +72,10 @@ interface return INTERFACE; all return ALL; block return BLOCK; pass return PASS; -keep return KEEP; -state return STATE; +stateful return STATEFUL; apply return APPLY; -quick return QUICK; +final return FINAL; +quick return FINAL; on return ON; inet6 return INET6; inet4 return INET; Index: src/usr.sbin/npf/npfctl/npf_var.c diff -u src/usr.sbin/npf/npfctl/npf_var.c:1.4 src/usr.sbin/npf/npfctl/npf_var.c:1.5 --- src/usr.sbin/npf/npfctl/npf_var.c:1.4 Sun Feb 26 21:50:05 2012 +++ src/usr.sbin/npf/npfctl/npf_var.c Wed May 30 21:30:07 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_var.c,v 1.4 2012/02/26 21:50:05 christos Exp $ */ +/* $NetBSD: npf_var.c,v 1.5 2012/05/30 21:30:07 rmind Exp $ */ /*- * Copyright (c) 2011-2012 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: npf_var.c,v 1.4 2012/02/26 21:50:05 christos Exp $"); +__RCSID("$NetBSD: npf_var.c,v 1.5 2012/05/30 21:30:07 rmind Exp $"); #include <stdlib.h> #include <string.h> @@ -62,6 +62,7 @@ npfvar_create(const char *name) { npfvar_t *vp = zalloc(sizeof(*vp)); vp->v_key = xstrdup(name); + var_num++; return vp; } @@ -88,7 +89,6 @@ npfvar_add(npfvar_t *vp) { vp->v_next = var_list; var_list = vp; - var_num++; } npfvar_t * @@ -169,6 +169,7 @@ npfvar_destroy(npfvar_t *vp) npfvar_free_elements(vp->v_elements); free(vp->v_key); free(vp); + var_num--; } char * Index: src/usr.sbin/npf/npfctl/npfctl.c diff -u src/usr.sbin/npf/npfctl/npfctl.c:1.10 src/usr.sbin/npf/npfctl/npfctl.c:1.11 --- src/usr.sbin/npf/npfctl/npfctl.c:1.10 Sun Feb 5 00:37:13 2012 +++ src/usr.sbin/npf/npfctl/npfctl.c Wed May 30 21:30:07 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npfctl.c,v 1.10 2012/02/05 00:37:13 rmind Exp $ */ +/* $NetBSD: npfctl.c,v 1.11 2012/05/30 21:30:07 rmind Exp $ */ /*- * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: npfctl.c,v 1.10 2012/02/05 00:37:13 rmind Exp $"); +__RCSID("$NetBSD: npfctl.c,v 1.11 2012/05/30 21:30:07 rmind Exp $"); #include <sys/ioctl.h> #include <sys/stat.h> @@ -50,14 +50,17 @@ extern const char * yyfilename; extern int yyparse(void); extern void yyrestart(FILE *); -#define NPFCTL_START 1 -#define NPFCTL_STOP 2 -#define NPFCTL_RELOAD 3 -#define NPFCTL_FLUSH 4 -#define NPFCTL_TABLE 5 -#define NPFCTL_STATS 6 -#define NPFCTL_SESSIONS_SAVE 7 -#define NPFCTL_SESSIONS_LOAD 8 +enum { + NPFCTL_START, + NPFCTL_STOP, + NPFCTL_RELOAD, + NPFCTL_SHOWCONF, + NPFCTL_FLUSH, + NPFCTL_TABLE, + NPFCTL_STATS, + NPFCTL_SESSIONS_SAVE, + NPFCTL_SESSIONS_LOAD, +}; static struct operations_s { const char * cmd; @@ -67,6 +70,7 @@ static struct operations_s { { "start", NPFCTL_START }, { "stop", NPFCTL_STOP }, { "reload", NPFCTL_RELOAD }, + { "show", NPFCTL_SHOWCONF, }, { "flush", NPFCTL_FLUSH }, /* Table */ { "table", NPFCTL_TABLE }, @@ -263,6 +267,9 @@ npfctl(int action, int argc, char **argv npfctl_parsecfg(argc < 3 ? NPF_CONF_PATH : argv[2]); ret = npfctl_config_send(fd); break; + case NPFCTL_SHOWCONF: + ret = npfctl_config_show(fd); + break; case NPFCTL_FLUSH: ret = npf_config_flush(fd); break; Index: src/usr.sbin/npf/npfctl/npfctl.h diff -u src/usr.sbin/npf/npfctl/npfctl.h:1.13 src/usr.sbin/npf/npfctl/npfctl.h:1.14 --- src/usr.sbin/npf/npfctl/npfctl.h:1.13 Sat Mar 10 22:21:50 2012 +++ src/usr.sbin/npf/npfctl/npfctl.h Wed May 30 21:30:07 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npfctl.h,v 1.13 2012/03/10 22:21:50 christos Exp $ */ +/* $NetBSD: npfctl.h,v 1.14 2012/05/30 21:30:07 rmind Exp $ */ /*- * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. @@ -71,7 +71,7 @@ typedef struct opt_proto { typedef struct rule_group { const char * rg_name; - int rg_attr; + uint32_t rg_attr; u_int rg_ifnum; } rule_group_t; @@ -146,6 +146,7 @@ void npfctl_gennc_tcpfl(nc_ctx_t *, uin void npfctl_config_init(bool); int npfctl_config_send(int); +int npfctl_config_show(int); void npfctl_build_rproc(const char *, npfvar_t *); void npfctl_build_group(const char *, int, u_int); @@ -154,6 +155,13 @@ void npfctl_build_rule(int, u_int, sa_f void npfctl_build_nat(int, u_int, const filt_opts_t *, npfvar_t *, npfvar_t *); void npfctl_build_table(const char *, u_int, const char *); -int npfctl_ncode_disassemble(FILE *, const void *, size_t); + +/* + * N-code disassembler. + */ +typedef struct nc_inf nc_inf_t; + +int npfctl_ncode_disassemble(FILE *, const void *, size_t, + nc_inf_t *); #endif