154558Sbp/*-
266479Sbp * Copyright (c) 1999, 2000 Boris Popov
354558Sbp * All rights reserved.
454558Sbp *
554558Sbp * Redistribution and use in source and binary forms, with or without
654558Sbp * modification, are permitted provided that the following conditions
754558Sbp * are met:
854558Sbp * 1. Redistributions of source code must retain the above copyright
954558Sbp *    notice, this list of conditions and the following disclaimer.
1054558Sbp * 2. Redistributions in binary form must reproduce the above copyright
1154558Sbp *    notice, this list of conditions and the following disclaimer in the
1254558Sbp *    documentation and/or other materials provided with the distribution.
1354558Sbp *
1454558Sbp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1554558Sbp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1654558Sbp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1754558Sbp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1854558Sbp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1954558Sbp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2054558Sbp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2154558Sbp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2254558Sbp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2354558Sbp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2454558Sbp * SUCH DAMAGE.
2554558Sbp *
2654558Sbp * $FreeBSD$
2754558Sbp */
2854558Sbp
2954558Sbp#include "opt_inet.h"
3054558Sbp#include "opt_ipx.h"
3156424Sbp#include "opt_ef.h"
3254558Sbp
3354558Sbp#include <sys/param.h>
3454558Sbp#include <sys/systm.h>
3554558Sbp#include <sys/sockio.h>
3654558Sbp#include <sys/malloc.h>
3754558Sbp#include <sys/mbuf.h>
3854558Sbp#include <sys/socket.h>
3954558Sbp#include <sys/syslog.h>
4054558Sbp#include <sys/kernel.h>
4154558Sbp#include <sys/module.h>
4254558Sbp
4354558Sbp#include <net/ethernet.h>
4454558Sbp#include <net/if_llc.h>
4554558Sbp#include <net/if.h>
4654558Sbp#include <net/if_arp.h>
4754558Sbp#include <net/if_dl.h>
4854558Sbp#include <net/if_types.h>
4954558Sbp#include <net/netisr.h>
5054558Sbp#include <net/bpf.h>
51185571Sbz#include <net/vnet.h>
5254558Sbp
5354558Sbp#ifdef INET
5454558Sbp#include <netinet/in.h>
5554558Sbp#include <netinet/in_var.h>
5654558Sbp#include <netinet/if_ether.h>
5754558Sbp#endif
5854558Sbp
5954558Sbp#ifdef IPX
6054558Sbp#include <netipx/ipx.h>
6154558Sbp#include <netipx/ipx_if.h>
6254558Sbp#endif
6354558Sbp
64143196Ssobomax/* If none of the supported layers is enabled explicitly enable them all */
65143196Ssobomax#if !defined(ETHER_II) && !defined(ETHER_8023) && !defined(ETHER_8022) && \
66143196Ssobomax    !defined(ETHER_SNAP)
67143196Ssobomax#define	ETHER_II	1
68143196Ssobomax#define	ETHER_8023	1
69143196Ssobomax#define	ETHER_8022	1
70143196Ssobomax#define	ETHER_SNAP	1
71143196Ssobomax#endif
72143196Ssobomax
7354558Sbp/* internal frame types */
7454558Sbp#define ETHER_FT_EII		0	/* Ethernet_II - default */
7554558Sbp#define	ETHER_FT_8023		1	/* 802.3 (Novell) */
7654558Sbp#define	ETHER_FT_8022		2	/* 802.2 */
7754558Sbp#define	ETHER_FT_SNAP		3	/* SNAP */
7854558Sbp#define	EF_NFT			4	/* total number of frame types */
7954558Sbp
8054558Sbp#ifdef EF_DEBUG
8187599Sobrien#define EFDEBUG(format, args...) printf("%s: "format, __func__ ,## args)
8254558Sbp#else
8354558Sbp#define EFDEBUG(format, args...)
8454558Sbp#endif
8554558Sbp
8687599Sobrien#define EFERROR(format, args...) printf("%s: "format, __func__ ,## args)
8754558Sbp
8854558Sbpstruct efnet {
89147256Sbrooks	struct ifnet	*ef_ifp;
90147256Sbrooks	struct ifnet	*ef_pifp;
91121816Sbrooks	int		ef_frametype;
9254558Sbp};
9354558Sbp
9454558Sbpstruct ef_link {
9560938Sjake	SLIST_ENTRY(ef_link) el_next;
9654558Sbp	struct ifnet	*el_ifp;		/* raw device for this clones */
9754558Sbp	struct efnet	*el_units[EF_NFT];	/* our clones */
9854558Sbp};
9954558Sbp
10060938Sjakestatic SLIST_HEAD(ef_link_head, ef_link) efdev = {NULL};
10154558Sbpstatic int efcount;
10254558Sbp
10354558Sbpextern int (*ef_inputp)(struct ifnet*, struct ether_header *eh, struct mbuf *m);
10459681Sbpextern int (*ef_outputp)(struct ifnet *ifp, struct mbuf **mp,
105249925Sglebius		const struct sockaddr *dst, short *tp, int *hlen);
10654558Sbp
10754558Sbp/*
10854558Sbpstatic void ef_reset (struct ifnet *);
10954558Sbp*/
11054558Sbpstatic int ef_attach(struct efnet *sc);
11154558Sbpstatic int ef_detach(struct efnet *sc);
11254558Sbpstatic void ef_init(void *);
11354558Sbpstatic int ef_ioctl(struct ifnet *, u_long, caddr_t);
11454558Sbpstatic void ef_start(struct ifnet *);
11554558Sbpstatic int ef_input(struct ifnet*, struct ether_header *, struct mbuf *);
11659681Sbpstatic int ef_output(struct ifnet *ifp, struct mbuf **mp,
117249925Sglebius		const struct sockaddr *dst, short *tp, int *hlen);
11854558Sbp
11954558Sbpstatic int ef_load(void);
12054558Sbpstatic int ef_unload(void);
12154558Sbp
12254558Sbp/*
12354558Sbp * Install the interface, most of structure initialization done in ef_clone()
12454558Sbp */
12554558Sbpstatic int
12654558Sbpef_attach(struct efnet *sc)
12754558Sbp{
128147256Sbrooks	struct ifnet *ifp = sc->ef_ifp;
12954558Sbp
13054558Sbp	ifp->if_start = ef_start;
13154558Sbp	ifp->if_init = ef_init;
132207554Ssobomax	ifp->if_snd.ifq_maxlen = ifqmaxlen;
13354558Sbp	ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
13454558Sbp	/*
13554558Sbp	 * Attach the interface
13654558Sbp	 */
137152315Sru	ether_ifattach(ifp, IF_LLADDR(sc->ef_pifp));
13854558Sbp
13954558Sbp	ifp->if_resolvemulti = 0;
14054558Sbp	ifp->if_type = IFT_XETHER;
141148887Srwatson	ifp->if_drv_flags |= IFF_DRV_RUNNING;
14254558Sbp
143121816Sbrooks	EFDEBUG("%s: attached\n", ifp->if_xname);
14454558Sbp	return 1;
14554558Sbp}
14654558Sbp
14754558Sbp/*
14854558Sbp * This is for _testing_only_, just removes interface from interfaces list
14954558Sbp */
15054558Sbpstatic int
15154558Sbpef_detach(struct efnet *sc)
15254558Sbp{
153147256Sbrooks	struct ifnet *ifp = sc->ef_ifp;
15454558Sbp
155147256Sbrooks	ether_ifdetach(ifp);
156147256Sbrooks	if_free(ifp);
157147256Sbrooks
15854558Sbp	return 0;
15954558Sbp}
16054558Sbp
16154558Sbpstatic void
16254558Sbpef_init(void *foo) {
16354558Sbp	return;
16454558Sbp}
16554558Sbp
16654558Sbpstatic int
16754558Sbpef_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
16854558Sbp{
169121816Sbrooks	struct efnet *sc = ifp->if_softc;
17054558Sbp	struct ifaddr *ifa = (struct ifaddr*)data;
171241686Sandre	int error;
17254558Sbp
173121816Sbrooks	EFDEBUG("IOCTL %ld for %s\n", cmd, ifp->if_xname);
17454558Sbp	error = 0;
17554558Sbp	switch (cmd) {
176106939Ssam	    case SIOCSIFFLAGS:
177106939Ssam		error = 0;
178106939Ssam		break;
17954558Sbp	    case SIOCSIFADDR:
180121816Sbrooks		if (sc->ef_frametype == ETHER_FT_8023 &&
18154558Sbp		    ifa->ifa_addr->sa_family != AF_IPX) {
18254558Sbp			error = EAFNOSUPPORT;
18354558Sbp			break;
18454558Sbp		}
18554558Sbp		ifp->if_flags |= IFF_UP;
18654558Sbp		/* FALL THROUGH */
187106939Ssam	    default:
18854558Sbp		error = ether_ioctl(ifp, cmd, data);
18954558Sbp		break;
19054558Sbp	}
19154558Sbp	return error;
19254558Sbp}
19354558Sbp
19454558Sbp/*
19554558Sbp * Currently packet prepared in the ether_output(), but this can be a better
19654558Sbp * place.
19754558Sbp */
19854558Sbpstatic void
19954558Sbpef_start(struct ifnet *ifp)
20054558Sbp{
20154558Sbp	struct efnet *sc = (struct efnet*)ifp->if_softc;
20254558Sbp	struct ifnet *p;
20354558Sbp	struct mbuf *m;
204130549Smlaier	int error;
20554558Sbp
206148887Srwatson	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
207147256Sbrooks	p = sc->ef_pifp;
20854558Sbp
20954558Sbp	EFDEBUG("\n");
21054558Sbp	for (;;) {
21154558Sbp		IF_DEQUEUE(&ifp->if_snd, m);
21254558Sbp		if (m == 0)
21354558Sbp			break;
214106939Ssam		BPF_MTAP(ifp, m);
215191607Skmacy		error = p->if_transmit(p, m);
216130549Smlaier		if (error) {
21759681Sbp			ifp->if_oerrors++;
21859681Sbp			continue;
21954558Sbp		}
22069152Sjlemon		ifp->if_opackets++;
22154558Sbp	}
222148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
22354558Sbp	return;
22454558Sbp}
22554558Sbp
22654558Sbp/*
22754558Sbp * Inline functions do not put additional overhead to procedure call or
22854558Sbp * parameter passing but simplify the code
22954558Sbp */
23054558Sbpstatic int __inline
231111888Sjlemonef_inputEII(struct mbuf *m, struct ether_header *eh, u_short ether_type)
23254558Sbp{
233111888Sjlemon	int isr;
234111888Sjlemon
23554558Sbp	switch(ether_type) {
23654558Sbp#ifdef IPX
237111888Sjlemon	case ETHERTYPE_IPX:
238111888Sjlemon		isr = NETISR_IPX;
23954558Sbp		break;
24054558Sbp#endif
24154558Sbp#ifdef INET
242111888Sjlemon	case ETHERTYPE_IP:
243295896Sgnn		if ((m = ip_fastforward(m)) == NULL)
244295896Sgnn			return (0);
245111888Sjlemon		isr = NETISR_IP;
24654558Sbp		break;
24754558Sbp
248111888Sjlemon	case ETHERTYPE_ARP:
249111888Sjlemon		isr = NETISR_ARP;
25054558Sbp		break;
25154558Sbp#endif
252111888Sjlemon	default:
253111888Sjlemon		return (EPROTONOSUPPORT);
25454558Sbp	}
255111888Sjlemon	netisr_dispatch(isr, m);
256111888Sjlemon	return (0);
25754558Sbp}
25854558Sbp
25954558Sbpstatic int __inline
26054558Sbpef_inputSNAP(struct mbuf *m, struct ether_header *eh, struct llc* l,
261111888Sjlemon	u_short ether_type)
26254558Sbp{
263111888Sjlemon	int isr;
264111888Sjlemon
26554558Sbp	switch(ether_type) {
26654558Sbp#ifdef IPX
267111888Sjlemon	case ETHERTYPE_IPX:
26854558Sbp		m_adj(m, 8);
269111888Sjlemon		isr = NETISR_IPX;
27054558Sbp		break;
27154558Sbp#endif
272111888Sjlemon	default:
273111888Sjlemon		return (EPROTONOSUPPORT);
27454558Sbp	}
275111888Sjlemon	netisr_dispatch(isr, m);
276111888Sjlemon	return (0);
27754558Sbp}
27854558Sbp
27954558Sbpstatic int __inline
28054558Sbpef_input8022(struct mbuf *m, struct ether_header *eh, struct llc* l,
281111888Sjlemon	u_short ether_type)
28254558Sbp{
283111888Sjlemon	int isr;
284111888Sjlemon
28554558Sbp	switch(ether_type) {
28654558Sbp#ifdef IPX
287111888Sjlemon	case 0xe0:
28854558Sbp		m_adj(m, 3);
289111888Sjlemon		isr = NETISR_IPX;
29054558Sbp		break;
29154558Sbp#endif
292111888Sjlemon	default:
293111888Sjlemon		return (EPROTONOSUPPORT);
29454558Sbp	}
295111888Sjlemon	netisr_dispatch(isr, m);
296111888Sjlemon	return (0);
29754558Sbp}
298111888Sjlemon
29954558Sbp/*
30054558Sbp * Called from ether_input()
30154558Sbp */
30254558Sbpstatic int
30354558Sbpef_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m)
30454558Sbp{
30554558Sbp	u_short ether_type;
30671891Sbp	int ft = -1;
30754558Sbp	struct efnet *efp;
30854558Sbp	struct ifnet *eifp;
30954558Sbp	struct llc *l;
31054558Sbp	struct ef_link *efl;
311111888Sjlemon	int isr;
31254558Sbp
31354558Sbp	ether_type = ntohs(eh->ether_type);
314132778Skan	l = NULL;
31554558Sbp	if (ether_type < ETHERMTU) {
31654558Sbp		l = mtod(m, struct llc*);
31754558Sbp		if (l->llc_dsap == 0xff && l->llc_ssap == 0xff) {
31854558Sbp			/*
31954558Sbp			 * Novell's "802.3" frame
32054558Sbp			 */
32154558Sbp			ft = ETHER_FT_8023;
32254558Sbp		} else if (l->llc_dsap == 0xaa && l->llc_ssap == 0xaa) {
32354558Sbp			/*
32454558Sbp			 * 802.2/SNAP
32554558Sbp			 */
32654558Sbp			ft = ETHER_FT_SNAP;
32754558Sbp			ether_type = ntohs(l->llc_un.type_snap.ether_type);
32854558Sbp		} else if (l->llc_dsap == l->llc_ssap) {
32954558Sbp			/*
33054558Sbp			 * 802.3/802.2
33154558Sbp			 */
33254558Sbp			ft = ETHER_FT_8022;
33354558Sbp			ether_type = l->llc_ssap;
33454558Sbp		}
33554558Sbp	} else
33654558Sbp		ft = ETHER_FT_EII;
33754558Sbp
33854558Sbp	if (ft == -1) {
33954558Sbp		EFDEBUG("Unrecognised ether_type %x\n", ether_type);
34059681Sbp		return EPROTONOSUPPORT;
34154558Sbp	}
34254558Sbp
34354558Sbp	/*
34454558Sbp	 * Check if interface configured for the given frame
34554558Sbp	 */
34654558Sbp	efp = NULL;
34754558Sbp	SLIST_FOREACH(efl, &efdev, el_next) {
34854558Sbp		if (efl->el_ifp == ifp) {
34954558Sbp			efp = efl->el_units[ft];
35054558Sbp			break;
35154558Sbp		}
35254558Sbp	}
35354558Sbp	if (efp == NULL) {
35454558Sbp		EFDEBUG("Can't find if for %d\n", ft);
35559681Sbp		return EPROTONOSUPPORT;
35654558Sbp	}
357147256Sbrooks	eifp = efp->ef_ifp;
35854558Sbp	if ((eifp->if_flags & IFF_UP) == 0)
35959681Sbp		return EPROTONOSUPPORT;
36054558Sbp	eifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
36154558Sbp	m->m_pkthdr.rcvif = eifp;
36254558Sbp
363123922Ssam	BPF_MTAP2(eifp, eh, ETHER_HDR_LEN, m);
36454558Sbp	/*
36554558Sbp	 * Now we ready to adjust mbufs and pass them to protocol intr's
36654558Sbp	 */
36754558Sbp	switch(ft) {
368111888Sjlemon	case ETHER_FT_EII:
369111888Sjlemon		return (ef_inputEII(m, eh, ether_type));
37054558Sbp#ifdef IPX
371111888Sjlemon	case ETHER_FT_8023:		/* only IPX can be here */
372111888Sjlemon		isr = NETISR_IPX;
37354558Sbp		break;
37454558Sbp#endif
375111888Sjlemon	case ETHER_FT_SNAP:
376111888Sjlemon		return (ef_inputSNAP(m, eh, l, ether_type));
377111888Sjlemon	case ETHER_FT_8022:
378111888Sjlemon		return (ef_input8022(m, eh, l, ether_type));
379111888Sjlemon	default:
38054558Sbp		EFDEBUG("No support for frame %d and proto %04x\n",
38154558Sbp			ft, ether_type);
382111888Sjlemon		return (EPROTONOSUPPORT);
38354558Sbp	}
384111888Sjlemon	netisr_dispatch(isr, m);
385111888Sjlemon	return (0);
38654558Sbp}
38754558Sbp
38854558Sbpstatic int
389249925Sglebiusef_output(struct ifnet *ifp, struct mbuf **mp, const struct sockaddr *dst,
390249925Sglebius	short *tp, int *hlen)
39154558Sbp{
392121816Sbrooks	struct efnet *sc = (struct efnet*)ifp->if_softc;
39359681Sbp	struct mbuf *m = *mp;
39454558Sbp	u_char *cp;
39554558Sbp	short type;
39654558Sbp
39754558Sbp	if (ifp->if_type != IFT_XETHER)
39859681Sbp		return ENETDOWN;
399121816Sbrooks	switch (sc->ef_frametype) {
40054558Sbp	    case ETHER_FT_EII:
40154558Sbp#ifdef IPX
40254558Sbp		type = htons(ETHERTYPE_IPX);
40354558Sbp#else
40459681Sbp		return EPFNOSUPPORT;
40554558Sbp#endif
40654558Sbp		break;
40754558Sbp	    case ETHER_FT_8023:
40854558Sbp		type = htons(m->m_pkthdr.len);
40954558Sbp		break;
41054558Sbp	    case ETHER_FT_8022:
411243882Sglebius		M_PREPEND(m, ETHER_HDR_LEN + 3, M_WAITOK);
41259681Sbp		/*
41359681Sbp		 * Ensure that ethernet header and next three bytes
41459681Sbp		 * will fit into single mbuf
41559681Sbp		 */
41659681Sbp		m = m_pullup(m, ETHER_HDR_LEN + 3);
41759681Sbp		if (m == NULL) {
41859681Sbp			*mp = NULL;
41959681Sbp			return ENOBUFS;
42059681Sbp		}
42159681Sbp		m_adj(m, ETHER_HDR_LEN);
42254558Sbp		type = htons(m->m_pkthdr.len);
42354558Sbp		cp = mtod(m, u_char *);
42454558Sbp		*cp++ = 0xE0;
42554558Sbp		*cp++ = 0xE0;
42654558Sbp		*cp++ = 0x03;
42766479Sbp		*hlen += 3;
42854558Sbp		break;
42954558Sbp	    case ETHER_FT_SNAP:
430243882Sglebius		M_PREPEND(m, 8, M_WAITOK);
43154558Sbp		type = htons(m->m_pkthdr.len);
43254558Sbp		cp = mtod(m, u_char *);
43354558Sbp		bcopy("\xAA\xAA\x03\x00\x00\x00\x81\x37", cp, 8);
43466479Sbp		*hlen += 8;
43554558Sbp		break;
43654558Sbp	    default:
43759681Sbp		return EPFNOSUPPORT;
43854558Sbp	}
43959681Sbp	*mp = m;
44054558Sbp	*tp = type;
44154558Sbp	return 0;
44254558Sbp}
44354558Sbp
44454558Sbp/*
44554558Sbp * Create clone from the given interface
44654558Sbp */
44754558Sbpstatic int
44854558Sbpef_clone(struct ef_link *efl, int ft)
44954558Sbp{
45054558Sbp	struct efnet *efp;
45154558Sbp	struct ifnet *eifp;
45254558Sbp	struct ifnet *ifp = efl->el_ifp;
45354558Sbp
45469781Sdwmalone	efp = (struct efnet*)malloc(sizeof(struct efnet), M_IFADDR,
455111119Simp	    M_WAITOK | M_ZERO);
45654558Sbp	if (efp == NULL)
45754558Sbp		return ENOMEM;
458147256Sbrooks	efp->ef_pifp = ifp;
459121816Sbrooks	efp->ef_frametype = ft;
460147256Sbrooks	eifp = efp->ef_ifp = if_alloc(IFT_ETHER);
461154318Srwatson	if (eifp == NULL) {
462154318Srwatson		free(efp, M_IFADDR);
463147256Sbrooks		return (ENOSPC);
464154318Srwatson	}
465121816Sbrooks	snprintf(eifp->if_xname, IFNAMSIZ,
466121816Sbrooks	    "%sf%d", ifp->if_xname, efp->ef_frametype);
467121816Sbrooks	eifp->if_dname = "ef";
468121816Sbrooks	eifp->if_dunit = IF_DUNIT_NONE;
46954558Sbp	eifp->if_softc = efp;
47054558Sbp	if (ifp->if_ioctl)
47154558Sbp		eifp->if_ioctl = ef_ioctl;
47254558Sbp	efl->el_units[ft] = efp;
47354558Sbp	return 0;
47454558Sbp}
47554558Sbp
47654558Sbpstatic int
47754558Sbpef_load(void)
47854558Sbp{
479183550Szec	VNET_ITERATOR_DECL(vnet_iter);
48054558Sbp	struct ifnet *ifp;
48154558Sbp	struct efnet *efp;
482154317Srwatson	struct ef_link *efl = NULL, *efl_temp;
48354558Sbp	int error = 0, d;
48454558Sbp
485183550Szec	VNET_LIST_RLOCK();
486183550Szec	VNET_FOREACH(vnet_iter) {
487183550Szec		CURVNET_SET(vnet_iter);
488196482Srwatson
489196482Srwatson		/*
490196482Srwatson		 * XXXRW: The following loop walks the ifnet list while
491196482Srwatson		 * modifying it, something not well-supported by ifnet
492196482Srwatson		 * locking.  To avoid lock upgrade/recursion issues, manually
493196482Srwatson		 * acquire a write lock of ifnet_sxlock here, rather than a
494196482Srwatson		 * read lock, so that when if_alloc() recurses the lock, we
495196482Srwatson		 * don't panic.  This structure, in which if_ef automatically
496196482Srwatson		 * attaches to all ethernet interfaces, should be replaced
497196482Srwatson		 * with a model like that found in if_vlan, in which
498196482Srwatson		 * interfaces are explicitly configured, which would avoid
499196482Srwatson		 * this (and other) problems.
500196482Srwatson		 */
501196482Srwatson		sx_xlock(&ifnet_sxlock);
502183550Szec		TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
503183550Szec			if (ifp->if_type != IFT_ETHER) continue;
504183550Szec			EFDEBUG("Found interface %s\n", ifp->if_xname);
505183550Szec			efl = (struct ef_link*)malloc(sizeof(struct ef_link),
506183550Szec			    M_IFADDR, M_WAITOK | M_ZERO);
507183550Szec			if (efl == NULL) {
508183550Szec				error = ENOMEM;
509183550Szec				break;
510183550Szec			}
51154558Sbp
512183550Szec			efl->el_ifp = ifp;
51354558Sbp#ifdef ETHER_II
514183550Szec			error = ef_clone(efl, ETHER_FT_EII);
515183550Szec			if (error) break;
51654558Sbp#endif
51754558Sbp#ifdef ETHER_8023
518183550Szec			error = ef_clone(efl, ETHER_FT_8023);
519183550Szec			if (error) break;
52054558Sbp#endif
52154558Sbp#ifdef ETHER_8022
522183550Szec			error = ef_clone(efl, ETHER_FT_8022);
523183550Szec			if (error) break;
52454558Sbp#endif
52554558Sbp#ifdef ETHER_SNAP
526183550Szec			error = ef_clone(efl, ETHER_FT_SNAP);
527183550Szec			if (error) break;
52854558Sbp#endif
529183550Szec			efcount++;
530183550Szec			SLIST_INSERT_HEAD(&efdev, efl, el_next);
531183550Szec		}
532196482Srwatson		sx_xunlock(&ifnet_sxlock);
533183550Szec		CURVNET_RESTORE();
53454558Sbp	}
535183550Szec	VNET_LIST_RUNLOCK();
53654558Sbp	if (error) {
53754558Sbp		if (efl)
53854558Sbp			SLIST_INSERT_HEAD(&efdev, efl, el_next);
539154317Srwatson		SLIST_FOREACH_SAFE(efl, &efdev, el_next, efl_temp) {
54054558Sbp			for (d = 0; d < EF_NFT; d++)
541147256Sbrooks				if (efl->el_units[d]) {
542147256Sbrooks					if (efl->el_units[d]->ef_pifp != NULL)
543147256Sbrooks						if_free(efl->el_units[d]->ef_pifp);
54454558Sbp					free(efl->el_units[d], M_IFADDR);
545147256Sbrooks				}
54654558Sbp			free(efl, M_IFADDR);
54754558Sbp		}
54854558Sbp		return error;
54954558Sbp	}
55054558Sbp	SLIST_FOREACH(efl, &efdev, el_next) {
55154558Sbp		for (d = 0; d < EF_NFT; d++) {
55254558Sbp			efp = efl->el_units[d];
55354558Sbp			if (efp)
55454558Sbp				ef_attach(efp);
55554558Sbp		}
55654558Sbp	}
55754558Sbp	ef_inputp = ef_input;
55854558Sbp	ef_outputp = ef_output;
55954558Sbp	EFDEBUG("Loaded\n");
56054558Sbp	return 0;
56154558Sbp}
56254558Sbp
56354558Sbpstatic int
56454558Sbpef_unload(void)
56554558Sbp{
56654558Sbp	struct efnet *efp;
56754558Sbp	struct ef_link *efl;
56854558Sbp	int d;
56954558Sbp
57054558Sbp	ef_inputp = NULL;
57154558Sbp	ef_outputp = NULL;
57254558Sbp	SLIST_FOREACH(efl, &efdev, el_next) {
57354558Sbp		for (d = 0; d < EF_NFT; d++) {
57454558Sbp			efp = efl->el_units[d];
57554558Sbp			if (efp) {
57654558Sbp				ef_detach(efp);
57754558Sbp			}
57854558Sbp		}
57954558Sbp	}
58054558Sbp	EFDEBUG("Unloaded\n");
58154558Sbp	return 0;
58254558Sbp}
58354558Sbp
58454558Sbpstatic int
58554558Sbpif_ef_modevent(module_t mod, int type, void *data)
58654558Sbp{
58754558Sbp	switch ((modeventtype_t)type) {
58854558Sbp	    case MOD_LOAD:
58954558Sbp		return ef_load();
59054558Sbp	    case MOD_UNLOAD:
59154558Sbp		return ef_unload();
59254558Sbp	    default:
593132199Sphk		return EOPNOTSUPP;
59454558Sbp	}
59554558Sbp	return 0;
59654558Sbp}
59754558Sbp
59854558Sbpstatic moduledata_t if_ef_mod = {
59954558Sbp	"if_ef", if_ef_modevent, NULL
60054558Sbp};
60154558Sbp
60254558SbpDECLARE_MODULE(if_ef, if_ef_mod, SI_SUB_PSEUDO, SI_ORDER_MIDDLE);
603