natm.c revision 41514
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 57static u_long natm5_sendspace = 16*1024; 58static u_long natm5_recvspace = 16*1024; 59 60static u_long natm0_sendspace = 16*1024; 61static 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 */ 70static int natm_usr_attach __P((struct socket *, int, struct proc *)); 71static int natm_usr_detach __P((struct socket *)); 72static int natm_usr_connect __P((struct socket *, struct sockaddr *, 73 struct proc *)); 74static int natm_usr_disconnect __P((struct socket *)); 75static int natm_usr_shutdown __P((struct socket *)); 76static int natm_usr_send __P((struct socket *, int, struct mbuf *, 77 struct sockaddr *, struct mbuf *, 78 struct proc *)); 79static int natm_usr_peeraddr __P((struct socket *, struct sockaddr **)); 80static int natm_usr_control __P((struct socket *, u_long, caddr_t, 81 struct ifnet *, struct proc *)); 82static int natm_usr_abort __P((struct socket *)); 83static int natm_usr_bind __P((struct socket *, struct sockaddr *, 84 struct proc *)); 85static int natm_usr_sockaddr __P((struct socket *, struct sockaddr **)); 86 87static int 88natm_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 117static int 118natm_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 141static int 142natm_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 224static int 225natm_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 267static int 268natm_usr_shutdown(struct socket *so) 269{ 270 socantsendmore(so); 271 return 0; 272} 273 274static int 275natm_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 318static int 319natm_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 347static int 348natm_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 390static int 391natm_usr_abort(struct socket *so) 392{ 393 return natm_usr_shutdown(so); 394} 395 396static int 397natm_usr_bind(struct socket *so, struct sockaddr *nam, struct proc *p) 398{ 399 return EOPNOTSUPP; 400} 401 402static int 403natm_usr_sockaddr(struct socket *so, struct sockaddr **nam) 404{ 405 return EOPNOTSUPP; 406} 407 408/* xxx - should be const */ 409struct 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__) 421int natm_usrreq(so, req, m, nam, control, p) 422#elif defined(__FreeBSD__) 423int natm_usrreq(so, req, m, nam, control) 424#endif 425 426struct socket *so; 427int req; 428struct mbuf *m, *nam, *control; 429#if defined(__NetBSD__) || defined(__OpenBSD__) 430struct 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 683done: 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 698void 699natmintr() 700 701{ 702 int s; 703 struct mbuf *m; 704 struct socket *so; 705 struct natmpcb *npcb; 706 707next: 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 742m->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__) 766NETISR_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 775int natm0_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 776 777int *name; 778u_int namelen; 779void *oldp; 780size_t *oldlenp; 781void *newp; 782size_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 796int natm5_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 797 798int *name; 799u_int namelen; 800void *oldp; 801size_t *oldlenp; 802void *newp; 803size_t newlen; 804 805{ 806 /* All sysctl names at this level are terminal. */ 807 if (namelen != 1) 808 return (ENOTDIR); 809 return (ENOPROTOOPT); 810} 811