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 /*      $OpenBSD: if_ethersubr.c,v 1.286 2023/01/26 07:32:40 deraadt Exp $      */
    2 /*      $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $        */
    3 
    4 /*
    5  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the project nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  */
   32 
   33 /*
   34  * Copyright (c) 1982, 1989, 1993
   35  *      The Regents of the University of California.  All rights reserved.
   36  *
   37  * Redistribution and use in source and binary forms, with or without
   38  * modification, are permitted provided that the following conditions
   39  * are met:
   40  * 1. Redistributions of source code must retain the above copyright
   41  *    notice, this list of conditions and the following disclaimer.
   42  * 2. Redistributions in binary form must reproduce the above copyright
   43  *    notice, this list of conditions and the following disclaimer in the
   44  *    documentation and/or other materials provided with the distribution.
   45  * 3. Neither the name of the University nor the names of its contributors
   46  *    may be used to endorse or promote products derived from this software
   47  *    without specific prior written permission.
   48  *
   49  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   50  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   51  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   52  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   53  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   54  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   55  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   56  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   57  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   58  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   59  * SUCH DAMAGE.
   60  *
   61  *      @(#)if_ethersubr.c      8.1 (Berkeley) 6/10/93
   62  */
   63 
   64 /*
   65 %%% portions-copyright-nrl-95
   66 Portions of this software are Copyright 1995-1998 by Randall Atkinson,
   67 Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights
   68 Reserved. All rights under this copyright have been assigned to the US
   69 Naval Research Laboratory (NRL). The NRL Copyright Notice and License
   70 Agreement Version 1.1 (January 17, 1995) applies to these portions of the
   71 software.
   72 You should have received a copy of the license with this software. If you
   73 didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
   74 */
   75 
   76 #include "bpfilter.h"
   77 
   78 #include <sys/param.h>
   79 #include <sys/systm.h>
   80 #include <sys/kernel.h>
   81 #include <sys/malloc.h>
   82 #include <sys/mbuf.h>
   83 #include <sys/socket.h>
   84 #include <sys/ioctl.h>
   85 #include <sys/errno.h>
   86 #include <sys/syslog.h>
   87 #include <sys/timeout.h>
   88 #include <sys/smr.h>
   89 
   90 #include <net/if.h>
   91 #include <net/netisr.h>
   92 #include <net/route.h>
   93 #include <net/if_llc.h>
   94 #include <net/if_dl.h>
   95 #include <net/if_media.h>
   96 #include <net/if_types.h>
   97 
   98 #include <netinet/in.h>
   99 #include <netinet/if_ether.h>
  100 #include <netinet/ip_ipsp.h>
  101 
  102 #if NBPFILTER > 0
  103 #include <net/bpf.h>
  104 #endif
  105 
  106 #include "vlan.h"
  107 #if NVLAN > 0
  108 #include <net/if_vlan_var.h>
  109 #endif
  110 
  111 #include "carp.h"
  112 #if NCARP > 0
  113 #include <netinet/ip_carp.h>
  114 #endif
  115 
  116 #include "pppoe.h"
  117 #if NPPPOE > 0
  118 #include <net/if_pppoe.h>
  119 #endif
  120 
  121 #include "bpe.h"
  122 #if NBPE > 0
  123 #include <net/if_bpe.h>
  124 #endif
  125 
  126 #ifdef INET6
  127 #include <netinet6/in6_var.h>
  128 #include <netinet6/nd6.h>
  129 #endif
  130 
  131 #ifdef PIPEX
  132 #include <net/pipex.h>
  133 #endif
  134 
  135 #ifdef MPLS
  136 #include <netmpls/mpls.h>
  137 #endif /* MPLS */
  138 
  139 u_int8_t etherbroadcastaddr[ETHER_ADDR_LEN] =
  140     { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  141 u_int8_t etheranyaddr[ETHER_ADDR_LEN] =
  142     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  143 #define senderr(e) { error = (e); goto bad;}
  144 
  145 int
  146 ether_ioctl(struct ifnet *ifp, struct arpcom *arp, u_long cmd, caddr_t data)
  147 {
  148         struct ifreq *ifr = (struct ifreq *)data;
  149         int error = 0;
  150 
  151         switch (cmd) {
  152         case SIOCSIFADDR:
  153                 break;
  154 
  155         case SIOCSIFMTU:
  156                 if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu)
  157                         error = EINVAL;
  158                 else
  159                         ifp->if_mtu = ifr->ifr_mtu;
  160                 break;
  161 
  162         case SIOCADDMULTI:
  163         case SIOCDELMULTI:
  164                 if (ifp->if_flags & IFF_MULTICAST) {
  165                         error = (cmd == SIOCADDMULTI) ?
  166                             ether_addmulti(ifr, arp) :
  167                             ether_delmulti(ifr, arp);
  168                 } else
  169                         error = ENOTTY;
  170                 break;
  171 
  172         default:
  173                 error = ENOTTY;
  174         }
  175 
  176         return (error);
  177 }
  178 
  179 
  180 void
  181 ether_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt)
  182 {
  183         if (rt == NULL)
  184                 return;
  185 
  186         switch (rt_key(rt)->sa_family) {
  187         case AF_INET:
  188                 arp_rtrequest(ifp, req, rt);
  189                 break;
  190 #ifdef INET6
  191         case AF_INET6:
  192                 nd6_rtrequest(ifp, req, rt);
  193                 break;
  194 #endif
  195         default:
  196                 break;
  197         }
  198 }
  199 
  200 int
  201 ether_resolve(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
  202     struct rtentry *rt, struct ether_header *eh)
  203 {
  204         struct arpcom *ac = (struct arpcom *)ifp;
  205         sa_family_t af = dst->sa_family;
  206         int error = 0;
  207 
  208         if (!ISSET(ifp->if_flags, IFF_RUNNING))
  209                 senderr(ENETDOWN);
  210 
  211         KASSERT(rt != NULL || ISSET(m->m_flags, M_MCAST|M_BCAST) ||
  212                 af == AF_UNSPEC || af == pseudo_AF_HDRCMPLT);
  213 
  214 #ifdef DIAGNOSTIC
  215         if (ifp->if_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid)) {
  216                 printf("%s: trying to send packet on wrong domain. "
  217                     "if %d vs. mbuf %d\n", ifp->if_xname,
  218                     ifp->if_rdomain, rtable_l2(m->m_pkthdr.ph_rtableid));
  219         }
  220 #endif
  221 
  222         switch (af) {
  223         case AF_INET:
  224                 error = arpresolve(ifp, rt, m, dst, eh->ether_dhost);
  225                 if (error)
  226                         return (error);
  227                 eh->ether_type = htons(ETHERTYPE_IP);
  228 
  229                 /*
  230                  * If broadcasting on a simplex interface, loopback a copy.
  231                  * The checksum must be calculated in software.  Keep the
  232                  * condition in sync with in_ifcap_cksum().
  233                  */
  234                 if (ISSET(m->m_flags, M_BCAST) &&
  235                     ISSET(ifp->if_flags, IFF_SIMPLEX) &&
  236                     !m->m_pkthdr.pf.routed) {
  237                         struct mbuf *mcopy;
  238 
  239                         /* XXX Should we input an unencrypted IPsec packet? */
  240                         mcopy = m_copym(m, 0, M_COPYALL, M_NOWAIT);
  241                         if (mcopy != NULL)
  242                                 if_input_local(ifp, mcopy, af);
  243                 }
  244                 break;
  245 #ifdef INET6
  246         case AF_INET6:
  247                 KERNEL_LOCK();
  248                 /* XXXSMP there is a MP race in nd6_resolve() */
  249                 error = nd6_resolve(ifp, rt, m, dst, eh->ether_dhost);
  250                 KERNEL_UNLOCK();
  251                 if (error)
  252                         return (error);
  253                 eh->ether_type = htons(ETHERTYPE_IPV6);
  254                 break;
  255 #endif
  256 #ifdef MPLS
  257         case AF_MPLS:
  258                 if (rt == NULL)
  259                         senderr(EHOSTUNREACH);
  260 
  261                 if (!ISSET(ifp->if_xflags, IFXF_MPLS))
  262                         senderr(ENETUNREACH);
  263 
  264                 dst = ISSET(rt->rt_flags, RTF_GATEWAY) ?
  265                     rt->rt_gateway : rt_key(rt);
  266 
  267                 switch (dst->sa_family) {
  268                 case AF_LINK:
  269                         if (satosdl(dst)->sdl_alen < sizeof(eh->ether_dhost))
  270                                 senderr(EHOSTUNREACH);
  271                         memcpy(eh->ether_dhost, LLADDR(satosdl(dst)),
  272                             sizeof(eh->ether_dhost));
  273                         break;
  274 #ifdef INET6
  275                 case AF_INET6:
  276                         KERNEL_LOCK();
  277                         /* XXXSMP there is a MP race in nd6_resolve() */
  278                         error = nd6_resolve(ifp, rt, m, dst, eh->ether_dhost);
  279                         KERNEL_UNLOCK();
  280                         if (error)
  281                                 return (error);
  282                         break;
  283 #endif
  284                 case AF_INET:
  285                         error = arpresolve(ifp, rt, m, dst, eh->ether_dhost);
  286                         if (error)
  287                                 return (error);
  288                         break;
  289                 default:
  290                         senderr(EHOSTUNREACH);
  291                 }
  292                 /* XXX handling for simplex devices in case of M/BCAST ?? */
  293                 if (m->m_flags & (M_BCAST | M_MCAST))
  294                         eh->ether_type = htons(ETHERTYPE_MPLS_MCAST);
  295                 else
  296                         eh->ether_type = htons(ETHERTYPE_MPLS);
  297                 break;
  298 #endif /* MPLS */
  299         case pseudo_AF_HDRCMPLT:
  300                 /* take the whole header from the sa */
  301                 memcpy(eh, dst->sa_data, sizeof(*eh));
  302                 return (0);
  303 
  304         case AF_UNSPEC:
  305                 /* take the dst and type from the sa, but get src below */
  306                 memcpy(eh, dst->sa_data, sizeof(*eh));
  307                 break;
  308 
  309         default:
  310                 printf("%s: can't handle af%d\n", ifp->if_xname, af);
  311                 senderr(EAFNOSUPPORT);
  312         }
  313 
  314         memcpy(eh->ether_shost, ac->ac_enaddr, sizeof(eh->ether_shost));
  315 
  316         return (0);
  317 
  318 bad:
  319         m_freem(m);
  320         return (error);
  321 }
  322 
  323 struct mbuf*
  324 ether_encap(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
  325     struct rtentry *rt, int *errorp)
  326 {
  327         struct ether_header eh;
  328         int error;
  329 
  330         error = ether_resolve(ifp, m, dst, rt, &eh);
  331         switch (error) {
  332         case 0:
  333                 break;
  334         case EAGAIN:
  335                 error = 0;
  336         default:
  337                 *errorp = error;
  338                 return (NULL);
  339         }
  340 
  341         m = m_prepend(m, ETHER_ALIGN + sizeof(eh), M_DONTWAIT);
  342         if (m == NULL) {
  343                 *errorp = ENOBUFS;
  344                 return (NULL);
  345         }
  346 
  347         m_adj(m, ETHER_ALIGN);
  348         memcpy(mtod(m, struct ether_header *), &eh, sizeof(eh));
  349 
  350         return (m);
  351 }
  352 
  353 int
  354 ether_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
  355     struct rtentry *rt)
  356 {
  357         int error;
  358 
  359         m = ether_encap(ifp, m, dst, rt, &error);
  360         if (m == NULL)
  361                 return (error);
  362 
  363         return (if_enqueue(ifp, m));
  364 }
  365 
  366 /*
  367  * Process a received Ethernet packet.
  368  *
  369  * Ethernet input has several "phases" of filtering packets to
  370  * support virtual/pseudo interfaces before actual layer 3 protocol
  371  * handling.
  372  *
  373  * First phase:
  374  *
  375  * The first phase supports drivers that aggregate multiple Ethernet
  376  * ports into a single logical interface, ie, aggr(4) and trunk(4).
  377  * These drivers intercept packets by swapping out the if_input handler
  378  * on the "port" interfaces to steal the packets before they get here
  379  * to ether_input().
  380  */
  381 void
  382 ether_input(struct ifnet *ifp, struct mbuf *m)
  383 {
  384         struct ether_header *eh;
  385         void (*input)(struct ifnet *, struct mbuf *);
  386         u_int16_t etype;
  387         struct arpcom *ac;
  388         const struct ether_brport *eb;
  389         unsigned int sdelim = 0;
  390         uint64_t dst, self;
  391 
  392         /* Drop short frames */
  393         if (m->m_len < ETHER_HDR_LEN)
  394                 goto dropanyway;
  395 
  396         /*
  397          * Second phase: service delimited packet filtering.
  398          *
  399          * Let vlan(4) and svlan(4) look at "service delimited"
  400          * packets. If a virtual interface does not exist to take
  401          * those packets, they're returned to ether_input() so a
  402          * bridge can have a go at forwarding them.
  403          */
  404 
  405         eh = mtod(m, struct ether_header *);
  406         dst = ether_addr_to_e64((struct ether_addr *)eh->ether_dhost);
  407         etype = ntohs(eh->ether_type);
  408 
  409         if (ISSET(m->m_flags, M_VLANTAG) ||
  410             etype == ETHERTYPE_VLAN || etype == ETHERTYPE_QINQ) {
  411 #if NVLAN > 0
  412                 m = vlan_input(ifp, m, &sdelim);
  413                 if (m == NULL)
  414                         return;
  415 #else
  416                 sdelim = 1;
  417 #endif
  418         }
  419 
  420         /*
  421          * Third phase: bridge processing.
  422          *
  423          * Give the packet to a bridge interface, ie, bridge(4),
  424          * veb(4), or tpmr(4), if it is configured. A bridge
  425          * may take the packet and forward it to another port, or it
  426          * may return it here to ether_input() to support local
  427          * delivery to this port.
  428          */
  429 
  430         ac = (struct arpcom *)ifp;
  431 
  432         smr_read_enter();
  433         eb = SMR_PTR_GET(&ac->ac_brport);
  434         if (eb != NULL)
  435                 eb->eb_port_take(eb->eb_port);
  436         smr_read_leave();
  437         if (eb != NULL) {
  438                 m = (*eb->eb_input)(ifp, m, dst, eb->eb_port);
  439                 eb->eb_port_rele(eb->eb_port);
  440                 if (m == NULL) {
  441                         return;
  442                 }
  443         }
  444 
  445         /*
  446          * Fourth phase: drop service delimited packets.
  447          *
  448          * If the packet has a tag, and a bridge didn't want it,
  449          * it's not for this port.
  450          */
  451 
  452         if (sdelim)
  453                 goto dropanyway;
  454 
  455         /*
  456          * Fifth phase: destination address check.
  457          *
  458          * Is the packet specifically addressed to this port?
  459          */
  460 
  461         eh = mtod(m, struct ether_header *);
  462         self = ether_addr_to_e64((struct ether_addr *)ac->ac_enaddr);
  463         if (dst != self) {
  464 #if NCARP > 0
  465                 /*
  466                  * If it's not for this port, it could be for carp(4).
  467                  */
  468                 if (ifp->if_type != IFT_CARP &&
  469                     !SRPL_EMPTY_LOCKED(&ifp->if_carp)) {
  470                         m = carp_input(ifp, m, dst);
  471                         if (m == NULL)
  472                                 return;
  473 
  474                         eh = mtod(m, struct ether_header *);
  475                 }
  476 #endif
  477 
  478                 /*
  479                  * If not, it must be multicast or broadcast to go further.
  480                  */
  481                 if (!ETH64_IS_MULTICAST(dst))
  482                         goto dropanyway;
  483 
  484                 /*
  485                  * If this is not a simplex interface, drop the packet
  486                  * if it came from us.
  487                  */
  488                 if ((ifp->if_flags & IFF_SIMPLEX) == 0) {
  489                         uint64_t src = ether_addr_to_e64(
  490                             (struct ether_addr *)eh->ether_shost);
  491                         if (self == src)
  492                                 goto dropanyway;
  493                 }
  494 
  495                 SET(m->m_flags, ETH64_IS_BROADCAST(dst) ? M_BCAST : M_MCAST);
  496                 ifp->if_imcasts++;
  497         }
  498 
  499         /*
  500          * Sixth phase: protocol demux.
  501          *
  502          * At this point it is known that the packet is destined
  503          * for layer 3 protocol handling on the local port.
  504          */
  505         etype = ntohs(eh->ether_type);
  506 
  507         switch (etype) {
  508         case ETHERTYPE_IP:
  509                 input = ipv4_input;
  510                 break;
  511 
  512         case ETHERTYPE_ARP:
  513                 if (ifp->if_flags & IFF_NOARP)
  514                         goto dropanyway;
  515                 input = arpinput;
  516                 break;
  517 
  518         case ETHERTYPE_REVARP:
  519                 if (ifp->if_flags & IFF_NOARP)
  520                         goto dropanyway;
  521                 input = revarpinput;
  522                 break;
  523 
  524 #ifdef INET6
  525         /*
  526          * Schedule IPv6 software interrupt for incoming IPv6 packet.
  527          */
  528         case ETHERTYPE_IPV6:
  529                 input = ipv6_input;
  530                 break;
  531 #endif /* INET6 */
  532 #if NPPPOE > 0 || defined(PIPEX)
  533         case ETHERTYPE_PPPOEDISC:
  534         case ETHERTYPE_PPPOE:
  535                 if (m->m_flags & (M_MCAST | M_BCAST))
  536                         goto dropanyway;
  537 #ifdef PIPEX
  538                 if (pipex_enable) {
  539                         struct pipex_session *session;
  540 
  541                         if ((session = pipex_pppoe_lookup_session(m)) != NULL) {
  542                                 pipex_pppoe_input(m, session);
  543                                 pipex_rele_session(session);
  544                                 return;
  545                         }
  546                 }
  547 #endif
  548                 if (etype == ETHERTYPE_PPPOEDISC) {
  549                         if (mq_enqueue(&pppoediscinq, m) == 0)
  550                                 schednetisr(NETISR_PPPOE);
  551                 } else {
  552                         if (mq_enqueue(&pppoeinq, m) == 0)
  553                                 schednetisr(NETISR_PPPOE);
  554                 }
  555                 return;
  556 #endif
  557 #ifdef MPLS
  558         case ETHERTYPE_MPLS:
  559         case ETHERTYPE_MPLS_MCAST:
  560                 input = mpls_input;
  561                 break;
  562 #endif
  563 #if NBPE > 0
  564         case ETHERTYPE_PBB:
  565                 bpe_input(ifp, m);
  566                 return;
  567 #endif
  568         default:
  569                 goto dropanyway;
  570         }
  571 
  572         m_adj(m, sizeof(*eh));
  573         (*input)(ifp, m);
  574         return;
  575 dropanyway:
  576         m_freem(m);
  577         return;
  578 }
  579 
  580 int
  581 ether_brport_isset(struct ifnet *ifp)
  582 {
  583         struct arpcom *ac = (struct arpcom *)ifp;
  584 
  585         KERNEL_ASSERT_LOCKED();
  586         if (SMR_PTR_GET_LOCKED(&ac->ac_brport) != NULL)
  587                 return (EBUSY);
  588 
  589         return (0);
  590 }
  591 
  592 void
  593 ether_brport_set(struct ifnet *ifp, const struct ether_brport *eb)
  594 {
  595         struct arpcom *ac = (struct arpcom *)ifp;
  596 
  597         KERNEL_ASSERT_LOCKED();
  598         KASSERTMSG(SMR_PTR_GET_LOCKED(&ac->ac_brport) == NULL,
  599             "%s setting an already set brport", ifp->if_xname);
  600 
  601         SMR_PTR_SET_LOCKED(&ac->ac_brport, eb);
  602 }
  603 
  604 void
  605 ether_brport_clr(struct ifnet *ifp)
  606 {
  607         struct arpcom *ac = (struct arpcom *)ifp;
  608 
  609         KERNEL_ASSERT_LOCKED();
  610         KASSERTMSG(SMR_PTR_GET_LOCKED(&ac->ac_brport) != NULL,
  611             "%s clearing an already clear brport", ifp->if_xname);
  612 
  613         SMR_PTR_SET_LOCKED(&ac->ac_brport, NULL);
  614 }
  615 
  616 const struct ether_brport *
  617 ether_brport_get(struct ifnet *ifp)
  618 {
  619         struct arpcom *ac = (struct arpcom *)ifp;
  620         SMR_ASSERT_CRITICAL();
  621         return (SMR_PTR_GET(&ac->ac_brport));
  622 }
  623 
  624 const struct ether_brport *
  625 ether_brport_get_locked(struct ifnet *ifp)
  626 {
  627         struct arpcom *ac = (struct arpcom *)ifp;
  628         KERNEL_ASSERT_LOCKED();
  629         return (SMR_PTR_GET_LOCKED(&ac->ac_brport));
  630 }
  631 
  632 /*
  633  * Convert Ethernet address to printable (loggable) representation.
  634  */
  635 static char digits[] = "0123456789abcdef";
  636 char *
  637 ether_sprintf(u_char *ap)
  638 {
  639         int i;
  640         static char etherbuf[ETHER_ADDR_LEN * 3];
  641         char *cp = etherbuf;
  642 
  643         for (i = 0; i < ETHER_ADDR_LEN; i++) {
  644                 *cp++ = digits[*ap >> 4];
  645                 *cp++ = digits[*ap++ & 0xf];
  646                 *cp++ = ':';
  647         }
  648         *--cp = 0;
  649         return (etherbuf);
  650 }
  651 
  652 /*
  653  * Generate a (hopefully) acceptable MAC address, if asked.
  654  */
  655 void
  656 ether_fakeaddr(struct ifnet *ifp)
  657 {
  658         static int unit;
  659         int rng = arc4random();
  660 
  661         /* Non-multicast; locally administered address */
  662         ((struct arpcom *)ifp)->ac_enaddr[0] = 0xfe;
  663         ((struct arpcom *)ifp)->ac_enaddr[1] = 0xe1;
  664         ((struct arpcom *)ifp)->ac_enaddr[2] = 0xba;
  665         ((struct arpcom *)ifp)->ac_enaddr[3] = 0xd0 | (unit++ & 0xf);
  666         ((struct arpcom *)ifp)->ac_enaddr[4] = rng;
  667         ((struct arpcom *)ifp)->ac_enaddr[5] = rng >> 8;
  668 }
  669 
  670 /*
  671  * Perform common duties while attaching to interface list
  672  */
  673 void
  674 ether_ifattach(struct ifnet *ifp)
  675 {
  676         struct arpcom *ac = (struct arpcom *)ifp;
  677 
  678         /*
  679          * Any interface which provides a MAC address which is obviously
  680          * invalid gets whacked, so that users will notice.
  681          */
  682         if (ETHER_IS_MULTICAST(((struct arpcom *)ifp)->ac_enaddr))
  683                 ether_fakeaddr(ifp);
  684 
  685         ifp->if_type = IFT_ETHER;
  686         ifp->if_addrlen = ETHER_ADDR_LEN;
  687         ifp->if_hdrlen = ETHER_HDR_LEN;
  688         ifp->if_mtu = ETHERMTU;
  689         ifp->if_input = ether_input;
  690         if (ifp->if_output == NULL)
  691                 ifp->if_output = ether_output;
  692         ifp->if_rtrequest = ether_rtrequest;
  693 
  694         if (ifp->if_hardmtu == 0)
  695                 ifp->if_hardmtu = ETHERMTU;
  696 
  697         if_alloc_sadl(ifp);
  698         memcpy(LLADDR(ifp->if_sadl), ac->ac_enaddr, ifp->if_addrlen);
  699         LIST_INIT(&ac->ac_multiaddrs);
  700 #if NBPFILTER > 0
  701         bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, ETHER_HDR_LEN);
  702 #endif
  703 }
  704 
  705 void
  706 ether_ifdetach(struct ifnet *ifp)
  707 {
  708         struct arpcom *ac = (struct arpcom *)ifp;
  709         struct ether_multi *enm;
  710 
  711         /* Undo pseudo-driver changes. */
  712         if_deactivate(ifp);
  713 
  714         for (enm = LIST_FIRST(&ac->ac_multiaddrs);
  715             enm != NULL;
  716             enm = LIST_FIRST(&ac->ac_multiaddrs)) {
  717                 LIST_REMOVE(enm, enm_list);
  718                 free(enm, M_IFMADDR, sizeof *enm);
  719         }
  720 }
  721 
  722 #if 0
  723 /*
  724  * This is for reference.  We have table-driven versions of the
  725  * crc32 generators, which are faster than the double-loop.
  726  */
  727 u_int32_t __pure
  728 ether_crc32_le_update(u_int_32_t crc, const u_int8_t *buf, size_t len)
  729 {
  730         u_int32_t c, carry;
  731         size_t i, j;
  732 
  733         for (i = 0; i < len; i++) {
  734                 c = buf[i];
  735                 for (j = 0; j < 8; j++) {
  736                         carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01);
  737                         crc >>= 1;
  738                         c >>= 1;
  739                         if (carry)
  740                                 crc = (crc ^ ETHER_CRC_POLY_LE);
  741                 }
  742         }
  743 
  744         return (crc);
  745 }
  746 
  747 u_int32_t __pure
  748 ether_crc32_be_update(u_int_32_t crc, const u_int8_t *buf, size_t len)
  749 {
  750         u_int32_t c, carry;
  751         size_t i, j;
  752 
  753         for (i = 0; i < len; i++) {
  754                 c = buf[i];
  755                 for (j = 0; j < 8; j++) {
  756                         carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01);
  757                         crc <<= 1;
  758                         c >>= 1;
  759                         if (carry)
  760                                 crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
  761                 }
  762         }
  763 
  764         return (crc);
  765 }
  766 #else
  767 u_int32_t __pure
  768 ether_crc32_le_update(u_int32_t crc, const u_int8_t *buf, size_t len)
  769 {
  770         static const u_int32_t crctab[] = {
  771                 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
  772                 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
  773                 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
  774                 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
  775         };
  776         size_t i;
  777 
  778         for (i = 0; i < len; i++) {
  779                 crc ^= buf[i];
  780                 crc = (crc >> 4) ^ crctab[crc & 0xf];
  781                 crc = (crc >> 4) ^ crctab[crc & 0xf];
  782         }
  783 
  784         return (crc);
  785 }
  786 
  787 u_int32_t __pure
  788 ether_crc32_be_update(u_int32_t crc, const u_int8_t *buf, size_t len)
  789 {
  790         static const u_int8_t rev[] = {
  791                 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
  792                 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
  793         };
  794         static const u_int32_t crctab[] = {
  795                 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
  796                 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
  797                 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
  798                 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd
  799         };
  800         size_t i;
  801         u_int8_t data;
  802 
  803         for (i = 0; i < len; i++) {
  804                 data = buf[i];
  805                 crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data & 0xf]];
  806                 crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data >> 4]];
  807         }
  808 
  809         return (crc);
  810 }
  811 #endif
  812 
  813 u_int32_t
  814 ether_crc32_le(const u_int8_t *buf, size_t len)
  815 {
  816         return ether_crc32_le_update(0xffffffff, buf, len);
  817 }
  818 
  819 u_int32_t
  820 ether_crc32_be(const u_int8_t *buf, size_t len)
  821 {
  822         return ether_crc32_be_update(0xffffffff, buf, len);
  823 }
  824 
  825 u_char  ether_ipmulticast_min[ETHER_ADDR_LEN] =
  826     { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
  827 u_char  ether_ipmulticast_max[ETHER_ADDR_LEN] =
  828     { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
  829 
  830 #ifdef INET6
  831 u_char  ether_ip6multicast_min[ETHER_ADDR_LEN] =
  832     { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 };
  833 u_char  ether_ip6multicast_max[ETHER_ADDR_LEN] =
  834     { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff };
  835 #endif
  836 
  837 /*
  838  * Convert a sockaddr into an Ethernet address or range of Ethernet
  839  * addresses.
  840  */
  841 int
  842 ether_multiaddr(struct sockaddr *sa, u_int8_t addrlo[ETHER_ADDR_LEN],
  843     u_int8_t addrhi[ETHER_ADDR_LEN])
  844 {
  845         struct sockaddr_in *sin;
  846 #ifdef INET6
  847         struct sockaddr_in6 *sin6;
  848 #endif /* INET6 */
  849 
  850         switch (sa->sa_family) {
  851 
  852         case AF_UNSPEC:
  853                 memcpy(addrlo, sa->sa_data, ETHER_ADDR_LEN);
  854                 memcpy(addrhi, addrlo, ETHER_ADDR_LEN);
  855                 break;
  856 
  857         case AF_INET:
  858                 sin = satosin(sa);
  859                 if (sin->sin_addr.s_addr == INADDR_ANY) {
  860                         /*
  861                          * An IP address of INADDR_ANY means listen to
  862                          * or stop listening to all of the Ethernet
  863                          * multicast addresses used for IP.
  864                          * (This is for the sake of IP multicast routers.)
  865                          */
  866                         memcpy(addrlo, ether_ipmulticast_min, ETHER_ADDR_LEN);
  867                         memcpy(addrhi, ether_ipmulticast_max, ETHER_ADDR_LEN);
  868                 } else {
  869                         ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
  870                         memcpy(addrhi, addrlo, ETHER_ADDR_LEN);
  871                 }
  872                 break;
  873 #ifdef INET6
  874         case AF_INET6:
  875                 sin6 = satosin6(sa);
  876                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
  877                         /*
  878                          * An IP6 address of 0 means listen to or stop
  879                          * listening to all of the Ethernet multicast
  880                          * address used for IP6.
  881                          *
  882                          * (This might not be healthy, given IPv6's reliance on
  883                          * multicast for things like neighbor discovery.
  884                          * Perhaps initializing all-nodes, solicited nodes, and
  885                          * possibly all-routers for this interface afterwards
  886                          * is not a bad idea.)
  887                          */
  888 
  889                         memcpy(addrlo, ether_ip6multicast_min, ETHER_ADDR_LEN);
  890                         memcpy(addrhi, ether_ip6multicast_max, ETHER_ADDR_LEN);
  891                 } else {
  892                         ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo);
  893                         memcpy(addrhi, addrlo, ETHER_ADDR_LEN);
  894                 }
  895                 break;
  896 #endif
  897 
  898         default:
  899                 return (EAFNOSUPPORT);
  900         }
  901         return (0);
  902 }
  903 
  904 /*
  905  * Add an Ethernet multicast address or range of addresses to the list for a
  906  * given interface.
  907  */
  908 int
  909 ether_addmulti(struct ifreq *ifr, struct arpcom *ac)
  910 {
  911         struct ether_multi *enm;
  912         u_char addrlo[ETHER_ADDR_LEN];
  913         u_char addrhi[ETHER_ADDR_LEN];
  914         int s = splnet(), error;
  915 
  916         error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
  917         if (error != 0) {
  918                 splx(s);
  919                 return (error);
  920         }
  921 
  922         /*
  923          * Verify that we have valid Ethernet multicast addresses.
  924          */
  925         if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
  926                 splx(s);
  927                 return (EINVAL);
  928         }
  929         /*
  930          * See if the address range is already in the list.
  931          */
  932         ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
  933         if (enm != NULL) {
  934                 /*
  935                  * Found it; just increment the reference count.
  936                  */
  937                 ++enm->enm_refcount;
  938                 splx(s);
  939                 return (0);
  940         }
  941         /*
  942          * New address or range; malloc a new multicast record
  943          * and link it into the interface's multicast list.
  944          */
  945         enm = malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);
  946         if (enm == NULL) {
  947                 splx(s);
  948                 return (ENOBUFS);
  949         }
  950         memcpy(enm->enm_addrlo, addrlo, ETHER_ADDR_LEN);
  951         memcpy(enm->enm_addrhi, addrhi, ETHER_ADDR_LEN);
  952         enm->enm_refcount = 1;
  953         LIST_INSERT_HEAD(&ac->ac_multiaddrs, enm, enm_list);
  954         ac->ac_multicnt++;
  955         if (memcmp(addrlo, addrhi, ETHER_ADDR_LEN) != 0)
  956                 ac->ac_multirangecnt++;
  957         splx(s);
  958         /*
  959          * Return ENETRESET to inform the driver that the list has changed
  960          * and its reception filter should be adjusted accordingly.
  961          */
  962         return (ENETRESET);
  963 }
  964 
  965 /*
  966  * Delete a multicast address record.
  967  */
  968 int
  969 ether_delmulti(struct ifreq *ifr, struct arpcom *ac)
  970 {
  971         struct ether_multi *enm;
  972         u_char addrlo[ETHER_ADDR_LEN];
  973         u_char addrhi[ETHER_ADDR_LEN];
  974         int s = splnet(), error;
  975 
  976         error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
  977         if (error != 0) {
  978                 splx(s);
  979                 return (error);
  980         }
  981 
  982         /*
  983          * Look up the address in our list.
  984          */
  985         ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
  986         if (enm == NULL) {
  987                 splx(s);
  988                 return (ENXIO);
  989         }
  990         if (--enm->enm_refcount != 0) {
  991                 /*
  992                  * Still some claims to this record.
  993                  */
  994                 splx(s);
  995                 return (0);
  996         }
  997         /*
  998          * No remaining claims to this record; unlink and free it.
  999          */
 1000         LIST_REMOVE(enm, enm_list);
 1001         free(enm, M_IFMADDR, sizeof *enm);
 1002         ac->ac_multicnt--;
 1003         if (memcmp(addrlo, addrhi, ETHER_ADDR_LEN) != 0)
 1004                 ac->ac_multirangecnt--;
 1005         splx(s);
 1006         /*
 1007          * Return ENETRESET to inform the driver that the list has changed
 1008          * and its reception filter should be adjusted accordingly.
 1009          */
 1010         return (ENETRESET);
 1011 }
 1012 
 1013 uint64_t
 1014 ether_addr_to_e64(const struct ether_addr *ea)
 1015 {
 1016         uint64_t e64 = 0;
 1017         size_t i;
 1018 
 1019         for (i = 0; i < nitems(ea->ether_addr_octet); i++) {
 1020                 e64 <<= 8;
 1021                 e64 |= ea->ether_addr_octet[i];
 1022         }
 1023 
 1024         return (e64);
 1025 }
 1026 
 1027 void
 1028 ether_e64_to_addr(struct ether_addr *ea, uint64_t e64)
 1029 {
 1030         size_t i = nitems(ea->ether_addr_octet);
 1031 
 1032         do {
 1033                 ea->ether_addr_octet[--i] = e64;
 1034                 e64 >>= 8;
 1035         } while (i > 0);
 1036 }

Cache object: 3e8ba1f8b3a087c8f48f367d0fc8e2d3


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