natm.c revision 116189
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 116189 2003-06-11 05:37:42Z obrien $"); 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 } 385 else 386 error = EOPNOTSUPP; 387 388 out: 389 splx(s); 390 return (error); 391} 392 393static int 394natm_usr_abort(struct socket *so) 395{ 396 return natm_usr_shutdown(so); 397} 398 399static int 400natm_usr_bind(struct socket *so, struct sockaddr *nam, d_thread_t *p) 401{ 402 return EOPNOTSUPP; 403} 404 405static int 406natm_usr_sockaddr(struct socket *so, struct sockaddr **nam) 407{ 408 return EOPNOTSUPP; 409} 410 411/* xxx - should be const */ 412struct pr_usrreqs natm_usrreqs = { 413 natm_usr_abort, pru_accept_notsupp, natm_usr_attach, natm_usr_bind, 414 natm_usr_connect, pru_connect2_notsupp, natm_usr_control, 415 natm_usr_detach, natm_usr_disconnect, pru_listen_notsupp, 416 natm_usr_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp, 417 natm_usr_send, pru_sense_null, natm_usr_shutdown, 418 natm_usr_sockaddr, sosend, soreceive, sopoll 419}; 420 421#else /* !FREEBSD_USRREQS */ 422 423#if defined(__NetBSD__) || defined(__OpenBSD__) 424int natm_usrreq(so, req, m, nam, control, p) 425#elif defined(__FreeBSD__) 426int natm_usrreq(so, req, m, nam, control) 427#endif 428 429struct socket *so; 430int req; 431struct mbuf *m, *nam, *control; 432#if defined(__NetBSD__) || defined(__OpenBSD__) 433struct proc *p; 434#endif 435 436{ 437 int error = 0, s, s2; 438 struct natmpcb *npcb; 439 struct sockaddr_natm *snatm; 440 struct atm_pseudoioctl api; 441 struct atm_pseudohdr *aph; 442 struct atm_rawioctl ario; 443 struct ifnet *ifp; 444 int proto = so->so_proto->pr_protocol; 445 446 s = SPLSOFTNET(); 447 448 npcb = (struct natmpcb *) so->so_pcb; 449 450 if (npcb == NULL && req != PRU_ATTACH) { 451 error = EINVAL; 452 goto done; 453 } 454 455 456 switch (req) { 457 case PRU_ATTACH: /* attach protocol to up */ 458 459 if (npcb) { 460 error = EISCONN; 461 break; 462 } 463 464 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 465 if (proto == PROTO_NATMAAL5) 466 error = soreserve(so, natm5_sendspace, natm5_recvspace); 467 else 468 error = soreserve(so, natm0_sendspace, natm0_recvspace); 469 if (error) 470 break; 471 } 472 473 so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK)); 474 npcb->npcb_socket = so; 475 476 break; 477 478 case PRU_DETACH: /* detach protocol from up */ 479 480 /* 481 * we turn on 'drain' *before* we sofree. 482 */ 483 484 npcb_free(npcb, NPCB_DESTROY); /* drain */ 485 so->so_pcb = NULL; 486 sotryfree(so); 487 488 break; 489 490 case PRU_CONNECT: /* establish connection to peer */ 491 492 /* 493 * validate nam and npcb 494 */ 495 496 if (nam->m_len != sizeof(*snatm)) { 497 error = EINVAL; 498 break; 499 } 500 snatm = mtod(nam, struct sockaddr_natm *); 501 if (snatm->snatm_len != sizeof(*snatm) || 502 (npcb->npcb_flags & NPCB_FREE) == 0) { 503 error = EINVAL; 504 break; 505 } 506 if (snatm->snatm_family != AF_NATM) { 507 error = EAFNOSUPPORT; 508 break; 509 } 510 511 snatm->snatm_if[IFNAMSIZ-1] = '\0'; /* XXX ensure null termination 512 since ifunit() uses strcmp */ 513 514 /* 515 * convert interface string to ifp, validate. 516 */ 517 518 ifp = ifunit(snatm->snatm_if); 519 if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) { 520 error = ENXIO; 521 break; 522 } 523 if (ifp->if_output != atm_output) { 524 error = EAFNOSUPPORT; 525 break; 526 } 527 528 529 /* 530 * register us with the NATM PCB layer 531 */ 532 533 if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) { 534 error = EADDRINUSE; 535 break; 536 } 537 538 /* 539 * enable rx 540 */ 541 542 ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; 543 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi; 544 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci); 545 api.rxhand = npcb; 546 s2 = splimp(); 547 if (ifp->if_ioctl == NULL || 548 ifp->if_ioctl(ifp, SIOCATMENA, (caddr_t) &api) != 0) { 549 splx(s2); 550 npcb_free(npcb, NPCB_REMOVE); 551 error = EIO; 552 break; 553 } 554 splx(s2); 555 556 soisconnected(so); 557 558 break; 559 560 case PRU_DISCONNECT: /* disconnect from peer */ 561 562 if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) { 563 printf("natm: disconnected check\n"); 564 error = EIO; 565 break; 566 } 567 ifp = npcb->npcb_ifp; 568 569 /* 570 * disable rx 571 */ 572 573 ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5; 574 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi; 575 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci); 576 api.rxhand = npcb; 577 s2 = splimp(); 578 if (ifp->if_ioctl != NULL) 579 ifp->if_ioctl(ifp, SIOCATMDIS, (caddr_t) &api); 580 splx(s2); 581 582 npcb_free(npcb, NPCB_REMOVE); 583 soisdisconnected(so); 584 585 break; 586 587 case PRU_SHUTDOWN: /* won't send any more data */ 588 socantsendmore(so); 589 break; 590 591 case PRU_SEND: /* send this data */ 592 if (control && control->m_len) { 593 m_freem(control); 594 m_freem(m); 595 error = EINVAL; 596 break; 597 } 598 599 /* 600 * send the data. we must put an atm_pseudohdr on first 601 */ 602 603 M_PREPEND(m, sizeof(*aph), M_TRYWAIT); 604 if (m == NULL) { 605 error = ENOBUFS; 606 break; 607 } 608 aph = mtod(m, struct atm_pseudohdr *); 609 ATM_PH_VPI(aph) = npcb->npcb_vpi; 610 ATM_PH_SETVCI(aph, npcb->npcb_vci); 611 ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; 612 613 error = atm_output(npcb->npcb_ifp, m, NULL, NULL); 614 615 break; 616 617 case PRU_SENSE: /* return status into m */ 618 /* return zero? */ 619 break; 620 621 case PRU_PEERADDR: /* fetch peer's address */ 622 snatm = mtod(nam, struct sockaddr_natm *); 623 bzero(snatm, sizeof(*snatm)); 624 nam->m_len = snatm->snatm_len = sizeof(*snatm); 625 snatm->snatm_family = AF_NATM; 626#if defined(__NetBSD__) || defined(__OpenBSD__) 627 bcopy(npcb->npcb_ifp->if_xname, snatm->snatm_if, sizeof(snatm->snatm_if)); 628#elif defined(__FreeBSD__) 629 snprintf(snatm->snatm_if, sizeof(snatm->snatm_if), 630 "%s%d", npcb->npcb_ifp->if_name, npcb->npcb_ifp->if_unit); 631#endif 632 snatm->snatm_vci = npcb->npcb_vci; 633 snatm->snatm_vpi = npcb->npcb_vpi; 634 break; 635 636 case PRU_CONTROL: /* control operations on protocol */ 637 /* 638 * raw atm ioctl. comes in as a SIOCRAWATM. we convert it to 639 * SIOCXRAWATM and pass it to the driver. 640 */ 641 if ((u_long)m == SIOCRAWATM) { 642 if (npcb->npcb_ifp == NULL) { 643 error = ENOTCONN; 644 break; 645 } 646 ario.npcb = npcb; 647 ario.rawvalue = *((int *)nam); 648 error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp, 649 SIOCXRAWATM, (caddr_t) &ario); 650 if (!error) { 651 if (ario.rawvalue) 652 npcb->npcb_flags |= NPCB_RAW; 653 else 654 npcb->npcb_flags &= ~(NPCB_RAW); 655 } 656 657 break; 658 } 659 660 error = EOPNOTSUPP; 661 break; 662 663 case PRU_BIND: /* bind socket to address */ 664 case PRU_LISTEN: /* listen for connection */ 665 case PRU_ACCEPT: /* accept connection from peer */ 666 case PRU_CONNECT2: /* connect two sockets */ 667 case PRU_ABORT: /* abort (fast DISCONNECT, DETATCH) */ 668 /* (only happens if LISTEN socket) */ 669 case PRU_RCVD: /* have taken data; more room now */ 670 case PRU_FASTTIMO: /* 200ms timeout */ 671 case PRU_SLOWTIMO: /* 500ms timeout */ 672 case PRU_RCVOOB: /* retrieve out of band data */ 673 case PRU_SENDOOB: /* send out of band data */ 674 case PRU_PROTORCV: /* receive from below */ 675 case PRU_PROTOSEND: /* send to below */ 676 case PRU_SOCKADDR: /* fetch socket's address */ 677#ifdef DIAGNOSTIC 678 printf("natm: PRU #%d unsupported\n", req); 679#endif 680 error = EOPNOTSUPP; 681 break; 682 683 default: panic("natm usrreq"); 684 } 685 686done: 687 splx(s); 688 return(error); 689} 690 691#endif /* !FREEBSD_USRREQS */ 692 693/* 694 * natmintr: splsoftnet interrupt 695 * 696 * note: we expect a socket pointer in rcvif rather than an interface 697 * pointer. we can get the interface pointer from the so's PCB if 698 * we really need it. 699 */ 700 701void 702natmintr(struct mbuf *m) 703{ 704 int s; 705 struct socket *so; 706 struct natmpcb *npcb; 707 708#ifdef DIAGNOSTIC 709 M_ASSERTPKTHDR(m); 710#endif 711 712 npcb = (struct natmpcb *) m->m_pkthdr.rcvif; /* XXX: overloaded */ 713 so = npcb->npcb_socket; 714 715 s = splimp(); /* could have atm devs @ different levels */ 716 npcb->npcb_inq--; 717 splx(s); 718 719 if (npcb->npcb_flags & NPCB_DRAIN) { 720 m_freem(m); 721 if (npcb->npcb_inq == 0) 722 FREE(npcb, M_PCB); /* done! */ 723 return; 724 } 725 726 if (npcb->npcb_flags & NPCB_FREE) { 727 m_freem(m); /* drop */ 728 return; 729 } 730 731#ifdef NEED_TO_RESTORE_IFP 732 m->m_pkthdr.rcvif = npcb->npcb_ifp; 733#else 734#ifdef DIAGNOSTIC 735m->m_pkthdr.rcvif = NULL; /* null it out to be safe */ 736#endif 737#endif 738 739 if (sbspace(&so->so_rcv) > m->m_pkthdr.len || 740 ((npcb->npcb_flags & NPCB_RAW) != 0 && so->so_rcv.sb_cc < NPCB_RAWCC) ) { 741#ifdef NATM_STAT 742 natm_sookcnt++; 743 natm_sookbytes += m->m_pkthdr.len; 744#endif 745 sbappendrecord(&so->so_rcv, m); 746 sorwakeup(so); 747 } else { 748#ifdef NATM_STAT 749 natm_sodropcnt++; 750 natm_sodropbytes += m->m_pkthdr.len; 751#endif 752 m_freem(m); 753 } 754} 755 756/* 757 * natm0_sysctl: not used, but here in case we want to add something 758 * later... 759 */ 760 761int natm0_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 762 763int *name; 764u_int namelen; 765void *oldp; 766size_t *oldlenp; 767void *newp; 768size_t newlen; 769 770{ 771 /* All sysctl names at this level are terminal. */ 772 if (namelen != 1) 773 return (ENOTDIR); 774 return (ENOPROTOOPT); 775} 776 777/* 778 * natm5_sysctl: not used, but here in case we want to add something 779 * later... 780 */ 781 782int natm5_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 783 784int *name; 785u_int namelen; 786void *oldp; 787size_t *oldlenp; 788void *newp; 789size_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