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.37 2005/12/11 23:05:24 thorpej 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.37 2005/12/11 23:05:24 thorpej 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(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst,
  102     struct rtentry *rt0)
  103 {
  104         u_int16_t etype = 0;                    /* if using LLC/SNAP */
  105         int error = 0, sz;
  106         struct atm_pseudohdr atmdst, *ad;
  107         struct mbuf *m = m0;
  108         struct rtentry *rt;
  109         struct atmllc *atmllc;
  110         u_int32_t atm_flags;
  111         ALTQ_DECL(struct altq_pktattr pktattr;)
  112 
  113         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
  114                 senderr(ENETDOWN);
  115 
  116         /*
  117          * If the queueing discipline needs packet classification,
  118          * do it before prepending link headers.
  119          */
  120         IFQ_CLASSIFY(&ifp->if_snd, m,
  121              (dst != NULL ? dst->sa_family : AF_UNSPEC), &pktattr);
  122 
  123         /*
  124          * check route
  125          */
  126         if ((rt = rt0) != NULL) {
  127 
  128                 if ((rt->rt_flags & RTF_UP) == 0) { /* route went down! */
  129                         if ((rt0 = rt = RTALLOC1(dst, 0)) != NULL)
  130                                 rt->rt_refcnt--;
  131                         else
  132                                 senderr(EHOSTUNREACH);
  133                 }
  134 
  135                 if (rt->rt_flags & RTF_GATEWAY) {
  136                         if (rt->rt_gwroute == 0)
  137                                 goto lookup;
  138                         if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
  139                                 rtfree(rt); rt = rt0;
  140                         lookup: rt->rt_gwroute = RTALLOC1(rt->rt_gateway, 0);
  141                                 if ((rt = rt->rt_gwroute) == 0)
  142                                         senderr(EHOSTUNREACH);
  143                         }
  144                 }
  145 
  146                 /* XXX: put RTF_REJECT code here if doing ATMARP */
  147 
  148         }
  149 
  150         /*
  151          * check for non-native ATM traffic   (dst != NULL)
  152          */
  153         if (dst) {
  154                 switch (dst->sa_family) {
  155 #ifdef INET
  156                 case AF_INET:
  157 #endif
  158 #ifdef INET6
  159                 case AF_INET6:
  160 #endif
  161 #if defined(INET) || defined(INET6)
  162                         if (dst->sa_family == AF_INET)
  163                                 etype = ETHERTYPE_IP;
  164                         else
  165                                 etype = ETHERTYPE_IPV6;
  166 # ifdef ATM_PVCEXT
  167                         if (ifp->if_flags & IFF_POINTOPOINT) {
  168                                 /* pvc subinterface */
  169                                 struct pvcsif *pvcsif = (struct pvcsif *)ifp;
  170                                 atmdst = pvcsif->sif_aph;
  171                                 break;
  172                         }
  173 # endif
  174                         if (!atmresolve(rt, m, dst, &atmdst)) {
  175                                 m = NULL;
  176                                 /* XXX: atmresolve already free'd it */
  177                                 senderr(EHOSTUNREACH);
  178                                 /* XXX: put ATMARP stuff here */
  179                                 /* XXX: watch who frees m on failure */
  180                         }
  181                         break;
  182 #endif
  183 
  184                 case AF_UNSPEC:
  185                         /*
  186                          * XXX: bpfwrite or output from a pvc shadow if.
  187                          * assuming dst contains 12 bytes (atm pseudo
  188                          * header (4) + LLC/SNAP (8))
  189                          */
  190                         bcopy(dst->sa_data, &atmdst, sizeof(atmdst));
  191                         break;
  192 
  193                 default:
  194 #if defined(__NetBSD__) || defined(__OpenBSD__)
  195                         printf("%s: can't handle af%d\n", ifp->if_xname,
  196                             dst->sa_family);
  197 #elif defined(__FreeBSD__) || defined(__bsdi__)
  198                         printf("%s%d: can't handle af%d\n", ifp->if_name,
  199                             ifp->if_unit, dst->sa_family);
  200 #endif
  201                         senderr(EAFNOSUPPORT);
  202                 }
  203 
  204                 /*
  205                  * must add atm_pseudohdr to data
  206                  */
  207                 sz = sizeof(atmdst);
  208                 atm_flags = ATM_PH_FLAGS(&atmdst);
  209                 if (atm_flags & ATM_PH_LLCSNAP) sz += 8; /* sizeof snap == 8 */
  210                 M_PREPEND(m, sz, M_DONTWAIT);
  211                 if (m == 0)
  212                         senderr(ENOBUFS);
  213                 ad = mtod(m, struct atm_pseudohdr *);
  214                 *ad = atmdst;
  215                 if (atm_flags & ATM_PH_LLCSNAP) {
  216                         atmllc = (struct atmllc *)(ad + 1);
  217                         bcopy(ATMLLC_HDR, atmllc->llchdr,
  218                                                 sizeof(atmllc->llchdr));
  219                         ATM_LLC_SETTYPE(atmllc, etype);
  220                 }
  221         }
  222 
  223         return ifq_enqueue(ifp, m ALTQ_COMMA ALTQ_DECL(&pktattr));
  224 
  225 bad:
  226         if (m)
  227                 m_freem(m);
  228         return (error);
  229 }
  230 
  231 /*
  232  * Process a received ATM packet;
  233  * the packet is in the mbuf chain m.
  234  */
  235 void
  236 atm_input(struct ifnet *ifp, struct atm_pseudohdr *ah, struct mbuf *m,
  237     void *rxhand)
  238 {
  239         struct ifqueue *inq;
  240         u_int16_t etype = ETHERTYPE_IP; /* default */
  241         int s;
  242 
  243         if ((ifp->if_flags & IFF_UP) == 0) {
  244                 m_freem(m);
  245                 return;
  246         }
  247         ifp->if_ibytes += m->m_pkthdr.len;
  248 
  249         if (rxhand) {
  250 #ifdef NATM
  251           struct natmpcb *npcb = rxhand;
  252           s = splnet();                 /* in case 2 atm cards @ diff lvls */
  253           npcb->npcb_inq++;                     /* count # in queue */
  254           splx(s);
  255           schednetisr(NETISR_NATM);
  256           inq = &natmintrq;
  257           m->m_pkthdr.rcvif = rxhand; /* XXX: overload */
  258 #else
  259           printf("atm_input: NATM detected but not configured in kernel\n");
  260           m_freem(m);
  261           return;
  262 #endif
  263         } else {
  264           /*
  265            * handle LLC/SNAP header, if present
  266            */
  267           if (ATM_PH_FLAGS(ah) & ATM_PH_LLCSNAP) {
  268             struct atmllc *alc;
  269             if (m->m_len < sizeof(*alc) && (m = m_pullup(m, sizeof(*alc))) == 0)
  270                   return; /* failed */
  271             alc = mtod(m, struct atmllc *);
  272             if (bcmp(alc, ATMLLC_HDR, 6)) {
  273 #if defined(__NetBSD__) || defined(__OpenBSD__)
  274               printf("%s: recv'd invalid LLC/SNAP frame [vp=%d,vc=%d]\n",
  275                   ifp->if_xname, ATM_PH_VPI(ah), ATM_PH_VCI(ah));
  276 #elif defined(__FreeBSD__) || defined(__bsdi__)
  277               printf("%s%d: recv'd invalid LLC/SNAP frame [vp=%d,vc=%d]\n",
  278                   ifp->if_name, ifp->if_unit, ATM_PH_VPI(ah), ATM_PH_VCI(ah));
  279 #endif
  280               m_freem(m);
  281               return;
  282             }
  283             etype = ATM_LLC_TYPE(alc);
  284             m_adj(m, sizeof(*alc));
  285           }
  286 
  287           switch (etype) {
  288 #ifdef INET
  289           case ETHERTYPE_IP:
  290 #ifdef GATEWAY
  291                   if (ipflow_fastforward(m))
  292                         return;
  293 #endif
  294                   schednetisr(NETISR_IP);
  295                   inq = &ipintrq;
  296                   break;
  297 #endif /* INET */
  298 #ifdef INET6
  299           case ETHERTYPE_IPV6:
  300                   schednetisr(NETISR_IPV6);
  301                   inq = &ip6intrq;
  302                   break;
  303 #endif
  304           default:
  305               m_freem(m);
  306               return;
  307           }
  308         }
  309 
  310         s = splnet();
  311         if (IF_QFULL(inq)) {
  312                 IF_DROP(inq);
  313                 m_freem(m);
  314         } else
  315                 IF_ENQUEUE(inq, m);
  316         splx(s);
  317 }
  318 
  319 /*
  320  * Perform common duties while attaching to interface list
  321  */
  322 void
  323 atm_ifattach(struct ifnet *ifp)
  324 {
  325 
  326         ifp->if_type = IFT_ATM;
  327         ifp->if_addrlen = 0;
  328         ifp->if_hdrlen = 0;
  329         ifp->if_dlt = DLT_ATM_RFC1483;
  330         ifp->if_mtu = ATMMTU;
  331         ifp->if_output = atm_output;
  332 #if 0 /* XXX XXX XXX */
  333         ifp->if_input = atm_input;
  334 #endif
  335 
  336         if_alloc_sadl(ifp);
  337         /* XXX Store LLADDR for ATMARP. */
  338 
  339 #if NBPFILTER > 0
  340         bpfattach(ifp, DLT_ATM_RFC1483, sizeof(struct atmllc));
  341 #endif
  342 }
  343 
  344 #ifdef ATM_PVCEXT
  345 
  346 static int pvc_max_number = 16; /* max number of PVCs */
  347 static int pvc_number = 0;      /* pvc unit number */
  348 
  349 struct ifnet *
  350 pvcsif_alloc(void)
  351 {
  352         struct pvcsif *pvcsif;
  353 
  354         if (pvc_number >= pvc_max_number)
  355                 return (NULL);
  356         MALLOC(pvcsif, struct pvcsif *, sizeof(struct pvcsif),
  357                M_DEVBUF, M_WAITOK);
  358         if (pvcsif == NULL)
  359                 return (NULL);
  360         memset(pvcsif, 0, sizeof(struct pvcsif));
  361 
  362 #ifdef __NetBSD__
  363         snprintf(pvcsif->sif_if.if_xname, sizeof(pvcsif->sif_if.if_xname),
  364             "pvc%d", pvc_number++);
  365 #else
  366         pvcsif->sif_if.if_name = "pvc";
  367         pvcsif->sif_if.if_unit = pvc_number++;
  368 #endif
  369         return (&pvcsif->sif_if);
  370 }
  371 #endif /* ATM_PVCEXT */

Cache object: e1accfae9374ae55d36876fb83364417


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