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  * 4. Neither the name of the University nor the names of its contributors
   14  *    may be used to endorse or promote products derived from this software
   15  *    without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  *      @(#)if_ethersubr.c      8.1 (Berkeley) 6/10/93
   30  * $FreeBSD: releng/6.0/sys/net/if_ethersubr.c 151571 2005-10-23 02:37:28Z thompsa $
   31  */
   32 
   33 #include "opt_atalk.h"
   34 #include "opt_inet.h"
   35 #include "opt_inet6.h"
   36 #include "opt_ipx.h"
   37 #include "opt_bdg.h"
   38 #include "opt_mac.h"
   39 #include "opt_netgraph.h"
   40 #include "opt_carp.h"
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/mac.h>
   46 #include <sys/malloc.h>
   47 #include <sys/module.h>
   48 #include <sys/mbuf.h>
   49 #include <sys/random.h>
   50 #include <sys/socket.h>
   51 #include <sys/sockio.h>
   52 #include <sys/sysctl.h>
   53 
   54 #include <net/if.h>
   55 #include <net/if_arp.h>
   56 #include <net/netisr.h>
   57 #include <net/route.h>
   58 #include <net/if_llc.h>
   59 #include <net/if_dl.h>
   60 #include <net/if_types.h>
   61 #include <net/bpf.h>
   62 #include <net/ethernet.h>
   63 #include <net/bridge.h>
   64 #include <net/if_bridgevar.h>
   65 #include <net/if_vlan_var.h>
   66 
   67 #if defined(INET) || defined(INET6)
   68 #include <netinet/in.h>
   69 #include <netinet/in_var.h>
   70 #include <netinet/if_ether.h>
   71 #include <netinet/ip_fw.h>
   72 #include <netinet/ip_dummynet.h>
   73 #endif
   74 #ifdef INET6
   75 #include <netinet6/nd6.h>
   76 #endif
   77 
   78 #ifdef DEV_CARP
   79 #include <netinet/ip_carp.h>
   80 #endif
   81 
   82 #ifdef IPX
   83 #include <netipx/ipx.h>
   84 #include <netipx/ipx_if.h>
   85 #endif
   86 int (*ef_inputp)(struct ifnet*, struct ether_header *eh, struct mbuf *m);
   87 int (*ef_outputp)(struct ifnet *ifp, struct mbuf **mp,
   88                 struct sockaddr *dst, short *tp, int *hlen);
   89 
   90 #ifdef NETATALK
   91 #include <netatalk/at.h>
   92 #include <netatalk/at_var.h>
   93 #include <netatalk/at_extern.h>
   94 
   95 #define llc_snap_org_code llc_un.type_snap.org_code
   96 #define llc_snap_ether_type llc_un.type_snap.ether_type
   97 
   98 extern u_char   at_org_code[3];
   99 extern u_char   aarp_org_code[3];
  100 #endif /* NETATALK */
  101 
  102 /* netgraph node hooks for ng_ether(4) */
  103 void    (*ng_ether_input_p)(struct ifnet *ifp, struct mbuf **mp);
  104 void    (*ng_ether_input_orphan_p)(struct ifnet *ifp, struct mbuf *m);
  105 int     (*ng_ether_output_p)(struct ifnet *ifp, struct mbuf **mp);
  106 void    (*ng_ether_attach_p)(struct ifnet *ifp);
  107 void    (*ng_ether_detach_p)(struct ifnet *ifp);
  108 
  109 void    (*vlan_input_p)(struct ifnet *, struct mbuf *);
  110 
  111 /* bridge support */
  112 int do_bridge;
  113 bridge_in_t *bridge_in_ptr;
  114 bdg_forward_t *bdg_forward_ptr;
  115 bdgtakeifaces_t *bdgtakeifaces_ptr;
  116 struct bdg_softc *ifp2sc;
  117 
  118 struct mbuf *(*bridge_input_p)(struct ifnet *, struct mbuf *); 
  119 int     (*bridge_output_p)(struct ifnet *, struct mbuf *, 
  120                 struct sockaddr *, struct rtentry *);
  121 void    (*bridge_dn_p)(struct mbuf *, struct ifnet *);
  122 void    (*bridge_detach_p)(struct ifnet *ifp);
  123 
  124 static const u_char etherbroadcastaddr[ETHER_ADDR_LEN] =
  125                         { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  126 
  127 static  int ether_resolvemulti(struct ifnet *, struct sockaddr **,
  128                 struct sockaddr *);
  129 
  130 /* XXX: should be in an arp support file, not here */
  131 MALLOC_DEFINE(M_ARPCOM, "arpcom", "802.* interface internals");
  132 
  133 #define senderr(e) do { error = (e); goto bad;} while (0)
  134 
  135 #if defined(INET) || defined(INET6)
  136 int
  137 ether_ipfw_chk(struct mbuf **m0, struct ifnet *dst,
  138         struct ip_fw **rule, int shared);
  139 static int ether_ipfw;
  140 #endif
  141 
  142 /*
  143  * Ethernet output routine.
  144  * Encapsulate a packet of type family for the local net.
  145  * Use trailer local net encapsulation if enough data in first
  146  * packet leaves a multiple of 512 bytes of data in remainder.
  147  * Assumes that ifp is actually pointer to arpcom structure.
  148  */
  149 int
  150 ether_output(struct ifnet *ifp, struct mbuf *m,
  151         struct sockaddr *dst, struct rtentry *rt0)
  152 {
  153         short type;
  154         int error, hdrcmplt = 0;
  155         u_char esrc[ETHER_ADDR_LEN], edst[ETHER_ADDR_LEN];
  156         struct ether_header *eh;
  157         int loop_copy = 0;
  158         int hlen;       /* link layer header length */
  159 
  160 #ifdef MAC
  161         error = mac_check_ifnet_transmit(ifp, m);
  162         if (error)
  163                 senderr(error);
  164 #endif
  165 
  166         if (ifp->if_flags & IFF_MONITOR)
  167                 senderr(ENETDOWN);
  168         if (!((ifp->if_flags & IFF_UP) &&
  169             (ifp->if_drv_flags & IFF_DRV_RUNNING)))
  170                 senderr(ENETDOWN);
  171 
  172         hlen = ETHER_HDR_LEN;
  173         switch (dst->sa_family) {
  174 #ifdef INET
  175         case AF_INET:
  176                 error = arpresolve(ifp, rt0, m, dst, edst);
  177                 if (error)
  178                         return (error == EWOULDBLOCK ? 0 : error);
  179                 type = htons(ETHERTYPE_IP);
  180                 break;
  181         case AF_ARP:
  182         {
  183                 struct arphdr *ah;
  184                 ah = mtod(m, struct arphdr *);
  185                 ah->ar_hrd = htons(ARPHRD_ETHER);
  186 
  187                 loop_copy = -1; /* if this is for us, don't do it */
  188 
  189                 switch(ntohs(ah->ar_op)) {
  190                 case ARPOP_REVREQUEST:
  191                 case ARPOP_REVREPLY:
  192                         type = htons(ETHERTYPE_REVARP);
  193                         break;
  194                 case ARPOP_REQUEST:
  195                 case ARPOP_REPLY:
  196                 default:
  197                         type = htons(ETHERTYPE_ARP);
  198                         break;
  199                 }
  200 
  201                 if (m->m_flags & M_BCAST)
  202                         bcopy(ifp->if_broadcastaddr, edst, ETHER_ADDR_LEN);
  203                 else
  204                         bcopy(ar_tha(ah), edst, ETHER_ADDR_LEN);
  205 
  206         }
  207         break;
  208 #endif
  209 #ifdef INET6
  210         case AF_INET6:
  211                 error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst);
  212                 if (error)
  213                         return error;
  214                 type = htons(ETHERTYPE_IPV6);
  215                 break;
  216 #endif
  217 #ifdef IPX
  218         case AF_IPX:
  219                 if (ef_outputp) {
  220                     error = ef_outputp(ifp, &m, dst, &type, &hlen);
  221                     if (error)
  222                         goto bad;
  223                 } else
  224                     type = htons(ETHERTYPE_IPX);
  225                 bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
  226                     (caddr_t)edst, sizeof (edst));
  227                 break;
  228 #endif
  229 #ifdef NETATALK
  230         case AF_APPLETALK:
  231           {
  232             struct at_ifaddr *aa;
  233 
  234             if ((aa = at_ifawithnet((struct sockaddr_at *)dst)) == NULL)
  235                     senderr(EHOSTUNREACH); /* XXX */
  236             if (!aarpresolve(ifp, m, (struct sockaddr_at *)dst, edst))
  237                     return (0);
  238             /*
  239              * In the phase 2 case, need to prepend an mbuf for the llc header.
  240              */
  241             if ( aa->aa_flags & AFA_PHASE2 ) {
  242                 struct llc llc;
  243 
  244                 M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT);
  245                 if (m == NULL)
  246                         senderr(ENOBUFS);
  247                 llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
  248                 llc.llc_control = LLC_UI;
  249                 bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code));
  250                 llc.llc_snap_ether_type = htons( ETHERTYPE_AT );
  251                 bcopy(&llc, mtod(m, caddr_t), LLC_SNAPFRAMELEN);
  252                 type = htons(m->m_pkthdr.len);
  253                 hlen = LLC_SNAPFRAMELEN + ETHER_HDR_LEN;
  254             } else {
  255                 type = htons(ETHERTYPE_AT);
  256             }
  257             break;
  258           }
  259 #endif /* NETATALK */
  260 
  261         case pseudo_AF_HDRCMPLT:
  262                 hdrcmplt = 1;
  263                 eh = (struct ether_header *)dst->sa_data;
  264                 (void)memcpy(esrc, eh->ether_shost, sizeof (esrc));
  265                 /* FALLTHROUGH */
  266 
  267         case AF_UNSPEC:
  268                 loop_copy = -1; /* if this is for us, don't do it */
  269                 eh = (struct ether_header *)dst->sa_data;
  270                 (void)memcpy(edst, eh->ether_dhost, sizeof (edst));
  271                 type = eh->ether_type;
  272                 break;
  273 
  274         default:
  275                 if_printf(ifp, "can't handle af%d\n", dst->sa_family);
  276                 senderr(EAFNOSUPPORT);
  277         }
  278 
  279         /*
  280          * Add local net header.  If no space in first mbuf,
  281          * allocate another.
  282          */
  283         M_PREPEND(m, ETHER_HDR_LEN, M_DONTWAIT);
  284         if (m == NULL)
  285                 senderr(ENOBUFS);
  286         eh = mtod(m, struct ether_header *);
  287         (void)memcpy(&eh->ether_type, &type,
  288                 sizeof(eh->ether_type));
  289         (void)memcpy(eh->ether_dhost, edst, sizeof (edst));
  290         if (hdrcmplt)
  291                 (void)memcpy(eh->ether_shost, esrc,
  292                         sizeof(eh->ether_shost));
  293         else
  294                 (void)memcpy(eh->ether_shost, IFP2ENADDR(ifp),
  295                         sizeof(eh->ether_shost));
  296 
  297        /*
  298         * Bridges require special output handling.
  299         */
  300         if (ifp->if_bridge) {
  301                 BRIDGE_OUTPUT(ifp, m, error);
  302                 return (error);
  303         }
  304 
  305         /*
  306          * If a simplex interface, and the packet is being sent to our
  307          * Ethernet address or a broadcast address, loopback a copy.
  308          * XXX To make a simplex device behave exactly like a duplex
  309          * device, we should copy in the case of sending to our own
  310          * ethernet address (thus letting the original actually appear
  311          * on the wire). However, we don't do that here for security
  312          * reasons and compatibility with the original behavior.
  313          */
  314         if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1) &&
  315             m_tag_find(m, PACKET_TAG_PF_ROUTED, NULL) == NULL) {
  316                 int csum_flags = 0;
  317 
  318                 if (m->m_pkthdr.csum_flags & CSUM_IP)
  319                         csum_flags |= (CSUM_IP_CHECKED|CSUM_IP_VALID);
  320                 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA)
  321                         csum_flags |= (CSUM_DATA_VALID|CSUM_PSEUDO_HDR);
  322 
  323                 if ((m->m_flags & M_BCAST) || (loop_copy > 0)) {
  324                         struct mbuf *n;
  325 
  326                         if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
  327                                 n->m_pkthdr.csum_flags |= csum_flags;
  328                                 if (csum_flags & CSUM_DATA_VALID)
  329                                         n->m_pkthdr.csum_data = 0xffff;
  330                                 (void)if_simloop(ifp, n, dst->sa_family, hlen);
  331                         } else
  332                                 ifp->if_iqdrops++;
  333                 } else if (bcmp(eh->ether_dhost, eh->ether_shost,
  334                                 ETHER_ADDR_LEN) == 0) {
  335                         m->m_pkthdr.csum_flags |= csum_flags;
  336                         if (csum_flags & CSUM_DATA_VALID)
  337                                 m->m_pkthdr.csum_data = 0xffff;
  338                         (void) if_simloop(ifp, m, dst->sa_family, hlen);
  339                         return (0);     /* XXX */
  340                 }
  341         }
  342 
  343 #ifdef DEV_CARP
  344         if (ifp->if_carp &&
  345             (error = carp_output(ifp, m, dst, NULL)))
  346                 goto bad;
  347 #endif
  348 
  349         /* Handle ng_ether(4) processing, if any */
  350         if (IFP2AC(ifp)->ac_netgraph != NULL) {
  351                 if ((error = (*ng_ether_output_p)(ifp, &m)) != 0) {
  352 bad:                    if (m != NULL)
  353                                 m_freem(m);
  354                         return (error);
  355                 }
  356                 if (m == NULL)
  357                         return (0);
  358         }
  359 
  360         /* Continue with link-layer output */
  361         return ether_output_frame(ifp, m);
  362 }
  363 
  364 /*
  365  * Ethernet link layer output routine to send a raw frame to the device.
  366  *
  367  * This assumes that the 14 byte Ethernet header is present and contiguous
  368  * in the first mbuf (if BRIDGE'ing).
  369  */
  370 int
  371 ether_output_frame(struct ifnet *ifp, struct mbuf *m)
  372 {
  373 #if defined(INET) || defined(INET6)
  374         struct ip_fw *rule = ip_dn_claim_rule(m);
  375 #else
  376         void *rule = NULL;
  377 #endif
  378         int error;
  379 
  380         if (rule == NULL && BDG_ACTIVE(ifp)) {
  381                 /*
  382                  * Beware, the bridge code notices the null rcvif and
  383                  * uses that identify that it's being called from
  384                  * ether_output as opposd to ether_input.  Yech.
  385                  */
  386                 m->m_pkthdr.rcvif = NULL;
  387                 m = bdg_forward_ptr(m, ifp);
  388                 if (m != NULL)
  389                         m_freem(m);
  390                 return (0);
  391         }
  392 #if defined(INET) || defined(INET6)
  393         if (IPFW_LOADED && ether_ipfw != 0) {
  394                 if (ether_ipfw_chk(&m, ifp, &rule, 0) == 0) {
  395                         if (m) {
  396                                 m_freem(m);
  397                                 return EACCES;  /* pkt dropped */
  398                         } else
  399                                 return 0;       /* consumed e.g. in a pipe */
  400                 }
  401         }
  402 #endif
  403 
  404         /*
  405          * Queue message on interface, update output statistics if
  406          * successful, and start output if interface not yet active.
  407          */
  408         IFQ_HANDOFF(ifp, m, error);
  409         return (error);
  410 }
  411 
  412 #if defined(INET) || defined(INET6)
  413 /*
  414  * ipfw processing for ethernet packets (in and out).
  415  * The second parameter is NULL from ether_demux, and ifp from
  416  * ether_output_frame. This section of code could be used from
  417  * bridge.c as well as long as we use some extra info
  418  * to distinguish that case from ether_output_frame();
  419  */
  420 int
  421 ether_ipfw_chk(struct mbuf **m0, struct ifnet *dst,
  422         struct ip_fw **rule, int shared)
  423 {
  424         struct ether_header *eh;
  425         struct ether_header save_eh;
  426         struct mbuf *m;
  427         int i;
  428         struct ip_fw_args args;
  429 
  430         if (*rule != NULL && fw_one_pass)
  431                 return 1; /* dummynet packet, already partially processed */
  432 
  433         /*
  434          * I need some amt of data to be contiguous, and in case others need
  435          * the packet (shared==1) also better be in the first mbuf.
  436          */
  437         m = *m0;
  438         i = min( m->m_pkthdr.len, max_protohdr);
  439         if ( shared || m->m_len < i) {
  440                 m = m_pullup(m, i);
  441                 if (m == NULL) {
  442                         *m0 = m;
  443                         return 0;
  444                 }
  445         }
  446         eh = mtod(m, struct ether_header *);
  447         save_eh = *eh;                  /* save copy for restore below */
  448         m_adj(m, ETHER_HDR_LEN);        /* strip ethernet header */
  449 
  450         args.m = m;             /* the packet we are looking at         */
  451         args.oif = dst;         /* destination, if any                  */
  452         args.rule = *rule;      /* matching rule to restart             */
  453         args.next_hop = NULL;   /* we do not support forward yet        */
  454         args.eh = &save_eh;     /* MAC header for bridged/MAC packets   */
  455         i = ip_fw_chk_ptr(&args);
  456         m = args.m;
  457         if (m != NULL) {
  458                 /*
  459                  * Restore Ethernet header, as needed, in case the
  460                  * mbuf chain was replaced by ipfw.
  461                  */
  462                 M_PREPEND(m, ETHER_HDR_LEN, M_DONTWAIT);
  463                 if (m == NULL) {
  464                         *m0 = m;
  465                         return 0;
  466                 }
  467                 if (eh != mtod(m, struct ether_header *))
  468                         bcopy(&save_eh, mtod(m, struct ether_header *),
  469                                 ETHER_HDR_LEN);
  470         }
  471         *m0 = m;
  472         *rule = args.rule;
  473 
  474         if (i == IP_FW_DENY) /* drop */
  475                 return 0;
  476 
  477         KASSERT(m != NULL, ("ether_ipfw_chk: m is NULL"));
  478 
  479         if (i == IP_FW_PASS) /* a PASS rule.  */
  480                 return 1;
  481 
  482         if (DUMMYNET_LOADED && (i == IP_FW_DUMMYNET)) {
  483                 /*
  484                  * Pass the pkt to dummynet, which consumes it.
  485                  * If shared, make a copy and keep the original.
  486                  */
  487                 if (shared) {
  488                         m = m_copypacket(m, M_DONTWAIT);
  489                         if (m == NULL)
  490                                 return 0;
  491                 } else {
  492                         /*
  493                          * Pass the original to dummynet and
  494                          * nothing back to the caller
  495                          */
  496                         *m0 = NULL ;
  497                 }
  498                 ip_dn_io_ptr(m, dst ? DN_TO_ETH_OUT: DN_TO_ETH_DEMUX, &args);
  499                 return 0;
  500         }
  501         /*
  502          * XXX at some point add support for divert/forward actions.
  503          * If none of the above matches, we have to drop the pkt.
  504          */
  505         return 0;
  506 }
  507 #endif
  508 
  509 /*
  510  * Process a received Ethernet packet; the packet is in the
  511  * mbuf chain m with the ethernet header at the front.
  512  */
  513 static void
  514 ether_input(struct ifnet *ifp, struct mbuf *m)
  515 {
  516         struct ether_header *eh;
  517         u_short etype;
  518 
  519         /*
  520          * Do consistency checks to verify assumptions
  521          * made by code past this point.
  522          */
  523         if ((m->m_flags & M_PKTHDR) == 0) {
  524                 if_printf(ifp, "discard frame w/o packet header\n");
  525                 ifp->if_ierrors++;
  526                 m_freem(m);
  527                 return;
  528         }
  529         if (m->m_len < ETHER_HDR_LEN) {
  530                 /* XXX maybe should pullup? */
  531                 if_printf(ifp, "discard frame w/o leading ethernet "
  532                                 "header (len %u pkt len %u)\n",
  533                                 m->m_len, m->m_pkthdr.len);
  534                 ifp->if_ierrors++;
  535                 m_freem(m);
  536                 return;
  537         }
  538         eh = mtod(m, struct ether_header *);
  539         etype = ntohs(eh->ether_type);
  540         if (m->m_pkthdr.len >
  541             ETHER_MAX_FRAME(ifp, etype, m->m_flags & M_HASFCS)) {
  542                 if_printf(ifp, "discard oversize frame "
  543                                 "(ether type %x flags %x len %u > max %lu)\n",
  544                                 etype, m->m_flags, m->m_pkthdr.len,
  545                                 ETHER_MAX_FRAME(ifp, etype,
  546                                                 m->m_flags & M_HASFCS));
  547                 ifp->if_ierrors++;
  548                 m_freem(m);
  549                 return;
  550         }
  551         if (m->m_pkthdr.rcvif == NULL) {
  552                 if_printf(ifp, "discard frame w/o interface pointer\n");
  553                 ifp->if_ierrors++;
  554                 m_freem(m);
  555                 return;
  556         }
  557 #ifdef DIAGNOSTIC
  558         if (m->m_pkthdr.rcvif != ifp) {
  559                 if_printf(ifp, "Warning, frame marked as received on %s\n",
  560                         m->m_pkthdr.rcvif->if_xname);
  561         }
  562 #endif
  563 
  564 #ifdef MAC
  565         /*
  566          * Tag the mbuf with an appropriate MAC label before any other
  567          * consumers can get to it.
  568          */
  569         mac_create_mbuf_from_ifnet(ifp, m);
  570 #endif
  571 
  572         /*
  573          * Give bpf a chance at the packet.
  574          */
  575         BPF_MTAP(ifp, m);
  576 
  577         if (ifp->if_flags & IFF_MONITOR) {
  578                 /*
  579                  * Interface marked for monitoring; discard packet.
  580                  */
  581                 m_freem(m);
  582                 return;
  583         }
  584 
  585         /* If the CRC is still on the packet, trim it off. */
  586         if (m->m_flags & M_HASFCS) {
  587                 m_adj(m, -ETHER_CRC_LEN);
  588                 m->m_flags &= ~M_HASFCS;
  589         }
  590 
  591         ifp->if_ibytes += m->m_pkthdr.len;
  592 
  593         /* Handle ng_ether(4) processing, if any */
  594         if (IFP2AC(ifp)->ac_netgraph != NULL) {
  595                 (*ng_ether_input_p)(ifp, &m);
  596                 if (m == NULL)
  597                         return;
  598         }
  599 
  600         /*
  601          * Tap the packet off here for a bridge.  bridge_input()
  602          * will return NULL if it has consumed the packet, otherwise
  603          * it gets processed as normal.  Note that bridge_input()
  604          * will always return the original packet if we need to
  605          * process it locally.
  606          */
  607         if (ifp->if_bridge) {
  608                 BRIDGE_INPUT(ifp, m);
  609                 if (m == NULL)
  610                         return;
  611         }
  612 
  613         /* Check for bridging mode */
  614         if (BDG_ACTIVE(ifp) )
  615                 if ((m = bridge_in_ptr(ifp, m)) == NULL)
  616                         return;
  617 
  618         /* First chunk of an mbuf contains good entropy */
  619         if (harvest.ethernet)
  620                 random_harvest(m, 16, 3, 0, RANDOM_NET);
  621         ether_demux(ifp, m);
  622 }
  623 
  624 /*
  625  * Upper layer processing for a received Ethernet packet.
  626  */
  627 void
  628 ether_demux(struct ifnet *ifp, struct mbuf *m)
  629 {
  630         struct ether_header *eh;
  631         int isr;
  632         u_short ether_type;
  633 #if defined(NETATALK)
  634         struct llc *l;
  635 #endif
  636 #if defined(INET) || defined(INET6)
  637         struct ip_fw *rule = ip_dn_claim_rule(m);
  638 #endif
  639 
  640         KASSERT(ifp != NULL, ("ether_demux: NULL interface pointer"));
  641 
  642         eh = mtod(m, struct ether_header *);
  643         ether_type = ntohs(eh->ether_type);
  644 
  645 #if defined(INET) || defined(INET6)
  646         if (rule)       /* packet was already bridged */
  647                 goto post_stats;
  648 #endif
  649 
  650         if (!(BDG_ACTIVE(ifp)) && !(ifp->if_bridge) &&
  651             !((ether_type == ETHERTYPE_VLAN || m->m_flags & M_VLANTAG) &&
  652             ifp->if_nvlans > 0)) {
  653 #ifdef DEV_CARP
  654                 /*
  655                  * XXX: Okay, we need to call carp_forus() and - if it is for
  656                  * us jump over code that does the normal check
  657                  * "IFP2ENADDR(ifp) == ether_dhost". The check sequence is a bit
  658                  * different from OpenBSD, so we jump over as few code as
  659                  * possible, to catch _all_ sanity checks. This needs
  660                  * evaluation, to see if the carp ether_dhost values break any
  661                  * of these checks!
  662                  */
  663                 if (ifp->if_carp && carp_forus(ifp->if_carp, eh->ether_dhost))
  664                         goto pre_stats;
  665 #endif
  666                 /*
  667                  * Discard packet if upper layers shouldn't see it because it
  668                  * was unicast to a different Ethernet address. If the driver
  669                  * is working properly, then this situation can only happen
  670                  * when the interface is in promiscuous mode.
  671                  *
  672                  * If VLANs are active, and this packet has a VLAN tag, do
  673                  * not drop it here but pass it on to the VLAN layer, to
  674                  * give them a chance to consider it as well (e. g. in case
  675                  * bridging is only active on a VLAN).  They will drop it if
  676                  * it's undesired.
  677                  */
  678                 if ((ifp->if_flags & IFF_PROMISC) != 0
  679                     && !ETHER_IS_MULTICAST(eh->ether_dhost)
  680                     && bcmp(eh->ether_dhost,
  681                       IFP2ENADDR(ifp), ETHER_ADDR_LEN) != 0
  682                     && (ifp->if_flags & IFF_PPROMISC) == 0) {
  683                             m_freem(m);
  684                             return;
  685                 }
  686         }
  687 
  688 #ifdef DEV_CARP
  689 pre_stats:
  690 #endif
  691         /* Discard packet if interface is not up */
  692         if ((ifp->if_flags & IFF_UP) == 0) {
  693                 m_freem(m);
  694                 return;
  695         }
  696         if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
  697                 if (bcmp(etherbroadcastaddr, eh->ether_dhost,
  698                     sizeof(etherbroadcastaddr)) == 0)
  699                         m->m_flags |= M_BCAST;
  700                 else
  701                         m->m_flags |= M_MCAST;
  702         }
  703         if (m->m_flags & (M_BCAST|M_MCAST))
  704                 ifp->if_imcasts++;
  705 
  706 #if defined(INET) || defined(INET6)
  707 post_stats:
  708         if (IPFW_LOADED && ether_ipfw != 0) {
  709                 if (ether_ipfw_chk(&m, NULL, &rule, 0) == 0) {
  710                         if (m)
  711                                 m_freem(m);
  712                         return;
  713                 }
  714         }
  715 #endif
  716 
  717         /*
  718          * Check to see if the device performed the VLAN decapsulation and
  719          * provided us with the tag.
  720          */
  721         if (m->m_flags & M_VLANTAG) {
  722                 /*
  723                  * If no VLANs are configured, drop.
  724                  */
  725                 if (ifp->if_nvlans == 0) {
  726                         ifp->if_noproto++;
  727                         m_freem(m);
  728                         return;
  729                 }
  730                 /*
  731                  * vlan_input() will either recursively call ether_input()
  732                  * or drop the packet.
  733                  */
  734                 KASSERT(vlan_input_p != NULL,("ether_input: VLAN not loaded!"));
  735                 (*vlan_input_p)(ifp, m);
  736                 return;
  737         }
  738 
  739         /*
  740          * Handle protocols that expect to have the Ethernet header
  741          * (and possibly FCS) intact.
  742          */
  743         switch (ether_type) {
  744         case ETHERTYPE_VLAN:
  745                 if (ifp->if_nvlans != 0) {
  746                         KASSERT(vlan_input_p,("ether_input: VLAN not loaded!"));
  747                         (*vlan_input_p)(ifp, m);
  748                 } else {
  749                         ifp->if_noproto++;
  750                         m_freem(m);
  751                 }
  752                 return;
  753         }
  754 
  755         /* Strip off Ethernet header. */
  756         m_adj(m, ETHER_HDR_LEN);
  757 
  758         /* If the CRC is still on the packet, trim it off. */
  759         if (m->m_flags & M_HASFCS) {
  760                 m_adj(m, -ETHER_CRC_LEN);
  761                 m->m_flags &= ~M_HASFCS;
  762         }
  763 
  764         switch (ether_type) {
  765 #ifdef INET
  766         case ETHERTYPE_IP:
  767                 if (ip_fastforward(m))
  768                         return;
  769                 isr = NETISR_IP;
  770                 break;
  771 
  772         case ETHERTYPE_ARP:
  773                 if (ifp->if_flags & IFF_NOARP) {
  774                         /* Discard packet if ARP is disabled on interface */
  775                         m_freem(m);
  776                         return;
  777                 }
  778                 isr = NETISR_ARP;
  779                 break;
  780 #endif
  781 #ifdef IPX
  782         case ETHERTYPE_IPX:
  783                 if (ef_inputp && ef_inputp(ifp, eh, m) == 0)
  784                         return;
  785                 isr = NETISR_IPX;
  786                 break;
  787 #endif
  788 #ifdef INET6
  789         case ETHERTYPE_IPV6:
  790                 isr = NETISR_IPV6;
  791                 break;
  792 #endif
  793 #ifdef NETATALK
  794         case ETHERTYPE_AT:
  795                 isr = NETISR_ATALK1;
  796                 break;
  797         case ETHERTYPE_AARP:
  798                 isr = NETISR_AARP;
  799                 break;
  800 #endif /* NETATALK */
  801         default:
  802 #ifdef IPX
  803                 if (ef_inputp && ef_inputp(ifp, eh, m) == 0)
  804                         return;
  805 #endif /* IPX */
  806 #if defined(NETATALK)
  807                 if (ether_type > ETHERMTU)
  808                         goto discard;
  809                 l = mtod(m, struct llc *);
  810                 if (l->llc_dsap == LLC_SNAP_LSAP &&
  811                     l->llc_ssap == LLC_SNAP_LSAP &&
  812                     l->llc_control == LLC_UI) {
  813                         if (bcmp(&(l->llc_snap_org_code)[0], at_org_code,
  814                             sizeof(at_org_code)) == 0 &&
  815                             ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) {
  816                                 m_adj(m, LLC_SNAPFRAMELEN);
  817                                 isr = NETISR_ATALK2;
  818                                 break;
  819                         }
  820                         if (bcmp(&(l->llc_snap_org_code)[0], aarp_org_code,
  821                             sizeof(aarp_org_code)) == 0 &&
  822                             ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) {
  823                                 m_adj(m, LLC_SNAPFRAMELEN);
  824                                 isr = NETISR_AARP;
  825                                 break;
  826                         }
  827                 }
  828 #endif /* NETATALK */
  829                 goto discard;
  830         }
  831         netisr_dispatch(isr, m);
  832         return;
  833 
  834 discard:
  835         /*
  836          * Packet is to be discarded.  If netgraph is present,
  837          * hand the packet to it for last chance processing;
  838          * otherwise dispose of it.
  839          */
  840         if (IFP2AC(ifp)->ac_netgraph != NULL) {
  841                 /*
  842                  * Put back the ethernet header so netgraph has a
  843                  * consistent view of inbound packets.
  844                  */
  845                 M_PREPEND(m, ETHER_HDR_LEN, M_DONTWAIT);
  846                 (*ng_ether_input_orphan_p)(ifp, m);
  847                 return;
  848         }
  849         m_freem(m);
  850 }
  851 
  852 /*
  853  * Convert Ethernet address to printable (loggable) representation.
  854  * This routine is for compatibility; it's better to just use
  855  *
  856  *      printf("%6D", <pointer to address>, ":");
  857  *
  858  * since there's no static buffer involved.
  859  */
  860 char *
  861 ether_sprintf(const u_char *ap)
  862 {
  863         static char etherbuf[18];
  864         snprintf(etherbuf, sizeof (etherbuf), "%6D", ap, ":");
  865         return (etherbuf);
  866 }
  867 
  868 /*
  869  * Perform common duties while attaching to interface list
  870  */
  871 void
  872 ether_ifattach(struct ifnet *ifp, const u_int8_t *llc)
  873 {
  874         int i;
  875         struct ifaddr *ifa;
  876         struct sockaddr_dl *sdl;
  877 
  878         ifp->if_addrlen = ETHER_ADDR_LEN;
  879         ifp->if_hdrlen = ETHER_HDR_LEN;
  880         if_attach(ifp);
  881         ifp->if_mtu = ETHERMTU;
  882         ifp->if_output = ether_output;
  883         ifp->if_input = ether_input;
  884         ifp->if_resolvemulti = ether_resolvemulti;
  885         if (ifp->if_baudrate == 0)
  886                 ifp->if_baudrate = IF_Mbps(10);         /* just a default */
  887         ifp->if_broadcastaddr = etherbroadcastaddr;
  888 
  889         ifa = ifaddr_byindex(ifp->if_index);
  890         KASSERT(ifa != NULL, ("%s: no lladdr!\n", __func__));
  891         sdl = (struct sockaddr_dl *)ifa->ifa_addr;
  892         sdl->sdl_type = IFT_ETHER;
  893         sdl->sdl_alen = ifp->if_addrlen;
  894         bcopy(llc, LLADDR(sdl), ifp->if_addrlen);
  895         /*
  896          * XXX: This doesn't belong here; we do it until
  897          * XXX:  all drivers are cleaned up
  898          */
  899         if (llc != IFP2ENADDR(ifp))
  900                 bcopy(llc, IFP2ENADDR(ifp), ifp->if_addrlen);
  901 
  902         bpfattach(ifp, DLT_EN10MB, ETHER_HDR_LEN);
  903         if (ng_ether_attach_p != NULL)
  904                 (*ng_ether_attach_p)(ifp);
  905         if (BDG_LOADED)
  906                 bdgtakeifaces_ptr();
  907 
  908         /* Announce Ethernet MAC address if non-zero. */
  909         for (i = 0; i < ifp->if_addrlen; i++)
  910                 if (llc[i] != 0)
  911                         break; 
  912         if (i != ifp->if_addrlen)
  913                 if_printf(ifp, "Ethernet address: %6D\n", llc, ":");
  914         if (debug_mpsafenet && (ifp->if_flags & IFF_NEEDSGIANT) != 0)
  915                 if_printf(ifp, "if_start running deferred for Giant\n");
  916 }
  917 
  918 /*
  919  * Perform common duties while detaching an Ethernet interface
  920  */
  921 void
  922 ether_ifdetach(struct ifnet *ifp)
  923 {
  924         if (IFP2AC(ifp)->ac_netgraph != NULL)
  925                 (*ng_ether_detach_p)(ifp);
  926 
  927         if (ifp->if_bridge) {
  928                 KASSERT(bridge_detach_p != NULL,
  929                     ("bridge_detach_p is NULL"));
  930                 (*bridge_detach_p)(ifp);
  931         }
  932 
  933         bpfdetach(ifp);
  934         if_detach(ifp);
  935         if (BDG_LOADED)
  936                 bdgtakeifaces_ptr();
  937 }
  938 
  939 SYSCTL_DECL(_net_link);
  940 SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
  941 #if defined(INET) || defined(INET6)
  942 SYSCTL_INT(_net_link_ether, OID_AUTO, ipfw, CTLFLAG_RW,
  943             &ether_ipfw,0,"Pass ether pkts through firewall");
  944 #endif
  945 
  946 #if 0
  947 /*
  948  * This is for reference.  We have a table-driven version
  949  * of the little-endian crc32 generator, which is faster
  950  * than the double-loop.
  951  */
  952 uint32_t
  953 ether_crc32_le(const uint8_t *buf, size_t len)
  954 {
  955         size_t i;
  956         uint32_t crc;
  957         int bit;
  958         uint8_t data;
  959 
  960         crc = 0xffffffff;       /* initial value */
  961 
  962         for (i = 0; i < len; i++) {
  963                 for (data = *buf++, bit = 0; bit < 8; bit++, data >>= 1)
  964                         carry = (crc ^ data) & 1;
  965                         crc >>= 1;
  966                         if (carry)
  967                                 crc = (crc ^ ETHER_CRC_POLY_LE);
  968         }
  969 
  970         return (crc);
  971 }
  972 #else
  973 uint32_t
  974 ether_crc32_le(const uint8_t *buf, size_t len)
  975 {
  976         static const uint32_t crctab[] = {
  977                 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
  978                 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
  979                 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
  980                 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
  981         };
  982         size_t i;
  983         uint32_t crc;
  984 
  985         crc = 0xffffffff;       /* initial value */
  986 
  987         for (i = 0; i < len; i++) {
  988                 crc ^= buf[i];
  989                 crc = (crc >> 4) ^ crctab[crc & 0xf];
  990                 crc = (crc >> 4) ^ crctab[crc & 0xf];
  991         }
  992 
  993         return (crc);
  994 }
  995 #endif
  996 
  997 uint32_t
  998 ether_crc32_be(const uint8_t *buf, size_t len)
  999 {
 1000         size_t i;
 1001         uint32_t crc, carry;
 1002         int bit;
 1003         uint8_t data;
 1004 
 1005         crc = 0xffffffff;       /* initial value */
 1006 
 1007         for (i = 0; i < len; i++) {
 1008                 for (data = *buf++, bit = 0; bit < 8; bit++, data >>= 1) {
 1009                         carry = ((crc & 0x80000000) ? 1 : 0) ^ (data & 0x01);
 1010                         crc <<= 1;
 1011                         if (carry)
 1012                                 crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
 1013                 }
 1014         }
 1015 
 1016         return (crc);
 1017 }
 1018 
 1019 int
 1020 ether_ioctl(struct ifnet *ifp, int command, caddr_t data)
 1021 {
 1022         struct ifaddr *ifa = (struct ifaddr *) data;
 1023         struct ifreq *ifr = (struct ifreq *) data;
 1024         int error = 0;
 1025 
 1026         switch (command) {
 1027         case SIOCSIFADDR:
 1028                 ifp->if_flags |= IFF_UP;
 1029 
 1030                 switch (ifa->ifa_addr->sa_family) {
 1031 #ifdef INET
 1032                 case AF_INET:
 1033                         ifp->if_init(ifp->if_softc);    /* before arpwhohas */
 1034                         arp_ifinit(ifp, ifa);
 1035                         break;
 1036 #endif
 1037 #ifdef IPX
 1038                 /*
 1039                  * XXX - This code is probably wrong
 1040                  */
 1041                 case AF_IPX:
 1042                         {
 1043                         struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
 1044 
 1045                         if (ipx_nullhost(*ina))
 1046                                 ina->x_host =
 1047                                     *(union ipx_host *)
 1048                                     IFP2ENADDR(ifp);
 1049                         else {
 1050                                 bcopy((caddr_t) ina->x_host.c_host,
 1051                                       (caddr_t) IFP2ENADDR(ifp),
 1052                                       ETHER_ADDR_LEN);
 1053                         }
 1054 
 1055                         /*
 1056                          * Set new address
 1057                          */
 1058                         ifp->if_init(ifp->if_softc);
 1059                         break;
 1060                         }
 1061 #endif
 1062                 default:
 1063                         ifp->if_init(ifp->if_softc);
 1064                         break;
 1065                 }
 1066                 break;
 1067 
 1068         case SIOCGIFADDR:
 1069                 {
 1070                         struct sockaddr *sa;
 1071 
 1072                         sa = (struct sockaddr *) & ifr->ifr_data;
 1073                         bcopy(IFP2ENADDR(ifp),
 1074                               (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
 1075                 }
 1076                 break;
 1077 
 1078         case SIOCSIFMTU:
 1079                 /*
 1080                  * Set the interface MTU.
 1081                  */
 1082                 if (ifr->ifr_mtu > ETHERMTU) {
 1083                         error = EINVAL;
 1084                 } else {
 1085                         ifp->if_mtu = ifr->ifr_mtu;
 1086                 }
 1087                 break;
 1088         default:
 1089                 error = EINVAL;                 /* XXX netbsd has ENOTTY??? */
 1090                 break;
 1091         }
 1092         return (error);
 1093 }
 1094 
 1095 static int
 1096 ether_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa,
 1097         struct sockaddr *sa)
 1098 {
 1099         struct sockaddr_dl *sdl;
 1100 #ifdef INET
 1101         struct sockaddr_in *sin;
 1102 #endif
 1103 #ifdef INET6
 1104         struct sockaddr_in6 *sin6;
 1105 #endif
 1106         u_char *e_addr;
 1107 
 1108         switch(sa->sa_family) {
 1109         case AF_LINK:
 1110                 /*
 1111                  * No mapping needed. Just check that it's a valid MC address.
 1112                  */
 1113                 sdl = (struct sockaddr_dl *)sa;
 1114                 e_addr = LLADDR(sdl);
 1115                 if (!ETHER_IS_MULTICAST(e_addr))
 1116                         return EADDRNOTAVAIL;
 1117                 *llsa = 0;
 1118                 return 0;
 1119 
 1120 #ifdef INET
 1121         case AF_INET:
 1122                 sin = (struct sockaddr_in *)sa;
 1123                 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
 1124                         return EADDRNOTAVAIL;
 1125                 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
 1126                        M_NOWAIT|M_ZERO);
 1127                 if (sdl == NULL)
 1128                         return ENOMEM;
 1129                 sdl->sdl_len = sizeof *sdl;
 1130                 sdl->sdl_family = AF_LINK;
 1131                 sdl->sdl_index = ifp->if_index;
 1132                 sdl->sdl_type = IFT_ETHER;
 1133                 sdl->sdl_alen = ETHER_ADDR_LEN;
 1134                 e_addr = LLADDR(sdl);
 1135                 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr);
 1136                 *llsa = (struct sockaddr *)sdl;
 1137                 return 0;
 1138 #endif
 1139 #ifdef INET6
 1140         case AF_INET6:
 1141                 sin6 = (struct sockaddr_in6 *)sa;
 1142                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 1143                         /*
 1144                          * An IP6 address of 0 means listen to all
 1145                          * of the Ethernet multicast address used for IP6.
 1146                          * (This is used for multicast routers.)
 1147                          */
 1148                         ifp->if_flags |= IFF_ALLMULTI;
 1149                         *llsa = 0;
 1150                         return 0;
 1151                 }
 1152                 if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
 1153                         return EADDRNOTAVAIL;
 1154                 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
 1155                        M_NOWAIT|M_ZERO);
 1156                 if (sdl == NULL)
 1157                         return (ENOMEM);
 1158                 sdl->sdl_len = sizeof *sdl;
 1159                 sdl->sdl_family = AF_LINK;
 1160                 sdl->sdl_index = ifp->if_index;
 1161                 sdl->sdl_type = IFT_ETHER;
 1162                 sdl->sdl_alen = ETHER_ADDR_LEN;
 1163                 e_addr = LLADDR(sdl);
 1164                 ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, e_addr);
 1165                 *llsa = (struct sockaddr *)sdl;
 1166                 return 0;
 1167 #endif
 1168 
 1169         default:
 1170                 /*
 1171                  * Well, the text isn't quite right, but it's the name
 1172                  * that counts...
 1173                  */
 1174                 return EAFNOSUPPORT;
 1175         }
 1176 }
 1177 
 1178 static void*
 1179 ether_alloc(u_char type, struct ifnet *ifp)
 1180 {
 1181         struct arpcom   *ac;
 1182         
 1183         ac = malloc(sizeof(struct arpcom), M_ARPCOM, M_WAITOK | M_ZERO);
 1184         ac->ac_ifp = ifp;
 1185 
 1186         return (ac);
 1187 }
 1188 
 1189 static void
 1190 ether_free(void *com, u_char type)
 1191 {
 1192 
 1193         free(com, M_ARPCOM);
 1194 }
 1195 
 1196 static int
 1197 ether_modevent(module_t mod, int type, void *data)
 1198 {
 1199 
 1200         switch (type) {
 1201         case MOD_LOAD:
 1202                 if_register_com_alloc(IFT_ETHER, ether_alloc, ether_free);
 1203                 break;
 1204         case MOD_UNLOAD:
 1205                 if_deregister_com_alloc(IFT_ETHER);
 1206                 break;
 1207         default:
 1208                 return EOPNOTSUPP;
 1209         }
 1210 
 1211         return (0);
 1212 }
 1213 
 1214 static moduledata_t ether_mod = {
 1215         "ether",
 1216         ether_modevent,
 1217         0
 1218 };
 1219 
 1220 DECLARE_MODULE(ether, ether_mod, SI_SUB_INIT_IF, SI_ORDER_ANY);
 1221 MODULE_VERSION(ether, 1);

Cache object: 2553ad47547bda81692f79332cc53782


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