Skip to content

Commit

Permalink
pf: backport changes around the following commit #242
Browse files Browse the repository at this point in the history
 commit 49f39043a02d6011c1907e1b07eb034652a1269c
 Author: phessler <phessler@openbsd.org>
 Date:   Fri Apr 28 14:08:34 2023 +0000

    Relax the "pass all" rule so all forms of neighbor advertisements are allowed
    in either direction.

    This more closely matches the IPv4 ARP behaviour.

    From sashan@
    discussed with kn@ deraadt@
  • Loading branch information
fichtner committed Feb 24, 2025
1 parent 7953277 commit 2640600
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 3 deletions.
4 changes: 3 additions & 1 deletion sys/net/pfvar.h
Original file line number Diff line number Diff line change
Expand Up @@ -1549,7 +1549,9 @@ struct pf_pdesc {
struct sctphdr sctp;
struct icmp icmp;
#ifdef INET6
struct icmp6_hdr icmp6;
struct icmp6_hdr icmp6;
struct mld_hdr mld;
struct nd_neighbor_solicit nd_ns;
#endif /* INET6 */
char any[0];
} hdr;
Expand Down
40 changes: 38 additions & 2 deletions sys/netpfil/pf/pf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1957,6 +1957,9 @@ pf_icmp_mapping(struct pf_pdesc *pd, u_int8_t type,

case MLD_LISTENER_QUERY:
case MLD_LISTENER_REPORT: {
struct mld_hdr *mld = &pd->hdr.mld;
u_int32_t h;

/*
* Listener Report can be sent by clients
* without an associated Listener Query.
Expand All @@ -1966,7 +1969,12 @@ pf_icmp_mapping(struct pf_pdesc *pd, u_int8_t type,
*/
*icmp_dir = PF_IN;
*virtual_type = MLD_LISTENER_QUERY;
*virtual_id = 0;
/* generate fake id for these messages */
h = mld->mld_addr.s6_addr32[0] ^
mld->mld_addr.s6_addr32[1] ^
mld->mld_addr.s6_addr32[2] ^
mld->mld_addr.s6_addr32[3];
*virtual_id = (h >> 16) ^ (h & 0xffff);
break;
}
case MLD_MTRACE:
Expand All @@ -1978,9 +1986,30 @@ pf_icmp_mapping(struct pf_pdesc *pd, u_int8_t type,

case ND_NEIGHBOR_SOLICIT:
*icmp_dir = PF_IN;
/* FALLTHROUGH */
case ND_NEIGHBOR_ADVERT: {
struct nd_neighbor_solicit *nd = &pd->hdr.nd_ns;
u_int32_t h;

*virtual_type = ND_NEIGHBOR_SOLICIT;
*virtual_id = 0;
/* generate fake id for these messages */
h = nd->nd_ns_target.s6_addr32[0] ^
nd->nd_ns_target.s6_addr32[1] ^
nd->nd_ns_target.s6_addr32[2] ^
nd->nd_ns_target.s6_addr32[3];
*virtual_id = (h >> 16) ^ (h & 0xffff);
/*
* the extra work here deals with 'keep state' option
* at pass rule for unsolicited advertisement. By
* returning 1 (state_icmp = 1) we override 'keep
* state' to 'no state' so we don't create state for
* unsolicited advertisements. No one expects answer to
* unsolicited advertisements so we should be good.
*/
if (type == ND_NEIGHBOR_ADVERT) {
*virtual_type = htons(*virtual_type);
return (1);
}
break;
}

Expand Down Expand Up @@ -4952,6 +4981,13 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm, struct pfi_kkif *kif,
/* icmp only. type always 0 in other cases */
else if (r->code && r->code != icmpcode + 1)
r = TAILQ_NEXT(r, entries);
/* icmpv6 only. don't create states on replies */
else if (pd->proto == IPPROTO_ICMPV6 &&
r->keep_state && !state_icmp &&
(r->rule_flag & PFRULE_STATESLOPPY) == 0 &&
icmp_dir != PF_IN &&
icmptype != ND_NEIGHBOR_ADVERT)
r = TAILQ_NEXT(r, entries);
else if (r->tos && !(r->tos == pd->tos))
r = TAILQ_NEXT(r, entries);
else if (r->rule_flag & PFRULE_FRAGMENT)
Expand Down

0 comments on commit 2640600

Please sign in to comment.