diff options
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 394 |
1 files changed, 230 insertions, 164 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index fe6d40418c0b..87551ca568cd 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -76,8 +76,8 @@ static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, | |||
76 | 76 | ||
77 | static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); | 77 | static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); |
78 | static void __tcp_v6_send_check(struct sk_buff *skb, | 78 | static void __tcp_v6_send_check(struct sk_buff *skb, |
79 | struct in6_addr *saddr, | 79 | const struct in6_addr *saddr, |
80 | struct in6_addr *daddr); | 80 | const struct in6_addr *daddr); |
81 | 81 | ||
82 | static const struct inet_connection_sock_af_ops ipv6_mapped; | 82 | static const struct inet_connection_sock_af_ops ipv6_mapped; |
83 | static const struct inet_connection_sock_af_ops ipv6_specific; | 83 | static const struct inet_connection_sock_af_ops ipv6_specific; |
@@ -86,7 +86,7 @@ static const struct tcp_sock_af_ops tcp_sock_ipv6_specific; | |||
86 | static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; | 86 | static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; |
87 | #else | 87 | #else |
88 | static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, | 88 | static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, |
89 | struct in6_addr *addr) | 89 | const struct in6_addr *addr) |
90 | { | 90 | { |
91 | return NULL; | 91 | return NULL; |
92 | } | 92 | } |
@@ -106,8 +106,8 @@ static void tcp_v6_hash(struct sock *sk) | |||
106 | } | 106 | } |
107 | 107 | ||
108 | static __inline__ __sum16 tcp_v6_check(int len, | 108 | static __inline__ __sum16 tcp_v6_check(int len, |
109 | struct in6_addr *saddr, | 109 | const struct in6_addr *saddr, |
110 | struct in6_addr *daddr, | 110 | const struct in6_addr *daddr, |
111 | __wsum base) | 111 | __wsum base) |
112 | { | 112 | { |
113 | return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base); | 113 | return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base); |
@@ -130,7 +130,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
130 | struct ipv6_pinfo *np = inet6_sk(sk); | 130 | struct ipv6_pinfo *np = inet6_sk(sk); |
131 | struct tcp_sock *tp = tcp_sk(sk); | 131 | struct tcp_sock *tp = tcp_sk(sk); |
132 | struct in6_addr *saddr = NULL, *final_p, final; | 132 | struct in6_addr *saddr = NULL, *final_p, final; |
133 | struct flowi fl; | 133 | struct rt6_info *rt; |
134 | struct flowi6 fl6; | ||
134 | struct dst_entry *dst; | 135 | struct dst_entry *dst; |
135 | int addr_type; | 136 | int addr_type; |
136 | int err; | 137 | int err; |
@@ -139,16 +140,16 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
139 | return -EINVAL; | 140 | return -EINVAL; |
140 | 141 | ||
141 | if (usin->sin6_family != AF_INET6) | 142 | if (usin->sin6_family != AF_INET6) |
142 | return(-EAFNOSUPPORT); | 143 | return -EAFNOSUPPORT; |
143 | 144 | ||
144 | memset(&fl, 0, sizeof(fl)); | 145 | memset(&fl6, 0, sizeof(fl6)); |
145 | 146 | ||
146 | if (np->sndflow) { | 147 | if (np->sndflow) { |
147 | fl.fl6_flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK; | 148 | fl6.flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK; |
148 | IP6_ECN_flow_init(fl.fl6_flowlabel); | 149 | IP6_ECN_flow_init(fl6.flowlabel); |
149 | if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) { | 150 | if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) { |
150 | struct ip6_flowlabel *flowlabel; | 151 | struct ip6_flowlabel *flowlabel; |
151 | flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); | 152 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
152 | if (flowlabel == NULL) | 153 | if (flowlabel == NULL) |
153 | return -EINVAL; | 154 | return -EINVAL; |
154 | ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst); | 155 | ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst); |
@@ -194,7 +195,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
194 | } | 195 | } |
195 | 196 | ||
196 | ipv6_addr_copy(&np->daddr, &usin->sin6_addr); | 197 | ipv6_addr_copy(&np->daddr, &usin->sin6_addr); |
197 | np->flow_label = fl.fl6_flowlabel; | 198 | np->flow_label = fl6.flowlabel; |
198 | 199 | ||
199 | /* | 200 | /* |
200 | * TCP over IPv4 | 201 | * TCP over IPv4 |
@@ -241,35 +242,27 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
241 | if (!ipv6_addr_any(&np->rcv_saddr)) | 242 | if (!ipv6_addr_any(&np->rcv_saddr)) |
242 | saddr = &np->rcv_saddr; | 243 | saddr = &np->rcv_saddr; |
243 | 244 | ||
244 | fl.proto = IPPROTO_TCP; | 245 | fl6.flowi6_proto = IPPROTO_TCP; |
245 | ipv6_addr_copy(&fl.fl6_dst, &np->daddr); | 246 | ipv6_addr_copy(&fl6.daddr, &np->daddr); |
246 | ipv6_addr_copy(&fl.fl6_src, | 247 | ipv6_addr_copy(&fl6.saddr, |
247 | (saddr ? saddr : &np->saddr)); | 248 | (saddr ? saddr : &np->saddr)); |
248 | fl.oif = sk->sk_bound_dev_if; | 249 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
249 | fl.mark = sk->sk_mark; | 250 | fl6.flowi6_mark = sk->sk_mark; |
250 | fl.fl_ip_dport = usin->sin6_port; | 251 | fl6.fl6_dport = usin->sin6_port; |
251 | fl.fl_ip_sport = inet->inet_sport; | 252 | fl6.fl6_sport = inet->inet_sport; |
252 | 253 | ||
253 | final_p = fl6_update_dst(&fl, np->opt, &final); | 254 | final_p = fl6_update_dst(&fl6, np->opt, &final); |
254 | 255 | ||
255 | security_sk_classify_flow(sk, &fl); | 256 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
256 | 257 | ||
257 | err = ip6_dst_lookup(sk, &dst, &fl); | 258 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true); |
258 | if (err) | 259 | if (IS_ERR(dst)) { |
260 | err = PTR_ERR(dst); | ||
259 | goto failure; | 261 | goto failure; |
260 | if (final_p) | ||
261 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
262 | |||
263 | err = __xfrm_lookup(sock_net(sk), &dst, &fl, sk, XFRM_LOOKUP_WAIT); | ||
264 | if (err < 0) { | ||
265 | if (err == -EREMOTE) | ||
266 | err = ip6_dst_blackhole(sk, &dst, &fl); | ||
267 | if (err < 0) | ||
268 | goto failure; | ||
269 | } | 262 | } |
270 | 263 | ||
271 | if (saddr == NULL) { | 264 | if (saddr == NULL) { |
272 | saddr = &fl.fl6_src; | 265 | saddr = &fl6.saddr; |
273 | ipv6_addr_copy(&np->rcv_saddr, saddr); | 266 | ipv6_addr_copy(&np->rcv_saddr, saddr); |
274 | } | 267 | } |
275 | 268 | ||
@@ -280,6 +273,26 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
280 | sk->sk_gso_type = SKB_GSO_TCPV6; | 273 | sk->sk_gso_type = SKB_GSO_TCPV6; |
281 | __ip6_dst_store(sk, dst, NULL, NULL); | 274 | __ip6_dst_store(sk, dst, NULL, NULL); |
282 | 275 | ||
276 | rt = (struct rt6_info *) dst; | ||
277 | if (tcp_death_row.sysctl_tw_recycle && | ||
278 | !tp->rx_opt.ts_recent_stamp && | ||
279 | ipv6_addr_equal(&rt->rt6i_dst.addr, &np->daddr)) { | ||
280 | struct inet_peer *peer = rt6_get_peer(rt); | ||
281 | /* | ||
282 | * VJ's idea. We save last timestamp seen from | ||
283 | * the destination in peer table, when entering state | ||
284 | * TIME-WAIT * and initialize rx_opt.ts_recent from it, | ||
285 | * when trying new connection. | ||
286 | */ | ||
287 | if (peer) { | ||
288 | inet_peer_refcheck(peer); | ||
289 | if ((u32)get_seconds() - peer->tcp_ts_stamp <= TCP_PAWS_MSL) { | ||
290 | tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp; | ||
291 | tp->rx_opt.ts_recent = peer->tcp_ts; | ||
292 | } | ||
293 | } | ||
294 | } | ||
295 | |||
283 | icsk->icsk_ext_hdr_len = 0; | 296 | icsk->icsk_ext_hdr_len = 0; |
284 | if (np->opt) | 297 | if (np->opt) |
285 | icsk->icsk_ext_hdr_len = (np->opt->opt_flen + | 298 | icsk->icsk_ext_hdr_len = (np->opt->opt_flen + |
@@ -318,7 +331,7 @@ failure: | |||
318 | static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 331 | static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
319 | u8 type, u8 code, int offset, __be32 info) | 332 | u8 type, u8 code, int offset, __be32 info) |
320 | { | 333 | { |
321 | struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; | 334 | const struct ipv6hdr *hdr = (const struct ipv6hdr*)skb->data; |
322 | const struct tcphdr *th = (struct tcphdr *)(skb->data+offset); | 335 | const struct tcphdr *th = (struct tcphdr *)(skb->data+offset); |
323 | struct ipv6_pinfo *np; | 336 | struct ipv6_pinfo *np; |
324 | struct sock *sk; | 337 | struct sock *sk; |
@@ -364,7 +377,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
364 | np = inet6_sk(sk); | 377 | np = inet6_sk(sk); |
365 | 378 | ||
366 | if (type == ICMPV6_PKT_TOOBIG) { | 379 | if (type == ICMPV6_PKT_TOOBIG) { |
367 | struct dst_entry *dst = NULL; | 380 | struct dst_entry *dst; |
368 | 381 | ||
369 | if (sock_owned_by_user(sk)) | 382 | if (sock_owned_by_user(sk)) |
370 | goto out; | 383 | goto out; |
@@ -376,29 +389,25 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
376 | 389 | ||
377 | if (dst == NULL) { | 390 | if (dst == NULL) { |
378 | struct inet_sock *inet = inet_sk(sk); | 391 | struct inet_sock *inet = inet_sk(sk); |
379 | struct flowi fl; | 392 | struct flowi6 fl6; |
380 | 393 | ||
381 | /* BUGGG_FUTURE: Again, it is not clear how | 394 | /* BUGGG_FUTURE: Again, it is not clear how |
382 | to handle rthdr case. Ignore this complexity | 395 | to handle rthdr case. Ignore this complexity |
383 | for now. | 396 | for now. |
384 | */ | 397 | */ |
385 | memset(&fl, 0, sizeof(fl)); | 398 | memset(&fl6, 0, sizeof(fl6)); |
386 | fl.proto = IPPROTO_TCP; | 399 | fl6.flowi6_proto = IPPROTO_TCP; |
387 | ipv6_addr_copy(&fl.fl6_dst, &np->daddr); | 400 | ipv6_addr_copy(&fl6.daddr, &np->daddr); |
388 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 401 | ipv6_addr_copy(&fl6.saddr, &np->saddr); |
389 | fl.oif = sk->sk_bound_dev_if; | 402 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
390 | fl.mark = sk->sk_mark; | 403 | fl6.flowi6_mark = sk->sk_mark; |
391 | fl.fl_ip_dport = inet->inet_dport; | 404 | fl6.fl6_dport = inet->inet_dport; |
392 | fl.fl_ip_sport = inet->inet_sport; | 405 | fl6.fl6_sport = inet->inet_sport; |
393 | security_skb_classify_flow(skb, &fl); | 406 | security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); |
394 | 407 | ||
395 | if ((err = ip6_dst_lookup(sk, &dst, &fl))) { | 408 | dst = ip6_dst_lookup_flow(sk, &fl6, NULL, false); |
396 | sk->sk_err_soft = -err; | 409 | if (IS_ERR(dst)) { |
397 | goto out; | 410 | sk->sk_err_soft = -PTR_ERR(dst); |
398 | } | ||
399 | |||
400 | if ((err = xfrm_lookup(net, &dst, &fl, sk, 0)) < 0) { | ||
401 | sk->sk_err_soft = -err; | ||
402 | goto out; | 411 | goto out; |
403 | } | 412 | } |
404 | 413 | ||
@@ -473,38 +482,37 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
473 | struct sk_buff * skb; | 482 | struct sk_buff * skb; |
474 | struct ipv6_txoptions *opt = NULL; | 483 | struct ipv6_txoptions *opt = NULL; |
475 | struct in6_addr * final_p, final; | 484 | struct in6_addr * final_p, final; |
476 | struct flowi fl; | 485 | struct flowi6 fl6; |
477 | struct dst_entry *dst; | 486 | struct dst_entry *dst; |
478 | int err = -1; | 487 | int err; |
479 | 488 | ||
480 | memset(&fl, 0, sizeof(fl)); | 489 | memset(&fl6, 0, sizeof(fl6)); |
481 | fl.proto = IPPROTO_TCP; | 490 | fl6.flowi6_proto = IPPROTO_TCP; |
482 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); | 491 | ipv6_addr_copy(&fl6.daddr, &treq->rmt_addr); |
483 | ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr); | 492 | ipv6_addr_copy(&fl6.saddr, &treq->loc_addr); |
484 | fl.fl6_flowlabel = 0; | 493 | fl6.flowlabel = 0; |
485 | fl.oif = treq->iif; | 494 | fl6.flowi6_oif = treq->iif; |
486 | fl.mark = sk->sk_mark; | 495 | fl6.flowi6_mark = sk->sk_mark; |
487 | fl.fl_ip_dport = inet_rsk(req)->rmt_port; | 496 | fl6.fl6_dport = inet_rsk(req)->rmt_port; |
488 | fl.fl_ip_sport = inet_rsk(req)->loc_port; | 497 | fl6.fl6_sport = inet_rsk(req)->loc_port; |
489 | security_req_classify_flow(req, &fl); | 498 | security_req_classify_flow(req, flowi6_to_flowi(&fl6)); |
490 | 499 | ||
491 | opt = np->opt; | 500 | opt = np->opt; |
492 | final_p = fl6_update_dst(&fl, opt, &final); | 501 | final_p = fl6_update_dst(&fl6, opt, &final); |
493 | 502 | ||
494 | err = ip6_dst_lookup(sk, &dst, &fl); | 503 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); |
495 | if (err) | 504 | if (IS_ERR(dst)) { |
496 | goto done; | 505 | err = PTR_ERR(dst); |
497 | if (final_p) | 506 | dst = NULL; |
498 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
499 | if ((err = xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0) | ||
500 | goto done; | 507 | goto done; |
501 | 508 | } | |
502 | skb = tcp_make_synack(sk, dst, req, rvp); | 509 | skb = tcp_make_synack(sk, dst, req, rvp); |
510 | err = -ENOMEM; | ||
503 | if (skb) { | 511 | if (skb) { |
504 | __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); | 512 | __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); |
505 | 513 | ||
506 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); | 514 | ipv6_addr_copy(&fl6.daddr, &treq->rmt_addr); |
507 | err = ip6_xmit(sk, skb, &fl, opt); | 515 | err = ip6_xmit(sk, skb, &fl6, opt); |
508 | err = net_xmit_eval(err); | 516 | err = net_xmit_eval(err); |
509 | } | 517 | } |
510 | 518 | ||
@@ -543,7 +551,7 @@ static void tcp_v6_reqsk_destructor(struct request_sock *req) | |||
543 | 551 | ||
544 | #ifdef CONFIG_TCP_MD5SIG | 552 | #ifdef CONFIG_TCP_MD5SIG |
545 | static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, | 553 | static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, |
546 | struct in6_addr *addr) | 554 | const struct in6_addr *addr) |
547 | { | 555 | { |
548 | struct tcp_sock *tp = tcp_sk(sk); | 556 | struct tcp_sock *tp = tcp_sk(sk); |
549 | int i; | 557 | int i; |
@@ -572,7 +580,7 @@ static struct tcp_md5sig_key *tcp_v6_reqsk_md5_lookup(struct sock *sk, | |||
572 | return tcp_v6_md5_do_lookup(sk, &inet6_rsk(req)->rmt_addr); | 580 | return tcp_v6_md5_do_lookup(sk, &inet6_rsk(req)->rmt_addr); |
573 | } | 581 | } |
574 | 582 | ||
575 | static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer, | 583 | static int tcp_v6_md5_do_add(struct sock *sk, const struct in6_addr *peer, |
576 | char *newkey, u8 newkeylen) | 584 | char *newkey, u8 newkeylen) |
577 | { | 585 | { |
578 | /* Add key to the list */ | 586 | /* Add key to the list */ |
@@ -637,7 +645,7 @@ static int tcp_v6_md5_add_func(struct sock *sk, struct sock *addr_sk, | |||
637 | newkey, newkeylen); | 645 | newkey, newkeylen); |
638 | } | 646 | } |
639 | 647 | ||
640 | static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer) | 648 | static int tcp_v6_md5_do_del(struct sock *sk, const struct in6_addr *peer) |
641 | { | 649 | { |
642 | struct tcp_sock *tp = tcp_sk(sk); | 650 | struct tcp_sock *tp = tcp_sk(sk); |
643 | int i; | 651 | int i; |
@@ -745,8 +753,8 @@ static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval, | |||
745 | } | 753 | } |
746 | 754 | ||
747 | static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, | 755 | static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, |
748 | struct in6_addr *daddr, | 756 | const struct in6_addr *daddr, |
749 | struct in6_addr *saddr, int nbytes) | 757 | const struct in6_addr *saddr, int nbytes) |
750 | { | 758 | { |
751 | struct tcp6_pseudohdr *bp; | 759 | struct tcp6_pseudohdr *bp; |
752 | struct scatterlist sg; | 760 | struct scatterlist sg; |
@@ -763,7 +771,7 @@ static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, | |||
763 | } | 771 | } |
764 | 772 | ||
765 | static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key, | 773 | static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key, |
766 | struct in6_addr *daddr, struct in6_addr *saddr, | 774 | const struct in6_addr *daddr, struct in6_addr *saddr, |
767 | struct tcphdr *th) | 775 | struct tcphdr *th) |
768 | { | 776 | { |
769 | struct tcp_md5sig_pool *hp; | 777 | struct tcp_md5sig_pool *hp; |
@@ -799,7 +807,7 @@ static int tcp_v6_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key, | |||
799 | struct sock *sk, struct request_sock *req, | 807 | struct sock *sk, struct request_sock *req, |
800 | struct sk_buff *skb) | 808 | struct sk_buff *skb) |
801 | { | 809 | { |
802 | struct in6_addr *saddr, *daddr; | 810 | const struct in6_addr *saddr, *daddr; |
803 | struct tcp_md5sig_pool *hp; | 811 | struct tcp_md5sig_pool *hp; |
804 | struct hash_desc *desc; | 812 | struct hash_desc *desc; |
805 | struct tcphdr *th = tcp_hdr(skb); | 813 | struct tcphdr *th = tcp_hdr(skb); |
@@ -811,7 +819,7 @@ static int tcp_v6_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key, | |||
811 | saddr = &inet6_rsk(req)->loc_addr; | 819 | saddr = &inet6_rsk(req)->loc_addr; |
812 | daddr = &inet6_rsk(req)->rmt_addr; | 820 | daddr = &inet6_rsk(req)->rmt_addr; |
813 | } else { | 821 | } else { |
814 | struct ipv6hdr *ip6h = ipv6_hdr(skb); | 822 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); |
815 | saddr = &ip6h->saddr; | 823 | saddr = &ip6h->saddr; |
816 | daddr = &ip6h->daddr; | 824 | daddr = &ip6h->daddr; |
817 | } | 825 | } |
@@ -849,7 +857,7 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) | |||
849 | { | 857 | { |
850 | __u8 *hash_location = NULL; | 858 | __u8 *hash_location = NULL; |
851 | struct tcp_md5sig_key *hash_expected; | 859 | struct tcp_md5sig_key *hash_expected; |
852 | struct ipv6hdr *ip6h = ipv6_hdr(skb); | 860 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); |
853 | struct tcphdr *th = tcp_hdr(skb); | 861 | struct tcphdr *th = tcp_hdr(skb); |
854 | int genhash; | 862 | int genhash; |
855 | u8 newhash[16]; | 863 | u8 newhash[16]; |
@@ -906,14 +914,8 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { | |||
906 | }; | 914 | }; |
907 | #endif | 915 | #endif |
908 | 916 | ||
909 | static struct timewait_sock_ops tcp6_timewait_sock_ops = { | ||
910 | .twsk_obj_size = sizeof(struct tcp6_timewait_sock), | ||
911 | .twsk_unique = tcp_twsk_unique, | ||
912 | .twsk_destructor= tcp_twsk_destructor, | ||
913 | }; | ||
914 | |||
915 | static void __tcp_v6_send_check(struct sk_buff *skb, | 917 | static void __tcp_v6_send_check(struct sk_buff *skb, |
916 | struct in6_addr *saddr, struct in6_addr *daddr) | 918 | const struct in6_addr *saddr, const struct in6_addr *daddr) |
917 | { | 919 | { |
918 | struct tcphdr *th = tcp_hdr(skb); | 920 | struct tcphdr *th = tcp_hdr(skb); |
919 | 921 | ||
@@ -937,7 +939,7 @@ static void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb) | |||
937 | 939 | ||
938 | static int tcp_v6_gso_send_check(struct sk_buff *skb) | 940 | static int tcp_v6_gso_send_check(struct sk_buff *skb) |
939 | { | 941 | { |
940 | struct ipv6hdr *ipv6h; | 942 | const struct ipv6hdr *ipv6h; |
941 | struct tcphdr *th; | 943 | struct tcphdr *th; |
942 | 944 | ||
943 | if (!pskb_may_pull(skb, sizeof(*th))) | 945 | if (!pskb_may_pull(skb, sizeof(*th))) |
@@ -955,7 +957,7 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb) | |||
955 | static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, | 957 | static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, |
956 | struct sk_buff *skb) | 958 | struct sk_buff *skb) |
957 | { | 959 | { |
958 | struct ipv6hdr *iph = skb_gro_network_header(skb); | 960 | const struct ipv6hdr *iph = skb_gro_network_header(skb); |
959 | 961 | ||
960 | switch (skb->ip_summed) { | 962 | switch (skb->ip_summed) { |
961 | case CHECKSUM_COMPLETE: | 963 | case CHECKSUM_COMPLETE: |
@@ -976,7 +978,7 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, | |||
976 | 978 | ||
977 | static int tcp6_gro_complete(struct sk_buff *skb) | 979 | static int tcp6_gro_complete(struct sk_buff *skb) |
978 | { | 980 | { |
979 | struct ipv6hdr *iph = ipv6_hdr(skb); | 981 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
980 | struct tcphdr *th = tcp_hdr(skb); | 982 | struct tcphdr *th = tcp_hdr(skb); |
981 | 983 | ||
982 | th->check = ~tcp_v6_check(skb->len - skb_transport_offset(skb), | 984 | th->check = ~tcp_v6_check(skb->len - skb_transport_offset(skb), |
@@ -991,7 +993,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
991 | { | 993 | { |
992 | struct tcphdr *th = tcp_hdr(skb), *t1; | 994 | struct tcphdr *th = tcp_hdr(skb), *t1; |
993 | struct sk_buff *buff; | 995 | struct sk_buff *buff; |
994 | struct flowi fl; | 996 | struct flowi6 fl6; |
995 | struct net *net = dev_net(skb_dst(skb)->dev); | 997 | struct net *net = dev_net(skb_dst(skb)->dev); |
996 | struct sock *ctl_sk = net->ipv6.tcp_sk; | 998 | struct sock *ctl_sk = net->ipv6.tcp_sk; |
997 | unsigned int tot_len = sizeof(struct tcphdr); | 999 | unsigned int tot_len = sizeof(struct tcphdr); |
@@ -1045,34 +1047,33 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
1045 | } | 1047 | } |
1046 | #endif | 1048 | #endif |
1047 | 1049 | ||
1048 | memset(&fl, 0, sizeof(fl)); | 1050 | memset(&fl6, 0, sizeof(fl6)); |
1049 | ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); | 1051 | ipv6_addr_copy(&fl6.daddr, &ipv6_hdr(skb)->saddr); |
1050 | ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr); | 1052 | ipv6_addr_copy(&fl6.saddr, &ipv6_hdr(skb)->daddr); |
1051 | 1053 | ||
1052 | buff->ip_summed = CHECKSUM_PARTIAL; | 1054 | buff->ip_summed = CHECKSUM_PARTIAL; |
1053 | buff->csum = 0; | 1055 | buff->csum = 0; |
1054 | 1056 | ||
1055 | __tcp_v6_send_check(buff, &fl.fl6_src, &fl.fl6_dst); | 1057 | __tcp_v6_send_check(buff, &fl6.saddr, &fl6.daddr); |
1056 | 1058 | ||
1057 | fl.proto = IPPROTO_TCP; | 1059 | fl6.flowi6_proto = IPPROTO_TCP; |
1058 | fl.oif = inet6_iif(skb); | 1060 | fl6.flowi6_oif = inet6_iif(skb); |
1059 | fl.fl_ip_dport = t1->dest; | 1061 | fl6.fl6_dport = t1->dest; |
1060 | fl.fl_ip_sport = t1->source; | 1062 | fl6.fl6_sport = t1->source; |
1061 | security_skb_classify_flow(skb, &fl); | 1063 | security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); |
1062 | 1064 | ||
1063 | /* Pass a socket to ip6_dst_lookup either it is for RST | 1065 | /* Pass a socket to ip6_dst_lookup either it is for RST |
1064 | * Underlying function will use this to retrieve the network | 1066 | * Underlying function will use this to retrieve the network |
1065 | * namespace | 1067 | * namespace |
1066 | */ | 1068 | */ |
1067 | if (!ip6_dst_lookup(ctl_sk, &dst, &fl)) { | 1069 | dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL, false); |
1068 | if (xfrm_lookup(net, &dst, &fl, NULL, 0) >= 0) { | 1070 | if (!IS_ERR(dst)) { |
1069 | skb_dst_set(buff, dst); | 1071 | skb_dst_set(buff, dst); |
1070 | ip6_xmit(ctl_sk, buff, &fl, NULL); | 1072 | ip6_xmit(ctl_sk, buff, &fl6, NULL); |
1071 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); | 1073 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); |
1072 | if (rst) | 1074 | if (rst) |
1073 | TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); | 1075 | TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); |
1074 | return; | 1076 | return; |
1075 | } | ||
1076 | } | 1077 | } |
1077 | 1078 | ||
1078 | kfree_skb(buff); | 1079 | kfree_skb(buff); |
@@ -1176,6 +1177,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1176 | struct ipv6_pinfo *np = inet6_sk(sk); | 1177 | struct ipv6_pinfo *np = inet6_sk(sk); |
1177 | struct tcp_sock *tp = tcp_sk(sk); | 1178 | struct tcp_sock *tp = tcp_sk(sk); |
1178 | __u32 isn = TCP_SKB_CB(skb)->when; | 1179 | __u32 isn = TCP_SKB_CB(skb)->when; |
1180 | struct dst_entry *dst = NULL; | ||
1179 | #ifdef CONFIG_SYN_COOKIES | 1181 | #ifdef CONFIG_SYN_COOKIES |
1180 | int want_cookie = 0; | 1182 | int want_cookie = 0; |
1181 | #else | 1183 | #else |
@@ -1273,6 +1275,8 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1273 | TCP_ECN_create_request(req, tcp_hdr(skb)); | 1275 | TCP_ECN_create_request(req, tcp_hdr(skb)); |
1274 | 1276 | ||
1275 | if (!isn) { | 1277 | if (!isn) { |
1278 | struct inet_peer *peer = NULL; | ||
1279 | |||
1276 | if (ipv6_opt_accepted(sk, skb) || | 1280 | if (ipv6_opt_accepted(sk, skb) || |
1277 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || | 1281 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || |
1278 | np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { | 1282 | np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { |
@@ -1285,13 +1289,57 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1285 | if (!sk->sk_bound_dev_if && | 1289 | if (!sk->sk_bound_dev_if && |
1286 | ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) | 1290 | ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) |
1287 | treq->iif = inet6_iif(skb); | 1291 | treq->iif = inet6_iif(skb); |
1288 | if (!want_cookie) { | 1292 | |
1289 | isn = tcp_v6_init_sequence(skb); | 1293 | if (want_cookie) { |
1290 | } else { | ||
1291 | isn = cookie_v6_init_sequence(sk, skb, &req->mss); | 1294 | isn = cookie_v6_init_sequence(sk, skb, &req->mss); |
1292 | req->cookie_ts = tmp_opt.tstamp_ok; | 1295 | req->cookie_ts = tmp_opt.tstamp_ok; |
1296 | goto have_isn; | ||
1297 | } | ||
1298 | |||
1299 | /* VJ's idea. We save last timestamp seen | ||
1300 | * from the destination in peer table, when entering | ||
1301 | * state TIME-WAIT, and check against it before | ||
1302 | * accepting new connection request. | ||
1303 | * | ||
1304 | * If "isn" is not zero, this request hit alive | ||
1305 | * timewait bucket, so that all the necessary checks | ||
1306 | * are made in the function processing timewait state. | ||
1307 | */ | ||
1308 | if (tmp_opt.saw_tstamp && | ||
1309 | tcp_death_row.sysctl_tw_recycle && | ||
1310 | (dst = inet6_csk_route_req(sk, req)) != NULL && | ||
1311 | (peer = rt6_get_peer((struct rt6_info *)dst)) != NULL && | ||
1312 | ipv6_addr_equal((struct in6_addr *)peer->daddr.addr.a6, | ||
1313 | &treq->rmt_addr)) { | ||
1314 | inet_peer_refcheck(peer); | ||
1315 | if ((u32)get_seconds() - peer->tcp_ts_stamp < TCP_PAWS_MSL && | ||
1316 | (s32)(peer->tcp_ts - req->ts_recent) > | ||
1317 | TCP_PAWS_WINDOW) { | ||
1318 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED); | ||
1319 | goto drop_and_release; | ||
1320 | } | ||
1293 | } | 1321 | } |
1322 | /* Kill the following clause, if you dislike this way. */ | ||
1323 | else if (!sysctl_tcp_syncookies && | ||
1324 | (sysctl_max_syn_backlog - inet_csk_reqsk_queue_len(sk) < | ||
1325 | (sysctl_max_syn_backlog >> 2)) && | ||
1326 | (!peer || !peer->tcp_ts_stamp) && | ||
1327 | (!dst || !dst_metric(dst, RTAX_RTT))) { | ||
1328 | /* Without syncookies last quarter of | ||
1329 | * backlog is filled with destinations, | ||
1330 | * proven to be alive. | ||
1331 | * It means that we continue to communicate | ||
1332 | * to destinations, already remembered | ||
1333 | * to the moment of synflood. | ||
1334 | */ | ||
1335 | LIMIT_NETDEBUG(KERN_DEBUG "TCP: drop open request from %pI6/%u\n", | ||
1336 | &treq->rmt_addr, ntohs(tcp_hdr(skb)->source)); | ||
1337 | goto drop_and_release; | ||
1338 | } | ||
1339 | |||
1340 | isn = tcp_v6_init_sequence(skb); | ||
1294 | } | 1341 | } |
1342 | have_isn: | ||
1295 | tcp_rsk(req)->snt_isn = isn; | 1343 | tcp_rsk(req)->snt_isn = isn; |
1296 | 1344 | ||
1297 | security_inet_conn_request(sk, skb, req); | 1345 | security_inet_conn_request(sk, skb, req); |
@@ -1304,6 +1352,8 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1304 | inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); | 1352 | inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); |
1305 | return 0; | 1353 | return 0; |
1306 | 1354 | ||
1355 | drop_and_release: | ||
1356 | dst_release(dst); | ||
1307 | drop_and_free: | 1357 | drop_and_free: |
1308 | reqsk_free(req); | 1358 | reqsk_free(req); |
1309 | drop: | 1359 | drop: |
@@ -1382,34 +1432,15 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1382 | if (sk_acceptq_is_full(sk)) | 1432 | if (sk_acceptq_is_full(sk)) |
1383 | goto out_overflow; | 1433 | goto out_overflow; |
1384 | 1434 | ||
1385 | if (dst == NULL) { | 1435 | if (!dst) { |
1386 | struct in6_addr *final_p, final; | 1436 | dst = inet6_csk_route_req(sk, req); |
1387 | struct flowi fl; | 1437 | if (!dst) |
1388 | |||
1389 | memset(&fl, 0, sizeof(fl)); | ||
1390 | fl.proto = IPPROTO_TCP; | ||
1391 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); | ||
1392 | final_p = fl6_update_dst(&fl, opt, &final); | ||
1393 | ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr); | ||
1394 | fl.oif = sk->sk_bound_dev_if; | ||
1395 | fl.mark = sk->sk_mark; | ||
1396 | fl.fl_ip_dport = inet_rsk(req)->rmt_port; | ||
1397 | fl.fl_ip_sport = inet_rsk(req)->loc_port; | ||
1398 | security_req_classify_flow(req, &fl); | ||
1399 | |||
1400 | if (ip6_dst_lookup(sk, &dst, &fl)) | ||
1401 | goto out; | ||
1402 | |||
1403 | if (final_p) | ||
1404 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
1405 | |||
1406 | if ((xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0) | ||
1407 | goto out; | 1438 | goto out; |
1408 | } | 1439 | } |
1409 | 1440 | ||
1410 | newsk = tcp_create_openreq_child(sk, req, skb); | 1441 | newsk = tcp_create_openreq_child(sk, req, skb); |
1411 | if (newsk == NULL) | 1442 | if (newsk == NULL) |
1412 | goto out; | 1443 | goto out_nonewsk; |
1413 | 1444 | ||
1414 | /* | 1445 | /* |
1415 | * No need to charge this sock to the relevant IPv6 refcnt debug socks | 1446 | * No need to charge this sock to the relevant IPv6 refcnt debug socks |
@@ -1438,7 +1469,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1438 | 1469 | ||
1439 | First: no IPv4 options. | 1470 | First: no IPv4 options. |
1440 | */ | 1471 | */ |
1441 | newinet->opt = NULL; | 1472 | newinet->inet_opt = NULL; |
1442 | newnp->ipv6_fl_list = NULL; | 1473 | newnp->ipv6_fl_list = NULL; |
1443 | 1474 | ||
1444 | /* Clone RX bits */ | 1475 | /* Clone RX bits */ |
@@ -1476,7 +1507,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1476 | 1507 | ||
1477 | tcp_mtup_init(newsk); | 1508 | tcp_mtup_init(newsk); |
1478 | tcp_sync_mss(newsk, dst_mtu(dst)); | 1509 | tcp_sync_mss(newsk, dst_mtu(dst)); |
1479 | newtp->advmss = dst_metric(dst, RTAX_ADVMSS); | 1510 | newtp->advmss = dst_metric_advmss(dst); |
1480 | tcp_initialize_rcv_mss(newsk); | 1511 | tcp_initialize_rcv_mss(newsk); |
1481 | 1512 | ||
1482 | newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6; | 1513 | newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6; |
@@ -1497,18 +1528,22 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1497 | } | 1528 | } |
1498 | #endif | 1529 | #endif |
1499 | 1530 | ||
1531 | if (__inet_inherit_port(sk, newsk) < 0) { | ||
1532 | sock_put(newsk); | ||
1533 | goto out; | ||
1534 | } | ||
1500 | __inet6_hash(newsk, NULL); | 1535 | __inet6_hash(newsk, NULL); |
1501 | __inet_inherit_port(sk, newsk); | ||
1502 | 1536 | ||
1503 | return newsk; | 1537 | return newsk; |
1504 | 1538 | ||
1505 | out_overflow: | 1539 | out_overflow: |
1506 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); | 1540 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); |
1507 | out: | 1541 | out_nonewsk: |
1508 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | ||
1509 | if (opt && opt != np->opt) | 1542 | if (opt && opt != np->opt) |
1510 | sock_kfree_s(sk, opt, opt->tot_len); | 1543 | sock_kfree_s(sk, opt, opt->tot_len); |
1511 | dst_release(dst); | 1544 | dst_release(dst); |
1545 | out: | ||
1546 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | ||
1512 | return NULL; | 1547 | return NULL; |
1513 | } | 1548 | } |
1514 | 1549 | ||
@@ -1587,10 +1622,9 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1587 | opt_skb = skb_clone(skb, GFP_ATOMIC); | 1622 | opt_skb = skb_clone(skb, GFP_ATOMIC); |
1588 | 1623 | ||
1589 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ | 1624 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ |
1590 | TCP_CHECK_TIMER(sk); | 1625 | sock_rps_save_rxhash(sk, skb->rxhash); |
1591 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) | 1626 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) |
1592 | goto reset; | 1627 | goto reset; |
1593 | TCP_CHECK_TIMER(sk); | ||
1594 | if (opt_skb) | 1628 | if (opt_skb) |
1595 | goto ipv6_pktoptions; | 1629 | goto ipv6_pktoptions; |
1596 | return 0; | 1630 | return 0; |
@@ -1610,18 +1644,18 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1610 | * the new socket.. | 1644 | * the new socket.. |
1611 | */ | 1645 | */ |
1612 | if(nsk != sk) { | 1646 | if(nsk != sk) { |
1647 | sock_rps_save_rxhash(nsk, skb->rxhash); | ||
1613 | if (tcp_child_process(sk, nsk, skb)) | 1648 | if (tcp_child_process(sk, nsk, skb)) |
1614 | goto reset; | 1649 | goto reset; |
1615 | if (opt_skb) | 1650 | if (opt_skb) |
1616 | __kfree_skb(opt_skb); | 1651 | __kfree_skb(opt_skb); |
1617 | return 0; | 1652 | return 0; |
1618 | } | 1653 | } |
1619 | } | 1654 | } else |
1655 | sock_rps_save_rxhash(sk, skb->rxhash); | ||
1620 | 1656 | ||
1621 | TCP_CHECK_TIMER(sk); | ||
1622 | if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) | 1657 | if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) |
1623 | goto reset; | 1658 | goto reset; |
1624 | TCP_CHECK_TIMER(sk); | ||
1625 | if (opt_skb) | 1659 | if (opt_skb) |
1626 | goto ipv6_pktoptions; | 1660 | goto ipv6_pktoptions; |
1627 | return 0; | 1661 | return 0; |
@@ -1669,7 +1703,7 @@ ipv6_pktoptions: | |||
1669 | static int tcp_v6_rcv(struct sk_buff *skb) | 1703 | static int tcp_v6_rcv(struct sk_buff *skb) |
1670 | { | 1704 | { |
1671 | struct tcphdr *th; | 1705 | struct tcphdr *th; |
1672 | struct ipv6hdr *hdr; | 1706 | const struct ipv6hdr *hdr; |
1673 | struct sock *sk; | 1707 | struct sock *sk; |
1674 | int ret; | 1708 | int ret; |
1675 | struct net *net = dev_net(skb->dev); | 1709 | struct net *net = dev_net(skb->dev); |
@@ -1814,19 +1848,51 @@ do_time_wait: | |||
1814 | goto discard_it; | 1848 | goto discard_it; |
1815 | } | 1849 | } |
1816 | 1850 | ||
1817 | static int tcp_v6_remember_stamp(struct sock *sk) | 1851 | static struct inet_peer *tcp_v6_get_peer(struct sock *sk, bool *release_it) |
1818 | { | 1852 | { |
1819 | /* Alas, not yet... */ | 1853 | struct rt6_info *rt = (struct rt6_info *) __sk_dst_get(sk); |
1820 | return 0; | 1854 | struct ipv6_pinfo *np = inet6_sk(sk); |
1855 | struct inet_peer *peer; | ||
1856 | |||
1857 | if (!rt || | ||
1858 | !ipv6_addr_equal(&np->daddr, &rt->rt6i_dst.addr)) { | ||
1859 | peer = inet_getpeer_v6(&np->daddr, 1); | ||
1860 | *release_it = true; | ||
1861 | } else { | ||
1862 | if (!rt->rt6i_peer) | ||
1863 | rt6_bind_peer(rt, 1); | ||
1864 | peer = rt->rt6i_peer; | ||
1865 | *release_it = false; | ||
1866 | } | ||
1867 | |||
1868 | return peer; | ||
1869 | } | ||
1870 | |||
1871 | static void *tcp_v6_tw_get_peer(struct sock *sk) | ||
1872 | { | ||
1873 | struct inet6_timewait_sock *tw6 = inet6_twsk(sk); | ||
1874 | struct inet_timewait_sock *tw = inet_twsk(sk); | ||
1875 | |||
1876 | if (tw->tw_family == AF_INET) | ||
1877 | return tcp_v4_tw_get_peer(sk); | ||
1878 | |||
1879 | return inet_getpeer_v6(&tw6->tw_v6_daddr, 1); | ||
1821 | } | 1880 | } |
1822 | 1881 | ||
1882 | static struct timewait_sock_ops tcp6_timewait_sock_ops = { | ||
1883 | .twsk_obj_size = sizeof(struct tcp6_timewait_sock), | ||
1884 | .twsk_unique = tcp_twsk_unique, | ||
1885 | .twsk_destructor= tcp_twsk_destructor, | ||
1886 | .twsk_getpeer = tcp_v6_tw_get_peer, | ||
1887 | }; | ||
1888 | |||
1823 | static const struct inet_connection_sock_af_ops ipv6_specific = { | 1889 | static const struct inet_connection_sock_af_ops ipv6_specific = { |
1824 | .queue_xmit = inet6_csk_xmit, | 1890 | .queue_xmit = inet6_csk_xmit, |
1825 | .send_check = tcp_v6_send_check, | 1891 | .send_check = tcp_v6_send_check, |
1826 | .rebuild_header = inet6_sk_rebuild_header, | 1892 | .rebuild_header = inet6_sk_rebuild_header, |
1827 | .conn_request = tcp_v6_conn_request, | 1893 | .conn_request = tcp_v6_conn_request, |
1828 | .syn_recv_sock = tcp_v6_syn_recv_sock, | 1894 | .syn_recv_sock = tcp_v6_syn_recv_sock, |
1829 | .remember_stamp = tcp_v6_remember_stamp, | 1895 | .get_peer = tcp_v6_get_peer, |
1830 | .net_header_len = sizeof(struct ipv6hdr), | 1896 | .net_header_len = sizeof(struct ipv6hdr), |
1831 | .setsockopt = ipv6_setsockopt, | 1897 | .setsockopt = ipv6_setsockopt, |
1832 | .getsockopt = ipv6_getsockopt, | 1898 | .getsockopt = ipv6_getsockopt, |
@@ -1858,7 +1924,7 @@ static const struct inet_connection_sock_af_ops ipv6_mapped = { | |||
1858 | .rebuild_header = inet_sk_rebuild_header, | 1924 | .rebuild_header = inet_sk_rebuild_header, |
1859 | .conn_request = tcp_v6_conn_request, | 1925 | .conn_request = tcp_v6_conn_request, |
1860 | .syn_recv_sock = tcp_v6_syn_recv_sock, | 1926 | .syn_recv_sock = tcp_v6_syn_recv_sock, |
1861 | .remember_stamp = tcp_v4_remember_stamp, | 1927 | .get_peer = tcp_v4_get_peer, |
1862 | .net_header_len = sizeof(struct iphdr), | 1928 | .net_header_len = sizeof(struct iphdr), |
1863 | .setsockopt = ipv6_setsockopt, | 1929 | .setsockopt = ipv6_setsockopt, |
1864 | .getsockopt = ipv6_getsockopt, | 1930 | .getsockopt = ipv6_getsockopt, |
@@ -1963,15 +2029,15 @@ static void get_openreq6(struct seq_file *seq, | |||
1963 | struct sock *sk, struct request_sock *req, int i, int uid) | 2029 | struct sock *sk, struct request_sock *req, int i, int uid) |
1964 | { | 2030 | { |
1965 | int ttd = req->expires - jiffies; | 2031 | int ttd = req->expires - jiffies; |
1966 | struct in6_addr *src = &inet6_rsk(req)->loc_addr; | 2032 | const struct in6_addr *src = &inet6_rsk(req)->loc_addr; |
1967 | struct in6_addr *dest = &inet6_rsk(req)->rmt_addr; | 2033 | const struct in6_addr *dest = &inet6_rsk(req)->rmt_addr; |
1968 | 2034 | ||
1969 | if (ttd < 0) | 2035 | if (ttd < 0) |
1970 | ttd = 0; | 2036 | ttd = 0; |
1971 | 2037 | ||
1972 | seq_printf(seq, | 2038 | seq_printf(seq, |
1973 | "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " | 2039 | "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " |
1974 | "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p\n", | 2040 | "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK\n", |
1975 | i, | 2041 | i, |
1976 | src->s6_addr32[0], src->s6_addr32[1], | 2042 | src->s6_addr32[0], src->s6_addr32[1], |
1977 | src->s6_addr32[2], src->s6_addr32[3], | 2043 | src->s6_addr32[2], src->s6_addr32[3], |
@@ -1992,7 +2058,7 @@ static void get_openreq6(struct seq_file *seq, | |||
1992 | 2058 | ||
1993 | static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) | 2059 | static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) |
1994 | { | 2060 | { |
1995 | struct in6_addr *dest, *src; | 2061 | const struct in6_addr *dest, *src; |
1996 | __u16 destp, srcp; | 2062 | __u16 destp, srcp; |
1997 | int timer_active; | 2063 | int timer_active; |
1998 | unsigned long timer_expires; | 2064 | unsigned long timer_expires; |
@@ -2022,7 +2088,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) | |||
2022 | 2088 | ||
2023 | seq_printf(seq, | 2089 | seq_printf(seq, |
2024 | "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " | 2090 | "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " |
2025 | "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %lu %lu %u %u %d\n", | 2091 | "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %lu %lu %u %u %d\n", |
2026 | i, | 2092 | i, |
2027 | src->s6_addr32[0], src->s6_addr32[1], | 2093 | src->s6_addr32[0], src->s6_addr32[1], |
2028 | src->s6_addr32[2], src->s6_addr32[3], srcp, | 2094 | src->s6_addr32[2], src->s6_addr32[3], srcp, |
@@ -2049,7 +2115,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) | |||
2049 | static void get_timewait6_sock(struct seq_file *seq, | 2115 | static void get_timewait6_sock(struct seq_file *seq, |
2050 | struct inet_timewait_sock *tw, int i) | 2116 | struct inet_timewait_sock *tw, int i) |
2051 | { | 2117 | { |
2052 | struct in6_addr *dest, *src; | 2118 | const struct in6_addr *dest, *src; |
2053 | __u16 destp, srcp; | 2119 | __u16 destp, srcp; |
2054 | struct inet6_timewait_sock *tw6 = inet6_twsk((struct sock *)tw); | 2120 | struct inet6_timewait_sock *tw6 = inet6_twsk((struct sock *)tw); |
2055 | int ttd = tw->tw_ttd - jiffies; | 2121 | int ttd = tw->tw_ttd - jiffies; |
@@ -2064,7 +2130,7 @@ static void get_timewait6_sock(struct seq_file *seq, | |||
2064 | 2130 | ||
2065 | seq_printf(seq, | 2131 | seq_printf(seq, |
2066 | "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " | 2132 | "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " |
2067 | "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p\n", | 2133 | "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK\n", |
2068 | i, | 2134 | i, |
2069 | src->s6_addr32[0], src->s6_addr32[1], | 2135 | src->s6_addr32[0], src->s6_addr32[1], |
2070 | src->s6_addr32[2], src->s6_addr32[3], srcp, | 2136 | src->s6_addr32[2], src->s6_addr32[3], srcp, |