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

Cache object: 417e9a4e9d070db52f8522b9fc24aa49


[ 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.