if_atmsubr.c revision 160038
125603Skjc/*      $NetBSD: if_atmsubr.c,v 1.10 1997/03/11 23:19:51 chuck Exp $       */
225603Skjc
3139823Simp/*-
425603Skjc *
525603Skjc * Copyright (c) 1996 Charles D. Cranor and Washington University.
625603Skjc * All rights reserved.
725603Skjc *
825603Skjc * Redistribution and use in source and binary forms, with or without
925603Skjc * modification, are permitted provided that the following conditions
1025603Skjc * are met:
1125603Skjc * 1. Redistributions of source code must retain the above copyright
1225603Skjc *    notice, this list of conditions and the following disclaimer.
1325603Skjc * 2. Redistributions in binary form must reproduce the above copyright
1425603Skjc *    notice, this list of conditions and the following disclaimer in the
1525603Skjc *    documentation and/or other materials provided with the distribution.
1625603Skjc * 3. All advertising materials mentioning features or use of this software
1725603Skjc *    must display the following acknowledgement:
1825603Skjc *      This product includes software developed by Charles D. Cranor and
1925603Skjc *	Washington University.
2025603Skjc * 4. The name of the author may not be used to endorse or promote products
2125603Skjc *    derived from this software without specific prior written permission.
2225603Skjc *
2325603Skjc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2425603Skjc * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2525603Skjc * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2625603Skjc * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2725603Skjc * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2825603Skjc * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2925603Skjc * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3025603Skjc * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3125603Skjc * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3225603Skjc * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3354263Sshin *
3425603Skjc * if_atmsubr.c
3525603Skjc */
3625603Skjc
37116720Sharti#include <sys/cdefs.h>
38116720Sharti__FBSDID("$FreeBSD: head/sys/net/if_atmsubr.c 160038 2006-06-29 19:22:05Z yar $");
39116720Sharti
4032350Seivind#include "opt_inet.h"
4154263Sshin#include "opt_inet6.h"
42105576Srwatson#include "opt_mac.h"
4332925Seivind#include "opt_natm.h"
4432350Seivind
4525603Skjc#include <sys/param.h>
4625603Skjc#include <sys/systm.h>
47114201Sharti#include <sys/kernel.h>
48114201Sharti#include <sys/module.h>
49105576Srwatson#include <sys/mac.h>
5025603Skjc#include <sys/mbuf.h>
5125603Skjc#include <sys/socket.h>
5237939Skjc#include <sys/sockio.h>
5337939Skjc#include <sys/errno.h>
54114201Sharti#include <sys/sysctl.h>
55117630Sharti#include <sys/malloc.h>
5625603Skjc
5725603Skjc#include <net/if.h>
5825603Skjc#include <net/netisr.h>
5925603Skjc#include <net/route.h>
6025603Skjc#include <net/if_dl.h>
6125603Skjc#include <net/if_types.h>
6225603Skjc#include <net/if_atm.h>
6325603Skjc
6425603Skjc#include <netinet/in.h>
6525603Skjc#include <netinet/if_atm.h>
6625603Skjc#include <netinet/if_ether.h> /* XXX: for ETHERTYPE_* */
6737939Skjc#if defined(INET) || defined(INET6)
6825603Skjc#include <netinet/in_var.h>
6925603Skjc#endif
7025603Skjc#ifdef NATM
7125603Skjc#include <netnatm/natm.h>
7225603Skjc#endif
7325603Skjc
74116741Sharti/*
75116741Sharti * Netgraph interface functions.
76116741Sharti * These need not be protected by a lock, because ng_atm nodes are persitent.
77116741Sharti * The ng_atm module can be unloaded only if all ATM interfaces have been
78116741Sharti * unloaded, so nobody should be in the code paths accessing these function
79116741Sharti * pointers.
80116741Sharti */
81116741Shartivoid	(*ng_atm_attach_p)(struct ifnet *);
82116741Shartivoid	(*ng_atm_detach_p)(struct ifnet *);
83116741Shartiint	(*ng_atm_output_p)(struct ifnet *, struct mbuf **);
84116741Shartivoid	(*ng_atm_input_p)(struct ifnet *, struct mbuf **,
85116741Sharti	    struct atm_pseudohdr *, void *);
86116741Shartivoid	(*ng_atm_input_orphan_p)(struct ifnet *, struct mbuf *,
87116741Sharti	    struct atm_pseudohdr *, void *);
88118157Shartivoid	(*ng_atm_event_p)(struct ifnet *, uint32_t, void *);
89116741Sharti
90116741Sharti/*
91116741Sharti * Harp pseudo interface hooks
92116741Sharti */
93116741Shartivoid	(*atm_harp_input_p)(struct ifnet *ifp, struct mbuf **m,
94116741Sharti	    struct atm_pseudohdr *ah, void *rxhand);
95116741Shartivoid	(*atm_harp_attach_p)(struct ifnet *);
96116741Shartivoid	(*atm_harp_detach_p)(struct ifnet *);
97118157Shartivoid	(*atm_harp_event_p)(struct ifnet *, uint32_t, void *);
98116741Sharti
99114201ShartiSYSCTL_NODE(_hw, OID_AUTO, atm, CTLFLAG_RW, 0, "ATM hardware");
100114201Sharti
101147256SbrooksMALLOC_DEFINE(M_IFATM, "ifatm", "atm interface internals");
102147256Sbrooks
10337939Skjc#ifndef ETHERTYPE_IPV6
104116720Sharti#define	ETHERTYPE_IPV6	0x86dd
10537939Skjc#endif
10625603Skjc
107116720Sharti#define	senderr(e) do { error = (e); goto bad; } while (0)
10825603Skjc
10925603Skjc/*
11025603Skjc * atm_output: ATM output routine
11125603Skjc *   inputs:
11225603Skjc *     "ifp" = ATM interface to output to
11325603Skjc *     "m0" = the packet to output
11425603Skjc *     "dst" = the sockaddr to send to (either IP addr, or raw VPI/VCI)
11525603Skjc *     "rt0" = the route to use
11625603Skjc *   returns: error code   [0 == ok]
11725603Skjc *
11825603Skjc *   note: special semantic: if (dst == NULL) then we assume "m" already
11925603Skjc *		has an atm_pseudohdr on it and just send it directly.
12025603Skjc *		[for native mode ATM output]   if dst is null, then
12125603Skjc *		rt0 must also be NULL.
12225603Skjc */
12325603Skjcint
124116720Shartiatm_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst,
125116720Sharti    struct rtentry *rt0)
12625603Skjc{
12725603Skjc	u_int16_t etype = 0;			/* if using LLC/SNAP */
12878249Speter	int error = 0, sz;
12925603Skjc	struct atm_pseudohdr atmdst, *ad;
13059633Skjc	struct mbuf *m = m0;
13125603Skjc	struct atmllc *atmllc;
13237939Skjc	struct atmllc *llc_hdr = NULL;
13325603Skjc	u_int32_t atm_flags;
13425603Skjc
135105576Srwatson#ifdef MAC
136105576Srwatson	error = mac_check_ifnet_transmit(ifp, m);
137105576Srwatson	if (error)
138105576Srwatson		senderr(error);
139105576Srwatson#endif
140105576Srwatson
141148887Srwatson	if (!((ifp->if_flags & IFF_UP) &&
142148887Srwatson	    (ifp->if_drv_flags & IFF_DRV_RUNNING)))
14325603Skjc		senderr(ENETDOWN);
14425603Skjc
14525603Skjc	/*
14625603Skjc	 * check for non-native ATM traffic   (dst != NULL)
14725603Skjc	 */
14825603Skjc	if (dst) {
14925603Skjc		switch (dst->sa_family) {
150116720Sharti
15137939Skjc#if defined(INET) || defined(INET6)
15225603Skjc		case AF_INET:
15337939Skjc		case AF_INET6:
154128636Sluigi		{
155148954Sglebius			struct rtentry *rt = NULL;
156128636Sluigi			/*
157128636Sluigi			 * check route
158128636Sluigi			 */
159148954Sglebius			if (rt0 != NULL) {
160148954Sglebius				error = rt_check(&rt, &rt0, dst);
161148954Sglebius				if (error)
162148954Sglebius					goto bad;
163148954Sglebius				RT_UNLOCK(rt);
164148954Sglebius			}
165128636Sluigi
16646695Skjc			if (dst->sa_family == AF_INET6)
167112193Sharti			        etype = ETHERTYPE_IPV6;
16846695Skjc			else
169112193Sharti			        etype = ETHERTYPE_IP;
17025603Skjc			if (!atmresolve(rt, m, dst, &atmdst)) {
17125603Skjc				m = NULL;
17225603Skjc				/* XXX: atmresolve already free'd it */
17325603Skjc				senderr(EHOSTUNREACH);
17425603Skjc				/* XXX: put ATMARP stuff here */
17525603Skjc				/* XXX: watch who frees m on failure */
17625603Skjc			}
177128636Sluigi		}
17825603Skjc			break;
17937939Skjc#endif /* INET || INET6 */
18025603Skjc
18137939Skjc		case AF_UNSPEC:
18237939Skjc			/*
18346695Skjc			 * XXX: bpfwrite. assuming dst contains 12 bytes
18446695Skjc			 * (atm pseudo header (4) + LLC/SNAP (8))
18537939Skjc			 */
18637939Skjc			bcopy(dst->sa_data, &atmdst, sizeof(atmdst));
187116720Sharti			llc_hdr = (struct atmllc *)(dst->sa_data +
188116720Sharti			    sizeof(atmdst));
18937939Skjc			break;
19037939Skjc
19125603Skjc		default:
192121816Sbrooks#if (defined(__FreeBSD__) && __FreeBSD_version >= 501113) || \
193121816Sbrooks    defined(__NetBSD__) || defined(__OpenBSD__)
19425603Skjc			printf("%s: can't handle af%d\n", ifp->if_xname,
19525603Skjc			    dst->sa_family);
19625603Skjc#elif defined(__FreeBSD__) || defined(__bsdi__)
19725603Skjc			printf("%s%d: can't handle af%d\n", ifp->if_name,
19825603Skjc			    ifp->if_unit, dst->sa_family);
19925603Skjc#endif
20025603Skjc			senderr(EAFNOSUPPORT);
20125603Skjc		}
20225603Skjc
20325603Skjc		/*
20425603Skjc		 * must add atm_pseudohdr to data
20525603Skjc		 */
20625603Skjc		sz = sizeof(atmdst);
20725603Skjc		atm_flags = ATM_PH_FLAGS(&atmdst);
208116720Sharti		if (atm_flags & ATM_PH_LLCSNAP)
209116720Sharti			sz += 8;	/* sizeof snap == 8 */
210111119Simp		M_PREPEND(m, sz, M_DONTWAIT);
21125603Skjc		if (m == 0)
21225603Skjc			senderr(ENOBUFS);
21325603Skjc		ad = mtod(m, struct atm_pseudohdr *);
21425603Skjc		*ad = atmdst;
21525603Skjc		if (atm_flags & ATM_PH_LLCSNAP) {
21625603Skjc			atmllc = (struct atmllc *)(ad + 1);
21737939Skjc			if (llc_hdr == NULL) {
21837939Skjc			        bcopy(ATMLLC_HDR, atmllc->llchdr,
21937939Skjc				      sizeof(atmllc->llchdr));
220116720Sharti				/* note: in host order */
22137939Skjc				ATM_LLC_SETTYPE(atmllc, etype);
22237939Skjc			}
22337939Skjc			else
22437939Skjc			        bcopy(llc_hdr, atmllc, sizeof(struct atmllc));
22525603Skjc		}
22625603Skjc	}
22725603Skjc
228116741Sharti	if (ng_atm_output_p != NULL) {
229116741Sharti		if ((error = (*ng_atm_output_p)(ifp, &m)) != 0) {
230116741Sharti			if (m != NULL)
231116741Sharti				m_freem(m);
232116741Sharti			return (error);
233116741Sharti		}
234116741Sharti		if (m == NULL)
235116741Sharti			return (0);
236116741Sharti	}
237116741Sharti
23825603Skjc	/*
23925603Skjc	 * Queue message on interface, and start output if interface
24025603Skjc	 * not yet active.
24125603Skjc	 */
242117629Sharti	if (!IF_HANDOFF_ADJ(&ifp->if_snd, m, ifp,
243117629Sharti	    -(int)sizeof(struct atm_pseudohdr)))
24469152Sjlemon		return (ENOBUFS);
24525603Skjc	return (error);
24625603Skjc
24725603Skjcbad:
24825603Skjc	if (m)
24925603Skjc		m_freem(m);
25025603Skjc	return (error);
25125603Skjc}
25225603Skjc
25325603Skjc/*
25425603Skjc * Process a received ATM packet;
25525603Skjc * the packet is in the mbuf chain m.
25625603Skjc */
25725603Skjcvoid
258116720Shartiatm_input(struct ifnet *ifp, struct atm_pseudohdr *ah, struct mbuf *m,
259116720Sharti    void *rxhand)
26025603Skjc{
261111888Sjlemon	int isr;
262116720Sharti	u_int16_t etype = ETHERTYPE_IP;		/* default */
26325603Skjc
26425603Skjc	if ((ifp->if_flags & IFF_UP) == 0) {
26525603Skjc		m_freem(m);
26625603Skjc		return;
26725603Skjc	}
268105576Srwatson#ifdef MAC
269105576Srwatson	mac_create_mbuf_from_ifnet(ifp, m);
270105576Srwatson#endif
27125603Skjc	ifp->if_ibytes += m->m_pkthdr.len;
27225603Skjc
273116741Sharti	if (ng_atm_input_p != NULL) {
274116741Sharti		(*ng_atm_input_p)(ifp, &m, ah, rxhand);
275116741Sharti		if (m == NULL)
276116741Sharti			return;
277116741Sharti	}
278116741Sharti
279116741Sharti	/* not eaten by ng_atm. Maybe it's a pseudo-harp PDU? */
280116741Sharti	if (atm_harp_input_p != NULL) {
281116741Sharti		(*atm_harp_input_p)(ifp, &m, ah, rxhand);
282116741Sharti		if (m == NULL)
283116741Sharti			return;
284116741Sharti	}
285116741Sharti
28625603Skjc	if (rxhand) {
28725603Skjc#ifdef NATM
288148125Srwatson		struct natmpcb *npcb;
289116720Sharti
290148125Srwatson		/*
291148125Srwatson		 * XXXRW: this use of 'rxhand' is not a very good idea, and
292148125Srwatson		 * was subject to races even before SMPng due to the release
293148125Srwatson		 * of spl here.
294148125Srwatson		 */
295148125Srwatson		NATM_LOCK();
296148125Srwatson		npcb = rxhand;
29737939Skjc		npcb->npcb_inq++;	/* count # in queue */
298111888Sjlemon		isr = NETISR_NATM;
29937939Skjc		m->m_pkthdr.rcvif = rxhand; /* XXX: overload */
300148125Srwatson		NATM_UNLOCK();
30125603Skjc#else
302116720Sharti		printf("atm_input: NATM detected but not "
303116720Sharti		    "configured in kernel\n");
304116741Sharti		goto dropit;
30525603Skjc#endif
30625603Skjc	} else {
30737939Skjc		/*
30837939Skjc		 * handle LLC/SNAP header, if present
30937939Skjc		 */
31037939Skjc		if (ATM_PH_FLAGS(ah) & ATM_PH_LLCSNAP) {
31137939Skjc			struct atmllc *alc;
312116720Sharti
31337939Skjc			if (m->m_len < sizeof(*alc) &&
31437939Skjc			    (m = m_pullup(m, sizeof(*alc))) == 0)
31537939Skjc				return; /* failed */
31637939Skjc			alc = mtod(m, struct atmllc *);
31737939Skjc			if (bcmp(alc, ATMLLC_HDR, 6)) {
318121816Sbrooks#if (defined(__FreeBSD__) && __FreeBSD_version >= 501113) || \
319121816Sbrooks    defined(__NetBSD__) || defined(__OpenBSD__)
320116720Sharti				printf("%s: recv'd invalid LLC/SNAP frame "
321116720Sharti				    "[vp=%d,vc=%d]\n", ifp->if_xname,
322116720Sharti				    ATM_PH_VPI(ah), ATM_PH_VCI(ah));
32325603Skjc#elif defined(__FreeBSD__) || defined(__bsdi__)
324116720Sharti				printf("%s%d: recv'd invalid LLC/SNAP frame "
325116720Sharti				    "[vp=%d,vc=%d]\n", ifp->if_name,
326116720Sharti				    ifp->if_unit, ATM_PH_VPI(ah),
327116720Sharti				    ATM_PH_VCI(ah));
32825603Skjc#endif
32937939Skjc				m_freem(m);
33037939Skjc				return;
33137939Skjc			}
33237939Skjc			etype = ATM_LLC_TYPE(alc);
33337939Skjc			m_adj(m, sizeof(*alc));
33437939Skjc		}
33525603Skjc
33637939Skjc		switch (etype) {
337116720Sharti
33825603Skjc#ifdef INET
33937939Skjc		case ETHERTYPE_IP:
340111888Sjlemon			isr = NETISR_IP;
34137939Skjc			break;
34225603Skjc#endif
343116720Sharti
34437939Skjc#ifdef INET6
34537939Skjc		case ETHERTYPE_IPV6:
346111888Sjlemon			isr = NETISR_IPV6;
34737939Skjc			break;
34837939Skjc#endif
34937939Skjc		default:
350116741Sharti#ifndef NATM
351116741Sharti  dropit:
352116741Sharti#endif
353116741Sharti			if (ng_atm_input_orphan_p != NULL)
354116741Sharti				(*ng_atm_input_orphan_p)(ifp, m, ah, rxhand);
355116741Sharti			else
356116741Sharti				m_freem(m);
35737939Skjc			return;
35837939Skjc		}
35925603Skjc	}
360111888Sjlemon	netisr_dispatch(isr, m);
36125603Skjc}
36225603Skjc
36325603Skjc/*
364114201Sharti * Perform common duties while attaching to interface list.
36525603Skjc */
36625603Skjcvoid
367116720Shartiatm_ifattach(struct ifnet *ifp)
36825603Skjc{
369111774Smdodd	struct ifaddr *ifa;
370111774Smdodd	struct sockaddr_dl *sdl;
371147256Sbrooks	struct ifatm *ifatm = ifp->if_l2com;
37225603Skjc
37325603Skjc	ifp->if_addrlen = 0;
37425603Skjc	ifp->if_hdrlen = 0;
375114201Sharti	if_attach(ifp);
37625603Skjc	ifp->if_mtu = ATMMTU;
37725603Skjc	ifp->if_output = atm_output;
378106939Ssam#if 0
379106939Ssam	ifp->if_input = atm_input;
380106939Ssam#endif
38146695Skjc	ifp->if_snd.ifq_maxlen = 50;	/* dummy */
38225603Skjc
38325603Skjc#if defined(__NetBSD__) || defined(__OpenBSD__)
38472012Sphk	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
38537939Skjc#elif defined(__FreeBSD__) && (__FreeBSD__ > 2)
386160035Syar	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
38725603Skjc#elif defined(__FreeBSD__) || defined(__bsdi__)
38825603Skjc	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
38925603Skjc#endif
390160038Syar		if (ifa->ifa_addr->sa_family == AF_LINK) {
391160038Syar			sdl = (struct sockaddr_dl *)ifa->ifa_addr;
39225603Skjc			sdl->sdl_type = IFT_ATM;
39325603Skjc			sdl->sdl_alen = ifp->if_addrlen;
39425603Skjc#ifdef notyet /* if using ATMARP, store hardware address using the next line */
39525603Skjc			bcopy(ifp->hw_addr, LLADDR(sdl), ifp->if_addrlen);
39625603Skjc#endif
39725603Skjc			break;
39825603Skjc		}
39937939Skjc
400114739Sharti	ifp->if_linkmib = &ifatm->mib;
401114739Sharti	ifp->if_linkmiblen = sizeof(ifatm->mib);
402116741Sharti
403116741Sharti	if(ng_atm_attach_p)
404116741Sharti		(*ng_atm_attach_p)(ifp);
405116741Sharti	if (atm_harp_attach_p)
406116741Sharti		(*atm_harp_attach_p)(ifp);
40737939Skjc}
408114201Sharti
409114201Sharti/*
410114201Sharti * Common stuff for detaching an ATM interface
411114201Sharti */
412114201Shartivoid
413114201Shartiatm_ifdetach(struct ifnet *ifp)
414114201Sharti{
415116741Sharti	if (atm_harp_detach_p)
416116741Sharti		(*atm_harp_detach_p)(ifp);
417116741Sharti	if(ng_atm_detach_p)
418116741Sharti		(*ng_atm_detach_p)(ifp);
419114201Sharti	if_detach(ifp);
420114201Sharti}
421114201Sharti
422117630Sharti/*
423117630Sharti * Support routine for the SIOCATMGVCCS ioctl().
424117630Sharti *
425117630Sharti * This routine assumes, that the private VCC structures used by the driver
426117630Sharti * begin with a struct atmio_vcc.
427117630Sharti *
428117630Sharti * Return a table of VCCs in a freshly allocated memory area.
429117630Sharti * Here we have a problem: we first count, how many vccs we need
430117630Sharti * to return. The we allocate the memory and finally fill it in.
431117630Sharti * Because we cannot lock while calling malloc, the number of active
432117630Sharti * vccs may change while we're in malloc. So we allocate a couple of
433117630Sharti * vccs more and if space anyway is not enough re-iterate.
434117630Sharti *
435117630Sharti * We could use an sx lock for the vcc tables.
436117630Sharti */
437117630Shartistruct atmio_vcctable *
438117630Shartiatm_getvccs(struct atmio_vcc **table, u_int size, u_int start,
439117630Sharti    struct mtx *lock, int waitok)
440117630Sharti{
441117630Sharti	u_int cid, alloc;
442117630Sharti	size_t len;
443117630Sharti	struct atmio_vcctable *vccs;
444117630Sharti	struct atmio_vcc *v;
445117630Sharti
446117630Sharti	alloc = start + 10;
447117630Sharti	vccs = NULL;
448117630Sharti
449117630Sharti	for (;;) {
450117630Sharti		len = sizeof(*vccs) + alloc * sizeof(vccs->vccs[0]);
451117630Sharti		vccs = reallocf(vccs, len, M_TEMP,
452117630Sharti		    waitok ? M_WAITOK : M_NOWAIT);
453117630Sharti		if (vccs == NULL)
454117630Sharti			return (NULL);
455117630Sharti		bzero(vccs, len);
456117630Sharti
457117630Sharti		vccs->count = 0;
458117630Sharti		v = vccs->vccs;
459117630Sharti
460117630Sharti		mtx_lock(lock);
461117630Sharti		for (cid = 0; cid < size; cid++)
462117630Sharti			if (table[cid] != NULL) {
463117630Sharti				if (++vccs->count == alloc)
464117630Sharti					/* too many - try again */
465117630Sharti					break;
466117630Sharti				*v++ = *table[cid];
467117630Sharti			}
468117630Sharti		mtx_unlock(lock);
469117630Sharti
470117630Sharti		if (cid == size)
471117630Sharti			break;
472117630Sharti
473117630Sharti		alloc *= 2;
474117630Sharti	}
475117630Sharti	return (vccs);
476117630Sharti}
477117630Sharti
478118157Sharti/*
479118157Sharti * Driver or channel state has changed. Inform whoever is interested
480118157Sharti * in these events.
481118157Sharti */
482118157Shartivoid
483118157Shartiatm_event(struct ifnet *ifp, u_int event, void *arg)
484118157Sharti{
485118157Sharti	if (ng_atm_event_p != NULL)
486118157Sharti		(*ng_atm_event_p)(ifp, event, arg);
487118157Sharti	if (atm_harp_event_p != NULL)
488118157Sharti		(*atm_harp_event_p)(ifp, event, arg);
489118157Sharti}
490118157Sharti
491147256Sbrooksstatic void *
492147256Sbrooksatm_alloc(u_char type, struct ifnet *ifp)
493147256Sbrooks{
494147256Sbrooks	struct ifatm	*ifatm;
495147256Sbrooks
496147256Sbrooks	ifatm = malloc(sizeof(struct ifatm), M_IFATM, M_WAITOK | M_ZERO);
497147256Sbrooks	ifatm->ifp = ifp;
498147256Sbrooks
499147256Sbrooks	return (ifatm);
500147256Sbrooks}
501147256Sbrooks
502147256Sbrooksstatic void
503147256Sbrooksatm_free(void *com, u_char type)
504147256Sbrooks{
505147256Sbrooks
506147256Sbrooks	free(com, M_IFATM);
507147256Sbrooks}
508147256Sbrooks
509147256Sbrooksstatic int
510147256Sbrooksatm_modevent(module_t mod, int type, void *data)
511147256Sbrooks{
512147256Sbrooks	switch (type) {
513147256Sbrooks	case MOD_LOAD:
514147256Sbrooks		if_register_com_alloc(IFT_ATM, atm_alloc, atm_free);
515147256Sbrooks		break;
516147256Sbrooks	case MOD_UNLOAD:
517147256Sbrooks		if_deregister_com_alloc(IFT_ATM);
518147256Sbrooks		break;
519147256Sbrooks	default:
520147256Sbrooks		return (EOPNOTSUPP);
521147256Sbrooks	}
522147256Sbrooks
523147256Sbrooks	return (0);
524147256Sbrooks}
525147256Sbrooks
526114201Shartistatic moduledata_t atm_mod = {
527114201Sharti        "atm",
528147256Sbrooks        atm_modevent,
529114201Sharti        0
530114201Sharti};
531114201Sharti
532147256SbrooksDECLARE_MODULE(atm, atm_mod, SI_SUB_INIT_IF, SI_ORDER_ANY);
533114201ShartiMODULE_VERSION(atm, 1);
534