diff options
-rw-r--r-- | include/net/tcp.h | 9 | ||||
-rw-r--r-- | net/ipv4/syncookies.c | 31 | ||||
-rw-r--r-- | net/ipv6/syncookies.c | 5 |
3 files changed, 27 insertions, 18 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h index 3a35b1500359..36c5084964cd 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -490,17 +490,16 @@ u32 __cookie_v4_init_sequence(const struct iphdr *iph, const struct tcphdr *th, | |||
490 | u16 *mssp); | 490 | u16 *mssp); |
491 | __u32 cookie_v4_init_sequence(struct sock *sk, const struct sk_buff *skb, | 491 | __u32 cookie_v4_init_sequence(struct sock *sk, const struct sk_buff *skb, |
492 | __u16 *mss); | 492 | __u16 *mss); |
493 | #endif | ||
494 | |||
495 | __u32 cookie_init_timestamp(struct request_sock *req); | 493 | __u32 cookie_init_timestamp(struct request_sock *req); |
496 | bool cookie_check_timestamp(struct tcp_options_received *opt, struct net *net, | 494 | bool cookie_timestamp_decode(struct tcp_options_received *opt); |
497 | bool *ecn_ok); | 495 | bool cookie_ecn_ok(const struct tcp_options_received *opt, |
496 | const struct net *net); | ||
498 | 497 | ||
499 | /* From net/ipv6/syncookies.c */ | 498 | /* From net/ipv6/syncookies.c */ |
500 | int __cookie_v6_check(const struct ipv6hdr *iph, const struct tcphdr *th, | 499 | int __cookie_v6_check(const struct ipv6hdr *iph, const struct tcphdr *th, |
501 | u32 cookie); | 500 | u32 cookie); |
502 | struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb); | 501 | struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb); |
503 | #ifdef CONFIG_SYN_COOKIES | 502 | |
504 | u32 __cookie_v6_init_sequence(const struct ipv6hdr *iph, | 503 | u32 __cookie_v6_init_sequence(const struct ipv6hdr *iph, |
505 | const struct tcphdr *th, u16 *mssp); | 504 | const struct tcphdr *th, u16 *mssp); |
506 | __u32 cookie_v6_init_sequence(struct sock *sk, const struct sk_buff *skb, | 505 | __u32 cookie_v6_init_sequence(struct sock *sk, const struct sk_buff *skb, |
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index c3792c0557dd..6de772500ee9 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c | |||
@@ -241,10 +241,10 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb, | |||
241 | * additional tcp options in the timestamp. | 241 | * additional tcp options in the timestamp. |
242 | * This extracts these options from the timestamp echo. | 242 | * This extracts these options from the timestamp echo. |
243 | * | 243 | * |
244 | * return false if we decode an option that should not be. | 244 | * return false if we decode a tcp option that is disabled |
245 | * on the host. | ||
245 | */ | 246 | */ |
246 | bool cookie_check_timestamp(struct tcp_options_received *tcp_opt, | 247 | bool cookie_timestamp_decode(struct tcp_options_received *tcp_opt) |
247 | struct net *net, bool *ecn_ok) | ||
248 | { | 248 | { |
249 | /* echoed timestamp, lowest bits contain options */ | 249 | /* echoed timestamp, lowest bits contain options */ |
250 | u32 options = tcp_opt->rcv_tsecr; | 250 | u32 options = tcp_opt->rcv_tsecr; |
@@ -258,9 +258,6 @@ bool cookie_check_timestamp(struct tcp_options_received *tcp_opt, | |||
258 | return false; | 258 | return false; |
259 | 259 | ||
260 | tcp_opt->sack_ok = (options & TS_OPT_SACK) ? TCP_SACK_SEEN : 0; | 260 | tcp_opt->sack_ok = (options & TS_OPT_SACK) ? TCP_SACK_SEEN : 0; |
261 | *ecn_ok = options & TS_OPT_ECN; | ||
262 | if (*ecn_ok && !net->ipv4.sysctl_tcp_ecn) | ||
263 | return false; | ||
264 | 261 | ||
265 | if (tcp_opt->sack_ok && !sysctl_tcp_sack) | 262 | if (tcp_opt->sack_ok && !sysctl_tcp_sack) |
266 | return false; | 263 | return false; |
@@ -273,7 +270,22 @@ bool cookie_check_timestamp(struct tcp_options_received *tcp_opt, | |||
273 | 270 | ||
274 | return sysctl_tcp_window_scaling != 0; | 271 | return sysctl_tcp_window_scaling != 0; |
275 | } | 272 | } |
276 | EXPORT_SYMBOL(cookie_check_timestamp); | 273 | EXPORT_SYMBOL(cookie_timestamp_decode); |
274 | |||
275 | bool cookie_ecn_ok(const struct tcp_options_received *tcp_opt, | ||
276 | const struct net *net) | ||
277 | { | ||
278 | bool ecn_ok = tcp_opt->rcv_tsecr & TS_OPT_ECN; | ||
279 | |||
280 | if (!ecn_ok) | ||
281 | return false; | ||
282 | |||
283 | if (net->ipv4.sysctl_tcp_ecn) | ||
284 | return true; | ||
285 | |||
286 | return false; | ||
287 | } | ||
288 | EXPORT_SYMBOL(cookie_ecn_ok); | ||
277 | 289 | ||
278 | struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) | 290 | struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) |
279 | { | 291 | { |
@@ -289,7 +301,6 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) | |||
289 | int mss; | 301 | int mss; |
290 | struct rtable *rt; | 302 | struct rtable *rt; |
291 | __u8 rcv_wscale; | 303 | __u8 rcv_wscale; |
292 | bool ecn_ok = false; | ||
293 | struct flowi4 fl4; | 304 | struct flowi4 fl4; |
294 | 305 | ||
295 | if (!sysctl_tcp_syncookies || !th->ack || th->rst) | 306 | if (!sysctl_tcp_syncookies || !th->ack || th->rst) |
@@ -310,7 +321,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) | |||
310 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | 321 | memset(&tcp_opt, 0, sizeof(tcp_opt)); |
311 | tcp_parse_options(skb, &tcp_opt, 0, NULL); | 322 | tcp_parse_options(skb, &tcp_opt, 0, NULL); |
312 | 323 | ||
313 | if (!cookie_check_timestamp(&tcp_opt, sock_net(sk), &ecn_ok)) | 324 | if (!cookie_timestamp_decode(&tcp_opt)) |
314 | goto out; | 325 | goto out; |
315 | 326 | ||
316 | ret = NULL; | 327 | ret = NULL; |
@@ -328,7 +339,6 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) | |||
328 | ireq->ir_loc_addr = ip_hdr(skb)->daddr; | 339 | ireq->ir_loc_addr = ip_hdr(skb)->daddr; |
329 | ireq->ir_rmt_addr = ip_hdr(skb)->saddr; | 340 | ireq->ir_rmt_addr = ip_hdr(skb)->saddr; |
330 | ireq->ir_mark = inet_request_mark(sk, skb); | 341 | ireq->ir_mark = inet_request_mark(sk, skb); |
331 | ireq->ecn_ok = ecn_ok; | ||
332 | ireq->snd_wscale = tcp_opt.snd_wscale; | 342 | ireq->snd_wscale = tcp_opt.snd_wscale; |
333 | ireq->sack_ok = tcp_opt.sack_ok; | 343 | ireq->sack_ok = tcp_opt.sack_ok; |
334 | ireq->wscale_ok = tcp_opt.wscale_ok; | 344 | ireq->wscale_ok = tcp_opt.wscale_ok; |
@@ -377,6 +387,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) | |||
377 | dst_metric(&rt->dst, RTAX_INITRWND)); | 387 | dst_metric(&rt->dst, RTAX_INITRWND)); |
378 | 388 | ||
379 | ireq->rcv_wscale = rcv_wscale; | 389 | ireq->rcv_wscale = rcv_wscale; |
390 | ireq->ecn_ok = cookie_ecn_ok(&tcp_opt, sock_net(sk)); | ||
380 | 391 | ||
381 | ret = get_cookie_sock(sk, skb, req, &rt->dst); | 392 | ret = get_cookie_sock(sk, skb, req, &rt->dst); |
382 | /* ip_queue_xmit() depends on our flow being setup | 393 | /* ip_queue_xmit() depends on our flow being setup |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index be291baa2ec2..52cc8cb02c0c 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -166,7 +166,6 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
166 | int mss; | 166 | int mss; |
167 | struct dst_entry *dst; | 167 | struct dst_entry *dst; |
168 | __u8 rcv_wscale; | 168 | __u8 rcv_wscale; |
169 | bool ecn_ok = false; | ||
170 | 169 | ||
171 | if (!sysctl_tcp_syncookies || !th->ack || th->rst) | 170 | if (!sysctl_tcp_syncookies || !th->ack || th->rst) |
172 | goto out; | 171 | goto out; |
@@ -186,7 +185,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
186 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | 185 | memset(&tcp_opt, 0, sizeof(tcp_opt)); |
187 | tcp_parse_options(skb, &tcp_opt, 0, NULL); | 186 | tcp_parse_options(skb, &tcp_opt, 0, NULL); |
188 | 187 | ||
189 | if (!cookie_check_timestamp(&tcp_opt, sock_net(sk), &ecn_ok)) | 188 | if (!cookie_timestamp_decode(&tcp_opt)) |
190 | goto out; | 189 | goto out; |
191 | 190 | ||
192 | ret = NULL; | 191 | ret = NULL; |
@@ -223,7 +222,6 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
223 | 222 | ||
224 | req->expires = 0UL; | 223 | req->expires = 0UL; |
225 | req->num_retrans = 0; | 224 | req->num_retrans = 0; |
226 | ireq->ecn_ok = ecn_ok; | ||
227 | ireq->snd_wscale = tcp_opt.snd_wscale; | 225 | ireq->snd_wscale = tcp_opt.snd_wscale; |
228 | ireq->sack_ok = tcp_opt.sack_ok; | 226 | ireq->sack_ok = tcp_opt.sack_ok; |
229 | ireq->wscale_ok = tcp_opt.wscale_ok; | 227 | ireq->wscale_ok = tcp_opt.wscale_ok; |
@@ -264,6 +262,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
264 | dst_metric(dst, RTAX_INITRWND)); | 262 | dst_metric(dst, RTAX_INITRWND)); |
265 | 263 | ||
266 | ireq->rcv_wscale = rcv_wscale; | 264 | ireq->rcv_wscale = rcv_wscale; |
265 | ireq->ecn_ok = cookie_ecn_ok(&tcp_opt, sock_net(sk)); | ||
267 | 266 | ||
268 | ret = get_cookie_sock(sk, skb, req, dst); | 267 | ret = get_cookie_sock(sk, skb, req, dst); |
269 | out: | 268 | out: |