diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 19 | ||||
-rw-r--r-- | net/ipv6/route.c | 15 | ||||
-rw-r--r-- | net/ipv6/udp.c | 7 |
3 files changed, 29 insertions, 12 deletions
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 84d7ebdb9d21..b9f40290d12a 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -542,6 +542,7 @@ ip6ip6_rcv(struct sk_buff *skb) | |||
542 | skb->dev = t->dev; | 542 | skb->dev = t->dev; |
543 | dst_release(skb->dst); | 543 | dst_release(skb->dst); |
544 | skb->dst = NULL; | 544 | skb->dst = NULL; |
545 | nf_reset(skb); | ||
545 | if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) | 546 | if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) |
546 | ipv6_copy_dscp(ipv6h, skb->nh.ipv6h); | 547 | ipv6_copy_dscp(ipv6h, skb->nh.ipv6h); |
547 | ip6ip6_ecn_decapsulate(ipv6h, skb); | 548 | ip6ip6_ecn_decapsulate(ipv6h, skb); |
@@ -1149,6 +1150,20 @@ fail: | |||
1149 | return err; | 1150 | return err; |
1150 | } | 1151 | } |
1151 | 1152 | ||
1153 | static void __exit ip6ip6_destroy_tunnels(void) | ||
1154 | { | ||
1155 | int h; | ||
1156 | struct ip6_tnl *t; | ||
1157 | |||
1158 | for (h = 0; h < HASH_SIZE; h++) { | ||
1159 | while ((t = tnls_r_l[h]) != NULL) | ||
1160 | unregister_netdevice(t->dev); | ||
1161 | } | ||
1162 | |||
1163 | t = tnls_wc[0]; | ||
1164 | unregister_netdevice(t->dev); | ||
1165 | } | ||
1166 | |||
1152 | /** | 1167 | /** |
1153 | * ip6_tunnel_cleanup - free resources and unregister protocol | 1168 | * ip6_tunnel_cleanup - free resources and unregister protocol |
1154 | **/ | 1169 | **/ |
@@ -1158,7 +1173,9 @@ static void __exit ip6_tunnel_cleanup(void) | |||
1158 | if (xfrm6_tunnel_deregister(&ip6ip6_handler)) | 1173 | if (xfrm6_tunnel_deregister(&ip6ip6_handler)) |
1159 | printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n"); | 1174 | printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n"); |
1160 | 1175 | ||
1161 | unregister_netdev(ip6ip6_fb_tnl_dev); | 1176 | rtnl_lock(); |
1177 | ip6ip6_destroy_tunnels(); | ||
1178 | rtnl_unlock(); | ||
1162 | } | 1179 | } |
1163 | 1180 | ||
1164 | module_init(ip6_tunnel_init); | 1181 | module_init(ip6_tunnel_init); |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c953466b7afd..b39ae99122d5 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -330,6 +330,8 @@ static int inline rt6_check_neigh(struct rt6_info *rt) | |||
330 | read_lock_bh(&neigh->lock); | 330 | read_lock_bh(&neigh->lock); |
331 | if (neigh->nud_state & NUD_VALID) | 331 | if (neigh->nud_state & NUD_VALID) |
332 | m = 2; | 332 | m = 2; |
333 | else if (!(neigh->nud_state & NUD_FAILED)) | ||
334 | m = 1; | ||
333 | read_unlock_bh(&neigh->lock); | 335 | read_unlock_bh(&neigh->lock); |
334 | } | 336 | } |
335 | return m; | 337 | return m; |
@@ -347,9 +349,7 @@ static int rt6_score_route(struct rt6_info *rt, int oif, | |||
347 | m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2; | 349 | m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2; |
348 | #endif | 350 | #endif |
349 | n = rt6_check_neigh(rt); | 351 | n = rt6_check_neigh(rt); |
350 | if (n > 1) | 352 | if (!n && (strict & RT6_LOOKUP_F_REACHABLE)) |
351 | m |= 16; | ||
352 | else if (!n && strict & RT6_LOOKUP_F_REACHABLE) | ||
353 | return -1; | 353 | return -1; |
354 | return m; | 354 | return m; |
355 | } | 355 | } |
@@ -380,10 +380,11 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif, | |||
380 | continue; | 380 | continue; |
381 | 381 | ||
382 | if (m > mpri) { | 382 | if (m > mpri) { |
383 | rt6_probe(match); | 383 | if (strict & RT6_LOOKUP_F_REACHABLE) |
384 | rt6_probe(match); | ||
384 | match = rt; | 385 | match = rt; |
385 | mpri = m; | 386 | mpri = m; |
386 | } else { | 387 | } else if (strict & RT6_LOOKUP_F_REACHABLE) { |
387 | rt6_probe(rt); | 388 | rt6_probe(rt); |
388 | } | 389 | } |
389 | } | 390 | } |
@@ -636,7 +637,7 @@ static struct rt6_info *ip6_pol_route_input(struct fib6_table *table, | |||
636 | int strict = 0; | 637 | int strict = 0; |
637 | int attempts = 3; | 638 | int attempts = 3; |
638 | int err; | 639 | int err; |
639 | int reachable = RT6_LOOKUP_F_REACHABLE; | 640 | int reachable = ipv6_devconf.forwarding ? 0 : RT6_LOOKUP_F_REACHABLE; |
640 | 641 | ||
641 | strict |= flags & RT6_LOOKUP_F_IFACE; | 642 | strict |= flags & RT6_LOOKUP_F_IFACE; |
642 | 643 | ||
@@ -733,7 +734,7 @@ static struct rt6_info *ip6_pol_route_output(struct fib6_table *table, | |||
733 | int strict = 0; | 734 | int strict = 0; |
734 | int attempts = 3; | 735 | int attempts = 3; |
735 | int err; | 736 | int err; |
736 | int reachable = RT6_LOOKUP_F_REACHABLE; | 737 | int reachable = ipv6_devconf.forwarding ? 0 : RT6_LOOKUP_F_REACHABLE; |
737 | 738 | ||
738 | strict |= flags & RT6_LOOKUP_F_IFACE; | 739 | strict |= flags & RT6_LOOKUP_F_IFACE; |
739 | 740 | ||
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index e0c3934a7e4b..c83f23e51c46 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -242,14 +242,13 @@ static void udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
242 | { | 242 | { |
243 | struct ipv6_pinfo *np; | 243 | struct ipv6_pinfo *np; |
244 | struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; | 244 | struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; |
245 | struct net_device *dev = skb->dev; | ||
246 | struct in6_addr *saddr = &hdr->saddr; | 245 | struct in6_addr *saddr = &hdr->saddr; |
247 | struct in6_addr *daddr = &hdr->daddr; | 246 | struct in6_addr *daddr = &hdr->daddr; |
248 | struct udphdr *uh = (struct udphdr*)(skb->data+offset); | 247 | struct udphdr *uh = (struct udphdr*)(skb->data+offset); |
249 | struct sock *sk; | 248 | struct sock *sk; |
250 | int err; | 249 | int err; |
251 | 250 | ||
252 | sk = udp_v6_lookup(daddr, uh->dest, saddr, uh->source, dev->ifindex); | 251 | sk = udp_v6_lookup(daddr, uh->dest, saddr, uh->source, inet6_iif(skb)); |
253 | 252 | ||
254 | if (sk == NULL) | 253 | if (sk == NULL) |
255 | return; | 254 | return; |
@@ -348,7 +347,7 @@ static void udpv6_mcast_deliver(struct udphdr *uh, | |||
348 | 347 | ||
349 | read_lock(&udp_hash_lock); | 348 | read_lock(&udp_hash_lock); |
350 | sk = sk_head(&udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]); | 349 | sk = sk_head(&udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]); |
351 | dif = skb->dev->ifindex; | 350 | dif = inet6_iif(skb); |
352 | sk = udp_v6_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif); | 351 | sk = udp_v6_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif); |
353 | if (!sk) { | 352 | if (!sk) { |
354 | kfree_skb(skb); | 353 | kfree_skb(skb); |
@@ -429,7 +428,7 @@ static int udpv6_rcv(struct sk_buff **pskb) | |||
429 | * check socket cache ... must talk to Alan about his plans | 428 | * check socket cache ... must talk to Alan about his plans |
430 | * for sock caches... i'll skip this for now. | 429 | * for sock caches... i'll skip this for now. |
431 | */ | 430 | */ |
432 | sk = udp_v6_lookup(saddr, uh->source, daddr, uh->dest, dev->ifindex); | 431 | sk = udp_v6_lookup(saddr, uh->source, daddr, uh->dest, inet6_iif(skb)); |
433 | 432 | ||
434 | if (sk == NULL) { | 433 | if (sk == NULL) { |
435 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) | 434 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) |