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)
This commit is contained in:
parent
63f13cedca
commit
798318490e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=280955
@ -214,7 +214,7 @@ in6_delayed_cksum(struct mbuf *m, uint32_t plen, u_short offset)
|
||||
|
||||
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 mbuf *m0, int hlen, u_char nextproto,
|
||||
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_pktopts *opt,
|
||||
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 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
|
||||
* 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);
|
||||
|
@ -388,7 +388,8 @@ void ip6_clearpktopts(struct ip6_pktopts *, int);
|
||||
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);
|
||||
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user