diff options
-rw-r--r-- | include/net/tcp.h | 3 | ||||
-rw-r--r-- | net/ipv4/syncookies.c | 27 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 9 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 21 | ||||
-rw-r--r-- | net/ipv4/tcp_minisocks.c | 7 | ||||
-rw-r--r-- | net/ipv6/syncookies.c | 28 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 3 |
7 files changed, 56 insertions, 42 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h index 03a49c703377..740d09be8e2d 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -409,7 +409,8 @@ extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
409 | 409 | ||
410 | extern void tcp_parse_options(struct sk_buff *skb, | 410 | extern void tcp_parse_options(struct sk_buff *skb, |
411 | struct tcp_options_received *opt_rx, | 411 | struct tcp_options_received *opt_rx, |
412 | int estab); | 412 | int estab, |
413 | struct dst_entry *dst); | ||
413 | 414 | ||
414 | extern u8 *tcp_parse_md5sig_option(struct tcphdr *th); | 415 | extern u8 *tcp_parse_md5sig_option(struct tcphdr *th); |
415 | 416 | ||
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 5ec678ad70ef..3146cc401748 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c | |||
@@ -276,13 +276,6 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, | |||
276 | 276 | ||
277 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESRECV); | 277 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESRECV); |
278 | 278 | ||
279 | /* check for timestamp cookie support */ | ||
280 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | ||
281 | tcp_parse_options(skb, &tcp_opt, 0); | ||
282 | |||
283 | if (tcp_opt.saw_tstamp) | ||
284 | cookie_check_timestamp(&tcp_opt); | ||
285 | |||
286 | ret = NULL; | 279 | ret = NULL; |
287 | req = inet_reqsk_alloc(&tcp_request_sock_ops); /* for safety */ | 280 | req = inet_reqsk_alloc(&tcp_request_sock_ops); /* for safety */ |
288 | if (!req) | 281 | if (!req) |
@@ -298,12 +291,6 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, | |||
298 | ireq->loc_addr = ip_hdr(skb)->daddr; | 291 | ireq->loc_addr = ip_hdr(skb)->daddr; |
299 | ireq->rmt_addr = ip_hdr(skb)->saddr; | 292 | ireq->rmt_addr = ip_hdr(skb)->saddr; |
300 | ireq->ecn_ok = 0; | 293 | ireq->ecn_ok = 0; |
301 | ireq->snd_wscale = tcp_opt.snd_wscale; | ||
302 | ireq->rcv_wscale = tcp_opt.rcv_wscale; | ||
303 | ireq->sack_ok = tcp_opt.sack_ok; | ||
304 | ireq->wscale_ok = tcp_opt.wscale_ok; | ||
305 | ireq->tstamp_ok = tcp_opt.saw_tstamp; | ||
306 | req->ts_recent = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0; | ||
307 | 294 | ||
308 | /* We throwed the options of the initial SYN away, so we hope | 295 | /* We throwed the options of the initial SYN away, so we hope |
309 | * the ACK carries the same options again (see RFC1122 4.2.3.8) | 296 | * the ACK carries the same options again (see RFC1122 4.2.3.8) |
@@ -352,6 +339,20 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, | |||
352 | } | 339 | } |
353 | } | 340 | } |
354 | 341 | ||
342 | /* check for timestamp cookie support */ | ||
343 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | ||
344 | tcp_parse_options(skb, &tcp_opt, 0, &rt->u.dst); | ||
345 | |||
346 | if (tcp_opt.saw_tstamp) | ||
347 | cookie_check_timestamp(&tcp_opt); | ||
348 | |||
349 | ireq->snd_wscale = tcp_opt.snd_wscale; | ||
350 | ireq->rcv_wscale = tcp_opt.rcv_wscale; | ||
351 | ireq->sack_ok = tcp_opt.sack_ok; | ||
352 | ireq->wscale_ok = tcp_opt.wscale_ok; | ||
353 | ireq->tstamp_ok = tcp_opt.saw_tstamp; | ||
354 | req->ts_recent = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0; | ||
355 | |||
355 | /* Try to redo what tcp_v4_send_synack did. */ | 356 | /* Try to redo what tcp_v4_send_synack did. */ |
356 | req->window_clamp = tp->window_clamp ? :dst_metric(&rt->u.dst, RTAX_WINDOW); | 357 | req->window_clamp = tp->window_clamp ? :dst_metric(&rt->u.dst, RTAX_WINDOW); |
357 | 358 | ||
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a0c3700bae3a..c7625005486d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -3698,12 +3698,14 @@ old_ack: | |||
3698 | * the fast version below fails. | 3698 | * the fast version below fails. |
3699 | */ | 3699 | */ |
3700 | void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx, | 3700 | void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx, |
3701 | int estab) | 3701 | int estab, struct dst_entry *dst) |
3702 | { | 3702 | { |
3703 | unsigned char *ptr; | 3703 | unsigned char *ptr; |
3704 | struct tcphdr *th = tcp_hdr(skb); | 3704 | struct tcphdr *th = tcp_hdr(skb); |
3705 | int length = (th->doff * 4) - sizeof(struct tcphdr); | 3705 | int length = (th->doff * 4) - sizeof(struct tcphdr); |
3706 | 3706 | ||
3707 | BUG_ON(!estab && !dst); | ||
3708 | |||
3707 | ptr = (unsigned char *)(th + 1); | 3709 | ptr = (unsigned char *)(th + 1); |
3708 | opt_rx->saw_tstamp = 0; | 3710 | opt_rx->saw_tstamp = 0; |
3709 | 3711 | ||
@@ -3820,7 +3822,7 @@ static int tcp_fast_parse_options(struct sk_buff *skb, struct tcphdr *th, | |||
3820 | if (tcp_parse_aligned_timestamp(tp, th)) | 3822 | if (tcp_parse_aligned_timestamp(tp, th)) |
3821 | return 1; | 3823 | return 1; |
3822 | } | 3824 | } |
3823 | tcp_parse_options(skb, &tp->rx_opt, 1); | 3825 | tcp_parse_options(skb, &tp->rx_opt, 1, NULL); |
3824 | return 1; | 3826 | return 1; |
3825 | } | 3827 | } |
3826 | 3828 | ||
@@ -5364,8 +5366,9 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, | |||
5364 | struct tcp_sock *tp = tcp_sk(sk); | 5366 | struct tcp_sock *tp = tcp_sk(sk); |
5365 | struct inet_connection_sock *icsk = inet_csk(sk); | 5367 | struct inet_connection_sock *icsk = inet_csk(sk); |
5366 | int saved_clamp = tp->rx_opt.mss_clamp; | 5368 | int saved_clamp = tp->rx_opt.mss_clamp; |
5369 | struct dst_entry *dst = __sk_dst_get(sk); | ||
5367 | 5370 | ||
5368 | tcp_parse_options(skb, &tp->rx_opt, 0); | 5371 | tcp_parse_options(skb, &tp->rx_opt, 0, dst); |
5369 | 5372 | ||
5370 | if (th->ack) { | 5373 | if (th->ack) { |
5371 | /* rfc793: | 5374 | /* rfc793: |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index a4a3390a5287..657ae334f125 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1257,11 +1257,21 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1257 | tcp_rsk(req)->af_specific = &tcp_request_sock_ipv4_ops; | 1257 | tcp_rsk(req)->af_specific = &tcp_request_sock_ipv4_ops; |
1258 | #endif | 1258 | #endif |
1259 | 1259 | ||
1260 | ireq = inet_rsk(req); | ||
1261 | ireq->loc_addr = daddr; | ||
1262 | ireq->rmt_addr = saddr; | ||
1263 | ireq->no_srccheck = inet_sk(sk)->transparent; | ||
1264 | ireq->opt = tcp_v4_save_options(sk, skb); | ||
1265 | |||
1266 | dst = inet_csk_route_req(sk, req); | ||
1267 | if(!dst) | ||
1268 | goto drop_and_free; | ||
1269 | |||
1260 | tcp_clear_options(&tmp_opt); | 1270 | tcp_clear_options(&tmp_opt); |
1261 | tmp_opt.mss_clamp = 536; | 1271 | tmp_opt.mss_clamp = 536; |
1262 | tmp_opt.user_mss = tcp_sk(sk)->rx_opt.user_mss; | 1272 | tmp_opt.user_mss = tcp_sk(sk)->rx_opt.user_mss; |
1263 | 1273 | ||
1264 | tcp_parse_options(skb, &tmp_opt, 0); | 1274 | tcp_parse_options(skb, &tmp_opt, 0, dst); |
1265 | 1275 | ||
1266 | if (want_cookie && !tmp_opt.saw_tstamp) | 1276 | if (want_cookie && !tmp_opt.saw_tstamp) |
1267 | tcp_clear_options(&tmp_opt); | 1277 | tcp_clear_options(&tmp_opt); |
@@ -1270,14 +1280,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1270 | 1280 | ||
1271 | tcp_openreq_init(req, &tmp_opt, skb); | 1281 | tcp_openreq_init(req, &tmp_opt, skb); |
1272 | 1282 | ||
1273 | ireq = inet_rsk(req); | ||
1274 | ireq->loc_addr = daddr; | ||
1275 | ireq->rmt_addr = saddr; | ||
1276 | ireq->no_srccheck = inet_sk(sk)->transparent; | ||
1277 | ireq->opt = tcp_v4_save_options(sk, skb); | ||
1278 | |||
1279 | if (security_inet_conn_request(sk, skb, req)) | 1283 | if (security_inet_conn_request(sk, skb, req)) |
1280 | goto drop_and_free; | 1284 | goto drop_and_release; |
1281 | 1285 | ||
1282 | if (!want_cookie) | 1286 | if (!want_cookie) |
1283 | TCP_ECN_create_request(req, tcp_hdr(skb)); | 1287 | TCP_ECN_create_request(req, tcp_hdr(skb)); |
@@ -1302,7 +1306,6 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1302 | */ | 1306 | */ |
1303 | if (tmp_opt.saw_tstamp && | 1307 | if (tmp_opt.saw_tstamp && |
1304 | tcp_death_row.sysctl_tw_recycle && | 1308 | tcp_death_row.sysctl_tw_recycle && |
1305 | (dst = inet_csk_route_req(sk, req)) != NULL && | ||
1306 | (peer = rt_get_peer((struct rtable *)dst)) != NULL && | 1309 | (peer = rt_get_peer((struct rtable *)dst)) != NULL && |
1307 | peer->v4daddr == saddr) { | 1310 | peer->v4daddr == saddr) { |
1308 | if (get_seconds() < peer->tcp_ts_stamp + TCP_PAWS_MSL && | 1311 | if (get_seconds() < peer->tcp_ts_stamp + TCP_PAWS_MSL && |
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 015e7c67dc88..463d51b53d37 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -102,7 +102,7 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb, | |||
102 | 102 | ||
103 | if (th->doff > (sizeof(*th) >> 2) && tcptw->tw_ts_recent_stamp) { | 103 | if (th->doff > (sizeof(*th) >> 2) && tcptw->tw_ts_recent_stamp) { |
104 | tmp_opt.tstamp_ok = 1; | 104 | tmp_opt.tstamp_ok = 1; |
105 | tcp_parse_options(skb, &tmp_opt, 1); | 105 | tcp_parse_options(skb, &tmp_opt, 1, NULL); |
106 | 106 | ||
107 | if (tmp_opt.saw_tstamp) { | 107 | if (tmp_opt.saw_tstamp) { |
108 | tmp_opt.ts_recent = tcptw->tw_ts_recent; | 108 | tmp_opt.ts_recent = tcptw->tw_ts_recent; |
@@ -500,10 +500,11 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, | |||
500 | int paws_reject = 0; | 500 | int paws_reject = 0; |
501 | struct tcp_options_received tmp_opt; | 501 | struct tcp_options_received tmp_opt; |
502 | struct sock *child; | 502 | struct sock *child; |
503 | struct dst_entry *dst = inet_csk_route_req(sk, req); | ||
503 | 504 | ||
504 | tmp_opt.saw_tstamp = 0; | 505 | tmp_opt.saw_tstamp = 0; |
505 | if (th->doff > (sizeof(struct tcphdr)>>2)) { | 506 | if (th->doff > (sizeof(struct tcphdr)>>2)) { |
506 | tcp_parse_options(skb, &tmp_opt, 0); | 507 | tcp_parse_options(skb, &tmp_opt, 0, dst); |
507 | 508 | ||
508 | if (tmp_opt.saw_tstamp) { | 509 | if (tmp_opt.saw_tstamp) { |
509 | tmp_opt.ts_recent = req->ts_recent; | 510 | tmp_opt.ts_recent = req->ts_recent; |
@@ -516,6 +517,8 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, | |||
516 | } | 517 | } |
517 | } | 518 | } |
518 | 519 | ||
520 | dst_release(dst); | ||
521 | |||
519 | /* Check for pure retransmitted SYN. */ | 522 | /* Check for pure retransmitted SYN. */ |
520 | if (TCP_SKB_CB(skb)->seq == tcp_rsk(req)->rcv_isn && | 523 | if (TCP_SKB_CB(skb)->seq == tcp_rsk(req)->rcv_isn && |
521 | flg == TCP_FLAG_SYN && | 524 | flg == TCP_FLAG_SYN && |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index c46da533888a..612fc53e0bb9 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -184,13 +184,6 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
184 | 184 | ||
185 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESRECV); | 185 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESRECV); |
186 | 186 | ||
187 | /* check for timestamp cookie support */ | ||
188 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | ||
189 | tcp_parse_options(skb, &tcp_opt, 0); | ||
190 | |||
191 | if (tcp_opt.saw_tstamp) | ||
192 | cookie_check_timestamp(&tcp_opt); | ||
193 | |||
194 | ret = NULL; | 187 | ret = NULL; |
195 | req = inet6_reqsk_alloc(&tcp6_request_sock_ops); | 188 | req = inet6_reqsk_alloc(&tcp6_request_sock_ops); |
196 | if (!req) | 189 | if (!req) |
@@ -224,12 +217,6 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
224 | req->expires = 0UL; | 217 | req->expires = 0UL; |
225 | req->retrans = 0; | 218 | req->retrans = 0; |
226 | ireq->ecn_ok = 0; | 219 | ireq->ecn_ok = 0; |
227 | ireq->snd_wscale = tcp_opt.snd_wscale; | ||
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; | ||
233 | treq->rcv_isn = ntohl(th->seq) - 1; | 220 | treq->rcv_isn = ntohl(th->seq) - 1; |
234 | treq->snt_isn = cookie; | 221 | treq->snt_isn = cookie; |
235 | 222 | ||
@@ -265,6 +252,21 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
265 | goto out_free; | 252 | goto out_free; |
266 | } | 253 | } |
267 | 254 | ||
255 | /* check for timestamp cookie support */ | ||
256 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | ||
257 | tcp_parse_options(skb, &tcp_opt, 0, dst); | ||
258 | |||
259 | if (tcp_opt.saw_tstamp) | ||
260 | cookie_check_timestamp(&tcp_opt); | ||
261 | |||
262 | req->ts_recent = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0; | ||
263 | |||
264 | ireq->snd_wscale = tcp_opt.snd_wscale; | ||
265 | ireq->rcv_wscale = tcp_opt.rcv_wscale; | ||
266 | ireq->sack_ok = tcp_opt.sack_ok; | ||
267 | ireq->wscale_ok = tcp_opt.wscale_ok; | ||
268 | ireq->tstamp_ok = tcp_opt.saw_tstamp; | ||
269 | |||
268 | req->window_clamp = tp->window_clamp ? :dst_metric(dst, RTAX_WINDOW); | 270 | req->window_clamp = tp->window_clamp ? :dst_metric(dst, RTAX_WINDOW); |
269 | tcp_select_initial_window(tcp_full_space(sk), req->mss, | 271 | tcp_select_initial_window(tcp_full_space(sk), req->mss, |
270 | &req->rcv_wnd, &req->window_clamp, | 272 | &req->rcv_wnd, &req->window_clamp, |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index c54ec3615ded..34925f089e07 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1167,6 +1167,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1167 | struct tcp_sock *tp = tcp_sk(sk); | 1167 | struct tcp_sock *tp = tcp_sk(sk); |
1168 | struct request_sock *req = NULL; | 1168 | struct request_sock *req = NULL; |
1169 | __u32 isn = TCP_SKB_CB(skb)->when; | 1169 | __u32 isn = TCP_SKB_CB(skb)->when; |
1170 | struct dst_entry *dst = __sk_dst_get(sk); | ||
1170 | #ifdef CONFIG_SYN_COOKIES | 1171 | #ifdef CONFIG_SYN_COOKIES |
1171 | int want_cookie = 0; | 1172 | int want_cookie = 0; |
1172 | #else | 1173 | #else |
@@ -1205,7 +1206,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1205 | tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); | 1206 | tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); |
1206 | tmp_opt.user_mss = tp->rx_opt.user_mss; | 1207 | tmp_opt.user_mss = tp->rx_opt.user_mss; |
1207 | 1208 | ||
1208 | tcp_parse_options(skb, &tmp_opt, 0); | 1209 | tcp_parse_options(skb, &tmp_opt, 0, dst); |
1209 | 1210 | ||
1210 | if (want_cookie && !tmp_opt.saw_tstamp) | 1211 | if (want_cookie && !tmp_opt.saw_tstamp) |
1211 | tcp_clear_options(&tmp_opt); | 1212 | tcp_clear_options(&tmp_opt); |