tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Specifying names for tap interfaces



Darren Reed wrote:
On 30/06/2012 2:47 AM, Roger Pau Monné wrote:
...
For example being able to name Xen virtual interfaces in the
Dom0 with a user defined name, but I'm sure other users will come up with
other uses. What would you require for this functionality?
At the very last, being able to get the driver name and instance
number in a convenient way (e.g. in ifconfig output).
Ok, I will take a look at that, which I guess will require the
introduction of a new ioctl and a corresponding field in ifnet.
You could always find the original name in dmesg, since everytime
the name changes a line is printed, but I agree it might be
confusing and difficult if you perform a lot of renames.

Start with making the information available through drvctl
as part of the property list for the driver and don't worry
about ifconfig.

Darren

The attached patch adds a new ioctl to perform the rename and propagate that rename to the associated device_t and sysctl entries. Please review this patch and check that the use of the spls is correct. I also had to change a part of the code of bpf_setif in bpf.c to allow the use of interfaces that doesn't end with a number.
From 3e90ed906c3b93a92be302e76455a22940e56d6f Mon Sep 17 00:00:00 2001
From: Roger Pau Monne <roger.pau%citrix.com@localhost>
Date: Mon, 25 Jun 2012 14:58:32 +0100
Subject: [PATCH] net: add support to rename interfaces

Add a new ioctl "SIOCSIFNAME" to rename network interfaces and add
support for it in ifconfig.

The added ioctl changes the field if_xname and if_dl in the ifnet
structure, and propagates those changes to the associated sysctl
entries and device_t (if present), so drvctl works with the new name.

Signed-off-by: Roger Pau Monne <roger.pau%citrix.com@localhost>
---
 sbin/ifconfig/ifconfig.8 |    3 ++
 sbin/ifconfig/ifconfig.c |   31 +++++++++++++++++++-
 sys/net/bpf.c            |   38 +++++++++---------------
 sys/net/if.c             |   72 +++++++++++++++++++++++++++++++++++++++++++++-
 sys/sys/sockio.h         |    2 +
 5 files changed, 120 insertions(+), 26 deletions(-)

diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8
index aca1d72..0ec95d2 100644
--- a/sbin/ifconfig/ifconfig.8
+++ b/sbin/ifconfig/ifconfig.8
@@ -313,6 +313,9 @@ to the destination network or host.
 Set the maximum transmission unit of the interface to
 .Ar n .
 Most interfaces don't support this option.
+.It Cm name Ar name
+Set the interface name to
+.Ar name .
 .It Cm netmask Ar mask
 .Pq inet, inet6, and ISO
 Specify how much of the address to reserve for subdividing
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
index 1d49ca8..f06e0e8 100644
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -129,6 +129,7 @@ static int setifnetmask(prop_dictionary_t, 
prop_dictionary_t);
 static int setifprefixlen(prop_dictionary_t, prop_dictionary_t);
 static int setlinkstr(prop_dictionary_t, prop_dictionary_t);
 static int unsetlinkstr(prop_dictionary_t, prop_dictionary_t);
+static int setifname(prop_dictionary_t, prop_dictionary_t);
 static void status(const struct sockaddr *, prop_dictionary_t,
     prop_dictionary_t);
 __dead static void usage(void);
@@ -189,11 +190,15 @@ struct paddr parse_broadcast = 
PADDR_INITIALIZER(&parse_broadcast,
     "broadcast address",
     setifbroadaddr, "broadcast", NULL, NULL, NULL, &command_root.pb_parser);
 
