pf: Refactor state killing

Extract the state killing code from pfioctl() and rephrase the filtering
conditions for readability.

No functional change intended.

MFC after:	1 week
Sponsored by:	Rubicon Communications, LLC ("Netgate")
Differential Revision:	https://reviews.freebsd.org/D29795
This commit is contained in:
Kristof Provost 2021-04-16 16:34:21 +02:00
parent 33f8d79d76
commit 586aab9e0a

View File

@ -2522,6 +2522,72 @@ pf_ioctl_addrule(struct pf_krule *rule, uint32_t ticket,
return (error);
}
static int
pf_killstates_row(struct pfioc_state_kill *psk, struct pf_idhash *ih)
{
struct pf_state *s;
struct pf_state_key *sk;
struct pf_addr *srcaddr, *dstaddr;
int killed = 0;
u_int16_t srcport, dstport;
relock_DIOCKILLSTATES:
PF_HASHROW_LOCK(ih);
LIST_FOREACH(s, &ih->states, entry) {
sk = s->key[PF_SK_WIRE];
if (s->direction == PF_OUT) {
srcaddr = &sk->addr[1];
dstaddr = &sk->addr[0];
srcport = sk->port[1];
dstport = sk->port[0];
} else {
srcaddr = &sk->addr[0];
dstaddr = &sk->addr[1];
srcport = sk->port[0];
dstport = sk->port[1];
}
if (psk->psk_af && sk->af != psk->psk_af)
continue;
if (psk->psk_proto && psk->psk_proto != sk->proto)
continue;
if (! PF_MATCHA(psk->psk_src.neg, &psk->psk_src.addr.v.a.addr,
&psk->psk_src.addr.v.a.mask, srcaddr, sk->af))
continue;
if (! PF_MATCHA(psk->psk_dst.neg, &psk->psk_dst.addr.v.a.addr,
&psk->psk_dst.addr.v.a.mask, dstaddr, sk->af))
continue;
if (psk->psk_src.port_op != 0 &&
! pf_match_port(psk->psk_src.port_op,
psk->psk_src.port[0], psk->psk_src.port[1], srcport))
continue;
if (psk->psk_dst.port_op != 0 &&
! pf_match_port(psk->psk_dst.port_op,
psk->psk_dst.port[0], psk->psk_dst.port[1], dstport))
continue;
if (psk->psk_label[0] && (! s->rule.ptr->label[0] ||
strcmp(psk->psk_label, s->rule.ptr->label)))
continue;
if (psk->psk_ifname[0] && strcmp(psk->psk_ifname,
s->kif->pfik_name))
continue;
pf_unlink_state(s, PF_ENTER_LOCKED);
killed++;
goto relock_DIOCKILLSTATES;
}
PF_HASHROW_UNLOCK(ih);
return (killed);
}
static int
pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
{
@ -3218,9 +3284,6 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
case DIOCKILLSTATES: {
struct pf_state *s;
struct pf_state_key *sk;
struct pf_addr *srcaddr, *dstaddr;
u_int16_t srcport, dstport;
struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
u_int i, killed = 0;
@ -3235,58 +3298,9 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
break;
}
for (i = 0; i <= pf_hashmask; i++) {
struct pf_idhash *ih = &V_pf_idhash[i];
for (i = 0; i <= pf_hashmask; i++)
killed += pf_killstates_row(psk, &V_pf_idhash[i]);
relock_DIOCKILLSTATES:
PF_HASHROW_LOCK(ih);
LIST_FOREACH(s, &ih->states, entry) {
sk = s->key[PF_SK_WIRE];
if (s->direction == PF_OUT) {
srcaddr = &sk->addr[1];
dstaddr = &sk->addr[0];
srcport = sk->port[1];
dstport = sk->port[0];
} else {
srcaddr = &sk->addr[0];
dstaddr = &sk->addr[1];
srcport = sk->port[0];
dstport = sk->port[1];
}
if ((!psk->psk_af || sk->af == psk->psk_af)
&& (!psk->psk_proto || psk->psk_proto ==
sk->proto) &&
PF_MATCHA(psk->psk_src.neg,
&psk->psk_src.addr.v.a.addr,
&psk->psk_src.addr.v.a.mask,
srcaddr, sk->af) &&
PF_MATCHA(psk->psk_dst.neg,
&psk->psk_dst.addr.v.a.addr,
&psk->psk_dst.addr.v.a.mask,
dstaddr, sk->af) &&
(psk->psk_src.port_op == 0 ||
pf_match_port(psk->psk_src.port_op,
psk->psk_src.port[0], psk->psk_src.port[1],
srcport)) &&
(psk->psk_dst.port_op == 0 ||
pf_match_port(psk->psk_dst.port_op,
psk->psk_dst.port[0], psk->psk_dst.port[1],
dstport)) &&
(!psk->psk_label[0] ||
(s->rule.ptr->label[0] &&
!strcmp(psk->psk_label,
s->rule.ptr->label))) &&
(!psk->psk_ifname[0] ||
!strcmp(psk->psk_ifname,
s->kif->pfik_name))) {
pf_unlink_state(s, PF_ENTER_LOCKED);
killed++;
goto relock_DIOCKILLSTATES;
}
}
PF_HASHROW_UNLOCK(ih);
}
psk->psk_killed = killed;
break;
}