diff options
| author | Gilad Ben-Yossef <gilad@codefidence.com> | 2009-10-28 00:15:22 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2009-10-29 04:28:41 -0400 |
| commit | 022c3f7d82f0f1c68018696f2f027b87b9bb45c2 (patch) | |
| tree | ca46c372d815e46f488ec348ae427d34d1f6079e | |
| parent | f55017a93f1a74d50244b1254b9a2bd7ac9bbf7d (diff) | |
Allow tcp_parse_options to consult dst entry
We need tcp_parse_options to be aware of dst_entry to
take into account per dst_entry TCP options settings
Signed-off-by: Gilad Ben-Yossef <gilad@codefidence.com>
Sigend-off-by: Ori Finkelman <ori@comsleep.com>
Sigend-off-by: Yony Amit <yony@comsleep.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -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); |
