Deleted Added
sdiff udiff text old ( 25606 ) new ( 28270 )
full compact
1/* $NetBSD: natm.c,v 1.5 1996/11/09 03:26:26 chuck Exp $ */
2
3/*
4 *
5 * Copyright (c) 1996 Charles D. Cranor and Washington University.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Charles D. Cranor and
19 * Washington University.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/*
36 * natm.c: native mode ATM access (both aal0 and aal5).
37 */
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/kernel.h>
42#include <sys/domain.h>
43#if defined(__FreeBSD__)
44#include <sys/sockio.h>
45#else
46#include <sys/ioctl.h>
47#endif
48#include <sys/proc.h>
49#include <sys/protosw.h>
50#include <sys/mbuf.h>
51#include <sys/socket.h>
52#include <sys/socketvar.h>
53
54#include <net/if.h>
55#include <net/if_atm.h>
56#include <net/netisr.h>
57#include <net/radix.h>
58#include <net/route.h>
59
60#include <netinet/in.h>
61
62#include <netnatm/natm.h>
63
64u_long natm5_sendspace = 16*1024;
65u_long natm5_recvspace = 16*1024;
66
67u_long natm0_sendspace = 16*1024;
68u_long natm0_recvspace = 16*1024;
69
70/*
71 * user requests
72 */
73#ifdef FREEBSD_USRREQS
74/*
75 * FreeBSD new usrreqs supersedes pr_usrreq.
76 */
77static int natm_usr_attach __P((struct socket *, int, struct proc *));
78static int natm_usr_detach __P((struct socket *));
79static int natm_usr_connect __P((struct socket *, struct sockaddr *,
80 struct proc *));
81static int natm_usr_disconnect __P((struct socket *));
82static int natm_usr_shutdown __P((struct socket *));
83static int natm_usr_send __P((struct socket *, int, struct mbuf *,
84 struct sockaddr *, struct mbuf *,
85 struct proc *));
86static int natm_usr_peeraddr __P((struct socket *, struct sockaddr **));
87static int natm_usr_control __P((struct socket *, int, caddr_t,
88 struct ifnet *, struct proc *));
89static int natm_usr_abort __P((struct socket *));
90static int natm_usr_bind __P((struct socket *, struct sockaddr *,
91 struct proc *));
92static int natm_usr_sockaddr __P((struct socket *, struct sockaddr **));
93
94static int
95natm_usr_attach(struct socket *so, int proto, struct proc *p)
96{
97 struct natmpcb *npcb;
98 int error = 0;
99 int s = SPLSOFTNET();
100
101 npcb = (struct natmpcb *) so->so_pcb;
102
103 if (npcb) {
104 error = EISCONN;
105 goto out;
106 }
107
108 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
109 if (proto == PROTO_NATMAAL5)
110 error = soreserve(so, natm5_sendspace, natm5_recvspace);
111 else
112 error = soreserve(so, natm0_sendspace, natm0_recvspace);
113 if (error)
114 goto out;
115 }
116
117 so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK));
118 npcb->npcb_socket = so;
119 out:
120 splx(s);
121 return (error);
122}
123
124static int
125natm_usr_detach(struct socket *so)
126{
127 struct natmpcb *npcb;
128 int error = 0;
129 int s = SPLSOFTNET();
130
131 npcb = (struct natmpcb *) so->so_pcb;
132 if (npcb == NULL) {
133 error = EINVAL;
134 goto out;
135 }
136
137 /*
138 * we turn on 'drain' *before* we sofree.
139 */
140 npcb_free(npcb, NPCB_DESTROY); /* drain */
141 so->so_pcb = NULL;
142 sofree(so);
143 out:
144 splx(s);
145 return (error);
146}
147
148static int
149natm_usr_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
150{
151 struct natmpcb *npcb;
152 struct sockaddr_natm *snatm;
153 struct atm_pseudoioctl api;
154 struct atm_pseudohdr *aph;
155 struct ifnet *ifp;
156 int error = 0;
157 int s2, s = SPLSOFTNET();
158 int proto = so->so_proto->pr_protocol;
159
160 npcb = (struct natmpcb *) so->so_pcb;
161 if (npcb == NULL) {
162 error = EINVAL;
163 goto out;
164 }
165
166 /*
167 * validate nam and npcb
168 */
169
170 snatm = (struct sockaddr_natm *)nam;
171 if (snatm->snatm_len != sizeof(*snatm) ||
172 (npcb->npcb_flags & NPCB_FREE) == 0) {
173 error = EINVAL;
174 goto out;
175 }
176 if (snatm->snatm_family != AF_NATM) {
177 error = EAFNOSUPPORT;
178 goto out;
179 }
180
181 snatm->snatm_if[IFNAMSIZ-1] = '\0'; /* XXX ensure null termination
182 since ifunit() uses strcmp */
183
184 /*
185 * convert interface string to ifp, validate.
186 */
187
188 ifp = ifunit(snatm->snatm_if);
189 if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) {
190 error = ENXIO;
191 goto out;
192 }
193 if (ifp->if_output != atm_output) {
194 error = EAFNOSUPPORT;
195 goto out;
196 }
197
198 /*
199 * register us with the NATM PCB layer
200 */
201
202 if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) {
203 error = EADDRINUSE;
204 goto out;
205 }
206
207 /*
208 * enable rx
209 */
210
211 ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
212 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
213 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
214 api.rxhand = npcb;
215 s2 = splimp();
216 if (ifp->if_ioctl == NULL ||
217 ifp->if_ioctl(ifp, SIOCATMENA, (caddr_t) &api) != 0) {
218 splx(s2);
219 npcb_free(npcb, NPCB_REMOVE);
220 error = EIO;
221 goto out;
222 }
223 splx(s2);
224
225 soisconnected(so);
226
227 out:
228 splx(s);
229 return (error);
230}
231
232static int
233natm_usr_disconnect(struct socket *so)
234{
235 struct natmpcb *npcb;
236 struct sockaddr_natm *snatm;
237 struct atm_pseudoioctl api;
238 struct atm_pseudohdr *aph;
239 struct ifnet *ifp;
240 int error = 0;
241 int s2, s = SPLSOFTNET();
242 int proto = so->so_proto->pr_protocol;
243
244 npcb = (struct natmpcb *) so->so_pcb;
245 if (npcb == NULL) {
246 error = EINVAL;
247 goto out;
248 }
249
250 if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
251 printf("natm: disconnected check\n");
252 error = EIO;
253 goto out;
254 }
255 ifp = npcb->npcb_ifp;
256
257 /*
258 * disable rx
259 */
260
261 ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5;
262 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
263 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
264 api.rxhand = npcb;
265 s2 = splimp();
266 if (ifp->if_ioctl != NULL)
267 ifp->if_ioctl(ifp, SIOCATMDIS, (caddr_t) &api);
268 splx(s2);
269
270 npcb_free(npcb, NPCB_REMOVE);
271 soisdisconnected(so);
272
273 out:
274 splx(s);
275 return (error);
276}
277
278static int
279natm_usr_shutdown(struct socket *so)
280{
281 socantsendmore(so);
282 return 0;
283}
284
285static int
286natm_usr_send(struct socket *so, int flags, struct mbuf *m,
287 struct sockaddr *nam, struct mbuf *control, struct proc *p)
288{
289 struct natmpcb *npcb;
290 struct atm_pseudohdr *aph;
291 int error = 0;
292 int s = SPLSOFTNET();
293 int proto = so->so_proto->pr_protocol;
294
295 npcb = (struct natmpcb *) so->so_pcb;
296 if (npcb == NULL) {
297 error = EINVAL;
298 goto out;
299 }
300
301 if (control && control->m_len) {
302 m_freem(control);
303 m_freem(m);
304 error = EINVAL;
305 goto out;
306 }
307
308 /*
309 * send the data. we must put an atm_pseudohdr on first
310 */
311
312 M_PREPEND(m, sizeof(*aph), M_WAITOK);
313 if (m == NULL) {
314 error = ENOBUFS;
315 goto out;
316 }
317 aph = mtod(m, struct atm_pseudohdr *);
318 ATM_PH_VPI(aph) = npcb->npcb_vpi;
319 ATM_PH_SETVCI(aph, npcb->npcb_vci);
320 ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
321
322 error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
323
324 out:
325 splx(s);
326 return (error);
327}
328
329static int
330natm_usr_peeraddr(struct socket *so, struct sockaddr **nam)
331{
332 struct natmpcb *npcb;
333 struct sockaddr_natm *snatm, ssnatm;
334 int error = 0;
335 int s = SPLSOFTNET();
336
337 npcb = (struct natmpcb *) so->so_pcb;
338 if (npcb == NULL) {
339 error = EINVAL;
340 goto out;
341 }
342
343 snatm = &ssnatm;
344 bzero(snatm, sizeof(*snatm));
345 snatm->snatm_len = sizeof(*snatm);
346 snatm->snatm_family = AF_NATM;
347 sprintf(snatm->snatm_if, "%s%d", npcb->npcb_ifp->if_name,
348 npcb->npcb_ifp->if_unit);
349 snatm->snatm_vci = npcb->npcb_vci;
350 snatm->snatm_vpi = npcb->npcb_vpi;
351 *nam = dup_sockaddr((struct sockaddr *)snatm, 0);
352
353 out:
354 splx(s);
355 return (error);
356}
357
358static int
359natm_usr_control(struct socket *so, int cmd, caddr_t arg,
360 struct ifnet *ifp, struct proc *p)
361{
362 struct natmpcb *npcb;
363 struct atm_rawioctl ario;
364 int error = 0;
365 int s = SPLSOFTNET();
366
367 npcb = (struct natmpcb *) so->so_pcb;
368 if (npcb == NULL) {
369 error = EINVAL;
370 goto out;
371 }
372
373 /*
374 * raw atm ioctl. comes in as a SIOCRAWATM. we convert it to
375 * SIOCXRAWATM and pass it to the driver.
376 */
377 if (cmd == SIOCRAWATM) {
378 if (npcb->npcb_ifp == NULL) {
379 error = ENOTCONN;
380 goto out;
381 }
382 ario.npcb = npcb;
383 ario.rawvalue = *((int *)arg);
384 error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp,
385 SIOCXRAWATM, (caddr_t) &ario);
386 if (!error) {
387 if (ario.rawvalue)
388 npcb->npcb_flags |= NPCB_RAW;
389 else
390 npcb->npcb_flags &= ~(NPCB_RAW);
391 }
392 }
393 else
394 error = EOPNOTSUPP;
395
396 out:
397 splx(s);
398 return (error);
399}
400
401static int
402natm_usr_abort(struct socket *so)
403{
404 return natm_usr_shutdown(so);
405}
406
407static int
408natm_usr_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
409{
410 return EOPNOTSUPP;
411}
412
413static int
414natm_usr_sockaddr(struct socket *so, struct sockaddr **nam)
415{
416 return EOPNOTSUPP;
417}
418
419/* xxx - should be const */
420struct pr_usrreqs natm_usrreqs = {
421 natm_usr_abort, pru_accept_notsupp, natm_usr_attach, natm_usr_bind,
422 natm_usr_connect, pru_connect2_notsupp, natm_usr_control,
423 natm_usr_detach, natm_usr_disconnect, pru_listen_notsupp,
424 natm_usr_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp,
425 natm_usr_send, pru_sense_null, natm_usr_shutdown,
426 natm_usr_sockaddr, sosend, soreceive, soselect
427};
428
429#else /* !FREEBSD_USRREQS */
430
431#if defined(__NetBSD__) || defined(__OpenBSD__)
432int natm_usrreq(so, req, m, nam, control, p)
433#elif defined(__FreeBSD__)
434int natm_usrreq(so, req, m, nam, control)
435#endif
436
437struct socket *so;
438int req;
439struct mbuf *m, *nam, *control;
440#if defined(__NetBSD__) || defined(__OpenBSD__)
441struct proc *p;
442#endif
443
444{
445 int error = 0, s, s2;
446 struct natmpcb *npcb;
447 struct sockaddr_natm *snatm;
448 struct atm_pseudoioctl api;
449 struct atm_pseudohdr *aph;
450 struct atm_rawioctl ario;
451 struct ifnet *ifp;
452 int proto = so->so_proto->pr_protocol;
453
454 s = SPLSOFTNET();
455
456 npcb = (struct natmpcb *) so->so_pcb;
457
458 if (npcb == NULL && req != PRU_ATTACH) {
459 error = EINVAL;
460 goto done;
461 }
462
463
464 switch (req) {
465 case PRU_ATTACH: /* attach protocol to up */
466
467 if (npcb) {
468 error = EISCONN;
469 break;
470 }
471
472 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
473 if (proto == PROTO_NATMAAL5)
474 error = soreserve(so, natm5_sendspace, natm5_recvspace);
475 else
476 error = soreserve(so, natm0_sendspace, natm0_recvspace);
477 if (error)
478 break;
479 }
480
481 so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK));
482 npcb->npcb_socket = so;
483
484 break;
485
486 case PRU_DETACH: /* detach protocol from up */
487
488 /*
489 * we turn on 'drain' *before* we sofree.
490 */
491
492 npcb_free(npcb, NPCB_DESTROY); /* drain */
493 so->so_pcb = NULL;
494 sofree(so);
495
496 break;
497
498 case PRU_CONNECT: /* establish connection to peer */
499
500 /*
501 * validate nam and npcb
502 */
503
504 if (nam->m_len != sizeof(*snatm)) {
505 error = EINVAL;
506 break;
507 }
508 snatm = mtod(nam, struct sockaddr_natm *);
509 if (snatm->snatm_len != sizeof(*snatm) ||
510 (npcb->npcb_flags & NPCB_FREE) == 0) {
511 error = EINVAL;
512 break;
513 }
514 if (snatm->snatm_family != AF_NATM) {
515 error = EAFNOSUPPORT;
516 break;
517 }
518
519 snatm->snatm_if[IFNAMSIZ-1] = '\0'; /* XXX ensure null termination
520 since ifunit() uses strcmp */
521
522 /*
523 * convert interface string to ifp, validate.
524 */
525
526 ifp = ifunit(snatm->snatm_if);
527 if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) {
528 error = ENXIO;
529 break;
530 }
531 if (ifp->if_output != atm_output) {
532 error = EAFNOSUPPORT;
533 break;
534 }
535
536
537 /*
538 * register us with the NATM PCB layer
539 */
540
541 if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) {
542 error = EADDRINUSE;
543 break;
544 }
545
546 /*
547 * enable rx
548 */
549
550 ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
551 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
552 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
553 api.rxhand = npcb;
554 s2 = splimp();
555 if (ifp->if_ioctl == NULL ||
556 ifp->if_ioctl(ifp, SIOCATMENA, (caddr_t) &api) != 0) {
557 splx(s2);
558 npcb_free(npcb, NPCB_REMOVE);
559 error = EIO;
560 break;
561 }
562 splx(s2);
563
564 soisconnected(so);
565
566 break;
567
568 case PRU_DISCONNECT: /* disconnect from peer */
569
570 if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
571 printf("natm: disconnected check\n");
572 error = EIO;
573 break;
574 }
575 ifp = npcb->npcb_ifp;
576
577 /*
578 * disable rx
579 */
580
581 ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5;
582 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
583 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
584 api.rxhand = npcb;
585 s2 = splimp();
586 if (ifp->if_ioctl != NULL)
587 ifp->if_ioctl(ifp, SIOCATMDIS, (caddr_t) &api);
588 splx(s2);
589
590 npcb_free(npcb, NPCB_REMOVE);
591 soisdisconnected(so);
592
593 break;
594
595 case PRU_SHUTDOWN: /* won't send any more data */
596 socantsendmore(so);
597 break;
598
599 case PRU_SEND: /* send this data */
600 if (control && control->m_len) {
601 m_freem(control);
602 m_freem(m);
603 error = EINVAL;
604 break;
605 }
606
607 /*
608 * send the data. we must put an atm_pseudohdr on first
609 */
610
611 M_PREPEND(m, sizeof(*aph), M_WAITOK);
612 if (m == NULL) {
613 error = ENOBUFS;
614 break;
615 }
616 aph = mtod(m, struct atm_pseudohdr *);
617 ATM_PH_VPI(aph) = npcb->npcb_vpi;
618 ATM_PH_SETVCI(aph, npcb->npcb_vci);
619 ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
620
621 error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
622
623 break;
624
625 case PRU_SENSE: /* return status into m */
626 /* return zero? */
627 break;
628
629 case PRU_PEERADDR: /* fetch peer's address */
630 snatm = mtod(nam, struct sockaddr_natm *);
631 bzero(snatm, sizeof(*snatm));
632 nam->m_len = snatm->snatm_len = sizeof(*snatm);
633 snatm->snatm_family = AF_NATM;
634#if defined(__NetBSD__) || defined(__OpenBSD__)
635 bcopy(npcb->npcb_ifp->if_xname, snatm->snatm_if, sizeof(snatm->snatm_if));
636#elif defined(__FreeBSD__)
637 sprintf(snatm->snatm_if, "%s%d", npcb->npcb_ifp->if_name,
638 npcb->npcb_ifp->if_unit);
639#endif
640 snatm->snatm_vci = npcb->npcb_vci;
641 snatm->snatm_vpi = npcb->npcb_vpi;
642 break;
643
644 case PRU_CONTROL: /* control operations on protocol */
645 /*
646 * raw atm ioctl. comes in as a SIOCRAWATM. we convert it to
647 * SIOCXRAWATM and pass it to the driver.
648 */
649 if ((u_long)m == SIOCRAWATM) {
650 if (npcb->npcb_ifp == NULL) {
651 error = ENOTCONN;
652 break;
653 }
654 ario.npcb = npcb;
655 ario.rawvalue = *((int *)nam);
656 error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp,
657 SIOCXRAWATM, (caddr_t) &ario);
658 if (!error) {
659 if (ario.rawvalue)
660 npcb->npcb_flags |= NPCB_RAW;
661 else
662 npcb->npcb_flags &= ~(NPCB_RAW);
663 }
664
665 break;
666 }
667
668 error = EOPNOTSUPP;
669 break;
670
671 case PRU_BIND: /* bind socket to address */
672 case PRU_LISTEN: /* listen for connection */
673 case PRU_ACCEPT: /* accept connection from peer */
674 case PRU_CONNECT2: /* connect two sockets */
675 case PRU_ABORT: /* abort (fast DISCONNECT, DETATCH) */
676 /* (only happens if LISTEN socket) */
677 case PRU_RCVD: /* have taken data; more room now */
678 case PRU_FASTTIMO: /* 200ms timeout */
679 case PRU_SLOWTIMO: /* 500ms timeout */
680 case PRU_RCVOOB: /* retrieve out of band data */
681 case PRU_SENDOOB: /* send out of band data */
682 case PRU_PROTORCV: /* receive from below */
683 case PRU_PROTOSEND: /* send to below */
684 case PRU_SOCKADDR: /* fetch socket's address */
685#ifdef DIAGNOSTIC
686 printf("natm: PRU #%d unsupported\n", req);
687#endif
688 error = EOPNOTSUPP;
689 break;
690
691 default: panic("natm usrreq");
692 }
693
694done:
695 splx(s);
696 return(error);
697}
698
699#endif /* !FREEBSD_USRREQS */
700
701/*
702 * natmintr: splsoftnet interrupt
703 *
704 * note: we expect a socket pointer in rcvif rather than an interface
705 * pointer. we can get the interface pointer from the so's PCB if
706 * we really need it.
707 */
708
709void
710natmintr()
711
712{
713 int s;
714 struct mbuf *m;
715 struct socket *so;
716 struct natmpcb *npcb;
717
718next:
719 s = splimp();
720 IF_DEQUEUE(&natmintrq, m);
721 splx(s);
722 if (m == NULL)
723 return;
724
725#ifdef DIAGNOSTIC
726 if ((m->m_flags & M_PKTHDR) == 0)
727 panic("natmintr no HDR");
728#endif
729
730 npcb = (struct natmpcb *) m->m_pkthdr.rcvif; /* XXX: overloaded */
731 so = npcb->npcb_socket;
732
733 s = splimp(); /* could have atm devs @ different levels */
734 npcb->npcb_inq--;
735 splx(s);
736
737 if (npcb->npcb_flags & NPCB_DRAIN) {
738 m_freem(m);
739 if (npcb->npcb_inq == 0)
740 FREE(npcb, M_PCB); /* done! */
741 goto next;
742 }
743
744 if (npcb->npcb_flags & NPCB_FREE) {
745 m_freem(m); /* drop */
746 goto next;
747 }
748
749#ifdef NEED_TO_RESTORE_IFP
750 m->m_pkthdr.rcvif = npcb->npcb_ifp;
751#else
752#ifdef DIAGNOSTIC
753m->m_pkthdr.rcvif = NULL; /* null it out to be safe */
754#endif
755#endif
756
757 if (sbspace(&so->so_rcv) > m->m_pkthdr.len ||
758 ((npcb->npcb_flags & NPCB_RAW) != 0 && so->so_rcv.sb_cc < NPCB_RAWCC) ) {
759#ifdef NATM_STAT
760 natm_sookcnt++;
761 natm_sookbytes += m->m_pkthdr.len;
762#endif
763 sbappendrecord(&so->so_rcv, m);
764 sorwakeup(so);
765 } else {
766#ifdef NATM_STAT
767 natm_sodropcnt++;
768 natm_sodropbytes += m->m_pkthdr.len;
769#endif
770 m_freem(m);
771 }
772
773 goto next;
774}
775
776#if defined(__FreeBSD__)
777NETISR_SET(NETISR_NATM, natmintr);
778#endif
779
780
781/*
782 * natm0_sysctl: not used, but here in case we want to add something
783 * later...
784 */
785
786int natm0_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
787
788int *name;
789u_int namelen;
790void *oldp;
791size_t *oldlenp;
792void *newp;
793size_t newlen;
794
795{
796 /* All sysctl names at this level are terminal. */
797 if (namelen != 1)
798 return (ENOTDIR);
799 return (ENOPROTOOPT);
800}
801
802/*
803 * natm5_sysctl: not used, but here in case we want to add something
804 * later...
805 */
806
807int natm5_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
808
809int *name;
810u_int namelen;
811void *oldp;
812size_t *oldlenp;
813void *newp;
814size_t newlen;
815
816{
817 /* All sysctl names at this level are terminal. */
818 if (namelen != 1)
819 return (ENOTDIR);
820 return (ENOPROTOOPT);
821}