diff options
author | NeilBrown <neilb@suse.de> | 2012-08-01 06:40:02 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2012-08-01 06:40:02 -0400 |
commit | bb181e2e48f8c85db08c9cb015cbba9618dbf05c (patch) | |
tree | 191bc24dd97bcb174535cc217af082f16da3b43d /net/dccp/ipv6.c | |
parent | d57368afe63b3b7b45ce6c2b8c5276417935be2f (diff) | |
parent | c039c332f23e794deb6d6f37b9f07ff3b27fb2cf (diff) |
Merge commit 'c039c332f23e794deb6d6f37b9f07ff3b27fb2cf' into md
Pull in pre-requisites for adding raid10 support to dm-raid.
Diffstat (limited to 'net/dccp/ipv6.c')
-rw-r--r-- | net/dccp/ipv6.c | 61 |
1 files changed, 16 insertions, 45 deletions
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index fa9512d86f3b..56840b249f3b 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -130,6 +130,13 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
130 | 130 | ||
131 | np = inet6_sk(sk); | 131 | np = inet6_sk(sk); |
132 | 132 | ||
133 | if (type == NDISC_REDIRECT) { | ||
134 | struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie); | ||
135 | |||
136 | if (dst) | ||
137 | dst->ops->redirect(dst, sk, skb); | ||
138 | } | ||
139 | |||
133 | if (type == ICMPV6_PKT_TOOBIG) { | 140 | if (type == ICMPV6_PKT_TOOBIG) { |
134 | struct dst_entry *dst = NULL; | 141 | struct dst_entry *dst = NULL; |
135 | 142 | ||
@@ -138,37 +145,12 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
138 | if ((1 << sk->sk_state) & (DCCPF_LISTEN | DCCPF_CLOSED)) | 145 | if ((1 << sk->sk_state) & (DCCPF_LISTEN | DCCPF_CLOSED)) |
139 | goto out; | 146 | goto out; |
140 | 147 | ||
141 | /* icmp should have updated the destination cache entry */ | 148 | dst = inet6_csk_update_pmtu(sk, ntohl(info)); |
142 | dst = __sk_dst_check(sk, np->dst_cookie); | 149 | if (!dst) |
143 | if (dst == NULL) { | 150 | goto out; |
144 | struct inet_sock *inet = inet_sk(sk); | ||
145 | struct flowi6 fl6; | ||
146 | |||
147 | /* BUGGG_FUTURE: Again, it is not clear how | ||
148 | to handle rthdr case. Ignore this complexity | ||
149 | for now. | ||
150 | */ | ||
151 | memset(&fl6, 0, sizeof(fl6)); | ||
152 | fl6.flowi6_proto = IPPROTO_DCCP; | ||
153 | fl6.daddr = np->daddr; | ||
154 | fl6.saddr = np->saddr; | ||
155 | fl6.flowi6_oif = sk->sk_bound_dev_if; | ||
156 | fl6.fl6_dport = inet->inet_dport; | ||
157 | fl6.fl6_sport = inet->inet_sport; | ||
158 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); | ||
159 | |||
160 | dst = ip6_dst_lookup_flow(sk, &fl6, NULL, false); | ||
161 | if (IS_ERR(dst)) { | ||
162 | sk->sk_err_soft = -PTR_ERR(dst); | ||
163 | goto out; | ||
164 | } | ||
165 | } else | ||
166 | dst_hold(dst); | ||
167 | 151 | ||
168 | if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst)) { | 152 | if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst)) |
169 | dccp_sync_mss(sk, dst_mtu(dst)); | 153 | dccp_sync_mss(sk, dst_mtu(dst)); |
170 | } /* else let the usual retransmit timer handle it */ | ||
171 | dst_release(dst); | ||
172 | goto out; | 154 | goto out; |
173 | } | 155 | } |
174 | 156 | ||
@@ -237,7 +219,6 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, | |||
237 | struct inet6_request_sock *ireq6 = inet6_rsk(req); | 219 | struct inet6_request_sock *ireq6 = inet6_rsk(req); |
238 | struct ipv6_pinfo *np = inet6_sk(sk); | 220 | struct ipv6_pinfo *np = inet6_sk(sk); |
239 | struct sk_buff *skb; | 221 | struct sk_buff *skb; |
240 | struct ipv6_txoptions *opt = NULL; | ||
241 | struct in6_addr *final_p, final; | 222 | struct in6_addr *final_p, final; |
242 | struct flowi6 fl6; | 223 | struct flowi6 fl6; |
243 | int err = -1; | 224 | int err = -1; |
@@ -253,9 +234,8 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, | |||
253 | fl6.fl6_sport = inet_rsk(req)->loc_port; | 234 | fl6.fl6_sport = inet_rsk(req)->loc_port; |
254 | security_req_classify_flow(req, flowi6_to_flowi(&fl6)); | 235 | security_req_classify_flow(req, flowi6_to_flowi(&fl6)); |
255 | 236 | ||
256 | opt = np->opt; | ||
257 | 237 | ||
258 | final_p = fl6_update_dst(&fl6, opt, &final); | 238 | final_p = fl6_update_dst(&fl6, np->opt, &final); |
259 | 239 | ||
260 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); | 240 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); |
261 | if (IS_ERR(dst)) { | 241 | if (IS_ERR(dst)) { |
@@ -272,13 +252,11 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, | |||
272 | &ireq6->loc_addr, | 252 | &ireq6->loc_addr, |
273 | &ireq6->rmt_addr); | 253 | &ireq6->rmt_addr); |
274 | fl6.daddr = ireq6->rmt_addr; | 254 | fl6.daddr = ireq6->rmt_addr; |
275 | err = ip6_xmit(sk, skb, &fl6, opt, np->tclass); | 255 | err = ip6_xmit(sk, skb, &fl6, np->opt, np->tclass); |
276 | err = net_xmit_eval(err); | 256 | err = net_xmit_eval(err); |
277 | } | 257 | } |
278 | 258 | ||
279 | done: | 259 | done: |
280 | if (opt != NULL && opt != np->opt) | ||
281 | sock_kfree_s(sk, opt, opt->tot_len); | ||
282 | dst_release(dst); | 260 | dst_release(dst); |
283 | return err; | 261 | return err; |
284 | } | 262 | } |
@@ -473,7 +451,6 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, | |||
473 | struct inet_sock *newinet; | 451 | struct inet_sock *newinet; |
474 | struct dccp6_sock *newdp6; | 452 | struct dccp6_sock *newdp6; |
475 | struct sock *newsk; | 453 | struct sock *newsk; |
476 | struct ipv6_txoptions *opt; | ||
477 | 454 | ||
478 | if (skb->protocol == htons(ETH_P_IP)) { | 455 | if (skb->protocol == htons(ETH_P_IP)) { |
479 | /* | 456 | /* |
@@ -518,7 +495,6 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, | |||
518 | return newsk; | 495 | return newsk; |
519 | } | 496 | } |
520 | 497 | ||
521 | opt = np->opt; | ||
522 | 498 | ||
523 | if (sk_acceptq_is_full(sk)) | 499 | if (sk_acceptq_is_full(sk)) |
524 | goto out_overflow; | 500 | goto out_overflow; |
@@ -530,7 +506,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, | |||
530 | memset(&fl6, 0, sizeof(fl6)); | 506 | memset(&fl6, 0, sizeof(fl6)); |
531 | fl6.flowi6_proto = IPPROTO_DCCP; | 507 | fl6.flowi6_proto = IPPROTO_DCCP; |
532 | fl6.daddr = ireq6->rmt_addr; | 508 | fl6.daddr = ireq6->rmt_addr; |
533 | final_p = fl6_update_dst(&fl6, opt, &final); | 509 | final_p = fl6_update_dst(&fl6, np->opt, &final); |
534 | fl6.saddr = ireq6->loc_addr; | 510 | fl6.saddr = ireq6->loc_addr; |
535 | fl6.flowi6_oif = sk->sk_bound_dev_if; | 511 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
536 | fl6.fl6_dport = inet_rsk(req)->rmt_port; | 512 | fl6.fl6_dport = inet_rsk(req)->rmt_port; |
@@ -595,11 +571,8 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, | |||
595 | * Yes, keeping reference count would be much more clever, but we make | 571 | * Yes, keeping reference count would be much more clever, but we make |
596 | * one more one thing there: reattach optmem to newsk. | 572 | * one more one thing there: reattach optmem to newsk. |
597 | */ | 573 | */ |
598 | if (opt != NULL) { | 574 | if (np->opt != NULL) |
599 | newnp->opt = ipv6_dup_options(newsk, opt); | 575 | newnp->opt = ipv6_dup_options(newsk, np->opt); |
600 | if (opt != np->opt) | ||
601 | sock_kfree_s(sk, opt, opt->tot_len); | ||
602 | } | ||
603 | 576 | ||
604 | inet_csk(newsk)->icsk_ext_hdr_len = 0; | 577 | inet_csk(newsk)->icsk_ext_hdr_len = 0; |
605 | if (newnp->opt != NULL) | 578 | if (newnp->opt != NULL) |
@@ -625,8 +598,6 @@ out_nonewsk: | |||
625 | dst_release(dst); | 598 | dst_release(dst); |
626 | out: | 599 | out: |
627 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | 600 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); |
628 | if (opt != NULL && opt != np->opt) | ||
629 | sock_kfree_s(sk, opt, opt->tot_len); | ||
630 | return NULL; | 601 | return NULL; |
631 | } | 602 | } |
632 | 603 | ||