review request: interface renaming patch

Brooks Davis brooks at one-eyed-alien.net
Mon Jan 26 13:22:28 PST 2004


On Fri, Jan 23, 2004 at 12:02:38PM -0800, Brooks Davis wrote:
> The patch is split into cleanups that apply to the tree regardless of
> this functional change and the actual functional changes.  You will need
> to use "patch -p2" to apply the patch due to they way I generated it
> from my perforce trees.

Here's a new version of the patch.  Following a suggestion from Vincent
Jardin, I announce the departure of the interface before renaming it and
announce its arrival afterwards.  I've also added some documentation for
SIOCSIFNAME to ifnet.9.

-- Brooks

*** Cleanup diffs ***

--- ../freebsd/sbin/ifconfig/ifconfig.c	Wed Oct 29 10:24:27 2003
+++ ../cleanup/sbin/ifconfig/ifconfig.c	Fri Jan 23 10:44:54 2004
@@ -113,7 +113,7 @@
 struct	sockaddr_in	netmask;
 struct	netrange	at_nr;		/* AppleTalk net range */
 
-char	name[32];
+char	name[IFNAMSIZ];
 int	flags;
 int	setaddr;
 int	setipdst;
@@ -596,8 +596,9 @@
 			addrcount++;
 			next += nextifm->ifm_msglen;
 		}
-		strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
-		name[sdl->sdl_nlen] = '\0';
+		strlcpy(name, sdl->sdl_data,
+		    sizeof(name) <= sdl->sdl_nlen ?
+		    sizeof(name) : sdl->sdl_nlen + 1);
 
 		if (all || namesonly) {
 			if (uponly)
--- ../freebsd/sbin/ifconfig/ifconfig.h	Thu Oct  9 18:23:30 2003
+++ ../cleanup/sbin/ifconfig/ifconfig.h	Fri Jan 23 10:44:54 2004
@@ -36,7 +36,7 @@
 
 extern struct ifreq ifr;
 
-extern char name[32];	/* name of interface */
+extern char name[IFNAMSIZ];	/* name of interface */
 extern int allmedia;
 extern int supmedia;
 struct afswtch;
--- ../freebsd/sys/net/if.c	Fri Jan 23 09:26:48 2004
+++ ../cleanup/sys/net/if.c	Fri Jan 23 10:21:15 2004
@@ -410,36 +410,34 @@
 	 * create a Link Level name for this device
 	 */
 	namelen = strlen(ifp->if_xname);
-#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
-	masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
+	masklen = offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
 	socksize = masklen + ifp->if_addrlen;
 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
 	if (socksize < sizeof(*sdl))
 		socksize = sizeof(*sdl);
 	socksize = ROUNDUP(socksize);
+#undef ROUNDUP
 	ifasize = sizeof(*ifa) + 2 * socksize;
-	ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK | M_ZERO);
-	if (ifa) {
-		IFA_LOCK_INIT(ifa);
-		sdl = (struct sockaddr_dl *)(ifa + 1);
-		sdl->sdl_len = socksize;
-		sdl->sdl_family = AF_LINK;
-		bcopy(ifp->if_xname, sdl->sdl_data, namelen);
-		sdl->sdl_nlen = namelen;
-		sdl->sdl_index = ifp->if_index;
-		sdl->sdl_type = ifp->if_type;
-		ifaddr_byindex(ifp->if_index) = ifa;
-		ifa->ifa_ifp = ifp;
-		ifa->ifa_rtrequest = link_rtrequest;
-		ifa->ifa_addr = (struct sockaddr *)sdl;
-		sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
-		ifa->ifa_netmask = (struct sockaddr *)sdl;
-		sdl->sdl_len = masklen;
-		while (namelen != 0)
-			sdl->sdl_data[--namelen] = 0xff;
-		ifa->ifa_refcnt = 1;
-		TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);
-	}
+	ifa = malloc(ifasize, M_IFADDR, M_WAITOK | M_ZERO);
+	IFA_LOCK_INIT(ifa);
+	sdl = (struct sockaddr_dl *)(ifa + 1);
+	sdl->sdl_len = socksize;
+	sdl->sdl_family = AF_LINK;
+	bcopy(ifp->if_xname, sdl->sdl_data, namelen);
+	sdl->sdl_nlen = namelen;
+	sdl->sdl_index = ifp->if_index;
+	sdl->sdl_type = ifp->if_type;
+	ifaddr_byindex(ifp->if_index) = ifa;
+	ifa->ifa_ifp = ifp;
+	ifa->ifa_rtrequest = link_rtrequest;
+	ifa->ifa_addr = (struct sockaddr *)sdl;
+	sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
+	ifa->ifa_netmask = (struct sockaddr *)sdl;
+	sdl->sdl_len = masklen;
+	while (namelen != 0)
+		sdl->sdl_data[--namelen] = 0xff;
+	ifa->ifa_refcnt = 1;
+	TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);
 	ifp->if_broadcastaddr = 0; /* reliably crash if used uninitialized */
 
 	if (domains)

