diff options
author | David S. Miller <davem@davemloft.net> | 2011-03-04 00:27:42 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-03-04 00:27:42 -0500 |
commit | 0a0e9ae1bd788bc19adc4d4ae08c98b233697402 (patch) | |
tree | 13825eeb5bbeae27d66e95f12168eff4b60701ab /net/bridge | |
parent | 01a16b21d6adf992aa863186c3c4e561a57c1714 (diff) | |
parent | b65a0e0c84cf489bfa00d6aa6c48abc5a237100f (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts:
drivers/net/bnx2x/bnx2x.h
Diffstat (limited to 'net/bridge')
-rw-r--r-- | net/bridge/br_multicast.c | 23 |
1 files changed, 12 insertions, 11 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 09d5c0987925..030a002ff8ee 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
@@ -37,10 +37,9 @@ | |||
37 | rcu_dereference_protected(X, lockdep_is_held(&br->multicast_lock)) | 37 | rcu_dereference_protected(X, lockdep_is_held(&br->multicast_lock)) |
38 | 38 | ||
39 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 39 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
40 | static inline int ipv6_is_local_multicast(const struct in6_addr *addr) | 40 | static inline int ipv6_is_transient_multicast(const struct in6_addr *addr) |
41 | { | 41 | { |
42 | if (ipv6_addr_is_multicast(addr) && | 42 | if (ipv6_addr_is_multicast(addr) && IPV6_ADDR_MC_FLAG_TRANSIENT(addr)) |
43 | IPV6_ADDR_MC_SCOPE(addr) <= IPV6_ADDR_SCOPE_LINKLOCAL) | ||
44 | return 1; | 43 | return 1; |
45 | return 0; | 44 | return 0; |
46 | } | 45 | } |
@@ -435,7 +434,6 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, | |||
435 | eth = eth_hdr(skb); | 434 | eth = eth_hdr(skb); |
436 | 435 | ||
437 | memcpy(eth->h_source, br->dev->dev_addr, 6); | 436 | memcpy(eth->h_source, br->dev->dev_addr, 6); |
438 | ipv6_eth_mc_map(group, eth->h_dest); | ||
439 | eth->h_proto = htons(ETH_P_IPV6); | 437 | eth->h_proto = htons(ETH_P_IPV6); |
440 | skb_put(skb, sizeof(*eth)); | 438 | skb_put(skb, sizeof(*eth)); |
441 | 439 | ||
@@ -447,8 +445,10 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, | |||
447 | ip6h->payload_len = htons(8 + sizeof(*mldq)); | 445 | ip6h->payload_len = htons(8 + sizeof(*mldq)); |
448 | ip6h->nexthdr = IPPROTO_HOPOPTS; | 446 | ip6h->nexthdr = IPPROTO_HOPOPTS; |
449 | ip6h->hop_limit = 1; | 447 | ip6h->hop_limit = 1; |
450 | ipv6_addr_set(&ip6h->saddr, 0, 0, 0, 0); | 448 | ipv6_dev_get_saddr(dev_net(br->dev), br->dev, &ip6h->daddr, 0, |
449 | &ip6h->saddr); | ||
451 | ipv6_addr_set(&ip6h->daddr, htonl(0xff020000), 0, 0, htonl(1)); | 450 | ipv6_addr_set(&ip6h->daddr, htonl(0xff020000), 0, 0, htonl(1)); |
451 | ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); | ||
452 | 452 | ||
453 | hopopt = (u8 *)(ip6h + 1); | 453 | hopopt = (u8 *)(ip6h + 1); |
454 | hopopt[0] = IPPROTO_ICMPV6; /* next hdr */ | 454 | hopopt[0] = IPPROTO_ICMPV6; /* next hdr */ |
@@ -780,11 +780,11 @@ static int br_ip6_multicast_add_group(struct net_bridge *br, | |||
780 | { | 780 | { |
781 | struct br_ip br_group; | 781 | struct br_ip br_group; |
782 | 782 | ||
783 | if (ipv6_is_local_multicast(group)) | 783 | if (!ipv6_is_transient_multicast(group)) |
784 | return 0; | 784 | return 0; |
785 | 785 | ||
786 | ipv6_addr_copy(&br_group.u.ip6, group); | 786 | ipv6_addr_copy(&br_group.u.ip6, group); |
787 | br_group.proto = htons(ETH_P_IP); | 787 | br_group.proto = htons(ETH_P_IPV6); |
788 | 788 | ||
789 | return br_multicast_add_group(br, port, &br_group); | 789 | return br_multicast_add_group(br, port, &br_group); |
790 | } | 790 | } |
@@ -1013,18 +1013,19 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br, | |||
1013 | 1013 | ||
1014 | nsrcs = skb_header_pointer(skb, | 1014 | nsrcs = skb_header_pointer(skb, |
1015 | len + offsetof(struct mld2_grec, | 1015 | len + offsetof(struct mld2_grec, |
1016 | grec_mca), | 1016 | grec_nsrcs), |
1017 | sizeof(_nsrcs), &_nsrcs); | 1017 | sizeof(_nsrcs), &_nsrcs); |
1018 | if (!nsrcs) | 1018 | if (!nsrcs) |
1019 | return -EINVAL; | 1019 | return -EINVAL; |
1020 | 1020 | ||
1021 | if (!pskb_may_pull(skb, | 1021 | if (!pskb_may_pull(skb, |
1022 | len + sizeof(*grec) + | 1022 | len + sizeof(*grec) + |
1023 | sizeof(struct in6_addr) * (*nsrcs))) | 1023 | sizeof(struct in6_addr) * ntohs(*nsrcs))) |
1024 | return -EINVAL; | 1024 | return -EINVAL; |
1025 | 1025 | ||
1026 | grec = (struct mld2_grec *)(skb->data + len); | 1026 | grec = (struct mld2_grec *)(skb->data + len); |
1027 | len += sizeof(*grec) + sizeof(struct in6_addr) * (*nsrcs); | 1027 | len += sizeof(*grec) + |
1028 | sizeof(struct in6_addr) * ntohs(*nsrcs); | ||
1028 | 1029 | ||
1029 | /* We treat these as MLDv1 reports for now. */ | 1030 | /* We treat these as MLDv1 reports for now. */ |
1030 | switch (grec->grec_type) { | 1031 | switch (grec->grec_type) { |
@@ -1340,7 +1341,7 @@ static void br_ip6_multicast_leave_group(struct net_bridge *br, | |||
1340 | { | 1341 | { |
1341 | struct br_ip br_group; | 1342 | struct br_ip br_group; |
1342 | 1343 | ||
1343 | if (ipv6_is_local_multicast(group)) | 1344 | if (!ipv6_is_transient_multicast(group)) |
1344 | return; | 1345 | return; |
1345 | 1346 | ||
1346 | ipv6_addr_copy(&br_group.u.ip6, group); | 1347 | ipv6_addr_copy(&br_group.u.ip6, group); |