git: 349fcf079ca3 - main - net: add ifnet_rename_event EVENTHANDLER(9) for interface renaming

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Mon, 22 Dec 2025 02:23:48 UTC
The branch main has been updated by glebius:

URL: https://cgit.FreeBSD.org/src/commit/?id=349fcf079ca32d5c93e45366d2b27638747affeb

commit 349fcf079ca32d5c93e45366d2b27638747affeb
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2025-12-21 21:31:43 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2025-12-22 02:23:14 +0000

    net: add ifnet_rename_event EVENTHANDLER(9) for interface renaming
    
    and don't trigger ifnet_arrival_event and ifnet_departure_event for a
    rename, as the interface isn't being detached from any protocol.  The
    consumers of the arrival/departure events are divided into a few
    categories:
    - which indeed need to do the same actions as if interface was fully
      detached and attached: routing socket and netlink notifications to
      userland and the Linux sysfs.  All addressed by this commit.
    - which build their logic based on an interface name, but should actually
      update their database on rename: packet filters.  This commit leaves
      them with the old behavior - emulate full detach & attach, but this
      should be improved.
    - which shouldn't do anything on rename, not touched by the commit.
    - ng_ether and if_tuntap, that are special and will be addressed by
      separate commits.
---
 sys/compat/linsysfs/linsysfs_net.c            | 15 +++++++-
 sys/net/if.c                                  |  4 +--
 sys/net/if_var.h                              | 11 ++++--
 sys/net/rtsock.c                              | 28 ++++++++++-----
 sys/netlink/route/iface.c                     | 36 ++++++++++++++------
 sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c |  8 +++++
 sys/netpfil/ipfw/ip_fw_iface.c                | 49 +++++++++++++++++----------
 sys/netpfil/pf/pf_if.c                        | 12 +++++++
 8 files changed, 118 insertions(+), 45 deletions(-)

diff --git a/sys/compat/linsysfs/linsysfs_net.c b/sys/compat/linsysfs/linsysfs_net.c
index 7439b0b4fdc0..dcc498e4e1ae 100644
--- a/sys/compat/linsysfs/linsysfs_net.c
+++ b/sys/compat/linsysfs/linsysfs_net.c
@@ -45,7 +45,7 @@
 #include <compat/linsysfs/linsysfs.h>
 
 struct pfs_node *net;
-static eventhandler_tag if_arrival_tag, if_departure_tag;
+static eventhandler_tag if_arrival_tag, if_departure_tag, if_rename_tag;
 
 static uint32_t net_latch_count = 0;
 static struct mtx net_latch_mtx;
@@ -312,6 +312,16 @@ linsysfs_if_departure(void *arg __unused, if_t ifp)
 	linsysfs_net_latch_rele();
 }
 
+static void
+linsysfs_if_rename(void *arg __unused, if_t ifp)
+{
+
+	linsysfs_net_latch_hold();
+	linsysfs_net_delif(ifp);
+	(void)linsysfs_net_addif(ifp, net);
+	linsysfs_net_latch_rele();
+}
+
 void
 linsysfs_net_init(void)
 {
@@ -324,6 +334,8 @@ linsysfs_net_init(void)
 	    linsysfs_if_arrival, NULL, EVENTHANDLER_PRI_ANY);
 	if_departure_tag = EVENTHANDLER_REGISTER(ifnet_departure_event,
 	    linsysfs_if_departure, NULL, EVENTHANDLER_PRI_ANY);
+	if_rename_tag = EVENTHANDLER_REGISTER(ifnet_rename_event,
+	    linsysfs_if_rename, NULL, EVENTHANDLER_PRI_ANY);
 
 	linsysfs_net_latch_hold();
 	VNET_LIST_RLOCK();
@@ -343,6 +355,7 @@ linsysfs_net_uninit(void)
 
 	EVENTHANDLER_DEREGISTER(ifnet_arrival_event, if_arrival_tag);
 	EVENTHANDLER_DEREGISTER(ifnet_departure_event, if_departure_tag);
