diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 3 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 19 | ||||
-rw-r--r-- | net/ipv6/datagram.c | 15 | ||||
-rw-r--r-- | net/ipv6/icmp.c | 134 | ||||
-rw-r--r-- | net/ipv6/inet6_connection_sock.c | 25 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 90 | ||||
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 19 | ||||
-rw-r--r-- | net/ipv6/ip6mr.c | 3 | ||||
-rw-r--r-- | net/ipv6/mcast.c | 13 | ||||
-rw-r--r-- | net/ipv6/mip6.c | 3 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 12 | ||||
-rw-r--r-- | net/ipv6/netfilter.c | 3 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 2 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_LOG.c | 3 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_REJECT.c | 3 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_reasm.c | 3 | ||||
-rw-r--r-- | net/ipv6/raw.c | 29 | ||||
-rw-r--r-- | net/ipv6/route.c | 90 | ||||
-rw-r--r-- | net/ipv6/sit.c | 31 | ||||
-rw-r--r-- | net/ipv6/syncookies.c | 7 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 63 | ||||
-rw-r--r-- | net/ipv6/udp.c | 17 | ||||
-rw-r--r-- | net/ipv6/xfrm6_policy.c | 11 | ||||
-rw-r--r-- | net/ipv6/xfrm6_state.c | 6 |
24 files changed, 340 insertions, 264 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index fd6782e3a038..3daaf3c7703c 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -718,12 +718,9 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
718 | struct inet6_ifaddr *ifa, *ifn; | 718 | struct inet6_ifaddr *ifa, *ifn; |
719 | struct inet6_dev *idev = ifp->idev; | 719 | struct inet6_dev *idev = ifp->idev; |
720 | int state; | 720 | int state; |
721 | int hash; | ||
722 | int deleted = 0, onlink = 0; | 721 | int deleted = 0, onlink = 0; |
723 | unsigned long expires = jiffies; | 722 | unsigned long expires = jiffies; |
724 | 723 | ||
725 | hash = ipv6_addr_hash(&ifp->addr); | ||
726 | |||
727 | spin_lock_bh(&ifp->state_lock); | 724 | spin_lock_bh(&ifp->state_lock); |
728 | state = ifp->state; | 725 | state = ifp->state; |
729 | ifp->state = INET6_IFADDR_STATE_DEAD; | 726 | ifp->state = INET6_IFADDR_STATE_DEAD; |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 978e80e2c4a8..a88b2e9d25f1 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -644,9 +644,8 @@ EXPORT_SYMBOL(inet6_unregister_protosw); | |||
644 | 644 | ||
645 | int inet6_sk_rebuild_header(struct sock *sk) | 645 | int inet6_sk_rebuild_header(struct sock *sk) |
646 | { | 646 | { |
647 | int err; | ||
648 | struct dst_entry *dst; | ||
649 | struct ipv6_pinfo *np = inet6_sk(sk); | 647 | struct ipv6_pinfo *np = inet6_sk(sk); |
648 | struct dst_entry *dst; | ||
650 | 649 | ||
651 | dst = __sk_dst_check(sk, np->dst_cookie); | 650 | dst = __sk_dst_check(sk, np->dst_cookie); |
652 | 651 | ||
@@ -668,17 +667,11 @@ int inet6_sk_rebuild_header(struct sock *sk) | |||
668 | 667 | ||
669 | final_p = fl6_update_dst(&fl, np->opt, &final); | 668 | final_p = fl6_update_dst(&fl, np->opt, &final); |
670 | 669 | ||
671 | err = ip6_dst_lookup(sk, &dst, &fl); | 670 | dst = ip6_dst_lookup_flow(sk, &fl, final_p, false); |
672 | if (err) { | 671 | if (IS_ERR(dst)) { |
673 | sk->sk_route_caps = 0; | 672 | sk->sk_route_caps = 0; |
674 | return err; | 673 | sk->sk_err_soft = -PTR_ERR(dst); |
675 | } | 674 | return PTR_ERR(dst); |
676 | if (final_p) | ||
677 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
678 | |||
679 | if ((err = xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0) { | ||
680 | sk->sk_err_soft = -err; | ||
681 | return err; | ||
682 | } | 675 | } |
683 | 676 | ||
684 | __ip6_dst_store(sk, dst, NULL, NULL); | 677 | __ip6_dst_store(sk, dst, NULL, NULL); |
@@ -772,7 +765,7 @@ out: | |||
772 | return err; | 765 | return err; |
773 | } | 766 | } |
774 | 767 | ||
775 | static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features) | 768 | static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, u32 features) |
776 | { | 769 | { |
777 | struct sk_buff *segs = ERR_PTR(-EINVAL); | 770 | struct sk_buff *segs = ERR_PTR(-EINVAL); |
778 | struct ipv6hdr *ipv6h; | 771 | struct ipv6hdr *ipv6h; |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 320bdb877eed..be3a781c0085 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -162,18 +162,11 @@ ipv4_connected: | |||
162 | opt = flowlabel ? flowlabel->opt : np->opt; | 162 | opt = flowlabel ? flowlabel->opt : np->opt; |
163 | final_p = fl6_update_dst(&fl, opt, &final); | 163 | final_p = fl6_update_dst(&fl, opt, &final); |
164 | 164 | ||
165 | err = ip6_dst_lookup(sk, &dst, &fl); | 165 | dst = ip6_dst_lookup_flow(sk, &fl, final_p, true); |
166 | if (err) | 166 | err = 0; |
167 | if (IS_ERR(dst)) { | ||
168 | err = PTR_ERR(dst); | ||
167 | goto out; | 169 | goto out; |
168 | if (final_p) | ||
169 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
170 | |||
171 | err = __xfrm_lookup(sock_net(sk), &dst, &fl, sk, XFRM_LOOKUP_WAIT); | ||
172 | if (err < 0) { | ||
173 | if (err == -EREMOTE) | ||
174 | err = ip6_dst_blackhole(sk, &dst, &fl); | ||
175 | if (err < 0) | ||
176 | goto out; | ||
177 | } | 170 | } |
178 | 171 | ||
179 | /* source address lookup done in ip6_dst_lookup */ | 172 | /* source address lookup done in ip6_dst_lookup */ |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 03e62f94ff8e..55665956b3a8 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -157,20 +157,20 @@ static int is_ineligible(struct sk_buff *skb) | |||
157 | /* | 157 | /* |
158 | * Check the ICMP output rate limit | 158 | * Check the ICMP output rate limit |
159 | */ | 159 | */ |
160 | static inline int icmpv6_xrlim_allow(struct sock *sk, u8 type, | 160 | static inline bool icmpv6_xrlim_allow(struct sock *sk, u8 type, |
161 | struct flowi *fl) | 161 | struct flowi *fl) |
162 | { | 162 | { |
163 | struct dst_entry *dst; | 163 | struct dst_entry *dst; |
164 | struct net *net = sock_net(sk); | 164 | struct net *net = sock_net(sk); |
165 | int res = 0; | 165 | bool res = false; |
166 | 166 | ||
167 | /* Informational messages are not limited. */ | 167 | /* Informational messages are not limited. */ |
168 | if (type & ICMPV6_INFOMSG_MASK) | 168 | if (type & ICMPV6_INFOMSG_MASK) |
169 | return 1; | 169 | return true; |
170 | 170 | ||
171 | /* Do not limit pmtu discovery, it would break it. */ | 171 | /* Do not limit pmtu discovery, it would break it. */ |
172 | if (type == ICMPV6_PKT_TOOBIG) | 172 | if (type == ICMPV6_PKT_TOOBIG) |
173 | return 1; | 173 | return true; |
174 | 174 | ||
175 | /* | 175 | /* |
176 | * Look up the output route. | 176 | * Look up the output route. |
@@ -182,7 +182,7 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, u8 type, | |||
182 | IP6_INC_STATS(net, ip6_dst_idev(dst), | 182 | IP6_INC_STATS(net, ip6_dst_idev(dst), |
183 | IPSTATS_MIB_OUTNOROUTES); | 183 | IPSTATS_MIB_OUTNOROUTES); |
184 | } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) { | 184 | } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) { |
185 | res = 1; | 185 | res = true; |
186 | } else { | 186 | } else { |
187 | struct rt6_info *rt = (struct rt6_info *)dst; | 187 | struct rt6_info *rt = (struct rt6_info *)dst; |
188 | int tmo = net->ipv6.sysctl.icmpv6_time; | 188 | int tmo = net->ipv6.sysctl.icmpv6_time; |
@@ -191,7 +191,9 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, u8 type, | |||
191 | if (rt->rt6i_dst.plen < 128) | 191 | if (rt->rt6i_dst.plen < 128) |
192 | tmo >>= ((128 - rt->rt6i_dst.plen)>>5); | 192 | tmo >>= ((128 - rt->rt6i_dst.plen)>>5); |
193 | 193 | ||
194 | res = xrlim_allow(dst, tmo); | 194 | if (!rt->rt6i_peer) |
195 | rt6_bind_peer(rt, 1); | ||
196 | res = inet_peer_xrlim_allow(rt->rt6i_peer, tmo); | ||
195 | } | 197 | } |
196 | dst_release(dst); | 198 | dst_release(dst); |
197 | return res; | 199 | return res; |
@@ -298,6 +300,68 @@ static void mip6_addr_swap(struct sk_buff *skb) | |||
298 | static inline void mip6_addr_swap(struct sk_buff *skb) {} | 300 | static inline void mip6_addr_swap(struct sk_buff *skb) {} |
299 | #endif | 301 | #endif |
300 | 302 | ||
303 | static struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb, | ||
304 | struct sock *sk, struct flowi *fl) | ||
305 | { | ||
306 | struct dst_entry *dst, *dst2; | ||
307 | struct flowi fl2; | ||
308 | int err; | ||
309 | |||
310 | err = ip6_dst_lookup(sk, &dst, fl); | ||
311 | if (err) | ||
312 | return ERR_PTR(err); | ||
313 | |||
314 | /* | ||
315 | * We won't send icmp if the destination is known | ||
316 | * anycast. | ||
317 | */ | ||
318 | if (((struct rt6_info *)dst)->rt6i_flags & RTF_ANYCAST) { | ||
319 | LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: acast source\n"); | ||
320 | dst_release(dst); | ||
321 | return ERR_PTR(-EINVAL); | ||
322 | } | ||
323 | |||
324 | /* No need to clone since we're just using its address. */ | ||
325 | dst2 = dst; | ||
326 | |||
327 | dst = xfrm_lookup(net, dst, fl, sk, 0); | ||
328 | if (!IS_ERR(dst)) { | ||
329 | if (dst != dst2) | ||
330 | return dst; | ||
331 | } else { | ||
332 | if (PTR_ERR(dst) == -EPERM) | ||
333 | dst = NULL; | ||
334 | else | ||
335 | return dst; | ||
336 | } | ||
337 | |||
338 | err = xfrm_decode_session_reverse(skb, &fl2, AF_INET6); | ||
339 | if (err) | ||
340 | goto relookup_failed; | ||
341 | |||
342 | err = ip6_dst_lookup(sk, &dst2, &fl2); | ||
343 | if (err) | ||
344 | goto relookup_failed; | ||
345 | |||
346 | dst2 = xfrm_lookup(net, dst2, &fl2, sk, XFRM_LOOKUP_ICMP); | ||
347 | if (!IS_ERR(dst2)) { | ||
348 | dst_release(dst); | ||
349 | dst = dst2; | ||
350 | } else { | ||
351 | err = PTR_ERR(dst2); | ||
352 | if (err == -EPERM) { | ||
353 | dst_release(dst); | ||
354 | return dst2; | ||
355 | } else | ||
356 | goto relookup_failed; | ||
357 | } | ||
358 | |||
359 | relookup_failed: | ||
360 | if (dst) | ||
361 | return dst; | ||
362 | return ERR_PTR(err); | ||
363 | } | ||
364 | |||
301 | /* | 365 | /* |
302 | * Send an ICMP message in response to a packet in error | 366 | * Send an ICMP message in response to a packet in error |
303 | */ | 367 | */ |
@@ -310,10 +374,8 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) | |||
310 | struct ipv6_pinfo *np; | 374 | struct ipv6_pinfo *np; |
311 | struct in6_addr *saddr = NULL; | 375 | struct in6_addr *saddr = NULL; |
312 | struct dst_entry *dst; | 376 | struct dst_entry *dst; |
313 | struct dst_entry *dst2; | ||
314 | struct icmp6hdr tmp_hdr; | 377 | struct icmp6hdr tmp_hdr; |
315 | struct flowi fl; | 378 | struct flowi fl; |
316 | struct flowi fl2; | ||
317 | struct icmpv6_msg msg; | 379 | struct icmpv6_msg msg; |
318 | int iif = 0; | 380 | int iif = 0; |
319 | int addr_type = 0; | 381 | int addr_type = 0; |
@@ -406,57 +468,10 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) | |||
406 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) | 468 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) |
407 | fl.oif = np->mcast_oif; | 469 | fl.oif = np->mcast_oif; |
408 | 470 | ||
409 | err = ip6_dst_lookup(sk, &dst, &fl); | 471 | dst = icmpv6_route_lookup(net, skb, sk, &fl); |
410 | if (err) | 472 | if (IS_ERR(dst)) |
411 | goto out; | ||
412 | |||
413 | /* | ||
414 | * We won't send icmp if the destination is known | ||
415 | * anycast. | ||
416 | */ | ||
417 | if (((struct rt6_info *)dst)->rt6i_flags & RTF_ANYCAST) { | ||
418 | LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: acast source\n"); | ||
419 | goto out_dst_release; | ||
420 | } | ||
421 | |||
422 | /* No need to clone since we're just using its address. */ | ||
423 | dst2 = dst; | ||
424 | |||
425 | err = xfrm_lookup(net, &dst, &fl, sk, 0); | ||
426 | switch (err) { | ||
427 | case 0: | ||
428 | if (dst != dst2) | ||
429 | goto route_done; | ||
430 | break; | ||
431 | case -EPERM: | ||
432 | dst = NULL; | ||
433 | break; | ||
434 | default: | ||
435 | goto out; | 473 | goto out; |
436 | } | ||
437 | |||
438 | if (xfrm_decode_session_reverse(skb, &fl2, AF_INET6)) | ||
439 | goto relookup_failed; | ||
440 | |||
441 | if (ip6_dst_lookup(sk, &dst2, &fl2)) | ||
442 | goto relookup_failed; | ||
443 | |||
444 | err = xfrm_lookup(net, &dst2, &fl2, sk, XFRM_LOOKUP_ICMP); | ||
445 | switch (err) { | ||
446 | case 0: | ||
447 | dst_release(dst); | ||
448 | dst = dst2; | ||
449 | break; | ||
450 | case -EPERM: | ||
451 | goto out_dst_release; | ||
452 | default: | ||
453 | relookup_failed: | ||
454 | if (!dst) | ||
455 | goto out; | ||
456 | break; | ||
457 | } | ||
458 | 474 | ||
459 | route_done: | ||
460 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) | 475 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) |
461 | hlimit = np->mcast_hops; | 476 | hlimit = np->mcast_hops; |
462 | else | 477 | else |
@@ -543,7 +558,8 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
543 | err = ip6_dst_lookup(sk, &dst, &fl); | 558 | err = ip6_dst_lookup(sk, &dst, &fl); |
544 | if (err) | 559 | if (err) |
545 | goto out; | 560 | goto out; |
546 | if ((err = xfrm_lookup(net, &dst, &fl, sk, 0)) < 0) | 561 | dst = xfrm_lookup(net, dst, &fl, sk, 0); |
562 | if (IS_ERR(dst)) | ||
547 | goto out; | 563 | goto out; |
548 | 564 | ||
549 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) | 565 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) |
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index d144e629d2b4..d687e1397333 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -74,13 +74,8 @@ struct dst_entry *inet6_csk_route_req(struct sock *sk, | |||
74 | fl.fl_ip_sport = inet_rsk(req)->loc_port; | 74 | fl.fl_ip_sport = inet_rsk(req)->loc_port; |
75 | security_req_classify_flow(req, &fl); | 75 | security_req_classify_flow(req, &fl); |
76 | 76 | ||
77 | if (ip6_dst_lookup(sk, &dst, &fl)) | 77 | dst = ip6_dst_lookup_flow(sk, &fl, final_p, false); |
78 | return NULL; | 78 | if (IS_ERR(dst)) |
79 | |||
80 | if (final_p) | ||
81 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
82 | |||
83 | if ((xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0) | ||
84 | return NULL; | 79 | return NULL; |
85 | 80 | ||
86 | return dst; | 81 | return dst; |
@@ -234,21 +229,13 @@ int inet6_csk_xmit(struct sk_buff *skb) | |||
234 | dst = __inet6_csk_dst_check(sk, np->dst_cookie); | 229 | dst = __inet6_csk_dst_check(sk, np->dst_cookie); |
235 | 230 | ||
236 | if (dst == NULL) { | 231 | if (dst == NULL) { |
237 | int err = ip6_dst_lookup(sk, &dst, &fl); | 232 | dst = ip6_dst_lookup_flow(sk, &fl, final_p, false); |
238 | |||
239 | if (err) { | ||
240 | sk->sk_err_soft = -err; | ||
241 | kfree_skb(skb); | ||
242 | return err; | ||
243 | } | ||
244 | |||
245 | if (final_p) | ||
246 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
247 | 233 | ||
248 | if ((err = xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0) { | 234 | if (IS_ERR(dst)) { |
235 | sk->sk_err_soft = -PTR_ERR(dst); | ||
249 | sk->sk_route_caps = 0; | 236 | sk->sk_route_caps = 0; |
250 | kfree_skb(skb); | 237 | kfree_skb(skb); |
251 | return err; | 238 | return PTR_ERR(dst); |
252 | } | 239 | } |
253 | 240 | ||
254 | __inet6_csk_dst_store(sk, dst, NULL, NULL); | 241 | __inet6_csk_dst_store(sk, dst, NULL, NULL); |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 5f8d242be3f3..adaffaf84555 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -274,13 +274,10 @@ int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev, | |||
274 | { | 274 | { |
275 | struct ipv6_pinfo *np = inet6_sk(sk); | 275 | struct ipv6_pinfo *np = inet6_sk(sk); |
276 | struct ipv6hdr *hdr; | 276 | struct ipv6hdr *hdr; |
277 | int totlen; | ||
278 | 277 | ||
279 | skb->protocol = htons(ETH_P_IPV6); | 278 | skb->protocol = htons(ETH_P_IPV6); |
280 | skb->dev = dev; | 279 | skb->dev = dev; |
281 | 280 | ||
282 | totlen = len + sizeof(struct ipv6hdr); | ||
283 | |||
284 | skb_reset_network_header(skb); | 281 | skb_reset_network_header(skb); |
285 | skb_put(skb, sizeof(struct ipv6hdr)); | 282 | skb_put(skb, sizeof(struct ipv6hdr)); |
286 | hdr = ipv6_hdr(skb); | 283 | hdr = ipv6_hdr(skb); |
@@ -479,10 +476,13 @@ int ip6_forward(struct sk_buff *skb) | |||
479 | else | 476 | else |
480 | target = &hdr->daddr; | 477 | target = &hdr->daddr; |
481 | 478 | ||
479 | if (!rt->rt6i_peer) | ||
480 | rt6_bind_peer(rt, 1); | ||
481 | |||
482 | /* Limit redirects both by destination (here) | 482 | /* Limit redirects both by destination (here) |
483 | and by source (inside ndisc_send_redirect) | 483 | and by source (inside ndisc_send_redirect) |
484 | */ | 484 | */ |
485 | if (xrlim_allow(dst, 1*HZ)) | 485 | if (inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ)) |
486 | ndisc_send_redirect(skb, n, target); | 486 | ndisc_send_redirect(skb, n, target); |
487 | } else { | 487 | } else { |
488 | int addrtype = ipv6_addr_type(&hdr->saddr); | 488 | int addrtype = ipv6_addr_type(&hdr->saddr); |
@@ -1002,29 +1002,71 @@ int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) | |||
1002 | EXPORT_SYMBOL_GPL(ip6_dst_lookup); | 1002 | EXPORT_SYMBOL_GPL(ip6_dst_lookup); |
1003 | 1003 | ||
1004 | /** | 1004 | /** |
1005 | * ip6_sk_dst_lookup - perform socket cached route lookup on flow | 1005 | * ip6_dst_lookup_flow - perform route lookup on flow with ipsec |
1006 | * @sk: socket which provides route info | ||
1007 | * @fl: flow to lookup | ||
1008 | * @final_dst: final destination address for ipsec lookup | ||
1009 | * @can_sleep: we are in a sleepable context | ||
1010 | * | ||
1011 | * This function performs a route lookup on the given flow. | ||
1012 | * | ||
1013 | * It returns a valid dst pointer on success, or a pointer encoded | ||
1014 | * error code. | ||
1015 | */ | ||
1016 | struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi *fl, | ||
1017 | const struct in6_addr *final_dst, | ||
1018 | bool can_sleep) | ||
1019 | { | ||
1020 | struct dst_entry *dst = NULL; | ||
1021 | int err; | ||
1022 | |||
1023 | err = ip6_dst_lookup_tail(sk, &dst, fl); | ||
1024 | if (err) | ||
1025 | return ERR_PTR(err); | ||
1026 | if (final_dst) | ||
1027 | ipv6_addr_copy(&fl->fl6_dst, final_dst); | ||
1028 | if (can_sleep) | ||
1029 | fl->flags |= FLOWI_FLAG_CAN_SLEEP; | ||
1030 | |||
1031 | return xfrm_lookup(sock_net(sk), dst, fl, sk, 0); | ||
1032 | } | ||
1033 | EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow); | ||
1034 | |||
1035 | /** | ||
1036 | * ip6_sk_dst_lookup_flow - perform socket cached route lookup on flow | ||
1006 | * @sk: socket which provides the dst cache and route info | 1037 | * @sk: socket which provides the dst cache and route info |
1007 | * @dst: pointer to dst_entry * for result | ||
1008 | * @fl: flow to lookup | 1038 | * @fl: flow to lookup |
1039 | * @final_dst: final destination address for ipsec lookup | ||
1040 | * @can_sleep: we are in a sleepable context | ||
1009 | * | 1041 | * |
1010 | * This function performs a route lookup on the given flow with the | 1042 | * This function performs a route lookup on the given flow with the |
1011 | * possibility of using the cached route in the socket if it is valid. | 1043 | * possibility of using the cached route in the socket if it is valid. |
1012 | * It will take the socket dst lock when operating on the dst cache. | 1044 | * It will take the socket dst lock when operating on the dst cache. |
1013 | * As a result, this function can only be used in process context. | 1045 | * As a result, this function can only be used in process context. |
1014 | * | 1046 | * |
1015 | * It returns zero on success, or a standard errno code on error. | 1047 | * It returns a valid dst pointer on success, or a pointer encoded |
1048 | * error code. | ||
1016 | */ | 1049 | */ |
1017 | int ip6_sk_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) | 1050 | struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi *fl, |
1051 | const struct in6_addr *final_dst, | ||
1052 | bool can_sleep) | ||
1018 | { | 1053 | { |
1019 | *dst = NULL; | 1054 | struct dst_entry *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie); |
1020 | if (sk) { | 1055 | int err; |
1021 | *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie); | ||
1022 | *dst = ip6_sk_dst_check(sk, *dst, fl); | ||
1023 | } | ||
1024 | 1056 | ||
1025 | return ip6_dst_lookup_tail(sk, dst, fl); | 1057 | dst = ip6_sk_dst_check(sk, dst, fl); |
1058 | |||
1059 | err = ip6_dst_lookup_tail(sk, &dst, fl); | ||
1060 | if (err) | ||
1061 | return ERR_PTR(err); | ||
1062 | if (final_dst) | ||
1063 | ipv6_addr_copy(&fl->fl6_dst, final_dst); | ||
1064 | if (can_sleep) | ||
1065 | fl->flags |= FLOWI_FLAG_CAN_SLEEP; | ||
1066 | |||
1067 | return xfrm_lookup(sock_net(sk), dst, fl, sk, 0); | ||
1026 | } | 1068 | } |
1027 | EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup); | 1069 | EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow); |
1028 | 1070 | ||
1029 | static inline int ip6_ufo_append_data(struct sock *sk, | 1071 | static inline int ip6_ufo_append_data(struct sock *sk, |
1030 | int getfrag(void *from, char *to, int offset, int len, | 1072 | int getfrag(void *from, char *to, int offset, int len, |
@@ -1061,7 +1103,6 @@ static inline int ip6_ufo_append_data(struct sock *sk, | |||
1061 | 1103 | ||
1062 | skb->ip_summed = CHECKSUM_PARTIAL; | 1104 | skb->ip_summed = CHECKSUM_PARTIAL; |
1063 | skb->csum = 0; | 1105 | skb->csum = 0; |
1064 | sk->sk_sndmsg_off = 0; | ||
1065 | } | 1106 | } |
1066 | 1107 | ||
1067 | err = skb_append_datato_frags(sk,skb, getfrag, from, | 1108 | err = skb_append_datato_frags(sk,skb, getfrag, from, |
@@ -1118,6 +1159,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1118 | int err; | 1159 | int err; |
1119 | int offset = 0; | 1160 | int offset = 0; |
1120 | int csummode = CHECKSUM_NONE; | 1161 | int csummode = CHECKSUM_NONE; |
1162 | __u8 tx_flags = 0; | ||
1121 | 1163 | ||
1122 | if (flags&MSG_PROBE) | 1164 | if (flags&MSG_PROBE) |
1123 | return 0; | 1165 | return 0; |
@@ -1202,6 +1244,13 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1202 | } | 1244 | } |
1203 | } | 1245 | } |
1204 | 1246 | ||
1247 | /* For UDP, check if TX timestamp is enabled */ | ||
1248 | if (sk->sk_type == SOCK_DGRAM) { | ||
1249 | err = sock_tx_timestamp(sk, &tx_flags); | ||
1250 | if (err) | ||
1251 | goto error; | ||
1252 | } | ||
1253 | |||
1205 | /* | 1254 | /* |
1206 | * Let's try using as much space as possible. | 1255 | * Let's try using as much space as possible. |
1207 | * Use MTU if total length of the message fits into the MTU. | 1256 | * Use MTU if total length of the message fits into the MTU. |
@@ -1306,6 +1355,12 @@ alloc_new_skb: | |||
1306 | sk->sk_allocation); | 1355 | sk->sk_allocation); |
1307 | if (unlikely(skb == NULL)) | 1356 | if (unlikely(skb == NULL)) |
1308 | err = -ENOBUFS; | 1357 | err = -ENOBUFS; |
1358 | else { | ||
1359 | /* Only the initial fragment | ||
1360 | * is time stamped. | ||
1361 | */ | ||
1362 | tx_flags = 0; | ||
1363 | } | ||
1309 | } | 1364 | } |
1310 | if (skb == NULL) | 1365 | if (skb == NULL) |
1311 | goto error; | 1366 | goto error; |
@@ -1317,6 +1372,9 @@ alloc_new_skb: | |||
1317 | /* reserve for fragmentation */ | 1372 | /* reserve for fragmentation */ |
1318 | skb_reserve(skb, hh_len+sizeof(struct frag_hdr)); | 1373 | skb_reserve(skb, hh_len+sizeof(struct frag_hdr)); |
1319 | 1374 | ||
1375 | if (sk->sk_type == SOCK_DGRAM) | ||
1376 | skb_shinfo(skb)->tx_flags = tx_flags; | ||
1377 | |||
1320 | /* | 1378 | /* |
1321 | * Find where to start putting bytes | 1379 | * Find where to start putting bytes |
1322 | */ | 1380 | */ |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 4f4483e697bd..02730ef26b0f 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -581,7 +581,8 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
581 | fl.fl4_dst = eiph->saddr; | 581 | fl.fl4_dst = eiph->saddr; |
582 | fl.fl4_tos = RT_TOS(eiph->tos); | 582 | fl.fl4_tos = RT_TOS(eiph->tos); |
583 | fl.proto = IPPROTO_IPIP; | 583 | fl.proto = IPPROTO_IPIP; |
584 | if (ip_route_output_key(dev_net(skb->dev), &rt, &fl)) | 584 | rt = ip_route_output_key(dev_net(skb->dev), &fl); |
585 | if (IS_ERR(rt)) | ||
585 | goto out; | 586 | goto out; |
586 | 587 | ||
587 | skb2->dev = rt->dst.dev; | 588 | skb2->dev = rt->dst.dev; |
@@ -593,12 +594,14 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
593 | fl.fl4_dst = eiph->daddr; | 594 | fl.fl4_dst = eiph->daddr; |
594 | fl.fl4_src = eiph->saddr; | 595 | fl.fl4_src = eiph->saddr; |
595 | fl.fl4_tos = eiph->tos; | 596 | fl.fl4_tos = eiph->tos; |
596 | if (ip_route_output_key(dev_net(skb->dev), &rt, &fl) || | 597 | rt = ip_route_output_key(dev_net(skb->dev), &fl); |
598 | if (IS_ERR(rt) || | ||
597 | rt->dst.dev->type != ARPHRD_TUNNEL) { | 599 | rt->dst.dev->type != ARPHRD_TUNNEL) { |
598 | ip_rt_put(rt); | 600 | if (!IS_ERR(rt)) |
601 | ip_rt_put(rt); | ||
599 | goto out; | 602 | goto out; |
600 | } | 603 | } |
601 | skb_dst_set(skb2, (struct dst_entry *)rt); | 604 | skb_dst_set(skb2, &rt->dst); |
602 | } else { | 605 | } else { |
603 | ip_rt_put(rt); | 606 | ip_rt_put(rt); |
604 | if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, | 607 | if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, |
@@ -903,8 +906,14 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
903 | else { | 906 | else { |
904 | dst = ip6_route_output(net, NULL, fl); | 907 | dst = ip6_route_output(net, NULL, fl); |
905 | 908 | ||
906 | if (dst->error || xfrm_lookup(net, &dst, fl, NULL, 0) < 0) | 909 | if (dst->error) |
907 | goto tx_err_link_failure; | 910 | goto tx_err_link_failure; |
911 | dst = xfrm_lookup(net, dst, fl, NULL, 0); | ||
912 | if (IS_ERR(dst)) { | ||
913 | err = PTR_ERR(dst); | ||
914 | dst = NULL; | ||
915 | goto tx_err_link_failure; | ||
916 | } | ||
908 | } | 917 | } |
909 | 918 | ||
910 | tdev = dst->dev; | 919 | tdev = dst->dev; |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 0e1d53bcf1e0..618f67ccda31 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -1039,7 +1039,6 @@ static void ip6mr_cache_resolve(struct net *net, struct mr6_table *mrt, | |||
1039 | 1039 | ||
1040 | while((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) { | 1040 | while((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) { |
1041 | if (ipv6_hdr(skb)->version == 0) { | 1041 | if (ipv6_hdr(skb)->version == 0) { |
1042 | int err; | ||
1043 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr)); | 1042 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr)); |
1044 | 1043 | ||
1045 | if (__ip6mr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) { | 1044 | if (__ip6mr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) { |
@@ -1050,7 +1049,7 @@ static void ip6mr_cache_resolve(struct net *net, struct mr6_table *mrt, | |||
1050 | skb_trim(skb, nlh->nlmsg_len); | 1049 | skb_trim(skb, nlh->nlmsg_len); |
1051 | ((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -EMSGSIZE; | 1050 | ((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -EMSGSIZE; |
1052 | } | 1051 | } |
1053 | err = rtnl_unicast(skb, net, NETLINK_CB(skb).pid); | 1052 | rtnl_unicast(skb, net, NETLINK_CB(skb).pid); |
1054 | } else | 1053 | } else |
1055 | ip6_mr_forward(net, mrt, skb, c); | 1054 | ip6_mr_forward(net, mrt, skb, c); |
1056 | } | 1055 | } |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 49f986d626a0..7b27d08ee281 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -1429,7 +1429,12 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1429 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, | 1429 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, |
1430 | skb->dev->ifindex); | 1430 | skb->dev->ifindex); |
1431 | 1431 | ||
1432 | err = xfrm_lookup(net, &dst, &fl, NULL, 0); | 1432 | dst = xfrm_lookup(net, dst, &fl, NULL, 0); |
1433 | err = 0; | ||
1434 | if (IS_ERR(dst)) { | ||
1435 | err = PTR_ERR(dst); | ||
1436 | dst = NULL; | ||
1437 | } | ||
1433 | skb_dst_set(skb, dst); | 1438 | skb_dst_set(skb, dst); |
1434 | if (err) | 1439 | if (err) |
1435 | goto err_out; | 1440 | goto err_out; |
@@ -1796,9 +1801,11 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1796 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, | 1801 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, |
1797 | skb->dev->ifindex); | 1802 | skb->dev->ifindex); |
1798 | 1803 | ||
1799 | err = xfrm_lookup(net, &dst, &fl, NULL, 0); | 1804 | dst = xfrm_lookup(net, dst, &fl, NULL, 0); |
1800 | if (err) | 1805 | if (IS_ERR(dst)) { |
1806 | err = PTR_ERR(dst); | ||
1801 | goto err_out; | 1807 | goto err_out; |
1808 | } | ||
1802 | 1809 | ||
1803 | skb_dst_set(skb, dst); | 1810 | skb_dst_set(skb, dst); |
1804 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, | 1811 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, |
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index d6e9599d0705..f3e3ca938a54 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c | |||
@@ -203,7 +203,8 @@ static inline int mip6_report_rl_allow(struct timeval *stamp, | |||
203 | return allow; | 203 | return allow; |
204 | } | 204 | } |
205 | 205 | ||
206 | static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, struct flowi *fl) | 206 | static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, |
207 | const struct flowi *fl) | ||
207 | { | 208 | { |
208 | struct net *net = xs_net(x); | 209 | struct net *net = xs_net(x); |
209 | struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb; | 210 | struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb; |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 2342545a5ee9..9360d3be94f0 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -529,8 +529,8 @@ void ndisc_send_skb(struct sk_buff *skb, | |||
529 | return; | 529 | return; |
530 | } | 530 | } |
531 | 531 | ||
532 | err = xfrm_lookup(net, &dst, &fl, NULL, 0); | 532 | dst = xfrm_lookup(net, dst, &fl, NULL, 0); |
533 | if (err < 0) { | 533 | if (IS_ERR(dst)) { |
534 | kfree_skb(skb); | 534 | kfree_skb(skb); |
535 | return; | 535 | return; |
536 | } | 536 | } |
@@ -1542,8 +1542,8 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1542 | if (dst == NULL) | 1542 | if (dst == NULL) |
1543 | return; | 1543 | return; |
1544 | 1544 | ||
1545 | err = xfrm_lookup(net, &dst, &fl, NULL, 0); | 1545 | dst = xfrm_lookup(net, dst, &fl, NULL, 0); |
1546 | if (err) | 1546 | if (IS_ERR(dst)) |
1547 | return; | 1547 | return; |
1548 | 1548 | ||
1549 | rt = (struct rt6_info *) dst; | 1549 | rt = (struct rt6_info *) dst; |
@@ -1553,7 +1553,9 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1553 | "ICMPv6 Redirect: destination is not a neighbour.\n"); | 1553 | "ICMPv6 Redirect: destination is not a neighbour.\n"); |
1554 | goto release; | 1554 | goto release; |
1555 | } | 1555 | } |
1556 | if (!xrlim_allow(dst, 1*HZ)) | 1556 | if (!rt->rt6i_peer) |
1557 | rt6_bind_peer(rt, 1); | ||
1558 | if (inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ)) | ||
1557 | goto release; | 1559 | goto release; |
1558 | 1560 | ||
1559 | if (dev->addr_len) { | 1561 | if (dev->addr_len) { |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 35915e8617f0..8d74116ae27d 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
@@ -39,7 +39,8 @@ int ip6_route_me_harder(struct sk_buff *skb) | |||
39 | if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && | 39 | if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && |
40 | xfrm_decode_session(skb, &fl, AF_INET6) == 0) { | 40 | xfrm_decode_session(skb, &fl, AF_INET6) == 0) { |
41 | skb_dst_set(skb, NULL); | 41 | skb_dst_set(skb, NULL); |
42 | if (xfrm_lookup(net, &dst, &fl, skb->sk, 0)) | 42 | dst = xfrm_lookup(net, dst, &fl, skb->sk, 0); |
43 | if (IS_ERR(dst)) | ||
43 | return -1; | 44 | return -1; |
44 | skb_dst_set(skb, dst); | 45 | skb_dst_set(skb, dst); |
45 | } | 46 | } |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 7d227c644f72..47b7b8df7fac 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -1076,6 +1076,7 @@ static int compat_table_info(const struct xt_table_info *info, | |||
1076 | memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); | 1076 | memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); |
1077 | newinfo->initial_entries = 0; | 1077 | newinfo->initial_entries = 0; |
1078 | loc_cpu_entry = info->entries[raw_smp_processor_id()]; | 1078 | loc_cpu_entry = info->entries[raw_smp_processor_id()]; |
1079 | xt_compat_init_offsets(AF_INET6, info->number); | ||
1079 | xt_entry_foreach(iter, loc_cpu_entry, info->size) { | 1080 | xt_entry_foreach(iter, loc_cpu_entry, info->size) { |
1080 | ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo); | 1081 | ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo); |
1081 | if (ret != 0) | 1082 | if (ret != 0) |
@@ -1679,6 +1680,7 @@ translate_compat_table(struct net *net, | |||
1679 | duprintf("translate_compat_table: size %u\n", info->size); | 1680 | duprintf("translate_compat_table: size %u\n", info->size); |
1680 | j = 0; | 1681 | j = 0; |
1681 | xt_compat_lock(AF_INET6); | 1682 | xt_compat_lock(AF_INET6); |
1683 | xt_compat_init_offsets(AF_INET6, number); | ||
1682 | /* Walk through entries, checking offsets. */ | 1684 | /* Walk through entries, checking offsets. */ |
1683 | xt_entry_foreach(iter0, entry0, total_size) { | 1685 | xt_entry_foreach(iter0, entry0, total_size) { |
1684 | ret = check_compat_entry_size_and_hooks(iter0, info, &size, | 1686 | ret = check_compat_entry_size_and_hooks(iter0, info, &size, |
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index de338037a736..e6af8d72f26b 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c | |||
@@ -452,8 +452,7 @@ ip6t_log_packet(u_int8_t pf, | |||
452 | in ? in->name : "", | 452 | in ? in->name : "", |
453 | out ? out->name : ""); | 453 | out ? out->name : ""); |
454 | 454 | ||
455 | /* MAC logging for input path only. */ | 455 | if (in != NULL) |
456 | if (in && !out) | ||
457 | dump_mac_header(m, loginfo, skb); | 456 | dump_mac_header(m, loginfo, skb); |
458 | 457 | ||
459 | dump_packet(m, loginfo, skb, skb_network_offset(skb), 1); | 458 | dump_packet(m, loginfo, skb, skb_network_offset(skb), 1); |
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index bf998feac14e..91f6a61cefab 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -101,7 +101,8 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
101 | dst_release(dst); | 101 | dst_release(dst); |
102 | return; | 102 | return; |
103 | } | 103 | } |
104 | if (xfrm_lookup(net, &dst, &fl, NULL, 0)) | 104 | dst = xfrm_lookup(net, dst, &fl, NULL, 0); |
105 | if (IS_ERR(dst)) | ||
105 | return; | 106 | return; |
106 | 107 | ||
107 | hh_len = (dst->dev->hard_header_len + 15)&~15; | 108 | hh_len = (dst->dev->hard_header_len + 15)&~15; |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 79d43aa8fa8d..085727263812 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/netfilter_ipv6.h> | 45 | #include <linux/netfilter_ipv6.h> |
46 | #include <linux/kernel.h> | 46 | #include <linux/kernel.h> |
47 | #include <linux/module.h> | 47 | #include <linux/module.h> |
48 | #include <net/netfilter/ipv6/nf_defrag_ipv6.h> | ||
48 | 49 | ||
49 | 50 | ||
50 | struct nf_ct_frag6_skb_cb | 51 | struct nf_ct_frag6_skb_cb |
@@ -73,7 +74,7 @@ static struct inet_frags nf_frags; | |||
73 | static struct netns_frags nf_init_frags; | 74 | static struct netns_frags nf_init_frags; |
74 | 75 | ||
75 | #ifdef CONFIG_SYSCTL | 76 | #ifdef CONFIG_SYSCTL |
76 | struct ctl_table nf_ct_frag6_sysctl_table[] = { | 77 | static struct ctl_table nf_ct_frag6_sysctl_table[] = { |
77 | { | 78 | { |
78 | .procname = "nf_conntrack_frag6_timeout", | 79 | .procname = "nf_conntrack_frag6_timeout", |
79 | .data = &nf_init_frags.timeout, | 80 | .data = &nf_init_frags.timeout, |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index c5b0915d106b..dc29b07caf42 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -124,18 +124,18 @@ static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb) | |||
124 | } | 124 | } |
125 | 125 | ||
126 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 126 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
127 | static int (*mh_filter)(struct sock *sock, struct sk_buff *skb); | 127 | typedef int mh_filter_t(struct sock *sock, struct sk_buff *skb); |
128 | 128 | ||
129 | int rawv6_mh_filter_register(int (*filter)(struct sock *sock, | 129 | static mh_filter_t __rcu *mh_filter __read_mostly; |
130 | struct sk_buff *skb)) | 130 | |
131 | int rawv6_mh_filter_register(mh_filter_t filter) | ||
131 | { | 132 | { |
132 | rcu_assign_pointer(mh_filter, filter); | 133 | rcu_assign_pointer(mh_filter, filter); |
133 | return 0; | 134 | return 0; |
134 | } | 135 | } |
135 | EXPORT_SYMBOL(rawv6_mh_filter_register); | 136 | EXPORT_SYMBOL(rawv6_mh_filter_register); |
136 | 137 | ||
137 | int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock, | 138 | int rawv6_mh_filter_unregister(mh_filter_t filter) |
138 | struct sk_buff *skb)) | ||
139 | { | 139 | { |
140 | rcu_assign_pointer(mh_filter, NULL); | 140 | rcu_assign_pointer(mh_filter, NULL); |
141 | synchronize_rcu(); | 141 | synchronize_rcu(); |
@@ -193,10 +193,10 @@ static int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) | |||
193 | * policy is placed in rawv6_rcv() because it is | 193 | * policy is placed in rawv6_rcv() because it is |
194 | * required for each socket. | 194 | * required for each socket. |
195 | */ | 195 | */ |
196 | int (*filter)(struct sock *sock, struct sk_buff *skb); | 196 | mh_filter_t *filter; |
197 | 197 | ||
198 | filter = rcu_dereference(mh_filter); | 198 | filter = rcu_dereference(mh_filter); |
199 | filtered = filter ? filter(sk, skb) : 0; | 199 | filtered = filter ? (*filter)(sk, skb) : 0; |
200 | break; | 200 | break; |
201 | } | 201 | } |
202 | #endif | 202 | #endif |
@@ -856,20 +856,11 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
856 | fl.oif = np->mcast_oif; | 856 | fl.oif = np->mcast_oif; |
857 | security_sk_classify_flow(sk, &fl); | 857 | security_sk_classify_flow(sk, &fl); |
858 | 858 | ||
859 | err = ip6_dst_lookup(sk, &dst, &fl); | 859 | dst = ip6_dst_lookup_flow(sk, &fl, final_p, true); |
860 | if (err) | 860 | if (IS_ERR(dst)) { |
861 | err = PTR_ERR(dst); | ||
861 | goto out; | 862 | goto out; |
862 | if (final_p) | ||
863 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
864 | |||
865 | err = __xfrm_lookup(sock_net(sk), &dst, &fl, sk, XFRM_LOOKUP_WAIT); | ||
866 | if (err < 0) { | ||
867 | if (err == -EREMOTE) | ||
868 | err = ip6_dst_blackhole(sk, &dst, &fl); | ||
869 | if (err < 0) | ||
870 | goto out; | ||
871 | } | 863 | } |
872 | |||
873 | if (hlimit < 0) { | 864 | if (hlimit < 0) { |
874 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) | 865 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) |
875 | hlimit = np->mcast_hops; | 866 | hlimit = np->mcast_hops; |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 904312e25a3c..d55d00c2a824 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -97,6 +97,36 @@ static struct rt6_info *rt6_get_route_info(struct net *net, | |||
97 | struct in6_addr *gwaddr, int ifindex); | 97 | struct in6_addr *gwaddr, int ifindex); |
98 | #endif | 98 | #endif |
99 | 99 | ||
100 | static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) | ||
101 | { | ||
102 | struct rt6_info *rt = (struct rt6_info *) dst; | ||
103 | struct inet_peer *peer; | ||
104 | u32 *p = NULL; | ||
105 | |||
106 | if (!rt->rt6i_peer) | ||
107 | rt6_bind_peer(rt, 1); | ||
108 | |||
109 | peer = rt->rt6i_peer; | ||
110 | if (peer) { | ||
111 | u32 *old_p = __DST_METRICS_PTR(old); | ||
112 | unsigned long prev, new; | ||
113 | |||
114 | p = peer->metrics; | ||
115 | if (inet_metrics_new(peer)) | ||
116 | memcpy(p, old_p, sizeof(u32) * RTAX_MAX); | ||
117 | |||
118 | new = (unsigned long) p; | ||
119 | prev = cmpxchg(&dst->_metrics, old, new); | ||
120 | |||
121 | if (prev != old) { | ||
122 | p = __DST_METRICS_PTR(prev); | ||
123 | if (prev & DST_METRICS_READ_ONLY) | ||
124 | p = NULL; | ||
125 | } | ||
126 | } | ||
127 | return p; | ||
128 | } | ||
129 | |||
100 | static struct dst_ops ip6_dst_ops_template = { | 130 | static struct dst_ops ip6_dst_ops_template = { |
101 | .family = AF_INET6, | 131 | .family = AF_INET6, |
102 | .protocol = cpu_to_be16(ETH_P_IPV6), | 132 | .protocol = cpu_to_be16(ETH_P_IPV6), |
@@ -105,6 +135,7 @@ static struct dst_ops ip6_dst_ops_template = { | |||
105 | .check = ip6_dst_check, | 135 | .check = ip6_dst_check, |
106 | .default_advmss = ip6_default_advmss, | 136 | .default_advmss = ip6_default_advmss, |
107 | .default_mtu = ip6_default_mtu, | 137 | .default_mtu = ip6_default_mtu, |
138 | .cow_metrics = ipv6_cow_metrics, | ||
108 | .destroy = ip6_dst_destroy, | 139 | .destroy = ip6_dst_destroy, |
109 | .ifdown = ip6_dst_ifdown, | 140 | .ifdown = ip6_dst_ifdown, |
110 | .negative_advice = ip6_negative_advice, | 141 | .negative_advice = ip6_negative_advice, |
@@ -132,6 +163,10 @@ static struct dst_ops ip6_dst_blackhole_ops = { | |||
132 | .update_pmtu = ip6_rt_blackhole_update_pmtu, | 163 | .update_pmtu = ip6_rt_blackhole_update_pmtu, |
133 | }; | 164 | }; |
134 | 165 | ||
166 | static const u32 ip6_template_metrics[RTAX_MAX] = { | ||
167 | [RTAX_HOPLIMIT - 1] = 255, | ||
168 | }; | ||
169 | |||
135 | static struct rt6_info ip6_null_entry_template = { | 170 | static struct rt6_info ip6_null_entry_template = { |
136 | .dst = { | 171 | .dst = { |
137 | .__refcnt = ATOMIC_INIT(1), | 172 | .__refcnt = ATOMIC_INIT(1), |
@@ -187,7 +222,7 @@ static struct rt6_info ip6_blk_hole_entry_template = { | |||
187 | /* allocate dst with ip6_dst_ops */ | 222 | /* allocate dst with ip6_dst_ops */ |
188 | static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops) | 223 | static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops) |
189 | { | 224 | { |
190 | return (struct rt6_info *)dst_alloc(ops); | 225 | return (struct rt6_info *)dst_alloc(ops, 0); |
191 | } | 226 | } |
192 | 227 | ||
193 | static void ip6_dst_destroy(struct dst_entry *dst) | 228 | static void ip6_dst_destroy(struct dst_entry *dst) |
@@ -206,6 +241,13 @@ static void ip6_dst_destroy(struct dst_entry *dst) | |||
206 | } | 241 | } |
207 | } | 242 | } |
208 | 243 | ||
244 | static atomic_t __rt6_peer_genid = ATOMIC_INIT(0); | ||
245 | |||
246 | static u32 rt6_peer_genid(void) | ||
247 | { | ||
248 | return atomic_read(&__rt6_peer_genid); | ||
249 | } | ||
250 | |||
209 | void rt6_bind_peer(struct rt6_info *rt, int create) | 251 | void rt6_bind_peer(struct rt6_info *rt, int create) |
210 | { | 252 | { |
211 | struct inet_peer *peer; | 253 | struct inet_peer *peer; |
@@ -213,6 +255,8 @@ void rt6_bind_peer(struct rt6_info *rt, int create) | |||
213 | peer = inet_getpeer_v6(&rt->rt6i_dst.addr, create); | 255 | peer = inet_getpeer_v6(&rt->rt6i_dst.addr, create); |
214 | if (peer && cmpxchg(&rt->rt6i_peer, NULL, peer) != NULL) | 256 | if (peer && cmpxchg(&rt->rt6i_peer, NULL, peer) != NULL) |
215 | inet_putpeer(peer); | 257 | inet_putpeer(peer); |
258 | else | ||
259 | rt->rt6i_peer_genid = rt6_peer_genid(); | ||
216 | } | 260 | } |
217 | 261 | ||
218 | static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | 262 | static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, |
@@ -826,17 +870,15 @@ struct dst_entry * ip6_route_output(struct net *net, struct sock *sk, | |||
826 | 870 | ||
827 | EXPORT_SYMBOL(ip6_route_output); | 871 | EXPORT_SYMBOL(ip6_route_output); |
828 | 872 | ||
829 | int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl) | 873 | struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig) |
830 | { | 874 | { |
831 | struct rt6_info *ort = (struct rt6_info *) *dstp; | 875 | struct rt6_info *rt = dst_alloc(&ip6_dst_blackhole_ops, 1); |
832 | struct rt6_info *rt = (struct rt6_info *) | 876 | struct rt6_info *ort = (struct rt6_info *) dst_orig; |
833 | dst_alloc(&ip6_dst_blackhole_ops); | ||
834 | struct dst_entry *new = NULL; | 877 | struct dst_entry *new = NULL; |
835 | 878 | ||
836 | if (rt) { | 879 | if (rt) { |
837 | new = &rt->dst; | 880 | new = &rt->dst; |
838 | 881 | ||
839 | atomic_set(&new->__refcnt, 1); | ||
840 | new->__use = 1; | 882 | new->__use = 1; |
841 | new->input = dst_discard; | 883 | new->input = dst_discard; |
842 | new->output = dst_discard; | 884 | new->output = dst_discard; |
@@ -862,11 +904,9 @@ int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl | |||
862 | dst_free(new); | 904 | dst_free(new); |
863 | } | 905 | } |
864 | 906 | ||
865 | dst_release(*dstp); | 907 | dst_release(dst_orig); |
866 | *dstp = new; | 908 | return new ? new : ERR_PTR(-ENOMEM); |
867 | return new ? 0 : -ENOMEM; | ||
868 | } | 909 | } |
869 | EXPORT_SYMBOL_GPL(ip6_dst_blackhole); | ||
870 | 910 | ||
871 | /* | 911 | /* |
872 | * Destination cache support functions | 912 | * Destination cache support functions |
@@ -878,9 +918,14 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) | |||
878 | 918 | ||
879 | rt = (struct rt6_info *) dst; | 919 | rt = (struct rt6_info *) dst; |
880 | 920 | ||
881 | if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) | 921 | if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) { |
922 | if (rt->rt6i_peer_genid != rt6_peer_genid()) { | ||
923 | if (!rt->rt6i_peer) | ||
924 | rt6_bind_peer(rt, 0); | ||
925 | rt->rt6i_peer_genid = rt6_peer_genid(); | ||
926 | } | ||
882 | return dst; | 927 | return dst; |
883 | 928 | } | |
884 | return NULL; | 929 | return NULL; |
885 | } | 930 | } |
886 | 931 | ||
@@ -931,7 +976,6 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
931 | dst_metric_set(dst, RTAX_FEATURES, features); | 976 | dst_metric_set(dst, RTAX_FEATURES, features); |
932 | } | 977 | } |
933 | dst_metric_set(dst, RTAX_MTU, mtu); | 978 | dst_metric_set(dst, RTAX_MTU, mtu); |
934 | call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst); | ||
935 | } | 979 | } |
936 | } | 980 | } |
937 | 981 | ||
@@ -1028,11 +1072,9 @@ out: | |||
1028 | 1072 | ||
1029 | int icmp6_dst_gc(void) | 1073 | int icmp6_dst_gc(void) |
1030 | { | 1074 | { |
1031 | struct dst_entry *dst, *next, **pprev; | 1075 | struct dst_entry *dst, **pprev; |
1032 | int more = 0; | 1076 | int more = 0; |
1033 | 1077 | ||
1034 | next = NULL; | ||
1035 | |||
1036 | spin_lock_bh(&icmp6_dst_lock); | 1078 | spin_lock_bh(&icmp6_dst_lock); |
1037 | pprev = &icmp6_dst_gc_list; | 1079 | pprev = &icmp6_dst_gc_list; |
1038 | 1080 | ||
@@ -1980,12 +2022,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
1980 | if (IS_ERR(neigh)) { | 2022 | if (IS_ERR(neigh)) { |
1981 | dst_free(&rt->dst); | 2023 | dst_free(&rt->dst); |
1982 | 2024 | ||
1983 | /* We are casting this because that is the return | 2025 | return ERR_CAST(neigh); |
1984 | * value type. But an errno encoded pointer is the | ||
1985 | * same regardless of the underlying pointer type, | ||
1986 | * and that's what we are returning. So this is OK. | ||
1987 | */ | ||
1988 | return (struct rt6_info *) neigh; | ||
1989 | } | 2026 | } |
1990 | rt->rt6i_nexthop = neigh; | 2027 | rt->rt6i_nexthop = neigh; |
1991 | 2028 | ||
@@ -2687,7 +2724,8 @@ static int __net_init ip6_route_net_init(struct net *net) | |||
2687 | net->ipv6.ip6_null_entry->dst.path = | 2724 | net->ipv6.ip6_null_entry->dst.path = |
2688 | (struct dst_entry *)net->ipv6.ip6_null_entry; | 2725 | (struct dst_entry *)net->ipv6.ip6_null_entry; |
2689 | net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops; | 2726 | net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
2690 | dst_metric_set(&net->ipv6.ip6_null_entry->dst, RTAX_HOPLIMIT, 255); | 2727 | dst_init_metrics(&net->ipv6.ip6_null_entry->dst, |
2728 | ip6_template_metrics, true); | ||
2691 | 2729 | ||
2692 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 2730 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
2693 | net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, | 2731 | net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, |
@@ -2698,7 +2736,8 @@ static int __net_init ip6_route_net_init(struct net *net) | |||
2698 | net->ipv6.ip6_prohibit_entry->dst.path = | 2736 | net->ipv6.ip6_prohibit_entry->dst.path = |
2699 | (struct dst_entry *)net->ipv6.ip6_prohibit_entry; | 2737 | (struct dst_entry *)net->ipv6.ip6_prohibit_entry; |
2700 | net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops; | 2738 | net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
2701 | dst_metric_set(&net->ipv6.ip6_prohibit_entry->dst, RTAX_HOPLIMIT, 255); | 2739 | dst_init_metrics(&net->ipv6.ip6_prohibit_entry->dst, |
2740 | ip6_template_metrics, true); | ||
2702 | 2741 | ||
2703 | net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, | 2742 | net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, |
2704 | sizeof(*net->ipv6.ip6_blk_hole_entry), | 2743 | sizeof(*net->ipv6.ip6_blk_hole_entry), |
@@ -2708,7 +2747,8 @@ static int __net_init ip6_route_net_init(struct net *net) | |||
2708 | net->ipv6.ip6_blk_hole_entry->dst.path = | 2747 | net->ipv6.ip6_blk_hole_entry->dst.path = |
2709 | (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; | 2748 | (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; |
2710 | net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; | 2749 | net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
2711 | dst_metric_set(&net->ipv6.ip6_blk_hole_entry->dst, RTAX_HOPLIMIT, 255); | 2750 | dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, |
2751 | ip6_template_metrics, true); | ||
2712 | #endif | 2752 | #endif |
2713 | 2753 | ||
2714 | net->ipv6.sysctl.flush_delay = 0; | 2754 | net->ipv6.sysctl.flush_delay = 0; |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 8ce38f10a547..b8c8adbd7cf6 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -412,7 +412,7 @@ static void prl_list_destroy_rcu(struct rcu_head *head) | |||
412 | 412 | ||
413 | p = container_of(head, struct ip_tunnel_prl_entry, rcu_head); | 413 | p = container_of(head, struct ip_tunnel_prl_entry, rcu_head); |
414 | do { | 414 | do { |
415 | n = p->next; | 415 | n = rcu_dereference_protected(p->next, 1); |
416 | kfree(p); | 416 | kfree(p); |
417 | p = n; | 417 | p = n; |
418 | } while (p); | 418 | } while (p); |
@@ -421,15 +421,17 @@ static void prl_list_destroy_rcu(struct rcu_head *head) | |||
421 | static int | 421 | static int |
422 | ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) | 422 | ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) |
423 | { | 423 | { |
424 | struct ip_tunnel_prl_entry *x, **p; | 424 | struct ip_tunnel_prl_entry *x; |
425 | struct ip_tunnel_prl_entry __rcu **p; | ||
425 | int err = 0; | 426 | int err = 0; |
426 | 427 | ||
427 | ASSERT_RTNL(); | 428 | ASSERT_RTNL(); |
428 | 429 | ||
429 | if (a && a->addr != htonl(INADDR_ANY)) { | 430 | if (a && a->addr != htonl(INADDR_ANY)) { |
430 | for (p = &t->prl; *p; p = &(*p)->next) { | 431 | for (p = &t->prl; |
431 | if ((*p)->addr == a->addr) { | 432 | (x = rtnl_dereference(*p)) != NULL; |
432 | x = *p; | 433 | p = &x->next) { |
434 | if (x->addr == a->addr) { | ||
433 | *p = x->next; | 435 | *p = x->next; |
434 | call_rcu(&x->rcu_head, prl_entry_destroy_rcu); | 436 | call_rcu(&x->rcu_head, prl_entry_destroy_rcu); |
435 | t->prl_count--; | 437 | t->prl_count--; |
@@ -438,9 +440,9 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) | |||
438 | } | 440 | } |
439 | err = -ENXIO; | 441 | err = -ENXIO; |
440 | } else { | 442 | } else { |
441 | if (t->prl) { | 443 | x = rtnl_dereference(t->prl); |
444 | if (x) { | ||
442 | t->prl_count = 0; | 445 | t->prl_count = 0; |
443 | x = t->prl; | ||
444 | call_rcu(&x->rcu_head, prl_list_destroy_rcu); | 446 | call_rcu(&x->rcu_head, prl_list_destroy_rcu); |
445 | t->prl = NULL; | 447 | t->prl = NULL; |
446 | } | 448 | } |
@@ -736,7 +738,8 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
736 | .fl4_tos = RT_TOS(tos), | 738 | .fl4_tos = RT_TOS(tos), |
737 | .oif = tunnel->parms.link, | 739 | .oif = tunnel->parms.link, |
738 | .proto = IPPROTO_IPV6 }; | 740 | .proto = IPPROTO_IPV6 }; |
739 | if (ip_route_output_key(dev_net(dev), &rt, &fl)) { | 741 | rt = ip_route_output_key(dev_net(dev), &fl); |
742 | if (IS_ERR(rt)) { | ||
740 | dev->stats.tx_carrier_errors++; | 743 | dev->stats.tx_carrier_errors++; |
741 | goto tx_error_icmp; | 744 | goto tx_error_icmp; |
742 | } | 745 | } |
@@ -860,8 +863,9 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) | |||
860 | .fl4_tos = RT_TOS(iph->tos), | 863 | .fl4_tos = RT_TOS(iph->tos), |
861 | .oif = tunnel->parms.link, | 864 | .oif = tunnel->parms.link, |
862 | .proto = IPPROTO_IPV6 }; | 865 | .proto = IPPROTO_IPV6 }; |
863 | struct rtable *rt; | 866 | struct rtable *rt = ip_route_output_key(dev_net(dev), &fl); |
864 | if (!ip_route_output_key(dev_net(dev), &rt, &fl)) { | 867 | |
868 | if (!IS_ERR(rt)) { | ||
865 | tdev = rt->dst.dev; | 869 | tdev = rt->dst.dev; |
866 | ip_rt_put(rt); | 870 | ip_rt_put(rt); |
867 | } | 871 | } |
@@ -1179,7 +1183,7 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) | |||
1179 | if (!dev->tstats) | 1183 | if (!dev->tstats) |
1180 | return -ENOMEM; | 1184 | return -ENOMEM; |
1181 | dev_hold(dev); | 1185 | dev_hold(dev); |
1182 | sitn->tunnels_wc[0] = tunnel; | 1186 | rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); |
1183 | return 0; | 1187 | return 0; |
1184 | } | 1188 | } |
1185 | 1189 | ||
@@ -1196,11 +1200,12 @@ static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_hea | |||
1196 | for (prio = 1; prio < 4; prio++) { | 1200 | for (prio = 1; prio < 4; prio++) { |
1197 | int h; | 1201 | int h; |
1198 | for (h = 0; h < HASH_SIZE; h++) { | 1202 | for (h = 0; h < HASH_SIZE; h++) { |
1199 | struct ip_tunnel *t = sitn->tunnels[prio][h]; | 1203 | struct ip_tunnel *t; |
1200 | 1204 | ||
1205 | t = rtnl_dereference(sitn->tunnels[prio][h]); | ||
1201 | while (t != NULL) { | 1206 | while (t != NULL) { |
1202 | unregister_netdevice_queue(t->dev, head); | 1207 | unregister_netdevice_queue(t->dev, head); |
1203 | t = t->next; | 1208 | t = rtnl_dereference(t->next); |
1204 | } | 1209 | } |
1205 | } | 1210 | } |
1206 | } | 1211 | } |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 09fd34f0dbf2..0b4cf350631b 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -243,12 +243,9 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
243 | fl.fl_ip_dport = inet_rsk(req)->rmt_port; | 243 | fl.fl_ip_dport = inet_rsk(req)->rmt_port; |
244 | fl.fl_ip_sport = inet_sk(sk)->inet_sport; | 244 | fl.fl_ip_sport = inet_sk(sk)->inet_sport; |
245 | security_req_classify_flow(req, &fl); | 245 | security_req_classify_flow(req, &fl); |
246 | if (ip6_dst_lookup(sk, &dst, &fl)) | ||
247 | goto out_free; | ||
248 | 246 | ||
249 | if (final_p) | 247 | dst = ip6_dst_lookup_flow(sk, &fl, final_p, false); |
250 | ipv6_addr_copy(&fl.fl6_dst, final_p); | 248 | if (IS_ERR(dst)) |
251 | if ((xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0) | ||
252 | goto out_free; | 249 | goto out_free; |
253 | } | 250 | } |
254 | 251 | ||
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 20aa95e37359..e59a31c48baf 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -255,18 +255,10 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
255 | 255 | ||
256 | security_sk_classify_flow(sk, &fl); | 256 | security_sk_classify_flow(sk, &fl); |
257 | 257 | ||
258 | err = ip6_dst_lookup(sk, &dst, &fl); | 258 | dst = ip6_dst_lookup_flow(sk, &fl, final_p, true); |
259 | if (err) | 259 | if (IS_ERR(dst)) { |
260 | err = PTR_ERR(dst); | ||
260 | goto failure; | 261 | goto failure; |
261 | if (final_p) | ||
262 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
263 | |||
264 | err = __xfrm_lookup(sock_net(sk), &dst, &fl, sk, XFRM_LOOKUP_WAIT); | ||
265 | if (err < 0) { | ||
266 | if (err == -EREMOTE) | ||
267 | err = ip6_dst_blackhole(sk, &dst, &fl); | ||
268 | if (err < 0) | ||
269 | goto failure; | ||
270 | } | 262 | } |
271 | 263 | ||
272 | if (saddr == NULL) { | 264 | if (saddr == NULL) { |
@@ -385,7 +377,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
385 | np = inet6_sk(sk); | 377 | np = inet6_sk(sk); |
386 | 378 | ||
387 | if (type == ICMPV6_PKT_TOOBIG) { | 379 | if (type == ICMPV6_PKT_TOOBIG) { |
388 | struct dst_entry *dst = NULL; | 380 | struct dst_entry *dst; |
389 | 381 | ||
390 | if (sock_owned_by_user(sk)) | 382 | if (sock_owned_by_user(sk)) |
391 | goto out; | 383 | goto out; |
@@ -413,13 +405,9 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
413 | fl.fl_ip_sport = inet->inet_sport; | 405 | fl.fl_ip_sport = inet->inet_sport; |
414 | security_skb_classify_flow(skb, &fl); | 406 | security_skb_classify_flow(skb, &fl); |
415 | 407 | ||
416 | if ((err = ip6_dst_lookup(sk, &dst, &fl))) { | 408 | dst = ip6_dst_lookup_flow(sk, &fl, NULL, false); |
417 | sk->sk_err_soft = -err; | 409 | if (IS_ERR(dst)) { |
418 | goto out; | 410 | sk->sk_err_soft = -PTR_ERR(dst); |
419 | } | ||
420 | |||
421 | if ((err = xfrm_lookup(net, &dst, &fl, sk, 0)) < 0) { | ||
422 | sk->sk_err_soft = -err; | ||
423 | goto out; | 411 | goto out; |
424 | } | 412 | } |
425 | 413 | ||
@@ -496,7 +484,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
496 | struct in6_addr * final_p, final; | 484 | struct in6_addr * final_p, final; |
497 | struct flowi fl; | 485 | struct flowi fl; |
498 | struct dst_entry *dst; | 486 | struct dst_entry *dst; |
499 | int err = -1; | 487 | int err; |
500 | 488 | ||
501 | memset(&fl, 0, sizeof(fl)); | 489 | memset(&fl, 0, sizeof(fl)); |
502 | fl.proto = IPPROTO_TCP; | 490 | fl.proto = IPPROTO_TCP; |
@@ -512,15 +500,13 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
512 | opt = np->opt; | 500 | opt = np->opt; |
513 | final_p = fl6_update_dst(&fl, opt, &final); | 501 | final_p = fl6_update_dst(&fl, opt, &final); |
514 | 502 | ||
515 | err = ip6_dst_lookup(sk, &dst, &fl); | 503 | dst = ip6_dst_lookup_flow(sk, &fl, final_p, false); |
516 | if (err) | 504 | if (IS_ERR(dst)) { |
505 | err = PTR_ERR(dst); | ||
517 | goto done; | 506 | goto done; |
518 | if (final_p) | 507 | } |
519 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
520 | if ((err = xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0) | ||
521 | goto done; | ||
522 | |||
523 | skb = tcp_make_synack(sk, dst, req, rvp); | 508 | skb = tcp_make_synack(sk, dst, req, rvp); |
509 | err = -ENOMEM; | ||
524 | if (skb) { | 510 | if (skb) { |
525 | __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); | 511 | __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); |
526 | 512 | ||
@@ -1079,15 +1065,14 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
1079 | * Underlying function will use this to retrieve the network | 1065 | * Underlying function will use this to retrieve the network |
1080 | * namespace | 1066 | * namespace |
1081 | */ | 1067 | */ |
1082 | if (!ip6_dst_lookup(ctl_sk, &dst, &fl)) { | 1068 | dst = ip6_dst_lookup_flow(ctl_sk, &fl, NULL, false); |
1083 | if (xfrm_lookup(net, &dst, &fl, NULL, 0) >= 0) { | 1069 | if (!IS_ERR(dst)) { |
1084 | skb_dst_set(buff, dst); | 1070 | skb_dst_set(buff, dst); |
1085 | ip6_xmit(ctl_sk, buff, &fl, NULL); | 1071 | ip6_xmit(ctl_sk, buff, &fl, NULL); |
1086 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); | 1072 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); |
1087 | if (rst) | 1073 | if (rst) |
1088 | TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); | 1074 | TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); |
1089 | return; | 1075 | return; |
1090 | } | ||
1091 | } | 1076 | } |
1092 | 1077 | ||
1093 | kfree_skb(buff); | 1078 | kfree_skb(buff); |
@@ -1323,7 +1308,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1323 | tcp_death_row.sysctl_tw_recycle && | 1308 | tcp_death_row.sysctl_tw_recycle && |
1324 | (dst = inet6_csk_route_req(sk, req)) != NULL && | 1309 | (dst = inet6_csk_route_req(sk, req)) != NULL && |
1325 | (peer = rt6_get_peer((struct rt6_info *)dst)) != NULL && | 1310 | (peer = rt6_get_peer((struct rt6_info *)dst)) != NULL && |
1326 | ipv6_addr_equal((struct in6_addr *)peer->daddr.a6, | 1311 | ipv6_addr_equal((struct in6_addr *)peer->daddr.addr.a6, |
1327 | &treq->rmt_addr)) { | 1312 | &treq->rmt_addr)) { |
1328 | inet_peer_refcheck(peer); | 1313 | inet_peer_refcheck(peer); |
1329 | if ((u32)get_seconds() - peer->tcp_ts_stamp < TCP_PAWS_MSL && | 1314 | if ((u32)get_seconds() - peer->tcp_ts_stamp < TCP_PAWS_MSL && |
@@ -1636,10 +1621,8 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1636 | opt_skb = skb_clone(skb, GFP_ATOMIC); | 1621 | opt_skb = skb_clone(skb, GFP_ATOMIC); |
1637 | 1622 | ||
1638 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ | 1623 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ |
1639 | TCP_CHECK_TIMER(sk); | ||
1640 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) | 1624 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) |
1641 | goto reset; | 1625 | goto reset; |
1642 | TCP_CHECK_TIMER(sk); | ||
1643 | if (opt_skb) | 1626 | if (opt_skb) |
1644 | goto ipv6_pktoptions; | 1627 | goto ipv6_pktoptions; |
1645 | return 0; | 1628 | return 0; |
@@ -1667,10 +1650,8 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1667 | } | 1650 | } |
1668 | } | 1651 | } |
1669 | 1652 | ||
1670 | TCP_CHECK_TIMER(sk); | ||
1671 | if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) | 1653 | if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) |
1672 | goto reset; | 1654 | goto reset; |
1673 | TCP_CHECK_TIMER(sk); | ||
1674 | if (opt_skb) | 1655 | if (opt_skb) |
1675 | goto ipv6_pktoptions; | 1656 | goto ipv6_pktoptions; |
1676 | return 0; | 1657 | return 0; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 9a009c66c8a3..d86d7f67a597 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -1125,18 +1125,11 @@ do_udp_sendmsg: | |||
1125 | 1125 | ||
1126 | security_sk_classify_flow(sk, &fl); | 1126 | security_sk_classify_flow(sk, &fl); |
1127 | 1127 | ||
1128 | err = ip6_sk_dst_lookup(sk, &dst, &fl); | 1128 | dst = ip6_sk_dst_lookup_flow(sk, &fl, final_p, true); |
1129 | if (err) | 1129 | if (IS_ERR(dst)) { |
1130 | err = PTR_ERR(dst); | ||
1131 | dst = NULL; | ||
1130 | goto out; | 1132 | goto out; |
1131 | if (final_p) | ||
1132 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
1133 | |||
1134 | err = __xfrm_lookup(sock_net(sk), &dst, &fl, sk, XFRM_LOOKUP_WAIT); | ||
1135 | if (err < 0) { | ||
1136 | if (err == -EREMOTE) | ||
1137 | err = ip6_dst_blackhole(sk, &dst, &fl); | ||
1138 | if (err < 0) | ||
1139 | goto out; | ||
1140 | } | 1133 | } |
1141 | 1134 | ||
1142 | if (hlimit < 0) { | 1135 | if (hlimit < 0) { |
@@ -1299,7 +1292,7 @@ static int udp6_ufo_send_check(struct sk_buff *skb) | |||
1299 | return 0; | 1292 | return 0; |
1300 | } | 1293 | } |
1301 | 1294 | ||
1302 | static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, int features) | 1295 | static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, u32 features) |
1303 | { | 1296 | { |
1304 | struct sk_buff *segs = ERR_PTR(-EINVAL); | 1297 | struct sk_buff *segs = ERR_PTR(-EINVAL); |
1305 | unsigned int mss; | 1298 | unsigned int mss; |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index da87428681cc..48ce496802fd 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -27,8 +27,8 @@ | |||
27 | static struct xfrm_policy_afinfo xfrm6_policy_afinfo; | 27 | static struct xfrm_policy_afinfo xfrm6_policy_afinfo; |
28 | 28 | ||
29 | static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, | 29 | static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, |
30 | xfrm_address_t *saddr, | 30 | const xfrm_address_t *saddr, |
31 | xfrm_address_t *daddr) | 31 | const xfrm_address_t *daddr) |
32 | { | 32 | { |
33 | struct flowi fl = {}; | 33 | struct flowi fl = {}; |
34 | struct dst_entry *dst; | 34 | struct dst_entry *dst; |
@@ -67,7 +67,7 @@ static int xfrm6_get_saddr(struct net *net, | |||
67 | return 0; | 67 | return 0; |
68 | } | 68 | } |
69 | 69 | ||
70 | static int xfrm6_get_tos(struct flowi *fl) | 70 | static int xfrm6_get_tos(const struct flowi *fl) |
71 | { | 71 | { |
72 | return 0; | 72 | return 0; |
73 | } | 73 | } |
@@ -87,7 +87,7 @@ static int xfrm6_init_path(struct xfrm_dst *path, struct dst_entry *dst, | |||
87 | } | 87 | } |
88 | 88 | ||
89 | static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, | 89 | static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, |
90 | struct flowi *fl) | 90 | const struct flowi *fl) |
91 | { | 91 | { |
92 | struct rt6_info *rt = (struct rt6_info*)xdst->route; | 92 | struct rt6_info *rt = (struct rt6_info*)xdst->route; |
93 | 93 | ||
@@ -220,6 +220,7 @@ static void xfrm6_dst_destroy(struct dst_entry *dst) | |||
220 | 220 | ||
221 | if (likely(xdst->u.rt6.rt6i_idev)) | 221 | if (likely(xdst->u.rt6.rt6i_idev)) |
222 | in6_dev_put(xdst->u.rt6.rt6i_idev); | 222 | in6_dev_put(xdst->u.rt6.rt6i_idev); |
223 | dst_destroy_metrics_generic(dst); | ||
223 | if (likely(xdst->u.rt6.rt6i_peer)) | 224 | if (likely(xdst->u.rt6.rt6i_peer)) |
224 | inet_putpeer(xdst->u.rt6.rt6i_peer); | 225 | inet_putpeer(xdst->u.rt6.rt6i_peer); |
225 | xfrm_dst_destroy(xdst); | 226 | xfrm_dst_destroy(xdst); |
@@ -257,6 +258,7 @@ static struct dst_ops xfrm6_dst_ops = { | |||
257 | .protocol = cpu_to_be16(ETH_P_IPV6), | 258 | .protocol = cpu_to_be16(ETH_P_IPV6), |
258 | .gc = xfrm6_garbage_collect, | 259 | .gc = xfrm6_garbage_collect, |
259 | .update_pmtu = xfrm6_update_pmtu, | 260 | .update_pmtu = xfrm6_update_pmtu, |
261 | .cow_metrics = dst_cow_metrics_generic, | ||
260 | .destroy = xfrm6_dst_destroy, | 262 | .destroy = xfrm6_dst_destroy, |
261 | .ifdown = xfrm6_dst_ifdown, | 263 | .ifdown = xfrm6_dst_ifdown, |
262 | .local_out = __ip6_local_out, | 264 | .local_out = __ip6_local_out, |
@@ -272,6 +274,7 @@ static struct xfrm_policy_afinfo xfrm6_policy_afinfo = { | |||
272 | .get_tos = xfrm6_get_tos, | 274 | .get_tos = xfrm6_get_tos, |
273 | .init_path = xfrm6_init_path, | 275 | .init_path = xfrm6_init_path, |
274 | .fill_dst = xfrm6_fill_dst, | 276 | .fill_dst = xfrm6_fill_dst, |
277 | .blackhole_route = ip6_blackhole_route, | ||
275 | }; | 278 | }; |
276 | 279 | ||
277 | static int __init xfrm6_policy_init(void) | 280 | static int __init xfrm6_policy_init(void) |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index a67575d472a3..a02598e0079a 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <net/addrconf.h> | 20 | #include <net/addrconf.h> |
21 | 21 | ||
22 | static void | 22 | static void |
23 | __xfrm6_init_tempsel(struct xfrm_selector *sel, struct flowi *fl) | 23 | __xfrm6_init_tempsel(struct xfrm_selector *sel, const struct flowi *fl) |
24 | { | 24 | { |
25 | /* Initialize temporary selector matching only | 25 | /* Initialize temporary selector matching only |
26 | * to current session. */ | 26 | * to current session. */ |
@@ -38,8 +38,8 @@ __xfrm6_init_tempsel(struct xfrm_selector *sel, struct flowi *fl) | |||
38 | } | 38 | } |
39 | 39 | ||
40 | static void | 40 | static void |
41 | xfrm6_init_temprop(struct xfrm_state *x, struct xfrm_tmpl *tmpl, | 41 | xfrm6_init_temprop(struct xfrm_state *x, const struct xfrm_tmpl *tmpl, |
42 | xfrm_address_t *daddr, xfrm_address_t *saddr) | 42 | const xfrm_address_t *daddr, const xfrm_address_t *saddr) |
43 | { | 43 | { |
44 | x->id = tmpl->id; | 44 | x->id = tmpl->id; |
45 | if (ipv6_addr_any((struct in6_addr*)&x->id.daddr)) | 45 | if (ipv6_addr_any((struct in6_addr*)&x->id.daddr)) |