natm.c revision 117643
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: head/sys/netnatm/natm.c 117643 2003-07-15 15:51:50Z harti $"); 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 55#include <net/if.h> 56#include <net/if_atm.h> 57#include <net/netisr.h> 58 59#include <netinet/in.h> 60 61#include <netnatm/natm.h> 62 63static u_long natm5_sendspace = 16*1024; 64static u_long natm5_recvspace = 16*1024; 65 66static u_long natm0_sendspace = 16*1024; 67static u_long natm0_recvspace = 16*1024; 68 69/* 70 * user requests 71 */ 72#ifdef FREEBSD_USRREQS 73/* 74 * FreeBSD new usrreqs supersedes pr_usrreq. 75 */ 76static int natm_usr_attach(struct socket *, int, d_thread_t *); 77static int natm_usr_detach(struct socket *); 78static int natm_usr_connect(struct socket *, struct sockaddr *, d_thread_t *); 79static int natm_usr_disconnect(struct socket *); 80static int natm_usr_shutdown(struct socket *); 81static int natm_usr_send(struct socket *, int, struct mbuf *, 82 struct sockaddr *, struct mbuf *, d_thread_t *); 83static int natm_usr_peeraddr(struct socket *, struct sockaddr **); 84static int natm_usr_control(struct socket *, u_long, caddr_t, 85 struct ifnet *, d_thread_t *); 86static int natm_usr_abort(struct socket *); 87static int natm_usr_bind(struct socket *, struct sockaddr *, d_thread_t *); 88static int natm_usr_sockaddr(struct socket *, struct sockaddr **); 89 90static int 91natm_usr_attach(struct socket *so, int proto, d_thread_t *p) 92{ 93 struct natmpcb *npcb; 94 int error = 0; 95 int s = SPLSOFTNET(); 96 97 npcb = (struct natmpcb *) so->so_pcb; 98 99 if (npcb) { 100 error = EISCONN; 101 goto out; 102 } 103 104 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 105 if (proto == PROTO_NATMAAL5) 106 error = soreserve(so, natm5_sendspace, natm5_recvspace); 107 else 108 error = soreserve(so, natm0_sendspace, natm0_recvspace); 109 if (error) 110 goto out; 111 } 112 113 so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK)); 114 npcb->npcb_socket = so; 115 out: 116 splx(s); 117 return (error); 118} 119 120static int 121natm_usr_detach(struct socket *so) 122{ 123 struct natmpcb *npcb; 124 int error = 0; 125 int s = SPLSOFTNET(); 126 127 npcb = (struct natmpcb *) so->so_pcb; 128 if (npcb == NULL) { 129 error = EINVAL; 130 goto out; 131 } 132 133 /* 134 * we turn on 'drain' *before* we sofree. 135 */ 136 npcb_free(npcb, NPCB_DESTROY); /* drain */ 137 so->so_pcb = NULL; 138 sotryfree(so); 139 out: 140 splx(s); 141 return (error); 142} 143 144static int 145natm_usr_connect(struct socket *so, struct sockaddr *nam, d_thread_t *p) 146{ 147 struct natmpcb *npcb; 148 struct sockaddr_natm *snatm; 149 struct atm_pseudoioctl api; 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 atm_pseudoioctl api; 232 struct ifnet *ifp; 233 int error = 0; 234 int s2, s = SPLSOFTNET(); 235 236 npcb = (struct natmpcb *) so->so_pcb; 237 if (npcb == NULL) { 238 error = EINVAL; 239 goto out; 240 } 241 242 if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) { 243 printf("natm: disconnected check\n"); 244 error = EIO; 245 goto out; 246 } 247 ifp = npcb->npcb_ifp; 248 249 /* 250 * disable rx 251 */ 252 253 ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5; 254 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi; 255 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci); 256 api.rxhand = npcb; 257 s2 = splimp(); 258 if (ifp->if_ioctl != NULL) 259 ifp->if_ioctl(ifp, SIOCATMDIS, (caddr_t) &api); 260 splx(s2); 261 262 npcb_free(npcb, NPCB_REMOVE); 263 soisdisconnected(so); 264 265 out: 266 splx(s); 267 return (error); 268} 269 270static int 271natm_usr_shutdown(struct socket *so) 272{ 273 socantsendmore(so); 274 return 0; 275} 276 277static int 278natm_usr_send(struct socket *so, int flags, struct mbuf *m, 279 struct sockaddr *nam, struct mbuf *control, d_thread_t *p) 280{ 281 struct natmpcb *npcb; 282 struct atm_pseudohdr *aph; 283 int error = 0; 284 int s = SPLSOFTNET(); 285 int proto = so->so_proto->pr_protocol; 286 287 npcb = (struct natmpcb *) so->so_pcb; 288 if (npcb == NULL) { 289 error = EINVAL; 290 goto out; 291 } 292 293 if (control && control->m_len) { 294 m_freem(control); 295 m_freem(m); 296 error = EINVAL; 297 goto out; 298 } 299 300 /* 301 * send the data. we must put an atm_pseudohdr on first 302 */ 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 321static int 322natm_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 snprintf(snatm->snatm_if, sizeof(snatm->snatm_if), 340 "%s%d", npcb->npcb_ifp->if_name, npcb->npcb_ifp->if_unit); 341 snatm->snatm_vci = npcb->npcb_vci; 342 snatm->snatm_vpi = npcb->npcb_vpi; 343 *nam = dup_sockaddr((struct sockaddr *)snatm, 0); 344 345 out: 346 splx(s); 347 return (error); 348} 349 350static int 351natm_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 struct atm_rawioctl ario; 356 int error = 0; 357 int s = SPLSOFTNET(); 358 359 npcb = (struct natmpcb *) so->so_pcb; 360 if (npcb == NULL) { 361 error = EINVAL; 362 goto out; 363 } 364 365 /* 366 * raw atm ioctl. comes in as a SIOCRAWATM. we convert it to 367 * SIOCXRAWATM and pass it to the driver. 368 */ 369 if (cmd == SIOCRAWATM) { 370 if (npcb->npcb_ifp == NULL) { 371 error = ENOTCONN; 372 goto out; 373 } 374 ario.npcb = npcb; 375 ario.rawvalue = *((int *)arg); 376 error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp, 377 SIOCXRAWATM, (caddr_t) &ario); 378 if (!error) { 379 if (ario.rawvalue) 380 npcb->npcb_flags |= NPCB_RAW; 381 else 382 npcb->npcb_flags &= ~(NPCB_RAW); 383 } 384 } else { 385 splx(s); 386 if (ifp == NULL || ifp->if_ioctl == NULL) 387 return (EOPNOTSUPP); 388 return ((*ifp->if_ioctl)(ifp, cmd, arg)); 389 } 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, d_thread_t *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 sotryfree(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_TRYWAIT); 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 snprintf(snatm->snatm_if, sizeof(snatm->snatm_if), 633 "%s%d", npcb->npcb_ifp->if_name, 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(struct mbuf *m) 706{ 707 int s; 708 struct socket *so; 709 struct natmpcb *npcb; 710 711#ifdef DIAGNOSTIC 712 M_ASSERTPKTHDR(m); 713#endif 714 715 npcb = (struct natmpcb *) m->m_pkthdr.rcvif; /* XXX: overloaded */ 716 so = npcb->npcb_socket; 717 718 s = splimp(); /* could have atm devs @ different levels */ 719 npcb->npcb_inq--; 720 splx(s); 721 722 if (npcb->npcb_flags & NPCB_DRAIN) { 723 m_freem(m); 724 if (npcb->npcb_inq == 0) 725 FREE(npcb, M_PCB); /* done! */ 726 return; 727 } 728 729 if (npcb->npcb_flags & NPCB_FREE) { 730 m_freem(m); /* drop */ 731 return; 732 } 733 734#ifdef NEED_TO_RESTORE_IFP 735 m->m_pkthdr.rcvif = npcb->npcb_ifp; 736#else 737#ifdef DIAGNOSTIC 738m->m_pkthdr.rcvif = NULL; /* null it out to be safe */ 739#endif 740#endif 741 742 if (sbspace(&so->so_rcv) > m->m_pkthdr.len || 743 ((npcb->npcb_flags & NPCB_RAW) != 0 && so->so_rcv.sb_cc < NPCB_RAWCC) ) { 744#ifdef NATM_STAT 745 natm_sookcnt++; 746 natm_sookbytes += m->m_pkthdr.len; 747#endif 748 sbappendrecord(&so->so_rcv, m); 749 sorwakeup(so); 750 } else { 751#ifdef NATM_STAT 752 natm_sodropcnt++; 753 natm_sodropbytes += m->m_pkthdr.len; 754#endif 755 m_freem(m); 756 } 757} 758 759/* 760 * natm0_sysctl: not used, but here in case we want to add something 761 * later... 762 */ 763 764int natm0_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 765 766int *name; 767u_int namelen; 768void *oldp; 769size_t *oldlenp; 770void *newp; 771size_t newlen; 772 773{ 774 /* All sysctl names at this level are terminal. */ 775 if (namelen != 1) 776 return (ENOTDIR); 777 return (ENOPROTOOPT); 778} 779 780/* 781 * natm5_sysctl: not used, but here in case we want to add something 782 * later... 783 */ 784 785int natm5_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 786 787int *name; 788u_int namelen; 789void *oldp; 790size_t *oldlenp; 791void *newp; 792size_t newlen; 793 794{ 795 /* All sysctl names at this level are terminal. */ 796 if (namelen != 1) 797 return (ENOTDIR); 798 return (ENOPROTOOPT); 799} 800