,,,Index: sys/net/if_vether.c
/*===================================================================
* Copyright (c) 2009 Theo de Raadt--- sys/net/if_vether.c (nonexistent)
*+++ sys/net/if_vether.c (working copy)
* Permission to use, copy, modify, and distribute this software for any@@ -0,0 +1,450 @@
* purpose with or without fee is hereby granted, provided that the above+/*
* c+ * Copyright notice and this permission notice appear in all copies.(c) 2009 Theo de Raadt
+ *
+ * Permission to use, copy, modify, * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIESand distribute this software for any
+ * purpose with or without fee is hereby granted, * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OFprovided that the above
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR+ * copyright notice and this permission notice appear in all copies.
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES+ *
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. * OR IN CONNECTION WITHIN NO EVENT SHALL THE USE OR PERFORMANCE OF THIS SOFTWARE.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
* Copyright (c) 2018+ * ACTION OF CONTRACT, 2021 Henning Andersen MatyschokNEGLIGENCE OR OTHER TORTIOUS ACTION, DARPA/AFRLARISING OUT OF
*+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
* Redistribution and use in source and binary forms, with or without+ */
* modification, are permitted provided that the following conditions+/*
+ * Copyright (c) 2018, 2021 Henning Andersen Matyschok, * are met:DARPA/AFRL
* 1. Redistributions of source code must retain the above copyright+ *
* notice+ * Redistribution and use in source and binary forms, this list of conditions and the following disclaimer.with or without
* 2.+ * modification, Redistributions in binary form must reproduce the above copyrightare permitted provided that the following conditions
* notice, this list of conditions and the following disclaimer in the+ * are met:
+ * 1. * documentation and/or other materials provided withRedistributions of source code must retain the distribution.above copyright
+ * notice, *this list of conditions and the following disclaimer.
+ * 2. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ORRedistributions in binary form must reproduce the above copyright
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO+ * notice, THE IMPLIEDthis list of conditions and the following disclaimer in the
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+ * documentation and/or other materials provided with the distribution.
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,+ *
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORTHE IMPLIED
* SERVICES; LOS+ * WARRANTIES OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* HOWEVER CAUSED AND ON ANY+ * DISCLAIMED. IN NO EVENT SHALL THEORY OF AUTHOR BE LIABILITY, WHETHER IN CONTRACTLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, * STRICT LIABILITYEXEMPLARY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING INOR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, * ANY WAY OUT OF THE USE OF THIS SOFTWAREBUT NOT LIMITED TO, EVEN IF ADVISED OF THEPROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; * POSSIBILITY OF SUCH DAMAGE.OR BUSINESS INTERRUPTION)
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
#include <sys/kernel.h>+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
#include <sys/module.h>+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
#include <sys/socket.h>+ * POSSIBILITY OF SUCH DAMAGE.
#include <sys/sockio.h>
#include <net/if.h>+ */
#include <net/if_var.h>+
+#include <net/if_clonesys/cdefs.h>
#include <net/if_dl.h>+
#include <net/if_media.h>+__FBSDID("$FreeBSD$");
#include <net/netisr.h>+
+#include <net/if_typessys/param.h>
+#include <net/bpfsys/kernel.h>
+#include <net/ethernetsys/module.h>
+#include <net/if_bridgevarsys/socket.h>
+#include <net/vnetsys/sockio.h>
/*
* Virtual Ethernet interface, ported from OpenBSD. This interface+
* operates in conjunction with if_bridge(4).+#include <net/if.h>
*/
struct vether_softc {+#include <net/if_var.h>
struct ifmedia sc_ifm; /* fake media information */+#include <net/if_clone.h>
struct ifnet *sc_ifp; /* network interface. */+#include <net/if_dl.h>
};+#include <net/if_media.h>
#define VETHER_IF_FLAGS (IFF_SIMPLEX|IFF_BROADCAST|IFF_MULTICAST)+#include <net/netisr.h>
#define VETHER_IFCAP_FLAGS (IFCAP_VLAN_MTU|IFCAP_JUMBO_MTU)+#include <net/if_types.h>
#define VETHER_IFM_FLAGS (IFM_ETHER|IFM_AUTO)
/*+#include <net/bpf.h>
* XXX+#include <net/ethernet.h>
* The set of protocol-numbers index-set+#include <net/if_bridgevar.h>
* against+#include <net/netisr.h> maps-to setvnet.h>
* over (enum), e. g.:+
*+/*
+ * Virtual Ethernet interface, ported from OpenBSD. * typedef enum netisr_proto {This interface
* netisr_ip = NETISR_IP,+ * operates in conjunction with if_bridge(4).
* netisr_igmp = NETISR_IGMP,+ */
* netisr_route = NETISR_ROUTE,+
* netisr_arp = NETISR_ARP,+struct vether_softc {
* + struct ifmedia sc_ifm; netisr_ether = NETISR_ETHER, /* fake media information */
+ struct ifnet *sc_ifp; /* network interface. * netisr_ipv6 = NETISR_IPV6,*/
* netisr_epair = NETISR_EPAIR,+};
* +#define VETHER_IF_FLAGS netisr_ip_direct = NETISR_IP_DIRECT,(IFF_SIMPLEX|IFF_BROADCAST|IFF_MULTICAST)
* netisr_ipv6_direct = NETISR_IPV6_DIRECT,+#define VETHER_IFCAP_FLAGS (IFCAP_VLAN_MTU|IFCAP_JUMBO_MTU)
* netisr_vether = NETISR_V+#define VETHER_IFM_FLAGS (IFM_ETHER_FWD,|IFM_AUTO)
* } netisr_proto_t;+
*/+/*
#define NETISR_VETHER_FWD 11
typedef enum vether_netisr_component {+ * XXX
vether_netisr_fwd = NETISR_VETHER_FWD,+ * The set of protocol-numbers index-set
} vether_netisr_component_t;
static void vether_ifaddr_init(struct ifnet *, struct ether_addr *);+ * against <net/netisr.h> maps-to set
static void vether_encap(struct mbuf *);+ * over (enum), e. g.:
static void vether_texeof(struct ifnet *);
static void vether_init(void *);+ *
static void+ * vether_stop(struct ifnet *); typedef enum netisr_proto {
static void+ * vether_start(struct ifnet *);
static int vether_media_change(struct ifnet *); netisr_ip = NETISR_IP,
static void+ * vether_media_status(struct ifnet *, struct ifmediareq *);netisr_igmp = NETISR_IGMP,
static int vether_ioctl(struct ifnet *, u_long, caddr_t);
static int vether_clone_create(struct if_clone *, int, caddr_t);+ * netisr_route = NETISR_ROUTE,
static void+ * vether_clone_destroy(struct ifnet *);
static struct netisr_handler vether_nh_fwd = {arp = NETISR_ARP,
.nh_name = "Softintr. for if_vether(4)"+ * netisr_ether = NETISR_ETHER,
+ * .nh_handler = vether_encap netisr_ipv6 = NETISR_IPV6,
+ * .nh_proto = vether_netisr_fwd netisr_epair = NETISR_EPAIR,
+ * .nh_policy netisr_ip_direct = NETISR_POLICY_FLOWIP_DIRECT,
};+ * netisr_ipv6_direct = NETISR_IPV6_DIRECT,
static const char vether_name[] = "+ * netisr_vether";
VNET_DEFINE(struct if_clone *, vether_cloner); = NETISR_VETHER_FWD,
#define V_vether_cloner VNET(vether_cloner)
static int+ * } netisr_proto_t;
vether_clone_create(struct if_clone *ifc, int unit, caddr_t data)+ */
{+#define NETISR_VETHER_FWD 11
struct vether_softc *sc;+
struct ifnet *ifp;+typedef enum vether_netisr_component {
+ struct ether_addr lla;vether_netisr_fwd = NETISR_VETHER_FWD,
int up_call;
/*+} vether_netisr_component_t;
* For safety reason, there is a condition test applied -+
+static void * independentlyvether_ifaddr_init(struct ifnet *, if M_WAITOK was enabled or not.struct ether_addr *);
*/
if ((sc = malloc(sizeof+static void vether_encap(struct vether_softc),mbuf *);
M_DEVBUF, M_WAITOK|M_ZERO)) != NULL) {
if ((ifp = if_alloc(IFT_ETHER)) != NULL) {+static void vether_texeof(struct ifnet *);
sc->sc_ifp = ifp;+
ifp->if_softc = sc;
+static void if_initname(ifp, vether_name, unit);
ifp->if_init = vether_init;(void *);
+static void ifp->if_ioctl = vether_ioctl; vether_stop(struct ifnet *);
ifp->if_start = vether_start;
ifp->if_flags = VETHER_IF_FLAGS;
ifp->if_capabilities = VETHER_IFCAP_FLAGS+static void vether_start(struct ifnet *);
ifp->if_capenable = VETHER_IFCAP_FLAGS;
ifp->if_baudrate = 0;
ifmedia_init(&sc->sc_ifm, 0, vether_media_change,+
+static int vether_media_status);change(struct ifnet *);
+static void ifvether_media_add(&sc->sc_ifm, VETHER_IFM_FLAGS, 0status(struct ifnet *, NULL);struct ifmediareq *);
ifmedia_set(&sc->sc_ifm+static int vether_ioctl(struct ifnet *, VETHER_IFM_FLAGS);
vether_ifaddr_init(ifpu_long, &lla);caddr_t);
ether_ifattach(ifp, lla.octet);
up_call = 0;+
} else {+static int vether_clone_create(struct if_clone *, int, caddr_t);
+static void up_call = ENOSPC;vether_clone_destroy(struct ifnet *);
free(sc, M_DEVBUF);+
}+static struct netisr_handler vether_nh_fwd = {
} else+ .nh_name = "Softintr. for if_vether(4)",
+ up_call = ENOBUFS;
return (up_call);.nh_handler = vether_encap,
}
static void+ .nh_proto = vether_netisr_fwd,
vether_clone_destroy(struct ifnet *ifp)+ .nh_policy = NETISR_POLICY_FLOW,
{+};
struct vether_softc *sc;
if (ifp != NULL) {+static const char vether_name[] = "vether";
ifp->if_flags &= ~IFF_UP;
vether_stop(ifp);
if ((sc = ifp->if_softc) != NULL) {+
free(sc+VNET_DEFINE(struct if_clone *, M_DEVBUF);vether_cloner);
ifp->if_softc = NULL;+#define V_vether_cloner VNET(vether_cloner)
}+
ether_ifdetach(ifp);+static int
+vether_clone_create(struct if_free(ifp);clone *ifc, int unit, caddr_t data)
}+{
}
static void+ struct vether_softc *sc;
vnet_vether_init(const void *unused __unused)+ struct ifnet *ifp;
{
+ V_vether_cloner = if_clone_simple(vether_name,struct ether_addr lla;
+ vether_clone_create, vether_clone_destroy, 0);int error;
}+
VNET_SYSINIT(vnet_vether_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,+ /*
vnet_vether_init+ * For safety reason, NULL);
static voidthere is a condition test applied -
vnet_vether_uninit(const void *unused __unused)+ * independently, if M_WAITOK was enabled or not.
{
+ if_clone_detach(V_vether_cloner); */
}+
VNET_SYSUNINIT(vnet_vether_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY+ if ((sc = malloc(sizeof(struct vether_softc),
vnet_vether_uninit+ M_DEVBUF, NULL);
static intM_WAITOK|M_ZERO)) != NULL) {
vether_mod_event(module_t mod, int event, void *data)+
+ if ((ifp = if_alloc(IFT_ETHER)) != NULL) {
+ switch (event) {c->sc_ifp = ifp;
+ case MOD_LOAD: ifp->if_softc = sc;
netisr_register(&vether_nh_fwd);+
+ return (0);if_initname(ifp, vether_name, unit);
case MOD_UNLOAD:+
+ netisr_unregister(& ifp->if_init = vether_nh_fwd);_init;
+ return (0);ifp->if_ioctl = vether_ioctl;
+ default:ifp->if_start = vether_start;
break;+
}+ ifp->if_flags = VETHER_IF_FLAGS;
return (EOPNOTSUPP);+
}
static moduledata_t vether_mod = {+ ifp->if_capabilities = VETHER_IFCAP_FLAGS;
+ "if_vether",ifp->if_capenable = VETHER_IFCAP_FLAGS;
vether_mod_event,+
0,+ ifp->if_baudrate = 0;
};+
DECLARE_MODULE(if_vether, vether_mod+ ifmedia_init(&sc->sc_ifm, SI_SUB_PSEUDO0, SI_ORDER_ANY);
/*vether_media_change,
* I/O.+ vether_media_status);
+ ifmedia_add(&sc->sc_ifm, VETHER_IFM_FLAGS, */
static void0, NULL);
vether_txeof(struct ifnet *ifp)+ ifmedia_set(&sc->sc_ifm, VETHER_IFM_FLAGS);
{+
+ struct mbuf *m;
if vether_ifaddr_init(ifp != NULL) {, &lla);
+ IFQ_DEQUEUE(&ifp->if_snd, m);ether_ifattach(ifp, lla.octet);
if (m != NULL) {+
BPF_MTAP(ifp, m);
if ((m->m_flags & M_PKTHDR) != 0) {
/* do some statistics */
if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len)+ error = 0;
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
/* discard, if not member of if_bridge(4) */} else {
+ if (ifp->if_bridge == NULL) error = ENOSPC;
+ m->m_pkthdr.rcvif = ifp;
/* free(sc, M_DEVBUF);
* Three cases are considered here:+ }
+ *} else
+ * (a) Frame was tx'd by layer above. error = ENOBUFS;
*+
* (b) Frame was rx'd by link-layer.+ return (error);
*+}
* (c) Data sink.+
*/+static void
if (m->m_pkthdr.rcvif == NULL) {+vether_clone_destroy(struct ifnet *ifp)
m->m_pkthdr.rcvif = ifp;+{
+ netisr_dispatch(struct vether_netisr_fwd, m);softc *sc;
} else if (m->m_pkthdr.rcvif != ifp) {+
+ m->m_pkthdr.rcvif = ifp;
/* demultiplex any other frame */if (ifp != NULL) {
+ (*ifp->if_input)(ifp, m);flags &= ~IFF_UP;
} else {+
+ m_freem(m);vether_stop(ifp);
m = NULL;+
+ }
} else {if ((sc = ifp->if_softc) != NULL) {
+ if_inc_counter(ifp, IFCOUNTER_OERRORSfree(sc, 1);
m_freem(m);M_DEVBUF);
+ mifp->if_softc = NULL;
+ }
+ vether_txeofifdetach(ifp);
+ }if_free(ifp);
+ }
}
static void+}
vether_start(struct ifnet *ifp)+
{+static void
if ((ifp->if_flags & IFF_UP) != 0) {+vnet_vether_init(const void *unused __unused)
ifp->if_drv_flags |= IFF_DRV_OACTIVE;+{
vether_txeof(ifp);+
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;V_vether_cloner = if_clone_simple(vether_name,
}+ vether_clone_create, vether_clone_destroy, 0);
}
/*+}
+VNET_SYSINIT(vnet_vether_init, SI_SUB_PROTO_IFATTACHDOMAIN, * Broadcast frame by if_bridge(4).SI_ORDER_ANY,
*/
static void+ vnet_vether_init, NULL);
vether_encap(struct mbuf *m)+
{+static void
struct mbuf *m;+vnet_vether_uninit(const void *unused __unused)
struct ifnet *ifp;+{
int up_call;
if (m != NULL) {
if ((m->m_flags & M_PKTHDR) != 0) {
if ((ifp = m->m_pkthdr.rcvif) != NULL) {
if (ifp->if_mtu > m->m_pkthdr.len)+
+ m_freem(m);if_clone_detach(V_vether_cloner);
else {+}
BRIDGE_OUTPUT(ifp+VNET_SYSUNINIT(vnet_vether_uninit, mSI_SUB_PSEUDO, up_call);
if (up_call != 0)SI_ORDER_ANY,
+ m_freem(m);vnet_vether_uninit, NULL);
}+
} else+static int
m_freem(m);+vether_mod_event(module_t mod, int event, void *data)
} else+{
+ m_freem(m);switch (event) {
}+ case MOD_LOAD:
}
/*+ netisr_register(&vether_nh_fwd);
* Initialize lla.+ return (0);
*/
static void+ case MOD_UNLOAD:
vether_ifaddr_init(struct ifnet *ifp, struct + netisr_unregister(&vether_addr *lla)nh_fwd);
{+ return (0);
caddr_t pfx, sfx;
if (ifp != NULL) {
+ if (lla != NULL) {default:
+ pfx = lla->octet; break;
pfx[0] = 0x02;
sfx = (pfx + 1);+ }
+ arc4rand(sfx, 5, 0);return (EOPNOTSUPP);
}+}
}+
}
+static intmoduledata_t vether_mod = {
vether_media_change(struct ifnet *ifp)+ "if_vether",
{+ vether_mod_event,
int up_call;
if (ifp != NULL)+ 0,
up_call = 0;+};
else+DECLARE_MODULE(if_vether, vether_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
up_call = EADDRNOTAVAIL;
return (up_call);+
}
static void+/*
vether_media_status(struct ifnet *ifp, struct ifmediareq *ifm)+ * I/O.
{+ */
if (ifp != NULL) {
if (ifm != NULL) {+
ifm->ifm_active = (IFM_ETHER|IFM_AUTO);+static void
ifm->ifm_status = (IFM_AVALID|IFM_ACTIVE);+vether_txeof(struct ifnet *ifp)
}+{
}+ struct mbuf *m;
}
static void+
vether_init(void *xsc)+ if (ifp != NULL) {
{+ IFQ_DEQUEUE(&ifp->if_snd, m);
+ struct vether_softc *sc; if (m != NULL) {
struct ifnet *ifp;
+ if ((sc = (struct vether_softc *)xsc) != NULL) {
if ((ifp = sc->sc_ifp) != NULL) { BPF_MTAP(ifp, m);
ifp->if_drv_flags |= IFF_DRV_RUNNING;+
+ ifp->if_drv ((m->m_flags &= ~IFF_DRV_OACTIVE; M_PKTHDR) != 0) {
}+
}+ /* do some statistics */
}
static void+
vether_stop(struct ifnet *ifp)+ if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len);
{+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if (ifp != NULL)+
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING|IFF_DRV_OACTIVE); /* discard, if not member of if_bridge(4) */
}
static int+ if (ifp->if_bridge == NULL)
vether_ioctl(struct ifnet *ifp, u_long req, caddr_t argp)+ m->m_pkthdr.rcvif = ifp;
{+
struct vether_softc *sc;+ /*
struct ifreq *ifr;+ * Three cases are considered here:
int up_call;
if (ifp != NULL) {
+ if ((sc = ifp->if_softc) != NULL) { *
+ ifr = (struct ifreq *)argp;
switch (req) { * (a) Frame was tx'd by layer above.
+ case SIOCSIFMTU: *
+ if (ifr->ifr_mtu < ETHER_MAX_LEN_JUMBO) { * (b) Frame was rx'd by link-layer.
+ ifp->if_mtu = ifr->ifr_mtu; *
+ up_call = 0;* (c) Data sink.
+ } else */
+ up_call = EINVAL;if (m->m_pkthdr.rcvif == NULL) {
+ break;m->m_pkthdr.rcvif = ifp;
+ case SIOCSIFMEDIA: /* Media types can't be changed. netisr_dispatch(vether_netisr_fwd, */m);
+ case SIOCGIFMEDIA:} else if (m->m_pkthdr.rcvif != ifp) {
+ up_call = ifmedia_ioctl(ifp, ifr, &sc->sc_ifm, req); m->m_pkthdr.rcvif = ifp;
break;+
+ case SIOCSIFFLAGS:/* demultiplex any other frame */
+ case SIOCADDMULTI: (*ifp->if_input)(ifp, m);
+ case SIOCDELMULTI: } else {
+ up_call = 0; m_freem(m);
+ break;m = NULL;
+ case SIOCSIFPHYS: }
up_call = EOPNOTSUPP;+
+ break;} else {
+ default: if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
up_call = ether_ioctl(ifp, req, argp);+
+ break;m_freem(m);
+ }m = NULL;
+ } else }
+ up_call = ENXIO;vether_txeof(ifp);
} else+ }
up_call = ENOTTY;
return (up_call);+ }
}
,,,+}
+
+static void
+vether_start(struct ifnet *ifp)
+{
+ if ((ifp->if_flags & IFF_UP) != 0) {
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ vether_txeof(ifp);
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ }
+}
+
+/*
+ * Broadcast frame by if_bridge(4).
+ */
+
+static void
+vether_encap(struct mbuf *m)
+{
+ struct mbuf *m;
+ struct ifnet *ifp;
+ int error;
+
+ if (m != NULL) {
+
+ if ((m->m_flags & M_PKTHDR) != 0) {
+
+ if ((ifp = m->m_pkthdr.rcvif) != NULL) {
+
+ if (ifp->if_mtu > m->m_pkthdr.len)
+ m_freem(m);
+ else {
+ BRIDGE_OUTPUT(ifp, m, error);
+
+ if (error != 0)
+ m_freem(m);
+ }
+ } else
+ m_freem(m);
+ } else
+ m_freem(m);
+ }
+}
+
+/*
+ * Initialize lla.
+ */
+
+static void
+vether_ifaddr_init(struct ifnet *ifp, struct ether_addr *lla)
+{
+ caddr_t pfx, sfx;
+
+ if (ifp != NULL) {
+
+ if (lla != NULL) {
+ pfx = lla->octet;
+ pfx[0] = 0x02;
+
+ sfx = (pfx + 1);
+ arc4rand(sfx, 5, 0);
+ }
+ }
+}
+
+static int
+vether_media_change(struct ifnet *ifp)
+{
+ int error;
+
+ if (ifp != NULL)
+ error = 0;
+ else
+ error = EADDRNOTAVAIL;
+
+ return (error);
+}
+
+static void
+vether_media_status(struct ifnet *ifp, struct ifmediareq *ifm)
+{
+ if (ifp != NULL) {
+
+ if (ifm != NULL) {
+ ifm->ifm_active = (IFM_ETHER|IFM_AUTO);
+ ifm->ifm_status = (IFM_AVALID|IFM_ACTIVE);
+ }
+ }
+}
+
+static void
+vether_init(void *xsc)
+{
+ struct vether_softc *sc;
+ struct ifnet *ifp;
+
+ if ((sc = (struct vether_softc *)xsc) != NULL) {
+
+ if ((ifp = sc->sc_ifp) != NULL) {
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ }
+ }
+}
+
+static void
+vether_stop(struct ifnet *ifp)
+{
+ if (ifp != NULL)
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING|IFF_DRV_OACTIVE);
+}
+
+static int
+vether_ioctl(struct ifnet *ifp, u_long req, caddr_t argp)
+{
+ struct vether_softc *sc;
+ struct ifreq *ifr;
+ int error;
+
+ if (ifp != NULL) {
+
+ if ((sc = ifp->if_softc) != NULL) {
+ ifr = (struct ifreq *)argp;
+
+ switch (req) {
+ case SIOCSIFMTU:
+ if (ifr->ifr_mtu < ETHER_MAX_LEN_JUMBO) {
+ ifp->if_mtu = ifr->ifr_mtu;
+ error = 0;
+ } else
+ error = EINVAL;
+ break;
+ case SIOCSIFMEDIA: /* Media types can't be changed. */
+ case SIOCGIFMEDIA:
+ error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifm, req);
+ break;
+ case SIOCSIFFLAGS:
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ error = 0;
+ break;
+ case SIOCSIFPHYS:
+ error = EOPNOTSUPP;
+ break;
+ default:
+ error = ether_ioctl(ifp, req, argp);
+ break;
+ }
+ } else
+ error = ENXIO;
+ } else
+ error = ENOTTY;
+
+ return (error);
+}
Henning Andersen Matyschok, 120179M11214, USAF
USAF
Henning Andersen Matyschok
Wasserlooser Weg 5
24944 Flensburg
Germany