*** Functional diffs ***

--- ../cleanup/sbin/ifconfig/ifconfig.8	Fri Jan 23 09:36:11 2004
+++ sbin/ifconfig/ifconfig.8	Fri Jan 23 10:58:58 2004
@@ -322,6 +322,9 @@
 and 802.11g
 .Pq Dq 11g
 operating modes.
+.It Cm name Ar name
+Set the interface name to
+.Ar name .
 .It Cm rxcsum , txcsum
 If the driver supports user-configurable checksum offloading,
 enable receive (or transmit) checksum offloading on the interface.
@@ -353,7 +356,10 @@
 If the interface is given without a unit number, try to create a new
 device with an arbitrary unit number.
 If creation of an arbitrary device is successful, the new device name is
-printed to standard output.
+printed to standard output unless the interface is renamed or destroyed
+in the same
+.Nm
+invocation.
 .It Cm destroy
 Destroy the specified network pseudo-device.
 .It Cm plumb
--- ../cleanup/sbin/ifconfig/ifconfig.c	Fri Jan 23 10:44:54 2004
+++ sbin/ifconfig/ifconfig.c	Fri Jan 23 10:58:58 2004
@@ -129,6 +129,7 @@
 
 int supmedia = 0;
 int listcloners = 0;
+int printname = 0;		/* Print the name of the created interface. */
 
 #ifdef INET6
 char	addr_buf[MAXHOSTNAMELEN *2 + 1];	/*for getnameinfo()*/
@@ -172,6 +173,7 @@
 c_func	setifipdst;
 c_func	setifflags, setifmetric, setifmtu, setifcap;
 c_func	clone_destroy;
+c_func	setifname;
 
 
 void clone_create(void);
@@ -286,6 +288,7 @@
 	{ "compress",	IFF_LINK0,	setifflags },
 	{ "noicmp",	IFF_LINK1,	setifflags },
 	{ "mtu",	NEXTARG,	setifmtu },
+	{ "name",	NEXTARG,	setifname },
 	{ 0,		0,		setifaddr },
 	{ 0,		0,		setifdstaddr },
 };
@@ -525,7 +528,7 @@
 			clone_create();
 			argc--, argv++;
 			if (argc == 0)
-				exit(0);
+				goto end;
 		}
 		ifindex = if_nametoindex(name);
 		if (ifindex == 0)
@@ -629,6 +632,9 @@
 
 	if (namesonly && need_nl > 0)
 		putchar('\n');
+end:
+	if (printname)
+		printf("%s\n", name);
 
 	exit (0);
 }
@@ -1037,6 +1043,30 @@
 		warn("ioctl (set mtu)");
 }
 
+void
+setifname(const char *val, int dummy __unused, int s, 
+    const struct afswtch *afp)
+{
+	char	*newname;
+
+	newname = strdup(val);
+
+	ifr.ifr_data = newname;
+	if (ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) {
+		warn("ioctl (set name)");
+		free(newname);
+		return;
+	}
+	strlcpy(name, newname, sizeof(name));
+	free(newname);
+
+	/*
+	 * Even if we just created the interface, we don't need to print
+	 * its name because we just nailed it down separately.
+	 */
+	printname = 0;
+}
+
 #define	IFFBITS \
 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \
 "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
@@ -1883,8 +1913,13 @@
 	if (ioctl(s, SIOCIFCREATE, &ifr) < 0)
 		err(1, "SIOCIFCREATE");
 
+	/*
+	 * If we get a different name back then we put in, we probably
+	 * want to print it out, but we might change our mind later so
+	 * we just signal our intrest and leave the printout for later.
+	 */
 	if (strcmp(name, ifr.ifr_name) != 0) {
-		printf("%s\n", ifr.ifr_name);
+		printname = 1;
 		strlcpy(name, ifr.ifr_name, sizeof(name));
 	}
 
@@ -1898,4 +1933,9 @@
 	(void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
 	if (ioctl(s, SIOCIFDESTROY, &ifr) < 0)
 		err(1, "SIOCIFDESTROY");
+	/*
+	 * If we create and destroy an interface in the same command,
+	 * there isn't any reason to print it's name.
+	 */
+	printname = 0;
 }
--- ../cleanup/share/man/man9/ifnet.9	Fri Jan 23 10:08:43 2004
+++ share/man/man9/ifnet.9	Mon Jan 26 13:11:57 2004
@@ -950,6 +950,13 @@
 Get interface configuration.
 (No call-down to driver.)
 .Pp
+.It Dv SIOCSIFNAME
+Set the interface name.
+.Dv RTM_IFANNOUCNE departure and arrival messages are sent so that
+routing code that relies on the interface name will update its interface
+list.
+Caller must have appropriate privilege.
+(No call-down to driver.)
 .It Dv SIOCGIFCAP
 .It Dv SIOCGIFFLAGS
 .It Dv SIOCGIFMETRIC
