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