The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netnatm/natm.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: natm.c,v 1.16 2008/05/22 00:59:19 dyoung 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/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: natm.c,v 1.16 2008/05/22 00:59:19 dyoung Exp $");
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/domain.h>
   46 #include <sys/ioctl.h>
   47 #include <sys/proc.h>
   48 #include <sys/protosw.h>
   49 #include <sys/mbuf.h>
   50 #include <sys/socket.h>
   51 #include <sys/socketvar.h>
   52 
   53 #include <net/if.h>
   54 #include <net/if_atm.h>
   55 #include <net/netisr.h>
   56 #include <net/radix.h>
   57 #include <net/route.h>
   58 
   59 #include <netinet/in.h>
   60 
   61 #include <netnatm/natm.h>
   62 
   63 u_long natm5_sendspace = 16*1024;
   64 u_long natm5_recvspace = 16*1024;
   65 
   66 u_long natm0_sendspace = 16*1024;
   67 u_long natm0_recvspace = 16*1024;
   68 
   69 /*
   70  * user requests
   71  */
   72 
   73 #if defined(__NetBSD__)
   74 int natm_usrreq(so, req, m, nam, control, l)
   75 #elif defined(__OpenBSD__)
   76 int natm_usrreq(so, req, m, nam, control, p)
   77 #elif defined(__FreeBSD__)
   78 int natm_usrreq(so, req, m, nam, control)
   79 #endif
   80 
   81 struct socket *so;
   82 int req;
   83 struct mbuf *m, *nam, *control;
   84 #if defined(__NetBSD__)
   85 struct lwp *l;
   86 #elif deifned(__OpenBSD__)
   87 struct proc *p;
   88 #endif
   89 
   90 {
   91   int error = 0, s, s2;
   92   struct natmpcb *npcb;
   93   struct sockaddr_natm *snatm;
   94   struct atm_pseudoioctl api;
   95   struct atm_pseudohdr *aph;
   96   struct atm_rawioctl ario;
   97   struct ifnet *ifp;
   98   int proto = so->so_proto->pr_protocol;
   99 
  100   s = SPLSOFTNET();
  101 
  102   npcb = (struct natmpcb *) so->so_pcb;
  103 
  104   if (npcb == NULL && req != PRU_ATTACH) {
  105     error = EINVAL;
  106     goto done;
  107   }
  108 
  109 
  110   switch (req) {
  111     case PRU_ATTACH:                    /* attach protocol to up */
  112 
  113       if (npcb) {
  114         error = EISCONN;
  115         break;
  116       }
  117 
  118       if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
  119         if (proto == PROTO_NATMAAL5)
  120           error = soreserve(so, natm5_sendspace, natm5_recvspace);
  121         else
  122           error = soreserve(so, natm0_sendspace, natm0_recvspace);
  123         if (error)
  124           break;
  125       }
  126 
  127       so->so_pcb = (void *) (npcb = npcb_alloc(M_WAITOK));
  128       npcb->npcb_socket = so;
  129 
  130       break;
  131 
  132     case PRU_DETACH:                    /* detach protocol from up */
  133 
  134       /*
  135        * we turn on 'drain' *before* we sofree.
  136        */
  137 
  138       npcb_free(npcb, NPCB_DESTROY);    /* drain */
  139       so->so_pcb = NULL;
  140       /* sofree drops the lock */
  141       sofree(so);
  142       mutex_enter(softnet_lock);
  143 
  144       break;
  145 
  146     case PRU_CONNECT:                   /* establish connection to peer */
  147 
  148       /*
  149        * validate nam and npcb
  150        */
  151 
  152       if (nam->m_len != sizeof(*snatm)) {
  153         error = EINVAL;
  154         break;
  155       }
  156       snatm = mtod(nam, struct sockaddr_natm *);
  157       if (snatm->snatm_len != sizeof(*snatm) ||
  158                 (npcb->npcb_flags & NPCB_FREE) == 0) {
  159         error = EINVAL;
  160         break;
  161       }
  162       if (snatm->snatm_family != AF_NATM) {
  163         error = EAFNOSUPPORT;
  164         break;
  165       }
  166 
  167       snatm->snatm_if[IFNAMSIZ-1] = '\0';  /* XXX ensure null termination
  168                                                 since ifunit() uses strcmp */
  169 
  170       /*
  171        * convert interface string to ifp, validate.
  172        */
  173 
  174       ifp = ifunit(snatm->snatm_if);
  175       if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) {
  176         error = ENXIO;
  177         break;
  178       }
  179       if (ifp->if_output != atm_output) {
  180         error = EAFNOSUPPORT;
  181         break;
  182       }
  183 
  184 
  185       /*
  186        * register us with the NATM PCB layer
  187        */
  188 
  189       if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) {
  190         error = EADDRINUSE;
  191         break;
  192       }
  193 
  194       /*
  195        * enable rx
  196        */
  197 
  198       ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
  199       ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
  200       ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
  201       api.rxhand = npcb;
  202       s2 = splnet();
  203       if (ifp->if_ioctl == NULL || ifp->if_ioctl(ifp, SIOCATMENA, &api) != 0) {
  204         splx(s2);
  205         npcb_free(npcb, NPCB_REMOVE);
  206         error = EIO;
  207         break;
  208       }
  209       splx(s2);
  210 
  211       soisconnected(so);
  212 
  213       break;
  214 
  215     case PRU_DISCONNECT:                /* disconnect from peer */
  216 
  217       if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
  218         printf("natm: disconnected check\n");
  219         error = EIO;
  220         break;
  221       }
  222       ifp = npcb->npcb_ifp;
  223 
  224       /*
  225        * disable rx
  226        */
  227 
  228       ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5;
  229       ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
  230       ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
  231       api.rxhand = npcb;
  232       s2 = splnet();
  233       if (ifp->if_ioctl != NULL)
  234           ifp->if_ioctl(ifp, SIOCATMDIS, &api);
  235       splx(s);
  236 
  237       npcb_free(npcb, NPCB_REMOVE);
  238       soisdisconnected(so);
  239 
  240       break;
  241 
  242     case PRU_SHUTDOWN:                  /* won't send any more data */
  243       socantsendmore(so);
  244       break;
  245 
  246     case PRU_SEND:                      /* send this data */
  247       if (control && control->m_len) {
  248         m_freem(control);
  249         m_freem(m);
  250         error = EINVAL;
  251         break;
  252       }
  253 
  254       /*
  255        * send the data.   we must put an atm_pseudohdr on first
  256        */
  257 
  258       M_PREPEND(m, sizeof(*aph), M_WAITOK);
  259       if (m == NULL) {
  260         error = ENOBUFS;
  261         break;
  262       }
  263       aph = mtod(m, struct atm_pseudohdr *);
  264       ATM_PH_VPI(aph) = npcb->npcb_vpi;
  265       ATM_PH_SETVCI(aph, npcb->npcb_vci);
  266       ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
  267 
  268       error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
  269 
  270       break;
  271 
  272     case PRU_SENSE:                     /* return status into m */
  273       /* return zero? */
  274       break;
  275 
  276     case PRU_PEERADDR:                  /* fetch peer's address */
  277       snatm = mtod(nam, struct sockaddr_natm *);
  278       bzero(snatm, sizeof(*snatm));
  279       nam->m_len = snatm->snatm_len = sizeof(*snatm);
  280       snatm->snatm_family = AF_NATM;
  281 #if defined(__NetBSD__) || defined(__OpenBSD__)
  282       bcopy(npcb->npcb_ifp->if_xname, snatm->snatm_if, sizeof(snatm->snatm_if));
  283 #elif defined(__FreeBSD__)
  284       snprintf(snatm->snatm_if, sizeof(snatm->snatm_if), "%s%d",
  285           npcb->npcb_ifp->if_name, npcb->npcb_ifp->if_unit);
  286 #endif
  287       snatm->snatm_vci = npcb->npcb_vci;
  288       snatm->snatm_vpi = npcb->npcb_vpi;
  289       break;
  290 
  291     case PRU_CONTROL:                   /* control operations on protocol */
  292       /*
  293        * raw atm ioctl.   comes in as a SIOCRAWATM.   we convert it to
  294        * SIOCXRAWATM and pass it to the driver.
  295        */
  296       if ((u_long)m == SIOCRAWATM) {
  297         if (npcb->npcb_ifp == NULL) {
  298           error = ENOTCONN;
  299           break;
  300         }
  301         ario.npcb = npcb;
  302         ario.rawvalue = *((int *)nam);
  303         error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp, SIOCXRAWATM, &ario);
  304         if (!error) {
  305           if (ario.rawvalue)
  306             npcb->npcb_flags |= NPCB_RAW;
  307           else
  308             npcb->npcb_flags &= ~(NPCB_RAW);
  309         }
  310 
  311         break;
  312       }
  313 
  314       error = EOPNOTSUPP;
  315       break;
  316 
  317     case PRU_BIND:                      /* bind socket to address */
  318     case PRU_LISTEN:                    /* listen for connection */
  319     case PRU_ACCEPT:                    /* accept connection from peer */
  320     case PRU_CONNECT2:                  /* connect two sockets */
  321     case PRU_ABORT:                     /* abort (fast DISCONNECT, DETATCH) */
  322                                         /* (only happens if LISTEN socket) */
  323     case PRU_RCVD:                      /* have taken data; more room now */
  324     case PRU_FASTTIMO:                  /* 200ms timeout */
  325     case PRU_SLOWTIMO:                  /* 500ms timeout */
  326     case PRU_RCVOOB:                    /* retrieve out of band data */
  327     case PRU_SENDOOB:                   /* send out of band data */
  328     case PRU_PROTORCV:                  /* receive from below */
  329     case PRU_PROTOSEND:                 /* send to below */
  330     case PRU_SOCKADDR:                  /* fetch socket's address */
  331 #ifdef DIAGNOSTIC
  332       printf("natm: PRU #%d unsupported\n", req);
  333 #endif
  334       error = EOPNOTSUPP;
  335       break;
  336 
  337     default: panic("natm usrreq");
  338   }
  339 
  340 done:
  341   splx(s);
  342   return(error);
  343 }
  344 
  345 /*
  346  * natmintr: splsoftnet interrupt
  347  *
  348  * note: we expect a socket pointer in rcvif rather than an interface
  349  * pointer.    we can get the interface pointer from the so's PCB if
  350  * we really need it.
  351  */
  352 
  353 void
  354 natmintr()
  355 
  356 {
  357   int s;
  358   struct mbuf *m;
  359   struct socket *so;
  360   struct natmpcb *npcb;
  361 
  362   mutex_enter(softnet_lock);
  363 next:
  364   s = splnet();
  365   IF_DEQUEUE(&natmintrq, m);
  366   splx(s);
  367   if (m == NULL) {
  368     mutex_exit(softnet_lock);
  369     return;
  370   }
  371 
  372 #ifdef DIAGNOSTIC
  373   if ((m->m_flags & M_PKTHDR) == 0)
  374     panic("natmintr no HDR");
  375 #endif
  376 
  377   npcb = (struct natmpcb *) m->m_pkthdr.rcvif; /* XXX: overloaded */
  378   so = npcb->npcb_socket;
  379 
  380   s = splnet();                 /* could have atm devs @ different levels */
  381   npcb->npcb_inq--;
  382   splx(s);
  383 
  384   if (npcb->npcb_flags & NPCB_DRAIN) {
  385     m_freem(m);
  386     if (npcb->npcb_inq == 0)
  387       FREE(npcb, M_PCB);                        /* done! */
  388     goto next;
  389   }
  390 
  391   if (npcb->npcb_flags & NPCB_FREE) {
  392     m_freem(m);                                 /* drop */
  393     goto next;
  394   }
  395 
  396 #ifdef NEED_TO_RESTORE_IFP
  397   m->m_pkthdr.rcvif = npcb->npcb_ifp;
  398 #else
  399 #ifdef DIAGNOSTIC
  400 m->m_pkthdr.rcvif = NULL;       /* null it out to be safe */
  401 #endif
  402 #endif
  403 
  404   if (sbspace(&so->so_rcv) > m->m_pkthdr.len ||
  405      ((npcb->npcb_flags & NPCB_RAW) != 0 && so->so_rcv.sb_cc < NPCB_RAWCC) ) {
  406 #ifdef NATM_STAT
  407     natm_sookcnt++;
  408     natm_sookbytes += m->m_pkthdr.len;
  409 #endif
  410     sbappendrecord(&so->so_rcv, m);
  411     sorwakeup(so);
  412   } else {
  413 #ifdef NATM_STAT
  414     natm_sodropcnt++;
  415     natm_sodropbytes += m->m_pkthdr.len;
  416 #endif
  417     m_freem(m);
  418   }
  419 
  420   goto next;
  421 }
  422 
  423 #if defined(__FreeBSD__)
  424 NETISR_SET(NETISR_NATM, natmintr);
  425 #endif
  426 
  427 
  428 #ifdef notyet
  429 /*
  430  * natm0_sysctl: not used, but here in case we want to add something
  431  * later...
  432  */
  433 
  434 int natm0_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
  435 
  436 int *name;
  437 u_int namelen;
  438 void *oldp;
  439 size_t *oldlenp;
  440 void *newp;
  441 size_t newlen;
  442 
  443 {
  444   /* All sysctl names at this level are terminal. */
  445   if (namelen != 1)
  446     return (ENOTDIR);
  447   return (ENOPROTOOPT);
  448 }
  449 
  450 /*
  451  * natm5_sysctl: not used, but here in case we want to add something
  452  * later...
  453  */
  454 
  455 int natm5_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
  456 
  457 int *name;
  458 u_int namelen;
  459 void *oldp;
  460 size_t *oldlenp;
  461 void *newp;
  462 size_t newlen;
  463 
  464 {
  465   /* All sysctl names at this level are terminal. */
  466   if (namelen != 1)
  467     return (ENOTDIR);
  468   return (ENOPROTOOPT);
  469 }
  470 #endif

Cache object: 9264c5db90450dbe774112991c6f1f83


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.