+	EVENTHANDLER_DEREGISTER(ifnet_rename_event, if_rename_tag);
 
 	linsysfs_net_latch_hold();
 	TAILQ_FOREACH_SAFE(nq, &ifp_nodes_q, ifp_nodes_next, nq_tmp) {
diff --git a/sys/net/if.c b/sys/net/if.c
index 3394aa90127f..1dea00da3cf2 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -3035,8 +3035,6 @@ if_rename(struct ifnet *ifp, char *new_name)
 	 */
 	ifp->if_flags |= IFF_RENAMING;
 
-	EVENTHANDLER_INVOKE(ifnet_departure_event, ifp);
-
 	if_printf(ifp, "changing name to '%s'\n", new_name);
 
 	IF_ADDR_WLOCK(ifp);
@@ -3063,7 +3061,7 @@ if_rename(struct ifnet *ifp, char *new_name)
 		sdl->sdl_data[--namelen] = 0xff;
 	IF_ADDR_WUNLOCK(ifp);
 
-	EVENTHANDLER_INVOKE(ifnet_arrival_event, ifp);
+	EVENTHANDLER_INVOKE(ifnet_rename_event, ifp, old_name);
 
 	ifp->if_flags &= ~IFF_RENAMING;
 
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index 4fb51aca0cd7..3c65b2b4d2d8 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -361,19 +361,24 @@ EVENTHANDLER_DECLARE(ifaddr_event_ext, ifaddr_event_ext_handler_t);
 
 /*
  * Interface arrival & departure events.
- * The ifnet_arrival_event is executed before the is yet globally visible.
- * Protocols shall use this event to attach themselves.  Protocols shall not
- * expect other protocols to be fully attached.
+ * The ifnet_arrival_event is executed before the interface is yet globally
+ * visible.  Protocols shall use this event to attach themselves.  Protocols
+ * shall not expect other protocols to be fully attached.
  * The ifnet_attached_event is executed after the interface is attached to all
  * protocols, is globally visible and fully functional.
  * The ifnet_departure_event is complementary to ifnet_arrival_event.  The
  * interface is no longer globally visible, protocols may detach.
  * XXXGL: immediate memory reclamation may not be safe in ifnet_departure_event.
+ * The ifnet_rename_event is executed after an interface is renamed.  The
+ * handlers would see the new name of the interface, and are also passed with
+ * old name in the argument.
  */
 typedef void (*ifnet_event_handler_t)(void *, if_t);
 EVENTHANDLER_DECLARE(ifnet_arrival_event, ifnet_event_handler_t);
 EVENTHANDLER_DECLARE(ifnet_attached_event, ifnet_event_handler_t);
 EVENTHANDLER_DECLARE(ifnet_departure_event, ifnet_event_handler_t);
+typedef void (*ifnet_rename_event_handler_t)(void *, if_t, const char *);
+EVENTHANDLER_DECLARE(ifnet_rename_event, ifnet_rename_event_handler_t);
 
 /* Interface link state change event */
 typedef void (*ifnet_link_event_handler_t)(void *, if_t, int);
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index 82af92545b79..774537366910 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -208,7 +208,7 @@ static int	sysctl_ifmalist(int af, struct walkarg *w);
 static void	rt_getmetrics(const struct rtentry *rt,
 			const struct nhop_object *nh, struct rt_metrics *out);
 static void	rt_dispatch(struct mbuf *, sa_family_t);
-static void	rt_ifannouncemsg(struct ifnet *ifp, int what);
+static void	rt_ifannouncemsg(struct ifnet *, int, const char *);
 static int	handle_rtm_get(struct rt_addrinfo *info, u_int fibnum,
 			struct rt_msghdr *rtm, struct rib_cmd_info *rc);
 static int	update_rtm_from_rc(struct rt_addrinfo *info,
@@ -319,17 +319,26 @@ SYSINIT(rtsock_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, rtsock_init, NULL);
 static void
 rts_ifnet_attached(void *arg __unused, struct ifnet *ifp)
 {
-	rt_ifannouncemsg(ifp, IFAN_ARRIVAL);
+	rt_ifannouncemsg(ifp, IFAN_ARRIVAL, NULL);
 }
 EVENTHANDLER_DEFINE(ifnet_attached_event, rts_ifnet_attached, NULL, 0);
 
 static void
 rts_handle_ifnet_departure(void *arg __unused, struct ifnet *ifp)
 {
-	rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
+	rt_ifannouncemsg(ifp, IFAN_DEPARTURE, NULL);
 }
 EVENTHANDLER_DEFINE(ifnet_departure_event, rts_handle_ifnet_departure, NULL, 0);
 
+static void
+rts_handle_ifnet_rename(void *arg __unused, struct ifnet *ifp,
+    const char *old_name)
+{
+	rt_ifannouncemsg(ifp, IFAN_DEPARTURE, old_name);
+	rt_ifannouncemsg(ifp, IFAN_ARRIVAL, NULL);
+}
+EVENTHANDLER_DEFINE(ifnet_rename_event, rts_handle_ifnet_rename, NULL, 0);
+
 static void
 rts_append_data(struct socket *so, struct mbuf *m)
 {
@@ -2143,7 +2152,7 @@ rt_newmaddrmsg(int cmd, struct ifmultiaddr *ifma)
 
 static struct mbuf *
 rt_makeifannouncemsg(struct ifnet *ifp, int type, int what,
-	struct rt_addrinfo *info)
+    struct rt_addrinfo *info, const char *ifname)
 {
 	struct if_announcemsghdr *ifan;
 	struct mbuf *m;
@@ -2155,8 +2164,9 @@ rt_makeifannouncemsg(struct ifnet *ifp, int type, int what,
 	if (m != NULL) {
 		ifan = mtod(m, struct if_announcemsghdr *);
 		ifan->ifan_index = ifp->if_index;
-		strlcpy(ifan->ifan_name, ifp->if_xname,
-			sizeof(ifan->ifan_name));
+		strlcpy(ifan->ifan_name,
+		    ifname != NULL ? ifname : ifp->if_xname,
+		    sizeof(ifan->ifan_name));
 		ifan->ifan_what = what;
 	}
 	return m;
@@ -2173,7 +2183,7 @@ rt_ieee80211msg(struct ifnet *ifp, int what, void *data, size_t data_len)
 	struct mbuf *m;
 	struct rt_addrinfo info;
 
-	m = rt_makeifannouncemsg(ifp, RTM_IEEE80211, what, &info);
+	m = rt_makeifannouncemsg(ifp, RTM_IEEE80211, what, &info, NULL);
 	if (m != NULL) {
 		/*
 		 * Append the ieee80211 data.  Try to stick it in the
@@ -2207,12 +2217,12 @@ rt_ieee80211msg(struct ifnet *ifp, int what, void *data, size_t data_len)
  * network interface arrival and departure.
  */
 static void
-rt_ifannouncemsg(struct ifnet *ifp, int what)
+rt_ifannouncemsg(struct ifnet *ifp, int what, const char *ifname)
 {
 	struct mbuf *m;
 	struct rt_addrinfo info;
 
-	m = rt_makeifannouncemsg(ifp, RTM_IFANNOUNCE, what, &info);
+	m = rt_makeifannouncemsg(ifp, RTM_IFANNOUNCE, what, &info, ifname);
 	if (m != NULL)
 		rt_dispatch(m, AF_UNSPEC);
 }
diff --git a/sys/netlink/route/iface.c b/sys/netlink/route/iface.c
index 29a9a89fd20c..e9c053015fad 100644
--- a/sys/netlink/route/iface.c
+++ b/sys/netlink/route/iface.c
@@ -70,7 +70,8 @@ struct netlink_walkargs {
 	int dumped;
 };
 
-static eventhandler_tag ifdetach_event, ifattach_event, iflink_event, ifaddr_event;
+static eventhandler_tag ifdetach_event, ifattach_event, ifrename_event,
+    iflink_event, ifaddr_event;
 
 static SLIST_HEAD(, nl_cloner) nl_cloners = SLIST_HEAD_INITIALIZER(nl_cloners);
 
@@ -288,7 +289,7 @@ dump_iface_caps(struct nl_writer *nw, struct ifnet *ifp)
  */
 static bool
 dump_iface(struct nl_writer *nw, if_t ifp, const struct nlmsghdr *hdr,
-    int if_flags_mask)
+    int if_flags_mask, const char *ifname)
 {
 	struct epoch_tracker et;
         struct ifinfomsg *ifinfo;
@@ -312,7 +313,8 @@ dump_iface(struct nl_writer *nw, if_t ifp, const struct nlmsghdr *hdr,
 	if (ifs.ifla_operstate == IF_OPER_UP)
 		ifinfo->ifi_flags |= IFF_LOWER_UP;
 
-        nlattr_add_string(nw, IFLA_IFNAME, if_name(ifp));
+        nlattr_add_string(nw, IFLA_IFNAME,
+	    ifname != NULL ? ifname : if_name(ifp));
         nlattr_add_u8(nw, IFLA_OPERSTATE, ifs.ifla_operstate);
         nlattr_add_u8(nw, IFLA_CARRIER, ifs.ifla_carrier);
 
@@ -438,7 +440,7 @@ static int
 dump_cb(if_t ifp, void *_arg)
 {
 	struct netlink_walkargs *wa = (struct netlink_walkargs *)_arg;
-	if (!dump_iface(wa->nw, ifp, &wa->hdr, 0))
+	if (!dump_iface(wa->nw, ifp, &wa->hdr, 0, NULL))
 		return (ENOMEM);
 	return (0);
 }
@@ -488,7 +490,7 @@ rtnl_handle_getlink(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_pstate *n
 
 		if (ifp != NULL) {
 			if (match_iface(ifp, &attrs)) {
-				if (!dump_iface(wa.nw, ifp, &wa.hdr, 0))
+				if (!dump_iface(wa.nw, ifp, &wa.hdr, 0, NULL))
 					error = ENOMEM;
 			} else
 				error = ENODEV;
@@ -1399,7 +1401,8 @@ rtnl_handle_ifaddr(void *arg __unused, struct ifaddr *ifa, int cmd)
 }
 
 static void
-rtnl_handle_ifevent(if_t ifp, int nlmsg_type, int if_flags_mask)
+rtnl_handle_ifevent(if_t ifp, int nlmsg_type, int if_flags_mask,
+    const char *ifname)
 {
 	struct nlmsghdr hdr = { .nlmsg_type = nlmsg_type };
 	struct nl_writer nw;
@@ -1409,7 +1412,7 @@ rtnl_handle_ifevent(if_t ifp, int nlmsg_type, int if_flags_mask)
 		NL_LOG(LOG_DEBUG, "error allocating group writer");
 		return;
 	}
-	dump_iface(&nw, ifp, &hdr, if_flags_mask);
+	dump_iface(&nw, ifp, &hdr, if_flags_mask, ifname);
         nlmsg_flush(&nw);
 }
 
@@ -1417,28 +1420,35 @@ static void
 rtnl_handle_ifattach(void *arg, if_t ifp)
 {
 	NL_LOG(LOG_DEBUG2, "ifnet %s", if_name(ifp));
-	rtnl_handle_ifevent(ifp, NL_RTM_NEWLINK, 0);
+	rtnl_handle_ifevent(ifp, NL_RTM_NEWLINK, 0, NULL);
 }
 
 static void
 rtnl_handle_ifdetach(void *arg, if_t ifp)
 {
 	NL_LOG(LOG_DEBUG2, "ifnet %s", if_name(ifp));
-	rtnl_handle_ifevent(ifp, NL_RTM_DELLINK, 0);
+	rtnl_handle_ifevent(ifp, NL_RTM_DELLINK, 0, NULL);
+}
+
+static void
+rtnl_handle_ifrename(void *arg, if_t ifp, const char *old_name)
+{
+	rtnl_handle_ifevent(ifp, NL_RTM_DELLINK, 0, old_name);
+	rtnl_handle_ifevent(ifp, NL_RTM_NEWLINK, 0, NULL);
 }
 
 static void
 rtnl_handle_iflink(void *arg, if_t ifp, int link_state __unused)
 {
 	NL_LOG(LOG_DEBUG2, "ifnet %s", if_name(ifp));
-	rtnl_handle_ifevent(ifp, NL_RTM_NEWLINK, 0);
+	rtnl_handle_ifevent(ifp, NL_RTM_NEWLINK, 0, NULL);
 }
 
 void
 rtnl_handle_ifnet_event(if_t ifp, int if_flags_mask)
 {
 	NL_LOG(LOG_DEBUG2, "ifnet %s", if_name(ifp));
-	rtnl_handle_ifevent(ifp, NL_RTM_NEWLINK, if_flags_mask);
+	rtnl_handle_ifevent(ifp, NL_RTM_NEWLINK, if_flags_mask, NULL);
 }
 
 static const struct rtnl_cmd_handler cmd_handlers[] = {
@@ -1513,6 +1523,9 @@ rtnl_ifaces_init(void)
 	ifdetach_event = EVENTHANDLER_REGISTER(
 	    ifnet_departure_event, rtnl_handle_ifdetach, NULL,
 	    EVENTHANDLER_PRI_ANY);
+	ifrename_event = EVENTHANDLER_REGISTER(
+	    ifnet_rename_event, rtnl_handle_ifrename, NULL,
+	    EVENTHANDLER_PRI_ANY);
 	ifaddr_event = EVENTHANDLER_REGISTER(
 	    rt_addrmsg, rtnl_handle_ifaddr, NULL,
 	    EVENTHANDLER_PRI_ANY);
@@ -1528,6 +1541,7 @@ rtnl_ifaces_destroy(void)
 {
 	EVENTHANDLER_DEREGISTER(ifnet_arrival_event, ifattach_event);
 	EVENTHANDLER_DEREGISTER(ifnet_departure_event, ifdetach_event);
+	EVENTHANDLER_DEREGISTER(ifnet_rename_event, ifrename_event);
 	EVENTHANDLER_DEREGISTER(rt_addrmsg, ifaddr_event);
 	EVENTHANDLER_DEREGISTER(ifnet_link_event, iflink_event);
 }
diff --git a/sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c b/sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c
index 207d1895dc3e..331fc454ca51 100644
--- a/sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c
+++ b/sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c
@@ -95,8 +95,10 @@ VNET_DEFINE(ipf_main_softc_t, ipfmain) = {
 
 VNET_DEFINE_STATIC(eventhandler_tag, ipf_arrivetag);
 VNET_DEFINE_STATIC(eventhandler_tag, ipf_departtag);
+VNET_DEFINE_STATIC(eventhandler_tag, ipf_renametag);
 #define	V_ipf_arrivetag		VNET(ipf_arrivetag)
 #define	V_ipf_departtag		VNET(ipf_departtag)
+#define	V_ipf_renametag		VNET(ipf_renametag)
 
 static void ipf_ifevent(void *arg, struct ifnet *ifp);
 
@@ -1349,6 +1351,9 @@ ipf_event_reg(void)
 	V_ipf_departtag = EVENTHANDLER_REGISTER(ifnet_departure_event, \
 					       ipf_ifevent, NULL, \
 					       EVENTHANDLER_PRI_ANY);
+	V_ipf_renametag = EVENTHANDLER_REGISTER(ifnet_rename_event, \
+					       ipf_ifevent, NULL, \
+					       EVENTHANDLER_PRI_ANY);
 }
 
 void
@@ -1360,6 +1365,9 @@ ipf_event_dereg(void)
 	if (V_ipf_departtag != NULL) {
 		EVENTHANDLER_DEREGISTER(ifnet_departure_event, V_ipf_departtag);
 	}
+	if (V_ipf_renametag != NULL) {
+		EVENTHANDLER_DEREGISTER(ifnet_rename_event, V_ipf_renametag);
+	}
 }
 
 
diff --git a/sys/netpfil/ipfw/ip_fw_iface.c b/sys/netpfil/ipfw/ip_fw_iface.c
index 3c648feecba4..71a25e84ec2b 100644
--- a/sys/netpfil/ipfw/ip_fw_iface.c
+++ b/sys/netpfil/ipfw/ip_fw_iface.c
@@ -77,12 +77,13 @@ static struct ipfw_sopt_handler	scodes[] = {
 /*
  * FreeBSD Kernel interface.
  */
-static void ipfw_kifhandler(void *arg, struct ifnet *ifp);
+static void ipfw_kifhandler(void *, struct ifnet *, const char *);
 static int ipfw_kiflookup(char *name);
 static void iface_khandler_register(void);
 static void iface_khandler_deregister(void);
 
-static eventhandler_tag ipfw_ifdetach_event, ipfw_ifattach_event;
+static eventhandler_tag ipfw_ifdetach_event, ipfw_ifattach_event,
+    ipfw_rename_event;
 static int num_vnets = 0;
 static struct mtx vnet_mtx;
 
@@ -90,19 +91,21 @@ static struct mtx vnet_mtx;
  * Checks if kernel interface is contained in our tracked
  * interface list and calls attach/detach handler.
  */
+enum ifevent { ARRIVAL, DEPARTURE, RENAME };
 static void
-ipfw_kifhandler(void *arg, struct ifnet *ifp)
+ipfw_kifhandler(void *arg, struct ifnet *ifp, const char *old_name)
 {
+	enum ifevent *what = arg;
 	struct ip_fw_chain *ch;
 	struct ipfw_iface *iif;
 	struct namedobj_instance *ii;
-	uintptr_t htype;
+
+	MPASS(*what != RENAME || old_name != NULL);
 
 	if (V_ipfw_vnet_ready == 0)
 		return;
 
 	ch = &V_layer3_chain;
-	htype = (uintptr_t)arg;
 
 	IPFW_UH_WLOCK(ch);
 	ii = CHAIN_TO_II(ch);
@@ -111,12 +114,23 @@ ipfw_kifhandler(void *arg, struct ifnet *ifp)
 		return;
 	}
 	iif = (struct ipfw_iface*)ipfw_objhash_lookup_name(ii, 0,
-	    if_name(ifp));
+	    *what == RENAME ? old_name : if_name(ifp));
 	if (iif != NULL) {
-		if (htype == 1)
+		switch (*what) {
+		case ARRIVAL:
 			handle_ifattach(ch, iif, ifp->if_index);
-		else
+			break;
+		case DEPARTURE:
+			handle_ifdetach(ch, iif, ifp->if_index);
+			break;
+		case RENAME:
+			/*
+			 * XXXGL: should be handled better.
+			 */
 			handle_ifdetach(ch, iif, ifp->if_index);
+			handle_ifattach(ch, iif, ifp->if_index);
+			break;
+		}
 	}
 	IPFW_UH_WUNLOCK(ch);
 }
@@ -143,12 +157,12 @@ iface_khandler_register(void)
 
 	printf("IPFW: starting up interface tracker\n");
 
-	ipfw_ifdetach_event = EVENTHANDLER_REGISTER(
-	    ifnet_departure_event, ipfw_kifhandler, NULL,
-	    EVENTHANDLER_PRI_ANY);
-	ipfw_ifattach_event = EVENTHANDLER_REGISTER(
-	    ifnet_arrival_event, ipfw_kifhandler, (void*)((uintptr_t)1),
-	    EVENTHANDLER_PRI_ANY);
+	ipfw_ifdetach_event = EVENTHANDLER_REGISTER(ifnet_departure_event,
+	    ipfw_kifhandler, (void*)(uintptr_t)DEPARTURE, EVENTHANDLER_PRI_ANY);
+	ipfw_ifattach_event = EVENTHANDLER_REGISTER(ifnet_arrival_event,
+	    ipfw_kifhandler, (void*)(uintptr_t)ARRIVAL, EVENTHANDLER_PRI_ANY);
+	ipfw_rename_event = EVENTHANDLER_REGISTER(ifnet_rename_event,
+	    ipfw_kifhandler, (void*)(uintptr_t)RENAME, EVENTHANDLER_PRI_ANY);
 }
 
 /*
@@ -171,10 +185,9 @@ iface_khandler_deregister(void)
 	if (destroy == 0)
 		return;
 
-	EVENTHANDLER_DEREGISTER(ifnet_arrival_event,
-	    ipfw_ifattach_event);
-	EVENTHANDLER_DEREGISTER(ifnet_departure_event,
-	    ipfw_ifdetach_event);
+	EVENTHANDLER_DEREGISTER(ifnet_arrival_event, ipfw_ifattach_event);
+	EVENTHANDLER_DEREGISTER(ifnet_departure_event, ipfw_ifdetach_event);
+	EVENTHANDLER_DEREGISTER(ifnet_rename_event, ipfw_rename_event);
 }
 
 /*
diff --git a/sys/netpfil/pf/pf_if.c b/sys/netpfil/pf/pf_if.c
index 2d85a553fb5a..5288de3d78a0 100644
--- a/sys/netpfil/pf/pf_if.c
+++ b/sys/netpfil/pf/pf_if.c
@@ -76,6 +76,7 @@ VNET_DEFINE(struct pfi_kkif *, pf_kifmarker);
 
 static eventhandler_tag	 pfi_attach_cookie;
 static eventhandler_tag	 pfi_detach_cookie;
+static eventhandler_tag  pfi_rename_cookie;
 static eventhandler_tag	 pfi_attach_group_cookie;
 static eventhandler_tag	 pfi_change_group_cookie;
 static eventhandler_tag	 pfi_detach_group_cookie;
@@ -95,6 +96,7 @@ static int	 pfi_skip_if(const char *, struct pfi_kkif *);
 static int	 pfi_unmask(void *);
 static void	 pfi_attach_ifnet_event(void * __unused, struct ifnet *);
 static void	 pfi_detach_ifnet_event(void * __unused, struct ifnet *);
+static void	 pfi_rename_ifnet_event(void * __unused, struct ifnet *);
 static void	 pfi_attach_group_event(void * __unused, struct ifg_group *);
 static void	 pfi_change_group_event(void * __unused, char *);
 static void	 pfi_detach_group_event(void * __unused, struct ifg_group *);
@@ -172,6 +174,8 @@ pfi_initialize(void)
 	    pfi_attach_ifnet_event, NULL, EVENTHANDLER_PRI_ANY);
 	pfi_detach_cookie = EVENTHANDLER_REGISTER(ifnet_departure_event,
 	    pfi_detach_ifnet_event, NULL, EVENTHANDLER_PRI_ANY);
+	pfi_rename_cookie = EVENTHANDLER_REGISTER(ifnet_rename_event,
+	    pfi_rename_ifnet_event, NULL, EVENTHANDLER_PRI_ANY);
 	pfi_attach_group_cookie = EVENTHANDLER_REGISTER(group_attach_event,
 	    pfi_attach_group_event, NULL, EVENTHANDLER_PRI_ANY);
 	pfi_change_group_cookie = EVENTHANDLER_REGISTER(group_change_event,
@@ -1069,6 +1073,14 @@ pfi_attach_ifnet_event(void *arg __unused, struct ifnet *ifp)
 	NET_EPOCH_EXIT(et);
 }
 
+static void
+pfi_rename_ifnet_event(void *arg, struct ifnet *ifp)
+{
+	/* XXXGL: should be handled better */
+	pfi_detach_ifnet_event(arg, ifp);
+	pfi_attach_ifnet_event(arg, ifp);
+}
+
 static void
 pfi_detach_ifnet_event(void *arg __unused, struct ifnet *ifp)
 {