|
@@ -4988,7 +4988,7 @@ static void dev_change_rx_flags(struct net_device *dev, int flags)
|
|
|
ops->ndo_change_rx_flags(dev, flags);
|
|
|
}
|
|
|
|
|
|
-static int __dev_set_promiscuity(struct net_device *dev, int inc)
|
|
|
+static int __dev_set_promiscuity(struct net_device *dev, int inc, bool notify)
|
|
|
{
|
|
|
unsigned int old_flags = dev->flags;
|
|
|
kuid_t uid;
|
|
@@ -5031,6 +5031,8 @@ static int __dev_set_promiscuity(struct net_device *dev, int inc)
|
|
|
|
|
|
dev_change_rx_flags(dev, IFF_PROMISC);
|
|
|
}
|
|
|
+ if (notify)
|
|
|
+ __dev_notify_flags(dev, old_flags, IFF_PROMISC);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -5050,7 +5052,7 @@ int dev_set_promiscuity(struct net_device *dev, int inc)
|
|
|
unsigned int old_flags = dev->flags;
|
|
|
int err;
|
|
|
|
|
|
- err = __dev_set_promiscuity(dev, inc);
|
|
|
+ err = __dev_set_promiscuity(dev, inc, true);
|
|
|
if (err < 0)
|
|
|
return err;
|
|
|
if (dev->flags != old_flags)
|
|
@@ -5059,22 +5061,9 @@ int dev_set_promiscuity(struct net_device *dev, int inc)
|
|
|
}
|
|
|
EXPORT_SYMBOL(dev_set_promiscuity);
|
|
|
|
|
|
-/**
|
|
|
- * dev_set_allmulti - update allmulti count on a device
|
|
|
- * @dev: device
|
|
|
- * @inc: modifier
|
|
|
- *
|
|
|
- * Add or remove reception of all multicast frames to a device. While the
|
|
|
- * count in the device remains above zero the interface remains listening
|
|
|
- * to all interfaces. Once it hits zero the device reverts back to normal
|
|
|
- * filtering operation. A negative @inc value is used to drop the counter
|
|
|
- * when releasing a resource needing all multicasts.
|
|
|
- * Return 0 if successful or a negative errno code on error.
|
|
|
- */
|
|
|
-
|
|
|
-int dev_set_allmulti(struct net_device *dev, int inc)
|
|
|
+static int __dev_set_allmulti(struct net_device *dev, int inc, bool notify)
|
|
|
{
|
|
|
- unsigned int old_flags = dev->flags;
|
|
|
+ unsigned int old_flags = dev->flags, old_gflags = dev->gflags;
|
|
|
|
|
|
ASSERT_RTNL();
|
|
|
|
|
@@ -5097,9 +5086,30 @@ int dev_set_allmulti(struct net_device *dev, int inc)
|
|
|
if (dev->flags ^ old_flags) {
|
|
|
dev_change_rx_flags(dev, IFF_ALLMULTI);
|
|
|
dev_set_rx_mode(dev);
|
|
|
+ if (notify)
|
|
|
+ __dev_notify_flags(dev, old_flags,
|
|
|
+ dev->gflags ^ old_gflags);
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dev_set_allmulti - update allmulti count on a device
|
|
|
+ * @dev: device
|
|
|
+ * @inc: modifier
|
|
|
+ *
|
|
|
+ * Add or remove reception of all multicast frames to a device. While the
|
|
|
+ * count in the device remains above zero the interface remains listening
|
|
|
+ * to all interfaces. Once it hits zero the device reverts back to normal
|
|
|
+ * filtering operation. A negative @inc value is used to drop the counter
|
|
|
+ * when releasing a resource needing all multicasts.
|
|
|
+ * Return 0 if successful or a negative errno code on error.
|
|
|
+ */
|
|
|
+
|
|
|
+int dev_set_allmulti(struct net_device *dev, int inc)
|
|
|
+{
|
|
|
+ return __dev_set_allmulti(dev, inc, true);
|
|
|
+}
|
|
|
EXPORT_SYMBOL(dev_set_allmulti);
|
|
|
|
|
|
/*
|
|
@@ -5124,10 +5134,10 @@ void __dev_set_rx_mode(struct net_device *dev)
|
|
|
* therefore calling __dev_set_promiscuity here is safe.
|
|
|
*/
|
|
|
if (!netdev_uc_empty(dev) && !dev->uc_promisc) {
|
|
|
- __dev_set_promiscuity(dev, 1);
|
|
|
+ __dev_set_promiscuity(dev, 1, false);
|
|
|
dev->uc_promisc = true;
|
|
|
} else if (netdev_uc_empty(dev) && dev->uc_promisc) {
|
|
|
- __dev_set_promiscuity(dev, -1);
|
|
|
+ __dev_set_promiscuity(dev, -1, false);
|
|
|
dev->uc_promisc = false;
|
|
|
}
|
|
|
}
|
|
@@ -5216,9 +5226,13 @@ int __dev_change_flags(struct net_device *dev, unsigned int flags)
|
|
|
|
|
|
if ((flags ^ dev->gflags) & IFF_PROMISC) {
|
|
|
int inc = (flags & IFF_PROMISC) ? 1 : -1;
|
|
|
+ unsigned int old_flags = dev->flags;
|
|
|
|
|
|
dev->gflags ^= IFF_PROMISC;
|
|
|
- dev_set_promiscuity(dev, inc);
|
|
|
+
|
|
|
+ if (__dev_set_promiscuity(dev, inc, false) >= 0)
|
|
|
+ if (dev->flags != old_flags)
|
|
|
+ dev_set_rx_mode(dev);
|
|
|
}
|
|
|
|
|
|
/* NOTE: order of synchronization of IFF_PROMISC and IFF_ALLMULTI
|
|
@@ -5229,7 +5243,7 @@ int __dev_change_flags(struct net_device *dev, unsigned int flags)
|
|
|
int inc = (flags & IFF_ALLMULTI) ? 1 : -1;
|
|
|
|
|
|
dev->gflags ^= IFF_ALLMULTI;
|
|
|
- dev_set_allmulti(dev, inc);
|
|
|
+ __dev_set_allmulti(dev, inc, false);
|
|
|
}
|
|
|
|
|
|
return ret;
|
|
@@ -5271,13 +5285,13 @@ void __dev_notify_flags(struct net_device *dev, unsigned int old_flags,
|
|
|
int dev_change_flags(struct net_device *dev, unsigned int flags)
|
|
|
{
|
|
|
int ret;
|
|
|
- unsigned int changes, old_flags = dev->flags;
|
|
|
+ unsigned int changes, old_flags = dev->flags, old_gflags = dev->gflags;
|
|
|
|
|
|
ret = __dev_change_flags(dev, flags);
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
|
|
|
- changes = old_flags ^ dev->flags;
|
|
|
+ changes = (old_flags ^ dev->flags) | (old_gflags ^ dev->gflags);
|
|
|
__dev_notify_flags(dev, old_flags, changes);
|
|
|
return ret;
|
|
|
}
|