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/net/if_atmsubr.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: if_atmsubr.c,v 1.32 2003/01/19 23:14:42 simonb 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  * if_atmsubr.c
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: if_atmsubr.c,v 1.32 2003/01/19 23:14:42 simonb Exp $");
   41 
   42 #include "opt_inet.h"
   43 #include "opt_gateway.h"
   44 #include "opt_natm.h"
   45 
   46 #include "bpfilter.h"
   47 
   48 #include <sys/param.h>
   49 #include <sys/systm.h>
   50 #include <sys/kernel.h>
   51 #include <sys/malloc.h>
   52 #include <sys/mbuf.h>
   53 #include <sys/protosw.h>
   54 #include <sys/socket.h>
   55 #include <sys/ioctl.h>
   56 #include <sys/errno.h>
   57 #include <sys/syslog.h>
   58 
   59 #include <machine/cpu.h>
   60 
   61 #include <net/if.h>
   62 #include <net/netisr.h>
   63 #include <net/route.h>
   64 #include <net/if_dl.h>
   65 #include <net/if_types.h>
   66 #include <net/if_atm.h>
   67 #include <net/ethertypes.h> /* XXX: for ETHERTYPE_* */
   68 
   69 #if NBPFILTER > 0
   70 #include <net/bpf.h>
   71 #endif
   72 
   73 #include <netinet/in.h>
   74 #include <netinet/if_atm.h>
   75 
   76 #if defined(INET) || defined(INET6)
   77 #include <netinet/in_var.h>
   78 #endif
   79 #ifdef NATM
   80 #include <netnatm/natm.h>
   81 #endif
   82 
   83 #define senderr(e) { error = (e); goto bad;}
   84 
   85 /*
   86  * atm_output: ATM output routine
   87  *   inputs:
   88  *     "ifp" = ATM interface to output to
   89  *     "m0" = the packet to output
   90  *     "dst" = the sockaddr to send to (either IP addr, or raw VPI/VCI)
   91  *     "rt0" = the route to use
   92  *   returns: error code   [0 == ok]
   93  *
   94  *   note: special semantic: if (dst == NULL) then we assume "m" already
   95  *              has an atm_pseudohdr on it and just send it directly.
   96  *              [for native mode ATM output]   if dst is null, then
   97  *              rt0 must also be NULL.
   98  */
   99 
  100 int
  101 atm_output(ifp, m0, dst, rt0)
  102         struct ifnet *ifp;
  103         struct mbuf *m0;
  104         struct sockaddr *dst;
  105         struct rtentry *rt0;
  106 {
  107         u_int16_t etype = 0;                    /* if using LLC/SNAP */
  108         int s, error = 0, sz, len;
  109         struct atm_pseudohdr atmdst, *ad;
  110         struct mbuf *m = m0;
  111         struct rtentry *rt;
  112         struct atmllc *atmllc;
  113         u_int32_t atm_flags;
  114         ALTQ_DECL(struct altq_pktattr pktattr;)
  115 
  116         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
  117                 senderr(ENETDOWN);
  118 
  119         /*
  120          * If the queueing discipline needs packet classification,
  121          * do it before prepending link headers.
  122          */
  123         IFQ_CLASSIFY(&ifp->if_snd, m,
  124              (dst != NULL ? dst->sa_family : AF_UNSPEC), &pktattr);
  125 
  126         /*
  127          * check route
  128          */
  129         if ((rt = rt0) != NULL) {
  130 
  131                 if ((rt->rt_flags & RTF_UP) == 0) { /* route went down! */
  132                         if ((rt0 = rt = RTALLOC1(dst, 0)) != NULL)
  133                                 rt->rt_refcnt--;
  134                         else 
  135                                 senderr(EHOSTUNREACH);
  136                 }
  137 
  138                 if (rt->rt_flags & RTF_GATEWAY) {
  139                         if (rt->rt_gwroute == 0)
  140                                 goto lookup;
  141                         if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
  142                                 rtfree(rt); rt = rt0;
  143                         lookup: rt->rt_gwroute = RTALLOC1(rt->rt_gateway, 0);
  144                                 if ((rt = rt->rt_gwroute) == 0)
  145                                         senderr(EHOSTUNREACH);
  146                         }
  147                 }
  148 
  149                 /* XXX: put RTF_REJECT code here if doing ATMARP */
  150 
  151         }
  152 
  153         /*
  154          * check for non-native ATM traffic   (dst != NULL)
  155          */
  156         if (dst) {
  157                 switch (dst->sa_family) {
  158 #ifdef INET
  159                 case AF_INET:
  160 #endif
  161 #ifdef INET6
  162                 case AF_INET6:
  163 #endif
  164 #if defined(INET) || defined(INET6)
  165                         if (dst->sa_family == AF_INET)
  166                                 etype = ETHERTYPE_IP;
  167                         else
  168                                 etype = ETHERTYPE_IPV6;
  169 # ifdef ATM_PVCEXT
  170                         if (ifp->if_flags & IFF_POINTOPOINT) {
  171                                 /* pvc subinterface */
  172                                 struct pvcsif *pvcsif = (struct pvcsif *)ifp;
  173                                 atmdst = pvcsif->sif_aph;
  174                                 break;
  175                         }
  176 # endif
  177                         if (!atmresolve(rt, m, dst, &atmdst)) {
  178                                 m = NULL; 
  179                                 /* XXX: atmresolve already free'd it */
  180                                 senderr(EHOSTUNREACH);
  181                                 /* XXX: put ATMARP stuff here */
  182                                 /* XXX: watch who frees m on failure */
  183                         }
  184                         break;
  185 #endif
  186 
  187                 case AF_UNSPEC:
  188                         /*
  189                          * XXX: bpfwrite or output from a pvc shadow if.
  190                          * assuming dst contains 12 bytes (atm pseudo
  191                          * header (4) + LLC/SNAP (8))
  192                          */
  193                         bcopy(dst->sa_data, &atmdst, sizeof(atmdst));
  194                         break;
  195                         
  196                 default:
  197 #if defined(__NetBSD__) || defined(__OpenBSD__)
  198                         printf("%s: can't handle af%d\n", ifp->if_xname, 
  199                             dst->sa_family);
  200 #elif defined(__FreeBSD__) || defined(__bsdi__)
  201                         printf("%s%d: can't handle af%d\n", ifp->if_name, 
  202                             ifp->if_unit, dst->sa_family);
  203 #endif
  204                         senderr(EAFNOSUPPORT);
  205                 }
  206 
  207                 /*
  208                  * must add atm_pseudohdr to data
  209                  */
  210                 sz = sizeof(atmdst);
  211                 atm_flags = ATM_PH_FLAGS(&atmdst);
  212                 if (atm_flags & ATM_PH_LLCSNAP) sz += 8; /* sizeof snap == 8 */
  213                 M_PREPEND(m, sz, M_DONTWAIT);
  214                 if (m == 0)
  215                         senderr(ENOBUFS);
  216                 ad = mtod(m, struct atm_pseudohdr *);
  217                 *ad = atmdst;
  218                 if (atm_flags & ATM_PH_LLCSNAP) {
  219                         atmllc = (struct atmllc *)(ad + 1);
  220                         bcopy(ATMLLC_HDR, atmllc->llchdr, 
  221                                                 sizeof(atmllc->llchdr));
  222                         ATM_LLC_SETTYPE(atmllc, etype); 
  223                 }
  224         }
  225 
  226         /*
  227          * Queue message on interface, and start output if interface
  228          * not yet active.
  229          */
  230 
  231         len = m->m_pkthdr.len;
  232         s = splnet();
  233         IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
  234         if (error) {
  235                 splx(s);
  236                 return (error);
  237         }
  238         ifp->if_obytes += len;
  239         if ((ifp->if_flags & IFF_OACTIVE) == 0)
  240                 (*ifp->if_start)(ifp);
  241         splx(s);
  242         return (error);
  243 
  244 bad:
  245         if (m)
  246                 m_freem(m);
  247         return (error);
  248 }
  249 
  250 /*
  251  * Process a received ATM packet;
  252  * the packet is in the mbuf chain m.
  253  */
  254 void
  255 atm_input(ifp, ah, m, rxhand)
  256         struct ifnet *ifp;
  257         struct atm_pseudohdr *ah;
  258         struct mbuf *m;
  259         void *rxhand;
  260 {
  261         struct ifqueue *inq;
  262         u_int16_t etype = ETHERTYPE_IP; /* default */
  263         int s;
  264 
  265         if ((ifp->if_flags & IFF_UP) == 0) {
  266                 m_freem(m);
  267                 return;
  268         }
  269         ifp->if_ibytes += m->m_pkthdr.len;
  270 
  271         if (rxhand) {
  272 #ifdef NATM
  273           struct natmpcb *npcb = rxhand;
  274           s = splnet();                 /* in case 2 atm cards @ diff lvls */
  275           npcb->npcb_inq++;                     /* count # in queue */
  276           splx(s);
  277           schednetisr(NETISR_NATM);
  278           inq = &natmintrq;
  279           m->m_pkthdr.rcvif = rxhand; /* XXX: overload */
  280 #else
  281           printf("atm_input: NATM detected but not configured in kernel\n");
  282           m_freem(m);
  283           return;
  284 #endif
  285         } else {
  286           /*
  287            * handle LLC/SNAP header, if present
  288            */
  289           if (ATM_PH_FLAGS(ah) & ATM_PH_LLCSNAP) {
  290             struct atmllc *alc;
  291             if (m->m_len < sizeof(*alc) && (m = m_pullup(m, sizeof(*alc))) == 0)
  292                   return; /* failed */
  293             alc = mtod(m, struct atmllc *);
  294             if (bcmp(alc, ATMLLC_HDR, 6)) {
  295 #if defined(__NetBSD__) || defined(__OpenBSD__)
  296               printf("%s: recv'd invalid LLC/SNAP frame [vp=%d,vc=%d]\n",
  297                   ifp->if_xname, ATM_PH_VPI(ah), ATM_PH_VCI(ah));
  298 #elif defined(__FreeBSD__) || defined(__bsdi__)
  299               printf("%s%d: recv'd invalid LLC/SNAP frame [vp=%d,vc=%d]\n",
  300                   ifp->if_name, ifp->if_unit, ATM_PH_VPI(ah), ATM_PH_VCI(ah));
  301 #endif
  302               m_freem(m);
  303               return;
  304             }
  305             etype = ATM_LLC_TYPE(alc);
  306             m_adj(m, sizeof(*alc));
  307           }
  308 
  309           switch (etype) {
  310 #ifdef INET
  311           case ETHERTYPE_IP:
  312 #ifdef GATEWAY
  313                   if (ipflow_fastforward(m))
  314                         return;
  315 #endif
  316                   schednetisr(NETISR_IP);
  317                   inq = &ipintrq;
  318                   break;
  319 #endif /* INET */
  320 #ifdef INET6
  321           case ETHERTYPE_IPV6:
  322                   schednetisr(NETISR_IPV6);
  323                   inq = &ip6intrq;
  324                   break;
  325 #endif
  326           default:
  327               m_freem(m);
  328               return;
  329           }
  330         }
  331 
  332         s = splnet();
  333         if (IF_QFULL(inq)) {
  334                 IF_DROP(inq);
  335                 m_freem(m);
  336         } else
  337                 IF_ENQUEUE(inq, m);
  338         splx(s);
  339 }
  340 
  341 /*
  342  * Perform common duties while attaching to interface list
  343  */
  344 void
  345 atm_ifattach(ifp)
  346         struct ifnet *ifp;
  347 {
  348 
  349         ifp->if_type = IFT_ATM;
  350         ifp->if_addrlen = 0;
  351         ifp->if_hdrlen = 0;
  352         ifp->if_dlt = DLT_ATM_RFC1483;
  353         ifp->if_mtu = ATMMTU;
  354         ifp->if_output = atm_output;
  355 #if 0 /* XXX XXX XXX */
  356         ifp->if_input = atm_input;
  357 #endif
  358 
  359         if_alloc_sadl(ifp);
  360         /* XXX Store LLADDR for ATMARP. */
  361 
  362 #if NBPFILTER > 0
  363         bpfattach(ifp, DLT_ATM_RFC1483, sizeof(struct atmllc));
  364 #endif
  365 }
  366 
  367 #ifdef ATM_PVCEXT
  368 
  369 static int pvc_max_number = 16; /* max number of PVCs */
  370 static int pvc_number = 0;      /* pvc unit number */
  371 
  372 struct ifnet *
  373 pvcsif_alloc()
  374 {
  375         struct pvcsif *pvcsif;
  376 
  377         if (pvc_number >= pvc_max_number)
  378                 return (NULL);
  379         MALLOC(pvcsif, struct pvcsif *, sizeof(struct pvcsif),
  380                M_DEVBUF, M_WAITOK);
  381         if (pvcsif == NULL)
  382                 return (NULL);
  383         memset(pvcsif, 0, sizeof(struct pvcsif));
  384 
  385 #ifdef __NetBSD__
  386         sprintf(pvcsif->sif_if.if_xname, "pvc%d", pvc_number++);
  387 #else
  388         pvcsif->sif_if.if_name = "pvc";
  389         pvcsif->sif_if.if_unit = pvc_number++;
  390 #endif
  391         return (&pvcsif->sif_if);
  392 }
  393 #endif /* ATM_PVCEXT */

Cache object: 899167a7882c165d02e1f1b03fa8c26a


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