Currently, the IPv6 fragmentation tag is not cleared after reassembly
unless as part of refragmentation when direction is `PF_FWD`. As a
result, `PF_IN` packets handled by if_wg.c retain the fragmentation tag
even after the encapsulation is removed, as long as the outer
encapsulation was originally fragmented. pf.c will then fragment the
encapsulated inner packets under the false belief that it had previously
reassembled them. This behavior is incorrect, so is the MTU calculation
during refragmentation in such case.
The proposed fix proactively removes the fragmentation tag if
refragmentation is deemed unnecessary. It also removes the check
condition on `pf_status.reass` as it should have no bearing on whether
packets previously reassembled need to be refragmented.
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) {