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_fddisubr.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_fddisubr.c,v 1.52 2004/03/22 18:02:12 matt Exp $    */
    2 
    3 /*
    4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    5  * All rights reserved.
    6  * 
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the project nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  * 
   19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * Copyright (c) 1982, 1989, 1993
   34  *      The Regents of the University of California.  All rights reserved.
   35  *
   36  * Redistribution and use in source and binary forms, with or without
   37  * modification, are permitted provided that the following conditions
   38  * are met:
   39  * 1. Redistributions of source code must retain the above copyright
   40  *    notice, this list of conditions and the following disclaimer.
   41  * 2. Redistributions in binary form must reproduce the above copyright
   42  *    notice, this list of conditions and the following disclaimer in the
   43  *    documentation and/or other materials provided with the distribution.
   44  * 3. Neither the name of the University nor the names of its contributors
   45  *    may be used to endorse or promote products derived from this software
   46  *    without specific prior written permission.
   47  *
   48  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   58  * SUCH DAMAGE.
   59  *
   60  *      @(#)if_fddisubr.c       8.1 (Berkeley) 6/10/93
   61  *
   62  * Id: if_fddisubr.c,v 1.15 1997/03/21 22:35:50 thomas Exp
   63  */
   64 
   65 /*
   66  * Copyright (c) 1995, 1996
   67  *      Matt Thomas <matt@3am-software.com>.  All rights reserved.
   68  *
   69  * Redistribution and use in source and binary forms, with or without
   70  * modification, are permitted provided that the following conditions
   71  * are met:
   72  * 1. Redistributions of source code must retain the above copyright
   73  *    notice, this list of conditions and the following disclaimer.
   74  * 2. Redistributions in binary form must reproduce the above copyright
   75  *    notice, this list of conditions and the following disclaimer in the
   76  *    documentation and/or other materials provided with the distribution.
   77  * 3. The name of its contributor may not be used to endorse or promote
   78  *    products derived from this software without specific prior written
   79  *    permission.
   80  *
   81  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   82  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   83  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   84  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   85  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   86  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   87  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   88  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   89  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   90  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   91  * SUCH DAMAGE.
   92  *
   93  *      @(#)if_fddisubr.c       8.1 (Berkeley) 6/10/93
   94  *
   95  * Id: if_fddisubr.c,v 1.15 1997/03/21 22:35:50 thomas Exp
   96  */
   97 
   98 #include <sys/cdefs.h>
   99 __KERNEL_RCSID(0, "$NetBSD: if_fddisubr.c,v 1.52 2004/03/22 18:02:12 matt Exp $");
  100 
  101 #include "opt_inet.h"
  102 #include "opt_atalk.h"
  103 #include "opt_ccitt.h"
  104 #include "opt_llc.h"
  105 #include "opt_iso.h"
  106 #include "opt_ns.h"
  107 #include "opt_ipx.h"
  108 #include "opt_mbuftrace.h"
  109 
  110 #include "bpfilter.h"
  111 
  112 #include <sys/param.h>
  113 #include <sys/systm.h>
  114 #include <sys/kernel.h>
  115 #include <sys/malloc.h>
  116 #include <sys/mbuf.h>
  117 #include <sys/protosw.h>
  118 #include <sys/socket.h>
  119 #include <sys/ioctl.h>
  120 #include <sys/errno.h>
  121 #include <sys/syslog.h>
  122 
  123 #include <machine/cpu.h>
  124 
  125 #include <net/if.h>
  126 #include <net/netisr.h>
  127 #include <net/route.h>
  128 #include <net/if_llc.h>
  129 #include <net/if_dl.h>
  130 #include <net/if_types.h>
  131 
  132 #if NBPFILTER > 0
  133 #include <net/bpf.h>
  134 #endif
  135 
  136 #ifdef INET
  137 #include <netinet/in.h>
  138 #include <netinet/in_var.h>
  139 #include <netinet/if_inarp.h>
  140 #include "opt_gateway.h"
  141 #endif
  142 #include <net/if_fddi.h>
  143 
  144 #ifdef IPX
  145 #include <netipx/ipx.h> 
  146 #include <netipx/ipx_if.h>
  147 #endif
  148 
  149 #ifdef INET6
  150 #ifndef INET
  151 #include <netinet/in.h>
  152 #include <netinet/in_var.h>
  153 #endif
  154 #include <netinet6/nd6.h>
  155 #endif
  156 
  157 #ifdef NS
  158 #include <netns/ns.h>
  159 #include <netns/ns_if.h>
  160 #endif
  161 
  162 #ifdef DECNET
  163 #include <netdnet/dn.h>
  164 #endif
  165 
  166 #ifdef ISO
  167 #include <netiso/argo_debug.h>
  168 #include <netiso/iso.h>
  169 #include <netiso/iso_var.h>
  170 #include <netiso/iso_snpac.h>
  171 #endif
  172 
  173 #ifdef LLC
  174 #include <netccitt/dll.h>
  175 #include <netccitt/llc_var.h>
  176 #endif
  177 
  178 #ifdef NETATALK
  179 #include <netatalk/at.h>
  180 #include <netatalk/at_var.h>
  181 #include <netatalk/at_extern.h>
  182 
  183 #define llc_snap_org_code llc_un.type_snap.org_code
  184 #define llc_snap_ether_type llc_un.type_snap.ether_type
  185 
  186 extern u_char   at_org_code[ 3 ];
  187 extern u_char   aarp_org_code[ 3 ];
  188 #endif /* NETATALK */
  189 
  190 #if defined(LLC) && defined(CCITT)
  191 extern struct ifqueue pkintrq;
  192 #endif
  193 
  194 #include "bpfilter.h"
  195 
  196 #define senderr(e) { error = (e); goto bad;}
  197 
  198 /*
  199  * This really should be defined in if_llc.h but in case it isn't.
  200  */
  201 #ifndef llc_snap
  202 #define llc_snap        llc_un.type_snap
  203 #endif
  204 
  205 #define FDDIADDR(ifp)           LLADDR((ifp)->if_sadl)
  206 
  207 static  int fddi_output __P((struct ifnet *, struct mbuf *,
  208             struct sockaddr *, struct rtentry *)); 
  209 static  void fddi_input __P((struct ifnet *, struct mbuf *));
  210 
  211 /*
  212  * FDDI output routine.
  213  * Encapsulate a packet of type family for the local net.
  214  * Assumes that ifp is actually pointer to ethercom structure.
  215  */
  216 static int
  217 fddi_output(ifp, m0, dst, rt0)
  218         struct ifnet *ifp;
  219         struct mbuf *m0;
  220         struct sockaddr *dst;
  221         struct rtentry *rt0;
  222 {
  223         u_int16_t etype;
  224         int s, len, error = 0, hdrcmplt = 0;
  225         u_char esrc[6], edst[6];
  226         struct mbuf *m = m0;
  227         struct rtentry *rt;
  228         struct fddi_header *fh;
  229         struct mbuf *mcopy = (struct mbuf *)0;
  230         ALTQ_DECL(struct altq_pktattr pktattr;)
  231         short mflags;
  232 
  233         MCLAIM(m, ifp->if_mowner);
  234         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
  235                 senderr(ENETDOWN);
  236 #if !defined(__bsdi__) || _BSDI_VERSION >= 199401
  237         if ((rt = rt0) != NULL) {
  238                 if ((rt->rt_flags & RTF_UP) == 0) {
  239                         if ((rt0 = rt = rtalloc1(dst, 1)) != NULL)
  240                                 rt->rt_refcnt--;
  241                         else 
  242                                 senderr(EHOSTUNREACH);
  243                 }
  244                 if (rt->rt_flags & RTF_GATEWAY) {
  245                         if (rt->rt_gwroute == 0)
  246                                 goto lookup;
  247                         if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
  248                                 rtfree(rt); rt = rt0;
  249                         lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);
  250                                 if ((rt = rt->rt_gwroute) == 0)
  251                                         senderr(EHOSTUNREACH);
  252                         }
  253                 }
  254                 if (rt->rt_flags & RTF_REJECT)
  255                         if (rt->rt_rmx.rmx_expire == 0 ||
  256                             time.tv_sec < rt->rt_rmx.rmx_expire)
  257                                 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
  258         }
  259 #endif
  260 
  261         /*
  262          * If the queueing discipline needs packet classification,
  263          * do it before prepending link headers.
  264          */
  265         IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
  266 
  267         switch (dst->sa_family) {
  268 
  269 #ifdef INET
  270         case AF_INET: {
  271 #define SIN(x) ((struct sockaddr_in *)(x))
  272                 if (m->m_flags & M_BCAST)
  273                         bcopy((caddr_t)fddibroadcastaddr, (caddr_t)edst,
  274                                 sizeof(edst));
  275                 else if (m->m_flags & M_MCAST) {
  276                         ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr,
  277                             (caddr_t)edst)
  278                 } else if (!arpresolve(ifp, rt, m, dst, edst))
  279                         return (0);     /* if not yet resolved */
  280                 /* If broadcasting on a simplex interface, loopback a copy */
  281                 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
  282                         mcopy = m_copy(m, 0, (int)M_COPYALL);
  283                 etype = htons(ETHERTYPE_IP);
  284                 break;
  285         }
  286 #endif
  287 #ifdef INET6
  288         case AF_INET6:
  289                 if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)edst)){
  290                         /* something bad happened */
  291                         return (0);
  292                 }
  293                 etype = htons(ETHERTYPE_IPV6);
  294                 break;
  295 #endif
  296 #ifdef AF_ARP
  297         case AF_ARP: {
  298                 struct arphdr *ah = mtod(m, struct arphdr *);
  299                 if (m->m_flags & M_BCAST)
  300                         bcopy((caddr_t)etherbroadcastaddr, (caddr_t)edst,
  301                                 sizeof(edst));
  302                 else
  303                         bcopy((caddr_t)ar_tha(ah),
  304                                 (caddr_t)edst, sizeof(edst));
  305                 
  306                 ah->ar_hrd = htons(ARPHRD_ETHER);
  307 
  308                 switch (ntohs(ah->ar_op)) {
  309                 case ARPOP_REVREQUEST:
  310                 case ARPOP_REVREPLY:
  311                         etype = htons(ETHERTYPE_REVARP);
  312                         break;
  313 
  314                 case ARPOP_REQUEST:
  315                 case ARPOP_REPLY:
  316                 default:
  317                         etype = htons(ETHERTYPE_ARP);
  318                 }
  319 
  320                 break;
  321         }
  322 #endif /* AF_ARP */
  323 #ifdef IPX
  324         case AF_IPX:
  325                 etype = htons(ETHERTYPE_IPX);
  326                 bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
  327                     (caddr_t)edst, sizeof (edst));
  328                 /* If broadcasting on a simplex interface, loopback a copy */
  329                 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
  330                         mcopy = m_copy(m, 0, (int)M_COPYALL);
  331                 break;
  332 #endif
  333 #ifdef NETATALK
  334         case AF_APPLETALK: {
  335                 struct at_ifaddr *aa;
  336                 if (!aarpresolve(ifp, m, (struct sockaddr_at *)dst, edst)) {
  337 #ifdef NETATALKDEBUG
  338                         printf("aarpresolv: failed\n");
  339 #endif
  340                         return (0);
  341                 }
  342                 /*
  343                  * ifaddr is the first thing in at_ifaddr
  344                  */
  345                 if ((aa = (struct at_ifaddr *)at_ifawithnet(
  346                     (struct sockaddr_at *)dst, ifp)) == NULL)
  347                         goto bad;
  348             
  349                 /*
  350                  * In the phase 2 case, we need to prepend an mbuf for the llc
  351                  * header. Since we must preserve the value of m, which is
  352                  * passed to us by value, we m_copy() the first mbuf, and use
  353                  * it for our llc header.
  354                  */
  355                 if (aa->aa_flags & AFA_PHASE2) {
  356                         struct llc llc;
  357 
  358                         M_PREPEND(m, sizeof(struct llc), M_NOWAIT);
  359                         if (m == 0)
  360                                 senderr(ENOBUFS);
  361                         llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
  362                         llc.llc_control = LLC_UI;
  363                         bcopy(at_org_code, llc.llc_snap_org_code,
  364                             sizeof(at_org_code));
  365                         llc.llc_snap_ether_type = htons(ETHERTYPE_ATALK);
  366                         bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc));
  367                         etype = 0;
  368                 } else {
  369                         etype = htons(ETHERTYPE_ATALK);
  370                 }
  371                 break;
  372         }
  373 #endif /* NETATALK */
  374 #ifdef NS
  375         case AF_NS:
  376                 etype = htons(ETHERTYPE_NS);
  377                 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
  378                     (caddr_t)edst, sizeof (edst));
  379                 if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst)))
  380                         return (looutput(ifp, m, dst, rt));
  381                 /* If broadcasting on a simplex interface, loopback a copy */
  382                 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
  383                         mcopy = m_copy(m, 0, (int)M_COPYALL);
  384                 break;
  385 #endif
  386 #ifdef  ISO
  387         case AF_ISO: {
  388                 int     snpalen;
  389                 struct  llc *l;
  390                 struct sockaddr_dl *sdl;
  391 
  392                 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
  393                     sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
  394                         bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
  395                 } else if ((error =
  396                             iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
  397                                             (char *)edst, &snpalen)) != 0)
  398                         goto bad; /* Not Resolved */
  399                 /* If broadcasting on a simplex interface, loopback a copy */
  400                 if (*edst & 1)
  401                         m->m_flags |= (M_BCAST|M_MCAST);
  402                 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
  403                     (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
  404                         M_PREPEND(mcopy, sizeof (*fh), M_DONTWAIT);
  405                         if (mcopy) {
  406                                 fh = mtod(mcopy, struct fddi_header *);
  407                                 bcopy((caddr_t)edst,
  408                                       (caddr_t)fh->fddi_dhost, sizeof (edst));
  409                                 bcopy((caddr_t)FDDIADDR(ifp),
  410                                       (caddr_t)fh->fddi_shost, sizeof (edst));
  411                         }
  412                 }
  413                 M_PREPEND(m, 3, M_DONTWAIT);
  414                 if (m == NULL)
  415                         return (0);
  416                 etype = 0;
  417                 l = mtod(m, struct llc *);
  418                 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
  419                 l->llc_control = LLC_UI;
  420                 } break;
  421 #endif /* ISO */
  422 #ifdef  LLC
  423 /*      case AF_NSAP: */
  424         case AF_CCITT: {
  425                 struct sockaddr_dl *sdl = 
  426                         (struct sockaddr_dl *) rt->rt_gateway;
  427 
  428                 if (sdl && sdl->sdl_family == AF_LINK
  429                     && sdl->sdl_alen > 0) {
  430                         bcopy(LLADDR(sdl), (char *)edst, sizeof(edst));
  431                 } else goto bad; /* Not a link interface ? Funny ... */
  432 
  433                 if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
  434                     (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
  435                         M_PREPEND(mcopy, sizeof (*fh), M_DONTWAIT);
  436                         if (mcopy) {
  437                                 fh = mtod(mcopy, struct fddi_header *);
  438                                 bcopy((caddr_t)edst,
  439                                       (caddr_t)fh->fddi_dhost, sizeof (edst));
  440                                 bcopy((caddr_t)FDDIADDR(ifp),
  441                                       (caddr_t)fh->fddi_shost, sizeof (edst));
  442                                 fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4;
  443                         }
  444                 }
  445                 etype = 0;
  446 #ifdef LLC_DEBUG
  447                 {
  448                         int i;
  449                         struct llc *l = mtod(m, struct llc *);
  450 
  451                         printf("fddi_output: sending LLC2 pkt to: ");
  452                         for (i=0; i<6; i++)
  453                                 printf("%x ", edst[i] & 0xff);
  454                         printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n", 
  455                                m->m_pkthdr.len, l->llc_dsap & 0xff, l->llc_ssap &0xff,
  456                                l->llc_control & 0xff);
  457 
  458                 }
  459 #endif /* LLC_DEBUG */
  460                 } break;
  461 #endif /* LLC */        
  462 
  463         case pseudo_AF_HDRCMPLT:
  464         {
  465                 struct fddi_header *fh = (struct fddi_header *)dst->sa_data;
  466                 hdrcmplt = 1;
  467                 bcopy((caddr_t)fh->fddi_shost, (caddr_t)esrc, sizeof (esrc));
  468                 /*FALLTHROUGH*/
  469         }
  470 
  471         case AF_LINK:
  472         {
  473                 struct fddi_header *fh = (struct fddi_header *)dst->sa_data;
  474                 bcopy((caddr_t)fh->fddi_dhost, (caddr_t)edst, sizeof (edst));
  475                 if (*edst & 1)
  476                         m->m_flags |= (M_BCAST|M_MCAST);
  477                 etype = 0;
  478                 break;
  479         }
  480 
  481         case AF_UNSPEC:
  482         {
  483                 struct ether_header *eh;
  484                 eh = (struct ether_header *)dst->sa_data;
  485                 bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
  486                 if (*edst & 1)
  487                         m->m_flags |= (M_BCAST|M_MCAST);
  488                 etype = eh->ether_type;
  489                 break;
  490         }
  491 
  492 #if NBPFILTER > 0
  493         case AF_IMPLINK:
  494         {
  495                 fh = mtod(m, struct fddi_header *);
  496                 error = EPROTONOSUPPORT;
  497                 switch (fh->fddi_fc & (FDDIFC_C|FDDIFC_L|FDDIFC_F)) {
  498                         case FDDIFC_LLC_ASYNC: {
  499                                 /* legal priorities are 0 through 7 */
  500                                 if ((fh->fddi_fc & FDDIFC_Z) > 7)
  501                                         goto bad;
  502                                 break;
  503                         }
  504                         case FDDIFC_LLC_SYNC: {
  505                                 /* FDDIFC_Z bits reserved, must be zero */
  506                                 if (fh->fddi_fc & FDDIFC_Z)
  507                                         goto bad;
  508                                 break;
  509                         }
  510                         case FDDIFC_SMT: {
  511                                 /* FDDIFC_Z bits must be non zero */
  512                                 if ((fh->fddi_fc & FDDIFC_Z) == 0)
  513                                         goto bad;
  514                                 break;
  515                         }
  516                         default: {
  517                                 /* anything else is too dangerous */
  518                                 goto bad;
  519                         }
  520                 }
  521                 error = 0;
  522                 if (fh->fddi_dhost[0] & 1)
  523                         m->m_flags |= (M_BCAST|M_MCAST);
  524                 goto queue_it;
  525         }
  526 #endif
  527         default:
  528                 printf("%s: can't handle af%d\n", ifp->if_xname,
  529                        dst->sa_family);
  530                 senderr(EAFNOSUPPORT);
  531         }
  532 
  533 
  534         if (mcopy)
  535                 (void) looutput(ifp, mcopy, dst, rt);
  536         if (etype != 0) {
  537                 struct llc *l;
  538                 M_PREPEND(m, sizeof (struct llc), M_DONTWAIT);
  539                 if (m == 0)
  540                         senderr(ENOBUFS);
  541                 l = mtod(m, struct llc *);
  542                 l->llc_control = LLC_UI;
  543                 l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP;
  544                 l->llc_snap.org_code[0] = l->llc_snap.org_code[1] = l->llc_snap.org_code[2] = 0;
  545                 bcopy((caddr_t) &etype, (caddr_t) &l->llc_snap.ether_type,
  546                         sizeof(u_int16_t));
  547         }
  548         /*
  549          * Add local net header.  If no space in first mbuf,
  550          * allocate another.
  551          */
  552         M_PREPEND(m, sizeof (struct fddi_header), M_DONTWAIT);
  553         if (m == 0)
  554                 senderr(ENOBUFS);
  555         fh = mtod(m, struct fddi_header *);
  556         fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4;
  557         bcopy((caddr_t)edst, (caddr_t)fh->fddi_dhost, sizeof (edst));
  558 #if NBPFILTER > 0
  559   queue_it:
  560 #endif
  561         if (hdrcmplt)
  562                 bcopy((caddr_t)esrc, (caddr_t)fh->fddi_shost,
  563                     sizeof(fh->fddi_shost));
  564         else
  565                 bcopy((caddr_t)FDDIADDR(ifp), (caddr_t)fh->fddi_shost,
  566                     sizeof(fh->fddi_shost));
  567         mflags = m->m_flags;
  568         len = m->m_pkthdr.len;
  569         s = splnet();
  570         /*
  571          * Queue message on interface, and start output if interface
  572          * not yet active.
  573          */
  574         IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
  575         if (error) {
  576                 /* mbuf is already freed */
  577                 splx(s);
  578                 return (error);
  579         }
  580         ifp->if_obytes += len;
  581         if (mflags & M_MCAST)
  582                 ifp->if_omcasts++;
  583         if ((ifp->if_flags & IFF_OACTIVE) == 0)
  584                 (*ifp->if_start)(ifp);
  585         splx(s);
  586         return (error);
  587 
  588 bad:
  589         if (m)
  590                 m_freem(m);
  591         return (error);
  592 }
  593 
  594 /*
  595  * Process a received FDDI packet;
  596  * the packet is in the mbuf chain m with
  597  * the fddi header.
  598  */
  599 static void
  600 fddi_input(ifp, m)
  601         struct ifnet *ifp;
  602         struct mbuf *m;
  603 {
  604         struct ifqueue *inq;
  605         struct llc *l;
  606         struct fddi_header *fh;
  607         int s;
  608 
  609         MCLAIM(m, &((struct ethercom *)ifp)->ec_rx_mowner);
  610         if ((ifp->if_flags & IFF_UP) == 0) {
  611                 m_freem(m);
  612                 return;
  613         }
  614 
  615         fh = mtod(m, struct fddi_header *);
  616 
  617         ifp->if_ibytes += m->m_pkthdr.len;
  618         if (fh->fddi_dhost[0] & 1) {
  619                 if (bcmp((caddr_t)fddibroadcastaddr, (caddr_t)fh->fddi_dhost,
  620                     sizeof(fddibroadcastaddr)) == 0)
  621                         m->m_flags |= M_BCAST;
  622                 else
  623                         m->m_flags |= M_MCAST;
  624                 ifp->if_imcasts++;
  625         } else if ((ifp->if_flags & IFF_PROMISC)
  626             && bcmp(FDDIADDR(ifp), (caddr_t)fh->fddi_dhost,
  627                     sizeof(fh->fddi_dhost)) != 0) {
  628                 m_freem(m);
  629                 return;
  630         }
  631 
  632 #ifdef M_LINK0
  633         /*
  634          * If this has a LLC priority of 0, then mark it so upper
  635          * layers have a hint that it really came via a FDDI/Ethernet
  636          * bridge.
  637          */
  638         if ((fh->fddi_fc & FDDIFC_LLC_PRIO7) == FDDIFC_LLC_PRIO0)
  639                 m->m_flags |= M_LINK0;
  640 #endif
  641 
  642         /* Strip off the FDDI header. */
  643         m_adj(m, sizeof(struct fddi_header));
  644 
  645         l = mtod(m, struct llc *);
  646         switch (l->llc_dsap) {
  647 #if defined(INET) || defined(INET6) || defined(NS) || defined(DECNET) || defined(IPX) || defined(NETATALK)
  648         case LLC_SNAP_LSAP:
  649         {
  650                 u_int16_t etype;
  651                 if (l->llc_control != LLC_UI || l->llc_ssap != LLC_SNAP_LSAP)
  652                         goto dropanyway;
  653 #ifdef NETATALK
  654                 if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code,
  655                          sizeof(at_org_code)) == 0 &&
  656                         ntohs(l->llc_snap_ether_type) == ETHERTYPE_ATALK) {
  657                     inq = &atintrq2;
  658                     m_adj( m, sizeof( struct llc ));
  659                     schednetisr(NETISR_ATALK);
  660                     break;
  661                 }
  662 
  663                 if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code,
  664                          sizeof(aarp_org_code)) == 0 &&
  665                         ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) {
  666                     m_adj( m, sizeof( struct llc ));
  667                     aarpinput(ifp, m); /* XXX */
  668                     return;
  669                 }
  670 #endif /* NETATALK */
  671                 if (l->llc_snap.org_code[0] != 0 || l->llc_snap.org_code[1] != 0|| l->llc_snap.org_code[2] != 0)
  672                         goto dropanyway;
  673                 etype = ntohs(l->llc_snap.ether_type);
  674                 m_adj(m, 8);
  675                 switch (etype) {
  676 #ifdef INET
  677                 case ETHERTYPE_IP:
  678 #ifdef GATEWAY
  679                         if (ipflow_fastforward(m))
  680                                 return;
  681 #endif
  682                         schednetisr(NETISR_IP);
  683                         inq = &ipintrq;
  684                         break;
  685 
  686                 case ETHERTYPE_ARP:
  687 #if !defined(__bsdi__) || _BSDI_VERSION >= 199401
  688                         schednetisr(NETISR_ARP);
  689                         inq = &arpintrq;
  690                         break;
  691 #else
  692                         arpinput(ifp, m);
  693                         return;
  694 #endif
  695 #endif
  696 #ifdef IPX      
  697                 case ETHERTYPE_IPX: 
  698                         schednetisr(NETISR_IPX);
  699                         inq = &ipxintrq;
  700                         break;  
  701 #endif   
  702 #ifdef NS
  703                 case ETHERTYPE_NS:
  704                         schednetisr(NETISR_NS);
  705                         inq = &nsintrq;
  706                         break;
  707 #endif
  708 #ifdef INET6
  709                 case ETHERTYPE_IPV6:
  710                         schednetisr(NETISR_IPV6);
  711                         inq = &ip6intrq;
  712                         break;
  713 
  714 #endif
  715 #ifdef DECNET
  716                 case ETHERTYPE_DECNET:
  717                         schednetisr(NETISR_DECNET);
  718                         inq = &decnetintrq;
  719                         break;
  720 #endif
  721 #ifdef NETATALK 
  722                 case ETHERTYPE_ATALK:
  723                         schednetisr(NETISR_ATALK);
  724                         inq = &atintrq1;
  725                         break;
  726                 case ETHERTYPE_AARP:
  727                         /* probably this should be done with a NETISR as well */
  728                         aarpinput(ifp, m); /* XXX */
  729                         return;
  730 #endif /* NETATALK */
  731                 default:
  732                         ifp->if_noproto++;
  733                         goto dropanyway;
  734                 }
  735                 break;
  736         }
  737 #endif /* INET || NS */
  738 #ifdef  ISO
  739         case LLC_ISO_LSAP: 
  740                 switch (l->llc_control) {
  741                 case LLC_UI:
  742                         /* LLC_UI_P forbidden in class 1 service */
  743                         if ((l->llc_dsap == LLC_ISO_LSAP) &&
  744                             (l->llc_ssap == LLC_ISO_LSAP)) {
  745                                 /* LSAP for ISO */
  746                                 m->m_data += 3;         /* XXX */
  747                                 m->m_len -= 3;          /* XXX */
  748                                 m->m_pkthdr.len -= 3;   /* XXX */
  749                                 M_PREPEND(m, sizeof *fh, M_DONTWAIT);
  750                                 if (m == 0)
  751                                         return;
  752                                 *mtod(m, struct fddi_header *) = *fh;
  753                                 schednetisr(NETISR_ISO);
  754                                 inq = &clnlintrq;
  755                                 break;
  756                         }
  757                         goto dropanyway;
  758                         
  759                 case LLC_XID:
  760                 case LLC_XID_P:
  761                         if(m->m_len < 6)
  762                                 goto dropanyway;
  763                         l->llc_window = 0;
  764                         l->llc_fid = 9;
  765                         l->llc_class = 1;
  766                         l->llc_dsap = l->llc_ssap = 0;
  767                         /* Fall through to */
  768                 case LLC_TEST:
  769                 case LLC_TEST_P:
  770                 {
  771                         struct sockaddr sa;
  772                         struct ether_header *eh;
  773                         int i;
  774                         u_char c = l->llc_dsap;
  775 
  776                         l->llc_dsap = l->llc_ssap;
  777                         l->llc_ssap = c;
  778                         eh = (struct ether_header *)sa.sa_data;
  779                         if (m->m_flags & (M_BCAST | M_MCAST))
  780                                 bcopy((caddr_t)FDDIADDR(ifp),
  781                                       (caddr_t)eh->ether_dhost, 6);
  782                         sa.sa_family = AF_UNSPEC;
  783                         sa.sa_len = sizeof(sa);
  784                         for (i = 0; i < 6; i++) {
  785                                 eh->ether_shost[i] = fh->fddi_dhost[i];
  786                                 eh->ether_dhost[i] = fh->fddi_shost[i];
  787                         }
  788                         eh->ether_type = 0;
  789                         ifp->if_output(ifp, m, &sa, NULL);
  790                         return;
  791                 }
  792                 default:
  793                         m_freem(m);
  794                         return;
  795                 }
  796                 break;
  797 #endif /* ISO */
  798 #ifdef LLC
  799         case LLC_X25_LSAP:
  800         {
  801                 M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
  802                 if (m == 0)
  803                         return;
  804                 if ( !sdl_sethdrif(ifp, fh->fddi_shost, LLC_X25_LSAP,
  805                                     fh->fddi_dhost, LLC_X25_LSAP, 6, 
  806                                     mtod(m, struct sdl_hdr *)))
  807                         panic("ETHER cons addr failure");
  808                 mtod(m, struct sdl_hdr *)->sdlhdr_len = m->m_pkthdr.len - sizeof(struct sdl_hdr);
  809 #ifdef LLC_DEBUG
  810                 printf("llc packet\n");
  811 #endif /* LLC_DEBUG */
  812                 schednetisr(NETISR_CCITT);
  813                 inq = &llcintrq;
  814                 break;
  815         }
  816 #endif /* LLC */
  817                 
  818         default:
  819                 ifp->if_noproto++;
  820         dropanyway:
  821                 m_freem(m);
  822                 return;
  823         }
  824 
  825         s = splnet();
  826         if (IF_QFULL(inq)) {
  827                 IF_DROP(inq);
  828                 m_freem(m);
  829         } else
  830                 IF_ENQUEUE(inq, m);
  831         splx(s);
  832 }
  833 
  834 /*
  835  * Perform common duties while attaching to interface list
  836  */
  837 void
  838 fddi_ifattach(ifp, lla)
  839         struct ifnet *ifp;
  840         caddr_t lla;
  841 {
  842         struct ethercom *ec = (struct ethercom *)ifp;
  843 
  844         ifp->if_type = IFT_FDDI;
  845         ifp->if_addrlen = 6;
  846         ifp->if_hdrlen = 21;
  847         ifp->if_dlt = DLT_FDDI;
  848         ifp->if_mtu = FDDIMTU;
  849         ifp->if_output = fddi_output;
  850         ifp->if_input = fddi_input;
  851         ifp->if_baudrate = IF_Mbps(100);
  852 #ifdef IFF_NOTRAILERS
  853         ifp->if_flags |= IFF_NOTRAILERS;
  854 #endif
  855 
  856         /*
  857          * Update the max_linkhdr
  858          */
  859         if (ALIGN(ifp->if_hdrlen) > max_linkhdr)
  860                 max_linkhdr = ALIGN(ifp->if_hdrlen);
  861 
  862         LIST_INIT(&ec->ec_multiaddrs);
  863         if_alloc_sadl(ifp);
  864         memcpy(LLADDR(ifp->if_sadl), lla, ifp->if_addrlen);
  865 
  866         ifp->if_broadcastaddr = fddibroadcastaddr;
  867 #if NBPFILTER > 0
  868         bpfattach(ifp, DLT_FDDI, sizeof(struct fddi_header));
  869 #endif /* NBPFILTER > 0 */
  870 #ifdef MBUFTRACE
  871         strlcpy(ec->ec_tx_mowner.mo_name, ifp->if_xname,
  872             sizeof(ec->ec_tx_mowner.mo_name));
  873         strlcpy(ec->ec_tx_mowner.mo_descr, "tx",
  874             sizeof(ec->ec_tx_mowner.mo_descr));
  875         strlcpy(ec->ec_rx_mowner.mo_name, ifp->if_xname,
  876             sizeof(ec->ec_rx_mowner.mo_name));
  877         strlcpy(ec->ec_rx_mowner.mo_descr, "rx",
  878             sizeof(ec->ec_rx_mowner.mo_descr));
  879         MOWNER_ATTACH(&ec->ec_tx_mowner);
  880         MOWNER_ATTACH(&ec->ec_rx_mowner);
  881         ifp->if_mowner = &ec->ec_tx_mowner;
  882 #endif
  883 }

Cache object: 70bfda0538bb4b78b4f3285e4a05154b


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