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$");
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 */
103192445Simpstatic int	natm_usr_attach(struct socket *, int, struct thread *);
104157985Srwatsonstatic void	natm_usr_detach(struct socket *);
105157985Srwatsonstatic int	natm_usr_connect(struct socket *, struct sockaddr *,
106192445Simp		    struct thread *);
107157985Srwatsonstatic int	natm_usr_disconnect(struct socket *);
108157985Srwatsonstatic int	natm_usr_shutdown(struct socket *);
109157985Srwatsonstatic int	natm_usr_send(struct socket *, int, struct mbuf *,
110192445Simp		    struct sockaddr *, struct mbuf *, struct thread *);
111157985Srwatsonstatic int	natm_usr_peeraddr(struct socket *, struct sockaddr **);
112157985Srwatsonstatic int	natm_usr_control(struct socket *, u_long, caddr_t,
113192445Simp		    struct ifnet *, struct thread *);
114157985Srwatsonstatic void	natm_usr_abort(struct socket *);
115157985Srwatsonstatic int	natm_usr_bind(struct socket *, struct sockaddr *,
116192445Simp		    struct thread *);
117157985Srwatsonstatic int	natm_usr_sockaddr(struct socket *, struct sockaddr **);
11825605Skjc
11925605Skjcstatic int
120192445Simpnatm_usr_attach(struct socket *so, int proto, struct thread *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
158192445Simpnatm_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *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	if (ifp->if_ioctl == NULL ||
225189851Srwatson	    ifp->if_ioctl(ifp, SIOCATMOPENVCC, (caddr_t)&op) != 0)
226157985Srwatson		return (EIO);
227157985Srwatson	soisconnected(so);
228157985Srwatson	return (error);
22925605Skjc}
23025605Skjc
23125605Skjcstatic int
23225605Skjcnatm_usr_disconnect(struct socket *so)
23325605Skjc{
234157985Srwatson	struct natmpcb *npcb;
235157985Srwatson	struct atmio_closevcc cl;
236157985Srwatson	struct ifnet *ifp;
237157985Srwatson	int error = 0;
23825605Skjc
239157985Srwatson	npcb = (struct natmpcb *)so->so_pcb;
240157985Srwatson	KASSERT(npcb != NULL, ("natm_usr_disconnect: npcb == NULL"));
24125605Skjc
242157985Srwatson	NATM_LOCK();
243157985Srwatson	if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
244157985Srwatson		NATM_UNLOCK();
245157985Srwatson		printf("natm: disconnected check\n");
246157985Srwatson		return (EIO);
247157985Srwatson	}
248157985Srwatson	ifp = npcb->npcb_ifp;
249157985Srwatson
250157985Srwatson	/*
251157985Srwatson	 * Disable rx.
252157985Srwatson	 *
253157985Srwatson	 * XXXRW: Eventually desirable to hold mutex over ioctl?
254157985Srwatson	 */
255157985Srwatson	cl.vpi = npcb->npcb_vpi;
256157985Srwatson	cl.vci = npcb->npcb_vci;
257157984Srwatson	NATM_UNLOCK();
258189851Srwatson	if (ifp->if_ioctl != NULL)
259157985Srwatson		ifp->if_ioctl(ifp, SIOCATMCLOSEVCC, (caddr_t)&cl);
260157985Srwatson	soisdisconnected(so);
261157985Srwatson	return (error);
26225605Skjc}
26325605Skjc
26425605Skjcstatic int
26525605Skjcnatm_usr_shutdown(struct socket *so)
26625605Skjc{
267157985Srwatson
268157985Srwatson	socantsendmore(so);
269157985Srwatson	return (0);
27025605Skjc}
27125605Skjc
27225605Skjcstatic int
27328270Swollmannatm_usr_send(struct socket *so, int flags, struct mbuf *m,
274192445Simp	struct sockaddr *nam, struct mbuf *control, struct thread *p)
27525605Skjc{
276157985Srwatson	struct natmpcb *npcb;
277157985Srwatson	struct atm_pseudohdr *aph;
278157985Srwatson	int error = 0;
279157985Srwatson	int proto = so->so_proto->pr_protocol;
28025605Skjc
281157985Srwatson	npcb = (struct natmpcb *)so->so_pcb;
282157985Srwatson	KASSERT(npcb != NULL, ("natm_usr_send: npcb == NULL"));
28325605Skjc
284157985Srwatson	NATM_LOCK();
285157985Srwatson	if (control && control->m_len) {
286157985Srwatson		NATM_UNLOCK();
287157985Srwatson		m_freem(control);
288157985Srwatson		m_freem(m);
289157985Srwatson		return (EINVAL);
290157985Srwatson	}
29125605Skjc
292157985Srwatson	/*
293157985Srwatson	 * Send the data.  We must put an atm_pseudohdr on first.
294157985Srwatson	 */
295243882Sglebius	M_PREPEND(m, sizeof(*aph), M_NOWAIT);
296157985Srwatson	if (m == NULL) {
297157985Srwatson		NATM_UNLOCK();
298157985Srwatson		m_freem(control);
299157985Srwatson		return (ENOBUFS);
300157985Srwatson	}
301157985Srwatson	aph = mtod(m, struct atm_pseudohdr *);
302157985Srwatson	ATM_PH_VPI(aph) = npcb->npcb_vpi;
303157985Srwatson	ATM_PH_SETVCI(aph, npcb->npcb_vci);
304157985Srwatson	ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
305157985Srwatson	error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
306157984Srwatson	NATM_UNLOCK();
307157985Srwatson	return (error);
30825605Skjc}
30925605Skjc
31025605Skjcstatic int
31128270Swollmannatm_usr_peeraddr(struct socket *so, struct sockaddr **nam)
31225605Skjc{
313157985Srwatson	struct natmpcb *npcb;
314157985Srwatson	struct sockaddr_natm *snatm, ssnatm;
31525605Skjc
316157985Srwatson	npcb = (struct natmpcb *)so->so_pcb;
317157985Srwatson	KASSERT(npcb != NULL, ("natm_usr_peeraddr: npcb == NULL"));
31825605Skjc
319157985Srwatson	NATM_LOCK();
320157985Srwatson	snatm = &ssnatm;
321157985Srwatson	bzero(snatm, sizeof(*snatm));
322157985Srwatson	snatm->snatm_len = sizeof(*snatm);
323157985Srwatson	snatm->snatm_family = AF_NATM;
324157985Srwatson	strlcpy(snatm->snatm_if, npcb->npcb_ifp->if_xname,
325157985Srwatson	    sizeof(snatm->snatm_if));
326157985Srwatson	snatm->snatm_vci = npcb->npcb_vci;
327157985Srwatson	snatm->snatm_vpi = npcb->npcb_vpi;
328157985Srwatson	NATM_UNLOCK();
329157985Srwatson	*nam = sodupsockaddr((struct sockaddr *)snatm, M_WAITOK);
330157985Srwatson	return (0);
33125605Skjc}
33225605Skjc
33325605Skjcstatic int
33436735Sdfrnatm_usr_control(struct socket *so, u_long cmd, caddr_t arg,
335192445Simp	struct ifnet *ifp, struct thread *p)
33625605Skjc{
337157985Srwatson	struct natmpcb *npcb;
33825605Skjc
339157985Srwatson	npcb = (struct natmpcb *)so->so_pcb;
340157985Srwatson	KASSERT(npcb != NULL, ("natm_usr_control: npcb == NULL"));
34125605Skjc
342255442Sdes	switch (cmd) {
343255442Sdes	case SIOCSIFADDR:
344255442Sdes	case SIOCSIFBRDADDR:
345255442Sdes	case SIOCSIFDSTADDR:
346255442Sdes	case SIOCSIFNETMASK:
347255442Sdes		/*
348255442Sdes		 * Although we should pass any non-ATM ioctl requests
349255442Sdes		 * down to driver, we filter some legacy INET requests.
350255442Sdes		 * Drivers trust SIOCSIFADDR et al to come from an already
351255442Sdes		 * privileged layer, and do not perform any credentials
352255442Sdes		 * checks or input validation.
353255442Sdes		 */
354255442Sdes		return (EINVAL);
355255442Sdes	}
356255442Sdes
357157985Srwatson	if (ifp == NULL || ifp->if_ioctl == NULL)
358157985Srwatson		return (EOPNOTSUPP);
359189851Srwatson	return ((*ifp->if_ioctl)(ifp, cmd, arg));
36025605Skjc}
36125605Skjc
362157366Srwatsonstatic void
36325605Skjcnatm_usr_abort(struct socket *so)
36425605Skjc{
365157985Srwatson
36625605Skjc}
36725605Skjc
368160549Srwatsonstatic void
369160549Srwatsonnatm_usr_close(struct socket *so)
370160549Srwatson{
371160549Srwatson
372160549Srwatson}
373160549Srwatson
37425605Skjcstatic int
375192445Simpnatm_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *p)
37625605Skjc{
377157985Srwatson
378157985Srwatson	return (EOPNOTSUPP);
37925605Skjc}
38025605Skjc
38125605Skjcstatic int
38228270Swollmannatm_usr_sockaddr(struct socket *so, struct sockaddr **nam)
38325605Skjc{
384157985Srwatson
385157985Srwatson	return (EOPNOTSUPP);
38625605Skjc}
38725605Skjc
38825605Skjc/* xxx - should be const */
38925605Skjcstruct pr_usrreqs natm_usrreqs = {
390137386Sphk	.pru_abort =		natm_usr_abort,
391137386Sphk	.pru_attach =		natm_usr_attach,
392137386Sphk	.pru_bind =		natm_usr_bind,
393137386Sphk	.pru_connect =		natm_usr_connect,
394137386Sphk	.pru_control =		natm_usr_control,
395137386Sphk	.pru_detach =		natm_usr_detach,
396137386Sphk	.pru_disconnect =	natm_usr_disconnect,
397137386Sphk	.pru_peeraddr =		natm_usr_peeraddr,
398137386Sphk	.pru_send =		natm_usr_send,
399137386Sphk	.pru_shutdown =		natm_usr_shutdown,
400137386Sphk	.pru_sockaddr =		natm_usr_sockaddr,
401160549Srwatson	.pru_close =		natm_usr_close,
40225605Skjc};
40325605Skjc
40425605Skjc/*
405148158Srwatson * natmintr: interrupt
40625605Skjc *
407157985Srwatson * Note: we expect a socket pointer in rcvif rather than an interface
408157985Srwatson * pointer.  We can get the interface pointer from the so's PCB if we really
409157985Srwatson * need it.
41025605Skjc */
41125605Skjcvoid
412111888Sjlemonnatmintr(struct mbuf *m)
41325605Skjc{
414118541Sharti	struct socket *so;
415118541Sharti	struct natmpcb *npcb;
41625605Skjc
41725605Skjc#ifdef DIAGNOSTIC
418118541Sharti	M_ASSERTPKTHDR(m);
41925605Skjc#endif
42025605Skjc
421148125Srwatson	NATM_LOCK();
422118541Sharti	npcb = (struct natmpcb *)m->m_pkthdr.rcvif;	/* XXX: overloaded */
423118541Sharti	so = npcb->npcb_socket;
42425605Skjc
425118541Sharti	npcb->npcb_inq--;
42625605Skjc
427118541Sharti	if (npcb->npcb_flags & NPCB_DRAIN) {
428118541Sharti		if (npcb->npcb_inq == 0)
429184205Sdes			free(npcb, M_PCB);			/* done! */
430148125Srwatson		NATM_UNLOCK();
431148125Srwatson		m_freem(m);
432118541Sharti		return;
433118541Sharti	}
43425605Skjc
435118541Sharti	if (npcb->npcb_flags & NPCB_FREE) {
436148125Srwatson		NATM_UNLOCK();
437118541Sharti		m_freem(m);					/* drop */
438118541Sharti		return;
439118541Sharti	}
44025605Skjc
44125605Skjc#ifdef NEED_TO_RESTORE_IFP
442118541Sharti	m->m_pkthdr.rcvif = npcb->npcb_ifp;
44325605Skjc#else
44425605Skjc#ifdef DIAGNOSTIC
445118541Sharti	m->m_pkthdr.rcvif = NULL;	/* null it out to be safe */
44625605Skjc#endif
44725605Skjc#endif
44825605Skjc
449118547Sharti	if (sbspace(&so->so_rcv) > m->m_pkthdr.len) {
45025605Skjc#ifdef NATM_STAT
451118541Sharti		natm_sookcnt++;
452118541Sharti		natm_sookbytes += m->m_pkthdr.len;
45325605Skjc#endif
454118541Sharti		sbappendrecord(&so->so_rcv, m);
455118541Sharti		sorwakeup(so);
456148125Srwatson		NATM_UNLOCK();
457118541Sharti	} else {
45825605Skjc#ifdef NATM_STAT
459118541Sharti		natm_sodropcnt++;
460118541Sharti		natm_sodropbytes += m->m_pkthdr.len;
46125605Skjc#endif
462148125Srwatson		NATM_UNLOCK();
463118541Sharti		m_freem(m);
464118541Sharti	}
46525605Skjc}
46625605Skjc
46725605Skjc/*
46825605Skjc * natm0_sysctl: not used, but here in case we want to add something
46925605Skjc * later...
47025605Skjc */
471118541Shartiint
472118541Shartinatm0_sysctl(SYSCTL_HANDLER_ARGS)
47325605Skjc{
474157985Srwatson
475118541Sharti	/* All sysctl names at this level are terminal. */
476118541Sharti	return (ENOENT);
47725605Skjc}
47825605Skjc
47925605Skjc/*
48025605Skjc * natm5_sysctl: not used, but here in case we want to add something
48125605Skjc * later...
48225605Skjc */
483118541Shartiint
484118541Shartinatm5_sysctl(SYSCTL_HANDLER_ARGS)
48525605Skjc{
486157985Srwatson
487118541Sharti	/* All sysctl names at this level are terminal. */
488118541Sharti	return (ENOENT);
48925605Skjc}
490