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

Cache object: 2fcd97ecc0a1bfd4caa4e69ebd66f976


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