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.54 2005/02/26 22:45:09 perry 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.54 2005/02/26 22:45:09 perry 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 #if defined(INET) || defined(INET6) || defined(NS) || defined(DECNET) || defined(IPX) || defined(NETATALK)
  605         struct ifqueue *inq;
  606         int s;
  607 #endif
  608         struct llc *l;
  609         struct fddi_header *fh;
  610 
  611         MCLAIM(m, &((struct ethercom *)ifp)->ec_rx_mowner);
  612         if ((ifp->if_flags & IFF_UP) == 0) {
  613                 m_freem(m);
  614                 return;
  615         }
  616 
  617         fh = mtod(m, struct fddi_header *);
  618 
  619         ifp->if_ibytes += m->m_pkthdr.len;
  620         if (fh->fddi_dhost[0] & 1) {
  621                 if (bcmp((caddr_t)fddibroadcastaddr, (caddr_t)fh->fddi_dhost,
  622                     sizeof(fddibroadcastaddr)) == 0)
  623                         m->m_flags |= M_BCAST;
  624                 else
  625                         m->m_flags |= M_MCAST;
  626                 ifp->if_imcasts++;
  627         } else if ((ifp->if_flags & IFF_PROMISC)
  628             && bcmp(FDDIADDR(ifp), (caddr_t)fh->fddi_dhost,
  629                     sizeof(fh->fddi_dhost)) != 0) {
  630                 m_freem(m);
  631                 return;
  632         }
  633 
  634 #ifdef M_LINK0
  635         /*
  636          * If this has a LLC priority of 0, then mark it so upper
  637          * layers have a hint that it really came via a FDDI/Ethernet
  638          * bridge.
  639          */
  640         if ((fh->fddi_fc & FDDIFC_LLC_PRIO7) == FDDIFC_LLC_PRIO0)
  641                 m->m_flags |= M_LINK0;
  642 #endif
  643 
  644         /* Strip off the FDDI header. */
  645         m_adj(m, sizeof(struct fddi_header));
  646 
  647         l = mtod(m, struct llc *);
  648         switch (l->llc_dsap) {
  649 #if defined(INET) || defined(INET6) || defined(NS) || defined(DECNET) || defined(IPX) || defined(NETATALK)
  650         case LLC_SNAP_LSAP:
  651         {
  652                 u_int16_t etype;
  653                 if (l->llc_control != LLC_UI || l->llc_ssap != LLC_SNAP_LSAP)
  654                         goto dropanyway;
  655 #ifdef NETATALK
  656                 if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code,
  657                          sizeof(at_org_code)) == 0 &&
  658                         ntohs(l->llc_snap_ether_type) == ETHERTYPE_ATALK) {
  659                     inq = &atintrq2;
  660                     m_adj( m, sizeof( struct llc ));
  661                     schednetisr(NETISR_ATALK);
  662                     break;
  663                 }
  664 
  665                 if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code,
  666                          sizeof(aarp_org_code)) == 0 &&
  667                         ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) {
  668                     m_adj( m, sizeof( struct llc ));
  669                     aarpinput(ifp, m); /* XXX */
  670                     return;
  671                 }
  672 #endif /* NETATALK */
  673                 if (l->llc_snap.org_code[0] != 0 || l->llc_snap.org_code[1] != 0|| l->llc_snap.org_code[2] != 0)
  674                         goto dropanyway;
  675                 etype = ntohs(l->llc_snap.ether_type);
  676                 m_adj(m, 8);
  677                 switch (etype) {
  678 #ifdef INET
  679                 case ETHERTYPE_IP:
  680 #ifdef GATEWAY
  681                         if (ipflow_fastforward(m))
  682                                 return;
  683 #endif
  684                         schednetisr(NETISR_IP);
  685                         inq = &ipintrq;
  686                         break;
  687 
  688                 case ETHERTYPE_ARP:
  689 #if !defined(__bsdi__) || _BSDI_VERSION >= 199401
  690                         schednetisr(NETISR_ARP);
  691                         inq = &arpintrq;
  692                         break;
  693 #else
  694                         arpinput(ifp, m);
  695                         return;
  696 #endif
  697 #endif
  698 #ifdef IPX
  699                 case ETHERTYPE_IPX:
  700                         schednetisr(NETISR_IPX);
  701                         inq = &ipxintrq;
  702                         break;
  703 #endif
  704 #ifdef NS
  705                 case ETHERTYPE_NS:
  706                         schednetisr(NETISR_NS);
  707                         inq = &nsintrq;
  708                         break;
  709 #endif
  710 #ifdef INET6
  711                 case ETHERTYPE_IPV6:
  712                         schednetisr(NETISR_IPV6);
  713                         inq = &ip6intrq;
  714                         break;
  715 
  716 #endif
  717 #ifdef DECNET
  718                 case ETHERTYPE_DECNET:
  719                         schednetisr(NETISR_DECNET);
  720                         inq = &decnetintrq;
  721                         break;
  722 #endif
  723 #ifdef NETATALK
  724                 case ETHERTYPE_ATALK:
  725                         schednetisr(NETISR_ATALK);
  726                         inq = &atintrq1;
  727                         break;
  728                 case ETHERTYPE_AARP:
  729                         /* probably this should be done with a NETISR as well */
  730                         aarpinput(ifp, m); /* XXX */
  731                         return;
  732 #endif /* NETATALK */
  733                 default:
  734                         ifp->if_noproto++;
  735                         goto dropanyway;
  736                 }
  737                 break;
  738         }
  739 #endif /* INET || NS */
  740 #ifdef  ISO
  741         case LLC_ISO_LSAP:
  742                 switch (l->llc_control) {
  743                 case LLC_UI:
  744                         /* LLC_UI_P forbidden in class 1 service */
  745                         if ((l->llc_dsap == LLC_ISO_LSAP) &&
  746                             (l->llc_ssap == LLC_ISO_LSAP)) {
  747                                 /* LSAP for ISO */
  748                                 m->m_data += 3;         /* XXX */
  749                                 m->m_len -= 3;          /* XXX */
  750                                 m->m_pkthdr.len -= 3;   /* XXX */
  751                                 M_PREPEND(m, sizeof *fh, M_DONTWAIT);
  752                                 if (m == 0)
  753                                         return;
  754                                 *mtod(m, struct fddi_header *) = *fh;
  755                                 schednetisr(NETISR_ISO);
  756                                 inq = &clnlintrq;
  757                                 break;
  758                         }
  759                         goto dropanyway;
  760 
  761                 case LLC_XID:
  762                 case LLC_XID_P:
  763                         if(m->m_len < 6)
  764                                 goto dropanyway;
  765                         l->llc_window = 0;
  766                         l->llc_fid = 9;
  767                         l->llc_class = 1;
  768                         l->llc_dsap = l->llc_ssap = 0;
  769                         /* Fall through to */
  770                 case LLC_TEST:
  771                 case LLC_TEST_P:
  772                 {
  773                         struct sockaddr sa;
  774                         struct ether_header *eh;
  775                         int i;
  776                         u_char c = l->llc_dsap;
  777 
  778                         l->llc_dsap = l->llc_ssap;
  779                         l->llc_ssap = c;
  780                         eh = (struct ether_header *)sa.sa_data;
  781                         if (m->m_flags & (M_BCAST | M_MCAST))
  782                                 bcopy((caddr_t)FDDIADDR(ifp),
  783                                       (caddr_t)eh->ether_dhost, 6);
  784                         sa.sa_family = AF_UNSPEC;
  785                         sa.sa_len = sizeof(sa);
  786                         for (i = 0; i < 6; i++) {
  787                                 eh->ether_shost[i] = fh->fddi_dhost[i];
  788                                 eh->ether_dhost[i] = fh->fddi_shost[i];
  789                         }
  790                         eh->ether_type = 0;
  791                         ifp->if_output(ifp, m, &sa, NULL);
  792                         return;
  793                 }
  794                 default:
  795                         m_freem(m);
  796                         return;
  797                 }
  798                 break;
  799 #endif /* ISO */
  800 #ifdef LLC
  801         case LLC_X25_LSAP:
  802         {
  803                 M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
  804                 if (m == 0)
  805                         return;
  806                 if ( !sdl_sethdrif(ifp, fh->fddi_shost, LLC_X25_LSAP,
  807                                     fh->fddi_dhost, LLC_X25_LSAP, 6,
  808                                     mtod(m, struct sdl_hdr *)))
  809                         panic("ETHER cons addr failure");
  810                 mtod(m, struct sdl_hdr *)->sdlhdr_len = m->m_pkthdr.len - sizeof(struct sdl_hdr);
  811 #ifdef LLC_DEBUG
  812                 printf("llc packet\n");
  813 #endif /* LLC_DEBUG */
  814                 schednetisr(NETISR_CCITT);
  815                 inq = &llcintrq;
  816                 break;
  817         }
  818 #endif /* LLC */
  819 
  820         default:
  821                 ifp->if_noproto++;
  822 #if defined(INET) || defined(INET6) || defined(NS) || defined(DECNET) || defined(IPX) || defined(NETATALK)
  823         dropanyway:
  824 #endif
  825                 m_freem(m);
  826                 return;
  827         }
  828 
  829 #if defined(INET) || defined(INET6) || defined(NS) || defined(DECNET) || defined(IPX) || defined(NETATALK)
  830         s = splnet();
  831         if (IF_QFULL(inq)) {
  832                 IF_DROP(inq);
  833                 m_freem(m);
  834         } else
  835                 IF_ENQUEUE(inq, m);
  836         splx(s);
  837 #endif
  838 }
  839 
  840 /*
  841  * Perform common duties while attaching to interface list
  842  */
  843 void
  844 fddi_ifattach(ifp, lla)
  845         struct ifnet *ifp;
  846         caddr_t lla;
  847 {
  848         struct ethercom *ec = (struct ethercom *)ifp;
  849 
  850         ifp->if_type = IFT_FDDI;
  851         ifp->if_addrlen = 6;
  852         ifp->if_hdrlen = 21;
  853         ifp->if_dlt = DLT_FDDI;
  854         ifp->if_mtu = FDDIMTU;
  855         ifp->if_output = fddi_output;
  856         ifp->if_input = fddi_input;
  857         ifp->if_baudrate = IF_Mbps(100);
  858 #ifdef IFF_NOTRAILERS
  859         ifp->if_flags |= IFF_NOTRAILERS;
  860 #endif
  861 
  862         /*
  863          * Update the max_linkhdr
  864          */
  865         if (ALIGN(ifp->if_hdrlen) > max_linkhdr)
  866                 max_linkhdr = ALIGN(ifp->if_hdrlen);
  867 
  868         LIST_INIT(&ec->ec_multiaddrs);
  869         if_alloc_sadl(ifp);
  870         memcpy(LLADDR(ifp->if_sadl), lla, ifp->if_addrlen);
  871 
  872         ifp->if_broadcastaddr = fddibroadcastaddr;
  873 #if NBPFILTER > 0
  874         bpfattach(ifp, DLT_FDDI, sizeof(struct fddi_header));
  875 #endif /* NBPFILTER > 0 */
  876 #ifdef MBUFTRACE
  877         strlcpy(ec->ec_tx_mowner.mo_name, ifp->if_xname,
  878             sizeof(ec->ec_tx_mowner.mo_name));
  879         strlcpy(ec->ec_tx_mowner.mo_descr, "tx",
  880             sizeof(ec->ec_tx_mowner.mo_descr));
  881         strlcpy(ec->ec_rx_mowner.mo_name, ifp->if_xname,
  882             sizeof(ec->ec_rx_mowner.mo_name));
  883         strlcpy(ec->ec_rx_mowner.mo_descr, "rx",
  884             sizeof(ec->ec_rx_mowner.mo_descr));
  885         MOWNER_ATTACH(&ec->ec_tx_mowner);
  886         MOWNER_ATTACH(&ec->ec_rx_mowner);
  887         ifp->if_mowner = &ec->ec_tx_mowner;
  888 #endif
  889 }

Cache object: 4eef56428cd02d47e72bb6da275fdbc0


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