From 36c19a572a7209bdd31dc30151badb6a4973161c Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Wed, 4 Feb 2004 02:54:25 +0000 Subject: [PATCH] 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 Max Laier --- share/man/man9/ifnet.9 | 7 ++++ sys/net/if.c | 79 ++++++++++++++++++++++++++++++------------ sys/sys/sockio.h | 1 + 3 files changed, 64 insertions(+), 23 deletions(-) diff --git a/share/man/man9/ifnet.9 b/share/man/man9/ifnet.9 index 1ab4ec043e7e..be2a40b2014f 100644 --- a/share/man/man9/ifnet.9 +++ b/share/man/man9/ifnet.9 @@ -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 diff --git a/sys/net/if.c b/sys/net/if.c index 8d68043b43c9..edec90f227eb 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -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) diff --git a/sys/sys/sockio.h b/sys/sys/sockio.h index 93ec3ed61429..b2e07f53dbab 100644 --- a/sys/sys/sockio.h +++ b/sys/sys/sockio.h @@ -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 */