aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/syncookies.c
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2008-04-10 06:12:40 -0400
committerDavid S. Miller <davem@davemloft.net>2008-04-10 06:12:40 -0400
commit4dfc2817025965a2fc78a18c50f540736a6b5c24 (patch)
treef8f2f76e660d9d5c7a0f39ed8a79cb6d6d181206 /net/ipv6/syncookies.c
parent15be75cdb5db442d0e33d37b20832b88f3ccd383 (diff)
[Syncookies]: Add support for TCP options via timestamps.
Allow the use of SACK and window scaling when syncookies are used and the client supports tcp timestamps. Options are encoded into the timestamp sent in the syn-ack and restored from the timestamp echo when the ack is received. Based on earlier work by Glenn Griffin. This patch avoids increasing the size of structs by encoding TCP options into the least significant bits of the timestamp and by not using any 'timestamp offset'. The downside is that the timestamp sent in the packet after the synack will increase by several seconds. changes since v1: don't duplicate timestamp echo decoding function, put it into ipv4/syncookie.c and have ipv6/syncookies.c use it. Feedback from Glenn Griffin: fix line indented with spaces, kill redundant if () Reviewed-by: Hagen Paul Pfeifer <hagen@jauu.net> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/syncookies.c')
-rw-r--r--net/ipv6/syncookies.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index 3a622e7abc02..938ce4ecde55 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -170,6 +170,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
170 int mss; 170 int mss;
171 struct dst_entry *dst; 171 struct dst_entry *dst;
172 __u8 rcv_wscale; 172 __u8 rcv_wscale;
173 struct tcp_options_received tcp_opt;
173 174
174 if (!sysctl_tcp_syncookies || !th->ack) 175 if (!sysctl_tcp_syncookies || !th->ack)
175 goto out; 176 goto out;
@@ -182,6 +183,13 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
182 183
183 NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESRECV); 184 NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESRECV);
184 185
186 /* check for timestamp cookie support */
187 memset(&tcp_opt, 0, sizeof(tcp_opt));
188 tcp_parse_options(skb, &tcp_opt, 0);
189
190 if (tcp_opt.saw_tstamp)
191 cookie_check_timestamp(&tcp_opt);
192
185 ret = NULL; 193 ret = NULL;
186 req = inet6_reqsk_alloc(&tcp6_request_sock_ops); 194 req = inet6_reqsk_alloc(&tcp6_request_sock_ops);
187 if (!req) 195 if (!req)
@@ -216,8 +224,12 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
216 224
217 req->expires = 0UL; 225 req->expires = 0UL;
218 req->retrans = 0; 226 req->retrans = 0;
219 ireq->snd_wscale = ireq->rcv_wscale = ireq->tstamp_ok = 0; 227 ireq->snd_wscale = tcp_opt.snd_wscale;
220 ireq->wscale_ok = ireq->sack_ok = 0; 228 ireq->rcv_wscale = tcp_opt.rcv_wscale;
229 ireq->sack_ok = tcp_opt.sack_ok;
230 ireq->wscale_ok = tcp_opt.wscale_ok;
231 ireq->tstamp_ok = tcp_opt.saw_tstamp;
232 req->ts_recent = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0;
221 treq->rcv_isn = ntohl(th->seq) - 1; 233 treq->rcv_isn = ntohl(th->seq) - 1;
222 treq->snt_isn = cookie; 234 treq->snt_isn = cookie;
223 235
@@ -253,10 +265,10 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
253 goto out; 265 goto out;
254 } 266 }
255 267
256 req->window_clamp = dst_metric(dst, RTAX_WINDOW); 268 req->window_clamp = tp->window_clamp ? :dst_metric(dst, RTAX_WINDOW);
257 tcp_select_initial_window(tcp_full_space(sk), req->mss, 269 tcp_select_initial_window(tcp_full_space(sk), req->mss,
258 &req->rcv_wnd, &req->window_clamp, 270 &req->rcv_wnd, &req->window_clamp,
259 0, &rcv_wscale); 271 ireq->wscale_ok, &rcv_wscale);
260 272
261 ireq->rcv_wscale = rcv_wscale; 273 ireq->rcv_wscale = rcv_wscale;
262 274