summaryrefslogtreecommitdiffstats
path: root/sys/netpfil/pf
diff options
context:
space:
mode:
authorkp <kp@FreeBSD.org>2015-04-01 12:15:01 +0000
committerkp <kp@FreeBSD.org>2015-04-01 12:15:01 +0000
commit86dedea3cb2f1216f9d21e55b1629038953fca9e (patch)
tree5958ad86bcc7cef1c3634d230c9c64ff720034f9 /sys/netpfil/pf
parentd8765deb30b50b6fdaa4638600d115adcdb092d3 (diff)
downloadFreeBSD-src-86dedea3cb2f1216f9d21e55b1629038953fca9e.zip
FreeBSD-src-86dedea3cb2f1216f9d21e55b1629038953fca9e.tar.gz
Preserve IPv6 fragment IDs accross reassembly and refragmentation
When forwarding fragmented IPv6 packets and filtering with PF we reassemble and refragment. That means we generate new fragment headers and a new fragment ID. We already save the fragment IDs so we can do the reassembly so it's straightforward to apply the incoming fragment ID on the refragmented packets. Differential Revision: https://reviews.freebsd.org/D2188 Approved by: gnn (mentor)
Diffstat (limited to 'sys/netpfil/pf')
-rw-r--r--sys/netpfil/pf/pf_norm.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/sys/netpfil/pf/pf_norm.c b/sys/netpfil/pf/pf_norm.c
index 36b33c2..8aaca93 100644
--- a/sys/netpfil/pf/pf_norm.c
+++ b/sys/netpfil/pf/pf_norm.c
@@ -104,6 +104,7 @@ struct pf_fragment_tag {
uint16_t ft_hdrlen; /* header length of reassembled pkt */
uint16_t ft_extoff; /* last extension header offset or 0 */
uint16_t ft_maxlen; /* maximum fragment payload length */
+ uint32_t ft_id; /* fragment id */
};
static struct mtx pf_frag_mtx;
@@ -673,6 +674,7 @@ pf_reassemble6(struct mbuf **m0, struct ip6_hdr *ip6, struct ip6_frag *fraghdr,
struct m_tag *mtag;
struct pf_fragment_tag *ftag;
int off;
+ uint32_t frag_id;
uint16_t total, maxlen;
uint8_t proto;
@@ -715,6 +717,7 @@ pf_reassemble6(struct mbuf **m0, struct ip6_hdr *ip6, struct ip6_frag *fraghdr,
/* We have all the data. */
extoff = frent->fe_extoff;
maxlen = frag->fr_maxlen;
+ frag_id = frag->fr_id;
frent = TAILQ_FIRST(&frag->fr_queue);
KASSERT(frent != NULL, ("frent != NULL"));
total = TAILQ_LAST(&frag->fr_queue, pf_fragq)->fe_off +
@@ -751,6 +754,7 @@ pf_reassemble6(struct mbuf **m0, struct ip6_hdr *ip6, struct ip6_frag *fraghdr,
ftag->ft_hdrlen = hdrlen;
ftag->ft_extoff = extoff;
ftag->ft_maxlen = maxlen;
+ ftag->ft_id = frag_id;
m_tag_prepend(m, mtag);
ip6 = mtod(m, struct ip6_hdr *);
@@ -1094,6 +1098,7 @@ pf_refragment6(struct ifnet *ifp, struct mbuf **m0, struct m_tag *mtag)
struct mbuf *m = *m0, *t;
struct pf_fragment_tag *ftag = (struct pf_fragment_tag *)(mtag + 1);
struct pf_pdesc pd;
+ uint32_t frag_id;
uint16_t hdrlen, extoff, maxlen;
uint8_t proto;
int error, action;
@@ -1101,6 +1106,7 @@ pf_refragment6(struct ifnet *ifp, struct mbuf **m0, struct m_tag *mtag)
hdrlen = ftag->ft_hdrlen;
extoff = ftag->ft_extoff;
maxlen = ftag->ft_maxlen;
+ frag_id = ftag->ft_id;
m_tag_delete(m, mtag);
mtag = NULL;
ftag = NULL;
@@ -1130,7 +1136,7 @@ pf_refragment6(struct ifnet *ifp, struct mbuf **m0, struct m_tag *mtag)
* is less than 8, ip6_fragment() will return EMSGSIZE and
* we drop the packet.
*/
- error = ip6_fragment(ifp, m, hdrlen, proto, maxlen);
+ error = ip6_fragment(ifp, m, hdrlen, proto, maxlen, frag_id);
m = (*m0)->m_nextpkt;
(*m0)->m_nextpkt = NULL;
if (error == 0) {
OpenPOWER on IntegriCloud