Hello
thank your for the report. You are absolutely right we need
to calculate hashkey. diff below fixes that.
in order to enter the 'fast path' DIOCKILLSTATES ioctl(2) command
we also must fix pfctl(8) so it sets af in `psk` argument to ioctl.
Diff also tweaks handling of killed output counter. I think
we should assigned psk->psk_killed unconditionally.
the patch below hopes to fix the issue.
thanks and
regards
sashan
--------8<---------------8<---------------8<------------------8<--------
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index f0d6127dc0c..6ad1874580f 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -74,7 +74,7 @@ void pfctl_net_kill_states(int, const char *, int, int);
void pfctl_label_kill_states(int, const char *, int, int);
void pfctl_id_kill_states(int, int);
void pfctl_key_kill_states(int, const char *, int, int);
-int pfctl_parse_host(char *, struct pf_rule_addr *);
+int pfctl_parse_host(char *, struct pf_rule_addr *, int *);
void pfctl_init_options(struct pfctl *);
int pfctl_load_options(struct pfctl *);
int pfctl_load_limit(struct pfctl *, unsigned int, unsigned int);
@@ -688,6 +688,7 @@ pfctl_key_kill_states(int dev, const char *iface, int opts,
int rdomain)
char *s, *token, *tokens[4];
struct protoent *p;
u_int i, sidx, didx;
+ int af_src, af_dst;
if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
warnx("no key specified");
@@ -728,11 +729,16 @@ pfctl_key_kill_states(int dev, const char *iface, int
opts, int rdomain)
} else
errx(1, "invalid direction: %s", tokens[2]);
- if (pfctl_parse_host(tokens[sidx], &psk.psk_src) == -1)
+ if (pfctl_parse_host(tokens[sidx], &psk.psk_src, &af_src) == -1)
errx(1, "invalid host: %s", tokens[sidx]);
- if (pfctl_parse_host(tokens[didx], &psk.psk_dst) == -1)
+ if (pfctl_parse_host(tokens[didx], &psk.psk_dst, &af_dst) == -1)
errx(1, "invalid host: %s", tokens[didx]);
+ if (af_src == af_dst)
+ psk.psk_af = af_src;
+ else
+ psk.psk_af = AF_UNSPEC;
+
if (ioctl(dev, DIOCKILLSTATES, &psk) == -1)
err(1, "DIOCKILLSTATES");
@@ -741,7 +747,7 @@ pfctl_key_kill_states(int dev, const char *iface, int opts,
int rdomain)
}
int
-pfctl_parse_host(char *str, struct pf_rule_addr *addr)
+pfctl_parse_host(char *str, struct pf_rule_addr *addr, int *af)
{
char *s = NULL, *sbs, *sbe;
struct addrinfo hints, *ai;
@@ -778,6 +784,9 @@ pfctl_parse_host(char *str, struct pf_rule_addr *addr)
addr->port_op = PF_OP_EQ;
addr->addr.type = PF_ADDR_ADDRMASK;
+ if (af != NULL)
+ *af = hints.ai_family;
+
return (0);
error:
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index cba0934c01b..99c66b5516a 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -1811,6 +1811,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags,
struct proc *p)
&psk->psk_dst.addr.v.a.addr, key.af);
key.port[sidx] = psk->psk_src.port[0];
key.port[didx] = psk->psk_dst.port[0];
+ key.hash = pf_pkt_hash(key.af, key.proto,
+ &key.addr[sidx], &key.addr[didx],
+ key.port[sidx], key.port[didx]);
sk = RBT_FIND(pf_state_tree, &pf_statetbl,
&key);
@@ -1839,8 +1842,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags,
struct proc *p)
}
}
}
- if (killed)
- psk->psk_killed = killed;
+ psk->psk_killed = killed;
PF_STATE_EXIT_WRITE();
PF_UNLOCK();
NET_UNLOCK();