--- sbin/ipfw/ipfw2.c Wed Apr 18 18:03:08 2007 +++ sbin/ipfw/ipfw2.c Tue May 29 15:35:00 2007 @@ -73,6 +74,8 @@ do_expired, /* display expired dynamic rules */ do_compact, /* show rules in compact mode */ do_force, /* do not ask for confirmation */ + do_acct, /* Show packet/byte count */ + use_set, /* work with specified set number */ show_sets, /* display rule sets */ test_only, /* only check syntax */ comment_only, /* only print action and comment */ @@ -226,6 +229,8 @@ }; static void show_usage(void); +static void list(int ac, char *av[], int show_counters); +static void delete(int ac, char *av[]); enum tokens { TOK_NULL=0, @@ -2350,6 +2354,7 @@ * ipfw set swap X Y * ipfw set move X to Y * ipfw set move rule X to Y + * ipfw set N {show | list} ... */ static void sets_handler(int ac, char *av[]) @@ -2364,6 +2369,27 @@ if (!ac) errx(EX_USAGE, "set needs command"); + if (isdigit(*av[0])) { + new_set = atoi(av[0]); + if (new_set > RESVD_SET) + errx(EX_DATAERR, "invalid set number %s\n", av[0]); + ac--; av++; + use_set = new_set + 1; + + if (ac > 0) { + if (_substrcmp(*av, "show") == 0) + list(ac, av, 1 /* show counters */); + else if (_substrcmp(*av, "print") == 0 || + _substrcmp(*av, "list") == 0) + list(ac, av, do_acct); + else if (_substrcmp(*av, "delete") == 0) + delete(ac, av); + else + errx(EX_USAGE, "bad command `%s'", *av); + } else + errx(EX_USAGE, "set needs command"); + return; + } if (_substrcmp(*av, "show") == 0) { void *data; char const *msg; @@ -2498,6 +2524,7 @@ u_long rnum, last; char *endptr; int seen = 0; + uint8_t set; const int ocmd = do_pipe ? IP_DUMMYNET_GET : IP_FW_GET; int nalloc = 1024; /* start somewhere... */ @@ -2552,6 +2579,10 @@ bcwidth = pcwidth = 0; if (show_counters) { for (n = 0, r = data; n < nstat; n++, r = NEXT(r)) { + /* skip rules from different set */ + if (use_set && r->set != use_set - 1) + continue; + /* packet counter */ width = snprintf(NULL, 0, "%llu", align_uint64(&r->pcnt)); @@ -2567,6 +2598,13 @@ } if (do_dynamic && ndyn) { for (n = 0, d = dynrules; n < ndyn; n++, d++) { + if (use_set) { + /* skip rules from different set */ + bcopy(&d->rule + sizeof(uint16_t), + &set, sizeof(uint8_t)); + if (set != use_set - 1) + continue; + } width = snprintf(NULL, 0, "%llu", align_uint64(&d->pcnt)); if (width > pcwidth) @@ -2580,14 +2618,24 @@ } /* if no rule numbers were specified, list all rules */ if (ac == 0) { - for (n = 0, r = data; n < nstat; n++, r = NEXT(r) ) + for (n = 0, r = data; n < nstat; n++, r = NEXT(r) ) { + if (use_set && r->set != use_set - 1) + continue; show_ipfw(r, pcwidth, bcwidth); + } if (do_dynamic && ndyn) { printf("## Dynamic rules (%d):\n", ndyn); - for (n = 0, d = dynrules; n < ndyn; n++, d++) + for (n = 0, d = dynrules; n < ndyn; n++, d++) { + if (use_set) { + bcopy(&d->rule + sizeof(uint16_t), + &set, sizeof(uint8_t)); + if (set != use_set - 1) + continue; + } show_dyn_ipfw(d, pcwidth, bcwidth); } + } goto done; } @@ -2606,6 +2654,8 @@ for (n = seen = 0, r = data; n < nstat; n++, r = NEXT(r) ) { if (r->rulenum > last) break; + if (use_set && r->set != use_set - 1) + continue; if (r->rulenum >= rnum && r->rulenum <= last) { show_ipfw(r, pcwidth, bcwidth); seen = 1; @@ -2634,6 +2684,12 @@ bcopy(&d->rule, &rulenum, sizeof(rulenum)); if (rulenum > rnum) break; + if (use_set) { + bcopy(&d->rule + sizeof(uint16_t), + &set, sizeof(uint8_t)); + if (set != use_set - 1) + continue; + } if (r->rulenum >= rnum && r->rulenum <= last) show_dyn_ipfw(d, pcwidth, bcwidth); } @@ -2671,7 +2727,8 @@ "nat N config {ip IPADDR|if IFNAME|log|deny_in|same_ports|unreg_only|reset|\n" " reverse|proxy_only|redirect_addr linkspec|\n" " redirect_port linkspec|redirect_proto linkspec}\n" -"set [disable N... enable N...] | move [rule] X to Y | swap X Y | show\n" +"set [disable N... enable N...] | move [rule] X to Y | swap X Y | show |\n" +" N {list | show} [N | N-M]\n" "table N {add ip[/bits] [value] | delete ip[/bits] | flush | list}\n" "\n" "RULE-BODY: check-state [PARAMS] | ACTION [PARAMS] ADDR [OPTION_LIST]\n" @@ -3189,6 +3246,11 @@ av++; ac--; NEED1("missing rule specification"); if (ac > 0 && _substrcmp(*av, "set") == 0) { + /* don't allow using the following syntax: + * ipfw set N delete set N + */ + if (use_set) + errx(EX_DATAERR, "invalid syntax"); do_set = 1; /* delete set */ ac--; av++; } @@ -3214,7 +3276,13 @@ do_pipe == 1 ? p.pipe_nr : p.fs.fs_nr); } } else { + if (use_set) { + /* XXX: hardcoded cmd = 5 */ + rulenum = (i & 0xffff) | (5 << 24) | + ((use_set - 1) << 16); + } else { rulenum = (i & 0xffff) | (do_set << 24); + } i = do_cmd(IP_FW_DEL, &rulenum, sizeof rulenum); if (i) { exitval = EX_UNAVAILABLE; @@ -5930,7 +6013,6 @@ { int ch, ac, save_ac; char **av, **save_av; - int do_acct = 0; /* Show packet/byte count */ #define WHITESP " \t\f\v\n\r" if (oldac == 0)