diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2009-11-09 03:16:08 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2009-11-09 03:16:08 +0000 |
commit | 6bf19b59d85f2b154aa58aecabda602efd0f838b (patch) | |
tree | 45cade4c520278c0524d7bd5f8225c634afea6cf | |
parent | ad0592d657a970d3b3d8200773732a354fad0461 (diff) |
vether(4) is a virtual ethernet device driver which can be used
so that a bridge-etherip-tunnel host can join into the bridge itself.
It is ridiculous that this capability was missing from our network
stack portfolio, considering we have bgp and ospf daemons...
discussed at length with claudio
-rw-r--r-- | share/man/man4/Makefile | 4 | ||||
-rw-r--r-- | share/man/man4/bridge.4 | 5 | ||||
-rw-r--r-- | share/man/man4/vether.4 | 56 | ||||
-rw-r--r-- | sys/conf/GENERIC | 3 | ||||
-rw-r--r-- | sys/conf/files | 4 | ||||
-rw-r--r-- | sys/net/if_bridge.c | 10 | ||||
-rw-r--r-- | sys/net/if_vether.c | 232 |
7 files changed, 307 insertions, 7 deletions
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 52dbab72585..11937c8c1e4 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.494 2009/10/27 11:27:37 dlg Exp $ +# $OpenBSD: Makefile,v 1.495 2009/11/09 03:16:07 deraadt Exp $ MAN= aac.4 ac97.4 acphy.4 \ acpi.4 acpiac.4 acpiasus.4 acpibat.4 acpibtn.4 acpicpu.4 acpidock.4 \ @@ -57,7 +57,7 @@ MAN= aac.4 ac97.4 acphy.4 \ ukphy.4 ulpt.4 umass.4 umbg.4 umct.4 umidi.4 umodem.4 ums.4 umsm.4 \ unix.4 uow.4 upgt.4 upl.4 uplcom.4 ural.4 urio.4 url.4 urlphy.4 \ urtw.4 usb.4 usbf.4 uscanner.4 uslcom.4 usscanner.4 uticom.4 uts.4 \ - uts.4 uvideo.4 uvisor.4 uvscom.4 uyap.4 vga.4 vgafb.4 vge.4 \ + uts.4 uvideo.4 uvisor.4 uvscom.4 uyap.4 vether.4 vga.4 vgafb.4 vge.4 \ viaenv.4 viapm.4 viasio.4 vic.4 video.4 vlan.4 vmt.4 vnd.4 vr.4 \ vscsi.4 \ watchdog.4 wb.4 wbenv.4 wbng.4 wbsd.4 wbsio.4 wd.4 wdc.4 we.4 \ diff --git a/share/man/man4/bridge.4 b/share/man/man4/bridge.4 index 58a190f6513..8aef2d206d3 100644 --- a/share/man/man4/bridge.4 +++ b/share/man/man4/bridge.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: bridge.4,v 1.66 2007/10/03 20:15:06 sthen Exp $ +.\" $OpenBSD: bridge.4,v 1.67 2009/11/09 03:16:07 deraadt Exp $ .\" .\" Copyright (c) 1999-2001 Jason L. Wright (jason@thought.net) .\" All rights reserved. @@ -24,7 +24,7 @@ .\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: October 3 2007 $ +.Dd $Mdocdate: November 9 2009 $ .Dt BRIDGE 4 .Os .Sh NAME @@ -622,6 +622,7 @@ and certificates, to impersonate the protected host(s)). .Xr ipsec 4 , .Xr netintro 4 , .Xr pf 4 , +.Xr vether 4 , .Xr bridgename.if 5 , .Xr brconfig 8 , .Xr ipsecctl 8 , diff --git a/share/man/man4/vether.4 b/share/man/man4/vether.4 new file mode 100644 index 00000000000..bec14e64d11 --- /dev/null +++ b/share/man/man4/vether.4 @@ -0,0 +1,56 @@ +.\" $OpenBSD: vether.4,v 1.1 2009/11/09 03:16:07 deraadt Exp $ +.\" +.\" Copyright (c) 2009 Theo de Raadt <deraadt@openbsd.org> +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate: November 9 2009 $ +.Dt VETHER 4 +.Os +.Sh NAME +.Nm vether +.Nd Virtual Ethernet interface +.Sh SYNOPSIS +.Cd "pseudo-device vether" +.Sh DESCRIPTION +The +.Nm +interface simulates a normal Ethernet interface by encapsulating +standard network frames with an Ethernet header, specifically +for use as a member in a +.Xr bridge 4 . +.Pp +To use +.Nm +the administrator needs to configure an address onto the interface +so that packets can be routed to it. +An Ethernet header will be prepended and, if the +.Nm +interface is a member of a +.Xr bridge , +the frame will show up there. +.Sh SEE ALSO +.Xr bridge 4 , +.Xr inet 4 , +.Xr inet6 4 , +.Xr hostname.if 5 , +.Xr ifconfig 8 , +.Xr netstart 8 +.Sh BUGS +Like +.Xr tun 4 , +the Ethernet address chosen will be partially random, and may +occasionally collide with another address. +.Pp +There are problems with +.Xr bpf 4 . diff --git a/sys/conf/GENERIC b/sys/conf/GENERIC index a742bf29569..5f6103acf33 100644 --- a/sys/conf/GENERIC +++ b/sys/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.149 2009/08/26 00:37:17 thib Exp $ +# $OpenBSD: GENERIC,v 1.150 2009/11/09 03:16:07 deraadt Exp $ # # Machine-independent option; used by all architectures for their # GENERIC kernel @@ -105,6 +105,7 @@ pseudo-device sl # CSLIP pseudo-device tun # network tunneling over tty pseudo-device vlan # IEEE 802.1Q VLAN pseudo-device trunk # Trunking support +pseudo-device vether # Virtual ethernet # for IPv6 #pseudo-device faith 1 # IPv[46] tcp relay translation i/f diff --git a/sys/conf/files b/sys/conf/files index d2fe3fbd3b4..b33ce9b7075 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $OpenBSD: files,v 1.480 2009/11/05 20:50:14 michele Exp $ +# $OpenBSD: files,v 1.481 2009/11/09 03:16:07 deraadt Exp $ # $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -507,6 +507,7 @@ pseudo-device gre: ifnet pseudo-device crypto: ifnet pseudo-device trunk: ifnet, ether, ifmedia pseudo-device mpe: ifnet, ether +pseudo-device vether: ifnet, ether pseudo-device sequencer pseudo-device systrace @@ -814,6 +815,7 @@ file net/if_gre.c gre needs-count file net/if_trunk.c trunk needs-count file net/trunklacp.c trunk file net/if_mpe.c mpe needs-count +file net/if_vether.c vether needs-count file net/if_aoe.c ether & aoe file net80211/ieee80211.c wlan file net80211/ieee80211_amrr.c wlan diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 1d14ec1c3c9..50fcbbb673b 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bridge.c,v 1.174 2009/01/06 21:23:18 claudio Exp $ */ +/* $OpenBSD: if_bridge.c,v 1.175 2009/11/09 03:16:05 deraadt Exp $ */ /* * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) @@ -2766,6 +2766,9 @@ bridge_fragment(struct bridge_softc *sc, struct ifnet *ifp, int bridge_ifenqueue(struct bridge_softc *sc, struct ifnet *ifp, struct mbuf *m) { +#if VETHER > 0 + extern void vetherstart(struct ifnet *); +#endif int error, len; short mflags; @@ -2774,6 +2777,11 @@ bridge_ifenqueue(struct bridge_softc *sc, struct ifnet *ifp, struct mbuf *m) if (ifp->if_type == IFT_GIF) m->m_flags |= M_PROTO1; #endif +#if VETHER > 0 + /* Indicate packets which are outbound */ + if (ifp->if_start == vetherstart) + m->m_flags |= M_PROTO1; +#endif #if NVLAN > 0 /* * If the underlying interface cannot do VLAN tag insertion itself, diff --git a/sys/net/if_vether.c b/sys/net/if_vether.c new file mode 100644 index 00000000000..b681b5f39fd --- /dev/null +++ b/sys/net/if_vether.c @@ -0,0 +1,232 @@ +/* $OpenBSD: if_vether.c,v 1.1 2009/11/09 03:16:05 deraadt Exp $ */ + +/* + * Copyright (c) 2009 Theo de Raadt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "vether.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/proc.h> +#include <sys/socket.h> +#include <sys/sockio.h> +#include <sys/ioctl.h> + +#include <net/if.h> +#include <net/if_dl.h> +#include <net/if_media.h> +#include <net/if_types.h> + +#include <net/if_types.h> +#include <net/netisr.h> +#include <net/route.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/if_ether.h> +#include <netinet/in_var.h> +#endif + +#include <dev/rndvar.h> + +#include "bpfilter.h" +#if NBPFILTER > 0 +#include <net/bpf.h> +#endif + +#ifdef MPLS_DEBUG +#define DPRINTF(x) do { if (vetherdebug) printf x ; } while (0) +#else +#define DPRINTF(x) +#endif + +void vetherattach(int); +int vetherioctl(struct ifnet *, u_long, caddr_t); +void vetherstart(struct ifnet *); +int vether_clone_create(struct if_clone *, int); +int vether_clone_destroy(struct ifnet *); +int vether_media_change(struct ifnet *); +void vether_media_status(struct ifnet *, struct ifmediareq *); + +struct vether_softc { + struct arpcom sc_ac; + struct ifmedia sc_media; + LIST_ENTRY(vether_softc) sc_list; +}; + +LIST_HEAD(, vether_softc) vether_list; +struct if_clone vether_cloner = + IF_CLONE_INITIALIZER("vether", vether_clone_create, vether_clone_destroy); + + +int +vether_media_change(struct ifnet *ifp) +{ + return (0); +} + +void +vether_media_status(struct ifnet *ifp, struct ifmediareq *imr) +{ + imr->ifm_active = IFM_ETHER | IFM_AUTO; + imr->ifm_status = IFM_AVALID | IFM_ACTIVE; +} + +void +vetherattach(int nvether) +{ + LIST_INIT(&vether_list); + if_clone_attach(&vether_cloner); +} + +int +vether_clone_create(struct if_clone *ifc, int unit) +{ + struct ifnet *ifp; + struct vether_softc *sc; + u_int32_t macaddr_rnd; + int s; + + if ((sc = malloc(sizeof(*sc), + M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) + return (ENOMEM); + + /* from if_tun.c: generate fake MAC address: 00 bd xx xx xx unit_no */ + sc->sc_ac.ac_enaddr[0] = 0x00; + sc->sc_ac.ac_enaddr[1] = 0xbd; + /* + * This no longer happens pre-scheduler so let's use the real + * random subsystem instead of random(). + */ + macaddr_rnd = arc4random(); + bcopy(&macaddr_rnd, &sc->sc_ac.ac_enaddr[2], sizeof(u_int32_t)); + sc->sc_ac.ac_enaddr[5] = (u_char)unit + 1; + + ifp = &sc->sc_ac.ac_if; + snprintf(ifp->if_xname, sizeof ifp->if_xname, "vether%d", unit); + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_softc = sc; + ifp->if_ioctl = vetherioctl; + ifp->if_start = vetherstart; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + IFQ_SET_READY(&ifp->if_snd); + + ifmedia_init(&sc->sc_media, 0, vether_media_change, + vether_media_status); + ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL); + ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO); + + if_attach(ifp); + ether_ifattach(ifp); + + s = splnet(); + LIST_INSERT_HEAD(&vether_list, sc, sc_list); + splx(s); + return (0); +} + +int +vether_clone_destroy(struct ifnet *ifp) +{ + struct vether_softc *sc = ifp->if_softc; + int s; + + s = splnet(); + LIST_REMOVE(sc, sc_list); + splx(s); + + ether_ifdetach(ifp); + if_detach(ifp); + free(sc, M_DEVBUF); + return (0); +} + +/* + * Start output on the vether interface. + */ +void +vetherstart(struct ifnet *ifp) +{ + struct mbuf *m; + int s, inout; + + for (;;) { + s = splnet(); + IFQ_DEQUEUE(&ifp->if_snd, m); + splx(s); + + if (m == NULL) + return; + + inout = (m->m_flags & M_PROTO1) ? + BPF_DIRECTION_IN : BPF_DIRECTION_OUT; + m->m_flags &= ~M_PROTO1; + +#if NBPFILTER > 0 + if (ifp->if_bpf) + bpf_mtap_ether(ifp->if_bpf, m, inout); +#endif + + if (inout == BPF_DIRECTION_IN) + ether_input_mbuf(ifp, m); + else + m_freem(m); + } +} + +/* ARGSUSED */ +int +vetherioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +{ + struct vether_softc *sc = (struct vether_softc *)ifp->if_softc; + struct ifaddr *ifa = (struct ifaddr *)data; + struct ifreq *ifr = (struct ifreq *)data; + int error = 0, link_state; + + ifr = (struct ifreq *)data; + switch (cmd) { + case SIOCSIFADDR: + ifp->if_flags |= IFF_UP; +#ifdef INET + if (ifa->ifa_addr->sa_family == AF_INET) + arp_ifinit(&sc->sc_ac, ifa); +#endif + /* FALLTHROUGH */ + + case SIOCSIFFLAGS: + if (ifp->if_flags & IFF_UP) { + ifp->if_flags |= IFF_RUNNING; + link_state = LINK_STATE_UP; + } else { + ifp->if_flags &= ~IFF_RUNNING; + link_state = LINK_STATE_DOWN; + } + if (ifp->if_link_state != link_state) { + ifp->if_link_state = link_state; + if_link_state_change(ifp); + } + break; + + case SIOCGIFMEDIA: + case SIOCSIFMEDIA: + error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); + break; + + default: + error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); + } + return (error); +} |