aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_multicast.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge/br_multicast.c')
-rw-r--r--net/bridge/br_multicast.c33
1 files changed, 30 insertions, 3 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index ef66365b7354..93067ecdb9a2 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1127,9 +1127,10 @@ static void br_multicast_query_received(struct net_bridge *br,
1127 struct net_bridge_port *port, 1127 struct net_bridge_port *port,
1128 struct bridge_mcast_querier *querier, 1128 struct bridge_mcast_querier *querier,
1129 int saddr, 1129 int saddr,
1130 bool is_general_query,
1130 unsigned long max_delay) 1131 unsigned long max_delay)
1131{ 1132{
1132 if (saddr) 1133 if (saddr && is_general_query)
1133 br_multicast_update_querier_timer(br, querier, max_delay); 1134 br_multicast_update_querier_timer(br, querier, max_delay);
1134 else if (timer_pending(&querier->timer)) 1135 else if (timer_pending(&querier->timer))
1135 return; 1136 return;
@@ -1181,8 +1182,16 @@ static int br_ip4_multicast_query(struct net_bridge *br,
1181 IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1; 1182 IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1;
1182 } 1183 }
1183 1184
1185 /* RFC2236+RFC3376 (IGMPv2+IGMPv3) require the multicast link layer
1186 * all-systems destination addresses (224.0.0.1) for general queries
1187 */
1188 if (!group && iph->daddr != htonl(INADDR_ALLHOSTS_GROUP)) {
1189 err = -EINVAL;
1190 goto out;
1191 }
1192
1184 br_multicast_query_received(br, port, &br->ip4_querier, !!iph->saddr, 1193 br_multicast_query_received(br, port, &br->ip4_querier, !!iph->saddr,
1185 max_delay); 1194 !group, max_delay);
1186 1195
1187 if (!group) 1196 if (!group)
1188 goto out; 1197 goto out;
@@ -1228,6 +1237,7 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1228 unsigned long max_delay; 1237 unsigned long max_delay;
1229 unsigned long now = jiffies; 1238 unsigned long now = jiffies;
1230 const struct in6_addr *group = NULL; 1239 const struct in6_addr *group = NULL;
1240 bool is_general_query;
1231 int err = 0; 1241 int err = 0;
1232 1242
1233 spin_lock(&br->multicast_lock); 1243 spin_lock(&br->multicast_lock);
@@ -1235,6 +1245,12 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1235 (port && port->state == BR_STATE_DISABLED)) 1245 (port && port->state == BR_STATE_DISABLED))
1236 goto out; 1246 goto out;
1237 1247
1248 /* RFC2710+RFC3810 (MLDv1+MLDv2) require link-local source addresses */
1249 if (!(ipv6_addr_type(&ip6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
1250 err = -EINVAL;
1251 goto out;
1252 }
1253
1238 if (skb->len == sizeof(*mld)) { 1254 if (skb->len == sizeof(*mld)) {
1239 if (!pskb_may_pull(skb, sizeof(*mld))) { 1255 if (!pskb_may_pull(skb, sizeof(*mld))) {
1240 err = -EINVAL; 1256 err = -EINVAL;
@@ -1256,8 +1272,19 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1256 max_delay = max(msecs_to_jiffies(mldv2_mrc(mld2q)), 1UL); 1272 max_delay = max(msecs_to_jiffies(mldv2_mrc(mld2q)), 1UL);
1257 } 1273 }
1258 1274
1275 is_general_query = group && ipv6_addr_any(group);
1276
1277 /* RFC2710+RFC3810 (MLDv1+MLDv2) require the multicast link layer
1278 * all-nodes destination address (ff02::1) for general queries
1279 */
1280 if (is_general_query && !ipv6_addr_is_ll_all_nodes(&ip6h->daddr)) {
1281 err = -EINVAL;
1282 goto out;
1283 }
1284
1259 br_multicast_query_received(br, port, &br->ip6_querier, 1285 br_multicast_query_received(br, port, &br->ip6_querier,
1260 !ipv6_addr_any(&ip6h->saddr), max_delay); 1286 !ipv6_addr_any(&ip6h->saddr),
1287 is_general_query, max_delay);
1261 1288
1262 if (!group) 1289 if (!group)
1263 goto out; 1290 goto out;