Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F140175455
D53516.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D53516.diff
View Options
diff --git a/sys/netinet/ip_ecn.h b/sys/netinet/ip_ecn.h
--- a/sys/netinet/ip_ecn.h
+++ b/sys/netinet/ip_ecn.h
@@ -31,20 +31,25 @@
* SUCH DAMAGE.
*
*/
-/*
- * ECN consideration on tunnel ingress/egress operation.
- * http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt
- */
#ifndef _NETINET_IP_ECN_H_
#define _NETINET_IP_ECN_H_
-#define ECN_ALLOWED 1 /* ECN allowed */
-#define ECN_FORBIDDEN 0 /* ECN forbidden */
+#ifndef _KERNEL
+#error "no user-serviceable parts inside"
+#endif
+
+#define ECN_COMPLETE 2 /* ECN normal mode with security log */
+#define ECN_ALLOWED 1 /* ECN normal mode */
+#define ECN_FORBIDDEN 0 /* ECN compatibility mode */
#define ECN_NOCARE (-1) /* no consideration to ECN */
-#ifdef _KERNEL
+/* ip[6]_ecn_egress return values */
+#define ECN_DROP 0 /* caller MUST drop the packet */
+#define ECN_SUCCESS 1 /* success */
+#define ECN_WARN 2 /* caller MAY log */
+#define ECN_ALARM 3 /* caller SHOULD log and MAY raise alarm */
+
extern void ip_ecn_ingress(int, uint8_t *, const uint8_t *);
extern int ip_ecn_egress(int, const uint8_t *, uint8_t *);
#endif
-#endif
diff --git a/sys/netinet/ip_ecn.c b/sys/netinet/ip_ecn.c
--- a/sys/netinet/ip_ecn.c
+++ b/sys/netinet/ip_ecn.c
@@ -31,10 +31,6 @@
* SUCH DAMAGE.
*
*/
-/*
- * ECN consideration on tunnel ingress/egress operation.
- * http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt
- */
#include <sys/cdefs.h>
#include "opt_inet.h"
@@ -59,7 +55,7 @@
/*
* ECN and TOS (or TCLASS) processing rules at tunnel encapsulation and
- * decapsulation from RFC3168:
+ * decapsulation from RFC6040:
*
* Outer Hdr at Inner Hdr at
* Encapsulator Decapsulator
@@ -67,18 +63,42 @@
* DS Field copied from inner hdr no change
* ECN Field constructed by (I) constructed by (E)
*
- * ECN_ALLOWED (full functionality):
- * (I) if the ECN field in the inner header is set to CE, then set the
- * ECN field in the outer header to ECT(0).
- * otherwise, copy the ECN field to the outer header.
+ * ECN_ALLOWED (normal mode):
+ * (I) copy the ECN field to the outer header.
*
* (E) if the ECN field in the outer header is set to CE and the ECN
* field of the inner header is not-ECT, drop the packet.
- * if the ECN field in the inner header is set to ECT(0) or ECT(1)
- * and the ECN field in the outer header is set to CE, then copy CE to
- * the inner header. otherwise, make no change to the inner header.
+ * If the ECN field in the inner header is set to ECT(0) and the ECN
+ * field in the outer header is set to ECT(1), copy ECT(1) to
+ * the inner header. If the ECN field in the inner header is set
+ * to ECT(0) or ECT(1) and the ECN field in the outer header is set to
+ * CE, copy CE to the inner header.
+ * Otherwise, make no change to the inner header. This behaviour can be
+ * summarized in the table below:
+ *
+ * Outer Header at Decapsulator
+ * +---------+------------+------------+------------+
+ * | Not-ECT | ECT(0) | ECT(1) | CE |
+ * Inner Hdr: +---------+------------+------------+------------+
+ * Not-ECT | Not-ECT |Not-ECT(!!!)|Not-ECT(!!!)| <drop>(!!!)|
+ * ECT(0) | ECT(0) | ECT(0) | ECT(1) | CE |
+ * ECT(1) | ECT(1) | ECT(1) (!) | ECT(1) | CE |
+ * CE | CE | CE | CE(!!!)| CE |
+ * +---------+------------+------------+------------+
+ *
+ * ECN_COMPLETE (normal mode with security log):
+ * certain combinations indicated in table by '(!!!)' or '(!)',
+ * where '(!!!)' means the combination always potentially dangerous which
+ * returns 3, while '(!)' means possibly dangerous in which returns 2.
+ * These combinations are unsed by previous ECN tunneling specifications
+ * and could be logged. Also, in case of more dangerous ones, the
+ * decapsulator SHOULD log the event and MAY also raise an alarm.
+ *
+ * Note: Caller SHOULD use rate-limited alarms so that the anomalous
+ * combinations will not amplify into a flood of alarm messages.
+ * Also, it MUST be possible to suppress alarms or logging.
*
- * ECN_FORBIDDEN (limited functionality):
+ * ECN_FORBIDDEN (compatibility mode):
* (I) set the ECN field to not-ECT in the outer header.
*
* (E) if the ECN field in the outer header is set to CE, drop the packet.
@@ -95,26 +115,22 @@
ip_ecn_ingress(int mode, uint8_t *outer, const uint8_t *inner)
{
- if (!outer || !inner)
- panic("NULL pointer passed to ip_ecn_ingress");
+ KASSERT(outer != NULL && inner != NULL,
+ "NULL pointer passed to ip_ecn_ingress");
*outer = *inner;
switch (mode) {
- case ECN_ALLOWED: /* ECN allowed */
- /*
- * full-functionality: if the inner is CE, set ECT(0)
- * to the outer. otherwise, copy the ECN field.
- */
- if ((*inner & IPTOS_ECN_MASK) == IPTOS_ECN_CE)
- *outer &= ~IPTOS_ECN_ECT1;
+ case ECN_COMPLETE:
+ case ECN_ALLOWED:
+ /* normal mode: always copy the ECN field. */
break;
- case ECN_FORBIDDEN: /* ECN forbidden */
- /*
- * limited-functionality: set not-ECT to the outer
- */
+
+ case ECN_FORBIDDEN:
+ /* compatibility mode: set not-ECT to the outer */
*outer &= ~IPTOS_ECN_MASK;
break;
- case ECN_NOCARE: /* no consideration to ECN */
+
+ case ECN_NOCARE:
break;
}
}
@@ -127,33 +143,57 @@
ip_ecn_egress(int mode, const uint8_t *outer, uint8_t *inner)
{
- if (!outer || !inner)
- panic("NULL pointer passed to ip_ecn_egress");
+ KASSERT(outer != NULL && inner != NULL,
+ "NULL pointer passed to ip_ecn_egress");
switch (mode) {
+ case ECN_COMPLETE:
+ if ((*outer & IPTOS_ECN_MASK) == IPTOS_ECN_ECT0) {
+ /* if the outer is ECT(0) and inner is ECT(1) raise a warning */
+ if ((*inner & IPTOS_ECN_MASK) == IPTOS_ECN_ECT1)
+ return (ECN_WARN);
+ /* if the inner is not-ECT and outer is ECT(0) raise an alarm */
+ if ((*inner & IPTOS_ECN_MASK) == IPTOS_ECN_NOTECT)
+ return (ECN_ALARM);
+ return (ECN_SUCCESS);
+ } else if ((*outer & IPTOS_ECN_MASK) == IPTOS_ECN_ECT1) {
+ /* if the outer is ECT(1) and inner is CE or ECT(1), raise an alarm */
+ if (((*inner & IPTOS_ECN_MASK) == IPTOS_ECN_CE) ||
+ ((*inner & IPTOS_ECN_MASK) == IPTOS_ECN_NOTECT))
+ return (ECN_ALARM);
+ /* if the outer is ECT(1) and inner is ECT(0), copy ECT(1) */
+ if ((*inner & IPTOS_ECN_MASK) == IPTOS_ECN_ECT0)
+ *inner = IPTOS_ECN_ECT1;
+ return (ECN_SUCCESS);
+ }
+ /* fallthrough */
case ECN_ALLOWED:
- /*
- * full-functionality: if the outer is CE and the inner is
- * not-ECT, should drop it. otherwise, copy CE.
- */
if ((*outer & IPTOS_ECN_MASK) == IPTOS_ECN_CE) {
+ /* if the outer is CE and the inner is not-ECT, drop it. */
if ((*inner & IPTOS_ECN_MASK) == IPTOS_ECN_NOTECT)
- return (0);
+ return (ECN_DROP);
+ /* otherwise, copy CE */
*inner |= IPTOS_ECN_CE;
+ } else if ((*outer & IPTOS_ECN_MASK) == IPTOS_ECN_ECT1) {
+ /* if the outer is ECT(1) and inner is ECT(0), copy ECT(1) */
+ if ((*inner & IPTOS_ECN_MASK) == IPTOS_ECN_ECT0)
+ *inner = IPTOS_ECN_ECT1;
}
break;
- case ECN_FORBIDDEN: /* ECN forbidden */
+
+ case ECN_FORBIDDEN:
/*
- * limited-functionality: if the outer is CE, should drop it.
+ * compatibility mode: if the outer is CE, should drop it.
* otherwise, leave the inner.
*/
if ((*outer & IPTOS_ECN_MASK) == IPTOS_ECN_CE)
- return (0);
+ return (ECN_DROP);
break;
- case ECN_NOCARE: /* no consideration to ECN */
+
+ case ECN_NOCARE:
break;
}
- return (1);
+ return (ECN_SUCCESS);
}
#ifdef INET6
@@ -162,31 +202,34 @@
{
uint8_t outer8, inner8;
- if (!outer || !inner)
- panic("NULL pointer passed to ip6_ecn_ingress");
+ KASSERT(outer != NULL && inner != NULL,
+ "NULL pointer passed to ip6_ecn_ingress");
- inner8 = (ntohl(*inner) >> 20) & 0xff;
+ inner8 = (ntohl(*inner) >> IPV6_FLOWLABEL_LEN) & 0xff;
ip_ecn_ingress(mode, &outer8, &inner8);
- *outer &= ~htonl(0xff << 20);
- *outer |= htonl((uint32_t)outer8 << 20);
+ *outer &= ~htonl(0xff << IPV6_FLOWLABEL_LEN);
+ *outer |= htonl((uint32_t)outer8 << IPV6_FLOWLABEL_LEN);
}
int
ip6_ecn_egress(int mode, const uint32_t *outer, uint32_t *inner)
{
uint8_t outer8, inner8, oinner8;
+ int ret;
+
+ KASSERT(outer != NULL && inner != NULL,
+ "NULL pointer passed to ip6_ecn_egress");
- if (!outer || !inner)
- panic("NULL pointer passed to ip6_ecn_egress");
+ outer8 = (ntohl(*outer) >> IPV6_FLOWLABEL_LEN) & 0xff;
+ inner8 = oinner8 = (ntohl(*inner) >> IPV6_FLOWLABEL_LEN) & 0xff;
- outer8 = (ntohl(*outer) >> 20) & 0xff;
- inner8 = oinner8 = (ntohl(*inner) >> 20) & 0xff;
- if (ip_ecn_egress(mode, &outer8, &inner8) == 0)
- return (0);
+ ret = ip_ecn_egress(mode, &outer8, &inner8);
+ if (ret == ECN_DROP)
+ return (ECN_DROP);
if (inner8 != oinner8) {
- *inner &= ~htonl(0xff << 20);
- *inner |= htonl((uint32_t)inner8 << 20);
+ *inner &= ~htonl(0xff << IPV6_FLOWLABEL_LEN);
+ *inner |= htonl((uint32_t)inner8 << IPV6_FLOWLABEL_LEN);
}
- return (1);
+ return (ret);
}
#endif
diff --git a/sys/netinet6/ip6_ecn.h b/sys/netinet6/ip6_ecn.h
--- a/sys/netinet6/ip6_ecn.h
+++ b/sys/netinet6/ip6_ecn.h
@@ -31,11 +31,6 @@
* $KAME: ip_ecn.h,v 1.5 2000/03/27 04:58:38 sumikawa Exp $
*/
-/*
- * ECN consideration on tunnel ingress/egress operation.
- * http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt
- */
-
#ifdef _KERNEL
extern void ip6_ecn_ingress(int, uint32_t *, const uint32_t *);
extern int ip6_ecn_egress(int, const uint32_t *, uint32_t *);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Dec 22, 3:13 AM (14 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27132950
Default Alt Text
D53516.diff (9 KB)
Attached To
Mode
D53516: Update ip_ecn to RFC 6040
Attached
Detach File
Event Timeline
Log In to Comment