summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/frag6.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet6/frag6.c')
-rw-r--r--sys/netinet6/frag6.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/sys/netinet6/frag6.c b/sys/netinet6/frag6.c
index 3bb425f..f8a86a1 100644
--- a/sys/netinet6/frag6.c
+++ b/sys/netinet6/frag6.c
@@ -52,6 +52,8 @@
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet/icmp6.h>
+#include <netinet/in_systm.h> /* for ECN definitions */
+#include <netinet/ip.h> /* for ECN definitions */
#include <net/net_osdep.h>
@@ -151,6 +153,7 @@ frag6_input(mp, offp, proto)
int first_frag = 0;
int fragoff, frgpartlen; /* must be larger than u_int16_t */
struct ifnet *dstifp;
+ u_int8_t ecn, ecn0;
ip6 = mtod(m, struct ip6_hdr *);
#ifndef PULLDOWN_TEST
@@ -350,6 +353,26 @@ frag6_input(mp, offp, proto)
}
/*
+ * Handle ECN by comparing this segment with the first one;
+ * if CE is set, do not lose CE.
+ * drop if CE and not-ECT are mixed for the same packet.
+ */
+ ecn = (ntohl(ip6->ip6_flow) >> 20) & IPTOS_ECN_MASK;
+ ecn0 = (ntohl(q6->ip6q_down->ip6af_head) >> 20) & IPTOS_ECN_MASK;
+ if (ecn == IPTOS_ECN_CE) {
+ if (ecn0 == IPTOS_ECN_NOTECT) {
+ free(ip6af, M_FTABLE);
+ goto dropfrag;
+ }
+ if (ecn0 != IPTOS_ECN_CE)
+ q6->ip6q_down->ip6af_head |= htonl(IPTOS_ECN_CE << 20);
+ }
+ if (ecn == IPTOS_ECN_NOTECT && ecn0 != IPTOS_ECN_NOTECT) {
+ free(ip6af, M_FTABLE);
+ goto dropfrag;
+ }
+
+ /*
* Find a segment which begins after this one does.
*/
for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
OpenPOWER on IntegriCloud