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:
parent
c78bcd05a8
commit
4f14e0fa86
@ -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
|
||||
|
79
sys/net/if.c
79
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)
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user