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_ethersubr.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 /*
    2  * Copyright (c) 1982, 1989, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *      This product includes software developed by the University of
   16  *      California, Berkeley and its contributors.
   17  * 4. Neither the name of the University nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  *
   33  *      @(#)if_ethersubr.c      8.1 (Berkeley) 6/10/93
   34  * $FreeBSD: src/sys/net/if_ethersubr.c,v 1.26.2.6 1999/09/05 08:17:36 peter Exp $
   35  */
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/kernel.h>
   40 #include <sys/malloc.h>
   41 #include <sys/mbuf.h>
   42 #include <sys/protosw.h>
   43 #include <sys/socket.h>
   44 #include <sys/ioctl.h>
   45 #include <sys/errno.h>
   46 #include <sys/syslog.h>
   47 #include <sys/sysctl.h>
   48 
   49 #include <net/if.h>
   50 #include <net/netisr.h>
   51 #include <net/route.h>
   52 #include <net/if_llc.h>
   53 #include <net/if_dl.h>
   54 #include <net/if_types.h>
   55 #include <net/ethernet.h>
   56 
   57 #ifdef INET
   58 #include <netinet/in.h>
   59 #include <netinet/in_var.h>
   60 #endif
   61 #include <netinet/if_ether.h>
   62 
   63 #ifdef IPX
   64 #include <netipx/ipx.h>
   65 #include <netipx/ipx_if.h>
   66 #endif
   67 
   68 #ifdef NS
   69 #include <netns/ns.h>
   70 #include <netns/ns_if.h>
   71 ushort ns_nettype;
   72 int ether_outputdebug = 0;
   73 int ether_inputdebug = 0;
   74 #endif
   75 
   76 #ifdef ISO
   77 #include <netiso/argo_debug.h>
   78 #include <netiso/iso.h>
   79 #include <netiso/iso_var.h>
   80 #include <netiso/iso_snpac.h>
   81 #endif
   82 
   83 /*#ifdef LLC
   84 #include <netccitt/dll.h>
   85 #include <netccitt/llc_var.h>
   86 #endif*/
   87 
   88 #if defined(LLC) && defined(CCITT)
   89 extern struct ifqueue pkintrq;
   90 #endif
   91 
   92 #ifdef NETATALK
   93 #include <netatalk/at.h>
   94 #include <netatalk/at_var.h>
   95 #include <netatalk/at_extern.h>
   96 
   97 #define llc_snap_org_code llc_un.type_snap.org_code
   98 #define llc_snap_ether_type llc_un.type_snap.ether_type
   99 
  100 extern u_char   at_org_code[ 3 ];
  101 extern u_char   aarp_org_code[ 3 ];
  102 #endif NETATALK
  103 
  104 #ifdef BRIDGE
  105 #include <net/bridge.h>
  106 #endif
  107 
  108 u_char  etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  109 #define senderr(e) { error = (e); goto bad;}
  110 
  111 /*
  112  * Ethernet output routine.
  113  * Encapsulate a packet of type family for the local net.
  114  * Use trailer local net encapsulation if enough data in first
  115  * packet leaves a multiple of 512 bytes of data in remainder.
  116  * Assumes that ifp is actually pointer to arpcom structure.
  117  */
  118 int
  119 ether_output(ifp, m0, dst, rt0)
  120         register struct ifnet *ifp;
  121         struct mbuf *m0;
  122         struct sockaddr *dst;
  123         struct rtentry *rt0;
  124 {
  125         short type;
  126         int s, error = 0;
  127         u_char *cp, edst[6];
  128         register struct mbuf *m2, *m = m0;
  129         register struct rtentry *rt;
  130         struct mbuf *mcopy = (struct mbuf *)0;
  131         register struct ether_header *eh;
  132         int off, len = m->m_pkthdr.len;
  133         struct arpcom *ac = (struct arpcom *)ifp;
  134         register struct ifqueue *inq;
  135 #ifdef NETATALK
  136         struct at_ifaddr *aa;
  137 #endif NETATALK
  138 
  139         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
  140                 senderr(ENETDOWN);
  141         rt = rt0;
  142         if (rt) {
  143                 if ((rt->rt_flags & RTF_UP) == 0) {
  144                         rt0 = rt = rtalloc1(dst, 1, 0UL);
  145                         if (rt0)
  146                                 rt->rt_refcnt--;
  147                         else
  148                                 senderr(EHOSTUNREACH);
  149                 }
  150                 if (rt->rt_flags & RTF_GATEWAY) {
  151                         if (rt->rt_gwroute == 0)
  152                                 goto lookup;
  153                         if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
  154                                 rtfree(rt); rt = rt0;
  155                         lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1,
  156                                                           0UL);
  157                                 if ((rt = rt->rt_gwroute) == 0)
  158                                         senderr(EHOSTUNREACH);
  159                         }
  160                 }
  161                 if (rt->rt_flags & RTF_REJECT)
  162                         if (rt->rt_rmx.rmx_expire == 0 ||
  163                             time.tv_sec < rt->rt_rmx.rmx_expire)
  164                                 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
  165         }
  166         switch (dst->sa_family) {
  167 
  168 #ifdef INET
  169         case AF_INET:
  170                 if (!arpresolve(ac, rt, m, dst, edst, rt0))
  171                         return (0);     /* if not yet resolved */
  172                 /* If broadcasting on a simplex interface, loopback a copy */
  173                 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
  174                         mcopy = m_copy(m, 0, (int)M_COPYALL);
  175                 off = m->m_pkthdr.len - m->m_len;
  176                 type = htons(ETHERTYPE_IP);
  177                 break;
  178 #endif
  179 #ifdef IPX
  180         case AF_IPX:
  181                 {
  182                 struct ifaddr *ia;
  183 
  184                 type = htons(ETHERTYPE_IPX);
  185                 bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
  186                     (caddr_t)edst, sizeof (edst));
  187                 for (ia = ifp->if_addrlist; ia != NULL; ia = ia->ifa_next)
  188                         if(ia->ifa_addr->sa_family == AF_IPX &&
  189                            !bcmp((caddr_t)edst,
  190                                  (caddr_t)&((struct ipx_ifaddr *)ia)->ia_addr.sipx_addr.x_host,
  191                                  sizeof(edst)))
  192                                 return (looutput(ifp, m, dst, rt));
  193                 /* If broadcasting on a simplex interface, loopback a copy */
  194                 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
  195                         mcopy = m_copy(m, 0, (int)M_COPYALL);
  196                 break;
  197                 }
  198 #endif
  199 #ifdef NETATALK
  200         case AF_APPLETALK:
  201             {
  202                 struct sockaddr_at *sat = (struct sockaddr_at *)dst;
  203 
  204                 /*
  205                  * super hack..
  206                  * Most of this loopback code should move into the appletalk
  207                  * code, but it's here for now.. remember to move it! [JRE]
  208                  * This may not get the same interface we started with
  209                  * fix asap. XXX
  210                  */
  211                 aa = at_ifawithnet( sat );
  212                 if (aa == NULL) {
  213                         goto bad;
  214                 }
  215                 if( aa->aa_ifa.ifa_ifp != ifp ) {
  216                         (*aa->aa_ifa.ifa_ifp->if_output)(aa->aa_ifa.ifa_ifp,
  217                                                         m,dst,rt);
  218                 }
  219                 if (((sat->sat_addr.s_net == ATADDR_ANYNET)
  220                   && (sat->sat_addr.s_node == ATADDR_ANYNODE))
  221                 || ((sat->sat_addr.s_net == aa->aa_addr.sat_addr.s_net )
  222                   && (sat->sat_addr.s_node == aa->aa_addr.sat_addr.s_node))) {
  223                         (void) looutput(ifp, m, dst, rt);
  224                         return(0);
  225                 }
  226 
  227                 if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst)) {
  228 #ifdef NETATALKDEBUG
  229                         extern char *prsockaddr(struct sockaddr *);
  230                         printf("aarpresolv: failed for %s\n", prsockaddr(dst));
  231 #endif NETATALKDEBUG
  232                         return (0);
  233                 }
  234 
  235                 /*
  236                  * If broadcasting on a simplex interface, loopback a copy
  237                  */
  238                 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
  239                         mcopy = m_copy(m, 0, (int)M_COPYALL);
  240             }
  241             /*
  242              * In the phase 2 case, we need to prepend an mbuf for the llc header.
  243              * Since we must preserve the value of m, which is passed to us by
  244              * value, we m_copy() the first mbuf, and use it for our llc header.
  245              */
  246             if ( aa->aa_flags & AFA_PHASE2 ) {
  247                 struct llc llc;
  248 
  249                 M_PREPEND(m, sizeof(struct llc), M_WAIT);
  250                 len += sizeof(struct llc);
  251                 llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
  252                 llc.llc_control = LLC_UI;
  253                 bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code));
  254                 llc.llc_snap_ether_type = htons( ETHERTYPE_AT );
  255                 bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc));
  256                 type = htons(m->m_pkthdr.len);
  257             } else {
  258                 type = htons(ETHERTYPE_AT);
  259             }
  260             break;
  261 #endif NETATALK
  262 #ifdef NS
  263         case AF_NS:
  264                 switch(ns_nettype){
  265                 default:
  266                 case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
  267                         type = 0x8137;
  268                         break;
  269                 case 0x0: /* Novell 802.3 */
  270                         type = htons( m->m_pkthdr.len);
  271                         break;
  272                 case 0xe0e0: /* Novell 802.2 and Token-Ring */
  273                         M_PREPEND(m, 3, M_WAIT);
  274                         type = htons( m->m_pkthdr.len);
  275                         cp = mtod(m, u_char *);
  276                         *cp++ = 0xE0;
  277                         *cp++ = 0xE0;
  278                         *cp++ = 0x03;
  279                         break;
  280                 }
  281                 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
  282                     (caddr_t)edst, sizeof (edst));
  283                 if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))){
  284                         m->m_pkthdr.rcvif = ifp;
  285                         schednetisr(NETISR_NS);
  286                         inq = &nsintrq;
  287                         s = splimp();
  288                         if (IF_QFULL(inq)) {
  289                                 IF_DROP(inq);
  290                                 m_freem(m);
  291                         } else
  292                                 IF_ENQUEUE(inq, m);
  293                         splx(s);
  294                         return (error);
  295                 }
  296                 if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof(edst))){
  297                         m2 = m_copy(m, 0, (int)M_COPYALL);
  298                         m2->m_pkthdr.rcvif = ifp;
  299                         schednetisr(NETISR_NS);
  300                         inq = &nsintrq;
  301                         s = splimp();
  302                         if (IF_QFULL(inq)) {
  303                                 IF_DROP(inq);
  304                                 m_freem(m2);
  305                         } else
  306                                 IF_ENQUEUE(inq, m2);
  307                         splx(s);
  308                 }
  309                 /* If broadcasting on a simplex interface, loopback a copy */
  310                 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)){
  311                         mcopy = m_copy(m, 0, (int)M_COPYALL);
  312                 }
  313                 break;
  314 #endif /* NS */
  315 #ifdef  ISO
  316         case AF_ISO: {
  317                 int     snpalen;
  318                 struct  llc *l;
  319                 register struct sockaddr_dl *sdl;
  320 
  321                 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
  322                     sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
  323                         bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
  324                 } else if (error =
  325                             iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
  326                                             (char *)edst, &snpalen))
  327                         goto bad; /* Not Resolved */
  328                 /* If broadcasting on a simplex interface, loopback a copy */
  329                 if (*edst & 1)
  330                         m->m_flags |= (M_BCAST|M_MCAST);
  331                 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
  332                     (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
  333                         M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
  334                         if (mcopy) {
  335                                 eh = mtod(mcopy, struct ether_header *);
  336                                 bcopy((caddr_t)edst,
  337                                       (caddr_t)eh->ether_dhost, sizeof (edst));
  338                                 bcopy((caddr_t)ac->ac_enaddr,
  339                                       (caddr_t)eh->ether_shost, sizeof (edst));
  340                         }
  341                 }
  342                 M_PREPEND(m, 3, M_DONTWAIT);
  343                 if (m == NULL)
  344                         return (0);
  345                 type = htons(m->m_pkthdr.len);
  346                 l = mtod(m, struct llc *);
  347                 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
  348                 l->llc_control = LLC_UI;
  349                 len += 3;
  350                 IFDEBUG(D_ETHER)
  351                         int i;
  352                         printf("unoutput: sending pkt to: ");
  353                         for (i=0; i<6; i++)
  354                                 printf("%x ", edst[i] & 0xff);
  355                         printf("\n");
  356                 ENDDEBUG
  357                 } break;
  358 #endif /* ISO */
  359 #ifdef  LLC
  360 /*      case AF_NSAP: */
  361         case AF_CCITT: {
  362                 register struct sockaddr_dl *sdl =
  363                         (struct sockaddr_dl *) rt -> rt_gateway;
  364 
  365                 if (sdl && sdl->sdl_family == AF_LINK
  366                     && sdl->sdl_alen > 0) {
  367                         bcopy(LLADDR(sdl), (char *)edst,
  368                                 sizeof(edst));
  369                 } else goto bad; /* Not a link interface ? Funny ... */
  370                 if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
  371                     (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
  372                         M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
  373                         if (mcopy) {
  374                                 eh = mtod(mcopy, struct ether_header *);
  375                                 bcopy((caddr_t)edst,
  376                                       (caddr_t)eh->ether_dhost, sizeof (edst));
  377                                 bcopy((caddr_t)ac->ac_enaddr,
  378                                       (caddr_t)eh->ether_shost, sizeof (edst));
  379                         }
  380                 }
  381                 type = htons(m->m_pkthdr.len);
  382 #ifdef LLC_DEBUG
  383                 {
  384                         int i;
  385                         register struct llc *l = mtod(m, struct llc *);
  386 
  387                         printf("ether_output: sending LLC2 pkt to: ");
  388                         for (i=0; i<6; i++)
  389                                 printf("%x ", edst[i] & 0xff);
  390                         printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
  391                                type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff,
  392                                l->llc_control & 0xff);
  393 
  394                 }
  395 #endif /* LLC_DEBUG */
  396                 } break;
  397 #endif /* LLC */
  398 
  399         case AF_UNSPEC:
  400                 eh = (struct ether_header *)dst->sa_data;
  401                 (void)memcpy(edst, eh->ether_dhost, sizeof (edst));
  402                 type = eh->ether_type;
  403                 break;
  404 
  405         default:
  406                 printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
  407                         dst->sa_family);
  408                 senderr(EAFNOSUPPORT);
  409         }
  410 
  411 
  412         if (mcopy)
  413                 (void) looutput(ifp, mcopy, dst, rt);
  414         /*
  415          * Add local net header.  If no space in first mbuf,
  416          * allocate another.
  417          */
  418         M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
  419         if (m == 0)
  420                 senderr(ENOBUFS);
  421         eh = mtod(m, struct ether_header *);
  422         (void)memcpy(&eh->ether_type, &type,
  423                 sizeof(eh->ether_type));
  424         (void)memcpy(eh->ether_dhost, edst, sizeof (edst));
  425         (void)memcpy(eh->ether_shost, ac->ac_enaddr,
  426             sizeof(eh->ether_shost));
  427 #ifdef BRIDGE
  428         if (do_bridge) {
  429             struct ifnet *old_ifp = ifp ;
  430             struct mbuf *m0 = m ;
  431             if (m->m_pkthdr.rcvif )
  432                 m->m_pkthdr.rcvif = NULL ;
  433             ifp = bridge_dst_lookup(m);
  434             bdg_forward(&m0, ifp);
  435             if (m0)
  436                 m_freem(m0);
  437             return 0 ;
  438         }
  439 #endif
  440         s = splimp();
  441         /*
  442          * Queue message on interface, and start output if interface
  443          * not yet active.
  444          */
  445         if (IF_QFULL(&ifp->if_snd)) {
  446                 IF_DROP(&ifp->if_snd);
  447                 splx(s);
  448                 senderr(ENOBUFS);
  449         }
  450         IF_ENQUEUE(&ifp->if_snd, m);
  451         if ((ifp->if_flags & IFF_OACTIVE) == 0)
  452                 (*ifp->if_start)(ifp);
  453         splx(s);
  454         ifp->if_obytes += len + sizeof (struct ether_header);
  455         if (m->m_flags & M_MCAST)
  456                 ifp->if_omcasts++;
  457         return (error);
  458 
  459 bad:
  460         if (m)
  461                 m_freem(m);
  462         return (error);
  463 }
  464 
  465 /*
  466  * Process a received Ethernet packet;
  467  * the packet is in the mbuf chain m without
  468  * the ether header, which is provided separately.
  469  */
  470 void
  471 ether_input(ifp, eh, m)
  472         struct ifnet *ifp;
  473         register struct ether_header *eh;
  474         struct mbuf *m;
  475 {
  476         register struct ifqueue *inq;
  477         u_short ether_type, *checksum;
  478         int s;
  479 #if defined (ISO) || defined (LLC) || defined(NETATALK)
  480         register struct llc *l;
  481 #endif
  482 
  483         if ((ifp->if_flags & IFF_UP) == 0) {
  484                 m_freem(m);
  485                 return;
  486         }
  487         ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
  488         if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
  489             sizeof(etherbroadcastaddr)) == 0)
  490                 m->m_flags |= M_BCAST;
  491         else if (eh->ether_dhost[0] & 1)
  492                 m->m_flags |= M_MCAST;
  493         if (m->m_flags & (M_BCAST|M_MCAST))
  494                 ifp->if_imcasts++;
  495 
  496         ether_type = ntohs(eh->ether_type);
  497 
  498         switch (ether_type) {
  499 #ifdef INET
  500         case ETHERTYPE_IP:
  501                 schednetisr(NETISR_IP);
  502                 inq = &ipintrq;
  503                 break;
  504 
  505         case ETHERTYPE_ARP:
  506                 schednetisr(NETISR_ARP);
  507                 inq = &arpintrq;
  508                 break;
  509 #endif
  510 #ifdef IPX
  511         case ETHERTYPE_IPX:
  512                 schednetisr(NETISR_IPX);
  513                 inq = &ipxintrq;
  514                 break;
  515 #endif
  516 #ifdef NS
  517         case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
  518                 schednetisr(NETISR_NS);
  519                 inq = &nsintrq;
  520                 break;
  521 
  522 #endif /* NS */
  523 #ifdef NETATALK
  524         case ETHERTYPE_AT:
  525                 schednetisr(NETISR_ATALK);
  526                 inq = &atintrq1;
  527                 break;
  528         case ETHERTYPE_AARP:
  529                 /* probably this should be done with a NETISR as well */
  530                 aarpinput((struct arpcom *)ifp, m); /* XXX */
  531                 return;
  532 #endif NETATALK
  533         default:
  534 #ifdef NS
  535                 checksum = mtod(m, ushort *);
  536                 /* Novell 802.3 */
  537                 if ((ether_type <= ETHERMTU) &&
  538                         ((*checksum == 0xffff) || (*checksum == 0xE0E0))){
  539                         if(*checksum == 0xE0E0) {
  540                                 m->m_pkthdr.len -= 3;
  541                                 m->m_len -= 3;
  542                                 m->m_data += 3;
  543                         }
  544                                 schednetisr(NETISR_NS);
  545                                 inq = &nsintrq;
  546                                 break;
  547                 }
  548 #endif /* NS */
  549 #if defined (ISO) || defined (LLC) || defined(NETATALK)
  550                 if (ether_type > ETHERMTU)
  551                         goto dropanyway;
  552                 l = mtod(m, struct llc *);
  553                 switch (l->llc_dsap) {
  554 #ifdef NETATALK
  555                 case LLC_SNAP_LSAP:
  556                     switch (l->llc_control) {
  557                     case LLC_UI:
  558                         if (l->llc_ssap != LLC_SNAP_LSAP)
  559                             goto dropanyway;
  560         
  561                         if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code,
  562                                    sizeof(at_org_code)) == 0 &&
  563                              ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) {
  564                             inq = &atintrq2;
  565                             m_adj( m, sizeof( struct llc ));
  566                             schednetisr(NETISR_ATALK);
  567                             break;
  568                         }
  569 
  570                         if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code,
  571                                    sizeof(aarp_org_code)) == 0 &&
  572                              ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) {
  573                             m_adj( m, sizeof( struct llc ));
  574                             aarpinput((struct arpcom *)ifp, m); /* XXX */
  575                             return;
  576                         }
  577                 
  578                     default:
  579                         goto dropanyway;
  580                     }
  581                     break;
  582 #endif NETATALK 
  583 #ifdef  ISO
  584                 case LLC_ISO_LSAP:
  585                         switch (l->llc_control) {
  586                         case LLC_UI:
  587                                 /* LLC_UI_P forbidden in class 1 service */
  588                                 if ((l->llc_dsap == LLC_ISO_LSAP) &&
  589                                     (l->llc_ssap == LLC_ISO_LSAP)) {
  590                                         /* LSAP for ISO */
  591                                         if (m->m_pkthdr.len > ether_type)
  592                                                 m_adj(m, ether_type - m->m_pkthdr.len);
  593                                         m->m_data += 3;         /* XXX */
  594                                         m->m_len -= 3;          /* XXX */
  595                                         m->m_pkthdr.len -= 3;   /* XXX */
  596                                         M_PREPEND(m, sizeof *eh, M_DONTWAIT);
  597                                         if (m == 0)
  598                                                 return;
  599                                         *mtod(m, struct ether_header *) = *eh;
  600                                         IFDEBUG(D_ETHER)
  601                                                 printf("clnp packet");
  602                                         ENDDEBUG
  603                                         schednetisr(NETISR_ISO);
  604                                         inq = &clnlintrq;
  605                                         break;
  606                                 }
  607                                 goto dropanyway;
  608 
  609                         case LLC_XID:
  610                         case LLC_XID_P:
  611                                 if(m->m_len < 6)
  612                                         goto dropanyway;
  613                                 l->llc_window = 0;
  614                                 l->llc_fid = 9;
  615                                 l->llc_class = 1;
  616                                 l->llc_dsap = l->llc_ssap = 0;
  617                                 /* Fall through to */
  618                         case LLC_TEST:
  619                         case LLC_TEST_P:
  620                         {
  621                                 struct sockaddr sa;
  622                                 register struct ether_header *eh2;
  623                                 int i;
  624                                 u_char c = l->llc_dsap;
  625 
  626                                 l->llc_dsap = l->llc_ssap;
  627                                 l->llc_ssap = c;
  628                                 if (m->m_flags & (M_BCAST | M_MCAST))
  629                                         bcopy((caddr_t)ac->ac_enaddr,
  630                                               (caddr_t)eh->ether_dhost, 6);
  631                                 sa.sa_family = AF_UNSPEC;
  632                                 sa.sa_len = sizeof(sa);
  633                                 eh2 = (struct ether_header *)sa.sa_data;
  634                                 for (i = 0; i < 6; i++) {
  635                                         eh2->ether_shost[i] = c = eh->ether_dhost[i];
  636                                         eh2->ether_dhost[i] =
  637                                                 eh->ether_dhost[i] = eh->ether_shost[i];
  638                                         eh->ether_shost[i] = c;
  639                                 }
  640                                 ifp->if_output(ifp, m, &sa, NULL);
  641                                 return;
  642                         }
  643                         default:
  644                                 m_freem(m);
  645                                 return;
  646                         }
  647                         break;
  648 #endif /* ISO */
  649 #ifdef LLC
  650                 case LLC_X25_LSAP:
  651                 {
  652                         if (m->m_pkthdr.len > ether_type)
  653                                 m_adj(m, ether_type - m->m_pkthdr.len);
  654                         M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
  655                         if (m == 0)
  656                                 return;
  657                         if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP,
  658                                             eh->ether_dhost, LLC_X25_LSAP, 6,
  659                                             mtod(m, struct sdl_hdr *)))
  660                                 panic("ETHER cons addr failure");
  661                         mtod(m, struct sdl_hdr *)->sdlhdr_len = ether_type;
  662 #ifdef LLC_DEBUG
  663                                 printf("llc packet\n");
  664 #endif /* LLC_DEBUG */
  665                         schednetisr(NETISR_CCITT);
  666                         inq = &llcintrq;
  667                         break;
  668                 }
  669 #endif /* LLC */
  670                 dropanyway:
  671                 default:
  672                         m_freem(m);
  673                         return;
  674                 }
  675 #else /* ISO || LLC || NETATALK */
  676             m_freem(m);
  677             return;
  678 #endif /* ISO || LLC || NETATALK */
  679         }
  680 
  681         s = splimp();
  682         if (IF_QFULL(inq)) {
  683                 IF_DROP(inq);
  684                 m_freem(m);
  685         } else
  686                 IF_ENQUEUE(inq, m);
  687         splx(s);
  688 }
  689 
  690 /*
  691  * Perform common duties while attaching to interface list
  692  */
  693 void
  694 ether_ifattach(ifp)
  695         register struct ifnet *ifp;
  696 {
  697         register struct ifaddr *ifa;
  698         register struct sockaddr_dl *sdl;
  699 
  700         ifp->if_type = IFT_ETHER;
  701         ifp->if_addrlen = 6;
  702         ifp->if_hdrlen = 14;
  703         ifp->if_mtu = ETHERMTU;
  704         if (ifp->if_baudrate == 0)
  705             ifp->if_baudrate = 10000000;
  706         for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
  707                 if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
  708                     sdl->sdl_family == AF_LINK) {
  709                         sdl->sdl_type = IFT_ETHER;
  710                         sdl->sdl_alen = ifp->if_addrlen;
  711                         bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
  712                               LLADDR(sdl), ifp->if_addrlen);
  713                         break;
  714                 }
  715 }
  716 
  717 static u_char ether_ipmulticast_min[6] = 
  718         { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
  719 static u_char ether_ipmulticast_max[6] =
  720         { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
  721 /*
  722  * Add an Ethernet multicast address or range of addresses to the list for a
  723  * given interface.
  724  */
  725 int
  726 ether_addmulti(ifr, ac)
  727         struct ifreq *ifr;
  728         register struct arpcom *ac;
  729 {
  730         register struct ether_multi *enm;
  731         struct sockaddr_in *sin;
  732         u_char addrlo[6];
  733         u_char addrhi[6];
  734         int set_allmulti = 0;
  735         int s = splimp();
  736 
  737         switch (ifr->ifr_addr.sa_family) {
  738 
  739         case AF_UNSPEC:
  740                 bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
  741                 bcopy(addrlo, addrhi, 6);
  742                 break;
  743 
  744 #ifdef INET
  745         case AF_INET:
  746                 sin = (struct sockaddr_in *)&(ifr->ifr_addr);
  747                 if (sin->sin_addr.s_addr == INADDR_ANY) {
  748                         /*
  749                          * An IP address of INADDR_ANY means listen to all
  750                          * of the Ethernet multicast addresses used for IP.
  751                          * (This is for the sake of IP multicast routers.)
  752                          */
  753                         bcopy(ether_ipmulticast_min, addrlo, 6);
  754                         bcopy(ether_ipmulticast_max, addrhi, 6);
  755                       set_allmulti = 1;
  756                 }
  757                 else {
  758                         ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
  759                         bcopy(addrlo, addrhi, 6);
  760                 }
  761                 break;
  762 #endif
  763 
  764         default:
  765                 splx(s);
  766                 return (EAFNOSUPPORT);
  767         }
  768 
  769         /*
  770          * Verify that we have valid Ethernet multicast addresses.
  771          */
  772         if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
  773                 splx(s);
  774                 return (EINVAL);
  775         }
  776         /*
  777          * See if the address range is already in the list.
  778          */
  779         ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
  780         if (enm != NULL) {
  781                 /*
  782                  * Found it; just increment the reference count.
  783                  */
  784                 ++enm->enm_refcount;
  785                 splx(s);
  786                 return (0);
  787         }
  788         /*
  789          * New address or range; malloc a new multicast record
  790          * and link it into the interface's multicast list.
  791          */
  792         enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);
  793         if (enm == NULL) {
  794                 splx(s);
  795                 return (ENOBUFS);
  796         }
  797         bcopy(addrlo, enm->enm_addrlo, 6);
  798         bcopy(addrhi, enm->enm_addrhi, 6);
  799         enm->enm_ac = ac;
  800         enm->enm_refcount = 1;
  801         enm->enm_next = ac->ac_multiaddrs;
  802         ac->ac_multiaddrs = enm;
  803         ac->ac_multicnt++;
  804         splx(s);
  805         if (set_allmulti)
  806                 ac->ac_if.if_flags |= IFF_ALLMULTI;
  807 
  808         /*
  809          * Return ENETRESET to inform the driver that the list has changed
  810          * and its reception filter should be adjusted accordingly.
  811          */
  812         return (ENETRESET);
  813 }
  814 
  815 /*
  816  * Delete a multicast address record.
  817  */
  818 int
  819 ether_delmulti(ifr, ac)
  820         struct ifreq *ifr;
  821         register struct arpcom *ac;
  822 {
  823         register struct ether_multi *enm;
  824         register struct ether_multi **p;
  825         struct sockaddr_in *sin;
  826         u_char addrlo[6];
  827         u_char addrhi[6];
  828       int unset_allmulti = 0;
  829         int s = splimp();
  830 
  831         switch (ifr->ifr_addr.sa_family) {
  832 
  833         case AF_UNSPEC:
  834                 bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
  835                 bcopy(addrlo, addrhi, 6);
  836                 break;
  837 
  838 #ifdef INET
  839         case AF_INET:
  840                 sin = (struct sockaddr_in *)&(ifr->ifr_addr);
  841                 if (sin->sin_addr.s_addr == INADDR_ANY) {
  842                         /*
  843                          * An IP address of INADDR_ANY means stop listening
  844                          * to the range of Ethernet multicast addresses used
  845                          * for IP.
  846                          */
  847                         bcopy(ether_ipmulticast_min, addrlo, 6);
  848                         bcopy(ether_ipmulticast_max, addrhi, 6);
  849                       unset_allmulti = 1;
  850                 }
  851                 else {
  852                         ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
  853                         bcopy(addrlo, addrhi, 6);
  854                 }
  855                 break;
  856 #endif
  857 
  858         default:
  859                 splx(s);
  860                 return (EAFNOSUPPORT);
  861         }
  862 
  863         /*
  864          * Look up the address in our list.
  865          */
  866         ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
  867         if (enm == NULL) {
  868                 splx(s);
  869                 return (ENXIO);
  870         }
  871         if (--enm->enm_refcount != 0) {
  872                 /*
  873                  * Still some claims to this record.
  874                  */
  875                 splx(s);
  876                 return (0);
  877         }
  878         /*
  879          * No remaining claims to this record; unlink and free it.
  880          */
  881         for (p = &enm->enm_ac->ac_multiaddrs;
  882              *p != enm;
  883              p = &(*p)->enm_next)
  884                 continue;
  885         *p = (*p)->enm_next;
  886         free(enm, M_IFMADDR);
  887         ac->ac_multicnt--;
  888         splx(s);
  889       if (unset_allmulti)
  890               ac->ac_if.if_flags &= ~IFF_ALLMULTI;
  891 
  892         /*
  893          * Return ENETRESET to inform the driver that the list has changed
  894          * and its reception filter should be adjusted accordingly.
  895          */
  896         return (ENETRESET);
  897 }
  898 
  899 SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
  900 
  901 int
  902 ether_ioctl(struct ifnet *ifp, int command, caddr_t data)
  903 {
  904         struct ifaddr *ifa = (struct ifaddr *) data;
  905         struct ifreq *ifr = (struct ifreq *) data;
  906         int error = 0;
  907 
  908         switch (command) {
  909         case SIOCSIFADDR:
  910                 ifp->if_flags |= IFF_UP;
  911 
  912                 switch (ifa->ifa_addr->sa_family) {
  913 #ifdef INET
  914                 case AF_INET:
  915                         ifp->if_init(ifp->if_softc);    /* before arpwhohas */
  916                         arp_ifinit((struct arpcom *)ifp, ifa);
  917                         break;
  918 #endif
  919 #ifdef IPX
  920                 /*
  921                  * XXX - This code is probably wrong
  922                  */
  923                 case AF_IPX:
  924                         {
  925                         register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
  926                         struct arpcom *ac = (struct arpcom *) (ifp->if_softc);
  927 
  928                         if (ipx_nullhost(*ina))
  929                                 ina->x_host =
  930                                     *(union ipx_host *) 
  931                                     ac->ac_enaddr;
  932                         else {
  933                                 bcopy((caddr_t) ina->x_host.c_host,
  934                                       (caddr_t) ac->ac_enaddr,
  935                                       sizeof(ac->ac_enaddr));
  936                         }
  937 
  938                         /*
  939                          * Set new address
  940                          */
  941                         ifp->if_init(ifp->if_softc);
  942                         break;
  943                         }
  944 #endif
  945 #ifdef NS
  946                 /*
  947                  * XXX - This code is probably wrong
  948                  */
  949                 case AF_NS:
  950                 {
  951                         register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
  952                         struct arpcom *ac = (struct arpcom *) (ifp->if_softc);
  953 
  954                         if (ns_nullhost(*ina))
  955                                 ina->x_host =
  956                                     *(union ns_host *) (ac->ac_enaddr);
  957                         else {
  958                                 bcopy((caddr_t) ina->x_host.c_host,
  959                                       (caddr_t) ac->ac_enaddr,
  960                                       sizeof(ac->ac_enaddr));
  961                         }
  962 
  963                         /*
  964                          * Set new address
  965                          */
  966                         ifp->if_init(ifp->if_softc);
  967                         break;
  968                 }
  969 #endif
  970                 default:
  971                         ifp->if_init(ifp->if_softc);
  972                         break;
  973                 }
  974                 break;
  975 
  976         case SIOCGIFADDR:
  977                 {
  978                         struct sockaddr *sa;
  979 
  980                         sa = (struct sockaddr *) & ifr->ifr_data;
  981                         bcopy(((struct arpcom *)ifp->if_softc)->ac_enaddr,
  982                               (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
  983                 }
  984                 break;
  985 
  986         case SIOCSIFMTU:
  987                 /*
  988                  * Set the interface MTU.
  989                  */
  990                 if (ifr->ifr_mtu > ETHERMTU) {
  991                         error = EINVAL;
  992                 } else {
  993                         ifp->if_mtu = ifr->ifr_mtu;
  994                 }
  995                 break;
  996         }
  997         return (error);
  998 }

Cache object: 1f49a8c2f423dc3904c959cb7feb760a


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