diff options
Diffstat (limited to 'net/ipv4/syncookies.c')
-rw-r--r-- | net/ipv4/syncookies.c | 35 |
1 files changed, 14 insertions, 21 deletions
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 51b5662545d6..8896329aebd0 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c | |||
@@ -18,8 +18,8 @@ | |||
18 | #include <net/tcp.h> | 18 | #include <net/tcp.h> |
19 | #include <net/route.h> | 19 | #include <net/route.h> |
20 | 20 | ||
21 | /* Timestamps: lowest 9 bits store TCP options */ | 21 | /* Timestamps: lowest bits store TCP options */ |
22 | #define TSBITS 9 | 22 | #define TSBITS 5 |
23 | #define TSMASK (((__u32)1 << TSBITS) - 1) | 23 | #define TSMASK (((__u32)1 << TSBITS) - 1) |
24 | 24 | ||
25 | extern int sysctl_tcp_syncookies; | 25 | extern int sysctl_tcp_syncookies; |
@@ -58,7 +58,7 @@ static u32 cookie_hash(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport, | |||
58 | 58 | ||
59 | /* | 59 | /* |
60 | * when syncookies are in effect and tcp timestamps are enabled we encode | 60 | * when syncookies are in effect and tcp timestamps are enabled we encode |
61 | * tcp options in the lowest 9 bits of the timestamp value that will be | 61 | * tcp options in the lower bits of the timestamp value that will be |
62 | * sent in the syn-ack. | 62 | * sent in the syn-ack. |
63 | * Since subsequent timestamps use the normal tcp_time_stamp value, we | 63 | * Since subsequent timestamps use the normal tcp_time_stamp value, we |
64 | * must make sure that the resulting initial timestamp is <= tcp_time_stamp. | 64 | * must make sure that the resulting initial timestamp is <= tcp_time_stamp. |
@@ -70,11 +70,9 @@ __u32 cookie_init_timestamp(struct request_sock *req) | |||
70 | u32 options = 0; | 70 | u32 options = 0; |
71 | 71 | ||
72 | ireq = inet_rsk(req); | 72 | ireq = inet_rsk(req); |
73 | if (ireq->wscale_ok) { | 73 | |
74 | options = ireq->snd_wscale; | 74 | options = ireq->wscale_ok ? ireq->snd_wscale : 0xf; |
75 | options |= ireq->rcv_wscale << 4; | 75 | options |= ireq->sack_ok << 4; |
76 | } | ||
77 | options |= ireq->sack_ok << 8; | ||
78 | 76 | ||
79 | ts = ts_now & ~TSMASK; | 77 | ts = ts_now & ~TSMASK; |
80 | ts |= options; | 78 | ts |= options; |
@@ -227,15 +225,14 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb, | |||
227 | * additional tcp options in the timestamp. | 225 | * additional tcp options in the timestamp. |
228 | * This extracts these options from the timestamp echo. | 226 | * This extracts these options from the timestamp echo. |
229 | * | 227 | * |
230 | * The lowest 4 bits are for snd_wscale | 228 | * The lowest 4 bits store snd_wscale. |
231 | * The next 4 lsb are for rcv_wscale | ||
232 | * The next lsb is for sack_ok | 229 | * The next lsb is for sack_ok |
233 | * | 230 | * |
234 | * return false if we decode an option that should not be. | 231 | * return false if we decode an option that should not be. |
235 | */ | 232 | */ |
236 | bool cookie_check_timestamp(struct tcp_options_received *tcp_opt) | 233 | bool cookie_check_timestamp(struct tcp_options_received *tcp_opt) |
237 | { | 234 | { |
238 | /* echoed timestamp, 9 lowest bits contain options */ | 235 | /* echoed timestamp, lowest bits contain options */ |
239 | u32 options = tcp_opt->rcv_tsecr & TSMASK; | 236 | u32 options = tcp_opt->rcv_tsecr & TSMASK; |
240 | 237 | ||
241 | if (!tcp_opt->saw_tstamp) { | 238 | if (!tcp_opt->saw_tstamp) { |
@@ -246,20 +243,17 @@ bool cookie_check_timestamp(struct tcp_options_received *tcp_opt) | |||
246 | if (!sysctl_tcp_timestamps) | 243 | if (!sysctl_tcp_timestamps) |
247 | return false; | 244 | return false; |
248 | 245 | ||
249 | tcp_opt->snd_wscale = options & 0xf; | ||
250 | options >>= 4; | ||
251 | tcp_opt->rcv_wscale = options & 0xf; | ||
252 | |||
253 | tcp_opt->sack_ok = (options >> 4) & 0x1; | 246 | tcp_opt->sack_ok = (options >> 4) & 0x1; |
254 | 247 | ||
255 | if (tcp_opt->sack_ok && !sysctl_tcp_sack) | 248 | if (tcp_opt->sack_ok && !sysctl_tcp_sack) |
256 | return false; | 249 | return false; |
257 | 250 | ||
258 | if (tcp_opt->snd_wscale || tcp_opt->rcv_wscale) { | 251 | if ((options & 0xf) == 0xf) |
259 | tcp_opt->wscale_ok = 1; | 252 | return true; /* no window scaling */ |
260 | return sysctl_tcp_window_scaling != 0; | 253 | |
261 | } | 254 | tcp_opt->wscale_ok = 1; |
262 | return true; | 255 | tcp_opt->snd_wscale = options & 0xf; |
256 | return sysctl_tcp_window_scaling != 0; | ||
263 | } | 257 | } |
264 | EXPORT_SYMBOL(cookie_check_timestamp); | 258 | EXPORT_SYMBOL(cookie_check_timestamp); |
265 | 259 | ||
@@ -313,7 +307,6 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, | |||
313 | ireq->rmt_addr = ip_hdr(skb)->saddr; | 307 | ireq->rmt_addr = ip_hdr(skb)->saddr; |
314 | ireq->ecn_ok = 0; | 308 | ireq->ecn_ok = 0; |
315 | ireq->snd_wscale = tcp_opt.snd_wscale; | 309 | ireq->snd_wscale = tcp_opt.snd_wscale; |
316 | ireq->rcv_wscale = tcp_opt.rcv_wscale; | ||
317 | ireq->sack_ok = tcp_opt.sack_ok; | 310 | ireq->sack_ok = tcp_opt.sack_ok; |
318 | ireq->wscale_ok = tcp_opt.wscale_ok; | 311 | ireq->wscale_ok = tcp_opt.wscale_ok; |
319 | ireq->tstamp_ok = tcp_opt.saw_tstamp; | 312 | ireq->tstamp_ok = tcp_opt.saw_tstamp; |