svn commit: r284572 - in stable/10/sys: netinet6 netpfil/pf

Kristof Provost kp at FreeBSD.org
Thu Jun 18 20:40:38 UTC 2015


Author: kp
Date: Thu Jun 18 20:40:36 2015
New Revision: 284572
URL: https://svnweb.freebsd.org/changeset/base/284572

Log:
  Merge r280955
  
  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/D2817
  Reviewed by:	gnn

Modified:
  stable/10/sys/netinet6/ip6_output.c
  stable/10/sys/netinet6/ip6_var.h
  stable/10/sys/netpfil/pf/pf_norm.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/netinet6/ip6_output.c
==============================================================================
--- stable/10/sys/netinet6/ip6_output.c	Thu Jun 18 20:34:39 2015	(r284571)
+++ stable/10/sys/netinet6/ip6_output.c	Thu Jun 18 20:40:36 2015	(r284572)
@@ -210,7 +210,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;
@@ -218,7 +218,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 *);
@@ -309,6 +308,7 @@ ip6_output(struct mbuf *m0, struct ip6_p
 	int hdrsplit = 0;
 	int sw_csum, tso;
 	struct m_tag *fwd_tag = NULL;
+	uint32_t id;
 
 	ip6 = mtod(m, struct ip6_hdr *);
 	if (ip6 == NULL) {
@@ -996,7 +996,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: stable/10/sys/netinet6/ip6_var.h
==============================================================================
--- stable/10/sys/netinet6/ip6_var.h	Thu Jun 18 20:34:39 2015	(r284571)
+++ stable/10/sys/netinet6/ip6_var.h	Thu Jun 18 20:40:36 2015	(r284572)
@@ -426,7 +426,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: stable/10/sys/netpfil/pf/pf_norm.c
==============================================================================
--- stable/10/sys/netpfil/pf/pf_norm.c	Thu Jun 18 20:34:39 2015	(r284571)
+++ stable/10/sys/netpfil/pf/pf_norm.c	Thu Jun 18 20:40:36 2015	(r284572)
@@ -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;
@@ -681,6 +682,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;
 
@@ -723,6 +725,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 +
@@ -759,6 +762,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 *);
@@ -1100,6 +1104,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;
@@ -1107,6 +1112,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;
@@ -1136,7 +1142,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) {


More information about the svn-src-all mailing list