Source-Changes-HG archive

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

[src/netbsd-1-5]: src/sys/net Pull up revisions 1.63-1.64, 1.67 (requested by...



details:   https://anonhg.NetBSD.org/src/rev/c157be7c647d
branches:  netbsd-1-5
changeset: 490444:c157be7c647d
user:      jhawk <jhawk%NetBSD.org@localhost>
date:      Sun Dec 31 17:57:40 2000 +0000

description:
Pull up revisions 1.63-1.64, 1.67 (requested by bouyer):
  Support cloning of network pseudo-interfaces.

diffstat:

 sys/net/if.c |  165 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 164 insertions(+), 1 deletions(-)

diffs (193 lines):

diff -r cb1a656723dd -r c157be7c647d sys/net/if.c
--- a/sys/net/if.c      Sun Dec 31 17:57:36 2000 +0000
+++ b/sys/net/if.c      Sun Dec 31 17:57:40 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if.c,v 1.62.4.5 2000/10/07 23:09:44 itojun Exp $       */
+/*     $NetBSD: if.c,v 1.62.4.6 2000/12/31 17:57:40 jhawk Exp $        */
 
 /*-
  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@@ -150,6 +150,12 @@
 
 int    if_rt_walktree __P((struct radix_node *, void *));
 
+struct if_clone *if_clone_lookup __P((const char *, int *));
+int if_clone_list __P((struct if_clonereq *));
+
+LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
+int if_cloners_count;
+
 /*
  * Network interface utility routines.
  *
@@ -483,6 +489,149 @@
 }
 
 /*
+ * Create a clone network interface.
+ */
+int
+if_clone_create(name)
+       const char *name;
+{
+       struct if_clone *ifc;
+       int unit;
+
+       ifc = if_clone_lookup(name, &unit);
+       if (ifc == NULL)
+               return (EINVAL);
+
+       if (ifunit(name) != NULL)
+               return (EEXIST);
+
+       return ((*ifc->ifc_create)(ifc, unit));
+}
+
+/*
+ * Destroy a clone network interface.
+ */
+int
+if_clone_destroy(name)
+       const char *name;
+{
+       struct if_clone *ifc;
+       struct ifnet *ifp;
+
+       ifc = if_clone_lookup(name, NULL);
+       if (ifc == NULL)
+               return (EINVAL);
+
+       ifp = ifunit(name);
+       if (ifp == NULL)
+               return (ENXIO);
+
+       if (ifc->ifc_destroy == NULL)
+               return (EOPNOTSUPP);
+
+       (*ifc->ifc_destroy)(ifp);
+       return (0);
+}
+
+/*
+ * Look up a network interface cloner.
+ */
+struct if_clone *
+if_clone_lookup(name, unitp)
+       const char *name;
+       int *unitp;
+{
+       struct if_clone *ifc;
+       const char *cp;
+       int i;
+
+       for (ifc = LIST_FIRST(&if_cloners); ifc != NULL;) {
+               for (cp = name, i = 0; i < ifc->ifc_namelen; i++, cp++) {
+                       if (ifc->ifc_name[i] != *cp)
+                               goto next_ifc;
+               }
+               goto found_name;
+ next_ifc:
+               ifc = LIST_NEXT(ifc, ifc_list);
+       }
+
+       /* No match. */
+       return (NULL);
+
+ found_name:
+       for (i = 0; *cp != '\0'; cp++) {
+               if (*cp < '0' || *cp > '9') {
+                       /* Bogus unit number. */
+                       return (NULL);
+               }
+               i = (i * 10) + (*cp - '0');
+       }
+
+       if (unitp != NULL)
+               *unitp = i;
+       return (ifc);
+}
+
+/*
+ * Register a network interface cloner.
+ */
+void
+if_clone_attach(ifc)
+       struct if_clone *ifc;
+{
+
+       LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
+       if_cloners_count++;
+}
+
+/*
+ * Unregister a network interface cloner.
+ */
+void
+if_clone_detach(ifc)
+       struct if_clone *ifc;
+{
+
+       LIST_REMOVE(ifc, ifc_list);
+       if_cloners_count--;
+}
+
+/*
+ * Provide list of interface cloners to userspace.
+ */
+int
+if_clone_list(ifcr)
+       struct if_clonereq *ifcr;
+{
+       char outbuf[IFNAMSIZ], *dst;
+       struct if_clone *ifc;
+       int count, error = 0;
+
+       ifcr->ifcr_total = if_cloners_count;
+       if ((dst = ifcr->ifcr_buffer) == NULL) {
+               /* Just asking how many there are. */
+               return (0);
+       }
+
+       if (ifcr->ifcr_count < 0)
+               return (EINVAL);
+
+       count = (if_cloners_count < ifcr->ifcr_count) ?
+           if_cloners_count : ifcr->ifcr_count;
+
+       for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0;
+            ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) {
+               strncpy(outbuf, ifc->ifc_name, IFNAMSIZ);
+               outbuf[IFNAMSIZ - 1] = '\0';    /* sanity */
+               error = copyout(outbuf, dst, IFNAMSIZ);
+               if (error)
+                       break;
+       }
+
+       return (error);
+}
+
+/*
  * Locate an interface based on a complete address.
  */
 /*ARGSUSED*/
@@ -863,6 +1012,20 @@
                return (ifconf(cmd, data));
        }
        ifr = (struct ifreq *)data;
+
+       switch (cmd) {
+       case SIOCIFCREATE:
+       case SIOCIFDESTROY:
+               if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
+                       return (error);
+               return ((cmd == SIOCIFCREATE) ?
+                       if_clone_create(ifr->ifr_name) :
+                       if_clone_destroy(ifr->ifr_name));
+
+       case SIOCIFGCLONERS:
+               return (if_clone_list((struct if_clonereq *)data));
+       }
+
        ifp = ifunit(ifr->ifr_name);
        if (ifp == 0)
                return (ENXIO);



Home | Main Index | Thread Index | Old Index