Mailing List Archive

[PATCH] Re: Unclean complains about ECN
Hi Graham,

Dans un message du 05 aoû à 11:49, Graham Murray écrivait :
> When running with ECN enabled, unclean complains "TCP reserved bits
> not zero" on packets with the ECN and/or CWR bits set.

This check uses the TCP_RESERVED_BITS macro that is defined according to
RFC793 : 'Reserved: 6 bits Reserved for future use. Must be zero.'

ECN uses the last two bits of the reserved field.

Imho a packet with ECN bits should not be considered as unclean even if
ECN is not enabled on the firewall.

I see three solutions.

1) Removing this check. I've seen some network experts claiming that
reserved bits should never mean "equal to zero". But in this case,
RFC793 clearly states that these bits should be zero. Therefore, I don't
think it is the best solution.

2) Fixing the check by ignoring the ECN bits.


diff -uNr linux-2.4.7-vanilla/net/ipv4/netfilter/ipt_unclean.c linux-fixed-unclean/net/ipv4/netfilter/ipt_unclean.c
--- linux-2.4.7-vanilla/net/ipv4/netfilter/ipt_unclean.c Sun Aug 5 16:37:48 2001
+++ linux-fixed-unclean/net/ipv4/netfilter/ipt_unclean.c Sun Aug 5 17:12:03 2001
@@ -321,8 +321,8 @@
return 0;
}

- /* CHECK: TCP reserved bits zero. */
- if(tcp_flag_word(tcph) & TCP_RESERVED_BITS) {
+ /* CHECK: TCP reserved bits (except TCP ECN related bits) zero. */
+ if(tcp_flag_word(tcph) & TCP_RESERVED_BITS & ~(TCP_FLAG_CWR|TCP_FLAG_ECE)) {
limpk("TCP reserved bits not zero\n");
return 0;
}

3) Define TCP_RESERVED_BITS according to RFC ECN update. This macro is
used by netfilter (here and for the LOG target) and to define
TCP_HP_BITS (header prediction). Thus we need to modify TCP_HP_BITS
definition as well. Imho, the best solution.


diff -uNr linux-2.4.7-vanilla/include/linux/tcp.h linux-new-tcp-reserved-bits/include/linux/tcp.h
--- linux-2.4.7-vanilla/include/linux/tcp.h Sun Aug 5 16:37:43 2001
+++ linux-new-tcp-reserved-bits/include/linux/tcp.h Sun Aug 5 18:20:44 2001
@@ -110,7 +110,7 @@
TCP_FLAG_RST = __constant_htonl(0x00040000),
TCP_FLAG_SYN = __constant_htonl(0x00020000),
TCP_FLAG_FIN = __constant_htonl(0x00010000),
- TCP_RESERVED_BITS = __constant_htonl(0x0FC00000),
+ TCP_RESERVED_BITS = __constant_htonl(0x0F000000),
TCP_DATA_OFFSET = __constant_htonl(0xF0000000)
};

diff -uNr linux-2.4.7-vanilla/include/net/tcp_ecn.h linux-new-tcp-reserved-bits/include/net/tcp_ecn.h
--- linux-2.4.7-vanilla/include/net/tcp_ecn.h Sun Aug 5 16:37:44 2001
+++ linux-new-tcp-reserved-bits/include/net/tcp_ecn.h Sun Aug 5 18:22:36 2001
@@ -7,7 +7,7 @@

#include <net/inet_ecn.h>

-#define TCP_HP_BITS (~(TCP_RESERVED_BITS|TCP_FLAG_PSH)|TCP_FLAG_ECE|TCP_FLAG_CWR)
+#define TCP_HP_BITS (~(TCP_RESERVED_BITS|TCP_FLAG_PSH))

#define TCP_ECN_OK 1
#define TCP_ECN_QUEUE_CWR 2
@@ -137,7 +137,7 @@

#else

-#define TCP_HP_BITS (~(TCP_RESERVED_BITS|TCP_FLAG_PSH))
+#define TCP_HP_BITS (~(TCP_RESERVED_BITS|TCP_FLAG_PSH) & ~(TCP_FLAG_ECE|TCP_FLAG_CWR))


#define TCP_ECN_send_syn(x...) do { } while (0)


Both patches have been tested. I currently run the second one (3rd
solution) on my own firewall flawlessly.

Any comments on this welcome.

Regards,

--
Guillaume Morin <guillaume@morinfr.org>

If it doesn't work, force it. If it breaks, it needed replacing anyway.
Re: [PATCH] Re: Unclean complains about ECN [ In reply to ]
ECN is no longer a proposed rfc, it's been accepted as an experimental
protocol in STD1. This field is no longer strictly reserved and may
contain a value other than zero.

David

Guillaume Morin wrote:

>Hi Graham,
>
>Dans un message du 05 aoû à 11:49, Graham Murray écrivait :
>
>>When running with ECN enabled, unclean complains "TCP reserved bits
>>not zero" on packets with the ECN and/or CWR bits set.
>>
>
>This check uses the TCP_RESERVED_BITS macro that is defined according to
>RFC793 : 'Reserved: 6 bits Reserved for future use. Must be zero.'
>
Re: [PATCH] Re: Unclean complains about ECN [ In reply to ]
Unfortunately, my testing host had ECN support disabled by proc. So I
missed a check that involved ECN in both patches. Here are updated
patches. They compile and are tested. The second one is in production on
my firewall.

