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