aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2010-06-21 07:48:45 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-27 01:00:03 -0400
commit172d69e63c7f1e8300d0e1c1bbd8eb0f630faa15 (patch)
treec71118ddc86186e235a920b9529c457db5e9aae5
parent734f614bc1e7c6bf075d201f6bd9a555b8b4a984 (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.h2
-rw-r--r--net/ipv4/syncookies.c15
-rw-r--r--net/ipv4/tcp_ipv4.c6
-rw-r--r--net/ipv6/syncookies.c5
-rw-r--r--net/ipv6/tcp_ipv6.c2
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
466extern __u32 cookie_init_timestamp(struct request_sock *req); 466extern __u32 cookie_init_timestamp(struct request_sock *req);
467extern bool cookie_check_timestamp(struct tcp_options_received *tcp_opt); 467extern bool cookie_check_timestamp(struct tcp_options_received *opt, bool *);
468 468
469/* From net/ipv6/syncookies.c */ 469/* From net/ipv6/syncookies.c */
470extern struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb); 470extern 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
25extern int sysctl_tcp_syncookies; 25extern 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 */
233bool cookie_check_timestamp(struct tcp_options_received *tcp_opt) 234bool 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) {