Dans un message du 05 aoû à 19:30, Guillaume Morin écrivait :
> 2) Fixing the check by ignoring the ECN bits.

diff -uNr linux-2.4.7-vanilla/net/ipv4/netfilter/ipt_unclean.c linux-fixed-unclean/net/ipv4/netfilter/ipt_unclean.c
--- linux-2.4.7-vanilla/net/ipv4/netfilter/ipt_unclean.c Sun Aug 5 16:37:48 2001
+++ linux-fixed-unclean/net/ipv4/netfilter/ipt_unclean.c Mon Aug 6 08:31:29 2001
@@ -257,6 +257,8 @@
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
+#define TH_ECE 0x40
+#define TH_CWR 0x80

/* TCP-specific checks. */
static int
@@ -321,14 +323,14 @@
return 0;
}

- /* CHECK: TCP reserved bits zero. */
- if(tcp_flag_word(tcph) & TCP_RESERVED_BITS) {
+ /* CHECK: TCP reserved bits (except TCP ECN related bit) zero. */
+ if(tcp_flag_word(tcph) & TCP_RESERVED_BITS & ~(TCP_FLAG_CWR|TCP_FLAG_ECE)) {
limpk("TCP reserved bits not zero\n");
return 0;
}

/* CHECK: TCP flags. */
- tcpflags = ((u_int8_t *)tcph)[13];
+ tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
if (tcpflags != TH_SYN
&& tcpflags != (TH_SYN|TH_ACK)
&& tcpflags != (TH_RST|TH_ACK)


> 3) Define TCP_RESERVED_BITS according to RFC ECN update. This macro is
> used by netfilter (here and for the LOG target) and to define
> TCP_HP_BITS (header prediction). Thus we need to modify TCP_HP_BITS
> definition as well. Imho, the best solution.


diff -uNr linux-2.4.7-vanilla/include/linux/tcp.h linux-new-tcp-reserved-bits/include/linux/tcp.h
--- linux-2.4.7-vanilla/include/linux/tcp.h Sun Aug 5 16:37:43 2001
+++ linux-new-tcp-reserved-bits/include/linux/tcp.h Sun Aug 5 18:56:23 2001
@@ -110,7 +110,7 @@
TCP_FLAG_RST = __constant_htonl(0x00040000),
TCP_FLAG_SYN = __constant_htonl(0x00020000),
TCP_FLAG_FIN = __constant_htonl(0x00010000),
- TCP_RESERVED_BITS = __constant_htonl(0x0FC00000),
+ TCP_RESERVED_BITS = __constant_htonl(0x0F000000),
TCP_DATA_OFFSET = __constant_htonl(0xF0000000)
};

diff -uNr linux-2.4.7-vanilla/include/net/tcp_ecn.h linux-new-tcp-reserved-bits/include/net/tcp_ecn.h
--- linux-2.4.7-vanilla/include/net/tcp_ecn.h Sun Aug 5 16:37:44 2001
+++ linux-new-tcp-reserved-bits/include/net/tcp_ecn.h Sun Aug 5 18:58:08 2001
@@ -7,7 +7,7 @@

#include <net/inet_ecn.h>

-#define TCP_HP_BITS (~(TCP_RESERVED_BITS|TCP_FLAG_PSH)|TCP_FLAG_ECE|TCP_FLAG_CWR)
+#define TCP_HP_BITS (~(TCP_RESERVED_BITS|TCP_FLAG_PSH))

#define TCP_ECN_OK 1
#define TCP_ECN_QUEUE_CWR 2
@@ -137,7 +137,7 @@

#else

-#define TCP_HP_BITS (~(TCP_RESERVED_BITS|TCP_FLAG_PSH))
+#define TCP_HP_BITS (~(TCP_RESERVED_BITS|TCP_FLAG_PSH) & ~(TCP_FLAG_ECE|TCP_FLAG_CWR))


#define TCP_ECN_send_syn(x...) do { } while (0)
diff -uNr linux-2.4.7-vanilla/net/ipv4/netfilter/ipt_unclean.c linux-new-tcp-reserved-bits/net/ipv4/netfilter/ipt_unclean.c
--- linux-2.4.7-vanilla/net/ipv4/netfilter/ipt_unclean.c Sun Aug 5 16:37:48 2001
+++ linux-new-tcp-reserved-bits/net/ipv4/netfilter/ipt_unclean.c Mon Aug 6 08:19:04 2001
@@ -257,6 +257,8 @@
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
+#define TH_ECE 0x40
+#define TH_CWR 0x80

/* TCP-specific checks. */
static int
@@ -328,7 +330,7 @@
}

/* CHECK: TCP flags. */
- tcpflags = ((u_int8_t *)tcph)[13];
+ tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
if (tcpflags != TH_SYN
&& tcpflags != (TH_SYN|TH_ACK)
&& tcpflags != (TH_RST|TH_ACK)

Any comments are welcome. Regards,

--
Guillaume Morin <guillaume@morinfr.org>

Unwisely, Santa offered a teddy bear to James, unaware that he had
been mauled by a grizzly earlier that year (T. Burton)