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) {

Reply via email to