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); |
