summaryrefslogtreecommitdiffstats
path: root/sys/net/if.c
diff options
context:
space:
mode:
authorbrooks <brooks@FreeBSD.org>2004-02-04 02:54:25 +0000
committerbrooks <brooks@FreeBSD.org>2004-02-04 02:54:25 +0000
commit4f14e0fa867d5fae33d247bfe7a0aff6a2f9374e (patch)
treeee6c51c3f7bd6bcd7b451bee4727dbb4e812fd97 /sys/net/if.c
parentc78bcd05a81896c93001355e8619caa0f1fda74d (diff)
downloadFreeBSD-src-4f14e0fa867d5fae33d247bfe7a0aff6a2f9374e.zip
FreeBSD-src-4f14e0fa867d5fae33d247bfe7a0aff6a2f9374e.tar.gz
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>
Diffstat (limited to 'sys/net/if.c')
-rw-r--r--sys/net/if.c79
1 files changed, 56 insertions, 23 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index 8d68043..edec90f 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)
OpenPOWER on IntegriCloud