diff options
Diffstat (limited to 'net/ipv6/inet6_connection_sock.c')
-rw-r--r-- | net/ipv6/inet6_connection_sock.c | 103 |
1 files changed, 63 insertions, 40 deletions
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index e6cee5292a0b..0251a6005be8 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -55,26 +55,26 @@ int inet6_csk_bind_conflict(const struct sock *sk, | |||
55 | EXPORT_SYMBOL_GPL(inet6_csk_bind_conflict); | 55 | EXPORT_SYMBOL_GPL(inet6_csk_bind_conflict); |
56 | 56 | ||
57 | struct dst_entry *inet6_csk_route_req(struct sock *sk, | 57 | struct dst_entry *inet6_csk_route_req(struct sock *sk, |
58 | struct flowi6 *fl6, | ||
58 | const struct request_sock *req) | 59 | const struct request_sock *req) |
59 | { | 60 | { |
60 | struct inet6_request_sock *treq = inet6_rsk(req); | 61 | struct inet6_request_sock *treq = inet6_rsk(req); |
61 | struct ipv6_pinfo *np = inet6_sk(sk); | 62 | struct ipv6_pinfo *np = inet6_sk(sk); |
62 | struct in6_addr *final_p, final; | 63 | struct in6_addr *final_p, final; |
63 | struct dst_entry *dst; | 64 | struct dst_entry *dst; |
64 | struct flowi6 fl6; | ||
65 | 65 | ||
66 | memset(&fl6, 0, sizeof(fl6)); | 66 | memset(fl6, 0, sizeof(*fl6)); |
67 | fl6.flowi6_proto = IPPROTO_TCP; | 67 | fl6->flowi6_proto = IPPROTO_TCP; |
68 | fl6.daddr = treq->rmt_addr; | 68 | fl6->daddr = treq->rmt_addr; |
69 | final_p = fl6_update_dst(&fl6, np->opt, &final); | 69 | final_p = fl6_update_dst(fl6, np->opt, &final); |
70 | fl6.saddr = treq->loc_addr; | 70 | fl6->saddr = treq->loc_addr; |
71 | fl6.flowi6_oif = sk->sk_bound_dev_if; | 71 | fl6->flowi6_oif = treq->iif; |
72 | fl6.flowi6_mark = sk->sk_mark; | 72 | fl6->flowi6_mark = sk->sk_mark; |
73 | fl6.fl6_dport = inet_rsk(req)->rmt_port; | 73 | fl6->fl6_dport = inet_rsk(req)->rmt_port; |
74 | fl6.fl6_sport = inet_rsk(req)->loc_port; | 74 | fl6->fl6_sport = inet_rsk(req)->loc_port; |
75 | security_req_classify_flow(req, flowi6_to_flowi(&fl6)); | 75 | security_req_classify_flow(req, flowi6_to_flowi(fl6)); |
76 | 76 | ||
77 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); | 77 | dst = ip6_dst_lookup_flow(sk, fl6, final_p, false); |
78 | if (IS_ERR(dst)) | 78 | if (IS_ERR(dst)) |
79 | return NULL; | 79 | return NULL; |
80 | 80 | ||
@@ -171,7 +171,8 @@ EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr); | |||
171 | 171 | ||
172 | static inline | 172 | static inline |
173 | void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst, | 173 | void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst, |
174 | struct in6_addr *daddr, struct in6_addr *saddr) | 174 | const struct in6_addr *daddr, |
175 | const struct in6_addr *saddr) | ||
175 | { | 176 | { |
176 | __ip6_dst_store(sk, dst, daddr, saddr); | 177 | __ip6_dst_store(sk, dst, daddr, saddr); |
177 | 178 | ||
@@ -203,43 +204,52 @@ struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie) | |||
203 | return dst; | 204 | return dst; |
204 | } | 205 | } |
205 | 206 | ||
206 | int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) | 207 | static struct dst_entry *inet6_csk_route_socket(struct sock *sk, |
208 | struct flowi6 *fl6) | ||
207 | { | 209 | { |
208 | struct sock *sk = skb->sk; | ||
209 | struct inet_sock *inet = inet_sk(sk); | 210 | struct inet_sock *inet = inet_sk(sk); |
210 | struct ipv6_pinfo *np = inet6_sk(sk); | 211 | struct ipv6_pinfo *np = inet6_sk(sk); |
211 | struct flowi6 fl6; | ||
212 | struct dst_entry *dst; | ||
213 | struct in6_addr *final_p, final; | 212 | struct in6_addr *final_p, final; |
214 | int res; | 213 | struct dst_entry *dst; |
215 | 214 | ||
216 | memset(&fl6, 0, sizeof(fl6)); | 215 | memset(fl6, 0, sizeof(*fl6)); |
217 | fl6.flowi6_proto = sk->sk_protocol; | 216 | fl6->flowi6_proto = sk->sk_protocol; |
218 | fl6.daddr = np->daddr; | 217 | fl6->daddr = np->daddr; |
219 | fl6.saddr = np->saddr; | 218 | fl6->saddr = np->saddr; |
220 | fl6.flowlabel = np->flow_label; | 219 | fl6->flowlabel = np->flow_label; |
221 | IP6_ECN_flow_xmit(sk, fl6.flowlabel); | 220 | IP6_ECN_flow_xmit(sk, fl6->flowlabel); |
222 | fl6.flowi6_oif = sk->sk_bound_dev_if; | 221 | fl6->flowi6_oif = sk->sk_bound_dev_if; |
223 | fl6.flowi6_mark = sk->sk_mark; | 222 | fl6->flowi6_mark = sk->sk_mark; |
224 | fl6.fl6_sport = inet->inet_sport; | 223 | fl6->fl6_sport = inet->inet_sport; |
225 | fl6.fl6_dport = inet->inet_dport; | 224 | fl6->fl6_dport = inet->inet_dport; |
226 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); | 225 | security_sk_classify_flow(sk, flowi6_to_flowi(fl6)); |
227 | 226 | ||
228 | final_p = fl6_update_dst(&fl6, np->opt, &final); | 227 | final_p = fl6_update_dst(fl6, np->opt, &final); |
229 | 228 | ||
230 | dst = __inet6_csk_dst_check(sk, np->dst_cookie); | 229 | dst = __inet6_csk_dst_check(sk, np->dst_cookie); |
230 | if (!dst) { | ||
231 | dst = ip6_dst_lookup_flow(sk, fl6, final_p, false); | ||
231 | 232 | ||
232 | if (dst == NULL) { | 233 | if (!IS_ERR(dst)) |
233 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); | 234 | __inet6_csk_dst_store(sk, dst, NULL, NULL); |
235 | } | ||
236 | return dst; | ||
237 | } | ||
234 | 238 | ||
235 | if (IS_ERR(dst)) { | 239 | int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) |
236 | sk->sk_err_soft = -PTR_ERR(dst); | 240 | { |
237 | sk->sk_route_caps = 0; | 241 | struct sock *sk = skb->sk; |
238 | kfree_skb(skb); | 242 | struct ipv6_pinfo *np = inet6_sk(sk); |
239 | return PTR_ERR(dst); | 243 | struct flowi6 fl6; |
240 | } | 244 | struct dst_entry *dst; |
245 | int res; | ||
241 | 246 | ||
242 | __inet6_csk_dst_store(sk, dst, NULL, NULL); | 247 | dst = inet6_csk_route_socket(sk, &fl6); |
248 | if (IS_ERR(dst)) { | ||
249 | sk->sk_err_soft = -PTR_ERR(dst); | ||
250 | sk->sk_route_caps = 0; | ||
251 | kfree_skb(skb); | ||
252 | return PTR_ERR(dst); | ||
243 | } | 253 | } |
244 | 254 | ||
245 | rcu_read_lock(); | 255 | rcu_read_lock(); |
@@ -253,3 +263,16 @@ int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) | |||
253 | return res; | 263 | return res; |
254 | } | 264 | } |
255 | EXPORT_SYMBOL_GPL(inet6_csk_xmit); | 265 | EXPORT_SYMBOL_GPL(inet6_csk_xmit); |
266 | |||
267 | struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu) | ||
268 | { | ||
269 | struct flowi6 fl6; | ||
270 | struct dst_entry *dst = inet6_csk_route_socket(sk, &fl6); | ||
271 | |||
272 | if (IS_ERR(dst)) | ||
273 | return NULL; | ||
274 | dst->ops->update_pmtu(dst, sk, NULL, mtu); | ||
275 | |||
276 | return inet6_csk_route_socket(sk, &fl6); | ||
277 | } | ||
278 | EXPORT_SYMBOL_GPL(inet6_csk_update_pmtu); | ||