NetBSD-Bugs archive

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

kern/46633: create network cloned devices without specifying a unit



>Number:         46633
>Category:       kern
>Synopsis:       create clone network interface without unit
>Confidential:   yes
>Severity:       non-critical
>Priority:       low
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Wed Jun 27 11:45:00 +0000 2012
>Originator:     Darren Reed
>Release:        NetBSD 5.99.59
>Organization:
NetBSD
>Environment:
>Description:
The ifconfig command currently requires that network devices that support
cloning be created by specifying the unit number when ifconfig is run.
This requires the caller of ifconfig to have somehow decided that the
unit number to be used to have already been allocated. This change removes
that need.

Whereas in the past a script was required to create an interface
like this:

# ifconfig gif0 create

the following will now work:

# ifconfig gif create
gif0
>How-To-Repeat:
Create a cloned network interface.
>Fix:
--- usr/src/sys/net/if.h.dist   2011-10-26 10:00:24.000000000 +0200
+++ usr/src/sys/net/if.h        2012-06-27 12:53:11.000000000 +0200
@@ -905,7 +905,7 @@
 void   if_clone_attach(struct if_clone *);
 void   if_clone_detach(struct if_clone *);
 
-int    if_clone_create(const char *);
+int    if_clone_create(const char *, char *, int);
 int    if_clone_destroy(const char *);
 
 int    ifq_enqueue(struct ifnet *, struct mbuf * ALTQ_COMMA
--- usr/src/sys/net/if.c.dist   2011-11-27 22:42:44.000000000 +0100
+++ usr/src/sys/net/if.c        2012-06-27 13:27:36.000000000 +0200
@@ -154,6 +154,7 @@
 
 static int     if_rt_walktree(struct rtentry *, void *);
 
+static struct if_clone *if_clone_find(const char *, const int);
 static struct if_clone *if_clone_lookup(const char *, int *);
 static int     if_clone_list(struct if_clonereq *);
 
@@ -927,15 +928,52 @@
        return ERESTART;
 }
 
+static struct if_clone *
+if_clone_find(const char *name, const int len)
+{
+       struct if_clone *ifc;
+
+       LIST_FOREACH(ifc, &if_cloners, ifc_list) {
+               if (strlen(ifc->ifc_name) == len &&
+                   strncmp(name, ifc->ifc_name, len) == 0)
+                       return ifc;
+       }
+
+       return NULL;
+}
+
 /*
  * Create a clone network interface.
  */
 int
-if_clone_create(const char *name)
+if_clone_create(const char *name, char *newname, int dynamic)
 {
+       char buffer[IFNAMSIZ];
        struct if_clone *ifc;
        int unit;
 
+       if (dynamic == 1) {
+               /*
+                * If "name" is the name of a device that supports cloning
+                * and thus excludes a unit number and the dynamic flag is
+                * set then attempt to allocate a unit number, construct
+                * the name for the new device and return it in newname.
+                * The assumption is newname is at least IFNAMSIZ in length.
+                */
+               ifc = if_clone_find(name, strlen(name));
+               if (newname != NULL && ifc != NULL) {
+                       for (unit = 0; unit < INT_MAX / 10; unit++) {
+                               snprintf(buffer, IFNAMSIZ, "%s%d",
+                                   name, unit);
+                               if (ifunit(buffer) == NULL) {
+                                       strlcpy(newname, buffer, IFNAMSIZ);
+                                       return (*ifc->ifc_create)(ifc, unit);
+                               }
+                       }
+                       return EINVAL;
+               }
+       }
+
        ifc = if_clone_lookup(name, &unit);
        if (ifc == NULL)
                return EINVAL;
@@ -988,12 +1026,7 @@
        if (cp == name || cp - name == IFNAMSIZ || !*cp)
                return NULL;    /* No name or unit number */
 
-       LIST_FOREACH(ifc, &if_cloners, ifc_list) {
-               if (strlen(ifc->ifc_name) == cp - name &&
-                   strncmp(name, ifc->ifc_name, cp - name) == 0)
-                       break;
-       }
-
+       ifc = if_clone_find(name, cp - name);
        if (ifc == NULL)
                return NULL;
 
@@ -1776,6 +1809,7 @@
 
        switch (cmd) {
        case SIOCIFCREATE:
+       case OSIOCIFCREATE:
        case SIOCIFDESTROY:
                if (l != NULL) {
                        error = kauth_authorize_network(l->l_cred,
@@ -1785,9 +1819,11 @@
                        if (error != 0)
                                return error;
                }
-               return (cmd == SIOCIFCREATE) ?
-                       if_clone_create(ifr->ifr_name) :
-                       if_clone_destroy(ifr->ifr_name);
+               if (cmd == OSIOCIFCREATE)
+                       return if_clone_create(ifr->ifr_name, NULL, 0);
+               if (cmd == SIOCIFDESTROY)
+                       return if_clone_destroy(ifr->ifr_name);
+               return if_clone_create(ifr->ifr_name, ifr->ifr_name, 1);
 
        case SIOCIFGCLONERS:
                return if_clone_list((struct if_clonereq *)data);
--- usr/src/sbin/ifconfig/util.c.dist   2010-12-14 08:52:22.000000000 +0100
+++ usr/src/sbin/ifconfig/util.c        2012-06-27 13:20:59.000000000 +0200
@@ -230,13 +230,19 @@
 int
 indirect_ioctl(prop_dictionary_t env, unsigned long cmd, void *data)
 {
+       struct ifreq oifr;
        struct ifreq ifr;
+       int error;
 
        memset(&ifr, 0, sizeof(ifr));
 
        ifr.ifr_data = data;
+       oifr = ifr;
 
-       return direct_ioctl(env, cmd, &ifr);
+       error = direct_ioctl(env, cmd, &ifr);
+       if (error == 0 && strncmp(ifr.ifr_name, oifr.ifr_name, IFNAMSIZ))
+               printf("%s\n", ifr.ifr_name);
+       return error;
 }
 
 void
--- usr/src/sbin/ifconfig/ifconfig.8.dist       2012-06-27 13:42:23.000000000 
+0200
+++ usr/src/sbin/ifconfig/ifconfig.8    2012-06-27 13:42:15.000000000 +0200
@@ -530,7 +530,9 @@
 interfaces previously configured with
 .Cm tunnel .
 .It Cm create
-Create the specified network pseudo-device.
+Create the specified network pseudo-device. When used without a unit
+number for the network interface, the kernel will allocate a unit and
+the full interface name is printed on stdout before the program exits.
 .It Cm destroy
 Destroy the specified network pseudo-device.
 .It Cm pltime Ar n



Home | Main Index | Thread Index | Old Index