natm.c revision 165900
1139823Simp/*-
2165900Srwatson * Copyright (c) 2005-2006 Robert N. M. Watson
3165900Srwatson * All rights reserved.
425605Skjc *
5165900Srwatson * Redistribution and use in source and binary forms, with or without
6165900Srwatson * modification, are permitted provided that the following conditions
7165900Srwatson * are met:
8165900Srwatson * 1. Redistributions of source code must retain the above copyright
9165900Srwatson *    notice, this list of conditions and the following disclaimer.
10165900Srwatson * 2. Redistributions in binary form must reproduce the above copyright
11165900Srwatson *    notice, this list of conditions and the following disclaimer in the
12165900Srwatson *    documentation and/or other materials provided with the distribution.
13165900Srwatson *
14165900Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15165900Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16165900Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17165900Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18165900Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19165900Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20165900Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21165900Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22165900Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23165900Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24165900Srwatson * SUCH DAMAGE.
25165900Srwatson *
2625605Skjc * Copyright (c) 1996 Charles D. Cranor and Washington University.
2725605Skjc * All rights reserved.
2825605Skjc *
2925605Skjc * Redistribution and use in source and binary forms, with or without
3025605Skjc * modification, are permitted provided that the following conditions
3125605Skjc * are met:
3225605Skjc * 1. Redistributions of source code must retain the above copyright
3325605Skjc *    notice, this list of conditions and the following disclaimer.
3425605Skjc * 2. Redistributions in binary form must reproduce the above copyright
3525605Skjc *    notice, this list of conditions and the following disclaimer in the
3625605Skjc *    documentation and/or other materials provided with the distribution.
3725605Skjc * 3. All advertising materials mentioning features or use of this software
3825605Skjc *    must display the following acknowledgement:
3925605Skjc *      This product includes software developed by Charles D. Cranor and
4025605Skjc *      Washington University.
4125605Skjc * 4. The name of the author may not be used to endorse or promote products
4225605Skjc *    derived from this software without specific prior written permission.
4325605Skjc *
4425605Skjc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
4525605Skjc * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
4625605Skjc * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
4725605Skjc * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
4825605Skjc * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4925605Skjc * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
5025605Skjc * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
5125605Skjc * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5225605Skjc * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
5325605Skjc * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54165900Srwatson *
55165900Srwatson * $NetBSD: natm.c,v 1.5 1996/11/09 03:26:26 chuck Exp $
5625605Skjc */
5725605Skjc
5825605Skjc/*
59157985Srwatson * natm.c: Native mode ATM access (both aal0 and aal5).
6025605Skjc */
6125605Skjc
62116189Sobrien#include <sys/cdefs.h>
63116189Sobrien__FBSDID("$FreeBSD: head/sys/netnatm/natm.c 165900 2007-01-08 22:30:39Z rwatson $");
64116189Sobrien
6525605Skjc#include <sys/param.h>
6695759Stanimura#include <sys/conf.h>
6725605Skjc#include <sys/kernel.h>
6895759Stanimura#include <sys/lock.h>
6929024Sbde#include <sys/malloc.h>
7025605Skjc#include <sys/mbuf.h>
7195759Stanimura#include <sys/protosw.h>
7295759Stanimura#include <sys/signalvar.h>
7325605Skjc#include <sys/socket.h>
7425605Skjc#include <sys/socketvar.h>
7595759Stanimura#include <sys/sockio.h>
7695759Stanimura#include <sys/sx.h>
7795759Stanimura#include <sys/systm.h>
78118541Sharti#include <sys/sysctl.h>
7925605Skjc
8025605Skjc#include <net/if.h>
8125605Skjc#include <net/if_atm.h>
8225605Skjc#include <net/netisr.h>
8325605Skjc
8425605Skjc#include <netinet/in.h>
8525605Skjc
8625605Skjc#include <netnatm/natm.h>
8725605Skjc
88157985Srwatsonstatic const u_long	natm5_sendspace = 16*1024;
89157985Srwatsonstatic const u_long	natm5_recvspace = 16*1024;
9025605Skjc
91157985Srwatsonstatic const u_long	natm0_sendspace = 16*1024;
92157985Srwatsonstatic const u_long	natm0_recvspace = 16*1024;
9325605Skjc
94157985Srwatson/*
95157985Srwatson * netnatm global subsystem lock, protects all global data structures in
96157985Srwatson * netnatm.
97157985Srwatson */
98157985Srwatsonstruct mtx	natm_mtx;
99148125Srwatson
10025605Skjc/*
101157985Srwatson * User socket requests.
10225605Skjc */
103157985Srwatsonstatic int	natm_usr_attach(struct socket *, int, d_thread_t *);
104157985Srwatsonstatic void	natm_usr_detach(struct socket *);
105157985Srwatsonstatic int	natm_usr_connect(struct socket *, struct sockaddr *,
106157985Srwatson		    d_thread_t *);
107157985Srwatsonstatic int	natm_usr_disconnect(struct socket *);
108157985Srwatsonstatic int	natm_usr_shutdown(struct socket *);
109157985Srwatsonstatic int	natm_usr_send(struct socket *, int, struct mbuf *,
110157985Srwatson		    struct sockaddr *, struct mbuf *, d_thread_t *);
111157985Srwatsonstatic int	natm_usr_peeraddr(struct socket *, struct sockaddr **);
112157985Srwatsonstatic int	natm_usr_control(struct socket *, u_long, caddr_t,
113157985Srwatson		    struct ifnet *, d_thread_t *);
114157985Srwatsonstatic void	natm_usr_abort(struct socket *);
115157985Srwatsonstatic int	natm_usr_bind(struct socket *, struct sockaddr *,
116157985Srwatson		    d_thread_t *);
117157985Srwatsonstatic int	natm_usr_sockaddr(struct socket *, struct sockaddr **);
11825605Skjc
11925605Skjcstatic int
12091458Speternatm_usr_attach(struct socket *so, int proto, d_thread_t *p)
12125605Skjc{
122157985Srwatson	struct natmpcb *npcb;
123157985Srwatson	int error = 0;
12425605Skjc
125157985Srwatson	npcb = (struct natmpcb *)so->so_pcb;
126157985Srwatson	KASSERT(npcb == NULL, ("natm_usr_attach: so_pcb != NULL"));
12725605Skjc
128157985Srwatson	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
129157985Srwatson		if (proto == PROTO_NATMAAL5)
130157985Srwatson			error = soreserve(so, natm5_sendspace,
131157985Srwatson			    natm5_recvspace);
132157985Srwatson		else
133157985Srwatson			error = soreserve(so, natm0_sendspace,
134157985Srwatson			    natm0_recvspace);
135157985Srwatson		if (error)
136157985Srwatson			return (error);
137157985Srwatson	}
138157985Srwatson	so->so_pcb = npcb = npcb_alloc(M_WAITOK);
139157985Srwatson	npcb->npcb_socket = so;
140157985Srwatson	return (error);
14125605Skjc}
14225605Skjc
143157370Srwatsonstatic void
14425605Skjcnatm_usr_detach(struct socket *so)
14525605Skjc{
146157985Srwatson	struct natmpcb *npcb;
14725605Skjc
148157985Srwatson	npcb = (struct natmpcb *)so->so_pcb;
149157985Srwatson	KASSERT(npcb != NULL, ("natm_usr_detach: npcb == NULL"));
150157983Srwatson
151157985Srwatson	NATM_LOCK();
152157985Srwatson	npcb_free(npcb, NPCB_DESTROY);	/* drain */
153157985Srwatson	so->so_pcb = NULL;
154157985Srwatson	NATM_UNLOCK();
15525605Skjc}
15625605Skjc
15725605Skjcstatic int
15891458Speternatm_usr_connect(struct socket *so, struct sockaddr *nam, d_thread_t *p)
15925605Skjc{
160157985Srwatson	struct natmpcb *npcb;
161157985Srwatson	struct sockaddr_natm *snatm;
162157985Srwatson	struct atmio_openvcc op;
163157985Srwatson	struct ifnet *ifp;
164157985Srwatson	int error = 0;
165157985Srwatson	int proto = so->so_proto->pr_protocol;
16625605Skjc
167157985Srwatson	npcb = (struct natmpcb *)so->so_pcb;
168157985Srwatson	KASSERT(npcb != NULL, ("natm_usr_connect: npcb == NULL"));
16925605Skjc
170157985Srwatson	/*
171157985Srwatson	 * Validate nam and npcb.
172157985Srwatson	 */
173157985Srwatson	NATM_LOCK();
174157985Srwatson	snatm = (struct sockaddr_natm *)nam;
175157985Srwatson	if (snatm->snatm_len != sizeof(*snatm) ||
176157985Srwatson		(npcb->npcb_flags & NPCB_FREE) == 0) {
177157985Srwatson		NATM_UNLOCK();
178157985Srwatson		return (EINVAL);
179157985Srwatson	}
180157985Srwatson	if (snatm->snatm_family != AF_NATM) {
181157985Srwatson		NATM_UNLOCK();
182157985Srwatson		return (EAFNOSUPPORT);
183157985Srwatson	}
18425605Skjc
185157985Srwatson	snatm->snatm_if[IFNAMSIZ - 1] = '\0';	/* XXX ensure null termination
186118541Sharti						   since ifunit() uses strcmp */
18725605Skjc
188157985Srwatson	/*
189157985Srwatson	 * Convert interface string to ifp, validate.
190157985Srwatson	 */
191157985Srwatson	ifp = ifunit(snatm->snatm_if);
192157985Srwatson	if (ifp == NULL || (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
193157985Srwatson		NATM_UNLOCK();
194157985Srwatson		return (ENXIO);
195157985Srwatson	}
196157985Srwatson	if (ifp->if_output != atm_output) {
197157985Srwatson		NATM_UNLOCK();
198157985Srwatson		return (EAFNOSUPPORT);
199157985Srwatson	}
20025605Skjc
201157985Srwatson	/*
202157985Srwatson	 * Register us with the NATM PCB layer.
203157985Srwatson	 */
204157985Srwatson	if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) {
205157985Srwatson		NATM_UNLOCK();
206157985Srwatson		return (EADDRINUSE);
207157985Srwatson	}
208157985Srwatson
209157985Srwatson	/*
210157985Srwatson	 * Open the channel.
211157985Srwatson	 *
212157985Srwatson	 * XXXRW: Eventually desirable to hold mutex over ioctl?
213157985Srwatson	 */
214157985Srwatson	bzero(&op, sizeof(op));
215157985Srwatson	op.rxhand = npcb;
216157985Srwatson	op.param.flags = ATMIO_FLAG_PVC;
217157985Srwatson	op.param.vpi = npcb->npcb_vpi;
218157985Srwatson	op.param.vci = npcb->npcb_vci;
219157985Srwatson	op.param.rmtu = op.param.tmtu = ifp->if_mtu;
220157985Srwatson	op.param.aal = (proto == PROTO_NATMAAL5) ? ATMIO_AAL_5 : ATMIO_AAL_0;
221157985Srwatson	op.param.traffic = ATMIO_TRAFFIC_UBR;
222157984Srwatson	NATM_UNLOCK();
22325605Skjc
224157985Srwatson	IFF_LOCKGIANT(ifp);
225157985Srwatson	if (ifp->if_ioctl == NULL ||
226157985Srwatson	    ifp->if_ioctl(ifp, SIOCATMOPENVCC, (caddr_t)&op) != 0) {
227157985Srwatson		IFF_UNLOCKGIANT(ifp);
228157985Srwatson		return (EIO);
229157985Srwatson	}
230148125Srwatson	IFF_UNLOCKGIANT(ifp);
231157985Srwatson	soisconnected(so);
232157985Srwatson	return (error);
23325605Skjc}
23425605Skjc
23525605Skjcstatic int
23625605Skjcnatm_usr_disconnect(struct socket *so)
23725605Skjc{
238157985Srwatson	struct natmpcb *npcb;
239157985Srwatson	struct atmio_closevcc cl;
240157985Srwatson	struct ifnet *ifp;
241157985Srwatson	int error = 0;
24225605Skjc
243157985Srwatson	npcb = (struct natmpcb *)so->so_pcb;
244157985Srwatson	KASSERT(npcb != NULL, ("natm_usr_disconnect: npcb == NULL"));
24525605Skjc
246157985Srwatson	NATM_LOCK();
247157985Srwatson	if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
248157985Srwatson		NATM_UNLOCK();
249157985Srwatson		printf("natm: disconnected check\n");
250157985Srwatson		return (EIO);
251157985Srwatson	}
252157985Srwatson	ifp = npcb->npcb_ifp;
253157985Srwatson
254157985Srwatson	/*
255157985Srwatson	 * Disable rx.
256157985Srwatson	 *
257157985Srwatson	 * XXXRW: Eventually desirable to hold mutex over ioctl?
258157985Srwatson	 */
259157985Srwatson	cl.vpi = npcb->npcb_vpi;
260157985Srwatson	cl.vci = npcb->npcb_vci;
261157984Srwatson	NATM_UNLOCK();
262157985Srwatson	if (ifp->if_ioctl != NULL) {
263157985Srwatson		IFF_LOCKGIANT(ifp);
264157985Srwatson		ifp->if_ioctl(ifp, SIOCATMCLOSEVCC, (caddr_t)&cl);
265157985Srwatson		IFF_UNLOCKGIANT(ifp);
266157985Srwatson	}
267157985Srwatson	soisdisconnected(so);
268157985Srwatson	return (error);
26925605Skjc}
27025605Skjc
27125605Skjcstatic int
27225605Skjcnatm_usr_shutdown(struct socket *so)
27325605Skjc{
274157985Srwatson
275157985Srwatson	socantsendmore(so);
276157985Srwatson	return (0);
27725605Skjc}
27825605Skjc
27925605Skjcstatic int
28028270Swollmannatm_usr_send(struct socket *so, int flags, struct mbuf *m,
281157985Srwatson	struct sockaddr *nam, struct mbuf *control, d_thread_t *p)
28225605Skjc{
283157985Srwatson	struct natmpcb *npcb;
284157985Srwatson	struct atm_pseudohdr *aph;
285157985Srwatson	int error = 0;
286157985Srwatson	int proto = so->so_proto->pr_protocol;
28725605Skjc
288157985Srwatson	npcb = (struct natmpcb *)so->so_pcb;
289157985Srwatson	KASSERT(npcb != NULL, ("natm_usr_send: npcb == NULL"));
29025605Skjc
291157985Srwatson	NATM_LOCK();
292157985Srwatson	if (control && control->m_len) {
293157985Srwatson		NATM_UNLOCK();
294157985Srwatson		m_freem(control);
295157985Srwatson		m_freem(m);
296157985Srwatson		return (EINVAL);
297157985Srwatson	}
29825605Skjc
299157985Srwatson	/*
300157985Srwatson	 * Send the data.  We must put an atm_pseudohdr on first.
301157985Srwatson	 */
302157985Srwatson	M_PREPEND(m, sizeof(*aph), M_DONTWAIT);
303157985Srwatson	if (m == NULL) {
304157985Srwatson		NATM_UNLOCK();
305157985Srwatson		m_freem(control);
306157985Srwatson		return (ENOBUFS);
307157985Srwatson	}
308157985Srwatson	aph = mtod(m, struct atm_pseudohdr *);
309157985Srwatson	ATM_PH_VPI(aph) = npcb->npcb_vpi;
310157985Srwatson	ATM_PH_SETVCI(aph, npcb->npcb_vci);
311157985Srwatson	ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
312157985Srwatson	error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
313157984Srwatson	NATM_UNLOCK();
314157985Srwatson	return (error);
31525605Skjc}
31625605Skjc
31725605Skjcstatic int
31828270Swollmannatm_usr_peeraddr(struct socket *so, struct sockaddr **nam)
31925605Skjc{
320157985Srwatson	struct natmpcb *npcb;
321157985Srwatson	struct sockaddr_natm *snatm, ssnatm;
32225605Skjc
323157985Srwatson	npcb = (struct natmpcb *)so->so_pcb;
324157985Srwatson	KASSERT(npcb != NULL, ("natm_usr_peeraddr: npcb == NULL"));
32525605Skjc
326157985Srwatson	NATM_LOCK();
327157985Srwatson	snatm = &ssnatm;
328157985Srwatson	bzero(snatm, sizeof(*snatm));
329157985Srwatson	snatm->snatm_len = sizeof(*snatm);
330157985Srwatson	snatm->snatm_family = AF_NATM;
331157985Srwatson	strlcpy(snatm->snatm_if, npcb->npcb_ifp->if_xname,
332157985Srwatson	    sizeof(snatm->snatm_if));
333157985Srwatson	snatm->snatm_vci = npcb->npcb_vci;
334157985Srwatson	snatm->snatm_vpi = npcb->npcb_vpi;
335157985Srwatson	NATM_UNLOCK();
336157985Srwatson	*nam = sodupsockaddr((struct sockaddr *)snatm, M_WAITOK);
337157985Srwatson	return (0);
33825605Skjc}
33925605Skjc
34025605Skjcstatic int
34136735Sdfrnatm_usr_control(struct socket *so, u_long cmd, caddr_t arg,
342157985Srwatson	struct ifnet *ifp, d_thread_t *p)
34325605Skjc{
344157985Srwatson	struct natmpcb *npcb;
345157985Srwatson	int error;
34625605Skjc
347157985Srwatson	npcb = (struct natmpcb *)so->so_pcb;
348157985Srwatson	KASSERT(npcb != NULL, ("natm_usr_control: npcb == NULL"));
34925605Skjc
350157985Srwatson	if (ifp == NULL || ifp->if_ioctl == NULL)
351157985Srwatson		return (EOPNOTSUPP);
352157985Srwatson	IFF_LOCKGIANT(ifp);
353157985Srwatson	error = ((*ifp->if_ioctl)(ifp, cmd, arg));
354157985Srwatson	IFF_UNLOCKGIANT(ifp);
355157985Srwatson	return (error);
35625605Skjc}
35725605Skjc
358157366Srwatsonstatic void
35925605Skjcnatm_usr_abort(struct socket *so)
36025605Skjc{
361157985Srwatson
36225605Skjc}
36325605Skjc
364160549Srwatsonstatic void
365160549Srwatsonnatm_usr_close(struct socket *so)
366160549Srwatson{
367160549Srwatson
368160549Srwatson}
369160549Srwatson
37025605Skjcstatic int
37191458Speternatm_usr_bind(struct socket *so, struct sockaddr *nam, d_thread_t *p)
37225605Skjc{
373157985Srwatson
374157985Srwatson	return (EOPNOTSUPP);
37525605Skjc}
37625605Skjc
37725605Skjcstatic int
37828270Swollmannatm_usr_sockaddr(struct socket *so, struct sockaddr **nam)
37925605Skjc{
380157985Srwatson
381157985Srwatson	return (EOPNOTSUPP);
38225605Skjc}
38325605Skjc
38425605Skjc/* xxx - should be const */
38525605Skjcstruct pr_usrreqs natm_usrreqs = {
386137386Sphk	.pru_abort =		natm_usr_abort,
387137386Sphk	.pru_attach =		natm_usr_attach,
388137386Sphk	.pru_bind =		natm_usr_bind,
389137386Sphk	.pru_connect =		natm_usr_connect,
390137386Sphk	.pru_control =		natm_usr_control,
391137386Sphk	.pru_detach =		natm_usr_detach,
392137386Sphk	.pru_disconnect =	natm_usr_disconnect,
393137386Sphk	.pru_peeraddr =		natm_usr_peeraddr,
394137386Sphk	.pru_send =		natm_usr_send,
395137386Sphk	.pru_shutdown =		natm_usr_shutdown,
396137386Sphk	.pru_sockaddr =		natm_usr_sockaddr,
397160549Srwatson	.pru_close =		natm_usr_close,
39825605Skjc};
39925605Skjc
40025605Skjc/*
401148158Srwatson * natmintr: interrupt
40225605Skjc *
403157985Srwatson * Note: we expect a socket pointer in rcvif rather than an interface
404157985Srwatson * pointer.  We can get the interface pointer from the so's PCB if we really
405157985Srwatson * need it.
40625605Skjc */
40725605Skjcvoid
408111888Sjlemonnatmintr(struct mbuf *m)
40925605Skjc{
410118541Sharti	struct socket *so;
411118541Sharti	struct natmpcb *npcb;
41225605Skjc
41325605Skjc#ifdef DIAGNOSTIC
414118541Sharti	M_ASSERTPKTHDR(m);
41525605Skjc#endif
41625605Skjc
417148125Srwatson	NATM_LOCK();
418118541Sharti	npcb = (struct natmpcb *)m->m_pkthdr.rcvif;	/* XXX: overloaded */
419118541Sharti	so = npcb->npcb_socket;
42025605Skjc
421118541Sharti	npcb->npcb_inq--;
42225605Skjc
423118541Sharti	if (npcb->npcb_flags & NPCB_DRAIN) {
424118541Sharti		if (npcb->npcb_inq == 0)
425118541Sharti			FREE(npcb, M_PCB);			/* done! */
426148125Srwatson		NATM_UNLOCK();
427148125Srwatson		m_freem(m);
428118541Sharti		return;
429118541Sharti	}
43025605Skjc
431118541Sharti	if (npcb->npcb_flags & NPCB_FREE) {
432148125Srwatson		NATM_UNLOCK();
433118541Sharti		m_freem(m);					/* drop */
434118541Sharti		return;
435118541Sharti	}
43625605Skjc
43725605Skjc#ifdef NEED_TO_RESTORE_IFP
438118541Sharti	m->m_pkthdr.rcvif = npcb->npcb_ifp;
43925605Skjc#else
44025605Skjc#ifdef DIAGNOSTIC
441118541Sharti	m->m_pkthdr.rcvif = NULL;	/* null it out to be safe */
44225605Skjc#endif
44325605Skjc#endif
44425605Skjc
445118547Sharti	if (sbspace(&so->so_rcv) > m->m_pkthdr.len) {
44625605Skjc#ifdef NATM_STAT
447118541Sharti		natm_sookcnt++;
448118541Sharti		natm_sookbytes += m->m_pkthdr.len;
44925605Skjc#endif
450118541Sharti		sbappendrecord(&so->so_rcv, m);
451118541Sharti		sorwakeup(so);
452148125Srwatson		NATM_UNLOCK();
453118541Sharti	} else {
45425605Skjc#ifdef NATM_STAT
455118541Sharti		natm_sodropcnt++;
456118541Sharti		natm_sodropbytes += m->m_pkthdr.len;
45725605Skjc#endif
458148125Srwatson		NATM_UNLOCK();
459118541Sharti		m_freem(m);
460118541Sharti	}
46125605Skjc}
46225605Skjc
46325605Skjc/*
46425605Skjc * natm0_sysctl: not used, but here in case we want to add something
46525605Skjc * later...
46625605Skjc */
467118541Shartiint
468118541Shartinatm0_sysctl(SYSCTL_HANDLER_ARGS)
46925605Skjc{
470157985Srwatson
471118541Sharti	/* All sysctl names at this level are terminal. */
472118541Sharti	return (ENOENT);
47325605Skjc}
47425605Skjc
47525605Skjc/*
47625605Skjc * natm5_sysctl: not used, but here in case we want to add something
47725605Skjc * later...
47825605Skjc */
479118541Shartiint
480118541Shartinatm5_sysctl(SYSCTL_HANDLER_ARGS)
48125605Skjc{
482157985Srwatson
483118541Sharti	/* All sysctl names at this level are terminal. */
484118541Sharti	return (ENOENT);
48525605Skjc}
486