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