aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/tcp.h9
-rw-r--r--net/ipv4/syncookies.c31
-rw-r--r--net/ipv6/syncookies.c5
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);
496bool cookie_check_timestamp(struct tcp_options_received *opt, struct net *net, 494bool cookie_timestamp_decode(struct tcp_options_received *opt);
497 bool *ecn_ok); 495bool 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 */
500int __cookie_v6_check(const struct ipv6hdr *iph, const struct tcphdr *th, 499int __cookie_v6_check(const struct ipv6hdr *iph, const struct tcphdr *th,
501 u32 cookie); 500 u32 cookie);
502struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb); 501struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb);
503#ifdef CONFIG_SYN_COOKIES 502
504u32 __cookie_v6_init_sequence(const struct ipv6hdr *iph, 503u32 __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 */
246bool cookie_check_timestamp(struct tcp_options_received *tcp_opt, 247bool 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}
276EXPORT_SYMBOL(cookie_check_timestamp); 273EXPORT_SYMBOL(cookie_timestamp_decode);
274
275bool 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}
288EXPORT_SYMBOL(cookie_ecn_ok);
277 289
278struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) 290struct 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);
269out: 268out: