|
@@ -1181,6 +1181,14 @@ static int br_ip4_multicast_query(struct net_bridge *br,
|
|
IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1;
|
|
IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /* RFC2236+RFC3376 (IGMPv2+IGMPv3) require the multicast link layer
|
|
|
|
+ * all-systems destination addresses (224.0.0.1) for general queries
|
|
|
|
+ */
|
|
|
|
+ if (!group && iph->daddr != htonl(INADDR_ALLHOSTS_GROUP)) {
|
|
|
|
+ err = -EINVAL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
br_multicast_query_received(br, port, &br->ip4_querier, !!iph->saddr,
|
|
br_multicast_query_received(br, port, &br->ip4_querier, !!iph->saddr,
|
|
max_delay);
|
|
max_delay);
|
|
|
|
|
|
@@ -1228,6 +1236,7 @@ static int br_ip6_multicast_query(struct net_bridge *br,
|
|
unsigned long max_delay;
|
|
unsigned long max_delay;
|
|
unsigned long now = jiffies;
|
|
unsigned long now = jiffies;
|
|
const struct in6_addr *group = NULL;
|
|
const struct in6_addr *group = NULL;
|
|
|
|
+ bool is_general_query;
|
|
int err = 0;
|
|
int err = 0;
|
|
|
|
|
|
spin_lock(&br->multicast_lock);
|
|
spin_lock(&br->multicast_lock);
|
|
@@ -1262,6 +1271,16 @@ static int br_ip6_multicast_query(struct net_bridge *br,
|
|
max_delay = max(msecs_to_jiffies(mldv2_mrc(mld2q)), 1UL);
|
|
max_delay = max(msecs_to_jiffies(mldv2_mrc(mld2q)), 1UL);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ is_general_query = group && ipv6_addr_any(group);
|
|
|
|
+
|
|
|
|
+ /* RFC2710+RFC3810 (MLDv1+MLDv2) require the multicast link layer
|
|
|
|
+ * all-nodes destination address (ff02::1) for general queries
|
|
|
|
+ */
|
|
|
|
+ if (is_general_query && !ipv6_addr_is_ll_all_nodes(&ip6h->daddr)) {
|
|
|
|
+ err = -EINVAL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
br_multicast_query_received(br, port, &br->ip6_querier,
|
|
br_multicast_query_received(br, port, &br->ip6_querier,
|
|
!ipv6_addr_any(&ip6h->saddr), max_delay);
|
|
!ipv6_addr_any(&ip6h->saddr), max_delay);
|
|
|
|
|