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 /* $FreeBSD: releng/5.1/sys/netnatm/natm.c 113255 2003-04-08 14:25:47Z des $ */
    3 
    4 /*
    5  *
    6  * Copyright (c) 1996 Charles D. Cranor and Washington University.
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. All advertising materials mentioning features or use of this software
   18  *    must display the following acknowledgement:
   19  *      This product includes software developed by Charles D. Cranor and
   20  *      Washington University.
   21  * 4. The name of the author may not be used to endorse or promote products
   22  *    derived from this software without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   27  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   29  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   33  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   34  */
   35 
   36 /*
   37  * natm.c: native mode ATM access (both aal0 and aal5).
   38  */
   39 
   40 #include <sys/param.h>
   41 #include <sys/conf.h>
   42 #include <sys/kernel.h>
   43 #include <sys/lock.h>
   44 #include <sys/malloc.h>
   45 #include <sys/mbuf.h>
   46 #include <sys/protosw.h>
   47 #include <sys/signalvar.h>
   48 #include <sys/socket.h>
   49 #include <sys/socketvar.h>
   50 #include <sys/sockio.h>
   51 #include <sys/sx.h>
   52 #include <sys/systm.h>
   53 
   54 #include <net/if.h>
   55 #include <net/if_atm.h>
   56 #include <net/netisr.h>
   57 
   58 #include <netinet/in.h>
   59 
   60 #include <netnatm/natm.h>
   61 
   62 static u_long natm5_sendspace = 16*1024;
   63 static u_long natm5_recvspace = 16*1024;
   64 
   65 static u_long natm0_sendspace = 16*1024;
   66 static u_long natm0_recvspace = 16*1024;
   67 
   68 /*
   69  * user requests
   70  */
   71 #ifdef FREEBSD_USRREQS
   72 /*
   73  * FreeBSD new usrreqs supersedes pr_usrreq.
   74  */
   75 static int natm_usr_attach(struct socket *, int, d_thread_t *);
   76 static int natm_usr_detach(struct socket *);
   77 static int natm_usr_connect(struct socket *, struct sockaddr *, d_thread_t *);
   78 static int natm_usr_disconnect(struct socket *);
   79 static int natm_usr_shutdown(struct socket *);
   80 static int natm_usr_send(struct socket *, int, struct mbuf *,
   81                               struct sockaddr *, struct mbuf *, d_thread_t *);
   82 static int natm_usr_peeraddr(struct socket *, struct sockaddr **);
   83 static int natm_usr_control(struct socket *, u_long, caddr_t,
   84                                  struct ifnet *, d_thread_t *);
   85 static int natm_usr_abort(struct socket *);
   86 static int natm_usr_bind(struct socket *, struct sockaddr *, d_thread_t *);
   87 static int natm_usr_sockaddr(struct socket *, struct sockaddr **);
   88 
   89 static int
   90 natm_usr_attach(struct socket *so, int proto, d_thread_t *p)
   91 {
   92     struct natmpcb *npcb;
   93     int error = 0;
   94     int s = SPLSOFTNET();
   95 
   96     npcb = (struct natmpcb *) so->so_pcb;
   97 
   98     if (npcb) {
   99         error = EISCONN;
  100         goto out;
  101     }
  102 
  103     if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
  104         if (proto == PROTO_NATMAAL5) 
  105             error = soreserve(so, natm5_sendspace, natm5_recvspace);
  106         else
  107             error = soreserve(so, natm0_sendspace, natm0_recvspace);
  108         if (error)
  109           goto out;
  110     }
  111 
  112     so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK));
  113     npcb->npcb_socket = so;
  114  out:
  115     splx(s);
  116     return (error);
  117 }
  118 
  119 static int
  120 natm_usr_detach(struct socket *so)
  121 {
  122     struct natmpcb *npcb;
  123     int error = 0;
  124     int s = SPLSOFTNET();
  125 
  126     npcb = (struct natmpcb *) so->so_pcb;
  127     if (npcb == NULL) {
  128         error = EINVAL;
  129         goto out;
  130     }
  131 
  132     /*
  133      * we turn on 'drain' *before* we sofree.
  134      */
  135     npcb_free(npcb, NPCB_DESTROY);      /* drain */
  136     so->so_pcb = NULL;
  137     sotryfree(so);
  138  out:
  139     splx(s);
  140     return (error);
  141 }
  142 
  143 static int
  144 natm_usr_connect(struct socket *so, struct sockaddr *nam, d_thread_t *p)
  145 {
  146     struct natmpcb *npcb;
  147     struct sockaddr_natm *snatm;
  148     struct atm_pseudoioctl api;
  149     struct ifnet *ifp;
  150     int error = 0;
  151     int s2, s = SPLSOFTNET();
  152     int proto = so->so_proto->pr_protocol;
  153 
  154     npcb = (struct natmpcb *) so->so_pcb;
  155     if (npcb == NULL) {
  156         error = EINVAL;
  157         goto out;
  158     }
  159 
  160     /*
  161      * validate nam and npcb
  162      */
  163 
  164     snatm = (struct sockaddr_natm *)nam;
  165     if (snatm->snatm_len != sizeof(*snatm) ||
  166         (npcb->npcb_flags & NPCB_FREE) == 0) {
  167         error = EINVAL;
  168         goto out;
  169     }
  170     if (snatm->snatm_family != AF_NATM) {
  171         error = EAFNOSUPPORT;
  172         goto out;
  173     }
  174 
  175     snatm->snatm_if[IFNAMSIZ-1] = '\0';  /* XXX ensure null termination
  176                                             since ifunit() uses strcmp */
  177 
  178     /*
  179      * convert interface string to ifp, validate.
  180      */
  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 
  196     if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) {
  197         error = EADDRINUSE;
  198         goto out;
  199     }
  200 
  201     /*
  202      * enable rx
  203      */
  204 
  205     ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
  206     ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
  207     ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
  208     api.rxhand = npcb;
  209     s2 = splimp();
  210     if (ifp->if_ioctl == NULL || 
  211         ifp->if_ioctl(ifp, SIOCATMENA, (caddr_t) &api) != 0) {
  212         splx(s2);
  213         npcb_free(npcb, NPCB_REMOVE);
  214         error = EIO;
  215         goto out;
  216     }
  217     splx(s2);
  218 
  219     soisconnected(so);
  220 
  221  out:
  222     splx(s);
  223     return (error);
  224 }
  225 
  226 static int
  227 natm_usr_disconnect(struct socket *so)
  228 {
  229     struct natmpcb *npcb;
  230     struct atm_pseudoioctl api;
  231     struct ifnet *ifp;
  232     int error = 0;
  233     int s2, s = SPLSOFTNET();
  234 
  235     npcb = (struct natmpcb *) so->so_pcb;
  236     if (npcb == NULL) {
  237         error = EINVAL;
  238         goto out;
  239     }
  240 
  241     if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
  242         printf("natm: disconnected check\n");
  243         error = EIO;
  244         goto out;
  245     }
  246     ifp = npcb->npcb_ifp;
  247 
  248     /*
  249      * disable rx
  250      */
  251 
  252     ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5;
  253     ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
  254     ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
  255     api.rxhand = npcb;
  256     s2 = splimp();
  257     if (ifp->if_ioctl != NULL)
  258         ifp->if_ioctl(ifp, SIOCATMDIS, (caddr_t) &api);
  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 
  303     M_PREPEND(m, sizeof(*aph), M_TRYWAIT);
  304     if (m == NULL) {
  305         error = ENOBUFS;
  306         goto out;
  307     }
  308     aph = mtod(m, struct atm_pseudohdr *);
  309     ATM_PH_VPI(aph) = npcb->npcb_vpi;
  310     ATM_PH_SETVCI(aph, npcb->npcb_vci);
  311     ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
  312 
  313     error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
  314 
  315  out:
  316     splx(s);
  317     return (error);
  318 }
  319 
  320 static int
  321 natm_usr_peeraddr(struct socket *so, struct sockaddr **nam)
  322 {
  323     struct natmpcb *npcb;
  324     struct sockaddr_natm *snatm, ssnatm;
  325     int error = 0;
  326     int s = SPLSOFTNET();
  327 
  328     npcb = (struct natmpcb *) so->so_pcb;
  329     if (npcb == NULL) {
  330         error = EINVAL;
  331         goto out;
  332     }
  333 
  334     snatm = &ssnatm;
  335     bzero(snatm, sizeof(*snatm));
  336     snatm->snatm_len = sizeof(*snatm);
  337     snatm->snatm_family = AF_NATM;
  338     snprintf(snatm->snatm_if, sizeof(snatm->snatm_if),
  339         "%s%d", npcb->npcb_ifp->if_name, npcb->npcb_ifp->if_unit);
  340     snatm->snatm_vci = npcb->npcb_vci;
  341     snatm->snatm_vpi = npcb->npcb_vpi;
  342     *nam = dup_sockaddr((struct sockaddr *)snatm, 0);
  343 
  344  out:
  345     splx(s);
  346     return (error);
  347 }
  348 
  349 static int
  350 natm_usr_control(struct socket *so, u_long cmd, caddr_t arg,
  351                  struct ifnet *ifp, d_thread_t *p)
  352 {
  353     struct natmpcb *npcb;
  354     struct atm_rawioctl ario;
  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     /*
  365      * raw atm ioctl.   comes in as a SIOCRAWATM.   we convert it to
  366      * SIOCXRAWATM and pass it to the driver.
  367      */
  368     if (cmd == SIOCRAWATM) {
  369         if (npcb->npcb_ifp == NULL) {
  370             error = ENOTCONN;
  371             goto out;
  372         }
  373         ario.npcb = npcb;
  374         ario.rawvalue = *((int *)arg);
  375         error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp, 
  376                                          SIOCXRAWATM, (caddr_t) &ario);
  377         if (!error) {
  378             if (ario.rawvalue) 
  379                 npcb->npcb_flags |= NPCB_RAW;
  380             else
  381                 npcb->npcb_flags &= ~(NPCB_RAW);
  382         }
  383     }
  384     else
  385         error = EOPNOTSUPP;
  386 
  387  out:
  388     splx(s);
  389     return (error);
  390 }
  391 
  392 static int
  393 natm_usr_abort(struct socket *so)
  394 {
  395     return natm_usr_shutdown(so);
  396 }
  397 
  398 static int
  399 natm_usr_bind(struct socket *so, struct sockaddr *nam, d_thread_t *p)
  400 {
  401     return EOPNOTSUPP;
  402 }
  403 
  404 static int
  405 natm_usr_sockaddr(struct socket *so, struct sockaddr **nam)
  406 {
  407     return EOPNOTSUPP;
  408 }
  409 
  410 /* xxx - should be const */
  411 struct pr_usrreqs natm_usrreqs = {
  412         natm_usr_abort, pru_accept_notsupp, natm_usr_attach, natm_usr_bind,
  413         natm_usr_connect, pru_connect2_notsupp, natm_usr_control,
  414         natm_usr_detach, natm_usr_disconnect, pru_listen_notsupp,
  415         natm_usr_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp,
  416         natm_usr_send, pru_sense_null, natm_usr_shutdown,
  417         natm_usr_sockaddr, sosend, soreceive, sopoll
  418 };
  419 
  420 #else  /* !FREEBSD_USRREQS */
  421 
  422 #if defined(__NetBSD__) || defined(__OpenBSD__)
  423 int natm_usrreq(so, req, m, nam, control, p)
  424 #elif defined(__FreeBSD__)
  425 int natm_usrreq(so, req, m, nam, control)
  426 #endif
  427 
  428 struct socket *so;
  429 int req;
  430 struct mbuf *m, *nam, *control;
  431 #if defined(__NetBSD__) || defined(__OpenBSD__)
  432 struct proc *p;
  433 #endif
  434 
  435 {
  436   int error = 0, s, s2;
  437   struct natmpcb *npcb;
  438   struct sockaddr_natm *snatm;
  439   struct atm_pseudoioctl api;
  440   struct atm_pseudohdr *aph;
  441   struct atm_rawioctl ario;
  442   struct ifnet *ifp;
  443   int proto = so->so_proto->pr_protocol;
  444 
  445   s = SPLSOFTNET();
  446 
  447   npcb = (struct natmpcb *) so->so_pcb;
  448 
  449   if (npcb == NULL && req != PRU_ATTACH) {
  450     error = EINVAL;
  451     goto done;
  452   }
  453     
  454 
  455   switch (req) {
  456     case PRU_ATTACH:                    /* attach protocol to up */
  457 
  458       if (npcb) {
  459         error = EISCONN;
  460         break;
  461       }
  462 
  463       if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
  464         if (proto == PROTO_NATMAAL5) 
  465           error = soreserve(so, natm5_sendspace, natm5_recvspace);
  466         else
  467           error = soreserve(so, natm0_sendspace, natm0_recvspace);
  468         if (error)
  469           break;
  470       }
  471 
  472       so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK));
  473       npcb->npcb_socket = so;
  474 
  475       break;
  476 
  477     case PRU_DETACH:                    /* detach protocol from up */
  478 
  479       /*
  480        * we turn on 'drain' *before* we sofree.
  481        */
  482 
  483       npcb_free(npcb, NPCB_DESTROY);    /* drain */
  484       so->so_pcb = NULL;
  485       sotryfree(so);
  486 
  487       break;
  488 
  489     case PRU_CONNECT:                   /* establish connection to peer */
  490 
  491       /*
  492        * validate nam and npcb
  493        */
  494 
  495       if (nam->m_len != sizeof(*snatm)) {
  496         error = EINVAL;
  497         break;
  498       }
  499       snatm = mtod(nam, struct sockaddr_natm *);
  500       if (snatm->snatm_len != sizeof(*snatm) ||
  501                 (npcb->npcb_flags & NPCB_FREE) == 0) {
  502         error = EINVAL;
  503         break;
  504       }
  505       if (snatm->snatm_family != AF_NATM) {
  506         error = EAFNOSUPPORT;
  507         break;
  508       }
  509 
  510       snatm->snatm_if[IFNAMSIZ-1] = '\0';  /* XXX ensure null termination
  511                                                 since ifunit() uses strcmp */
  512 
  513       /*
  514        * convert interface string to ifp, validate.
  515        */
  516 
  517       ifp = ifunit(snatm->snatm_if);
  518       if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) {
  519         error = ENXIO;
  520         break;
  521       }
  522       if (ifp->if_output != atm_output) {
  523         error = EAFNOSUPPORT;
  524         break;
  525       }
  526 
  527 
  528       /*
  529        * register us with the NATM PCB layer
  530        */
  531 
  532       if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) {
  533         error = EADDRINUSE;
  534         break;
  535       }
  536 
  537       /*
  538        * enable rx
  539        */
  540 
  541       ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
  542       ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
  543       ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
  544       api.rxhand = npcb;
  545       s2 = splimp();
  546       if (ifp->if_ioctl == NULL || 
  547           ifp->if_ioctl(ifp, SIOCATMENA, (caddr_t) &api) != 0) {
  548         splx(s2);
  549         npcb_free(npcb, NPCB_REMOVE);
  550         error = EIO;
  551         break;
  552       }
  553       splx(s2);
  554 
  555       soisconnected(so);
  556 
  557       break;
  558 
  559     case PRU_DISCONNECT:                /* disconnect from peer */
  560 
  561       if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
  562         printf("natm: disconnected check\n");
  563         error = EIO;
  564         break;
  565       }
  566       ifp = npcb->npcb_ifp;
  567 
  568       /*
  569        * disable rx
  570        */
  571 
  572       ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5;
  573       ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
  574       ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
  575       api.rxhand = npcb;
  576       s2 = splimp();
  577       if (ifp->if_ioctl != NULL)
  578           ifp->if_ioctl(ifp, SIOCATMDIS, (caddr_t) &api);
  579       splx(s2);
  580 
  581       npcb_free(npcb, NPCB_REMOVE);
  582       soisdisconnected(so);
  583 
  584       break;
  585 
  586     case PRU_SHUTDOWN:                  /* won't send any more data */
  587       socantsendmore(so);
  588       break;
  589 
  590     case PRU_SEND:                      /* send this data */
  591       if (control && control->m_len) {
  592         m_freem(control);
  593         m_freem(m);
  594         error = EINVAL;
  595         break;
  596       }
  597 
  598       /*
  599        * send the data.   we must put an atm_pseudohdr on first
  600        */
  601 
  602       M_PREPEND(m, sizeof(*aph), M_TRYWAIT);
  603       if (m == NULL) {
  604         error = ENOBUFS;
  605         break;
  606       }
  607       aph = mtod(m, struct atm_pseudohdr *);
  608       ATM_PH_VPI(aph) = npcb->npcb_vpi;
  609       ATM_PH_SETVCI(aph, npcb->npcb_vci);
  610       ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
  611 
  612       error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
  613 
  614       break;
  615 
  616     case PRU_SENSE:                     /* return status into m */
  617       /* return zero? */
  618       break;
  619 
  620     case PRU_PEERADDR:                  /* fetch peer's address */
  621       snatm = mtod(nam, struct sockaddr_natm *);
  622       bzero(snatm, sizeof(*snatm));
  623       nam->m_len = snatm->snatm_len = sizeof(*snatm);
  624       snatm->snatm_family = AF_NATM;
  625 #if defined(__NetBSD__) || defined(__OpenBSD__)
  626       bcopy(npcb->npcb_ifp->if_xname, snatm->snatm_if, sizeof(snatm->snatm_if));
  627 #elif defined(__FreeBSD__)
  628       snprintf(snatm->snatm_if, sizeof(snatm->snatm_if),
  629         "%s%d", npcb->npcb_ifp->if_name, npcb->npcb_ifp->if_unit);
  630 #endif
  631       snatm->snatm_vci = npcb->npcb_vci;
  632       snatm->snatm_vpi = npcb->npcb_vpi;
  633       break;
  634 
  635     case PRU_CONTROL:                   /* control operations on protocol */
  636       /*
  637        * raw atm ioctl.   comes in as a SIOCRAWATM.   we convert it to
  638        * SIOCXRAWATM and pass it to the driver.
  639        */
  640       if ((u_long)m == SIOCRAWATM) {
  641         if (npcb->npcb_ifp == NULL) {
  642           error = ENOTCONN;
  643           break;
  644         }
  645         ario.npcb = npcb;
  646         ario.rawvalue = *((int *)nam);
  647         error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp, 
  648                                 SIOCXRAWATM, (caddr_t) &ario);
  649         if (!error) {
  650           if (ario.rawvalue) 
  651             npcb->npcb_flags |= NPCB_RAW;
  652           else
  653             npcb->npcb_flags &= ~(NPCB_RAW);
  654         }
  655 
  656         break;
  657       }
  658 
  659       error = EOPNOTSUPP;
  660       break;
  661 
  662     case PRU_BIND:                      /* bind socket to address */
  663     case PRU_LISTEN:                    /* listen for connection */
  664     case PRU_ACCEPT:                    /* accept connection from peer */
  665     case PRU_CONNECT2:                  /* connect two sockets */
  666     case PRU_ABORT:                     /* abort (fast DISCONNECT, DETATCH) */
  667                                         /* (only happens if LISTEN socket) */
  668     case PRU_RCVD:                      /* have taken data; more room now */
  669     case PRU_FASTTIMO:                  /* 200ms timeout */
  670     case PRU_SLOWTIMO:                  /* 500ms timeout */
  671     case PRU_RCVOOB:                    /* retrieve out of band data */
  672     case PRU_SENDOOB:                   /* send out of band data */
  673     case PRU_PROTORCV:                  /* receive from below */
  674     case PRU_PROTOSEND:                 /* send to below */
  675     case PRU_SOCKADDR:                  /* fetch socket's address */
  676 #ifdef DIAGNOSTIC
  677       printf("natm: PRU #%d unsupported\n", req);
  678 #endif
  679       error = EOPNOTSUPP;
  680       break;
  681    
  682     default: panic("natm usrreq");
  683   }
  684 
  685 done:
  686   splx(s);
  687   return(error);
  688 }
  689 
  690 #endif  /* !FREEBSD_USRREQS */
  691 
  692 /*
  693  * natmintr: splsoftnet interrupt
  694  *
  695  * note: we expect a socket pointer in rcvif rather than an interface
  696  * pointer.    we can get the interface pointer from the so's PCB if
  697  * we really need it.
  698  */
  699 
  700 void
  701 natmintr(struct mbuf *m)
  702 {
  703   int s;
  704   struct socket *so;
  705   struct natmpcb *npcb;
  706 
  707 #ifdef DIAGNOSTIC
  708   M_ASSERTPKTHDR(m);
  709 #endif
  710 
  711   npcb = (struct natmpcb *) m->m_pkthdr.rcvif; /* XXX: overloaded */
  712   so = npcb->npcb_socket;
  713 
  714   s = splimp();                 /* could have atm devs @ different levels */
  715   npcb->npcb_inq--;
  716   splx(s);
  717 
  718   if (npcb->npcb_flags & NPCB_DRAIN) {
  719     m_freem(m);
  720     if (npcb->npcb_inq == 0)
  721       FREE(npcb, M_PCB);                        /* done! */
  722     return;
  723   }
  724 
  725   if (npcb->npcb_flags & NPCB_FREE) {
  726     m_freem(m);                                 /* drop */
  727     return;
  728   }
  729 
  730 #ifdef NEED_TO_RESTORE_IFP
  731   m->m_pkthdr.rcvif = npcb->npcb_ifp;
  732 #else
  733 #ifdef DIAGNOSTIC
  734 m->m_pkthdr.rcvif = NULL;       /* null it out to be safe */
  735 #endif
  736 #endif
  737 
  738   if (sbspace(&so->so_rcv) > m->m_pkthdr.len ||
  739      ((npcb->npcb_flags & NPCB_RAW) != 0 && so->so_rcv.sb_cc < NPCB_RAWCC) ) {
  740 #ifdef NATM_STAT
  741     natm_sookcnt++;
  742     natm_sookbytes += m->m_pkthdr.len;
  743 #endif
  744     sbappendrecord(&so->so_rcv, m);
  745     sorwakeup(so);
  746   } else {
  747 #ifdef NATM_STAT
  748     natm_sodropcnt++;
  749     natm_sodropbytes += m->m_pkthdr.len;
  750 #endif
  751     m_freem(m);
  752   }
  753 }
  754 
  755 /* 
  756  * natm0_sysctl: not used, but here in case we want to add something
  757  * later...
  758  */
  759 
  760 int natm0_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
  761 
  762 int *name;
  763 u_int namelen;
  764 void *oldp;
  765 size_t *oldlenp;
  766 void *newp;
  767 size_t newlen;
  768 
  769 {
  770   /* All sysctl names at this level are terminal. */
  771   if (namelen != 1)
  772     return (ENOTDIR);
  773   return (ENOPROTOOPT);
  774 }
  775 
  776 /* 
  777  * natm5_sysctl: not used, but here in case we want to add something
  778  * later...
  779  */
  780 
  781 int natm5_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
  782 
  783 int *name;
  784 u_int namelen;
  785 void *oldp;
  786 size_t *oldlenp;
  787 void *newp;
  788 size_t newlen;
  789 
  790 {
  791   /* All sysctl names at this level are terminal. */
  792   if (namelen != 1)
  793     return (ENOTDIR);
  794   return (ENOPROTOOPT);
  795 }

Cache object: de28fd7869aca1833f5bacace4f6b21c


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