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) {
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to