Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 1 Apr 2015 12:15:01 +0000 (UTC)
From:      Kristof Provost <kp@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r280955 - in head/sys: netinet6 netpfil/pf
Message-ID:  <201504011215.t31CF1wb047368@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kp
Date: Wed Apr  1 12:15:01 2015
New Revision: 280955
URL: https://svnweb.freebsd.org/changeset/base/280955

Log:
  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)

Modified:
  head/sys/netinet6/ip6_output.c
  head/sys/netinet6/ip6_var.h
  head/sys/netpfil/pf/pf_norm.c

Modified: head/sys/netinet6/ip6_output.c
==============================================================================
--- head/sys/netinet6/ip6_output.c	Wed Apr  1 10:10:20 2015	(r280954)
+++ head/sys/netinet6/ip6_output.c	Wed Apr  1 12:15:01 2015	(r280955)
@@ -214,7 +214,7 @@ in6_delayed_cksum(struct mbuf *m, uint32
 
 int
 ip6_fragment(struct ifnet *ifp, struct mbuf *m0, int hlen, u_char nextproto,
-    int mtu)
+    int mtu, uint32_t id)
 {
 	struct mbuf *m, **mnext, *m_frgpart;
 	struct ip6_hdr *ip6, *mhip6;
@@ -222,7 +222,6 @@ ip6_fragment(struct ifnet *ifp, struct m
 	int off;
 	int error;
 	int tlen = m0->m_pkthdr.len;
-	uint32_t id = htonl(ip6_randomid());
 
 	m = m0;
 	ip6 = mtod(m, struct ip6_hdr *);
@@ -318,6 +317,7 @@ ip6_output(struct mbuf *m0, struct ip6_p
 	int needfiblookup;
 	uint32_t fibnum;
 	struct m_tag *fwd_tag = NULL;
+	uint32_t id;
 
 	ip6 = mtod(m, struct ip6_hdr *);
 	if (ip6 == NULL) {
@@ -1010,7 +1010,8 @@ passout:
 		 * chain.
 		 */
 		m0 = m;
-		if ((error = ip6_fragment(ifp, m, hlen, nextproto, len)))
+		id = htonl(ip6_randomid());
+		if ((error = ip6_fragment(ifp, m, hlen, nextproto, len, id)))
 			goto sendorfree;
 
 		in6_ifstat_inc(ifp, ifs6_out_fragok);

Modified: head/sys/netinet6/ip6_var.h
==============================================================================
--- head/sys/netinet6/ip6_var.h	Wed Apr  1 10:10:20 2015	(r280954)
+++ head/sys/netinet6/ip6_var.h	Wed Apr  1 12:15:01 2015	(r280955)
@@ -388,7 +388,8 @@ void	ip6_clearpktopts(struct ip6_pktopts
 struct ip6_pktopts *ip6_copypktopts(struct ip6_pktopts *, int);
 int	ip6_optlen(struct inpcb *);
 int	ip6_deletefraghdr(struct mbuf *, int, int);
-int	ip6_fragment(struct ifnet *, struct mbuf *, int, u_char, int);
+int	ip6_fragment(struct ifnet *, struct mbuf *, int, u_char, int,
+			uint32_t);
 
 int	route6_input(struct mbuf **, int *, int);
 

Modified: head/sys/netpfil/pf/pf_norm.c
==============================================================================
--- head/sys/netpfil/pf/pf_norm.c	Wed Apr  1 10:10:20 2015	(r280954)
+++ head/sys/netpfil/pf/pf_norm.c	Wed Apr  1 12:15:01 2015	(r280955)
@@ -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 
 	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 
 	/* 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 
 	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
 	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
 	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
 	 * 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) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201504011215.t31CF1wb047368>