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

Cache object: 8fbad28ad5ac4cf98f31795f3847d66e


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