Page MenuHomeFreeBSD

D1767.id3714.vs3621.diff
No OneTemporary

D1767.id3714.vs3621.diff

Index: sys/net/pfvar.h
===================================================================
--- sys/net/pfvar.h
+++ sys/net/pfvar.h
@@ -1588,6 +1588,7 @@
int pf_match_port(u_int8_t, u_int16_t, u_int16_t, u_int16_t);
void pf_normalize_init(void);
+int pf_refragment6(struct ifnet *, struct mbuf **, struct m_tag *mtag);
void pf_normalize_cleanup(void);
int pf_normalize_ip(struct mbuf **, int, struct pfi_kif *, u_short *,
struct pf_pdesc *);
Index: sys/netpfil/pf/pf.h
===================================================================
--- sys/netpfil/pf/pf.h
+++ sys/netpfil/pf/pf.h
@@ -43,7 +43,7 @@
#endif
#endif
-enum { PF_INOUT, PF_IN, PF_OUT };
+enum { PF_INOUT, PF_IN, PF_OUT, PF_FWD };
enum { PF_PASS, PF_DROP, PF_SCRUB, PF_NOSCRUB, PF_NAT, PF_NONAT,
PF_BINAT, PF_NOBINAT, PF_RDR, PF_NORDR, PF_SYNPROXY_DROP, PF_DEFER };
enum { PF_RULESET_SCRUB, PF_RULESET_FILTER, PF_RULESET_NAT,
Index: sys/netpfil/pf/pf.c
===================================================================
--- sys/netpfil/pf/pf.c
+++ sys/netpfil/pf/pf.c
@@ -5496,7 +5496,7 @@
goto bad;
if (oifp != ifp) {
- if (pf_test6(PF_OUT, ifp, &m0, NULL) != PF_PASS)
+ if (pf_test6(PF_FWD, ifp, &m0, NULL) != PF_PASS)
goto bad;
else if (m0 == NULL)
goto done;
@@ -6054,15 +6054,21 @@
struct pfi_kif *kif;
u_short action, reason = 0, log = 0;
struct mbuf *m = *m0, *n = NULL;
+ struct m_tag *mtag;
struct ip6_hdr *h = NULL;
struct pf_rule *a = NULL, *r = &V_pf_default_rule, *tr, *nr;
struct pf_state *s = NULL;
struct pf_ruleset *ruleset = NULL;
struct pf_pdesc pd;
int off, terminal = 0, dirndx, rh_cnt = 0;
+ int fwdir = dir;
+
M_ASSERTPKTHDR(m);
+ if (ifp != m->m_pkthdr.rcvif)
+ fwdir = PF_FWD;
+
if (!V_pf_status.running)
return (PF_PASS);
@@ -6424,6 +6430,11 @@
if (s)
PF_STATE_UNLOCK(s);
+ /* if reassembled packet passed, create new fragments */
+ if (action == PF_PASS && *m0 && fwdir == PF_FWD &&
+ (mtag = m_tag_find(m, PACKET_TAG_PF_REASSEMBLED, NULL)) != NULL)
+ action = pf_refragment6(ifp, m0, mtag);
+
return (action);
}
#endif /* INET6 */
Index: sys/netpfil/pf/pf_mtag.h
===================================================================
--- sys/netpfil/pf/pf_mtag.h
+++ sys/netpfil/pf/pf_mtag.h
@@ -39,6 +39,7 @@
#define PF_TAG_TRANSLATE_LOCALHOST 0x04
#define PF_PACKET_LOOPED 0x08
#define PF_FASTFWD_OURS_PRESENT 0x10
+#define PACKET_TAG_PF_REASSEMBLED 0x20 /* pf reassembled ipv6 packet */
struct pf_mtag {
void *hdr; /* saved hdr pos in mbuf, for ECN */
Index: sys/netpfil/pf/pf_norm.c
===================================================================
--- sys/netpfil/pf/pf_norm.c
+++ sys/netpfil/pf/pf_norm.c
@@ -675,6 +675,8 @@
struct pf_frent *frent;
struct pf_fragment *frag;
struct pf_fragment_cmp key;
+ struct m_tag *mtag;
+ struct pf_fragment_tag *ftag;
int off;
u_int16_t total, maxlen;
u_int8_t proto;
@@ -748,6 +750,15 @@
m->m_pkthdr.len = plen;
}
+ if ((mtag = m_tag_get(PACKET_TAG_PF_REASSEMBLED, sizeof(struct
+ pf_fragment_tag), M_NOWAIT)) == NULL)
+ goto fail;
+ ftag = (struct pf_fragment_tag *)(mtag + 1);
+ ftag->ft_hdrlen = hdrlen;
+ ftag->ft_extoff = extoff;
+ ftag->ft_maxlen = maxlen;
+ m_tag_prepend(m, mtag);
+
ip6 = mtod(m, struct ip6_hdr *);
ip6->ip6_plen = htons(hdrlen - sizeof(struct ip6_hdr) + total);
if (extoff) {
@@ -1082,6 +1093,76 @@
}
int
+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;
+ u_int16_t hdrlen, extoff, maxlen;
+ u_int8_t proto;
+ int error, action;
+
+ hdrlen = ftag->ft_hdrlen;
+ extoff = ftag->ft_extoff;
+ maxlen = ftag->ft_maxlen;
+ m_tag_delete(m, mtag);
+ mtag = NULL;
+ ftag = NULL;
+
+ if (extoff) {
+ int off;
+
+ /* Use protocol from next field of last extension header */
+ if ((m = m_getptr(m, extoff + offsetof(struct ip6_ext,
+ ip6e_nxt), &off)) == NULL)
+ panic("pf_refragment6: short mbuf chain");
+ proto = *(mtod(m, caddr_t) + off);
+ *(mtod(m, caddr_t) + off) = IPPROTO_FRAGMENT;
+ m = *m0;
+ } else {
+ struct ip6_hdr *hdr;
+
+ hdr = mtod(m, struct ip6_hdr *);
+ proto = hdr->ip6_nxt;
+ hdr->ip6_nxt = IPPROTO_FRAGMENT;
+ }
+
+ /*
+ * Maxlen may be less than 8 iff there was only a single
+ * fragment. As it was fragmented before, add a fragment
+ * header also for a single fragment. If total or maxlen
+ * is less than 8, ip6_fragment() will return EMSGSIZE and
+ * we drop the packet.
+ */
+
+ error = ip6_fragment(ifp, m, hdrlen, proto, maxlen);
+ m = (*m0)->m_nextpkt;
+ (*m0)->m_nextpkt = NULL;
+ if (error == 0) {
+ /* The first mbuf contains the unfragmented packet */
+ m_freem(*m0);
+ *m0 = NULL;
+ action = PF_PASS;
+ } else {
+ /* Drop expects an mbuf to free */
+ DPFPRINTF(("refragment error %d", error));
+ action = PF_DROP;
+ }
+ for (t = m; m; m = t) {
+ t = m->m_nextpkt;
+ m->m_nextpkt = NULL;
+ memset(&pd, 0, sizeof(pd));
+ pd.pf_mtag = pf_find_mtag(m);
+ if (error == 0)
+ ip6_forward(m, 0);
+ else
+ m_freem(m);
+ }
+
+ return (action);
+}
+
+int
pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
struct pf_pdesc *pd)
{

File Metadata

Mime Type
text/plain
Expires
Sat, Jan 24, 8:20 AM (6 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27895205
Default Alt Text
D1767.id3714.vs3621.diff (5 KB)

Event Timeline