Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F3662656
Masterwork From Distant Lands
No One
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
thj
Aug 19 2018, 6:31 PM
2018-08-19 18:31:34 (UTC+0)
Size
4 KB
Referenced Files
None
Subscribers
None
Masterwork From Distant Lands
View Options
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 *);
File Metadata
Details
Attached
Mime Type
text/plain; charset=utf-8
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1529467
Default Alt Text
Masterwork From Distant Lands (4 KB)
Attached To
Mode
P212 Masterwork From Distant Lands
Attached
Detach File
Event Timeline
Log In to Comment