Page MenuHomeFreeBSD

D30092.id88540.diff
No OneTemporary

D30092.id88540.diff

Index: lib/libpfctl/libpfctl.h
===================================================================
--- lib/libpfctl/libpfctl.h
+++ lib/libpfctl/libpfctl.h
@@ -194,6 +194,7 @@
struct pf_rule_addr rt_addr;
char ifname[IFNAMSIZ];
char label[PF_RULE_LABEL_SIZE];
+ bool kill_match;
};
int pfctl_get_rule(int dev, u_int32_t nr, u_int32_t ticket,
Index: lib/libpfctl/libpfctl.c
===================================================================
--- lib/libpfctl/libpfctl.c
+++ lib/libpfctl/libpfctl.c
@@ -645,6 +645,7 @@
pfctl_nv_add_rule_addr(nvl, "rt_addr", &kill->rt_addr);
nvlist_add_string(nvl, "ifname", kill->ifname);
nvlist_add_string(nvl, "label", kill->label);
+ nvlist_add_bool(nvl, "kill_match", kill->kill_match);
nv.data = nvlist_pack(nvl, &nv.len);
nv.size = nv.len;
Index: sbin/pfctl/pfctl.8
===================================================================
--- sbin/pfctl/pfctl.8
+++ sbin/pfctl/pfctl.8
@@ -35,7 +35,7 @@
.Sh SYNOPSIS
.Nm pfctl
.Bk -words
-.Op Fl AdeghmNnOPqRrvz
+.Op Fl AdeghMmNnOPqRrvz
.Op Fl a Ar anchor
.Oo Fl D Ar macro Ns =
.Ar value Oc
@@ -331,6 +331,16 @@
To kill all states using a gateway in 192.168.0.0/24:
.Pp
.Dl # pfctl -k gateway -k 192.168.0.0/24
+.Pp
+.It Fl M
+Kill matching states in the opposite direction (on other interfaces) when
+killing states.
+This applies to states killed using the -k option and also will apply to the
+flush command when flushing states.
+This is useful when an interface is specified when flushing states. Example:
+.Pp
+.Dl # pfctl -M -i interface -Fs
+.Pp
.It Fl m
Merge in explicitly given options without resetting those
which are omitted.
Index: sbin/pfctl/pfctl.c
===================================================================
--- sbin/pfctl/pfctl.c
+++ sbin/pfctl/pfctl.c
@@ -245,7 +245,7 @@
extern char *__progname;
fprintf(stderr,
-"usage: %s [-AdeghmNnOPqRrvz] [-a anchor] [-D macro=value] [-F modifier]\n"
+"usage: %s [-AdeghMmNnOPqRrvz] [-a anchor] [-D macro=value] [-F modifier]\n"
"\t[-f file] [-i interface] [-K host | network]\n"
"\t[-k host | network | gateway | label | id] [-o level] [-p device]\n"
"\t[-s modifier] [-t table -T command [address ...]] [-x level]\n",
@@ -478,6 +478,9 @@
sizeof(kill.ifname)) >= sizeof(kill.ifname))
errx(1, "invalid interface: %s", iface);
+ if (opts & PF_OPT_KILLMATCH)
+ kill.kill_match = true;
+
if (pfctl_clear_states(dev, &kill, &killed))
err(1, "DIOCCLRSTATES");
if ((opts & PF_OPT_QUIET) == 0)
@@ -661,6 +664,9 @@
pfctl_addrprefix(state_kill[0], &kill.src.addr.v.a.mask);
+ if (opts & PF_OPT_KILLMATCH)
+ kill.kill_match = true;
+
if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) {
errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
/* NOTREACHED */
@@ -768,6 +774,9 @@
sizeof(kill.ifname)) >= sizeof(kill.ifname))
errx(1, "invalid interface: %s", iface);
+ if (opts & PF_OPT_KILLMATCH)
+ kill.kill_match = true;
+
pfctl_addrprefix(state_kill[1], &kill.rt_addr.addr.v.a.mask);
if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL, &res))) {
@@ -821,6 +830,9 @@
sizeof(kill.ifname)) >= sizeof(kill.ifname))
errx(1, "invalid interface: %s", iface);
+ if (opts & PF_OPT_KILLMATCH)
+ kill.kill_match = true;
+
if (strlcpy(kill.label, state_kill[1], sizeof(kill.label)) >=
sizeof(kill.label))
errx(1, "label too long: %s", state_kill[1]);
@@ -846,6 +858,10 @@
}
memset(&kill, 0, sizeof(kill));
+
+ if (opts & PF_OPT_KILLMATCH)
+ kill.kill_match = true;
+
if ((sscanf(state_kill[1], "%jx/%x",
&kill.cmp.id, &kill.cmp.creatorid)) == 2)
HTONL(kill.cmp.creatorid);
@@ -2199,7 +2215,7 @@
usage();
while ((ch = getopt(argc, argv,
- "a:AdD:eqf:F:ghi:k:K:mnNOo:Pp:rRs:t:T:vx:z")) != -1) {
+ "a:AdD:eqf:F:ghi:k:K:mMnNOo:Pp:rRs:t:T:vx:z")) != -1) {
switch (ch) {
case 'a':
anchoropt = optarg;
@@ -2252,6 +2268,9 @@
case 'm':
opts |= PF_OPT_MERGE;
break;
+ case 'M':
+ opts |= PF_OPT_KILLMATCH;
+ break;
case 'n':
opts |= PF_OPT_NOACTION;
break;
Index: sbin/pfctl/pfctl_parser.h
===================================================================
--- sbin/pfctl/pfctl_parser.h
+++ sbin/pfctl/pfctl_parser.h
@@ -55,6 +55,7 @@
#define PF_OPT_NUMERIC 0x1000
#define PF_OPT_MERGE 0x2000
#define PF_OPT_RECURSE 0x4000
+#define PF_OPT_KILLMATCH 0x8000
#define PF_TH_ALL 0xFF
Index: share/man/man4/pf.4
===================================================================
--- share/man/man4/pf.4
+++ share/man/man4/pf.4
@@ -338,6 +338,10 @@
Remove matching entries from the state table.
This ioctl returns the number of killed states in
.Va "killed" .
+If
+.Va "kill_match"
+is true the kernel will also look for and kill a matching state in the opposite
+direction for each state matching the original criteria.
.Bd -literal
nvlist pf_state_cmp {
number id;
@@ -354,6 +358,7 @@
nvlist pf_rule_addr rt_addr;
string ifname[IFNAMSIZ];
string label[PF_RULE_LABEL_SIZE];
+ boolean kill_match;
};
.Ed
.It Dv DIOCCLRSTATESNV Fa "struct pfioc_state_kill *psk"
Index: sys/net/pfvar.h
===================================================================
--- sys/net/pfvar.h
+++ sys/net/pfvar.h
@@ -1085,6 +1085,7 @@
char psk_ifname[IFNAMSIZ];
char psk_label[PF_RULE_LABEL_SIZE];
u_int psk_killed;
+ bool psk_kill_match;
};
#endif
Index: sys/netpfil/pf/pf_ioctl.c
===================================================================
--- sys/netpfil/pf/pf_ioctl.c
+++ sys/netpfil/pf/pf_ioctl.c
@@ -2450,6 +2450,8 @@
sizeof(kill->psk_ifname)));
PFNV_CHK(pf_nvstring(nvl, "label", kill->psk_label,
sizeof(kill->psk_label)));
+ if (nvlist_exists_bool(nvl, "kill_match"))
+ kill->psk_kill_match = nvlist_get_bool(nvl, "kill_match");
errout:
return (error);
@@ -2627,13 +2629,33 @@
return (false);
}
+static unsigned int
+pf_kill_matching_state(struct pf_state_key_cmp *key, int dir)
+{
+ struct pf_state *match;
+ int more = 0;
+ unsigned int killed = 0;
+
+ /* Call with unlocked hashrow */
+
+ match = pf_find_state_all(key, dir, &more);
+ if (match && !more) {
+ pf_unlink_state(match, 0);
+ killed++;
+ }
+
+ return (killed);
+}
+
static int
pf_killstates_row(struct pf_kstate_kill *psk, struct pf_idhash *ih)
{
struct pf_state *s;
struct pf_state_key *sk;
struct pf_addr *srcaddr, *dstaddr;
- int killed = 0;
+ struct pf_state_key_cmp match_key;
+ int idx, killed = 0;
+ unsigned int dir;
u_int16_t srcport, dstport;
relock_DIOCKILLSTATES:
@@ -2690,8 +2712,36 @@
s->kif->pfik_name))
continue;
+ if (psk->psk_kill_match) {
+ /* Create the key to find matching states, with lock
+ * held. */
+
+ bzero(&match_key, sizeof(match_key));
+
+ if (s->direction == PF_OUT) {
+ dir = PF_IN;
+ idx = PF_SK_STACK;
+ } else {
+ dir = PF_OUT;
+ idx = PF_SK_WIRE;
+ }
+
+ match_key.af = s->key[idx]->af;
+ match_key.proto = s->key[idx]->proto;
+ PF_ACPY(&match_key.addr[0],
+ &s->key[idx]->addr[1], match_key.af);
+ match_key.port[0] = s->key[idx]->port[1];
+ PF_ACPY(&match_key.addr[1],
+ &s->key[idx]->addr[0], match_key.af);
+ match_key.port[1] = s->key[idx]->port[0];
+ }
+
pf_unlink_state(s, PF_ENTER_LOCKED);
killed++;
+
+ if (psk->psk_kill_match)
+ killed += pf_kill_matching_state(&match_key, dir);
+
goto relock_DIOCKILLSTATES;
}
PF_HASHROW_UNLOCK(ih);
@@ -5400,27 +5450,57 @@
static unsigned int
pf_clear_states(const struct pf_kstate_kill *kill)
{
+ struct pf_state_key_cmp match_key;
struct pf_state *s;
- unsigned int killed = 0;
+ int idx;
+ unsigned int killed = 0, dir;
for (unsigned int i = 0; i <= pf_hashmask; i++) {
struct pf_idhash *ih = &V_pf_idhash[i];
relock_DIOCCLRSTATES:
PF_HASHROW_LOCK(ih);
- LIST_FOREACH(s, &ih->states, entry)
- if (!kill->psk_ifname[0] ||
- !strcmp(kill->psk_ifname,
- s->kif->pfik_name)) {
- /*
- * Don't send out individual
- * delete messages.
- */
- s->state_flags |= PFSTATE_NOSYNC;
- pf_unlink_state(s, PF_ENTER_LOCKED);
- killed++;
- goto relock_DIOCCLRSTATES;
+ LIST_FOREACH(s, &ih->states, entry) {
+ if (kill->psk_ifname[0] &&
+ strcmp(kill->psk_ifname,
+ s->kif->pfik_name))
+ continue;
+
+ if (kill->psk_kill_match) {
+ bzero(&match_key, sizeof(match_key));
+
+ if (s->direction == PF_OUT) {
+ dir = PF_IN;
+ idx = PF_SK_STACK;
+ } else {
+ dir = PF_OUT;
+ idx = PF_SK_WIRE;
+ }
+
+ match_key.af = s->key[idx]->af;
+ match_key.proto = s->key[idx]->proto;
+ PF_ACPY(&match_key.addr[0],
+ &s->key[idx]->addr[1], match_key.af);
+ match_key.port[0] = s->key[idx]->port[1];
+ PF_ACPY(&match_key.addr[1],
+ &s->key[idx]->addr[0], match_key.af);
+ match_key.port[1] = s->key[idx]->port[0];
}
+
+ /*
+ * Don't send out individual
+ * delete messages.
+ */
+ s->state_flags |= PFSTATE_NOSYNC;
+ pf_unlink_state(s, PF_ENTER_LOCKED);
+ killed++;
+
+ if (kill->psk_kill_match)
+ killed += pf_kill_matching_state(&match_key,
+ dir);
+
+ goto relock_DIOCCLRSTATES;
+ }
PF_HASHROW_UNLOCK(ih);
}

File Metadata

Mime Type
text/plain
Expires
Fri, Aug 14, 12:43 PM (7 h, 38 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36726207
Default Alt Text
D30092.id88540.diff (9 KB)

Event Timeline