#define        IN_LOOPBACK(a)          ((((long int) (a)) & 0xff000000) == 0x7f000000)
 
 /* Defines for Multicast INADDR */
-#define INADDR_UNSPEC_GROUP    0xe0000000U     /* 224.0.0.0   */
-#define INADDR_ALLHOSTS_GROUP  0xe0000001U     /* 224.0.0.1   */
-#define INADDR_ALLRTRS_GROUP    0xe0000002U    /* 224.0.0.2 */
-#define INADDR_MAX_LOCAL_GROUP  0xe00000ffU    /* 224.0.0.255 */
+#define INADDR_UNSPEC_GROUP            0xe0000000U     /* 224.0.0.0   */
+#define INADDR_ALLHOSTS_GROUP          0xe0000001U     /* 224.0.0.1   */
+#define INADDR_ALLRTRS_GROUP           0xe0000002U     /* 224.0.0.2 */
+#define INADDR_ALLSNOOPERS_GROUP       0xe000006aU     /* 224.0.0.106 */
+#define INADDR_MAX_LOCAL_GROUP         0xe00000ffU     /* 224.0.0.255 */
 #endif
 
 /* <asm/byteorder.h> contains the htonl type stuff.. */
 
        INIT_HLIST_HEAD(&br->mdb_list);
 }
 
+static void br_ip4_multicast_join_snoopers(struct net_bridge *br)
+{
+       struct in_device *in_dev = in_dev_get(br->dev);
+
+       if (!in_dev)
+               return;
+
+       ip_mc_inc_group(in_dev, htonl(INADDR_ALLSNOOPERS_GROUP));
+       in_dev_put(in_dev);
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+static void br_ip6_multicast_join_snoopers(struct net_bridge *br)
+{
+       struct in6_addr addr;
+
+       ipv6_addr_set(&addr, htonl(0xff020000), 0, 0, htonl(0x6a));
+       ipv6_dev_mc_inc(br->dev, &addr);
+}
+#else
+static inline void br_ip6_multicast_join_snoopers(struct net_bridge *br)
+{
+}
+#endif
+
+static void br_multicast_join_snoopers(struct net_bridge *br)
+{
+       br_ip4_multicast_join_snoopers(br);
+       br_ip6_multicast_join_snoopers(br);
+}
+
+static void br_ip4_multicast_leave_snoopers(struct net_bridge *br)
+{
+       struct in_device *in_dev = in_dev_get(br->dev);
+
+       if (WARN_ON(!in_dev))
+               return;
+
+       ip_mc_dec_group(in_dev, htonl(INADDR_ALLSNOOPERS_GROUP));
+       in_dev_put(in_dev);
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+static void br_ip6_multicast_leave_snoopers(struct net_bridge *br)
+{
+       struct in6_addr addr;
+
+       ipv6_addr_set(&addr, htonl(0xff020000), 0, 0, htonl(0x6a));
+       ipv6_dev_mc_dec(br->dev, &addr);
+}
+#else
+static inline void br_ip6_multicast_leave_snoopers(struct net_bridge *br)
+{
+}
+#endif
+
+static void br_multicast_leave_snoopers(struct net_bridge *br)
+{
+       br_ip4_multicast_leave_snoopers(br);
+       br_ip6_multicast_leave_snoopers(br);
+}
+
 static void __br_multicast_open(struct net_bridge *br,
                                struct bridge_mcast_own_query *query)
 {
 
 void br_multicast_open(struct net_bridge *br)
 {
+       if (br_opt_get(br, BROPT_MULTICAST_ENABLED))
+               br_multicast_join_snoopers(br);
+
        __br_multicast_open(br, &br->ip4_own_query);
 #if IS_ENABLED(CONFIG_IPV6)
        __br_multicast_open(br, &br->ip6_own_query);
        del_timer_sync(&br->ip6_other_query.timer);
        del_timer_sync(&br->ip6_own_query.timer);
 #endif
+
+       if (br_opt_get(br, BROPT_MULTICAST_ENABLED))
+               br_multicast_leave_snoopers(br);
 }
 
 void br_multicast_dev_del(struct net_bridge *br)
 
        br_mc_disabled_update(br->dev, val);
        br_opt_toggle(br, BROPT_MULTICAST_ENABLED, !!val);
-       if (!br_opt_get(br, BROPT_MULTICAST_ENABLED))
+       if (!br_opt_get(br, BROPT_MULTICAST_ENABLED)) {
+               br_multicast_leave_snoopers(br);
                goto unlock;
+       }
 
        if (!netif_running(br->dev))
                goto unlock;