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.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: releng/5.3/sys/netnatm/natm.c 136738 2004-10-21 09:30:48Z rwatson $");
   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 #include <sys/sysctl.h>
   55 
   56 #include <net/if.h>
   57 #include <net/if_atm.h>
   58 #include <net/netisr.h>
   59 
   60 #include <netinet/in.h>
   61 
   62 #include <netnatm/natm.h>
   63 
   64 static const u_long natm5_sendspace = 16*1024;
   65 static const u_long natm5_recvspace = 16*1024;
   66 
   67 static const u_long natm0_sendspace = 16*1024;
   68 static const u_long natm0_recvspace = 16*1024;
   69 
   70 /*
   71  * user requests
   72  */
   73 #ifdef FREEBSD_USRREQS
   74 /*
   75  * FreeBSD new usrreqs supersedes pr_usrreq.
   76  */
   77 static int natm_usr_attach(struct socket *, int, d_thread_t *);
   78 static int natm_usr_detach(struct socket *);
   79 static int natm_usr_connect(struct socket *, struct sockaddr *, d_thread_t *);
   80 static int natm_usr_disconnect(struct socket *);
   81 static int natm_usr_shutdown(struct socket *);
   82 static int natm_usr_send(struct socket *, int, struct mbuf *,
   83     struct sockaddr *, struct mbuf *, d_thread_t *);
   84 static int natm_usr_peeraddr(struct socket *, struct sockaddr **);
   85 static int natm_usr_control(struct socket *, u_long, caddr_t,
   86     struct ifnet *, d_thread_t *);
   87 static int natm_usr_abort(struct socket *);
   88 static int natm_usr_bind(struct socket *, struct sockaddr *, d_thread_t *);
   89 static int natm_usr_sockaddr(struct socket *, struct sockaddr **);
   90 
   91 static int
   92 natm_usr_attach(struct socket *so, int proto, d_thread_t *p)
   93 {
   94     struct natmpcb *npcb;
   95     int error = 0;
   96     int s = SPLSOFTNET();
   97 
   98     npcb = (struct natmpcb *)so->so_pcb;
   99 
  100     if (npcb) {
  101         error = EISCONN;
  102         goto out;
  103     }
  104 
  105     if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
  106         if (proto == PROTO_NATMAAL5) 
  107             error = soreserve(so, natm5_sendspace, natm5_recvspace);
  108         else
  109             error = soreserve(so, natm0_sendspace, natm0_recvspace);
  110         if (error)
  111           goto out;
  112     }
  113 
  114     so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK));
  115     npcb->npcb_socket = so;
  116  out:
  117     splx(s);
  118     return (error);
  119 }
  120 
  121 static int
  122 natm_usr_detach(struct socket *so)
  123 {
  124     struct natmpcb *npcb;
  125     int error = 0;
  126     int s = SPLSOFTNET();
  127 
  128     npcb = (struct natmpcb *)so->so_pcb;
  129     if (npcb == NULL) {
  130         error = EINVAL;
  131         goto out;
  132     }
  133 
  134     /*
  135      * we turn on 'drain' *before* we sofree.
  136      */
  137     npcb_free(npcb, NPCB_DESTROY);      /* drain */
  138     ACCEPT_LOCK();
  139     SOCK_LOCK(so);
  140     so->so_pcb = NULL;
  141     sotryfree(so);
  142  out:
  143     splx(s);
  144     return (error);
  145 }
  146 
  147 static int
  148 natm_usr_connect(struct socket *so, struct sockaddr *nam, d_thread_t *p)
  149 {
  150     struct natmpcb *npcb;
  151     struct sockaddr_natm *snatm;
  152     struct atmio_openvcc op;
  153     struct ifnet *ifp;
  154     int error = 0;
  155     int s2, s = SPLSOFTNET();
  156     int proto = so->so_proto->pr_protocol;
  157 
  158     npcb = (struct natmpcb *)so->so_pcb;
  159     if (npcb == NULL) {
  160         error = EINVAL;
  161         goto out;
  162     }
  163 
  164     /*
  165      * validate nam and npcb
  166      */
  167     snatm = (struct sockaddr_natm *)nam;
  168     if (snatm->snatm_len != sizeof(*snatm) ||
  169         (npcb->npcb_flags & NPCB_FREE) == 0) {
  170         error = EINVAL;
  171         goto out;
  172     }
  173     if (snatm->snatm_family != AF_NATM) {
  174         error = EAFNOSUPPORT;
  175         goto out;
  176     }
  177 
  178     snatm->snatm_if[IFNAMSIZ - 1] = '\0';       /* XXX ensure null termination
  179                                                    since ifunit() uses strcmp */
  180 
  181     /*
  182      * convert interface string to ifp, validate.
  183      */
  184     ifp = ifunit(snatm->snatm_if);
  185     if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) {
  186         error = ENXIO;
  187         goto out;
  188     }
  189     if (ifp->if_output != atm_output) {
  190         error = EAFNOSUPPORT;
  191         goto out;
  192     }
  193 
  194     /*
  195      * register us with the NATM PCB layer
  196      */
  197     if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) {
  198         error = EADDRINUSE;
  199         goto out;
  200     }
  201 
  202     /*
  203      * open the channel
  204      */
  205     bzero(&op, sizeof(op));
  206     op.rxhand = npcb;
  207     op.param.flags = ATMIO_FLAG_PVC;
  208     op.param.vpi = npcb->npcb_vpi;
  209     op.param.vci = npcb->npcb_vci;
  210     op.param.rmtu = op.param.tmtu = ifp->if_mtu;
  211     op.param.aal = (proto == PROTO_NATMAAL5) ? ATMIO_AAL_5 : ATMIO_AAL_0;
  212     op.param.traffic = ATMIO_TRAFFIC_UBR;
  213 
  214     s2 = splimp();
  215     if (ifp->if_ioctl == NULL || 
  216         ifp->if_ioctl(ifp, SIOCATMOPENVCC, (caddr_t)&op) != 0) {
  217         splx(s2);
  218         npcb_free(npcb, NPCB_REMOVE);
  219         error = EIO;
  220         goto out;
  221     }
  222     splx(s2);
  223 
  224     soisconnected(so);
  225 
  226  out:
  227     splx(s);
  228     return (error);
  229 }
  230 
  231 static int
  232 natm_usr_disconnect(struct socket *so)
  233 {
  234     struct natmpcb *npcb;
  235     struct atmio_closevcc cl;
  236     struct ifnet *ifp;
  237     int error = 0;
  238     int s2, s = SPLSOFTNET();
  239 
  240     npcb = (struct natmpcb *)so->so_pcb;
  241     if (npcb == NULL) {
  242         error = EINVAL;
  243         goto out;
  244     }
  245 
  246     if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
  247         printf("natm: disconnected check\n");
  248         error = EIO;
  249         goto out;
  250     }
  251     ifp = npcb->npcb_ifp;
  252 
  253     /*
  254      * disable rx
  255      */
  256     cl.vpi = npcb->npcb_vpi;
  257     cl.vci = npcb->npcb_vci;
  258     s2 = splimp();
  259     if (ifp->if_ioctl != NULL)
  260         ifp->if_ioctl(ifp, SIOCATMCLOSEVCC, (caddr_t)&cl);
  261     splx(s2);
  262 
  263     npcb_free(npcb, NPCB_REMOVE);
  264     soisdisconnected(so);
  265 
  266  out:
  267     splx(s);
  268     return (error);
  269 }
  270 
  271 static int
  272 natm_usr_shutdown(struct socket *so)
  273 {
  274     socantsendmore(so);
  275     return (0);
  276 }
  277 
  278 static int
  279 natm_usr_send(struct socket *so, int flags, struct mbuf *m, 
  280     struct sockaddr *nam, struct mbuf *control, d_thread_t *p)
  281 {
  282     struct natmpcb *npcb;
  283     struct atm_pseudohdr *aph;
  284     int error = 0;
  285     int s = SPLSOFTNET();
  286     int proto = so->so_proto->pr_protocol;
  287 
  288     npcb = (struct natmpcb *)so->so_pcb;
  289     if (npcb == NULL) {
  290         error = EINVAL;
  291         goto out;
  292     }
  293 
  294     if (control && control->m_len) {
  295         m_freem(control);
  296         m_freem(m);
  297         error = EINVAL;
  298         goto out;
  299     }
  300 
  301     /*
  302      * send the data.   we must put an atm_pseudohdr on first
  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 
  321 static int
  322 natm_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     strlcpy(snatm->snatm_if, npcb->npcb_ifp->if_xname,
  340         sizeof(snatm->snatm_if));
  341     snatm->snatm_vci = npcb->npcb_vci;
  342     snatm->snatm_vpi = npcb->npcb_vpi;
  343     *nam = sodupsockaddr((struct sockaddr *)snatm, M_NOWAIT);
  344 
  345  out:
  346     splx(s);
  347     return (error);
  348 }
  349 
  350 static int
  351 natm_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     int error = 0;
  356     int s = SPLSOFTNET();
  357 
  358     npcb = (struct natmpcb *)so->so_pcb;
  359     if (npcb == NULL) {
  360         error = EINVAL;
  361         goto out;
  362     }
  363 
  364     splx(s);
  365     if (ifp == NULL || ifp->if_ioctl == NULL) {
  366         error = EOPNOTSUPP;
  367         goto out;
  368     }
  369     return ((*ifp->if_ioctl)(ifp, cmd, arg));
  370 
  371  out:
  372     splx(s);
  373     return (error);
  374 }
  375 
  376 static int
  377 natm_usr_abort(struct socket *so)
  378 {
  379     return (natm_usr_shutdown(so));
  380 }
  381 
  382 static int
  383 natm_usr_bind(struct socket *so, struct sockaddr *nam, d_thread_t *p)
  384 {
  385     return (EOPNOTSUPP);
  386 }
  387 
  388 static int
  389 natm_usr_sockaddr(struct socket *so, struct sockaddr **nam)
  390 {
  391     return (EOPNOTSUPP);
  392 }
  393 
  394 /* xxx - should be const */
  395 struct pr_usrreqs natm_usrreqs = {
  396         natm_usr_abort, pru_accept_notsupp, natm_usr_attach, natm_usr_bind,
  397         natm_usr_connect, pru_connect2_notsupp, natm_usr_control,
  398         natm_usr_detach, natm_usr_disconnect, pru_listen_notsupp,
  399         natm_usr_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp,
  400         natm_usr_send, pru_sense_null, natm_usr_shutdown,
  401         natm_usr_sockaddr, sosend, soreceive, sopoll, pru_sosetlabel_null
  402 };
  403 
  404 #else  /* !FREEBSD_USRREQS */
  405 
  406 #if defined(__NetBSD__) || defined(__OpenBSD__)
  407 int natm_usrreq(so, req, m, nam, control, p)
  408 #elif defined(__FreeBSD__)
  409 int natm_usrreq(so, req, m, nam, control)
  410 #endif
  411 
  412 struct socket *so;
  413 int req;
  414 struct mbuf *m, *nam, *control;
  415 #if defined(__NetBSD__) || defined(__OpenBSD__)
  416 struct proc *p;
  417 #endif
  418 
  419 {
  420   int error = 0, s, s2;
  421   struct natmpcb *npcb;
  422   struct sockaddr_natm *snatm;
  423   struct atm_pseudoioctl api;
  424   struct atm_pseudohdr *aph;
  425   struct atm_rawioctl ario;
  426   struct ifnet *ifp;
  427   int proto = so->so_proto->pr_protocol;
  428 
  429   s = SPLSOFTNET();
  430 
  431   npcb = (struct natmpcb *) so->so_pcb;
  432 
  433   if (npcb == NULL && req != PRU_ATTACH) {
  434     error = EINVAL;
  435     goto done;
  436   }
  437     
  438 
  439   switch (req) {
  440     case PRU_ATTACH:                    /* attach protocol to up */
  441 
  442       if (npcb) {
  443         error = EISCONN;
  444         break;
  445       }
  446 
  447       if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
  448         if (proto == PROTO_NATMAAL5) 
  449           error = soreserve(so, natm5_sendspace, natm5_recvspace);
  450         else
  451           error = soreserve(so, natm0_sendspace, natm0_recvspace);
  452         if (error)
  453           break;
  454       }
  455 
  456       so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK));
  457       npcb->npcb_socket = so;
  458 
  459       break;
  460 
  461     case PRU_DETACH:                    /* detach protocol from up */
  462 
  463       /*
  464        * we turn on 'drain' *before* we sofree.
  465        */
  466 
  467       npcb_free(npcb, NPCB_DESTROY);    /* drain */
  468       ACCEPT_LOCK();
  469       SOCK_LOCK(so);
  470       so->so_pcb = NULL;
  471       sotryfree(so);
  472 
  473       break;
  474 
  475     case PRU_CONNECT:                   /* establish connection to peer */
  476 
  477       /*
  478        * validate nam and npcb
  479        */
  480 
  481       if (nam->m_len != sizeof(*snatm)) {
  482         error = EINVAL;
  483         break;
  484       }
  485       snatm = mtod(nam, struct sockaddr_natm *);
  486       if (snatm->snatm_len != sizeof(*snatm) ||
  487                 (npcb->npcb_flags & NPCB_FREE) == 0) {
  488         error = EINVAL;
  489         break;
  490       }
  491       if (snatm->snatm_family != AF_NATM) {
  492         error = EAFNOSUPPORT;
  493         break;
  494       }
  495 
  496       snatm->snatm_if[IFNAMSIZ-1] = '\0';  /* XXX ensure null termination
  497                                                 since ifunit() uses strcmp */
  498 
  499       /*
  500        * convert interface string to ifp, validate.
  501        */
  502 
  503       ifp = ifunit(snatm->snatm_if);
  504       if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) {
  505         error = ENXIO;
  506         break;
  507       }
  508       if (ifp->if_output != atm_output) {
  509         error = EAFNOSUPPORT;
  510         break;
  511       }
  512 
  513 
  514       /*
  515        * register us with the NATM PCB layer
  516        */
  517 
  518       if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) {
  519         error = EADDRINUSE;
  520         break;
  521       }
  522 
  523       /*
  524        * enable rx
  525        */
  526 
  527       ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
  528       ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
  529       ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
  530       api.rxhand = npcb;
  531       s2 = splimp();
  532       if (ifp->if_ioctl == NULL || 
  533           ifp->if_ioctl(ifp, SIOCATMENA, (caddr_t) &api) != 0) {
  534         splx(s2);
  535         npcb_free(npcb, NPCB_REMOVE);
  536         error = EIO;
  537         break;
  538       }
  539       splx(s2);
  540 
  541       soisconnected(so);
  542 
  543       break;
  544 
  545     case PRU_DISCONNECT:                /* disconnect from peer */
  546 
  547       if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
  548         printf("natm: disconnected check\n");
  549         error = EIO;
  550         break;
  551       }
  552       ifp = npcb->npcb_ifp;
  553 
  554       /*
  555        * disable rx
  556        */
  557 
  558       ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5;
  559       ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
  560       ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
  561       api.rxhand = npcb;
  562       s2 = splimp();
  563       if (ifp->if_ioctl != NULL)
  564           ifp->if_ioctl(ifp, SIOCATMDIS, (caddr_t) &api);
  565       splx(s2);
  566 
  567       npcb_free(npcb, NPCB_REMOVE);
  568       soisdisconnected(so);
  569 
  570       break;
  571 
  572     case PRU_SHUTDOWN:                  /* won't send any more data */
  573       socantsendmore(so);
  574       break;
  575 
  576     case PRU_SEND:                      /* send this data */
  577       if (control && control->m_len) {
  578         m_freem(control);
  579         m_freem(m);
  580         error = EINVAL;
  581         break;
  582       }
  583 
  584       /*
  585        * send the data.   we must put an atm_pseudohdr on first
  586        */
  587 
  588       M_PREPEND(m, sizeof(*aph), M_TRYWAIT);
  589       if (m == NULL) {
  590         error = ENOBUFS;
  591         break;
  592       }
  593       aph = mtod(m, struct atm_pseudohdr *);
  594       ATM_PH_VPI(aph) = npcb->npcb_vpi;
  595       ATM_PH_SETVCI(aph, npcb->npcb_vci);
  596       ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
  597 
  598       error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
  599 
  600       break;
  601 
  602     case PRU_SENSE:                     /* return status into m */
  603       /* return zero? */
  604       break;
  605 
  606     case PRU_PEERADDR:                  /* fetch peer's address */
  607       snatm = mtod(nam, struct sockaddr_natm *);
  608       bzero(snatm, sizeof(*snatm));
  609       nam->m_len = snatm->snatm_len = sizeof(*snatm);
  610       snatm->snatm_family = AF_NATM;
  611 #if defined(__NetBSD__) || defined(__OpenBSD__)
  612       bcopy(npcb->npcb_ifp->if_xname, snatm->snatm_if, sizeof(snatm->snatm_if));
  613 #elif defined(__FreeBSD__)
  614       snprintf(snatm->snatm_if, sizeof(snatm->snatm_if),
  615         "%s%d", npcb->npcb_ifp->if_name, npcb->npcb_ifp->if_unit);
  616 #endif
  617       snatm->snatm_vci = npcb->npcb_vci;
  618       snatm->snatm_vpi = npcb->npcb_vpi;
  619       break;
  620 
  621     case PRU_CONTROL:                   /* control operations on protocol */
  622       /*
  623        * raw atm ioctl.   comes in as a SIOCRAWATM.   we convert it to
  624        * SIOCXRAWATM and pass it to the driver.
  625        */
  626       if ((u_long)m == SIOCRAWATM) {
  627         if (npcb->npcb_ifp == NULL) {
  628           error = ENOTCONN;
  629           break;
  630         }
  631         ario.npcb = npcb;
  632         ario.rawvalue = *((int *)nam);
  633         error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp, 
  634                                 SIOCXRAWATM, (caddr_t) &ario);
  635         if (!error) {
  636           if (ario.rawvalue) 
  637             npcb->npcb_flags |= NPCB_RAW;
  638           else
  639             npcb->npcb_flags &= ~(NPCB_RAW);
  640         }
  641 
  642         break;
  643       }
  644 
  645       error = EOPNOTSUPP;
  646       break;
  647 
  648     case PRU_BIND:                      /* bind socket to address */
  649     case PRU_LISTEN:                    /* listen for connection */
  650     case PRU_ACCEPT:                    /* accept connection from peer */
  651     case PRU_CONNECT2:                  /* connect two sockets */
  652     case PRU_ABORT:                     /* abort (fast DISCONNECT, DETATCH) */
  653                                         /* (only happens if LISTEN socket) */
  654     case PRU_RCVD:                      /* have taken data; more room now */
  655     case PRU_FASTTIMO:                  /* 200ms timeout */
  656     case PRU_SLOWTIMO:                  /* 500ms timeout */
  657     case PRU_RCVOOB:                    /* retrieve out of band data */
  658     case PRU_SENDOOB:                   /* send out of band data */
  659     case PRU_PROTORCV:                  /* receive from below */
  660     case PRU_PROTOSEND:                 /* send to below */
  661     case PRU_SOCKADDR:                  /* fetch socket's address */
  662 #ifdef DIAGNOSTIC
  663       printf("natm: PRU #%d unsupported\n", req);
  664 #endif
  665       error = EOPNOTSUPP;
  666       break;
  667    
  668     default: panic("natm usrreq");
  669   }
  670 
  671 done:
  672   splx(s);
  673   return(error);
  674 }
  675 
  676 #endif  /* !FREEBSD_USRREQS */
  677 
  678 /*
  679  * natmintr: splsoftnet interrupt
  680  *
  681  * note: we expect a socket pointer in rcvif rather than an interface
  682  * pointer.    we can get the interface pointer from the so's PCB if
  683  * we really need it.
  684  */
  685 void
  686 natmintr(struct mbuf *m)
  687 {
  688         int s;
  689         struct socket *so;
  690         struct natmpcb *npcb;
  691 
  692         GIANT_REQUIRED;
  693 
  694 #ifdef DIAGNOSTIC
  695         M_ASSERTPKTHDR(m);
  696 #endif
  697 
  698         npcb = (struct natmpcb *)m->m_pkthdr.rcvif;     /* XXX: overloaded */
  699         so = npcb->npcb_socket;
  700 
  701         s = splimp();           /* could have atm devs @ different levels */
  702         npcb->npcb_inq--;
  703         splx(s);
  704 
  705         if (npcb->npcb_flags & NPCB_DRAIN) {
  706                 m_freem(m);
  707                 if (npcb->npcb_inq == 0)
  708                         FREE(npcb, M_PCB);                      /* done! */
  709                 return;
  710         }
  711 
  712         if (npcb->npcb_flags & NPCB_FREE) {
  713                 m_freem(m);                                     /* drop */
  714                 return;
  715         }
  716 
  717 #ifdef NEED_TO_RESTORE_IFP
  718         m->m_pkthdr.rcvif = npcb->npcb_ifp;
  719 #else
  720 #ifdef DIAGNOSTIC
  721         m->m_pkthdr.rcvif = NULL;       /* null it out to be safe */
  722 #endif
  723 #endif
  724 
  725         if (sbspace(&so->so_rcv) > m->m_pkthdr.len) {
  726 #ifdef NATM_STAT
  727                 natm_sookcnt++;
  728                 natm_sookbytes += m->m_pkthdr.len;
  729 #endif
  730                 sbappendrecord(&so->so_rcv, m);
  731                 sorwakeup(so);
  732         } else {
  733 #ifdef NATM_STAT
  734                 natm_sodropcnt++;
  735                 natm_sodropbytes += m->m_pkthdr.len;
  736 #endif
  737                 m_freem(m);
  738         }
  739 }
  740 
  741 /* 
  742  * natm0_sysctl: not used, but here in case we want to add something
  743  * later...
  744  */
  745 int
  746 natm0_sysctl(SYSCTL_HANDLER_ARGS)
  747 {
  748         /* All sysctl names at this level are terminal. */
  749         return (ENOENT);
  750 }
  751 
  752 /* 
  753  * natm5_sysctl: not used, but here in case we want to add something
  754  * later...
  755  */
  756 int
  757 natm5_sysctl(SYSCTL_HANDLER_ARGS)
  758 {
  759         /* All sysctl names at this level are terminal. */
  760         return (ENOENT);
  761 }

Cache object: a4a82137b4e62255aabcd96bf1a13442


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