--- ../cleanup/sys/net/if.c	Fri Jan 23 10:21:15 2004
+++ sys/net/if.c	Fri Jan 23 20:52:02 2004
@@ -410,7 +410,11 @@
 	 * create a Link Level name for this device
 	 */
 	namelen = strlen(ifp->if_xname);
-	masklen = offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
+	/*
+	 * Always save enough space for any possiable name so we can do
+	 * a rename in place later.
+	 */
+	masklen = offsetof(struct sockaddr_dl, sdl_data[0]) + IFNAMSIZ;
 	socksize = masklen + ifp->if_addrlen;
 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
 	if (socksize < sizeof(*sdl))
@@ -733,17 +737,16 @@
 	int bytoff, bitoff;
 	int unit;
 
-	ifc = if_clone_lookup(name, &unit);
-	if (ifc == NULL)
-		return (EINVAL);
-
-	if (unit < ifc->ifc_minifs)
-		return (EINVAL);
-
 	ifp = ifunit(name);
 	if (ifp == NULL)
 		return (ENXIO);
 
+	unit = ifp->if_dunit;
+
+	ifc = if_clone_lookup(ifp->if_dname, NULL);
+	if (ifc == NULL)
+		return (EINVAL);
+
 	if (ifc->ifc_destroy == NULL)
 		return (EOPNOTSUPP);
 
@@ -1228,25 +1231,11 @@
 struct ifnet *
 ifunit(const char *name)
 {
-	char namebuf[IFNAMSIZ + sizeof("net")];	/* XXX net_cdevsw.d_name */
 	struct ifnet *ifp;
-	dev_t dev;
-
-	/*
-	 * Now search all the interfaces for this name/number
-	 */
 
-	/*
-	 * XXX
-	 * Devices should really be known as /dev/fooN, not /dev/net/fooN.
-	 */
-	snprintf(namebuf, sizeof(namebuf), "%s/%s", net_cdevsw.d_name, name);
 	IFNET_RLOCK();
 	TAILQ_FOREACH(ifp, &ifnet, if_link) {
-		dev = ifdev_byindex(ifp->if_index);
-		if (strcmp(devtoname(dev), namebuf) == 0)
-			break;
-		if (dev_named(dev, name))
+		if (strncmp(name, ifp->if_xname, IFNAMSIZ) == 0)
 			break;
 	}
 	IFNET_RUNLOCK();
@@ -1289,6 +1278,10 @@
 	struct ifstat *ifs;
 	int error = 0;
 	int new_flags;
+	size_t namelen, onamelen;
+	char new_name[IFNAMSIZ];
+	struct ifaddr *ifa;
+	struct sockaddr_dl *sdl;
 
 	ifr = (struct ifreq *)data;
 	switch (cmd) {
@@ -1370,6 +1363,46 @@
 		error = mac_ioctl_ifnet_set(td->td_ucred, ifr, ifp);
 		break;
 #endif
+
+	case SIOCSIFNAME:
+		error = suser(td);
+		if (error)
+			return (error);
+		error = copyinstr(ifr->ifr_data, new_name, IFNAMSIZ, NULL);
+		if (error)
+			return (error);
+		if (ifunit(new_name) != NULL)
+			return (EEXIST);
+		
+		/* Announce the departure of the interface. */
+		rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
+
+		strlcpy(ifp->if_xname, new_name, sizeof(ifp->if_xname));
+		ifa = TAILQ_FIRST(&ifp->if_addrhead);
+		IFA_LOCK(ifa);
+		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;
+		IFA_UNLOCK(ifa);
+
+		/* Announce the return of the interface. */
+		rt_ifannouncemsg(ifp, IFAN_ARRIVAL);
+		break;
 
 	case SIOCSIFMETRIC:
 		error = suser(td);
--- ../cleanup/sys/sys/sockio.h	Fri Jan 23 09:38:05 2004
+++ sys/sys/sockio.h	Mon Dec  8 12:03:32 2003
@@ -82,6 +82,7 @@
 #define	SIOCGIFINDEX	_IOWR('i', 32, struct ifreq)	/* get IF index */
 #define	SIOCGIFMAC	_IOWR('i', 38, struct ifreq)	/* get IF MAC label */
 #define	SIOCSIFMAC	 _IOW('i', 39, struct ifreq)	/* set IF MAC label */
+#define	SIOCSIFNAME	 _IOW('i', 40, struct ifreq)	/* set IF name */
 
 #define	SIOCADDMULTI	 _IOW('i', 49, struct ifreq)	/* add m'cast addr */
 #define	SIOCDELMULTI	 _IOW('i', 50, struct ifreq)	/* del m'cast addr */

-- 
Any statement of the form "X is the one, true Y" is FALSE.
PGP fingerprint 655D 519C 26A7 82E7 2529  9BF0 5D8E 8BE9 F238 1AD4


More information about the freebsd-net mailing list