if_atmsubr.c revision 148125
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 148125 2005-07-18 16:55:46Z rwatson $");
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
141116720Sharti	if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING))
14225603Skjc		senderr(ENETDOWN);
14325603Skjc
14425603Skjc	/*
14525603Skjc	 * check for non-native ATM traffic   (dst != NULL)
14625603Skjc	 */
14725603Skjc	if (dst) {
14825603Skjc		switch (dst->sa_family) {
149116720Sharti
15037939Skjc#if defined(INET) || defined(INET6)
15125603Skjc		case AF_INET:
15237939Skjc		case AF_INET6:
153128636Sluigi		{
154128636Sluigi			struct rtentry *rt;
155128636Sluigi			/*
156128636Sluigi			 * check route
157128636Sluigi			 */
158128636Sluigi			error = rt_check(&rt, &rt0, dst);
159128636Sluigi			if (error)
160128636Sluigi				goto bad;
161128636Sluigi
16246695Skjc			if (dst->sa_family == AF_INET6)
163112193Sharti			        etype = ETHERTYPE_IPV6;
16446695Skjc			else
165112193Sharti			        etype = ETHERTYPE_IP;
16625603Skjc			if (!atmresolve(rt, m, dst, &atmdst)) {
16725603Skjc				m = NULL;
16825603Skjc				/* XXX: atmresolve already free'd it */
16925603Skjc				senderr(EHOSTUNREACH);
17025603Skjc				/* XXX: put ATMARP stuff here */
17125603Skjc				/* XXX: watch who frees m on failure */
17225603Skjc			}
173128636Sluigi		}
17425603Skjc			break;
17537939Skjc#endif /* INET || INET6 */
17625603Skjc
17737939Skjc		case AF_UNSPEC:
17837939Skjc			/*
17946695Skjc			 * XXX: bpfwrite. assuming dst contains 12 bytes
18046695Skjc			 * (atm pseudo header (4) + LLC/SNAP (8))
18137939Skjc			 */
18237939Skjc			bcopy(dst->sa_data, &atmdst, sizeof(atmdst));
183116720Sharti			llc_hdr = (struct atmllc *)(dst->sa_data +
184116720Sharti			    sizeof(atmdst));
18537939Skjc			break;
18637939Skjc
18725603Skjc		default:
188121816Sbrooks#if (defined(__FreeBSD__) && __FreeBSD_version >= 501113) || \
189121816Sbrooks    defined(__NetBSD__) || defined(__OpenBSD__)
19025603Skjc			printf("%s: can't handle af%d\n", ifp->if_xname,
19125603Skjc			    dst->sa_family);
19225603Skjc#elif defined(__FreeBSD__) || defined(__bsdi__)
19325603Skjc			printf("%s%d: can't handle af%d\n", ifp->if_name,
19425603Skjc			    ifp->if_unit, dst->sa_family);
19525603Skjc#endif
19625603Skjc			senderr(EAFNOSUPPORT);
19725603Skjc		}
19825603Skjc
19925603Skjc		/*
20025603Skjc		 * must add atm_pseudohdr to data
20125603Skjc		 */
20225603Skjc		sz = sizeof(atmdst);
20325603Skjc		atm_flags = ATM_PH_FLAGS(&atmdst);
204116720Sharti		if (atm_flags & ATM_PH_LLCSNAP)
205116720Sharti			sz += 8;	/* sizeof snap == 8 */
206111119Simp		M_PREPEND(m, sz, M_DONTWAIT);
20725603Skjc		if (m == 0)
20825603Skjc			senderr(ENOBUFS);
20925603Skjc		ad = mtod(m, struct atm_pseudohdr *);
21025603Skjc		*ad = atmdst;
21125603Skjc		if (atm_flags & ATM_PH_LLCSNAP) {
21225603Skjc			atmllc = (struct atmllc *)(ad + 1);
21337939Skjc			if (llc_hdr == NULL) {
21437939Skjc			        bcopy(ATMLLC_HDR, atmllc->llchdr,
21537939Skjc				      sizeof(atmllc->llchdr));
216116720Sharti				/* note: in host order */
21737939Skjc				ATM_LLC_SETTYPE(atmllc, etype);
21837939Skjc			}
21937939Skjc			else
22037939Skjc			        bcopy(llc_hdr, atmllc, sizeof(struct atmllc));
22125603Skjc		}
22225603Skjc	}
22325603Skjc
224116741Sharti	if (ng_atm_output_p != NULL) {
225116741Sharti		if ((error = (*ng_atm_output_p)(ifp, &m)) != 0) {
226116741Sharti			if (m != NULL)
227116741Sharti				m_freem(m);
228116741Sharti			return (error);
229116741Sharti		}
230116741Sharti		if (m == NULL)
231116741Sharti			return (0);
232116741Sharti	}
233116741Sharti
23425603Skjc	/*
23525603Skjc	 * Queue message on interface, and start output if interface
23625603Skjc	 * not yet active.
23725603Skjc	 */
238117629Sharti	if (!IF_HANDOFF_ADJ(&ifp->if_snd, m, ifp,
239117629Sharti	    -(int)sizeof(struct atm_pseudohdr)))
24069152Sjlemon		return (ENOBUFS);
24125603Skjc	return (error);
24225603Skjc
24325603Skjcbad:
24425603Skjc	if (m)
24525603Skjc		m_freem(m);
24625603Skjc	return (error);
24725603Skjc}
24825603Skjc
24925603Skjc/*
25025603Skjc * Process a received ATM packet;
25125603Skjc * the packet is in the mbuf chain m.
25225603Skjc */
25325603Skjcvoid
254116720Shartiatm_input(struct ifnet *ifp, struct atm_pseudohdr *ah, struct mbuf *m,
255116720Sharti    void *rxhand)
25625603Skjc{
257111888Sjlemon	int isr;
258116720Sharti	u_int16_t etype = ETHERTYPE_IP;		/* default */
25925603Skjc
26025603Skjc	if ((ifp->if_flags & IFF_UP) == 0) {
26125603Skjc		m_freem(m);
26225603Skjc		return;
26325603Skjc	}
264105576Srwatson#ifdef MAC
265105576Srwatson	mac_create_mbuf_from_ifnet(ifp, m);
266105576Srwatson#endif
26725603Skjc	ifp->if_ibytes += m->m_pkthdr.len;
26825603Skjc
269116741Sharti	if (ng_atm_input_p != NULL) {
270116741Sharti		(*ng_atm_input_p)(ifp, &m, ah, rxhand);
271116741Sharti		if (m == NULL)
272116741Sharti			return;
273116741Sharti	}
274116741Sharti
275116741Sharti	/* not eaten by ng_atm. Maybe it's a pseudo-harp PDU? */
276116741Sharti	if (atm_harp_input_p != NULL) {
277116741Sharti		(*atm_harp_input_p)(ifp, &m, ah, rxhand);
278116741Sharti		if (m == NULL)
279116741Sharti			return;
280116741Sharti	}
281116741Sharti
28225603Skjc	if (rxhand) {
28325603Skjc#ifdef NATM
284148125Srwatson		struct natmpcb *npcb;
285116720Sharti
286148125Srwatson		/*
287148125Srwatson		 * XXXRW: this use of 'rxhand' is not a very good idea, and
288148125Srwatson		 * was subject to races even before SMPng due to the release
289148125Srwatson		 * of spl here.
290148125Srwatson		 */
291148125Srwatson		NATM_LOCK();
292148125Srwatson		npcb = rxhand;
29337939Skjc		npcb->npcb_inq++;	/* count # in queue */
294111888Sjlemon		isr = NETISR_NATM;
29537939Skjc		m->m_pkthdr.rcvif = rxhand; /* XXX: overload */
296148125Srwatson		NATM_UNLOCK();
29725603Skjc#else
298116720Sharti		printf("atm_input: NATM detected but not "
299116720Sharti		    "configured in kernel\n");
300116741Sharti		goto dropit;
30125603Skjc#endif
30225603Skjc	} else {
30337939Skjc		/*
30437939Skjc		 * handle LLC/SNAP header, if present
30537939Skjc		 */
30637939Skjc		if (ATM_PH_FLAGS(ah) & ATM_PH_LLCSNAP) {
30737939Skjc			struct atmllc *alc;
308116720Sharti
30937939Skjc			if (m->m_len < sizeof(*alc) &&
31037939Skjc			    (m = m_pullup(m, sizeof(*alc))) == 0)
31137939Skjc				return; /* failed */
31237939Skjc			alc = mtod(m, struct atmllc *);
31337939Skjc			if (bcmp(alc, ATMLLC_HDR, 6)) {
314121816Sbrooks#if (defined(__FreeBSD__) && __FreeBSD_version >= 501113) || \
315121816Sbrooks    defined(__NetBSD__) || defined(__OpenBSD__)
316116720Sharti				printf("%s: recv'd invalid LLC/SNAP frame "
317116720Sharti				    "[vp=%d,vc=%d]\n", ifp->if_xname,
318116720Sharti				    ATM_PH_VPI(ah), ATM_PH_VCI(ah));
31925603Skjc#elif defined(__FreeBSD__) || defined(__bsdi__)
320116720Sharti				printf("%s%d: recv'd invalid LLC/SNAP frame "
321116720Sharti				    "[vp=%d,vc=%d]\n", ifp->if_name,
322116720Sharti				    ifp->if_unit, ATM_PH_VPI(ah),
323116720Sharti				    ATM_PH_VCI(ah));
32425603Skjc#endif
32537939Skjc				m_freem(m);
32637939Skjc				return;
32737939Skjc			}
32837939Skjc			etype = ATM_LLC_TYPE(alc);
32937939Skjc			m_adj(m, sizeof(*alc));
33037939Skjc		}
33125603Skjc
33237939Skjc		switch (etype) {
333116720Sharti
33425603Skjc#ifdef INET
33537939Skjc		case ETHERTYPE_IP:
336111888Sjlemon			isr = NETISR_IP;
33737939Skjc			break;
33825603Skjc#endif
339116720Sharti
34037939Skjc#ifdef INET6
34137939Skjc		case ETHERTYPE_IPV6:
342111888Sjlemon			isr = NETISR_IPV6;
34337939Skjc			break;
34437939Skjc#endif
34537939Skjc		default:
346116741Sharti#ifndef NATM
347116741Sharti  dropit:
348116741Sharti#endif
349116741Sharti			if (ng_atm_input_orphan_p != NULL)
350116741Sharti				(*ng_atm_input_orphan_p)(ifp, m, ah, rxhand);
351116741Sharti			else
352116741Sharti				m_freem(m);
35337939Skjc			return;
35437939Skjc		}
35525603Skjc	}
356111888Sjlemon	netisr_dispatch(isr, m);
35725603Skjc}
35825603Skjc
35925603Skjc/*
360114201Sharti * Perform common duties while attaching to interface list.
36125603Skjc */
36225603Skjcvoid
363116720Shartiatm_ifattach(struct ifnet *ifp)
36425603Skjc{
365111774Smdodd	struct ifaddr *ifa;
366111774Smdodd	struct sockaddr_dl *sdl;
367147256Sbrooks	struct ifatm *ifatm = ifp->if_l2com;
36825603Skjc
36925603Skjc	ifp->if_addrlen = 0;
37025603Skjc	ifp->if_hdrlen = 0;
371114201Sharti	if_attach(ifp);
37225603Skjc	ifp->if_mtu = ATMMTU;
37325603Skjc	ifp->if_output = atm_output;
374106939Ssam#if 0
375106939Ssam	ifp->if_input = atm_input;
376106939Ssam#endif
37746695Skjc	ifp->if_snd.ifq_maxlen = 50;	/* dummy */
37825603Skjc
37925603Skjc#if defined(__NetBSD__) || defined(__OpenBSD__)
38072012Sphk	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
38137939Skjc#elif defined(__FreeBSD__) && (__FreeBSD__ > 2)
38271959Sphk	for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa;
38371959Sphk	    ifa = TAILQ_NEXT(ifa, ifa_link))
38425603Skjc#elif defined(__FreeBSD__) || defined(__bsdi__)
38525603Skjc	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
38625603Skjc#endif
38725603Skjc		if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
38825603Skjc		    sdl->sdl_family == AF_LINK) {
38925603Skjc			sdl->sdl_type = IFT_ATM;
39025603Skjc			sdl->sdl_alen = ifp->if_addrlen;
39125603Skjc#ifdef notyet /* if using ATMARP, store hardware address using the next line */
39225603Skjc			bcopy(ifp->hw_addr, LLADDR(sdl), ifp->if_addrlen);
39325603Skjc#endif
39425603Skjc			break;
39525603Skjc		}
39637939Skjc
397114739Sharti	ifp->if_linkmib = &ifatm->mib;
398114739Sharti	ifp->if_linkmiblen = sizeof(ifatm->mib);
399116741Sharti
400116741Sharti	if(ng_atm_attach_p)
401116741Sharti		(*ng_atm_attach_p)(ifp);
402116741Sharti	if (atm_harp_attach_p)
403116741Sharti		(*atm_harp_attach_p)(ifp);
40437939Skjc}
405114201Sharti
406114201Sharti/*
407114201Sharti * Common stuff for detaching an ATM interface
408114201Sharti */
409114201Shartivoid
410114201Shartiatm_ifdetach(struct ifnet *ifp)
411114201Sharti{
412116741Sharti	if (atm_harp_detach_p)
413116741Sharti		(*atm_harp_detach_p)(ifp);
414116741Sharti	if(ng_atm_detach_p)
415116741Sharti		(*ng_atm_detach_p)(ifp);
416114201Sharti	if_detach(ifp);
417114201Sharti}
418114201Sharti
419117630Sharti/*
420117630Sharti * Support routine for the SIOCATMGVCCS ioctl().
421117630Sharti *
422117630Sharti * This routine assumes, that the private VCC structures used by the driver
423117630Sharti * begin with a struct atmio_vcc.
424117630Sharti *
425117630Sharti * Return a table of VCCs in a freshly allocated memory area.
426117630Sharti * Here we have a problem: we first count, how many vccs we need
427117630Sharti * to return. The we allocate the memory and finally fill it in.
428117630Sharti * Because we cannot lock while calling malloc, the number of active
429117630Sharti * vccs may change while we're in malloc. So we allocate a couple of
430117630Sharti * vccs more and if space anyway is not enough re-iterate.
431117630Sharti *
432117630Sharti * We could use an sx lock for the vcc tables.
433117630Sharti */
434117630Shartistruct atmio_vcctable *
435117630Shartiatm_getvccs(struct atmio_vcc **table, u_int size, u_int start,
436117630Sharti    struct mtx *lock, int waitok)
437117630Sharti{
438117630Sharti	u_int cid, alloc;
439117630Sharti	size_t len;
440117630Sharti	struct atmio_vcctable *vccs;
441117630Sharti	struct atmio_vcc *v;
442117630Sharti
443117630Sharti	alloc = start + 10;
444117630Sharti	vccs = NULL;
445117630Sharti
446117630Sharti	for (;;) {
447117630Sharti		len = sizeof(*vccs) + alloc * sizeof(vccs->vccs[0]);
448117630Sharti		vccs = reallocf(vccs, len, M_TEMP,
449117630Sharti		    waitok ? M_WAITOK : M_NOWAIT);
450117630Sharti		if (vccs == NULL)
451117630Sharti			return (NULL);
452117630Sharti		bzero(vccs, len);
453117630Sharti
454117630Sharti		vccs->count = 0;
455117630Sharti		v = vccs->vccs;
456117630Sharti
457117630Sharti		mtx_lock(lock);
458117630Sharti		for (cid = 0; cid < size; cid++)
459117630Sharti			if (table[cid] != NULL) {
460117630Sharti				if (++vccs->count == alloc)
461117630Sharti					/* too many - try again */
462117630Sharti					break;
463117630Sharti				*v++ = *table[cid];
464117630Sharti			}
465117630Sharti		mtx_unlock(lock);
466117630Sharti
467117630Sharti		if (cid == size)
468117630Sharti			break;
469117630Sharti
470117630Sharti		alloc *= 2;
471117630Sharti	}
472117630Sharti	return (vccs);
473117630Sharti}
474117630Sharti
475118157Sharti/*
476118157Sharti * Driver or channel state has changed. Inform whoever is interested
477118157Sharti * in these events.
478118157Sharti */
479118157Shartivoid
480118157Shartiatm_event(struct ifnet *ifp, u_int event, void *arg)
481118157Sharti{
482118157Sharti	if (ng_atm_event_p != NULL)
483118157Sharti		(*ng_atm_event_p)(ifp, event, arg);
484118157Sharti	if (atm_harp_event_p != NULL)
485118157Sharti		(*atm_harp_event_p)(ifp, event, arg);
486118157Sharti}
487118157Sharti
488147256Sbrooksstatic void *
489147256Sbrooksatm_alloc(u_char type, struct ifnet *ifp)
490147256Sbrooks{
491147256Sbrooks	struct ifatm	*ifatm;
492147256Sbrooks
493147256Sbrooks	ifatm = malloc(sizeof(struct ifatm), M_IFATM, M_WAITOK | M_ZERO);
494147256Sbrooks	ifatm->ifp = ifp;
495147256Sbrooks
496147256Sbrooks	return (ifatm);
497147256Sbrooks}
498147256Sbrooks
499147256Sbrooksstatic void
500147256Sbrooksatm_free(void *com, u_char type)
501147256Sbrooks{
502147256Sbrooks
503147256Sbrooks	free(com, M_IFATM);
504147256Sbrooks}
505147256Sbrooks
506147256Sbrooksstatic int
507147256Sbrooksatm_modevent(module_t mod, int type, void *data)
508147256Sbrooks{
509147256Sbrooks	switch (type) {
510147256Sbrooks	case MOD_LOAD:
511147256Sbrooks		if_register_com_alloc(IFT_ATM, atm_alloc, atm_free);
512147256Sbrooks		break;
513147256Sbrooks	case MOD_UNLOAD:
514147256Sbrooks		if_deregister_com_alloc(IFT_ATM);
515147256Sbrooks		break;
516147256Sbrooks	default:
517147256Sbrooks		return (EOPNOTSUPP);
518147256Sbrooks	}
519147256Sbrooks
520147256Sbrooks	return (0);
521147256Sbrooks}
522147256Sbrooks
523114201Shartistatic moduledata_t atm_mod = {
524114201Sharti        "atm",
525147256Sbrooks        atm_modevent,
526114201Sharti        0
527114201Sharti};
528114201Sharti
529147256SbrooksDECLARE_MODULE(atm, atm_mod, SI_SUB_INIT_IF, SI_ORDER_ANY);
530114201ShartiMODULE_VERSION(atm, 1);
531