+struct pstr name = PSTR_INITIALIZER1(&name, "name", setifname, "name",
+    false, &command_root.pb_parser);
+
 static const struct kwinst misckw[] = {
          {.k_word = "alias", .k_key = "alias", .k_deact = "alias",
           .k_type = KW_T_BOOL, .k_neg = true,
           .k_bool = true, .k_negbool = false,
           .k_nextparser = &command_root.pb_parser}
+       , {.k_word = "name", .k_nextparser = &name.ps_parser}
        , {.k_word = "broadcast", .k_nextparser = &parse_broadcast.pa_parser}
        , {.k_word = "delete", .k_key = "alias", .k_deact = "alias",
           .k_type = KW_T_BOOL, .k_bool = false,
@@ -1362,6 +1367,29 @@ unsetlinkstr(prop_dictionary_t env, prop_dictionary_t 
oenv)
        return 0;
 }
 
+static int
+setifname(prop_dictionary_t env, prop_dictionary_t oenv)
+{
+       const char *ifname;
+       char *newname;
+       prop_data_t data;
+
+       if ((ifname = getifname(env)) == NULL)
+               err(EXIT_FAILURE, "getifname");
+
+       data = (prop_data_t)prop_dictionary_get(env, "name");
+       assert(data != NULL);
+       newname = strndup(prop_data_data_nocopy(data), prop_data_size(data));
+
+       if (indirect_ioctl(env, SIOCSIFNAME, newname) == -1) {
+               free(newname);
+               err(EXIT_FAILURE, "SIOCSIFNAME");
+       }
+
+       free(newname);
+       return 0;
+}
+
 static void
 usage(void)
 {
@@ -1375,7 +1403,8 @@ usage(void)
        fprintf(stderr, "usage: %s [-h] %s[-v] [-z] %sinterface\n"
                "\t[ af [ address [ dest_addr ] ] [ netmask mask ] [ prefixlen 
n ]\n"
                "\t\t[ alias | -alias ] ]\n"
-               "\t[ up ] [ down ] [ metric n ] [ mtu n ]\n", progname,
+               "\t[ up ] [ down ] [ metric n ] [ mtu n ]\n"
+               "\t[ name new_name ]\n", progname,
                flag_is_registered(gflags, 'm') ? "[-m] " : "",
                flag_is_registered(gflags, 'L') ? "[-L] " : "");
 
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index 7d1bb8a..463c943 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -1100,30 +1100,20 @@ static int
 bpf_setif(struct bpf_d *d, struct ifreq *ifr)
 {
        struct bpf_if *bp;
-       char *cp;
-       int unit_seen, i, s, error;
-
-       /*
-        * Make sure the provided name has a unit number, and default
-        * it to '0' if not specified.
-        * XXX This is ugly ... do this differently?
-        */
-       unit_seen = 0;
-       cp = ifr->ifr_name;
-       cp[sizeof(ifr->ifr_name) - 1] = '\0';   /* sanity */
-       while (*cp++)
-               if (*cp >= '0' && *cp <= '9')
-                       unit_seen = 1;
-       if (!unit_seen) {
-               /* Make sure to leave room for the '\0'. */
-               for (i = 0; i < (IFNAMSIZ - 1); ++i) {
-                       if ((ifr->ifr_name[i] >= 'a' &&
-                            ifr->ifr_name[i] <= 'z') ||
-                           (ifr->ifr_name[i] >= 'A' &&
-                            ifr->ifr_name[i] <= 'Z'))
-                               continue;
-                       ifr->ifr_name[i] = '0';
-               }
+       int i, s, error;
+
+       /* Sanity check */
+       for (i = 0; i < IFNAMSIZ; ++i) {
+               if ((ifr->ifr_name[i] >= 'a' &&
+                    ifr->ifr_name[i] <= 'z') ||
+                   (ifr->ifr_name[i] >= 'A' &&
+                    ifr->ifr_name[i] <= 'Z') ||
+                   (ifr->ifr_name[i] >= '0' &&
+                    ifr->ifr_name[i] <= '9'))
+                       continue;
+               if (ifr->ifr_name[i] == '\0')
+                       break;
+               return EINVAL;
        }
 
        /*
diff --git a/sys/net/if.c b/sys/net/if.c
index f663954..05f5d71 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -113,6 +113,7 @@ __KERNEL_RCSID(0, "$NetBSD: if.c,v 1.260 2012/02/03 
03:35:30 christos Exp $");
 #include <sys/syslog.h>
 #include <sys/kauth.h>
 #include <sys/kmem.h>
+#include <sys/device.h>
 
 #include <net/if.h>
 #include <net/if_dl.h>
@@ -1498,10 +1499,16 @@ if_byindex(u_int idx)
 int
 ifioctl_common(struct ifnet *ifp, u_long cmd, void *data)
 {
-       int s;
+       int s, error, i;
        struct ifreq *ifr;
        struct ifcapreq *ifcr;
        struct ifdatareq *ifdr;
+       char new_name[IFNAMSIZ];
+       struct ifaddr *ifa;
+       struct sockaddr_dl *sdl;
+       size_t namelen, onamelen;
+       device_t dv;
+       device_lock_t dvl;
 
        switch (cmd) {
        case SIOCSIFCAP:
@@ -1627,6 +1634,69 @@ ifioctl_common(struct ifnet *ifp, u_long cmd, void *data)
                nd6_setmtu(ifp);
 #endif
                return ENETRESET;
+       case SIOCSIFNAME:
+               ifr = data;
+               error = copyinstr(ifr->ifr_data, new_name, IFNAMSIZ, NULL);
+               if (error)
+                       return error;
+
+               /* Sanity check */
+               if (new_name[0] == '\0')
+                       return EINVAL;
+               for (i = 0; i < IFNAMSIZ; ++i) {
+                       if ((new_name[i] >= 'a' &&
+                            new_name[i] <= 'z') ||
+                           (new_name[i] >= 'A' &&
+                            new_name[i] <= 'Z') ||
+                           (new_name[i] >= '0' &&
+                            new_name[i] <= '9'))
+                               continue;
+                       if (new_name[i] == '\0')
+                               break;
+                       return EINVAL;
+               }
+               if (ifunit(new_name) != NULL)
+                       return EEXIST;
+
+               log(LOG_INFO, "renaming interface %s to %s\n",
+                             ifp->if_xname, new_name);
+
+               /* Change the name of the related device_t */
+               dv = device_find_by_xname(ifp->if_xname);
+               if (dv) {
+                       dvl = device_getlock(dv);
+                       mutex_enter(&dvl->dvl_mtx);
+                       strncpy(dv->dv_xname, new_name, IFNAMSIZ);
+                       mutex_exit(&dvl->dvl_mtx);
+               }
+
+               /* Change name in ifnet */
+               s = splnet();
+               strncpy(ifp->if_xname, new_name, IFNAMSIZ);
+               ifa = ifp->if_dl;
+               sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+               namelen = strlen(new_name);
+               onamelen = sdl->sdl_nlen;
+
+               if (namelen != onamelen) {
+                       memmove(&sdl->sdl_data[namelen],
+                               &sdl->sdl_data[onamelen], sdl->sdl_alen);
+               }
+               bcopy(new_name, &sdl->sdl_data[0], namelen);
+               sdl->sdl_nlen = namelen;
+               sdl->sdl_len = sockaddr_dl_measure(sdl->sdl_nlen, 
sdl->sdl_alen);
+
+               sdl = (struct sockaddr_dl *)ifa->ifa_netmask;
+               bzero(sdl->sdl_data, onamelen);
+               while (namelen != 0)
+                       sdl->sdl_data[--namelen] = 0xff;
+               splx(s);
+
+               /* Change sysctl entries */
+               sysctl_teardown(&ifp->if_sysctl_log);
+               sysctl_sndq_setup(&ifp->if_sysctl_log, ifp->if_xname, 
&ifp->if_snd);
+
+               break;
        default:
                return ENOTTY;
        }
diff --git a/sys/sys/sockio.h b/sys/sys/sockio.h
index 3e97c9f..cdd231d 100644
--- a/sys/sys/sockio.h
+++ b/sys/sys/sockio.h
@@ -132,6 +132,8 @@
 #define SIOCGLINKSTR   _IOWR('i', 135, struct ifdrv)
 #define SIOCSLINKSTR    _IOW('i', 136, struct ifdrv)
 
+#define SIOCSIFNAME     _IOW('i', 137, struct ifreq) /* change IF name */
+
 #define        SIOCSETPFSYNC   _IOW('i', 247, struct ifreq)    
 #define        SIOCGETPFSYNC   _IOWR('i', 248, struct ifreq)
 
-- 
1.7.7.5 (Apple Git-26)



Home | Main Index | Thread Index | Old Index