git: 56d4550c4d71 - main - ifnet: factor out interface renaming into a separate function.

From: Alexander V. Chernikov <melifaro_at_FreeBSD.org>
Date: Thu, 20 Apr 2023 10:24:01 UTC
The branch main has been updated by melifaro:

URL: https://cgit.FreeBSD.org/src/commit/?id=56d4550c4d71e61057362b3f7d5e391496efec4e

commit 56d4550c4d71e61057362b3f7d5e391496efec4e
Author:     Alexander V. Chernikov <melifaro@FreeBSD.org>
AuthorDate: 2023-04-19 14:26:20 +0000
Commit:     Alexander V. Chernikov <melifaro@FreeBSD.org>
CommitDate: 2023-04-20 10:23:37 +0000

    ifnet: factor out interface renaming into a separate function.
    
    This change is required to support interface renaming via Netlink.
    No functional changes intended.
    
    Reviewed by:    zlei
    Differential Revision: https://reviews.freebsd.org/D39692
    MFC after:      2 weeks
---
 sys/net/if.c     | 116 ++++++++++++++++++++++++++++++-------------------------
 sys/net/if_var.h |   1 +
 2 files changed, 64 insertions(+), 53 deletions(-)

diff --git a/sys/net/if.c b/sys/net/if.c
index 90ed39bb2cff..b53a361c2ba3 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -2476,13 +2476,9 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
 	struct ifreq *ifr;
 	int error = 0, do_ifup = 0;
 	int new_flags, temp_flags;
-	size_t namelen, onamelen;
 	size_t descrlen, nvbuflen;
 	char *descrbuf;
 	char new_name[IFNAMSIZ];
-	char old_name[IFNAMSIZ], strbuf[IFNAMSIZ + 8];
-	struct ifaddr *ifa;
-	struct sockaddr_dl *sdl;
 	void *buf;
 	nvlist_t *nvcap;
 	struct siocsifcapnv_driver_data drv_ioctl_data;
@@ -2749,55 +2745,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
 		    NULL);
 		if (error != 0)
 			return (error);
-		if (new_name[0] == '\0')
-			return (EINVAL);
-		if (strcmp(new_name, ifp->if_xname) == 0)
-			break;
-		if (ifunit(new_name) != NULL)
-			return (EEXIST);
-
-		/*
-		 * XXX: Locking.  Nothing else seems to lock if_flags,
-		 * and there are numerous other races with the
-		 * ifunit() checks not being atomic with namespace
-		 * changes (renames, vmoves, if_attach, etc).
-		 */
-		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);
-		strlcpy(old_name, ifp->if_xname, sizeof(old_name));
-		strlcpy(ifp->if_xname, new_name, sizeof(ifp->if_xname));
-		ifa = ifp->if_addr;
-		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
-		namelen = strlen(new_name);
-		onamelen = sdl->sdl_nlen;
-		/*
-		 * Move the address if needed.  This is safe because we
-		 * allocate space for a name of length IFNAMSIZ when we
-		 * create this in if_attach().
-		 */
-		if (namelen != onamelen) {
-			bcopy(sdl->sdl_data + onamelen,
-			    sdl->sdl_data + namelen, sdl->sdl_alen);
-		}
-		bcopy(new_name, sdl->sdl_data, namelen);
-		sdl->sdl_nlen = namelen;
-		sdl = (struct sockaddr_dl *)ifa->ifa_netmask;
-		bzero(sdl->sdl_data, onamelen);
-		while (namelen != 0)
-			sdl->sdl_data[--namelen] = 0xff;
-		IF_ADDR_WUNLOCK(ifp);
-
-		EVENTHANDLER_INVOKE(ifnet_arrival_event, ifp);
-
-		ifp->if_flags &= ~IFF_RENAMING;
-
-		snprintf(strbuf, sizeof(strbuf), "name=%s", new_name);
-		devctl_notify("IFNET", old_name, "RENAME", strbuf);
+		error = if_rename(ifp, new_name);
 		break;
 
 #ifdef VIMAGE
@@ -3207,6 +3155,68 @@ out_noref:
 	return (error);
 }
 
+int
+if_rename(struct ifnet *ifp, char *new_name)
+{
+	struct ifaddr *ifa;
+	struct sockaddr_dl *sdl;
+	size_t namelen, onamelen;
+	char old_name[IFNAMSIZ];
+	char strbuf[IFNAMSIZ + 8];
+
+	if (new_name[0] == '\0')
+		return (EINVAL);
+	if (strcmp(new_name, ifp->if_xname) == 0)
+		return (0);
+	if (ifunit(new_name) != NULL)
+		return (EEXIST);
+
+	/*
+	 * XXX: Locking.  Nothing else seems to lock if_flags,
+	 * and there are numerous other races with the
+	 * ifunit() checks not being atomic with namespace
+	 * changes (renames, vmoves, if_attach, etc).
+	 */
+	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);
+	strlcpy(old_name, ifp->if_xname, sizeof(old_name));
+	strlcpy(ifp->if_xname, new_name, sizeof(ifp->if_xname));
+	ifa = ifp->if_addr;
+	sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+	namelen = strlen(new_name);
+	onamelen = sdl->sdl_nlen;
+	/*
+	 * Move the address if needed.  This is safe because we
+	 * allocate space for a name of length IFNAMSIZ when we
+	 * create this in if_attach().
+	 */
+	if (namelen != onamelen) {
+		bcopy(sdl->sdl_data + onamelen,
+		    sdl->sdl_data + namelen, sdl->sdl_alen);
+	}
+	bcopy(new_name, sdl->sdl_data, namelen);
+	sdl->sdl_nlen = namelen;
+	sdl = (struct sockaddr_dl *)ifa->ifa_netmask;
+	bzero(sdl->sdl_data, onamelen);
+	while (namelen != 0)
+		sdl->sdl_data[--namelen] = 0xff;
+	IF_ADDR_WUNLOCK(ifp);
+
+	EVENTHANDLER_INVOKE(ifnet_arrival_event, ifp);
+
+	ifp->if_flags &= ~IFF_RENAMING;
+
+	snprintf(strbuf, sizeof(strbuf), "name=%s", new_name);
+	devctl_notify("IFNET", old_name, "RENAME", strbuf);
+
+	return (0);
+}
+
 /*
  * The code common to handling reference counted flags,
  * e.g., in ifpromisc() and if_allmulti().
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index 5f11998ecab8..e21bf44516cc 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -590,6 +590,7 @@ const char *if_getdname(const if_t ifp);
 void if_setdname(if_t ifp, const char *name);
 const char *if_name(if_t ifp);
 int if_setname(if_t ifp, const char *name);
+int if_rename(struct ifnet *ifp, char *new_name);
 void if_setdescr(if_t ifp, char *descrbuf);
 char *if_allocdescr(size_t sz, int malloc_flag);
 void if_freedescr(char *descrbuf);