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