diff options
-rw-r--r-- | include/net/tcp.h | 2 | ||||
-rw-r--r-- | net/ipv4/syncookies.c | 25 | ||||
-rw-r--r-- | net/ipv6/syncookies.c | 4 |
3 files changed, 22 insertions, 9 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h index 9e68e25c8b82..18c246c9b009 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -464,7 +464,7 @@ extern __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, | |||
464 | __u16 *mss); | 464 | __u16 *mss); |
465 | 465 | ||
466 | extern __u32 cookie_init_timestamp(struct request_sock *req); | 466 | extern __u32 cookie_init_timestamp(struct request_sock *req); |
467 | extern void cookie_check_timestamp(struct tcp_options_received *tcp_opt); | 467 | extern bool cookie_check_timestamp(struct tcp_options_received *tcp_opt); |
468 | 468 | ||
469 | /* From net/ipv6/syncookies.c */ | 469 | /* From net/ipv6/syncookies.c */ |
470 | extern struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb); | 470 | extern struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb); |
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 02bef6aa8b30..51b5662545d6 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c | |||
@@ -230,23 +230,36 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb, | |||
230 | * The lowest 4 bits are for snd_wscale | 230 | * The lowest 4 bits are for snd_wscale |
231 | * The next 4 lsb are for rcv_wscale | 231 | * The next 4 lsb are for rcv_wscale |
232 | * The next lsb is for sack_ok | 232 | * The next lsb is for sack_ok |
233 | * | ||
234 | * return false if we decode an option that should not be. | ||
233 | */ | 235 | */ |
234 | void cookie_check_timestamp(struct tcp_options_received *tcp_opt) | 236 | bool cookie_check_timestamp(struct tcp_options_received *tcp_opt) |
235 | { | 237 | { |
236 | /* echoed timestamp, 9 lowest bits contain options */ | 238 | /* echoed timestamp, 9 lowest bits contain options */ |
237 | u32 options = tcp_opt->rcv_tsecr & TSMASK; | 239 | u32 options = tcp_opt->rcv_tsecr & TSMASK; |
238 | 240 | ||
241 | if (!tcp_opt->saw_tstamp) { | ||
242 | tcp_clear_options(tcp_opt); | ||
243 | return true; | ||
244 | } | ||
245 | |||
246 | if (!sysctl_tcp_timestamps) | ||
247 | return false; | ||
248 | |||
239 | tcp_opt->snd_wscale = options & 0xf; | 249 | tcp_opt->snd_wscale = options & 0xf; |
240 | options >>= 4; | 250 | options >>= 4; |
241 | tcp_opt->rcv_wscale = options & 0xf; | 251 | tcp_opt->rcv_wscale = options & 0xf; |
242 | 252 | ||
243 | tcp_opt->sack_ok = (options >> 4) & 0x1; | 253 | tcp_opt->sack_ok = (options >> 4) & 0x1; |
244 | 254 | ||
245 | if (tcp_opt->sack_ok) | 255 | if (tcp_opt->sack_ok && !sysctl_tcp_sack) |
246 | tcp_sack_reset(tcp_opt); | 256 | return false; |
247 | 257 | ||
248 | if (tcp_opt->snd_wscale || tcp_opt->rcv_wscale) | 258 | if (tcp_opt->snd_wscale || tcp_opt->rcv_wscale) { |
249 | tcp_opt->wscale_ok = 1; | 259 | tcp_opt->wscale_ok = 1; |
260 | return sysctl_tcp_window_scaling != 0; | ||
261 | } | ||
262 | return true; | ||
250 | } | 263 | } |
251 | EXPORT_SYMBOL(cookie_check_timestamp); | 264 | EXPORT_SYMBOL(cookie_check_timestamp); |
252 | 265 | ||
@@ -281,8 +294,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, | |||
281 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | 294 | memset(&tcp_opt, 0, sizeof(tcp_opt)); |
282 | tcp_parse_options(skb, &tcp_opt, &hash_location, 0); | 295 | tcp_parse_options(skb, &tcp_opt, &hash_location, 0); |
283 | 296 | ||
284 | if (tcp_opt.saw_tstamp) | 297 | if (!cookie_check_timestamp(&tcp_opt)) |
285 | cookie_check_timestamp(&tcp_opt); | 298 | goto out; |
286 | 299 | ||
287 | ret = NULL; | 300 | ret = NULL; |
288 | req = inet_reqsk_alloc(&tcp_request_sock_ops); /* for safety */ | 301 | req = inet_reqsk_alloc(&tcp_request_sock_ops); /* for safety */ |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 70d330f8c990..c7ee57421ece 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -180,8 +180,8 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
180 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | 180 | memset(&tcp_opt, 0, sizeof(tcp_opt)); |
181 | tcp_parse_options(skb, &tcp_opt, &hash_location, 0); | 181 | tcp_parse_options(skb, &tcp_opt, &hash_location, 0); |
182 | 182 | ||
183 | if (tcp_opt.saw_tstamp) | 183 | if (!cookie_check_timestamp(&tcp_opt)) |
184 | cookie_check_timestamp(&tcp_opt); | 184 | goto out; |
185 | 185 | ||
186 | ret = NULL; | 186 | ret = NULL; |
187 | req = inet6_reqsk_alloc(&tcp6_request_sock_ops); | 187 | req = inet6_reqsk_alloc(&tcp6_request_sock_ops); |