Page MenuHomeFreeBSD
Paste P212

Masterwork From Distant Lands
ActivePublic

Authored by thj on Aug 19 2018, 6:31 PM.
diff --git a/sys/netinet6/frag6.c b/sys/netinet6/frag6.c
index 26a10c673ab..4a4e28120be 100644
--- a/sys/netinet6/frag6.c
+++ b/sys/netinet6/frag6.c
@@ -495,11 +495,15 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
#endif
/*
- * If first fragment doesn't have the entire header chain drop it per
- * rfc7112.
+ * If first fragment doesn't have a full header chain drop it.
+ * RFC7112:
+ * "When a host fragments an IPv6 datagram, it MUST include the entire
+ * IPv6 Header Chain in the First Fragment."
*/
- if (first_frag && !validhdrchain(m))
+ if (first_frag && !ip6_validhdrchain(m, *offp, proto)) {
+ printf("%s: invalid hdr chain on first frag dropping\n", __func__);
goto dropfrag;
+ }
/*
* Stick new segment in its place;
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index 87788cb3b6d..1a4883453ad 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -124,6 +124,12 @@ __FBSDID("$FreeBSD$");
#include <netinet6/ip6protosw.h>
+#include <netinet/icmp6.h>
+#include <netinet/tcp.h>
+#include <netinet/sctp.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
extern struct domain inet6domain;
u_char ip6_protox[IPPROTO_MAX];
@@ -1848,6 +1854,96 @@ ip6_lasthdr(const struct mbuf *m, int off, int proto, int *nxtp)
}
}
+/*
+ * walk header chain and search for an upper layer header
+ */
+int
+ip6_validhdrchain(const struct mbuf *m, int off, int proto)
+{
+ int newoff;
+ int nxt;
+ int *nxtp = NULL;
+
+ if (!nxtp) {
+ nxt = -1;
+ nxtp = &nxt;
+ }
+ printf("%s: at start proto %d off %d\n", __func__, proto, off);
+ while (1) {
+ newoff = ip6_nexthdr(m, off, proto, nxtp);
+ printf("%s: nxthdr %d newoff %d\n", __func__, *nxtp, newoff);
+
+ /* If we are at the end, stop */
+ if (newoff < 0)
+ return 0;
+ else if (newoff < off)
+ return 0; /* invalid */
+ else if (newoff == off)
+ return 0;
+
+ off = newoff;
+ proto = *nxtp;
+
+ printf("%s: header proto is: %d\n", __func__, proto);
+ printf("%s: m_pkthdr.len %d off %d pkthdr - off %d\n", __func__,
+ m->m_pkthdr.len, off, m->m_pkthdr.len - off);
+
+ //int remaining = m->m_pkthdr.len - off;
+
+ NOW WRITE TESTS FOR EACH OF THESE CASE
+
+ switch (proto) {
+ case IPPROTO_UDP:
+ case IPPROTO_UDPLITE:
+ if (m->m_pkthdr.len < (off + sizeof(struct udphdr))) {
+ printf("%s: UDP(-lite) not enough upper layer header\n", __func__);
+ return 0;
+ }
+ printf("%s: UDP(-lite) enough upper layer header\n", __func__);
+ return 1;
+ case IPPROTO_TCP:
+ if (m->m_pkthdr.len < (off + TCP_MAXHLEN)) {
+ printf("%s: TCP not enough upper layer header\n", __func__);
+ return 0;
+ }
+ printf("%s: TCP enough upper layer header\n", __func__);
+ return 1;
+ case IPPROTO_SCTP:
+ if (m->m_pkthdr.len < (off + sizeof(struct sctphdr))) {
+ printf("%s: SCTP not enough upper layer header\n", __func__);
+ return 0;
+ }
+ printf("%s: SCTP enough upper layer header\n", __func__);
+ return 1;
+ case IPPROTO_ICMPV6:
+ if (m->m_pkthdr.len < (off + sizeof(struct icmp6_hdr))) {
+ printf("%s: ICMPv6 not enough upper layer header\n", __func__);
+ return 0;
+ }
+ printf("%s: ICMPv6 enough upper layer header\n", __func__);
+ return 1;
+ case IPPROTO_IPV6:
+ if (m->m_pkthdr.len < (off + sizeof(struct ip6_hdr))) {
+ printf("%s: IP6 not enough upper layer header (IP in IP)\n", __func__);
+ return 0;
+ }
+ printf("%s: IP enough upper layer header\n", __func__);
+ return 1;
+ case IPPROTO_ESP:
+ if (m->m_pkthdr.len < (off + sizeof(uint32_t))) {
+ printf("%s: ESP not enough upper layer header\n", __func__);
+ return 0;
+ }
+ printf("%s: ESP enough upper layer header\n", __func__);
+ return 1;
+ default:
+ /* Unknown upper layer header error */
+ printf("%s: unknown value, continuing\n", __func__);
+ }
+ }
+ return 0;
+}
+
/*
* System control for IP6
*/
diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h
index 74b5f89cf1f..ef99c006ffc 100644
--- a/sys/netinet6/ip6_var.h
+++ b/sys/netinet6/ip6_var.h
@@ -370,6 +370,7 @@ int ip6_unknown_opt(u_int8_t *, struct mbuf *, int);
int ip6_get_prevhdr(const struct mbuf *, int);
int ip6_nexthdr(const struct mbuf *, int, int, int *);
int ip6_lasthdr(const struct mbuf *, int, int, int *);
+int ip6_validhdrchain(const struct mbuf *, int, int);
extern int (*ip6_mforward)(struct ip6_hdr *, struct ifnet *,
struct mbuf *);

Event Timeline

thj edited the content of this paste. (Show Details)Aug 19 2018, 6:31 PM
thj changed the title of this paste from untitled to Masterwork From Distant Lands.