aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/ipv6.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2012-08-01 06:40:02 -0400
committerNeilBrown <neilb@suse.de>2012-08-01 06:40:02 -0400
commitbb181e2e48f8c85db08c9cb015cbba9618dbf05c (patch)
tree191bc24dd97bcb174535cc217af082f16da3b43d /net/dccp/ipv6.c
parentd57368afe63b3b7b45ce6c2b8c5276417935be2f (diff)
parentc039c332f23e794deb6d6f37b9f07ff3b27fb2cf (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.c61
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
279done: 259done:
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);
626out: 599out:
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