diff options
Diffstat (limited to 'net/bridge/br_multicast.c')
-rw-r--r-- | net/bridge/br_multicast.c | 42 |
1 files changed, 21 insertions, 21 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index f701a21acb34..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 | } |
@@ -232,8 +231,7 @@ static void br_multicast_group_expired(unsigned long data) | |||
232 | if (!netif_running(br->dev) || timer_pending(&mp->timer)) | 231 | if (!netif_running(br->dev) || timer_pending(&mp->timer)) |
233 | goto out; | 232 | goto out; |
234 | 233 | ||
235 | if (!hlist_unhashed(&mp->mglist)) | 234 | mp->mglist = false; |
236 | hlist_del_init(&mp->mglist); | ||
237 | 235 | ||
238 | if (mp->ports) | 236 | if (mp->ports) |
239 | goto out; | 237 | goto out; |
@@ -276,7 +274,7 @@ static void br_multicast_del_pg(struct net_bridge *br, | |||
276 | del_timer(&p->query_timer); | 274 | del_timer(&p->query_timer); |
277 | call_rcu_bh(&p->rcu, br_multicast_free_pg); | 275 | call_rcu_bh(&p->rcu, br_multicast_free_pg); |
278 | 276 | ||
279 | if (!mp->ports && hlist_unhashed(&mp->mglist) && | 277 | if (!mp->ports && !mp->mglist && |
280 | netif_running(br->dev)) | 278 | netif_running(br->dev)) |
281 | mod_timer(&mp->timer, jiffies); | 279 | mod_timer(&mp->timer, jiffies); |
282 | 280 | ||
@@ -436,7 +434,6 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, | |||
436 | eth = eth_hdr(skb); | 434 | eth = eth_hdr(skb); |
437 | 435 | ||
438 | memcpy(eth->h_source, br->dev->dev_addr, 6); | 436 | memcpy(eth->h_source, br->dev->dev_addr, 6); |
439 | ipv6_eth_mc_map(group, eth->h_dest); | ||
440 | eth->h_proto = htons(ETH_P_IPV6); | 437 | eth->h_proto = htons(ETH_P_IPV6); |
441 | skb_put(skb, sizeof(*eth)); | 438 | skb_put(skb, sizeof(*eth)); |
442 | 439 | ||
@@ -448,8 +445,10 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, | |||
448 | ip6h->payload_len = htons(8 + sizeof(*mldq)); | 445 | ip6h->payload_len = htons(8 + sizeof(*mldq)); |
449 | ip6h->nexthdr = IPPROTO_HOPOPTS; | 446 | ip6h->nexthdr = IPPROTO_HOPOPTS; |
450 | ip6h->hop_limit = 1; | 447 | ip6h->hop_limit = 1; |
451 | 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); | ||
452 | 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); | ||
453 | 452 | ||
454 | hopopt = (u8 *)(ip6h + 1); | 453 | hopopt = (u8 *)(ip6h + 1); |
455 | hopopt[0] = IPPROTO_ICMPV6; /* next hdr */ | 454 | hopopt[0] = IPPROTO_ICMPV6; /* next hdr */ |
@@ -528,7 +527,7 @@ static void br_multicast_group_query_expired(unsigned long data) | |||
528 | struct net_bridge *br = mp->br; | 527 | struct net_bridge *br = mp->br; |
529 | 528 | ||
530 | spin_lock(&br->multicast_lock); | 529 | spin_lock(&br->multicast_lock); |
531 | if (!netif_running(br->dev) || hlist_unhashed(&mp->mglist) || | 530 | if (!netif_running(br->dev) || !mp->mglist || |
532 | mp->queries_sent >= br->multicast_last_member_count) | 531 | mp->queries_sent >= br->multicast_last_member_count) |
533 | goto out; | 532 | goto out; |
534 | 533 | ||
@@ -719,7 +718,7 @@ static int br_multicast_add_group(struct net_bridge *br, | |||
719 | goto err; | 718 | goto err; |
720 | 719 | ||
721 | if (!port) { | 720 | if (!port) { |
722 | hlist_add_head(&mp->mglist, &br->mglist); | 721 | mp->mglist = true; |
723 | mod_timer(&mp->timer, now + br->multicast_membership_interval); | 722 | mod_timer(&mp->timer, now + br->multicast_membership_interval); |
724 | goto out; | 723 | goto out; |
725 | } | 724 | } |
@@ -781,11 +780,11 @@ static int br_ip6_multicast_add_group(struct net_bridge *br, | |||
781 | { | 780 | { |
782 | struct br_ip br_group; | 781 | struct br_ip br_group; |
783 | 782 | ||
784 | if (ipv6_is_local_multicast(group)) | 783 | if (!ipv6_is_transient_multicast(group)) |
785 | return 0; | 784 | return 0; |
786 | 785 | ||
787 | ipv6_addr_copy(&br_group.u.ip6, group); | 786 | ipv6_addr_copy(&br_group.u.ip6, group); |
788 | br_group.proto = htons(ETH_P_IP); | 787 | br_group.proto = htons(ETH_P_IPV6); |
789 | 788 | ||
790 | return br_multicast_add_group(br, port, &br_group); | 789 | return br_multicast_add_group(br, port, &br_group); |
791 | } | 790 | } |
@@ -1014,18 +1013,19 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br, | |||
1014 | 1013 | ||
1015 | nsrcs = skb_header_pointer(skb, | 1014 | nsrcs = skb_header_pointer(skb, |
1016 | len + offsetof(struct mld2_grec, | 1015 | len + offsetof(struct mld2_grec, |
1017 | grec_mca), | 1016 | grec_nsrcs), |
1018 | sizeof(_nsrcs), &_nsrcs); | 1017 | sizeof(_nsrcs), &_nsrcs); |
1019 | if (!nsrcs) | 1018 | if (!nsrcs) |
1020 | return -EINVAL; | 1019 | return -EINVAL; |
1021 | 1020 | ||
1022 | if (!pskb_may_pull(skb, | 1021 | if (!pskb_may_pull(skb, |
1023 | len + sizeof(*grec) + | 1022 | len + sizeof(*grec) + |
1024 | sizeof(struct in6_addr) * (*nsrcs))) | 1023 | sizeof(struct in6_addr) * ntohs(*nsrcs))) |
1025 | return -EINVAL; | 1024 | return -EINVAL; |
1026 | 1025 | ||
1027 | grec = (struct mld2_grec *)(skb->data + len); | 1026 | grec = (struct mld2_grec *)(skb->data + len); |
1028 | len += sizeof(*grec) + sizeof(struct in6_addr) * (*nsrcs); | 1027 | len += sizeof(*grec) + |
1028 | sizeof(struct in6_addr) * ntohs(*nsrcs); | ||
1029 | 1029 | ||
1030 | /* We treat these as MLDv1 reports for now. */ | 1030 | /* We treat these as MLDv1 reports for now. */ |
1031 | switch (grec->grec_type) { | 1031 | switch (grec->grec_type) { |
@@ -1165,7 +1165,7 @@ static int br_ip4_multicast_query(struct net_bridge *br, | |||
1165 | 1165 | ||
1166 | max_delay *= br->multicast_last_member_count; | 1166 | max_delay *= br->multicast_last_member_count; |
1167 | 1167 | ||
1168 | if (!hlist_unhashed(&mp->mglist) && | 1168 | if (mp->mglist && |
1169 | (timer_pending(&mp->timer) ? | 1169 | (timer_pending(&mp->timer) ? |
1170 | time_after(mp->timer.expires, now + max_delay) : | 1170 | time_after(mp->timer.expires, now + max_delay) : |
1171 | try_to_del_timer_sync(&mp->timer) >= 0)) | 1171 | try_to_del_timer_sync(&mp->timer) >= 0)) |
@@ -1177,7 +1177,7 @@ static int br_ip4_multicast_query(struct net_bridge *br, | |||
1177 | if (timer_pending(&p->timer) ? | 1177 | if (timer_pending(&p->timer) ? |
1178 | time_after(p->timer.expires, now + max_delay) : | 1178 | time_after(p->timer.expires, now + max_delay) : |
1179 | try_to_del_timer_sync(&p->timer) >= 0) | 1179 | try_to_del_timer_sync(&p->timer) >= 0) |
1180 | mod_timer(&mp->timer, now + max_delay); | 1180 | mod_timer(&p->timer, now + max_delay); |
1181 | } | 1181 | } |
1182 | 1182 | ||
1183 | out: | 1183 | out: |
@@ -1236,7 +1236,7 @@ static int br_ip6_multicast_query(struct net_bridge *br, | |||
1236 | goto out; | 1236 | goto out; |
1237 | 1237 | ||
1238 | max_delay *= br->multicast_last_member_count; | 1238 | max_delay *= br->multicast_last_member_count; |
1239 | if (!hlist_unhashed(&mp->mglist) && | 1239 | if (mp->mglist && |
1240 | (timer_pending(&mp->timer) ? | 1240 | (timer_pending(&mp->timer) ? |
1241 | time_after(mp->timer.expires, now + max_delay) : | 1241 | time_after(mp->timer.expires, now + max_delay) : |
1242 | try_to_del_timer_sync(&mp->timer) >= 0)) | 1242 | try_to_del_timer_sync(&mp->timer) >= 0)) |
@@ -1248,7 +1248,7 @@ static int br_ip6_multicast_query(struct net_bridge *br, | |||
1248 | if (timer_pending(&p->timer) ? | 1248 | if (timer_pending(&p->timer) ? |
1249 | time_after(p->timer.expires, now + max_delay) : | 1249 | time_after(p->timer.expires, now + max_delay) : |
1250 | try_to_del_timer_sync(&p->timer) >= 0) | 1250 | try_to_del_timer_sync(&p->timer) >= 0) |
1251 | mod_timer(&mp->timer, now + max_delay); | 1251 | mod_timer(&p->timer, now + max_delay); |
1252 | } | 1252 | } |
1253 | 1253 | ||
1254 | out: | 1254 | out: |
@@ -1283,7 +1283,7 @@ static void br_multicast_leave_group(struct net_bridge *br, | |||
1283 | br->multicast_last_member_interval; | 1283 | br->multicast_last_member_interval; |
1284 | 1284 | ||
1285 | if (!port) { | 1285 | if (!port) { |
1286 | if (!hlist_unhashed(&mp->mglist) && | 1286 | if (mp->mglist && |
1287 | (timer_pending(&mp->timer) ? | 1287 | (timer_pending(&mp->timer) ? |
1288 | time_after(mp->timer.expires, time) : | 1288 | time_after(mp->timer.expires, time) : |
1289 | try_to_del_timer_sync(&mp->timer) >= 0)) { | 1289 | try_to_del_timer_sync(&mp->timer) >= 0)) { |
@@ -1341,7 +1341,7 @@ static void br_ip6_multicast_leave_group(struct net_bridge *br, | |||
1341 | { | 1341 | { |
1342 | struct br_ip br_group; | 1342 | struct br_ip br_group; |
1343 | 1343 | ||
1344 | if (ipv6_is_local_multicast(group)) | 1344 | if (!ipv6_is_transient_multicast(group)) |
1345 | return; | 1345 | return; |
1346 | 1346 | ||
1347 | ipv6_addr_copy(&br_group.u.ip6, group); | 1347 | ipv6_addr_copy(&br_group.u.ip6, group); |