Page MenuHomeFreeBSD

D52056.diff
No OneTemporary

D52056.diff

diff --git a/sys/net/if.c b/sys/net/if.c
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -2589,16 +2589,7 @@
* flip. They require special handling because in-kernel
* consumers may indepdently toggle them.
*/
- if ((ifp->if_flags ^ new_flags) & IFF_PPROMISC) {
- if (new_flags & IFF_PPROMISC)
- ifp->if_flags |= IFF_PROMISC;
- else if (ifp->if_pcount == 0)
- ifp->if_flags &= ~IFF_PROMISC;
- if (log_promisc_mode_change)
- if_printf(ifp, "permanently promiscuous mode %s\n",
- ((new_flags & IFF_PPROMISC) ?
- "enabled" : "disabled"));
- }
+ if_setppromisc(ifp, new_flags & IFF_PPROMISC);
if ((ifp->if_flags ^ new_flags) & IFF_PALLMULTI) {
if (new_flags & IFF_PALLMULTI)
ifp->if_flags |= IFF_ALLMULTI;
@@ -4456,6 +4447,32 @@
return (ifp->if_mtu);
}
+void
+if_setppromisc(if_t ifp, bool ppromisc)
+{
+ int new_flags;
+
+ if (ppromisc)
+ new_flags = ifp->if_flags | IFF_PPROMISC;
+ else
+ new_flags = ifp->if_flags & ~IFF_PPROMISC;
+ if ((ifp->if_flags ^ new_flags) & IFF_PPROMISC) {
+ if (new_flags & IFF_PPROMISC)
+ new_flags |= IFF_PROMISC;
+ /*
+ * Only unset IFF_PROMISC if there are no more consumers of
+ * promiscuity, i.e. the ifp->if_pcount refcount is 0.
+ */
+ else if (ifp->if_pcount == 0)
+ new_flags &= ~IFF_PROMISC;
+ if (log_promisc_mode_change)
+ if_printf(ifp, "permanently promiscuous mode %s\n",
+ ((new_flags & IFF_PPROMISC) ?
+ "enabled" : "disabled"));
+ }
+ ifp->if_flags = new_flags;
+}
+
/*
* Methods for drivers to access interface unicast and multicast
* link level addresses. Driver shall not know 'struct ifaddr' neither
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -622,6 +622,7 @@
int if_getmtu(const if_t ifp);
int if_getmtu_family(const if_t ifp, int family);
void if_notifymtu(if_t ifp);
+void if_setppromisc(const if_t ifp, bool ppromisc);
int if_setflagbits(if_t ifp, int set, int clear);
int if_setflags(if_t ifp, int flags);
int if_getflags(const if_t ifp);
diff --git a/sys/netlink/route/iface_drivers.c b/sys/netlink/route/iface_drivers.c
--- a/sys/netlink/route/iface_drivers.c
+++ b/sys/netlink/route/iface_drivers.c
@@ -105,13 +105,16 @@
}
}
- if (lattrs->ifi_change & IFF_PROMISC) {
- error = ifpromisc(ifp, lattrs->ifi_flags & IFF_PROMISC);
- if (error != 0) {
- nlmsg_report_err_msg(npt, "unable to set promisc");
- return (error);
- }
- }
+ if ((lattrs->ifi_change & IFF_PROMISC) != 0 ||
+ lattrs->ifi_change == 0)
+ /*
+ * When asking for IFF_PROMISC, set permanent flag instead
+ * (IFF_PPROMISC) as we have no way of doing promiscuity
+ * reference counting through ifpromisc(). Every call to this
+ * function either sets or unsets IFF_PROMISC, and ifi_change
+ * is usually set to 0xFFFFFFFF.
+ */
+ if_setppromisc(ifp, (lattrs->ifi_flags & IFF_PROMISC) != 0);
if (lattrs->ifla_address != NULL) {
if (nlp_has_priv(npt->nlp, PRIV_NET_SETIFMAC)) {

File Metadata

Mime Type
text/plain
Expires
Tue, Mar 17, 1:59 PM (2 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29784567
Default Alt Text
D52056.diff (3 KB)

Event Timeline