Re: pf.c: IPv6 Fragmentation Tag Not Cleared after Reassembly
Alexandr Nedvedicky <[email protected]>
| Newsgroups | gmane.os.openbsd.bugs |
|---|---|
| Message-ID | <[email protected]> |
Hello,
I still need to configure wireguard tunnel over IPv6 just to
try it out first so I can understand things better.
to get to this code path one needs to set wg(4) mtu to 9k and try to
send ICMPv6 echo-requests 32k big. then we should get to 'double
fragmentation' path:
32k -> 9k -> ~1.5k (physical ethernet)
receiving reply goes in reverse direction:
ip6_input_if() on ethernet
pf_test(PF_IN, 1.5k)
add PACKET_TAG_PF_REASSEMBLED
reassemble packet to 9k UDP datagram with wg(4) payload
ip_ours()
wg_input()
the PACKET_TAG_PF_REASSEMBLED is left at mbuf
pf_pkt_addr_changed(m)
put packet to wg_deliver_in() task which calls ip6_input_if()
the ip6_input_if() task then does:
pf_test(PF_IN, 9k)
add PACKET_TAG_PF_REASSEMBLED after 9k frags are
reassembled to 32k ICMPv6 fragment. my understanding
is the packet has two PACKET_TAG_PF_REASSEMBLED tags now.
one for ethernet, the other for wireguard.
ip_ours() for local bound packets or ip6_forward() for forwarding
local bound traffic should should be fine here.
it's forwarding case what brings us to code path where we hit
error. for forwarding case the IP stack calls pf_test() again
pf_test(PF_FWD, 32k). the code reaches the area touched by your diff:
8786
8787 #ifdef INET6
8788 /* if reassembled packet passed, create new fragments */
8789 if (pf_status.reass && action == PF_PASS && pd.m && fwdir == PF_FWD &&
8790 pd.af == AF_INET6) {
8791 struct m_tag *mtag;
8792
8793 if ((mtag = m_tag_find(pd.m, PACKET_TAG_PF_REASSEMBLED, NULL)))
8794 action = pf_refragment6(&pd.m, mtag, NULL, NULL, NULL);
8795 }
8796 #endif /* INET6 */
the pf_refragment() creates a chain of brand new packets. the frag sizes
match the MTU of outbound interface.
So this is my understadning. I was trying to think of some observable error.
but apart from having a packet with two REASSEMBLED tags attached I can not
think of anything else that goes wrong here.
I'm more concerned the things may actually break when the tag is deleted
for PF_IN packets. that's just my gut feeling about it.
thanks and
regards
sashan
On Sun, Aug 09, 2026 at 04:35:58PM +0000, Zixu Wu wrote:
</snip>
> diff --git a/sys/net/pf.c b/sys/net/pf.c
> index 0fd00c0dbf3..493b7385730 100644
> --- a/sys/net/pf.c
> +++ b/sys/net/pf.c
> @@ -8785,13 +8785,17 @@ done:
> }
>
> #ifdef INET6
> - /* if reassembled packet passed, create new fragments */
> - if (pf_status.reass && action == PF_PASS && pd.m && fwdir == PF_FWD &&
> - pd.af == AF_INET6) {
> + /* create new fragments if necessary */
> + if (pd.m && pd.af == AF_INET6) {
> struct m_tag *mtag;
>
> - if ((mtag = m_tag_find(pd.m, PACKET_TAG_PF_REASSEMBLED, NULL)))
> - action = pf_refragment6(&pd.m, mtag, NULL, NULL, NULL);
> + if ((mtag = m_tag_find(pd.m, PACKET_TAG_PF_REASSEMBLED, NULL))) {
> + if (action == PF_PASS && fwdir == PF_FWD) {
> + action = pf_refragment6(&pd.m, mtag, NULL, NULL, NULL);
> + } else {
> + m_tag_delete(pd.m, mtag);
> + }
> + }
> }
> #endif /* INET6 */
> if (st && action != PF_DROP) {
>