OSDN Git Service

r8152: allow userland to disable multicast
authorSven van Ashbrook <svenva@chromium.org>
Tue, 30 Aug 2022 04:59:39 +0000 (04:59 +0000)
committerJakub Kicinski <kuba@kernel.org>
Wed, 31 Aug 2022 21:55:50 +0000 (14:55 -0700)
The rtl8152 driver does not disable multicasting when userspace asks
it to. For example:
 $ ifconfig eth0 -multicast -allmulti
 $ tcpdump -p -i eth0  # will still capture multicast frames

Fix by clearing the device multicast filter table when multicast and
allmulti are both unset.

Tested as follows:
- Set multicast on eth0 network interface
- verify that multicast packets are coming in:
  $ tcpdump -p -i eth0
- Clear multicast and allmulti on eth0 network interface
- verify that no more multicast packets are coming in:
  $ tcpdump -p -i eth0

Signed-off-by: Sven van Ashbrook <svenva@chromium.org>
Acked-by: Hayes Wang <hayeswang@realtek.com>
Link: https://lore.kernel.org/r/20220830045923.net-next.v1.1.I4fee0ac057083d4f848caf0fa3a9fd466fc374a0@changeid
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/usb/r8152.c

index 45dcc3f..dca6f71 100644 (file)
@@ -2727,22 +2727,26 @@ static void _rtl8152_set_rx_mode(struct net_device *netdev)
                ocp_data |= RCR_AM | RCR_AAP;
                mc_filter[1] = 0xffffffff;
                mc_filter[0] = 0xffffffff;
-       } else if ((netdev_mc_count(netdev) > multicast_filter_limit) ||
-                  (netdev->flags & IFF_ALLMULTI)) {
+       } else if ((netdev->flags & IFF_MULTICAST &&
+                               netdev_mc_count(netdev) > multicast_filter_limit) ||
+                          (netdev->flags & IFF_ALLMULTI)) {
                /* Too many to filter perfectly -- accept all multicasts. */
                ocp_data |= RCR_AM;
                mc_filter[1] = 0xffffffff;
                mc_filter[0] = 0xffffffff;
        } else {
-               struct netdev_hw_addr *ha;
-
                mc_filter[1] = 0;
                mc_filter[0] = 0;
-               netdev_for_each_mc_addr(ha, netdev) {
-                       int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
 
-                       mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
-                       ocp_data |= RCR_AM;
+               if (netdev->flags & IFF_MULTICAST) {
+                       struct netdev_hw_addr *ha;
+
+                       netdev_for_each_mc_addr(ha, netdev) {
+                               int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
+
+                               mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
+                               ocp_data |= RCR_AM;
+                       }
                }
        }