1272957Srodrigc/*-
2234949Sbapt * Copyright (c) 2005-2006 Robert N. M. Watson
3234949Sbapt * All rights reserved.
4234949Sbapt *
5234949Sbapt * Redistribution and use in source and binary forms, with or without
6234949Sbapt * modification, are permitted provided that the following conditions
7234949Sbapt * are met:
8234949Sbapt * 1. Redistributions of source code must retain the above copyright
9234949Sbapt *    notice, this list of conditions and the following disclaimer.
10234949Sbapt * 2. Redistributions in binary form must reproduce the above copyright
11234949Sbapt *    notice, this list of conditions and the following disclaimer in the
12268899Sbapt *    documentation and/or other materials provided with the distribution.
13268899Sbapt *
14268899Sbapt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15268899Sbapt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16268899Sbapt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17268899Sbapt * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18234949Sbapt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19268899Sbapt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20268899Sbapt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21268899Sbapt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22268899Sbapt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23234949Sbapt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24268899Sbapt * SUCH DAMAGE.
25268899Sbapt *
26268899Sbapt * Copyright (c) 1996 Charles D. Cranor and Washington University.
27268899Sbapt * All rights reserved.
28234949Sbapt *
29234949Sbapt * Redistribution and use in source and binary forms, with or without
30234949Sbapt * modification, are permitted provided that the following conditions
31234949Sbapt * are met:
32234949Sbapt * 1. Redistributions of source code must retain the above copyright
33268899Sbapt *    notice, this list of conditions and the following disclaimer.
34234949Sbapt * 2. Redistributions in binary form must reproduce the above copyright
35234949Sbapt *    notice, this list of conditions and the following disclaimer in the
36234949Sbapt *    documentation and/or other materials provided with the distribution.
37234949Sbapt * 3. All advertising materials mentioning features or use of this software
38234949Sbapt *    must display the following acknowledgement:
39234949Sbapt *      This product includes software developed by Charles D. Cranor and
40234949Sbapt *      Washington University.
41234949Sbapt * 4. The name of the author may not be used to endorse or promote products
42234949Sbapt *    derived from this software without specific prior written permission.
43234949Sbapt *
44234949Sbapt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
45234949Sbapt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
46234949Sbapt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
47234949Sbapt * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
48234949Sbapt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
49234949Sbapt * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50234949Sbapt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51234949Sbapt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52234949Sbapt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
53234949Sbapt * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54234949Sbapt *
55234949Sbapt * $NetBSD: natm.c,v 1.5 1996/11/09 03:26:26 chuck Exp $
56234949Sbapt */
57234949Sbapt
58234949Sbapt/*
59234949Sbapt * natm.c: Native mode ATM access (both aal0 and aal5).
60268899Sbapt */
61268899Sbapt
62268899Sbapt#include <sys/cdefs.h>
63268899Sbapt__FBSDID("$FreeBSD$");
64268899Sbapt
65268899Sbapt#include <sys/param.h>
66268899Sbapt#include <sys/conf.h>
67268899Sbapt#include <sys/kernel.h>
68268899Sbapt#include <sys/lock.h>
69268899Sbapt#include <sys/malloc.h>
70268899Sbapt#include <sys/mbuf.h>
71268899Sbapt#include <sys/protosw.h>
72268899Sbapt#include <sys/signalvar.h>
73272955Srodrigc#include <sys/socket.h>
74268899Sbapt#include <sys/socketvar.h>
75268899Sbapt#include <sys/sockio.h>
76268899Sbapt#include <sys/sx.h>
77268899Sbapt#include <sys/systm.h>
78268899Sbapt#include <sys/sysctl.h>
79268899Sbapt
80268899Sbapt#include <net/if.h>
81268899Sbapt#include <net/if_atm.h>
82268899Sbapt#include <net/netisr.h>
83268899Sbapt
84272955Srodrigc#include <netinet/in.h>
85272955Srodrigc
86268899Sbapt#include <netnatm/natm.h>
87268899Sbapt
88268899Sbaptstatic const u_long	natm5_sendspace = 16*1024;
89268899Sbaptstatic const u_long	natm5_recvspace = 16*1024;
90268899Sbapt
91268899Sbaptstatic const u_long	natm0_sendspace = 16*1024;
92234949Sbaptstatic const u_long	natm0_recvspace = 16*1024;
93234949Sbapt
94234949Sbapt/*
95234949Sbapt * netnatm global subsystem lock, protects all global data structures in
96234949Sbapt * netnatm.
97234949Sbapt */
98234949Sbaptstruct mtx	natm_mtx;
99240517Sbapt
100234949Sbapt/*
101234949Sbapt * User socket requests.
102234949Sbapt */
103234949Sbaptstatic int	natm_usr_attach(struct socket *, int, struct thread *);
104234949Sbaptstatic void	natm_usr_detach(struct socket *);
105234949Sbaptstatic int	natm_usr_connect(struct socket *, struct sockaddr *,
106234949Sbapt		    struct thread *);
107234949Sbaptstatic int	natm_usr_disconnect(struct socket *);
108234949Sbaptstatic int	natm_usr_shutdown(struct socket *);
109234949Sbaptstatic int	natm_usr_send(struct socket *, int, struct mbuf *,
110234949Sbapt		    struct sockaddr *, struct mbuf *, struct thread *);
111234949Sbaptstatic int	natm_usr_peeraddr(struct socket *, struct sockaddr **);
112234949Sbaptstatic int	natm_usr_control(struct socket *, u_long, caddr_t,
113234949Sbapt		    struct ifnet *, struct thread *);
114234949Sbaptstatic void	natm_usr_abort(struct socket *);
115234949Sbaptstatic int	natm_usr_bind(struct socket *, struct sockaddr *,
116234949Sbapt		    struct thread *);
117234949Sbaptstatic int	natm_usr_sockaddr(struct socket *, struct sockaddr **);
118234949Sbapt
119234949Sbaptstatic int
120234949Sbaptnatm_usr_attach(struct socket *so, int proto, struct thread *p)
121234949Sbapt{
122234949Sbapt	struct natmpcb *npcb;
123234949Sbapt	int error = 0;
124234949Sbapt
125234949Sbapt	npcb = (struct natmpcb *)so->so_pcb;
126234949Sbapt	KASSERT(npcb == NULL, ("natm_usr_attach: so_pcb != NULL"));
127234949Sbapt
128234949Sbapt	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
129234949Sbapt		if (proto == PROTO_NATMAAL5)
130272957Srodrigc			error = soreserve(so, natm5_sendspace,
131234949Sbapt			    natm5_recvspace);
132234949Sbapt		else
133234949Sbapt			error = soreserve(so, natm0_sendspace,
134234949Sbapt			    natm0_recvspace);
135234949Sbapt		if (error)
136234949Sbapt			return (error);
137234949Sbapt	}
138272957Srodrigc	so->so_pcb = npcb = npcb_alloc(M_WAITOK);
139234949Sbapt	npcb->npcb_socket = so;
140268899Sbapt	return (error);
141272957Srodrigc}
142234949Sbapt
143234949Sbaptstatic void
144240517Sbaptnatm_usr_detach(struct socket *so)
145234949Sbapt{
146234949Sbapt	struct natmpcb *npcb;
147234949Sbapt
148234949Sbapt	npcb = (struct natmpcb *)so->so_pcb;
149234949Sbapt	KASSERT(npcb != NULL, ("natm_usr_detach: npcb == NULL"));
150272957Srodrigc
151234949Sbapt	NATM_LOCK();
152268899Sbapt	npcb_free(npcb, NPCB_DESTROY);	/* drain */
153234949Sbapt	so->so_pcb = NULL;
154234949Sbapt	NATM_UNLOCK();
155272957Srodrigc}
156268899Sbapt
157268899Sbaptstatic int
158234949Sbaptnatm_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *p)
159234949Sbapt{
160234949Sbapt	struct natmpcb *npcb;
161234949Sbapt	struct sockaddr_natm *snatm;
162234949Sbapt	struct atmio_openvcc op;
163234949Sbapt	struct ifnet *ifp;
164234949Sbapt	int error = 0;
165234949Sbapt	int proto = so->so_proto->pr_protocol;
166234949Sbapt
167234949Sbapt	npcb = (struct natmpcb *)so->so_pcb;
168234949Sbapt	KASSERT(npcb != NULL, ("natm_usr_connect: npcb == NULL"));
169234949Sbapt
170240517Sbapt	/*
171234949Sbapt	 * Validate nam and npcb.
172234949Sbapt	 */
173234949Sbapt	NATM_LOCK();
174234949Sbapt	snatm = (struct sockaddr_natm *)nam;
175234949Sbapt	if (snatm->snatm_len != sizeof(*snatm) ||
176234949Sbapt		(npcb->npcb_flags & NPCB_FREE) == 0) {
177234949Sbapt		NATM_UNLOCK();
178234949Sbapt		return (EINVAL);
179234949Sbapt	}
180234949Sbapt	if (snatm->snatm_family != AF_NATM) {
181234949Sbapt		NATM_UNLOCK();
182234949Sbapt		return (EAFNOSUPPORT);
183234949Sbapt	}
184234949Sbapt
185234949Sbapt	snatm->snatm_if[IFNAMSIZ - 1] = '\0';	/* XXX ensure null termination
186234949Sbapt						   since ifunit() uses strcmp */
187234949Sbapt
188234949Sbapt	/*
189234949Sbapt	 * Convert interface string to ifp, validate.
190234949Sbapt	 */
191234949Sbapt	ifp = ifunit(snatm->snatm_if);
192234949Sbapt	if (ifp == NULL || (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
193234949Sbapt		NATM_UNLOCK();
194234949Sbapt		return (ENXIO);
195234949Sbapt	}
196234949Sbapt	if (ifp->if_output != atm_output) {
197234949Sbapt		NATM_UNLOCK();
198234949Sbapt		return (EAFNOSUPPORT);
199234949Sbapt	}
200234949Sbapt
201234949Sbapt	/*
202234949Sbapt	 * Register us with the NATM PCB layer.
203234949Sbapt	 */
204234949Sbapt	if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) {
205234949Sbapt		NATM_UNLOCK();
206234949Sbapt		return (EADDRINUSE);
207234949Sbapt	}
208234949Sbapt
209234949Sbapt	/*
210234949Sbapt	 * Open the channel.
211272955Srodrigc	 *
212234949Sbapt	 * XXXRW: Eventually desirable to hold mutex over ioctl?
213234949Sbapt	 */
214234949Sbapt	bzero(&op, sizeof(op));
215234949Sbapt	op.rxhand = npcb;
216234949Sbapt	op.param.flags = ATMIO_FLAG_PVC;
217234949Sbapt	op.param.vpi = npcb->npcb_vpi;
218234949Sbapt	op.param.vci = npcb->npcb_vci;
219234949Sbapt	op.param.rmtu = op.param.tmtu = ifp->if_mtu;
220234949Sbapt	op.param.aal = (proto == PROTO_NATMAAL5) ? ATMIO_AAL_5 : ATMIO_AAL_0;
221234949Sbapt	op.param.traffic = ATMIO_TRAFFIC_UBR;
222234949Sbapt	NATM_UNLOCK();
223234949Sbapt
224234949Sbapt	if (ifp->if_ioctl == NULL ||
225234949Sbapt	    ifp->if_ioctl(ifp, SIOCATMOPENVCC, (caddr_t)&op) != 0)
226234949Sbapt		return (EIO);
227234949Sbapt	soisconnected(so);
228234949Sbapt	return (error);
229234949Sbapt}
230234949Sbapt
231234949Sbaptstatic int
232234949Sbaptnatm_usr_disconnect(struct socket *so)
233234949Sbapt{
234234949Sbapt	struct natmpcb *npcb;
235234949Sbapt	struct atmio_closevcc cl;
236234949Sbapt	struct ifnet *ifp;
237234949Sbapt	int error = 0;
238234949Sbapt
239234949Sbapt	npcb = (struct natmpcb *)so->so_pcb;
240234949Sbapt	KASSERT(npcb != NULL, ("natm_usr_disconnect: npcb == NULL"));
241234949Sbapt
242234949Sbapt	NATM_LOCK();
243234949Sbapt	if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
244234949Sbapt		NATM_UNLOCK();
245234949Sbapt		printf("natm: disconnected check\n");
246234949Sbapt		return (EIO);
247234949Sbapt	}
248234949Sbapt	ifp = npcb->npcb_ifp;
249234949Sbapt
250234949Sbapt	/*
251272955Srodrigc	 * Disable rx.
252272955Srodrigc	 *
253272955Srodrigc	 * XXXRW: Eventually desirable to hold mutex over ioctl?
254272955Srodrigc	 */
255272955Srodrigc	cl.vpi = npcb->npcb_vpi;
256272955Srodrigc	cl.vci = npcb->npcb_vci;
257272955Srodrigc	NATM_UNLOCK();
258272955Srodrigc	if (ifp->if_ioctl != NULL)
259272955Srodrigc		ifp->if_ioctl(ifp, SIOCATMCLOSEVCC, (caddr_t)&cl);
260272955Srodrigc	soisdisconnected(so);
261272955Srodrigc	return (error);
262272955Srodrigc}
263272955Srodrigc
264272955Srodrigcstatic int
265272955Srodrigcnatm_usr_shutdown(struct socket *so)
266272955Srodrigc{
267272955Srodrigc
268272955Srodrigc	socantsendmore(so);
269272955Srodrigc	return (0);
270272955Srodrigc}
271272955Srodrigc
272272955Srodrigcstatic int
273272955Srodrigcnatm_usr_send(struct socket *so, int flags, struct mbuf *m,
274272955Srodrigc	struct sockaddr *nam, struct mbuf *control, struct thread *p)
275272955Srodrigc{
276272955Srodrigc	struct natmpcb *npcb;
277272955Srodrigc	struct atm_pseudohdr *aph;
278272955Srodrigc	int error = 0;
279272955Srodrigc	int proto = so->so_proto->pr_protocol;
280272955Srodrigc
281272955Srodrigc	npcb = (struct natmpcb *)so->so_pcb;
282272955Srodrigc	KASSERT(npcb != NULL, ("natm_usr_send: npcb == NULL"));
283272955Srodrigc
284272955Srodrigc	NATM_LOCK();
285272955Srodrigc	if (control && control->m_len) {
286268899Sbapt		NATM_UNLOCK();
287268899Sbapt		m_freem(control);
288268899Sbapt		m_freem(m);
289268899Sbapt		return (EINVAL);
290268899Sbapt	}
291268899Sbapt
292268899Sbapt	/*
293268899Sbapt	 * Send the data.  We must put an atm_pseudohdr on first.
294268899Sbapt	 */
295268899Sbapt	M_PREPEND(m, sizeof(*aph), M_NOWAIT);
296268899Sbapt	if (m == NULL) {
297268899Sbapt		NATM_UNLOCK();
298268899Sbapt		m_freem(control);
299268899Sbapt		return (ENOBUFS);
300268899Sbapt	}
301268899Sbapt	aph = mtod(m, struct atm_pseudohdr *);
302268899Sbapt	ATM_PH_VPI(aph) = npcb->npcb_vpi;
303268899Sbapt	ATM_PH_SETVCI(aph, npcb->npcb_vci);
304268899Sbapt	ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
305268899Sbapt	error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
306268899Sbapt	NATM_UNLOCK();
307268899Sbapt	return (error);
308268899Sbapt}
309268899Sbapt
310268899Sbaptstatic int
311268899Sbaptnatm_usr_peeraddr(struct socket *so, struct sockaddr **nam)
312268899Sbapt{
313268899Sbapt	struct natmpcb *npcb;
314268899Sbapt	struct sockaddr_natm *snatm, ssnatm;
315268899Sbapt
316268899Sbapt	npcb = (struct natmpcb *)so->so_pcb;
317268899Sbapt	KASSERT(npcb != NULL, ("natm_usr_peeraddr: npcb == NULL"));
318234949Sbapt
319234949Sbapt	NATM_LOCK();
320268899Sbapt	snatm = &ssnatm;
321234949Sbapt	bzero(snatm, sizeof(*snatm));
322268899Sbapt	snatm->snatm_len = sizeof(*snatm);
323268899Sbapt	snatm->snatm_family = AF_NATM;
324268899Sbapt	strlcpy(snatm->snatm_if, npcb->npcb_ifp->if_xname,
325234949Sbapt	    sizeof(snatm->snatm_if));
326234949Sbapt	snatm->snatm_vci = npcb->npcb_vci;
327234949Sbapt	snatm->snatm_vpi = npcb->npcb_vpi;
328234949Sbapt	NATM_UNLOCK();
329234949Sbapt	*nam = sodupsockaddr((struct sockaddr *)snatm, M_WAITOK);
330234949Sbapt	return (0);
331234949Sbapt}
332268899Sbapt
333234949Sbaptstatic int
334234949Sbaptnatm_usr_control(struct socket *so, u_long cmd, caddr_t arg,
335234949Sbapt	struct ifnet *ifp, struct thread *p)
336234949Sbapt{
337234949Sbapt	struct natmpcb *npcb;
338234949Sbapt
339234949Sbapt	npcb = (struct natmpcb *)so->so_pcb;
340234949Sbapt	KASSERT(npcb != NULL, ("natm_usr_control: npcb == NULL"));
341234949Sbapt
342234949Sbapt	switch (cmd) {
343234949Sbapt	case SIOCSIFADDR:
344234949Sbapt	case SIOCSIFBRDADDR:
345234949Sbapt	case SIOCSIFDSTADDR:
346234949Sbapt	case SIOCSIFNETMASK:
347234949Sbapt		/*
348234949Sbapt		 * Although we should pass any non-ATM ioctl requests
349234949Sbapt		 * down to driver, we filter some legacy INET requests.
350234949Sbapt		 * Drivers trust SIOCSIFADDR et al to come from an already
351234949Sbapt		 * privileged layer, and do not perform any credentials
352234949Sbapt		 * checks or input validation.
353268899Sbapt		 */
354268899Sbapt		return (EINVAL);
355268899Sbapt	}
356268899Sbapt
357268899Sbapt	if (ifp == NULL || ifp->if_ioctl == NULL)
358234949Sbapt		return (EOPNOTSUPP);
359234949Sbapt	return ((*ifp->if_ioctl)(ifp, cmd, arg));
360234949Sbapt}
361234949Sbapt
362234949Sbaptstatic void
363234949Sbaptnatm_usr_abort(struct socket *so)
364234949Sbapt{
365234949Sbapt
366268899Sbapt}
367268899Sbapt
368268899Sbaptstatic void
369268899Sbaptnatm_usr_close(struct socket *so)
370234949Sbapt{
371234949Sbapt
372234949Sbapt}
373234949Sbapt
374234949Sbaptstatic int
375234949Sbaptnatm_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *p)
376234949Sbapt{
377234949Sbapt
378234949Sbapt	return (EOPNOTSUPP);
379234949Sbapt}
380234949Sbapt
381234949Sbaptstatic int
382234949Sbaptnatm_usr_sockaddr(struct socket *so, struct sockaddr **nam)
383234949Sbapt{
384234949Sbapt
385234949Sbapt	return (EOPNOTSUPP);
386234949Sbapt}
387234949Sbapt
388235723Sbapt/* xxx - should be const */
389234949Sbaptstruct pr_usrreqs natm_usrreqs = {
390234949Sbapt	.pru_abort =		natm_usr_abort,
391234949Sbapt	.pru_attach =		natm_usr_attach,
392234949Sbapt	.pru_bind =		natm_usr_bind,
393234949Sbapt	.pru_connect =		natm_usr_connect,
394234949Sbapt	.pru_control =		natm_usr_control,
395234949Sbapt	.pru_detach =		natm_usr_detach,
396234949Sbapt	.pru_disconnect =	natm_usr_disconnect,
397234949Sbapt	.pru_peeraddr =		natm_usr_peeraddr,
398234949Sbapt	.pru_send =		natm_usr_send,
399234949Sbapt	.pru_shutdown =		natm_usr_shutdown,
400234949Sbapt	.pru_sockaddr =		natm_usr_sockaddr,
401234949Sbapt	.pru_close =		natm_usr_close,
402234949Sbapt};
403234949Sbapt
404234949Sbapt/*
405234949Sbapt * natmintr: interrupt
406234949Sbapt *
407234949Sbapt * Note: we expect a socket pointer in rcvif rather than an interface
408234949Sbapt * pointer.  We can get the interface pointer from the so's PCB if we really
409234949Sbapt * need it.
410234949Sbapt */
411234949Sbaptvoid
412234949Sbaptnatmintr(struct mbuf *m)
413234949Sbapt{
414234949Sbapt	struct socket *so;
415234949Sbapt	struct natmpcb *npcb;
416234949Sbapt
417234949Sbapt#ifdef DIAGNOSTIC
418234949Sbapt	M_ASSERTPKTHDR(m);
419234949Sbapt#endif
420234949Sbapt
421234949Sbapt	NATM_LOCK();
422268899Sbapt	npcb = (struct natmpcb *)m->m_pkthdr.rcvif;	/* XXX: overloaded */
423268899Sbapt	so = npcb->npcb_socket;
424268899Sbapt
425268899Sbapt	npcb->npcb_inq--;
426268899Sbapt
427268899Sbapt	if (npcb->npcb_flags & NPCB_DRAIN) {
428268899Sbapt		if (npcb->npcb_inq == 0)
429268899Sbapt			free(npcb, M_PCB);			/* done! */
430268899Sbapt		NATM_UNLOCK();
431268899Sbapt		m_freem(m);
432268899Sbapt		return;
433268899Sbapt	}
434268899Sbapt
435268899Sbapt	if (npcb->npcb_flags & NPCB_FREE) {
436268899Sbapt		NATM_UNLOCK();
437268899Sbapt		m_freem(m);					/* drop */
438268899Sbapt		return;
439268899Sbapt	}
440268899Sbapt
441268899Sbapt#ifdef NEED_TO_RESTORE_IFP
442268899Sbapt	m->m_pkthdr.rcvif = npcb->npcb_ifp;
443268899Sbapt#else
444268899Sbapt#ifdef DIAGNOSTIC
445268899Sbapt	m->m_pkthdr.rcvif = NULL;	/* null it out to be safe */
446268899Sbapt#endif
447268899Sbapt#endif
448268899Sbapt
449268899Sbapt	if (sbspace(&so->so_rcv) > m->m_pkthdr.len) {
450268899Sbapt#ifdef NATM_STAT
451268899Sbapt		natm_sookcnt++;
452268899Sbapt		natm_sookbytes += m->m_pkthdr.len;
453268899Sbapt#endif
454268899Sbapt		sbappendrecord(&so->so_rcv, m);
455268899Sbapt		sorwakeup(so);
456268899Sbapt		NATM_UNLOCK();
457268899Sbapt	} else {
458268899Sbapt#ifdef NATM_STAT
459268899Sbapt		natm_sodropcnt++;
460268899Sbapt		natm_sodropbytes += m->m_pkthdr.len;
461268899Sbapt#endif
462268899Sbapt		NATM_UNLOCK();
463268899Sbapt		m_freem(m);
464268899Sbapt	}
465268899Sbapt}
466268899Sbapt
467268899Sbapt/*
468268899Sbapt * natm0_sysctl: not used, but here in case we want to add something
469268899Sbapt * later...
470268899Sbapt */
471268899Sbaptint
472268899Sbaptnatm0_sysctl(SYSCTL_HANDLER_ARGS)
473268899Sbapt{
474268899Sbapt
475268899Sbapt	/* All sysctl names at this level are terminal. */
476268899Sbapt	return (ENOENT);
477268899Sbapt}
478268899Sbapt
479268899Sbapt/*
480268899Sbapt * natm5_sysctl: not used, but here in case we want to add something
481268899Sbapt * later...
482268899Sbapt */
483268899Sbaptint
484268899Sbaptnatm5_sysctl(SYSCTL_HANDLER_ARGS)
485268899Sbapt{
486268899Sbapt
487268899Sbapt	/* All sysctl names at this level are terminal. */
488268899Sbapt	return (ENOENT);
489268899Sbapt}
490268899Sbapt