Add the kernel side of network interface renaming support.

The basic process is to send a routing socket announcement that the
interface has departed, change if_xname, update the sockaddr_dl
associated with the interface, and announce the arrival of the interface
on the routing socket.

As part of this change, ifunit() is greatly simplified by testing
if_xname directly.  if_clone_destroy() now uses if_dname to look up the
cloner for the interface and if_dunit to identify the unit number.

Reviewed by:	ru, sam (concept)
		Vincent Jardin <vjardin AT free.fr>
		Max Laier <max AT love2party.net>
This commit is contained in:
brooks 2004-02-04 02:54:25 +00:00
parent c78bcd05a8
commit 4f14e0fa86
3 changed files with 64 additions and 23 deletions

View File

@ -961,6 +961,13 @@ The following commands are handled by
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

View File

@ -410,7 +410,11 @@ if_attach(struct ifnet *ifp)
* 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;
if (socksize < sizeof(*sdl))
socksize = sizeof(*sdl);
@ -731,17 +735,16 @@ if_clone_destroy(const char *name)
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);
@ -1226,25 +1229,11 @@ if_slowtimo(void *arg)
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();
@ -1287,6 +1276,10 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
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) {
@ -1369,6 +1362,46 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
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);
if (error)

View File

@ -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 */