[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
kernel/2165: Network pseudo device cloning support
- To: gnats@openbsd.org
- Subject: kernel/2165: Network pseudo device cloning support
- From: Kyunghwan Kim <redjade@ada.snu.ac.kr>
- Date: Fri, 2 Nov 2001 18:33:27 +0900
- Resent-Date: Fri, 2 Nov 2001 02:40:03 -0700 (MST)
- Resent-From: gnats@cvs.openbsd.org (GNATS Management)
- Resent-Message-Id: <200111020940.fA29e3nX020979@cvs.openbsd.org>
- Resent-Reply-To: gnats@cvs.openbsd.org, redjade@ada.snu.ac.kr
- Resent-To: bugs@cvs.openbsd.org
>Number: 2165
>Category: kernel
>Synopsis: Network pseudo device cloning support
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: bugs
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Fri Nov 2 02:40:01 MST 2001
>Last-Modified:
>Originator: Kyunghwan Kim
>Organization:
net
>Release: -current
>Environment:
System : OpenBSD 3.0
Architecture: OpenBSD.i386
Machine : i386
>Description:
Network pseudo devices such as gif(4) and bridge(4) is configured
by config(8) and number of devices is static(unchangable) after
kernel linking. Even though it can be changed using config(8),
it also needs another reboot.
This allows network pseudo devices to be created and destroyed
on the fly via ifconfig(8) rather than specifying the count in the
kernel configuration.
This patch provides pseudo device cloning and ifconfig(8)
support and is heavily based on device cloning implementation
of NetBSD and FreeBSD.
>How-To-Repeat:
nothing to repeat.
>Fix:
apply patch below at /usr/src.
--- sys/sys/sockio.h.orig Fri Nov 2 11:26:19 2001
+++ sys/sys/sockio.h Fri Nov 2 16:34:29 2001
@@ -1,4 +1,4 @@
-/* $OpenBSD: sockio.h,v 1.18 2000/12/31 00:14:59 angelos Exp $ */
+/* $OpenBSD$ */
/* $NetBSD: sockio.h,v 1.5 1995/08/23 00:40:47 thorpej Exp $ */
/*-
@@ -134,6 +134,9 @@
#define GRESPROTO _IOW('i', 105, struct ifreq)
#define GREGPROTO _IOWR('i', 106, struct ifreq)
+#define SIOCIFCREATE _IOWR('i', 120, struct ifreq) /* create clone if */
+#define SIOCIFDESTROY _IOW('i', 121, struct ifreq) /* destory clone if */
+#define SIOCIFGCLONERS _IOWR('i', 122, struct if_clonereq) /* get cloners */
#define SIOCSIFMTU _IOW('i', 127, struct ifreq) /* set ifnet mtu */
#define SIOCGIFMTU _IOWR('i', 126, struct ifreq) /* get ifnet mtu */
#define SIOCSIFASYNCMAP _IOW('i', 125, struct ifreq) /* set ppp asyncmap */
--- sys/net/if.h.orig Wed Oct 31 15:03:30 2001
+++ sys/net/if.h Fri Nov 2 17:53:10 2001
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.h,v 1.30 2001/07/05 08:27:38 jjbg Exp $ */
+/* $OpenBSD$ */
/* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */
/*
@@ -423,6 +423,31 @@
char *if_name;
};
+/*
+ * Structure describing a `cloning' interface.
+ */
+struct if_clone {
+ LIST_ENTRY(if_clone) ifc_list; /* on list of cloners */
+ const char *ifc_name; /* name of device */
+ size_t ifc_namelen; /* length of name */
+
+ int (*ifc_create)(struct if_clone *, int);
+ void (*ifc_destroy)(struct ifnet *);
+};
+
+#define IF_CLONE_INITIALIZER(name, create, destroy) \
+ { { 0 }, name, sizeof(name) -1, create, destroy }
+
+/*
+ * Structure used to query names of interface cloners.
+ */
+
+struct if_clonereq {
+ int ifcr_total; /* total cloners (out) */
+ int ifcr_count; /* room for this many in user buffer */
+ char *ifcr_buffer; /* buffer for cloner names */
+};
+
#ifndef _KERNEL
__BEGIN_DECLS
unsigned int if_nametoindex __P((const char *));
@@ -576,6 +601,12 @@
struct ifaddr *ifaof_ifpforaddr __P((struct sockaddr *, struct ifnet *));
void ifafree __P((struct ifaddr *));
void link_rtrequest __P((int, struct rtentry *, struct rt_addrinfo *));
+
+void if_clone_attach __P((struct if_clone *));
+void if_clone_detach __P((struct if_clone *));
+
+int if_clone_create __P((char *));
+int if_clone_destroy __P((char *));
int loioctl __P((struct ifnet *, u_long, caddr_t));
void loopattach __P((int));
--- sys/net/if.c.orig Wed Oct 31 15:03:26 2001
+++ sys/net/if.c Fri Nov 2 17:57:15 2001
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.c,v 1.48 2001/06/27 05:50:06 kjc Exp $ */
+/* $OpenBSD$ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
@@ -126,6 +126,12 @@
extern void nd6_setmtu __P((struct ifnet *));
#endif
+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.
*
@@ -316,6 +322,153 @@
}
/*
+ * Create a clone network interface.
+ */
+int
+if_clone_create(name)
+ 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)
+ 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:
+ if (*cp == '\0') {
+ i = -1;
+ } else {
+ 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);
+}
+
+/*
* Detach an interface from everything in the kernel. Also deallocate
* private resources.
* XXX So far only the INET protocol family has been looked over
@@ -724,6 +877,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);
--- ifconfig.c.orig Fri Nov 2 14:18:13 2001
+++ ifconfig.c Fri Nov 2 18:27:20 2001
@@ -1,4 +1,4 @@
-/* $OpenBSD: ifconfig.c,v 1.52 2001/08/19 01:51:34 itojun Exp $ */
+/* $OpenBSD$ */
/* $NetBSD: ifconfig.c,v 1.40 1997/10/01 02:19:43 enami Exp $ */
/*
@@ -194,6 +194,8 @@
void unsetvlandev __P((char *, int));
void vlan_status ();
void fixnsel __P((struct sockaddr_iso *));
+void clone_create __P((const char *, int));
+void clone_destroy __P((const char *, int));
int main __P((int, char *[]));
int prefix __P((void *val, int));
@@ -274,6 +276,11 @@
{ "giftunnel", NEXTARG2, 0, settunnel } ,
{ "tunnel", NEXTARG2, 0, settunnel } ,
{ "deletetunnel", 0, 0, deletetunnel } ,
+#if 0
+ /* XXX `create' special-cased below */
+ { "create", 0, 0, clone_create },
+#endif
+ { "destroy", 0, 0, clone_destroy },
{ "link0", IFF_LINK0, 0, setifflags } ,
{ "-link0", -IFF_LINK0, 0, setifflags } ,
{ "link1", IFF_LINK1, 0, setifflags } ,
@@ -404,6 +411,18 @@
} else
(void) strlcpy(name, *argv, sizeof(name));
argc--, argv++;
+
+ /*
+ * NOTE: We must special-case the `create' command right
+ * here as we would otherwise fail in getinfo().
+ */
+ if (argc > 0 && strcmp(argv[0], "create") == 0) {
+ clone_create(argv[0], 0);
+ argc--, argv++;
+ if (argc == 0)
+ exit(0);
+ }
+
if (argc > 0) {
for (afp = rafp = afs; rafp->af_name; rafp++)
if (strcmp(rafp->af_name, *argv) == 0) {
@@ -2263,7 +2282,9 @@
"\t[ -802.2 | -802.3 | -802.2tr | -snap | -EtherII ]\n"
"\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ]\n"
" ifconfig [-a | -A | -am | -Am] [ af ]\n"
- " ifconfig -m interface [af]\n");
+ " ifconfig -m interface [af]\n"
+ " ifconfig interface create\n"
+ " ifconfig interface destroy\n");
exit(1);
}
@@ -2407,3 +2428,28 @@
return(result);
}
#endif
+
+void
+clone_destroy(addr, param)
+ const char *addr;
+ int param;
+{
+
+ (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ if (ioctl(s, SIOCIFDESTROY, (caddr_t)&ifr) < 0)
+ warn("SIOCIFDESTROY");
+}
+
+void
+clone_create(addr, param)
+ const char *addr;
+ int param;
+{
+
+ /* clone_create is called early */
+ getsock(AF_INET);
+
+ (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ if (ioctl(s, SIOCIFCREATE, (caddr_t)&ifr) < 0)
+ warn("SIOCIFCREATE");
+}
--- ifconfig.8.orig Fri Nov 2 14:18:20 2001
+++ ifconfig.8 Fri Nov 2 16:47:41 2001
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ifconfig.8,v 1.51 2001/05/02 06:44:23 itojun Exp $
+.\" $OpenBSD$
.\" $NetBSD: ifconfig.8,v 1.11 1996/01/04 21:27:29 pk Exp $
.\" $FreeBSD: ifconfig.8,v 1.16 1998/02/01 07:03:29 steve Exp $
.\"
@@ -75,6 +75,12 @@
.Nm ifconfig
.Op Fl A | Am
.Op Ar address_family
+.Nm ifconfig
+.Ar interface
+.Cm create
+.Nm ifconfig
+.Ar interface
+.Cm destroy
.Sh DESCRIPTION
The
.Nm
@@ -219,6 +225,10 @@
.It Cm deletetunnel
Removes the source and dsetination tunnel addresses,
configured onto a tunnel interface.
+.It Cm create
+Create the specified network pseudo-device.
+.It Cm destroy
+Destroy the specified network pseudo-device.
.It Cm ipdst
This is used to specify an Internet host who is willing to receive
ip packets encapsulating NS packets bound for a remote network.
>Audit-Trail:
>Unformatted: