|
|||||||||||
|
kernel/2870: support for network pseudo device cloning
From: <logix(at)foobar.franken.de>
Date: Fri Aug 09 2002 - 19:13:20 EDT >Number: 2870 >Category: kernel >Synopsis: support for network pseudo device cloning >Confidential: no >Severity: non-critical >Priority: low >Responsible: bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: net >Arrival-Date: Thu Nov 07 13:11:15 MST 2002 >Closed-Date: >Last-Modified: >Originator: Harold Gutch >Release: any >Organization: net >Environment: System : OpenBSD 3.0 Architecture: OpenBSD.i386 Machine : i386 >Description: OpenBSD does not support network pseudo device cloning (runtime allocating of gif(4)-devices and such). >How-To-Repeat: - >Fix: Apply the patch below, recompile ifconfig and recompile (and install) your kernel. "ifconfig gifX create" (with X being a number) will from then on create a new gif(4)-device, and "ifconfig gifX destroy" will remove it. Note: This is based on PR 2165; the patch attached to that PR was incomplete though and did therefore not work. --- usr/include/sys/sockio.h.orig Sat Aug 10 02:48:15 2002 +++ usr/include/sys/sockio.h Sat Aug 10 02:48:22 2002
/*-
#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 */
--- usr/src/sys/sys/sockio.h.orig Sat Aug 10 02:48:16 2002
+++ usr/src/sys/sys/sockio.h Sat Aug 10 02:48:22 2002
/*-
#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 */
--- usr/src/sys/net/if.h.orig Sat Aug 10 02:48:17 2002
+++ usr/src/sys/net/if.h Sat Aug 10 02:48:22 2002
/*
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)); --- usr/src/sys/net/if.c.orig Sat Aug 10 02:48:17 2002 +++ usr/src/sys/net/if.c Sat Aug 10 02:48:22 2002
/*
+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; + /*
/*
+ * 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 @@ -66,6 +66,16 @@ int ngif; void gifattach __P((int));
+LIST_HEAD(, gif_softc) gif_softc_list;
+
+int gif_clone_create __P((struct if_clone *, int));
+void gif_clone_destroy __P((struct ifnet *));
+
+struct if_clone gif_cloner =
+ IF_CLONE_INITIALIZER("gif", gif_clone_create, gif_clone_destroy);
+
+void gif_delete_tunnel __P((struct gif_softc *));
+
/*
#if NBPFILTER > 0
- bpfattach(&sc->gif_if.if_bpf, &sc->gif_if, DLT_NULL,
- sizeof(u_int));
+ bpfattach(&sc->gif_if.if_bpf, &sc->gif_if, DLT_NULL, sizeof(u_int));
#endif
- }
+ LIST_INSERT_HEAD(&gif_softc_list, sc, gif_list);
+ return (0);
+}
+
+void
+gif_clone_destroy(ifp)
+ struct ifnet *ifp;
+{
+ struct gif_softc *sc = (void *) ifp;
+
+ gif_delete_tunnel(sc);
+ LIST_REMOVE(sc, gif_list);
+
+#if NBPFILTER > 0
+ bpfdetach(ifp);
+#endif
+ if_detach(ifp);
+
+ free(sc, M_DEVBUF);
}
void
int error = 0, size; struct sockaddr *dst, *src; struct sockaddr *sa; - int i; int s; struct gif_softc *sc2; @@ -415,15 +448,7 @@ #ifdef SIOCDIFPHYADDR
case SIOCDIFPHYADDR:
- if (sc->gif_psrc) {
- free((caddr_t)sc->gif_psrc, M_IFADDR);
- sc->gif_psrc = NULL;
- }
- if (sc->gif_pdst) {
- free((caddr_t)sc->gif_pdst, M_IFADDR);
- sc->gif_pdst = NULL;
- }
- /* change the IFF_{UP, RUNNING} flag as well? */
+ gif_delete_tunnel(sc);
break;
#endif
@@ -526,4 +551,25 @@
}
return error; +} + +void +gif_delete_tunnel(sc) + struct gif_softc *sc; +{ + int s; + + s = splsoftnet(); + + if (sc->gif_psrc) { + free((caddr_t)sc->gif_psrc, M_IFADDR); + sc->gif_psrc = NULL; + } + if (sc->gif_pdst) { + free((caddr_t)sc->gif_pdst, M_IFADDR); + sc->gif_pdst = NULL; + } + /* change the IFF_UP flag as well? */ + + splx(s); } --- usr/src/sys/net/if_gif.h.orig Sat Aug 10 02:48:18 2002 +++ usr/src/sys/net/if_gif.h Sat Aug 10 02:48:22 2002 @@ -37,7 +37,7 @@ #ifndef _NET_IF_GIF_H_ #define _NET_IF_GIF_H_
-
@@ -52,6 +52,9 @@
} gifsc_gifscr; int gif_flags; + const struct encaptab *encap_cookie4; + const struct encaptab *encap_cookie6; + LIST_ENTRY(gif_softc) gif_list; /* list of all gifs */}; #define gif_ro gifsc_gifscr.gifscr_ro --- usr/src/sys/netinet/in_gif.c.orig Sat Aug 10 02:48:18 2002 +++ usr/src/sys/netinet/in_gif.c Sat Aug 10 02:48:50 2002 @@ -61,6 +61,8 @@ #include "gif.h" #include "bridge.h"
+extern LIST_HEAD(, gif_softc) gif_softc_list;
+
struct ifnet *ifp;
struct gif_softc *sc; struct ifnet *gifp = NULL; struct ip *ip; - int i; va_list ap; va_start(ap, m); @@ -197,7 +198,7 @@
/* this code will be soon improved. */
#define satosin(sa) ((struct sockaddr_in *)(sa))
- for (i = 0, sc = gif_softc; i < ngif; i++, sc++) {
+ for (sc = LIST_FIRST(&gif_softc_list); sc != NULL; sc = LIST_NEXT(sc, gif_list)) {
if (sc->gif_psrc == NULL
|| sc->gif_pdst == NULL
|| sc->gif_psrc->sa_family != AF_INET
--- usr/src/sys/netinet/ip_ether.c.orig Sat Aug 10 02:48:19 2002
+++ usr/src/sys/netinet/ip_ether.c Sat Aug 10 02:48:22 2002
@@ -64,6 +64,7 @@ */ int etherip_allow = 0; +extern LIST_HEAD(, gif_softc) gif_softc_list; struct etheripstat etheripstat;
/*
va_list ap; #if NGIF > 0 - int i; + struct gif_softc *sc; #if NBRIDGE > 0 int s; #endif /* NBRIDGE */ @@ -227,20 +228,20 @@ #if NGIF > 0
/* Find appropriate gif(4) interface */
- for (i = 0; i < ngif; i++) {
- if ((gif_softc[i].gif_psrc == NULL) ||
- (gif_softc[i].gif_pdst == NULL) ||
- !(gif_softc[i].gif_if.if_flags & (IFF_UP|IFF_RUNNING)))
+ for (sc = LIST_FIRST(&gif_softc_list); sc != NULL; sc = LIST_NEXT(sc, gif_list)) {
+ if ((sc->gif_psrc == NULL) ||
+ (sc->gif_pdst == NULL) ||
+ !(sc->gif_if.if_flags & (IFF_UP|IFF_RUNNING)))
continue;
- if (!bcmp(gif_softc[i].gif_psrc, &sdst, gif_softc[i].gif_psrc->sa_len) &&
- !bcmp(gif_softc[i].gif_pdst, &ssrc, gif_softc[i].gif_pdst->sa_len) &&
- gif_softc[i].gif_if.if_bridge != NULL)
+ if (!bcmp(sc->gif_psrc, &sdst, sc->gif_psrc->sa_len) &&
+ !bcmp(sc->gif_pdst, &ssrc, sc->gif_pdst->sa_len) &&
+ sc->gif_if.if_bridge != NULL)
break;
}
/* None found. */
- if (i >= ngif) {
+ if (NULL == sc) {
DPRINTF(("etherip_input(): no interface found\n"));
etheripstat.etherip_noifdrops++;
m_freem(m);
/*
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)); }
@@ -2408,3 +2429,28 @@
return(result);
+
+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");
+}
--- usr/src/sbin/ifconfig/ifconfig.8.orig Sat Aug 10 02:48:20 2002
+++ usr/src/sbin/ifconfig/ifconfig.8 Sat Aug 10 02:48:22 2002
.\"
@@ -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. >Release-Note: >Audit-Trail: >Unformatted:Received on Thu Nov 7 15:28:44 2002 This archive was generated by hypermail 2.1.8 : Wed Aug 23 2006 - 13:29:36 EDT |
||||||||||
|
|||||||||||