@ -19,10 +19,6 @@
# include <net/tcp.h>
# include <net/route.h>
/* Timestamps: lowest bits store TCP options */
# define TSBITS 6
# define TSMASK (((__u32)1 << TSBITS) - 1)
extern int sysctl_tcp_syncookies ;
static u32 syncookie_secret [ 2 ] [ 16 - 4 + SHA_DIGEST_WORDS ] __read_mostly ;
@ -30,6 +26,30 @@ static u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS] __read_mostly;
# define COOKIEBITS 24 /* Upper bits store count */
# define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
/* TCP Timestamp: 6 lowest bits of timestamp sent in the cookie SYN-ACK
* stores TCP options :
*
* MSB LSB
* | 31 . . . 6 | 5 | 4 | 3 2 1 0 |
* | Timestamp | ECN | SACK | WScale |
*
* When we receive a valid cookie - ACK , we look at the echoed tsval ( if
* any ) to figure out which TCP options we should use for the rebuilt
* connection .
*
* A WScale setting of ' 0xf ' ( which is an invalid scaling value )
* means that original syn did not include the TCP window scaling option .
*/
# define TS_OPT_WSCALE_MASK 0xf
# define TS_OPT_SACK BIT(4)
# define TS_OPT_ECN BIT(5)
/* There is no TS_OPT_TIMESTAMP:
* if ACK contains timestamp option , we already know it was
* requested / supported by the syn / synack exchange .
*/
# define TSBITS 6
# define TSMASK (((__u32)1 << TSBITS) - 1)
static DEFINE_PER_CPU ( __u32 [ 16 + 5 + SHA_WORKSPACE_WORDS ] ,
ipv4_cookie_scratch ) ;
@ -67,9 +87,11 @@ __u32 cookie_init_timestamp(struct request_sock *req)
ireq = inet_rsk ( req ) ;
options = ireq - > wscale_ok ? ireq - > snd_wscale : 0xf ;
options | = ireq - > sack_ok < < 4 ;
options | = ireq - > ecn_ok < < 5 ;
options = ireq - > wscale_ok ? ireq - > snd_wscale : TS_OPT_WSCALE_MASK ;
if ( ireq - > sack_ok )
options | = TS_OPT_SACK ;
if ( ireq - > ecn_ok )
options | = TS_OPT_ECN ;
ts = ts_now & ~ TSMASK ;
ts | = options ;
@ -219,16 +241,13 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
* additional tcp options in the timestamp .
* This extracts these options from the timestamp echo .
*
* The lowest 4 bits store snd_wscale .
* next 2 bits indicate SACK and ECN support .
*
* return false if we decode an option that should not be .
*/
bool cookie_check_timestamp ( struct tcp_options_received * tcp_opt ,
struct net * net , bool * ecn_ok )
{
/* echoed timestamp, lowest bits contain options */
u32 options = tcp_opt - > rcv_tsecr & TSMASK ;
u32 options = tcp_opt - > rcv_tsecr ;
if ( ! tcp_opt - > saw_tstamp ) {
tcp_clear_options ( tcp_opt ) ;
@ -238,19 +257,20 @@ bool cookie_check_timestamp(struct tcp_options_received *tcp_opt,
if ( ! sysctl_tcp_timestamps )
return false ;
tcp_opt - > sack_ok = ( options & ( 1 < < 4 ) ) ? TCP_SACK_SEEN : 0 ;
* ecn_ok = ( options > > 5 ) & 1 ;
tcp_opt - > sack_ok = ( options & TS_OPT_SACK ) ? TCP_SACK_SEEN : 0 ;
* ecn_ok = options & TS_OPT_ECN ;
if ( * ecn_ok & & ! net - > ipv4 . sysctl_tcp_ecn )
return false ;
if ( tcp_opt - > sack_ok & & ! sysctl_tcp_sack )
return false ;
if ( ( options & 0xf ) = = 0xf )
if ( ( options & TS_OPT_WSCALE_MASK ) = = TS_OPT_WSCALE_MASK )
return true ; /* no window scaling */
tcp_opt - > wscale_ok = 1 ;
tcp_opt - > snd_wscale = options & 0xf ;
tcp_opt - > snd_wscale = options & TS_OPT_WSCALE_MASK ;
return sysctl_tcp_window_scaling ! = 0 ;
}
EXPORT_SYMBOL ( cookie_check_timestamp ) ;