diff options
author | Florian Westphal <fw@strlen.de> | 2010-06-21 07:48:45 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-27 01:00:03 -0400 |
commit | 172d69e63c7f1e8300d0e1c1bbd8eb0f630faa15 (patch) | |
tree | c71118ddc86186e235a920b9529c457db5e9aae5 | |
parent | 734f614bc1e7c6bf075d201f6bd9a555b8b4a984 (diff) |
syncookies: add support for ECN
Allows use of ECN when syncookies are in effect by encoding ecn_ok
into the syn-ack tcp timestamp.
While at it, remove a uneeded #ifdef CONFIG_SYN_COOKIES.
With CONFIG_SYN_COOKIES=nm want_cookie is ifdef'd to 0 and gcc
removes the "if (0)".
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/tcp.h | 2 | ||||
-rw-r--r-- | net/ipv4/syncookies.c | 15 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 6 | ||||
-rw-r--r-- | net/ipv6/syncookies.c | 5 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 2 |
5 files changed, 17 insertions, 13 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h index 18c246c9b009..c2f96c2cc89c 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 bool cookie_check_timestamp(struct tcp_options_received *tcp_opt); | 467 | extern bool cookie_check_timestamp(struct tcp_options_received *opt, bool *); |
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 8896329aebd0..650cace2180d 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <net/route.h> | 19 | #include <net/route.h> |
20 | 20 | ||
21 | /* Timestamps: lowest bits store TCP options */ | 21 | /* Timestamps: lowest bits store TCP options */ |
22 | #define TSBITS 5 | 22 | #define TSBITS 6 |
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; |
@@ -73,6 +73,7 @@ __u32 cookie_init_timestamp(struct request_sock *req) | |||
73 | 73 | ||
74 | options = ireq->wscale_ok ? ireq->snd_wscale : 0xf; | 74 | options = ireq->wscale_ok ? ireq->snd_wscale : 0xf; |
75 | options |= ireq->sack_ok << 4; | 75 | options |= ireq->sack_ok << 4; |
76 | options |= ireq->ecn_ok << 5; | ||
76 | 77 | ||
77 | ts = ts_now & ~TSMASK; | 78 | ts = ts_now & ~TSMASK; |
78 | ts |= options; | 79 | ts |= options; |
@@ -226,11 +227,11 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb, | |||
226 | * This extracts these options from the timestamp echo. | 227 | * This extracts these options from the timestamp echo. |
227 | * | 228 | * |
228 | * The lowest 4 bits store snd_wscale. | 229 | * The lowest 4 bits store snd_wscale. |
229 | * The next lsb is for sack_ok | 230 | * next 2 bits indicate SACK and ECN support. |
230 | * | 231 | * |
231 | * return false if we decode an option that should not be. | 232 | * return false if we decode an option that should not be. |
232 | */ | 233 | */ |
233 | bool cookie_check_timestamp(struct tcp_options_received *tcp_opt) | 234 | bool cookie_check_timestamp(struct tcp_options_received *tcp_opt, bool *ecn_ok) |
234 | { | 235 | { |
235 | /* echoed timestamp, lowest bits contain options */ | 236 | /* echoed timestamp, lowest bits contain options */ |
236 | u32 options = tcp_opt->rcv_tsecr & TSMASK; | 237 | u32 options = tcp_opt->rcv_tsecr & TSMASK; |
@@ -244,6 +245,9 @@ bool cookie_check_timestamp(struct tcp_options_received *tcp_opt) | |||
244 | return false; | 245 | return false; |
245 | 246 | ||
246 | tcp_opt->sack_ok = (options >> 4) & 0x1; | 247 | tcp_opt->sack_ok = (options >> 4) & 0x1; |
248 | *ecn_ok = (options >> 5) & 1; | ||
249 | if (*ecn_ok && !sysctl_tcp_ecn) | ||
250 | return false; | ||
247 | 251 | ||
248 | if (tcp_opt->sack_ok && !sysctl_tcp_sack) | 252 | if (tcp_opt->sack_ok && !sysctl_tcp_sack) |
249 | return false; | 253 | return false; |
@@ -272,6 +276,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, | |||
272 | int mss; | 276 | int mss; |
273 | struct rtable *rt; | 277 | struct rtable *rt; |
274 | __u8 rcv_wscale; | 278 | __u8 rcv_wscale; |
279 | bool ecn_ok; | ||
275 | 280 | ||
276 | if (!sysctl_tcp_syncookies || !th->ack || th->rst) | 281 | if (!sysctl_tcp_syncookies || !th->ack || th->rst) |
277 | goto out; | 282 | goto out; |
@@ -288,7 +293,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, | |||
288 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | 293 | memset(&tcp_opt, 0, sizeof(tcp_opt)); |
289 | tcp_parse_options(skb, &tcp_opt, &hash_location, 0); | 294 | tcp_parse_options(skb, &tcp_opt, &hash_location, 0); |
290 | 295 | ||
291 | if (!cookie_check_timestamp(&tcp_opt)) | 296 | if (!cookie_check_timestamp(&tcp_opt, &ecn_ok)) |
292 | goto out; | 297 | goto out; |
293 | 298 | ||
294 | ret = NULL; | 299 | ret = NULL; |
@@ -305,7 +310,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, | |||
305 | ireq->rmt_port = th->source; | 310 | ireq->rmt_port = th->source; |
306 | ireq->loc_addr = ip_hdr(skb)->daddr; | 311 | ireq->loc_addr = ip_hdr(skb)->daddr; |
307 | ireq->rmt_addr = ip_hdr(skb)->saddr; | 312 | ireq->rmt_addr = ip_hdr(skb)->saddr; |
308 | ireq->ecn_ok = 0; | 313 | ireq->ecn_ok = ecn_ok; |
309 | ireq->snd_wscale = tcp_opt.snd_wscale; | 314 | ireq->snd_wscale = tcp_opt.snd_wscale; |
310 | ireq->sack_ok = tcp_opt.sack_ok; | 315 | ireq->sack_ok = tcp_opt.sack_ok; |
311 | ireq->wscale_ok = tcp_opt.wscale_ok; | 316 | ireq->wscale_ok = tcp_opt.wscale_ok; |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 2e41e6f92968..8fa32f5ae2ce 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1328,14 +1328,12 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1328 | if (security_inet_conn_request(sk, skb, req)) | 1328 | if (security_inet_conn_request(sk, skb, req)) |
1329 | goto drop_and_free; | 1329 | goto drop_and_free; |
1330 | 1330 | ||
1331 | if (!want_cookie) | 1331 | if (!want_cookie || tmp_opt.tstamp_ok) |
1332 | TCP_ECN_create_request(req, tcp_hdr(skb)); | 1332 | TCP_ECN_create_request(req, tcp_hdr(skb)); |
1333 | 1333 | ||
1334 | if (want_cookie) { | 1334 | if (want_cookie) { |
1335 | #ifdef CONFIG_SYN_COOKIES | ||
1336 | req->cookie_ts = tmp_opt.tstamp_ok; | ||
1337 | #endif | ||
1338 | isn = cookie_v4_init_sequence(sk, skb, &req->mss); | 1335 | isn = cookie_v4_init_sequence(sk, skb, &req->mss); |
1336 | req->cookie_ts = tmp_opt.tstamp_ok; | ||
1339 | } else if (!isn) { | 1337 | } else if (!isn) { |
1340 | struct inet_peer *peer = NULL; | 1338 | struct inet_peer *peer = NULL; |
1341 | 1339 | ||
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 84d818cfae17..09fd34f0dbf2 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -164,6 +164,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
164 | int mss; | 164 | int mss; |
165 | struct dst_entry *dst; | 165 | struct dst_entry *dst; |
166 | __u8 rcv_wscale; | 166 | __u8 rcv_wscale; |
167 | bool ecn_ok; | ||
167 | 168 | ||
168 | if (!sysctl_tcp_syncookies || !th->ack || th->rst) | 169 | if (!sysctl_tcp_syncookies || !th->ack || th->rst) |
169 | goto out; | 170 | goto out; |
@@ -180,7 +181,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
180 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | 181 | memset(&tcp_opt, 0, sizeof(tcp_opt)); |
181 | tcp_parse_options(skb, &tcp_opt, &hash_location, 0); | 182 | tcp_parse_options(skb, &tcp_opt, &hash_location, 0); |
182 | 183 | ||
183 | if (!cookie_check_timestamp(&tcp_opt)) | 184 | if (!cookie_check_timestamp(&tcp_opt, &ecn_ok)) |
184 | goto out; | 185 | goto out; |
185 | 186 | ||
186 | ret = NULL; | 187 | ret = NULL; |
@@ -215,7 +216,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
215 | 216 | ||
216 | req->expires = 0UL; | 217 | req->expires = 0UL; |
217 | req->retrans = 0; | 218 | req->retrans = 0; |
218 | ireq->ecn_ok = 0; | 219 | ireq->ecn_ok = ecn_ok; |
219 | ireq->snd_wscale = tcp_opt.snd_wscale; | 220 | ireq->snd_wscale = tcp_opt.snd_wscale; |
220 | ireq->sack_ok = tcp_opt.sack_ok; | 221 | ireq->sack_ok = tcp_opt.sack_ok; |
221 | ireq->wscale_ok = tcp_opt.wscale_ok; | 222 | ireq->wscale_ok = tcp_opt.wscale_ok; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index f87534569366..5ebc27ecebdc 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1269,7 +1269,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1269 | treq = inet6_rsk(req); | 1269 | treq = inet6_rsk(req); |
1270 | ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr); | 1270 | ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr); |
1271 | ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr); | 1271 | ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr); |
1272 | if (!want_cookie) | 1272 | if (!want_cookie || tmp_opt.tstamp_ok) |
1273 | TCP_ECN_create_request(req, tcp_hdr(skb)); | 1273 | TCP_ECN_create_request(req, tcp_hdr(skb)); |
1274 | 1274 | ||
1275 | if (!isn) { | 1275 | if (!isn) { |