Page MenuHomeFreeBSD

D52056.1779266529.diff
No OneTemporary

Size
3 KB
Referenced Files
None
Subscribers
None

D52056.1779266529.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, int 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_PROMISC) {
+ 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, int 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
@@ -93,7 +93,12 @@
if (lattrs->ifla_mtu > 0) {
if (nlp_has_priv(npt->nlp, PRIV_NET_SETIFMTU)) {
struct ifreq ifr = { .ifr_mtu = lattrs->ifla_mtu };
- error = ifhwioctl(SIOCSIFMTU, ifp, (char *)&ifr, curthread);
+ error = ifhwioctl(SIOCSIFMTU, ifp, (char *)&ifr,
+ curthread);
+ if (error != 0) {
+ nlmsg_report_err_msg(npt, "Failed to set mtu");
+ return (error);
+ }
} else {
nlmsg_report_err_msg(npt, "Not enough privileges to set mtu");
return (EPERM);
@@ -101,13 +106,15 @@
}
if ((lattrs->ifi_change & IFF_PROMISC) != 0 ||
- lattrs->ifi_change == 0) {
- error = ifpromisc(ifp, lattrs->ifi_flags & IFF_PROMISC);
- if (error != 0) {
- nlmsg_report_err_msg(npt, "unable to set promisc");
- return (error);
- }
- }
+ 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);
return (0);
}

File Metadata

Mime Type
text/plain
Expires
Wed, May 20, 8:42 AM (15 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28752999
Default Alt Text
D52056.1779266529.diff (3 KB)

Event Timeline