git: 80e76c61ccc4 - main - pf: set scope in pf_refragment6()

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Thu, 16 Mar 2023 10:01:25 UTC
The branch main has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=80e76c61ccc47651ca1be34b912d53536db34e6f

commit 80e76c61ccc47651ca1be34b912d53536db34e6f
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2023-03-13 09:27:59 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2023-03-16 09:59:04 +0000

    pf: set scope in pf_refragment6()
    
    Link-local traffic needs to have a scope embedded before it's passed on
    to ip6_output(). Do so in pf_refragment6(), because when we end up here
    in the output path we may have passed through ip6_output() already
    (before being reassembled), where the scope would have been removed.
    
    Re-embed the scope so that link-local traffic is sent correctly.
    
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D39062
---
 sys/netpfil/pf/pf_norm.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/sys/netpfil/pf/pf_norm.c b/sys/netpfil/pf/pf_norm.c
index bc5f6d38a2bf..8d36e72d71b2 100644
--- a/sys/netpfil/pf/pf_norm.c
+++ b/sys/netpfil/pf/pf_norm.c
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
 #include <netinet/ip.h>
 #include <netinet/ip_var.h>
 #include <netinet6/ip6_var.h>
+#include <netinet6/scope6_var.h>
 #include <netinet/tcp.h>
 #include <netinet/tcp_fsm.h>
 #include <netinet/tcp_seq.h>
@@ -946,6 +947,7 @@ pf_refragment6(struct ifnet *ifp, struct mbuf **m0, struct m_tag *mtag,
     bool forward)
 {
 	struct mbuf		*m = *m0, *t;
+	struct ip6_hdr		*hdr;
 	struct pf_fragment_tag	*ftag = (struct pf_fragment_tag *)(mtag + 1);
 	struct pf_pdesc		 pd;
 	uint32_t		 frag_id;
@@ -972,13 +974,17 @@ pf_refragment6(struct ifnet *ifp, struct mbuf **m0, struct m_tag *mtag,
 		*(mtod(m, char *) + off) = IPPROTO_FRAGMENT;
 		m = *m0;
 	} else {
-		struct ip6_hdr *hdr;
-
 		hdr = mtod(m, struct ip6_hdr *);
 		proto = hdr->ip6_nxt;
 		hdr->ip6_nxt = IPPROTO_FRAGMENT;
 	}
 
+	/* In case of link-local traffic we'll need a scope set. */
+	hdr = mtod(m, struct ip6_hdr *);
+
+	in6_setscope(&hdr->ip6_src, ifp, NULL);
+	in6_setscope(&hdr->ip6_dst, ifp, NULL);
+
 	/* The MTU must be a multiple of 8 bytes, or we risk doing the
 	 * fragmentation wrong. */
 	maxlen = maxlen & ~7;