diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /net/ipv6/tcp_ipv6.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 176 |
1 files changed, 126 insertions, 50 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 21d100b68b19..075f540ec197 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/jhash.h> | 38 | #include <linux/jhash.h> |
39 | #include <linux/ipsec.h> | 39 | #include <linux/ipsec.h> |
40 | #include <linux/times.h> | 40 | #include <linux/times.h> |
41 | #include <linux/slab.h> | ||
41 | 42 | ||
42 | #include <linux/ipv6.h> | 43 | #include <linux/ipv6.h> |
43 | #include <linux/icmpv6.h> | 44 | #include <linux/icmpv6.h> |
@@ -96,7 +97,7 @@ static void tcp_v6_hash(struct sock *sk) | |||
96 | return; | 97 | return; |
97 | } | 98 | } |
98 | local_bh_disable(); | 99 | local_bh_disable(); |
99 | __inet6_hash(sk); | 100 | __inet6_hash(sk, NULL); |
100 | local_bh_enable(); | 101 | local_bh_enable(); |
101 | } | 102 | } |
102 | } | 103 | } |
@@ -226,10 +227,9 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
226 | #endif | 227 | #endif |
227 | goto failure; | 228 | goto failure; |
228 | } else { | 229 | } else { |
229 | ipv6_addr_set(&np->saddr, 0, 0, htonl(0x0000FFFF), | 230 | ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr); |
230 | inet->saddr); | 231 | ipv6_addr_set_v4mapped(inet->inet_rcv_saddr, |
231 | ipv6_addr_set(&np->rcv_saddr, 0, 0, htonl(0x0000FFFF), | 232 | &np->rcv_saddr); |
232 | inet->rcv_saddr); | ||
233 | } | 233 | } |
234 | 234 | ||
235 | return err; | 235 | return err; |
@@ -243,8 +243,9 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
243 | ipv6_addr_copy(&fl.fl6_src, | 243 | ipv6_addr_copy(&fl.fl6_src, |
244 | (saddr ? saddr : &np->saddr)); | 244 | (saddr ? saddr : &np->saddr)); |
245 | fl.oif = sk->sk_bound_dev_if; | 245 | fl.oif = sk->sk_bound_dev_if; |
246 | fl.mark = sk->sk_mark; | ||
246 | fl.fl_ip_dport = usin->sin6_port; | 247 | fl.fl_ip_dport = usin->sin6_port; |
247 | fl.fl_ip_sport = inet->sport; | 248 | fl.fl_ip_sport = inet->inet_sport; |
248 | 249 | ||
249 | if (np->opt && np->opt->srcrt) { | 250 | if (np->opt && np->opt->srcrt) { |
250 | struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; | 251 | struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; |
@@ -276,7 +277,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
276 | 277 | ||
277 | /* set the source address */ | 278 | /* set the source address */ |
278 | ipv6_addr_copy(&np->saddr, saddr); | 279 | ipv6_addr_copy(&np->saddr, saddr); |
279 | inet->rcv_saddr = LOOPBACK4_IPV6; | 280 | inet->inet_rcv_saddr = LOOPBACK4_IPV6; |
280 | 281 | ||
281 | sk->sk_gso_type = SKB_GSO_TCPV6; | 282 | sk->sk_gso_type = SKB_GSO_TCPV6; |
282 | __ip6_dst_store(sk, dst, NULL, NULL); | 283 | __ip6_dst_store(sk, dst, NULL, NULL); |
@@ -288,7 +289,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
288 | 289 | ||
289 | tp->rx_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); | 290 | tp->rx_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); |
290 | 291 | ||
291 | inet->dport = usin->sin6_port; | 292 | inet->inet_dport = usin->sin6_port; |
292 | 293 | ||
293 | tcp_set_state(sk, TCP_SYN_SENT); | 294 | tcp_set_state(sk, TCP_SYN_SENT); |
294 | err = inet6_hash_connect(&tcp_death_row, sk); | 295 | err = inet6_hash_connect(&tcp_death_row, sk); |
@@ -298,8 +299,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
298 | if (!tp->write_seq) | 299 | if (!tp->write_seq) |
299 | tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32, | 300 | tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32, |
300 | np->daddr.s6_addr32, | 301 | np->daddr.s6_addr32, |
301 | inet->sport, | 302 | inet->inet_sport, |
302 | inet->dport); | 303 | inet->inet_dport); |
303 | 304 | ||
304 | err = tcp_connect(sk); | 305 | err = tcp_connect(sk); |
305 | if (err) | 306 | if (err) |
@@ -311,7 +312,7 @@ late_failure: | |||
311 | tcp_set_state(sk, TCP_CLOSE); | 312 | tcp_set_state(sk, TCP_CLOSE); |
312 | __sk_dst_reset(sk); | 313 | __sk_dst_reset(sk); |
313 | failure: | 314 | failure: |
314 | inet->dport = 0; | 315 | inet->inet_dport = 0; |
315 | sk->sk_route_caps = 0; | 316 | sk->sk_route_caps = 0; |
316 | return err; | 317 | return err; |
317 | } | 318 | } |
@@ -383,8 +384,9 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
383 | ipv6_addr_copy(&fl.fl6_dst, &np->daddr); | 384 | ipv6_addr_copy(&fl.fl6_dst, &np->daddr); |
384 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 385 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); |
385 | fl.oif = sk->sk_bound_dev_if; | 386 | fl.oif = sk->sk_bound_dev_if; |
386 | fl.fl_ip_dport = inet->dport; | 387 | fl.mark = sk->sk_mark; |
387 | fl.fl_ip_sport = inet->sport; | 388 | fl.fl_ip_dport = inet->inet_dport; |
389 | fl.fl_ip_sport = inet->inet_sport; | ||
388 | security_skb_classify_flow(skb, &fl); | 390 | security_skb_classify_flow(skb, &fl); |
389 | 391 | ||
390 | if ((err = ip6_dst_lookup(sk, &dst, &fl))) { | 392 | if ((err = ip6_dst_lookup(sk, &dst, &fl))) { |
@@ -460,7 +462,8 @@ out: | |||
460 | } | 462 | } |
461 | 463 | ||
462 | 464 | ||
463 | static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req) | 465 | static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, |
466 | struct request_values *rvp) | ||
464 | { | 467 | { |
465 | struct inet6_request_sock *treq = inet6_rsk(req); | 468 | struct inet6_request_sock *treq = inet6_rsk(req); |
466 | struct ipv6_pinfo *np = inet6_sk(sk); | 469 | struct ipv6_pinfo *np = inet6_sk(sk); |
@@ -477,6 +480,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req) | |||
477 | ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr); | 480 | ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr); |
478 | fl.fl6_flowlabel = 0; | 481 | fl.fl6_flowlabel = 0; |
479 | fl.oif = treq->iif; | 482 | fl.oif = treq->iif; |
483 | fl.mark = sk->sk_mark; | ||
480 | fl.fl_ip_dport = inet_rsk(req)->rmt_port; | 484 | fl.fl_ip_dport = inet_rsk(req)->rmt_port; |
481 | fl.fl_ip_sport = inet_rsk(req)->loc_port; | 485 | fl.fl_ip_sport = inet_rsk(req)->loc_port; |
482 | security_req_classify_flow(req, &fl); | 486 | security_req_classify_flow(req, &fl); |
@@ -497,7 +501,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req) | |||
497 | if ((err = xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0) | 501 | if ((err = xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0) |
498 | goto done; | 502 | goto done; |
499 | 503 | ||
500 | skb = tcp_make_synack(sk, dst, req); | 504 | skb = tcp_make_synack(sk, dst, req, rvp); |
501 | if (skb) { | 505 | if (skb) { |
502 | struct tcphdr *th = tcp_hdr(skb); | 506 | struct tcphdr *th = tcp_hdr(skb); |
503 | 507 | ||
@@ -517,6 +521,13 @@ done: | |||
517 | return err; | 521 | return err; |
518 | } | 522 | } |
519 | 523 | ||
524 | static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req, | ||
525 | struct request_values *rvp) | ||
526 | { | ||
527 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); | ||
528 | return tcp_v6_send_synack(sk, req, rvp); | ||
529 | } | ||
530 | |||
520 | static inline void syn_flood_warning(struct sk_buff *skb) | 531 | static inline void syn_flood_warning(struct sk_buff *skb) |
521 | { | 532 | { |
522 | #ifdef CONFIG_SYN_COOKIES | 533 | #ifdef CONFIG_SYN_COOKIES |
@@ -873,7 +884,7 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) | |||
873 | 884 | ||
874 | if (genhash || memcmp(hash_location, newhash, 16) != 0) { | 885 | if (genhash || memcmp(hash_location, newhash, 16) != 0) { |
875 | if (net_ratelimit()) { | 886 | if (net_ratelimit()) { |
876 | printk(KERN_INFO "MD5 Hash %s for (%pI6, %u)->(%pI6, %u)\n", | 887 | printk(KERN_INFO "MD5 Hash %s for [%pI6c]:%u->[%pI6c]:%u\n", |
877 | genhash ? "failed" : "mismatch", | 888 | genhash ? "failed" : "mismatch", |
878 | &ip6h->saddr, ntohs(th->source), | 889 | &ip6h->saddr, ntohs(th->source), |
879 | &ip6h->daddr, ntohs(th->dest)); | 890 | &ip6h->daddr, ntohs(th->dest)); |
@@ -887,10 +898,11 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) | |||
887 | struct request_sock_ops tcp6_request_sock_ops __read_mostly = { | 898 | struct request_sock_ops tcp6_request_sock_ops __read_mostly = { |
888 | .family = AF_INET6, | 899 | .family = AF_INET6, |
889 | .obj_size = sizeof(struct tcp6_request_sock), | 900 | .obj_size = sizeof(struct tcp6_request_sock), |
890 | .rtx_syn_ack = tcp_v6_send_synack, | 901 | .rtx_syn_ack = tcp_v6_rtx_synack, |
891 | .send_ack = tcp_v6_reqsk_send_ack, | 902 | .send_ack = tcp_v6_reqsk_send_ack, |
892 | .destructor = tcp_v6_reqsk_destructor, | 903 | .destructor = tcp_v6_reqsk_destructor, |
893 | .send_reset = tcp_v6_send_reset | 904 | .send_reset = tcp_v6_send_reset, |
905 | .syn_ack_timeout = tcp_syn_ack_timeout, | ||
894 | }; | 906 | }; |
895 | 907 | ||
896 | #ifdef CONFIG_TCP_MD5SIG | 908 | #ifdef CONFIG_TCP_MD5SIG |
@@ -1003,7 +1015,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
1003 | skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len); | 1015 | skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len); |
1004 | 1016 | ||
1005 | t1 = (struct tcphdr *) skb_push(buff, tot_len); | 1017 | t1 = (struct tcphdr *) skb_push(buff, tot_len); |
1006 | skb_reset_transport_header(skb); | 1018 | skb_reset_transport_header(buff); |
1007 | 1019 | ||
1008 | /* Swap the send and the receive. */ | 1020 | /* Swap the send and the receive. */ |
1009 | memset(t1, 0, sizeof(*t1)); | 1021 | memset(t1, 0, sizeof(*t1)); |
@@ -1159,11 +1171,13 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | |||
1159 | */ | 1171 | */ |
1160 | static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | 1172 | static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) |
1161 | { | 1173 | { |
1174 | struct tcp_extend_values tmp_ext; | ||
1175 | struct tcp_options_received tmp_opt; | ||
1176 | u8 *hash_location; | ||
1177 | struct request_sock *req; | ||
1162 | struct inet6_request_sock *treq; | 1178 | struct inet6_request_sock *treq; |
1163 | struct ipv6_pinfo *np = inet6_sk(sk); | 1179 | struct ipv6_pinfo *np = inet6_sk(sk); |
1164 | struct tcp_options_received tmp_opt; | ||
1165 | struct tcp_sock *tp = tcp_sk(sk); | 1180 | struct tcp_sock *tp = tcp_sk(sk); |
1166 | struct request_sock *req = NULL; | ||
1167 | __u32 isn = TCP_SKB_CB(skb)->when; | 1181 | __u32 isn = TCP_SKB_CB(skb)->when; |
1168 | #ifdef CONFIG_SYN_COOKIES | 1182 | #ifdef CONFIG_SYN_COOKIES |
1169 | int want_cookie = 0; | 1183 | int want_cookie = 0; |
@@ -1202,8 +1216,52 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1202 | tcp_clear_options(&tmp_opt); | 1216 | tcp_clear_options(&tmp_opt); |
1203 | tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); | 1217 | tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); |
1204 | tmp_opt.user_mss = tp->rx_opt.user_mss; | 1218 | tmp_opt.user_mss = tp->rx_opt.user_mss; |
1219 | tcp_parse_options(skb, &tmp_opt, &hash_location, 0); | ||
1220 | |||
1221 | if (tmp_opt.cookie_plus > 0 && | ||
1222 | tmp_opt.saw_tstamp && | ||
1223 | !tp->rx_opt.cookie_out_never && | ||
1224 | (sysctl_tcp_cookie_size > 0 || | ||
1225 | (tp->cookie_values != NULL && | ||
1226 | tp->cookie_values->cookie_desired > 0))) { | ||
1227 | u8 *c; | ||
1228 | u32 *d; | ||
1229 | u32 *mess = &tmp_ext.cookie_bakery[COOKIE_DIGEST_WORDS]; | ||
1230 | int l = tmp_opt.cookie_plus - TCPOLEN_COOKIE_BASE; | ||
1231 | |||
1232 | if (tcp_cookie_generator(&tmp_ext.cookie_bakery[0]) != 0) | ||
1233 | goto drop_and_free; | ||
1234 | |||
1235 | /* Secret recipe starts with IP addresses */ | ||
1236 | d = &ipv6_hdr(skb)->daddr.s6_addr32[0]; | ||
1237 | *mess++ ^= *d++; | ||
1238 | *mess++ ^= *d++; | ||
1239 | *mess++ ^= *d++; | ||
1240 | *mess++ ^= *d++; | ||
1241 | d = &ipv6_hdr(skb)->saddr.s6_addr32[0]; | ||
1242 | *mess++ ^= *d++; | ||
1243 | *mess++ ^= *d++; | ||
1244 | *mess++ ^= *d++; | ||
1245 | *mess++ ^= *d++; | ||
1246 | |||
1247 | /* plus variable length Initiator Cookie */ | ||
1248 | c = (u8 *)mess; | ||
1249 | while (l-- > 0) | ||
1250 | *c++ ^= *hash_location++; | ||
1205 | 1251 | ||
1206 | tcp_parse_options(skb, &tmp_opt, 0); | 1252 | #ifdef CONFIG_SYN_COOKIES |
1253 | want_cookie = 0; /* not our kind of cookie */ | ||
1254 | #endif | ||
1255 | tmp_ext.cookie_out_never = 0; /* false */ | ||
1256 | tmp_ext.cookie_plus = tmp_opt.cookie_plus; | ||
1257 | } else if (!tp->rx_opt.cookie_in_always) { | ||
1258 | /* redundant indications, but ensure initialization. */ | ||
1259 | tmp_ext.cookie_out_never = 1; /* true */ | ||
1260 | tmp_ext.cookie_plus = 0; | ||
1261 | } else { | ||
1262 | goto drop_and_free; | ||
1263 | } | ||
1264 | tmp_ext.cookie_in_always = tp->rx_opt.cookie_in_always; | ||
1207 | 1265 | ||
1208 | if (want_cookie && !tmp_opt.saw_tstamp) | 1266 | if (want_cookie && !tmp_opt.saw_tstamp) |
1209 | tcp_clear_options(&tmp_opt); | 1267 | tcp_clear_options(&tmp_opt); |
@@ -1236,23 +1294,21 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1236 | 1294 | ||
1237 | isn = tcp_v6_init_sequence(skb); | 1295 | isn = tcp_v6_init_sequence(skb); |
1238 | } | 1296 | } |
1239 | |||
1240 | tcp_rsk(req)->snt_isn = isn; | 1297 | tcp_rsk(req)->snt_isn = isn; |
1241 | 1298 | ||
1242 | security_inet_conn_request(sk, skb, req); | 1299 | security_inet_conn_request(sk, skb, req); |
1243 | 1300 | ||
1244 | if (tcp_v6_send_synack(sk, req)) | 1301 | if (tcp_v6_send_synack(sk, req, |
1245 | goto drop; | 1302 | (struct request_values *)&tmp_ext) || |
1303 | want_cookie) | ||
1304 | goto drop_and_free; | ||
1246 | 1305 | ||
1247 | if (!want_cookie) { | 1306 | inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); |
1248 | inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); | 1307 | return 0; |
1249 | return 0; | ||
1250 | } | ||
1251 | 1308 | ||
1309 | drop_and_free: | ||
1310 | reqsk_free(req); | ||
1252 | drop: | 1311 | drop: |
1253 | if (req) | ||
1254 | reqsk_free(req); | ||
1255 | |||
1256 | return 0; /* don't send reset */ | 1312 | return 0; /* don't send reset */ |
1257 | } | 1313 | } |
1258 | 1314 | ||
@@ -1290,11 +1346,9 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1290 | 1346 | ||
1291 | memcpy(newnp, np, sizeof(struct ipv6_pinfo)); | 1347 | memcpy(newnp, np, sizeof(struct ipv6_pinfo)); |
1292 | 1348 | ||
1293 | ipv6_addr_set(&newnp->daddr, 0, 0, htonl(0x0000FFFF), | 1349 | ipv6_addr_set_v4mapped(newinet->inet_daddr, &newnp->daddr); |
1294 | newinet->daddr); | ||
1295 | 1350 | ||
1296 | ipv6_addr_set(&newnp->saddr, 0, 0, htonl(0x0000FFFF), | 1351 | ipv6_addr_set_v4mapped(newinet->inet_saddr, &newnp->saddr); |
1297 | newinet->saddr); | ||
1298 | 1352 | ||
1299 | ipv6_addr_copy(&newnp->rcv_saddr, &newnp->saddr); | 1353 | ipv6_addr_copy(&newnp->rcv_saddr, &newnp->saddr); |
1300 | 1354 | ||
@@ -1345,6 +1399,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1345 | } | 1399 | } |
1346 | ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr); | 1400 | ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr); |
1347 | fl.oif = sk->sk_bound_dev_if; | 1401 | fl.oif = sk->sk_bound_dev_if; |
1402 | fl.mark = sk->sk_mark; | ||
1348 | fl.fl_ip_dport = inet_rsk(req)->rmt_port; | 1403 | fl.fl_ip_dport = inet_rsk(req)->rmt_port; |
1349 | fl.fl_ip_sport = inet_rsk(req)->loc_port; | 1404 | fl.fl_ip_sport = inet_rsk(req)->loc_port; |
1350 | security_req_classify_flow(req, &fl); | 1405 | security_req_classify_flow(req, &fl); |
@@ -1431,7 +1486,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1431 | newtp->advmss = dst_metric(dst, RTAX_ADVMSS); | 1486 | newtp->advmss = dst_metric(dst, RTAX_ADVMSS); |
1432 | tcp_initialize_rcv_mss(newsk); | 1487 | tcp_initialize_rcv_mss(newsk); |
1433 | 1488 | ||
1434 | newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6; | 1489 | newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6; |
1490 | newinet->inet_rcv_saddr = LOOPBACK4_IPV6; | ||
1435 | 1491 | ||
1436 | #ifdef CONFIG_TCP_MD5SIG | 1492 | #ifdef CONFIG_TCP_MD5SIG |
1437 | /* Copy over the MD5 key from the original socket */ | 1493 | /* Copy over the MD5 key from the original socket */ |
@@ -1448,7 +1504,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1448 | } | 1504 | } |
1449 | #endif | 1505 | #endif |
1450 | 1506 | ||
1451 | __inet6_hash(newsk); | 1507 | __inet6_hash(newsk, NULL); |
1452 | __inet_inherit_port(sk, newsk); | 1508 | __inet_inherit_port(sk, newsk); |
1453 | 1509 | ||
1454 | return newsk; | 1510 | return newsk; |
@@ -1685,8 +1741,11 @@ process: | |||
1685 | if (!tcp_prequeue(sk, skb)) | 1741 | if (!tcp_prequeue(sk, skb)) |
1686 | ret = tcp_v6_do_rcv(sk, skb); | 1742 | ret = tcp_v6_do_rcv(sk, skb); |
1687 | } | 1743 | } |
1688 | } else | 1744 | } else if (unlikely(sk_add_backlog(sk, skb))) { |
1689 | sk_add_backlog(sk, skb); | 1745 | bh_unlock_sock(sk); |
1746 | NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP); | ||
1747 | goto discard_and_relse; | ||
1748 | } | ||
1690 | bh_unlock_sock(sk); | 1749 | bh_unlock_sock(sk); |
1691 | 1750 | ||
1692 | sock_put(sk); | 1751 | sock_put(sk); |
@@ -1848,7 +1907,7 @@ static int tcp_v6_init_sock(struct sock *sk) | |||
1848 | */ | 1907 | */ |
1849 | tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; | 1908 | tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; |
1850 | tp->snd_cwnd_clamp = ~0; | 1909 | tp->snd_cwnd_clamp = ~0; |
1851 | tp->mss_cache = 536; | 1910 | tp->mss_cache = TCP_MSS_DEFAULT; |
1852 | 1911 | ||
1853 | tp->reordering = sysctl_tcp_reordering; | 1912 | tp->reordering = sysctl_tcp_reordering; |
1854 | 1913 | ||
@@ -1864,6 +1923,19 @@ static int tcp_v6_init_sock(struct sock *sk) | |||
1864 | tp->af_specific = &tcp_sock_ipv6_specific; | 1923 | tp->af_specific = &tcp_sock_ipv6_specific; |
1865 | #endif | 1924 | #endif |
1866 | 1925 | ||
1926 | /* TCP Cookie Transactions */ | ||
1927 | if (sysctl_tcp_cookie_size > 0) { | ||
1928 | /* Default, cookies without s_data_payload. */ | ||
1929 | tp->cookie_values = | ||
1930 | kzalloc(sizeof(*tp->cookie_values), | ||
1931 | sk->sk_allocation); | ||
1932 | if (tp->cookie_values != NULL) | ||
1933 | kref_init(&tp->cookie_values->kref); | ||
1934 | } | ||
1935 | /* Presumed zeroed, in order of appearance: | ||
1936 | * cookie_in_always, cookie_out_never, | ||
1937 | * s_data_constant, s_data_in, s_data_out | ||
1938 | */ | ||
1867 | sk->sk_sndbuf = sysctl_tcp_wmem[1]; | 1939 | sk->sk_sndbuf = sysctl_tcp_wmem[1]; |
1868 | sk->sk_rcvbuf = sysctl_tcp_rmem[1]; | 1940 | sk->sk_rcvbuf = sysctl_tcp_rmem[1]; |
1869 | 1941 | ||
@@ -1931,8 +2003,8 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) | |||
1931 | 2003 | ||
1932 | dest = &np->daddr; | 2004 | dest = &np->daddr; |
1933 | src = &np->rcv_saddr; | 2005 | src = &np->rcv_saddr; |
1934 | destp = ntohs(inet->dport); | 2006 | destp = ntohs(inet->inet_dport); |
1935 | srcp = ntohs(inet->sport); | 2007 | srcp = ntohs(inet->inet_sport); |
1936 | 2008 | ||
1937 | if (icsk->icsk_pending == ICSK_TIME_RETRANS) { | 2009 | if (icsk->icsk_pending == ICSK_TIME_RETRANS) { |
1938 | timer_active = 1; | 2010 | timer_active = 1; |
@@ -2045,7 +2117,7 @@ static struct tcp_seq_afinfo tcp6_seq_afinfo = { | |||
2045 | }, | 2117 | }, |
2046 | }; | 2118 | }; |
2047 | 2119 | ||
2048 | int tcp6_proc_init(struct net *net) | 2120 | int __net_init tcp6_proc_init(struct net *net) |
2049 | { | 2121 | { |
2050 | return tcp_proc_register(net, &tcp6_seq_afinfo); | 2122 | return tcp_proc_register(net, &tcp6_seq_afinfo); |
2051 | } | 2123 | } |
@@ -2109,27 +2181,31 @@ static struct inet_protosw tcpv6_protosw = { | |||
2109 | .protocol = IPPROTO_TCP, | 2181 | .protocol = IPPROTO_TCP, |
2110 | .prot = &tcpv6_prot, | 2182 | .prot = &tcpv6_prot, |
2111 | .ops = &inet6_stream_ops, | 2183 | .ops = &inet6_stream_ops, |
2112 | .capability = -1, | ||
2113 | .no_check = 0, | 2184 | .no_check = 0, |
2114 | .flags = INET_PROTOSW_PERMANENT | | 2185 | .flags = INET_PROTOSW_PERMANENT | |
2115 | INET_PROTOSW_ICSK, | 2186 | INET_PROTOSW_ICSK, |
2116 | }; | 2187 | }; |
2117 | 2188 | ||
2118 | static int tcpv6_net_init(struct net *net) | 2189 | static int __net_init tcpv6_net_init(struct net *net) |
2119 | { | 2190 | { |
2120 | return inet_ctl_sock_create(&net->ipv6.tcp_sk, PF_INET6, | 2191 | return inet_ctl_sock_create(&net->ipv6.tcp_sk, PF_INET6, |
2121 | SOCK_RAW, IPPROTO_TCP, net); | 2192 | SOCK_RAW, IPPROTO_TCP, net); |
2122 | } | 2193 | } |
2123 | 2194 | ||
2124 | static void tcpv6_net_exit(struct net *net) | 2195 | static void __net_exit tcpv6_net_exit(struct net *net) |
2125 | { | 2196 | { |
2126 | inet_ctl_sock_destroy(net->ipv6.tcp_sk); | 2197 | inet_ctl_sock_destroy(net->ipv6.tcp_sk); |
2127 | inet_twsk_purge(net, &tcp_hashinfo, &tcp_death_row, AF_INET6); | 2198 | } |
2199 | |||
2200 | static void __net_exit tcpv6_net_exit_batch(struct list_head *net_exit_list) | ||
2201 | { | ||
2202 | inet_twsk_purge(&tcp_hashinfo, &tcp_death_row, AF_INET6); | ||
2128 | } | 2203 | } |
2129 | 2204 | ||
2130 | static struct pernet_operations tcpv6_net_ops = { | 2205 | static struct pernet_operations tcpv6_net_ops = { |
2131 | .init = tcpv6_net_init, | 2206 | .init = tcpv6_net_init, |
2132 | .exit = tcpv6_net_exit, | 2207 | .exit = tcpv6_net_exit, |
2208 | .exit_batch = tcpv6_net_exit_batch, | ||
2133 | }; | 2209 | }; |
2134 | 2210 | ||
2135 | int __init tcpv6_init(void) | 2211 | int __init tcpv6_init(void) |