aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/addrconf.c2
-rw-r--r--net/ipv6/icmp.c4
-rw-r--r--net/ipv6/ip6_input.c2
-rw-r--r--net/ipv6/ip6mr.c24
-rw-r--r--net/ipv6/route.c2
5 files changed, 24 insertions, 10 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index e92ad8455c63..f9afb452249c 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4250,7 +4250,7 @@ static struct addrconf_sysctl_table
4250 .procname = "mc_forwarding", 4250 .procname = "mc_forwarding",
4251 .data = &ipv6_devconf.mc_forwarding, 4251 .data = &ipv6_devconf.mc_forwarding,
4252 .maxlen = sizeof(int), 4252 .maxlen = sizeof(int),
4253 .mode = 0644, 4253 .mode = 0444,
4254 .proc_handler = proc_dointvec, 4254 .proc_handler = proc_dointvec,
4255 }, 4255 },
4256#endif 4256#endif
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 4f433847d95f..36dff8807183 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -443,10 +443,10 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
443 if (xfrm_decode_session_reverse(skb, &fl2, AF_INET6)) 443 if (xfrm_decode_session_reverse(skb, &fl2, AF_INET6))
444 goto relookup_failed; 444 goto relookup_failed;
445 445
446 if (ip6_dst_lookup(sk, &dst2, &fl)) 446 if (ip6_dst_lookup(sk, &dst2, &fl2))
447 goto relookup_failed; 447 goto relookup_failed;
448 448
449 err = xfrm_lookup(net, &dst2, &fl, sk, XFRM_LOOKUP_ICMP); 449 err = xfrm_lookup(net, &dst2, &fl2, sk, XFRM_LOOKUP_ICMP);
450 switch (err) { 450 switch (err) {
451 case 0: 451 case 0:
452 dst_release(dst); 452 dst_release(dst);
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 936f48946e20..f171e8dbac91 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -255,6 +255,7 @@ int ip6_mc_input(struct sk_buff *skb)
255 * IPv6 multicast router mode is now supported ;) 255 * IPv6 multicast router mode is now supported ;)
256 */ 256 */
257 if (dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding && 257 if (dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding &&
258 !(ipv6_addr_type(&hdr->daddr) & IPV6_ADDR_LINKLOCAL) &&
258 likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) { 259 likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) {
259 /* 260 /*
260 * Okay, we try to forward - split and duplicate 261 * Okay, we try to forward - split and duplicate
@@ -316,7 +317,6 @@ int ip6_mc_input(struct sk_buff *skb)
316 } 317 }
317 318
318 if (skb2) { 319 if (skb2) {
319 skb2->dev = skb2->dst->dev;
320 ip6_mr_input(skb2); 320 ip6_mr_input(skb2);
321 } 321 }
322 } 322 }
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 3c51b2d827f4..228be551e9c1 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -48,6 +48,7 @@
48#include <linux/pim.h> 48#include <linux/pim.h>
49#include <net/addrconf.h> 49#include <net/addrconf.h>
50#include <linux/netfilter_ipv6.h> 50#include <linux/netfilter_ipv6.h>
51#include <net/ip6_checksum.h>
51 52
52/* Big lock, protecting vif table, mrt cache and mroute socket state. 53/* Big lock, protecting vif table, mrt cache and mroute socket state.
53 Note that the changes are semaphored via rtnl_lock. 54 Note that the changes are semaphored via rtnl_lock.
@@ -365,7 +366,9 @@ static int pim6_rcv(struct sk_buff *skb)
365 pim = (struct pimreghdr *)skb_transport_header(skb); 366 pim = (struct pimreghdr *)skb_transport_header(skb);
366 if (pim->type != ((PIM_VERSION << 4) | PIM_REGISTER) || 367 if (pim->type != ((PIM_VERSION << 4) | PIM_REGISTER) ||
367 (pim->flags & PIM_NULL_REGISTER) || 368 (pim->flags & PIM_NULL_REGISTER) ||
368 (ip_compute_csum((void *)pim, sizeof(*pim)) != 0 && 369 (csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
370 sizeof(*pim), IPPROTO_PIM,
371 csum_partial((void *)pim, sizeof(*pim), 0)) &&
369 csum_fold(skb_checksum(skb, 0, skb->len, 0)))) 372 csum_fold(skb_checksum(skb, 0, skb->len, 0))))
370 goto drop; 373 goto drop;
371 374
@@ -392,7 +395,7 @@ static int pim6_rcv(struct sk_buff *skb)
392 skb_pull(skb, (u8 *)encap - skb->data); 395 skb_pull(skb, (u8 *)encap - skb->data);
393 skb_reset_network_header(skb); 396 skb_reset_network_header(skb);
394 skb->dev = reg_dev; 397 skb->dev = reg_dev;
395 skb->protocol = htons(ETH_P_IP); 398 skb->protocol = htons(ETH_P_IPV6);
396 skb->ip_summed = 0; 399 skb->ip_summed = 0;
397 skb->pkt_type = PACKET_HOST; 400 skb->pkt_type = PACKET_HOST;
398 dst_release(skb->dst); 401 dst_release(skb->dst);
@@ -481,6 +484,7 @@ static int mif6_delete(struct net *net, int vifi)
481{ 484{
482 struct mif_device *v; 485 struct mif_device *v;
483 struct net_device *dev; 486 struct net_device *dev;
487 struct inet6_dev *in6_dev;
484 if (vifi < 0 || vifi >= net->ipv6.maxvif) 488 if (vifi < 0 || vifi >= net->ipv6.maxvif)
485 return -EADDRNOTAVAIL; 489 return -EADDRNOTAVAIL;
486 490
@@ -513,6 +517,10 @@ static int mif6_delete(struct net *net, int vifi)
513 517
514 dev_set_allmulti(dev, -1); 518 dev_set_allmulti(dev, -1);
515 519
520 in6_dev = __in6_dev_get(dev);
521 if (in6_dev)
522 in6_dev->cnf.mc_forwarding--;
523
516 if (v->flags & MIFF_REGISTER) 524 if (v->flags & MIFF_REGISTER)
517 unregister_netdevice(dev); 525 unregister_netdevice(dev);
518 526
@@ -622,6 +630,7 @@ static int mif6_add(struct net *net, struct mif6ctl *vifc, int mrtsock)
622 int vifi = vifc->mif6c_mifi; 630 int vifi = vifc->mif6c_mifi;
623 struct mif_device *v = &net->ipv6.vif6_table[vifi]; 631 struct mif_device *v = &net->ipv6.vif6_table[vifi];
624 struct net_device *dev; 632 struct net_device *dev;
633 struct inet6_dev *in6_dev;
625 int err; 634 int err;
626 635
627 /* Is vif busy ? */ 636 /* Is vif busy ? */
@@ -662,6 +671,10 @@ static int mif6_add(struct net *net, struct mif6ctl *vifc, int mrtsock)
662 return -EINVAL; 671 return -EINVAL;
663 } 672 }
664 673
674 in6_dev = __in6_dev_get(dev);
675 if (in6_dev)
676 in6_dev->cnf.mc_forwarding++;
677
665 /* 678 /*
666 * Fill in the VIF structures 679 * Fill in the VIF structures
667 */ 680 */
@@ -838,8 +851,6 @@ static int ip6mr_cache_report(struct net *net, struct sk_buff *pkt, mifi_t mifi,
838 851
839 skb->dst = dst_clone(pkt->dst); 852 skb->dst = dst_clone(pkt->dst);
840 skb->ip_summed = CHECKSUM_UNNECESSARY; 853 skb->ip_summed = CHECKSUM_UNNECESSARY;
841
842 skb_pull(skb, sizeof(struct ipv6hdr));
843 } 854 }
844 855
845 if (net->ipv6.mroute6_sk == NULL) { 856 if (net->ipv6.mroute6_sk == NULL) {
@@ -1222,8 +1233,10 @@ static int ip6mr_sk_init(struct sock *sk)
1222 1233
1223 rtnl_lock(); 1234 rtnl_lock();
1224 write_lock_bh(&mrt_lock); 1235 write_lock_bh(&mrt_lock);
1225 if (likely(net->ipv6.mroute6_sk == NULL)) 1236 if (likely(net->ipv6.mroute6_sk == NULL)) {
1226 net->ipv6.mroute6_sk = sk; 1237 net->ipv6.mroute6_sk = sk;
1238 net->ipv6.devconf_all->mc_forwarding++;
1239 }
1227 else 1240 else
1228 err = -EADDRINUSE; 1241 err = -EADDRINUSE;
1229 write_unlock_bh(&mrt_lock); 1242 write_unlock_bh(&mrt_lock);
@@ -1242,6 +1255,7 @@ int ip6mr_sk_done(struct sock *sk)
1242 if (sk == net->ipv6.mroute6_sk) { 1255 if (sk == net->ipv6.mroute6_sk) {
1243 write_lock_bh(&mrt_lock); 1256 write_lock_bh(&mrt_lock);
1244 net->ipv6.mroute6_sk = NULL; 1257 net->ipv6.mroute6_sk = NULL;
1258 net->ipv6.devconf_all->mc_forwarding--;
1245 write_unlock_bh(&mrt_lock); 1259 write_unlock_bh(&mrt_lock);
1246 1260
1247 mroute_clean_tables(net); 1261 mroute_clean_tables(net);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index c4a59824ac2c..9c574235c905 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -794,7 +794,7 @@ void ip6_route_input(struct sk_buff *skb)
794 .proto = iph->nexthdr, 794 .proto = iph->nexthdr,
795 }; 795 };
796 796
797 if (rt6_need_strict(&iph->daddr)) 797 if (rt6_need_strict(&iph->daddr) && skb->dev->type != ARPHRD_PIMREG)
798 flags |= RT6_LOOKUP_F_IFACE; 798 flags |= RT6_LOOKUP_F_IFACE;
799 799
800 skb->dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input); 800 skb->dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input);