Limiting the "flush all" operation to a specific interface does not
make sense, and the intention was clear as well:
pfctl.c revision 1.298
date: 2010/06/28 23:21:41; author: mcbride; state: Exp; lines: +27
-11;
Clean up iterface stats handling:
- 'make -Fi' reset ALL the interface statistics
can be restricted with -i ifname
- 'make -Fa -i ifname' fail (it's meaningless)
- get rid of a silly little struct that's only used for one thing
ok henning
Yet, tables and rules are always cleared:
# pfctl -F all -i foo
0 tables deleted.
rules cleared
pfctl: don't specify an interface with -Fall
usage: pfctl ...
It even clears statistics for the empty interface:
# pfctl -F all -i ''
0 tables deleted.
rules cleared
8 states cleared
source tracking entries cleared
pf: statistics cleared for interface
pf: interface flags reset
That's unacceptable.
Currently, the idiom `opt && *opt' is used to test for table, key and
interface arguments, but is inherently unable to detect empy values
since the NULL initialised `opt' is unconditionally set to `optarg'
which may be empty.
Diff below bails out immediately when `-i ...' is passed and hoists
empty option argument checks into the getopt(3) routine. All code using
these arguments can now rely on them not being empty if given.
$ ./obj/pfctl -F all -i ''
pfctl: empty interface name
# ./obj/pfctl -F all -i foo
pfctl: don't specify an interface with -Fall
usage: pfctl ...
Feedback? OK?
Regress passes.
NB: parse.y does accept empty strings for anchors, tables, interfaces
and tables and handles them poorly, but that's stuff for another diff.
Index: pfctl.c
===================================================================
RCS file: /cvs/src/sbin/pfctl/pfctl.c,v
retrieving revision 1.362
diff -u -p -r1.362 pfctl.c
--- pfctl.c 2 Jan 2019 23:08:00 -0000 1.362
+++ pfctl.c 5 Jan 2019 19:03:07 -0000
@@ -2342,6 +2342,8 @@ main(int argc, char *argv[])
"a:dD:eqf:F:ghi:k:K:L:Nno:Pp:R:rS:s:t:T:vV:x:z")) != -1) {
switch (ch) {
case 'a':
+ if (!*optarg)
+ errx(1, "emtpy anchor name");
anchoropt = optarg;
break;
case 'd':
@@ -2369,6 +2371,8 @@ main(int argc, char *argv[])
mode = O_RDWR;
break;
case 'i':
+ if (!*optarg)
+ errx(1, "empty interface name");
ifaceopt = optarg;
break;
case 'k':
@@ -2377,6 +2381,8 @@ main(int argc, char *argv[])
usage();
/* NOTREACHED */
}
+ if (!*optarg)
+ errx(1, "empty state key");
state_kill[state_killers++] = optarg;
mode = O_RDWR;
break;
@@ -2386,6 +2392,8 @@ main(int argc, char *argv[])
usage();
/* NOTREACHED */
}
+ if (!*optarg)
+ errx(1, "empty source tracking key");
src_node_kill[src_node_killers++] = optarg;
mode = O_RDWR;
break;
@@ -2434,6 +2442,8 @@ main(int argc, char *argv[])
}
break;
case 't':
+ if (!*optarg)
+ errx(1, "empty table name");
tableopt = optarg;
break;
case 'T':
@@ -2626,13 +2636,13 @@ main(int argc, char *argv[])
pfctl_clear_stats(dev, ifaceopt, opts);
break;
case 'a':
- pfctl_clear_tables(anchorname, opts);
- pfctl_clear_rules(dev, opts, anchorname);
- if (ifaceopt && *ifaceopt) {
+ if (ifaceopt) {
warnx("don't specify an interface with -Fall");
usage();
/* NOTREACHED */
}
+ pfctl_clear_tables(anchorname, opts);
+ pfctl_clear_rules(dev, opts, anchorname);
if (!*anchorname) {
pfctl_clear_states(dev, ifaceopt, opts);
pfctl_clear_src_nodes(dev, opts);