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.63.6.1 2006/12/18 14:43:31 tron 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.63.6.1 2006/12/18 14:43:31 tron Exp $");
  100 
  101 #include "opt_inet.h"
  102 #include "opt_atalk.h"
  103 #include "opt_iso.h"
  104 #include "opt_ipx.h"
  105 #include "opt_mbuftrace.h"
  106 
  107 #include "bpfilter.h"
  108 
  109 #include <sys/param.h>
  110 #include <sys/systm.h>
  111 #include <sys/kernel.h>
  112 #include <sys/malloc.h>
  113 #include <sys/mbuf.h>
  114 #include <sys/protosw.h>
  115 #include <sys/socket.h>
  116 #include <sys/ioctl.h>
  117 #include <sys/errno.h>
  118 #include <sys/syslog.h>
  119 
  120 #include <machine/cpu.h>
  121 
  122 #include <net/if.h>
  123 #include <net/netisr.h>
  124 #include <net/route.h>
  125 #include <net/if_llc.h>
  126 #include <net/if_dl.h>
  127 #include <net/if_types.h>
  128 
  129 #if NBPFILTER > 0
  130 #include <net/bpf.h>
  131 #endif
  132 
  133 #ifdef INET
  134 #include <netinet/in.h>
  135 #include <netinet/in_var.h>
  136 #include <netinet/if_inarp.h>
  137 #include "opt_gateway.h"
  138 #endif
  139 #include <net/if_fddi.h>
  140 
  141 #ifdef IPX
  142 #include <netipx/ipx.h>
  143 #include <netipx/ipx_if.h>
  144 #endif
  145 
  146 #ifdef INET6
  147 #ifndef INET
  148 #include <netinet/in.h>
  149 #include <netinet/in_var.h>
  150 #endif
  151 #include <netinet6/nd6.h>
  152 #endif
  153 
  154 
  155 #include "carp.h"
  156 #if NCARP > 0
  157 #include <netinet/ip_carp.h>
  158 #endif
  159 
  160 #ifdef DECNET
  161 #include <netdnet/dn.h>
  162 #endif
  163 
  164 #ifdef ISO
  165 #include <netiso/argo_debug.h>
  166 #include <netiso/iso.h>
  167 #include <netiso/iso_var.h>
  168 #include <netiso/iso_snpac.h>
  169 #endif
  170 
  171 
  172 #ifdef NETATALK
  173 #include <netatalk/at.h>
  174 #include <netatalk/at_var.h>
  175 #include <netatalk/at_extern.h>
  176 
  177 #define llc_snap_org_code llc_un.type_snap.org_code
  178 #define llc_snap_ether_type llc_un.type_snap.ether_type
  179 
  180 extern u_char   at_org_code[ 3 ];
  181 extern u_char   aarp_org_code[ 3 ];
  182 #endif /* NETATALK */
  183 
  184 
  185 #include "bpfilter.h"
  186 
  187 #define senderr(e) { error = (e); goto bad;}
  188 
  189 /*
  190  * This really should be defined in if_llc.h but in case it isn't.
  191  */
  192 #ifndef llc_snap
  193 #define llc_snap        llc_un.type_snap
  194 #endif
  195 
  196 #define FDDIADDR(ifp)           LLADDR((ifp)->if_sadl)
  197 
  198 static  int fddi_output(struct ifnet *, struct mbuf *,
  199             struct sockaddr *, struct rtentry *);
  200 static  void fddi_input(struct ifnet *, struct mbuf *);
  201 
  202 /*
  203  * FDDI output routine.
  204  * Encapsulate a packet of type family for the local net.
  205  * Assumes that ifp is actually pointer to ethercom structure.
  206  */
  207 static int
  208 fddi_output(struct ifnet *ifp0, struct mbuf *m0, struct sockaddr *dst,
  209     struct rtentry *rt0)
  210 {
  211         u_int16_t etype;
  212         int error = 0, hdrcmplt = 0;
  213         u_char esrc[6], edst[6];
  214         struct mbuf *m = m0;
  215         struct rtentry *rt;
  216         struct fddi_header *fh;
  217         struct mbuf *mcopy = (struct mbuf *)0;
  218         struct ifnet *ifp = ifp0;
  219         ALTQ_DECL(struct altq_pktattr pktattr;)
  220 
  221         MCLAIM(m, ifp->if_mowner);
  222 
  223 #if NCARP > 0
  224         if (ifp->if_type == IFT_CARP) {
  225                 struct ifaddr *ifa;
  226 
  227                 /* loop back if this is going to the carp interface */
  228                 if (dst != NULL && ifp0->if_link_state == LINK_STATE_UP &&
  229                     (ifa = ifa_ifwithaddr(dst)) != NULL &&
  230                     ifa->ifa_ifp == ifp0)
  231                         return (looutput(ifp0, m, dst, rt0));
  232 
  233                 ifp = ifp->if_carpdev;
  234                 /* ac = (struct arpcom *)ifp; */
  235 
  236                 if ((ifp0->if_flags & (IFF_UP|IFF_RUNNING)) !=
  237                     (IFF_UP|IFF_RUNNING))
  238                         senderr(ENETDOWN);
  239         }
  240 #endif /* NCARP > 0 */
  241         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
  242                 senderr(ENETDOWN);
  243 #if !defined(__bsdi__) || _BSDI_VERSION >= 199401
  244         if ((rt = rt0) != NULL) {
  245                 if ((rt->rt_flags & RTF_UP) == 0) {
  246                         if ((rt0 = rt = rtalloc1(dst, 1)) != NULL)
  247                                 rt->rt_refcnt--;
  248                         else
  249                                 senderr(EHOSTUNREACH);
  250                 }
  251                 if (rt->rt_flags & RTF_GATEWAY) {
  252                         if (rt->rt_gwroute == 0)
  253                                 goto lookup;
  254                         if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
  255                                 rtfree(rt); rt = rt0;
  256                         lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);
  257                                 if ((rt = rt->rt_gwroute) == 0)
  258                                         senderr(EHOSTUNREACH);
  259                         }
  260                 }
  261                 if (rt->rt_flags & RTF_REJECT)
  262                         if (rt->rt_rmx.rmx_expire == 0 ||
  263                             time_second < rt->rt_rmx.rmx_expire)
  264                                 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
  265         }
  266 #endif
  267 
  268         /*
  269          * If the queueing discipline needs packet classification,
  270          * do it before prepending link headers.
  271          */
  272         IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
  273 
  274         switch (dst->sa_family) {
  275 
  276 #ifdef INET
  277         case AF_INET: {
  278 #define SIN(x) ((struct sockaddr_in *)(x))
  279                 if (m->m_flags & M_BCAST)
  280                         memcpy(edst, fddibroadcastaddr, sizeof(edst));
  281                 else if (m->m_flags & M_MCAST) {
  282                         ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr,
  283                             (caddr_t)edst)
  284                 } else if (!arpresolve(ifp, rt, m, dst, edst))
  285                         return (0);     /* if not yet resolved */
  286                 /* If broadcasting on a simplex interface, loopback a copy */
  287                 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
  288                         mcopy = m_copy(m, 0, (int)M_COPYALL);
  289                 etype = htons(ETHERTYPE_IP);
  290                 break;
  291         }
  292 #endif
  293 #ifdef INET6
  294         case AF_INET6:
  295                 if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)edst)){
  296                         /* something bad happened */
  297                         return (0);
  298                 }
  299                 etype = htons(ETHERTYPE_IPV6);
  300                 break;
  301 #endif
  302 #ifdef AF_ARP
  303         case AF_ARP: {
  304                 struct arphdr *ah = mtod(m, struct arphdr *);
  305                 if (m->m_flags & M_BCAST)
  306                         memcpy(edst, etherbroadcastaddr, sizeof(edst));
  307                 else {
  308                         caddr_t tha = ar_tha(ah);
  309 
  310                         KASSERT(tha);
  311                         memcpy(edst, tha, sizeof(edst));
  312                 }
  313 
  314                 ah->ar_hrd = htons(ARPHRD_ETHER);
  315 
  316                 switch (ntohs(ah->ar_op)) {
  317                 case ARPOP_REVREQUEST:
  318                 case ARPOP_REVREPLY:
  319                         etype = htons(ETHERTYPE_REVARP);
  320                         break;
  321 
  322                 case ARPOP_REQUEST:
  323                 case ARPOP_REPLY:
  324                 default:
  325                         etype = htons(ETHERTYPE_ARP);
  326                 }
  327 
  328                 break;
  329         }
  330 #endif /* AF_ARP */
  331 #ifdef IPX
  332         case AF_IPX:
  333                 etype = htons(ETHERTYPE_IPX);
  334                 memcpy(edst, &(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
  335                     sizeof (edst));
  336                 /* If broadcasting on a simplex interface, loopback a copy */
  337                 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
  338                         mcopy = m_copy(m, 0, (int)M_COPYALL);
  339                 break;
  340 #endif
  341 #ifdef NETATALK
  342         case AF_APPLETALK: {
  343                 struct at_ifaddr *aa;
  344                 if (!aarpresolve(ifp, m, (struct sockaddr_at *)dst, edst)) {
  345 #ifdef NETATALKDEBUG
  346                         printf("aarpresolv: failed\n");
  347 #endif
  348                         return (0);
  349                 }
  350                 /*
  351                  * ifaddr is the first thing in at_ifaddr
  352                  */
  353                 if ((aa = (struct at_ifaddr *)at_ifawithnet(
  354                     (struct sockaddr_at *)dst, ifp)) == NULL)
  355                         goto bad;
  356 
  357                 /*
  358                  * In the phase 2 case, we need to prepend an mbuf for the llc
  359                  * header. Since we must preserve the value of m, which is
  360                  * passed to us by value, we m_copy() the first mbuf, and use
  361                  * it for our llc header.
  362                  */
  363                 if (aa->aa_flags & AFA_PHASE2) {
  364                         struct llc llc;
  365 
  366                         M_PREPEND(m, sizeof(struct llc), M_NOWAIT);
  367                         if (m == 0)
  368                                 senderr(ENOBUFS);
  369                         llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
  370                         llc.llc_control = LLC_UI;
  371                         memcpy(llc.llc_snap_org_code, at_org_code,
  372                             sizeof(at_org_code));
  373                         llc.llc_snap_ether_type = htons(ETHERTYPE_ATALK);
  374                         memcpy(mtod(m, caddr_t), &llc, sizeof(struct llc));
  375                         etype = 0;
  376                 } else {
  377                         etype = htons(ETHERTYPE_ATALK);
  378                 }
  379                 break;
  380         }
  381 #endif /* NETATALK */
  382 #ifdef  ISO
  383         case AF_ISO: {
  384                 int     snpalen;
  385                 struct  llc *l;
  386                 struct sockaddr_dl *sdl;
  387 
  388                 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
  389                     sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
  390                         memcpy(edst, LLADDR(sdl), sizeof(edst));
  391                 } else if ((error =
  392                             iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
  393                                             (char *)edst, &snpalen)) != 0)
  394                         goto bad; /* Not Resolved */
  395                 /* If broadcasting on a simplex interface, loopback a copy */
  396                 if (*edst & 1)
  397                         m->m_flags |= (M_BCAST|M_MCAST);
  398                 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
  399                     (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
  400                         M_PREPEND(mcopy, sizeof (*fh), M_DONTWAIT);
  401                         if (mcopy) {
  402                                 fh = mtod(mcopy, struct fddi_header *);
  403                                 memcpy(fh->fddi_dhost, edst, sizeof (edst));
  404                                 memcpy(fh->fddi_shost, FDDIADDR(ifp),
  405                                     sizeof (edst));
  406                         }
  407                 }
  408                 M_PREPEND(m, 3, M_DONTWAIT);
  409                 if (m == NULL)
  410                         return (0);
  411                 etype = 0;
  412                 l = mtod(m, struct llc *);
  413                 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
  414                 l->llc_control = LLC_UI;
  415                 } break;
  416 #endif /* ISO */
  417 
  418         case pseudo_AF_HDRCMPLT:
  419         {
  420                 struct fddi_header *fh1 = (struct fddi_header *)dst->sa_data;
  421                 hdrcmplt = 1;
  422                 memcpy(esrc, fh1->fddi_shost, sizeof (esrc));
  423                 /*FALLTHROUGH*/
  424         }
  425 
  426         case AF_LINK:
  427         {
  428                 struct fddi_header *fh1 = (struct fddi_header *)dst->sa_data;
  429                 memcpy(edst, fh1->fddi_dhost, sizeof (edst));
  430                 if (*edst & 1)
  431                         m->m_flags |= (M_BCAST|M_MCAST);
  432                 etype = 0;
  433                 break;
  434         }
  435 
  436         case AF_UNSPEC:
  437         {
  438                 struct ether_header *eh;
  439                 eh = (struct ether_header *)dst->sa_data;
  440                 memcpy(edst, eh->ether_dhost, sizeof (edst));
  441                 if (*edst & 1)
  442                         m->m_flags |= (M_BCAST|M_MCAST);
  443                 etype = eh->ether_type;
  444                 break;
  445         }
  446 
  447 #if NBPFILTER > 0
  448         case AF_IMPLINK:
  449         {
  450                 fh = mtod(m, struct fddi_header *);
  451                 error = EPROTONOSUPPORT;
  452                 switch (fh->fddi_fc & (FDDIFC_C|FDDIFC_L|FDDIFC_F)) {
  453                         case FDDIFC_LLC_ASYNC: {
  454                                 /* legal priorities are 0 through 7 */
  455                                 if ((fh->fddi_fc & FDDIFC_Z) > 7)
  456                                         goto bad;
  457                                 break;
  458                         }
  459                         case FDDIFC_LLC_SYNC: {
  460                                 /* FDDIFC_Z bits reserved, must be zero */
  461                                 if (fh->fddi_fc & FDDIFC_Z)
  462                                         goto bad;
  463                                 break;
  464                         }
  465                         case FDDIFC_SMT: {
  466                                 /* FDDIFC_Z bits must be non zero */
  467                                 if ((fh->fddi_fc & FDDIFC_Z) == 0)
  468                                         goto bad;
  469                                 break;
  470                         }
  471                         default: {
  472                                 /* anything else is too dangerous */
  473                                 goto bad;
  474                         }
  475                 }
  476                 error = 0;
  477                 if (fh->fddi_dhost[0] & 1)
  478                         m->m_flags |= (M_BCAST|M_MCAST);
  479                 goto queue_it;
  480         }
  481 #endif
  482         default:
  483                 printf("%s: can't handle af%d\n", ifp->if_xname,
  484                        dst->sa_family);
  485                 senderr(EAFNOSUPPORT);
  486         }
  487 
  488 
  489         if (mcopy)
  490                 (void) looutput(ifp, mcopy, dst, rt);
  491         if (etype != 0) {
  492                 struct llc *l;
  493                 M_PREPEND(m, sizeof (struct llc), M_DONTWAIT);
  494                 if (m == 0)
  495                         senderr(ENOBUFS);
  496                 l = mtod(m, struct llc *);
  497                 l->llc_control = LLC_UI;
  498                 l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP;
  499                 l->llc_snap.org_code[0] = l->llc_snap.org_code[1] = l->llc_snap.org_code[2] = 0;
  500                 memcpy(&l->llc_snap.ether_type, &etype, sizeof(u_int16_t));
  501         }
  502         /*
  503          * Add local net header.  If no space in first mbuf,
  504          * allocate another.
  505          */
  506         M_PREPEND(m, sizeof (struct fddi_header), M_DONTWAIT);
  507         if (m == 0)
  508                 senderr(ENOBUFS);
  509         fh = mtod(m, struct fddi_header *);
  510         fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4;
  511         memcpy(fh->fddi_dhost, edst, sizeof (edst));
  512 #if NBPFILTER > 0
  513   queue_it:
  514 #endif
  515         if (hdrcmplt)
  516                 memcpy(fh->fddi_shost, esrc, sizeof(fh->fddi_shost));
  517         else
  518                 memcpy(fh->fddi_shost, FDDIADDR(ifp), sizeof(fh->fddi_shost));
  519 
  520 #if NCARP > 0
  521         if (ifp0 != ifp && ifp0->if_type == IFT_CARP)
  522                 memcpy(FDDIADDR(ifp0), fh->fddi_shost, sizeof(fh->fddi_shost));
  523 
  524         if (ifp != ifp0)
  525                 ifp0->if_obytes += m->m_pkthdr.len;
  526 #endif /* NCARP > 0 */
  527         return ifq_enqueue(ifp, m ALTQ_COMMA ALTQ_DECL(&pktattr));
  528 
  529 bad:
  530         if (m)
  531                 m_freem(m);
  532         return (error);
  533 }
  534 
  535 /*
  536  * Process a received FDDI packet;
  537  * the packet is in the mbuf chain m with
  538  * the fddi header.
  539  */
  540 static void
  541 fddi_input(struct ifnet *ifp, struct mbuf *m)
  542 {
  543 #if defined(INET) || defined(INET6) || defined(NS) || defined(DECNET) || defined(IPX) || defined(NETATALK)
  544         struct ifqueue *inq;
  545         int s;
  546 #endif
  547         struct llc *l;
  548         struct fddi_header *fh;
  549 
  550         MCLAIM(m, &((struct ethercom *)ifp)->ec_rx_mowner);
  551         if ((ifp->if_flags & IFF_UP) == 0) {
  552                 m_freem(m);
  553                 return;
  554         }
  555 
  556         fh = mtod(m, struct fddi_header *);
  557 
  558         ifp->if_ibytes += m->m_pkthdr.len;
  559         if (fh->fddi_dhost[0] & 1) {
  560                 if (memcmp(fddibroadcastaddr, fh->fddi_dhost,
  561                     sizeof(fddibroadcastaddr)) == 0)
  562                         m->m_flags |= M_BCAST;
  563                 else
  564                         m->m_flags |= M_MCAST;
  565                 ifp->if_imcasts++;
  566         } else if ((ifp->if_flags & IFF_PROMISC)
  567             && memcmp(FDDIADDR(ifp), (caddr_t)fh->fddi_dhost,
  568                     sizeof(fh->fddi_dhost)) != 0) {
  569                 m_freem(m);
  570                 return;
  571         }
  572 
  573 #ifdef M_LINK0
  574         /*
  575          * If this has a LLC priority of 0, then mark it so upper
  576          * layers have a hint that it really came via a FDDI/Ethernet
  577          * bridge.
  578          */
  579         if ((fh->fddi_fc & FDDIFC_LLC_PRIO7) == FDDIFC_LLC_PRIO0)
  580                 m->m_flags |= M_LINK0;
  581 #endif
  582 
  583         l = (struct llc *)(fh+1);
  584         switch (l->llc_dsap) {
  585 #if defined(INET) || defined(INET6) || defined(NS) || defined(DECNET) || defined(IPX) || defined(NETATALK)
  586         case LLC_SNAP_LSAP:
  587         {
  588                 u_int16_t etype;
  589                 if (l->llc_control != LLC_UI || l->llc_ssap != LLC_SNAP_LSAP)
  590                         goto dropanyway;
  591 
  592                 /* Strip off the FDDI header. */
  593                 m_adj(m, sizeof(struct fddi_header));
  594 
  595 #ifdef NETATALK
  596                 if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code,
  597                          sizeof(at_org_code)) == 0 &&
  598                         ntohs(l->llc_snap_ether_type) == ETHERTYPE_ATALK) {
  599                     inq = &atintrq2;
  600                     m_adj( m, sizeof( struct llc ));
  601                     schednetisr(NETISR_ATALK);
  602                     break;
  603                 }
  604 
  605                 if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code,
  606                          sizeof(aarp_org_code)) == 0 &&
  607                         ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) {
  608                     m_adj( m, sizeof( struct llc ));
  609                     aarpinput(ifp, m); /* XXX */
  610                     return;
  611                 }
  612 #endif /* NETATALK */
  613                 if (l->llc_snap.org_code[0] != 0 || l->llc_snap.org_code[1] != 0|| l->llc_snap.org_code[2] != 0)
  614                         goto dropanyway;
  615                 etype = ntohs(l->llc_snap.ether_type);
  616                 m_adj(m, 8);
  617 #if NCARP > 0
  618                 if (ifp->if_carp && ifp->if_type != IFT_CARP &&
  619                     (carp_input(m, (u_int8_t *)&fh->fddi_shost,
  620                     (u_int8_t *)&fh->fddi_dhost, l->llc_snap.ether_type) == 0))
  621                         return;
  622 #endif
  623 
  624                 switch (etype) {
  625 #ifdef INET
  626                 case ETHERTYPE_IP:
  627 #ifdef GATEWAY
  628                         if (ipflow_fastforward(m))
  629                                 return;
  630 #endif
  631                         schednetisr(NETISR_IP);
  632                         inq = &ipintrq;
  633                         break;
  634 
  635                 case ETHERTYPE_ARP:
  636 #if !defined(__bsdi__) || _BSDI_VERSION >= 199401
  637                         schednetisr(NETISR_ARP);
  638                         inq = &arpintrq;
  639                         break;
  640 #else
  641                         arpinput(ifp, m);
  642                         return;
  643 #endif
  644 #endif
  645 #ifdef IPX
  646                 case ETHERTYPE_IPX:
  647                         schednetisr(NETISR_IPX);
  648                         inq = &ipxintrq;
  649                         break;
  650 #endif
  651 #ifdef INET6
  652                 case ETHERTYPE_IPV6:
  653                         schednetisr(NETISR_IPV6);
  654                         inq = &ip6intrq;
  655                         break;
  656 
  657 #endif
  658 #ifdef DECNET
  659                 case ETHERTYPE_DECNET:
  660                         schednetisr(NETISR_DECNET);
  661                         inq = &decnetintrq;
  662                         break;
  663 #endif
  664 #ifdef NETATALK
  665                 case ETHERTYPE_ATALK:
  666                         schednetisr(NETISR_ATALK);
  667                         inq = &atintrq1;
  668                         break;
  669                 case ETHERTYPE_AARP:
  670                         /* probably this should be done with a NETISR as well */
  671                         aarpinput(ifp, m); /* XXX */
  672                         return;
  673 #endif /* NETATALK */
  674                 default:
  675                         ifp->if_noproto++;
  676                         goto dropanyway;
  677                 }
  678                 break;
  679         }
  680 #endif /* INET || NS */
  681 #ifdef  ISO
  682         case LLC_ISO_LSAP:
  683                 switch (l->llc_control) {
  684                 case LLC_UI:
  685                         /* LLC_UI_P forbidden in class 1 service */
  686                         if ((l->llc_dsap == LLC_ISO_LSAP) &&
  687                             (l->llc_ssap == LLC_ISO_LSAP)) {
  688 
  689                                 schednetisr(NETISR_ISO);
  690                                 inq = &clnlintrq;
  691                                 break;
  692                         }
  693                         goto dropanyway;
  694 
  695                 case LLC_XID:
  696                 case LLC_XID_P:
  697                         if(m->m_len <
  698                             LLC_XID_BASIC_MINLEN + sizeof(struct fddi_header))
  699                                 goto dropanyway;
  700                         l->llc_window = 0;
  701                         l->llc_fid = 9;
  702                         l->llc_class = 1;
  703                         l->llc_dsap = l->llc_ssap = 0;
  704                         /* Fall through to */
  705                 case LLC_TEST:
  706                 case LLC_TEST_P:
  707                 {
  708                         struct sockaddr sa;
  709                         struct ether_header *eh;
  710                         int i;
  711                         u_char c = l->llc_dsap;
  712 
  713                         l->llc_dsap = l->llc_ssap;
  714                         l->llc_ssap = c;
  715                         eh = (struct ether_header *)sa.sa_data;
  716                         if (m->m_flags & (M_BCAST | M_MCAST))
  717                                 memcpy(eh->ether_dhost, FDDIADDR(ifp), 6);
  718                         sa.sa_family = AF_UNSPEC;
  719                         sa.sa_len = sizeof(sa);
  720                         for (i = 0; i < 6; i++) {
  721                                 eh->ether_shost[i] = fh->fddi_dhost[i];
  722                                 eh->ether_dhost[i] = fh->fddi_shost[i];
  723                         }
  724                         eh->ether_type = 0;
  725                         m_adj(m, sizeof(struct fddi_header));
  726                         ifp->if_output(ifp, m, &sa, NULL);
  727                         return;
  728                 }
  729                 default:
  730                         m_freem(m);
  731                         return;
  732                 }
  733                 break;
  734 #endif /* ISO */
  735 
  736         default:
  737                 ifp->if_noproto++;
  738 #if defined(INET) || defined(INET6) || defined(NS) || defined(DECNET) || defined(IPX) || defined(NETATALK)
  739         dropanyway:
  740 #endif
  741                 m_freem(m);
  742                 return;
  743         }
  744 
  745 #if defined(INET) || defined(INET6) || defined(NS) || defined(DECNET) || defined(IPX) || defined(NETATALK)
  746         s = splnet();
  747         if (IF_QFULL(inq)) {
  748                 IF_DROP(inq);
  749                 m_freem(m);
  750         } else
  751                 IF_ENQUEUE(inq, m);
  752         splx(s);
  753 #endif
  754 }
  755 
  756 /*
  757  * Perform common duties while attaching to interface list
  758  */
  759 void
  760 fddi_ifattach(struct ifnet *ifp, caddr_t lla)
  761 {
  762         struct ethercom *ec = (struct ethercom *)ifp;
  763 
  764         ifp->if_type = IFT_FDDI;
  765         ifp->if_addrlen = 6;
  766         ifp->if_hdrlen = 21;
  767         ifp->if_dlt = DLT_FDDI;
  768         ifp->if_mtu = FDDIMTU;
  769         ifp->if_output = fddi_output;
  770         ifp->if_input = fddi_input;
  771         ifp->if_baudrate = IF_Mbps(100);
  772 #ifdef IFF_NOTRAILERS
  773         ifp->if_flags |= IFF_NOTRAILERS;
  774 #endif
  775 
  776         /*
  777          * Update the max_linkhdr
  778          */
  779         if (ALIGN(ifp->if_hdrlen) > max_linkhdr)
  780                 max_linkhdr = ALIGN(ifp->if_hdrlen);
  781 
  782         LIST_INIT(&ec->ec_multiaddrs);
  783         if_alloc_sadl(ifp);
  784         memcpy(LLADDR(ifp->if_sadl), lla, ifp->if_addrlen);
  785 
  786         ifp->if_broadcastaddr = fddibroadcastaddr;
  787 #if NBPFILTER > 0
  788         bpfattach(ifp, DLT_FDDI, sizeof(struct fddi_header));
  789 #endif /* NBPFILTER > 0 */
  790 #ifdef MBUFTRACE
  791         strlcpy(ec->ec_tx_mowner.mo_name, ifp->if_xname,
  792             sizeof(ec->ec_tx_mowner.mo_name));
  793         strlcpy(ec->ec_tx_mowner.mo_descr, "tx",
  794             sizeof(ec->ec_tx_mowner.mo_descr));
  795         strlcpy(ec->ec_rx_mowner.mo_name, ifp->if_xname,
  796             sizeof(ec->ec_rx_mowner.mo_name));
  797         strlcpy(ec->ec_rx_mowner.mo_descr, "rx",
  798             sizeof(ec->ec_rx_mowner.mo_descr));
  799         MOWNER_ATTACH(&ec->ec_tx_mowner);
  800         MOWNER_ATTACH(&ec->ec_rx_mowner);
  801         ifp->if_mowner = &ec->ec_tx_mowner;
  802 #endif
  803 }

Cache object: 3927ee1d7a4fa893462ccd96216ed143


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