summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2009-11-09 03:16:08 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2009-11-09 03:16:08 +0000
commit6bf19b59d85f2b154aa58aecabda602efd0f838b (patch)
tree45cade4c520278c0524d7bd5f8225c634afea6cf
parentad0592d657a970d3b3d8200773732a354fad0461 (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/Makefile4
-rw-r--r--share/man/man4/bridge.45
-rw-r--r--share/man/man4/vether.456
-rw-r--r--sys/conf/GENERIC3
-rw-r--r--sys/conf/files4
-rw-r--r--sys/net/if_bridge.c10
-rw-r--r--sys/net/if_vether.c232
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);
+}