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