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

Cache object: a11e067f22b697bf3e1561f22e8ca97a


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