LCOV - code coverage report
Current view: top level - net - if_ethersubr.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 264 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 15 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: if_ethersubr.c,v 1.253 2018/03/13 01:31:48 dlg 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/protosw.h>
      84             : #include <sys/socket.h>
      85             : #include <sys/ioctl.h>
      86             : #include <sys/errno.h>
      87             : #include <sys/syslog.h>
      88             : #include <sys/timeout.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 "pppoe.h"
     107             : #if NPPPOE > 0
     108             : #include <net/if_pppoe.h>
     109             : #endif
     110             : 
     111             : #ifdef INET6
     112             : #include <netinet6/in6_var.h>
     113             : #include <netinet6/nd6.h>
     114             : #endif
     115             : 
     116             : #ifdef PIPEX
     117             : #include <net/pipex.h>
     118             : #endif
     119             : 
     120             : #ifdef MPLS
     121             : #include <netmpls/mpls.h>
     122             : #endif /* MPLS */
     123             : 
     124             : u_int8_t etherbroadcastaddr[ETHER_ADDR_LEN] =
     125             :     { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
     126             : u_int8_t etheranyaddr[ETHER_ADDR_LEN] =
     127             :     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
     128             : #define senderr(e) { error = (e); goto bad;}
     129             : 
     130             : int
     131           0 : ether_ioctl(struct ifnet *ifp, struct arpcom *arp, u_long cmd, caddr_t data)
     132             : {
     133           0 :         struct ifreq *ifr = (struct ifreq *)data;
     134             :         int error = 0;
     135             : 
     136           0 :         switch (cmd) {
     137             :         case SIOCSIFADDR:
     138             :                 break;
     139             : 
     140             :         case SIOCSIFMTU:
     141           0 :                 if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu)
     142           0 :                         error = EINVAL;
     143             :                 else
     144           0 :                         ifp->if_mtu = ifr->ifr_mtu;
     145             :                 break;
     146             : 
     147             :         case SIOCADDMULTI:
     148             :         case SIOCDELMULTI:
     149           0 :                 if (ifp->if_flags & IFF_MULTICAST) {
     150           0 :                         error = (cmd == SIOCADDMULTI) ?
     151           0 :                             ether_addmulti(ifr, arp) :
     152           0 :                             ether_delmulti(ifr, arp);
     153           0 :                 } else
     154             :                         error = ENOTTY;
     155             :                 break;
     156             : 
     157             :         default:
     158             :                 error = ENOTTY;
     159           0 :         }
     160             : 
     161           0 :         return (error);
     162             : }
     163             : 
     164             : 
     165             : void
     166           0 : ether_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt)
     167             : {
     168           0 :         switch (rt_key(rt)->sa_family) {
     169             :         case AF_INET:
     170           0 :                 arp_rtrequest(ifp, req, rt);
     171           0 :                 break;
     172             : #ifdef INET6
     173             :         case AF_INET6:
     174           0 :                 nd6_rtrequest(ifp, req, rt);
     175           0 :                 break;
     176             : #endif
     177             :         default:
     178             :                 break;
     179             :         }
     180           0 : }
     181             : /*
     182             :  * Ethernet output routine.
     183             :  * Encapsulate a packet of type family for the local net.
     184             :  * Assumes that ifp is actually pointer to arpcom structure.
     185             :  */
     186             : int
     187           0 : ether_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
     188             :     struct rtentry *rt)
     189             : {
     190             :         u_int16_t etype;
     191           0 :         u_char edst[ETHER_ADDR_LEN];
     192             :         u_char *esrc;
     193             :         struct mbuf *mcopy = NULL;
     194             :         struct ether_header *eh;
     195           0 :         struct arpcom *ac = (struct arpcom *)ifp;
     196           0 :         sa_family_t af = dst->sa_family;
     197             :         int error = 0;
     198             : 
     199           0 :         KASSERT(rt != NULL || ISSET(m->m_flags, M_MCAST|M_BCAST) ||
     200             :                 af == AF_UNSPEC || af == pseudo_AF_HDRCMPLT);
     201             : 
     202             : #ifdef DIAGNOSTIC
     203           0 :         if (ifp->if_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid)) {
     204           0 :                 printf("%s: trying to send packet on wrong domain. "
     205           0 :                     "if %d vs. mbuf %d\n", ifp->if_xname,
     206           0 :                     ifp->if_rdomain, rtable_l2(m->m_pkthdr.ph_rtableid));
     207           0 :         }
     208             : #endif
     209             : 
     210           0 :         esrc = ac->ac_enaddr;
     211             : 
     212           0 :         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
     213           0 :                 senderr(ENETDOWN);
     214             : 
     215           0 :         switch (af) {
     216             :         case AF_INET:
     217           0 :                 error = arpresolve(ifp, rt, m, dst, edst);
     218           0 :                 if (error)
     219           0 :                         return (error == EAGAIN ? 0 : error);
     220             :                 /* If broadcasting on a simplex interface, loopback a copy */
     221           0 :                 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
     222           0 :                     !m->m_pkthdr.pf.routed)
     223           0 :                         mcopy = m_copym(m, 0, M_COPYALL, M_NOWAIT);
     224             :                 etype = htons(ETHERTYPE_IP);
     225           0 :                 break;
     226             : #ifdef INET6
     227             :         case AF_INET6:
     228           0 :                 error = nd6_resolve(ifp, rt, m, dst, edst);
     229           0 :                 if (error)
     230           0 :                         return (error == EAGAIN ? 0 : error);
     231             :                 etype = htons(ETHERTYPE_IPV6);
     232           0 :                 break;
     233             : #endif
     234             : #ifdef MPLS
     235             :         case AF_MPLS:
     236           0 :                 if (rt)
     237           0 :                         dst = rt_key(rt);
     238             :                 else
     239           0 :                         senderr(EHOSTUNREACH);
     240             : 
     241           0 :                 if (!ISSET(ifp->if_xflags, IFXF_MPLS))
     242           0 :                         senderr(ENETUNREACH);
     243             : 
     244           0 :                 switch (dst->sa_family) {
     245             :                         case AF_LINK:
     246           0 :                                 if (satosdl(dst)->sdl_alen < sizeof(edst))
     247           0 :                                         senderr(EHOSTUNREACH);
     248           0 :                                 memcpy(edst, LLADDR(satosdl(dst)),
     249             :                                     sizeof(edst));
     250           0 :                                 break;
     251             : #ifdef INET6
     252             :                         case AF_INET6:
     253           0 :                                 error = nd6_resolve(ifp, rt, m, dst, edst);
     254           0 :                                 if (error)
     255           0 :                                         return (error == EAGAIN ? 0 : error);
     256             :                                 break;
     257             : #endif
     258             :                         case AF_INET:
     259             :                         case AF_MPLS:
     260           0 :                                 error = arpresolve(ifp, rt, m, dst, edst);
     261           0 :                                 if (error)
     262           0 :                                         return (error == EAGAIN ? 0 : error);
     263             :                                 break;
     264             :                         default:
     265           0 :                                 senderr(EHOSTUNREACH);
     266             :                 }
     267             :                 /* XXX handling for simplex devices in case of M/BCAST ?? */
     268           0 :                 if (m->m_flags & (M_BCAST | M_MCAST))
     269           0 :                         etype = htons(ETHERTYPE_MPLS_MCAST);
     270             :                 else
     271             :                         etype = htons(ETHERTYPE_MPLS);
     272             :                 break;
     273             : #endif /* MPLS */
     274             :         case pseudo_AF_HDRCMPLT:
     275           0 :                 eh = (struct ether_header *)dst->sa_data;
     276           0 :                 esrc = eh->ether_shost;
     277             :                 /* FALLTHROUGH */
     278             : 
     279             :         case AF_UNSPEC:
     280           0 :                 eh = (struct ether_header *)dst->sa_data;
     281           0 :                 memcpy(edst, eh->ether_dhost, sizeof(edst));
     282             :                 /* AF_UNSPEC doesn't swap the byte order of the ether_type. */
     283           0 :                 etype = eh->ether_type;
     284           0 :                 break;
     285             : 
     286             :         default:
     287           0 :                 printf("%s: can't handle af%d\n", ifp->if_xname,
     288           0 :                         dst->sa_family);
     289           0 :                 senderr(EAFNOSUPPORT);
     290             :         }
     291             : 
     292             :         /* XXX Should we feed-back an unencrypted IPsec packet ? */
     293           0 :         if (mcopy)
     294           0 :                 if_input_local(ifp, mcopy, dst->sa_family);
     295             : 
     296           0 :         M_PREPEND(m, sizeof(struct ether_header) + ETHER_ALIGN, M_DONTWAIT);
     297           0 :         if (m == NULL)
     298           0 :                 return (ENOBUFS);
     299           0 :         m_adj(m, ETHER_ALIGN);
     300           0 :         eh = mtod(m, struct ether_header *);
     301           0 :         eh->ether_type = etype;
     302           0 :         memcpy(eh->ether_dhost, edst, sizeof(eh->ether_dhost));
     303           0 :         memcpy(eh->ether_shost, esrc, sizeof(eh->ether_shost));
     304             : 
     305           0 :         return (if_enqueue(ifp, m));
     306             : bad:
     307           0 :         m_freem(m);
     308           0 :         return (error);
     309           0 : }
     310             : 
     311             : /*
     312             :  * Process a received Ethernet packet;
     313             :  * the packet is in the mbuf chain m without
     314             :  * the ether header, which is provided separately.
     315             :  */
     316             : int
     317           0 : ether_input(struct ifnet *ifp, struct mbuf *m, void *cookie)
     318             : {
     319             :         struct ether_header *eh;
     320             :         void (*input)(struct ifnet *, struct mbuf *);
     321             :         u_int16_t etype;
     322             :         struct arpcom *ac;
     323             : 
     324             :         /* Drop short frames */
     325           0 :         if (m->m_len < ETHER_HDR_LEN)
     326             :                 goto dropanyway;
     327             : 
     328           0 :         ac = (struct arpcom *)ifp;
     329           0 :         eh = mtod(m, struct ether_header *);
     330             : 
     331             :         /* Is the packet for us? */
     332           0 :         if (memcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN) != 0) {
     333             : 
     334             :                 /* If not, it must be multicast or broadcast to go further */
     335           0 :                 if (!ETHER_IS_MULTICAST(eh->ether_dhost))
     336             :                         goto dropanyway;
     337             : 
     338             :                 /*
     339             :                  * If this is not a simplex interface, drop the packet
     340             :                  * if it came from us.
     341             :                  */
     342           0 :                 if ((ifp->if_flags & IFF_SIMPLEX) == 0) {
     343           0 :                         if (memcmp(ac->ac_enaddr, eh->ether_shost,
     344           0 :                             ETHER_ADDR_LEN) == 0)
     345             :                                 goto dropanyway;
     346             :                 }
     347             : 
     348           0 :                 if (memcmp(etherbroadcastaddr, eh->ether_dhost,
     349           0 :                     ETHER_ADDR_LEN) == 0)
     350           0 :                         m->m_flags |= M_BCAST;
     351             :                 else
     352           0 :                         m->m_flags |= M_MCAST;
     353           0 :                 ifp->if_imcasts++;
     354           0 :         }
     355             : 
     356             :         /*
     357             :          * HW vlan tagged packets that were not collected by vlan(4) must
     358             :          * be dropped now.
     359             :          */
     360           0 :         if (m->m_flags & M_VLANTAG)
     361             :                 goto dropanyway;
     362             : 
     363           0 :         etype = ntohs(eh->ether_type);
     364             : 
     365           0 :         switch (etype) {
     366             :         case ETHERTYPE_IP:
     367             :                 input = ipv4_input;
     368           0 :                 break;
     369             : 
     370             :         case ETHERTYPE_ARP:
     371           0 :                 if (ifp->if_flags & IFF_NOARP)
     372             :                         goto dropanyway;
     373             :                 input = arpinput;
     374           0 :                 break;
     375             : 
     376             :         case ETHERTYPE_REVARP:
     377           0 :                 if (ifp->if_flags & IFF_NOARP)
     378             :                         goto dropanyway;
     379             :                 input = revarpinput;
     380           0 :                 break;
     381             : 
     382             : #ifdef INET6
     383             :         /*
     384             :          * Schedule IPv6 software interrupt for incoming IPv6 packet.
     385             :          */
     386             :         case ETHERTYPE_IPV6:
     387             :                 input = ipv6_input;
     388           0 :                 break;
     389             : #endif /* INET6 */
     390             : #if NPPPOE > 0 || defined(PIPEX)
     391             :         case ETHERTYPE_PPPOEDISC:
     392             :         case ETHERTYPE_PPPOE:
     393           0 :                 if (m->m_flags & (M_MCAST | M_BCAST))
     394             :                         goto dropanyway;
     395             : #ifdef PIPEX
     396           0 :                 if (pipex_enable) {
     397             :                         struct pipex_session *session;
     398             : 
     399           0 :                         if ((session = pipex_pppoe_lookup_session(m)) != NULL) {
     400           0 :                                 pipex_pppoe_input(m, session);
     401           0 :                                 return (1);
     402             :                         }
     403           0 :                 }
     404             : #endif
     405           0 :                 if (etype == ETHERTYPE_PPPOEDISC)
     406           0 :                         niq_enqueue(&pppoediscinq, m);
     407             :                 else
     408           0 :                         niq_enqueue(&pppoeinq, m);
     409           0 :                 return (1);
     410             : #endif
     411             : #ifdef MPLS
     412             :         case ETHERTYPE_MPLS:
     413             :         case ETHERTYPE_MPLS_MCAST:
     414             :                 input = mpls_input;
     415           0 :                 break;
     416             : #endif
     417             :         default:
     418             :                 goto dropanyway;
     419             :         }
     420             : 
     421           0 :         m_adj(m, sizeof(*eh));
     422           0 :         (*input)(ifp, m);
     423           0 :         return (1);
     424             : dropanyway:
     425           0 :         m_freem(m);
     426           0 :         return (1);
     427           0 : }
     428             : 
     429             : /*
     430             :  * Convert Ethernet address to printable (loggable) representation.
     431             :  */
     432             : static char digits[] = "0123456789abcdef";
     433             : char *
     434           0 : ether_sprintf(u_char *ap)
     435             : {
     436             :         int i;
     437             :         static char etherbuf[ETHER_ADDR_LEN * 3];
     438             :         char *cp = etherbuf;
     439             : 
     440           0 :         for (i = 0; i < ETHER_ADDR_LEN; i++) {
     441           0 :                 *cp++ = digits[*ap >> 4];
     442           0 :                 *cp++ = digits[*ap++ & 0xf];
     443           0 :                 *cp++ = ':';
     444             :         }
     445           0 :         *--cp = 0;
     446           0 :         return (etherbuf);
     447             : }
     448             : 
     449             : /*
     450             :  * Generate a (hopefully) acceptable MAC address, if asked.
     451             :  */
     452             : void
     453           0 : ether_fakeaddr(struct ifnet *ifp)
     454             : {
     455             :         static int unit;
     456           0 :         int rng = arc4random();
     457             : 
     458             :         /* Non-multicast; locally administered address */
     459           0 :         ((struct arpcom *)ifp)->ac_enaddr[0] = 0xfe;
     460           0 :         ((struct arpcom *)ifp)->ac_enaddr[1] = 0xe1;
     461           0 :         ((struct arpcom *)ifp)->ac_enaddr[2] = 0xba;
     462           0 :         ((struct arpcom *)ifp)->ac_enaddr[3] = 0xd0 | (unit++ & 0xf);
     463           0 :         ((struct arpcom *)ifp)->ac_enaddr[4] = rng;
     464           0 :         ((struct arpcom *)ifp)->ac_enaddr[5] = rng >> 8;
     465           0 : }
     466             : 
     467             : /*
     468             :  * Perform common duties while attaching to interface list
     469             :  */
     470             : void
     471           0 : ether_ifattach(struct ifnet *ifp)
     472             : {
     473           0 :         struct arpcom *ac = (struct arpcom *)ifp;
     474             : 
     475             :         /*
     476             :          * Any interface which provides a MAC address which is obviously
     477             :          * invalid gets whacked, so that users will notice.
     478             :          */
     479           0 :         if (ETHER_IS_MULTICAST(((struct arpcom *)ifp)->ac_enaddr))
     480           0 :                 ether_fakeaddr(ifp);
     481             : 
     482           0 :         ifp->if_type = IFT_ETHER;
     483           0 :         ifp->if_addrlen = ETHER_ADDR_LEN;
     484           0 :         ifp->if_hdrlen = ETHER_HDR_LEN;
     485           0 :         ifp->if_mtu = ETHERMTU;
     486           0 :         ifp->if_output = ether_output;
     487           0 :         ifp->if_rtrequest = ether_rtrequest;
     488             : 
     489           0 :         if_ih_insert(ifp, ether_input, NULL);
     490             : 
     491           0 :         if (ifp->if_hardmtu == 0)
     492           0 :                 ifp->if_hardmtu = ETHERMTU;
     493             : 
     494           0 :         if_alloc_sadl(ifp);
     495           0 :         memcpy(LLADDR(ifp->if_sadl), ac->ac_enaddr, ifp->if_addrlen);
     496           0 :         LIST_INIT(&ac->ac_multiaddrs);
     497             : #if NBPFILTER > 0
     498           0 :         bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, ETHER_HDR_LEN);
     499             : #endif
     500           0 : }
     501             : 
     502             : void
     503           0 : ether_ifdetach(struct ifnet *ifp)
     504             : {
     505           0 :         struct arpcom *ac = (struct arpcom *)ifp;
     506             :         struct ether_multi *enm;
     507             : 
     508             :         /* Undo pseudo-driver changes. */
     509           0 :         if_deactivate(ifp);
     510             : 
     511           0 :         if_ih_remove(ifp, ether_input, NULL);
     512             : 
     513           0 :         KASSERT(SRPL_EMPTY_LOCKED(&ifp->if_inputs));
     514             : 
     515           0 :         for (enm = LIST_FIRST(&ac->ac_multiaddrs);
     516           0 :             enm != NULL;
     517           0 :             enm = LIST_FIRST(&ac->ac_multiaddrs)) {
     518           0 :                 LIST_REMOVE(enm, enm_list);
     519           0 :                 free(enm, M_IFMADDR, sizeof *enm);
     520             :         }
     521           0 : }
     522             : 
     523             : #if 0
     524             : /*
     525             :  * This is for reference.  We have table-driven versions of the
     526             :  * crc32 generators, which are faster than the double-loop.
     527             :  */
     528             : u_int32_t __pure
     529             : ether_crc32_le_update(u_int_32_t crc, const u_int8_t *buf, size_t len)
     530             : {
     531             :         u_int32_t c, carry;
     532             :         size_t i, j;
     533             : 
     534             :         for (i = 0; i < len; i++) {
     535             :                 c = buf[i];
     536             :                 for (j = 0; j < 8; j++) {
     537             :                         carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01);
     538             :                         crc >>= 1;
     539             :                         c >>= 1;
     540             :                         if (carry)
     541             :                                 crc = (crc ^ ETHER_CRC_POLY_LE);
     542             :                 }
     543             :         }
     544             : 
     545             :         return (crc);
     546             : }
     547             : 
     548             : u_int32_t __pure
     549             : ether_crc32_be_update(u_int_32_t crc, const u_int8_t *buf, size_t len)
     550             : {
     551             :         u_int32_t c, carry;
     552             :         size_t i, j;
     553             : 
     554             :         for (i = 0; i < len; i++) {
     555             :                 c = buf[i];
     556             :                 for (j = 0; j < 8; j++) {
     557             :                         carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01);
     558             :                         crc <<= 1;
     559             :                         c >>= 1;
     560             :                         if (carry)
     561             :                                 crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
     562             :                 }
     563             :         }
     564             : 
     565             :         return (crc);
     566             : }
     567             : #else
     568             : u_int32_t __pure
     569           0 : ether_crc32_le_update(u_int32_t crc, const u_int8_t *buf, size_t len)
     570             : {
     571             :         static const u_int32_t crctab[] = {
     572             :                 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
     573             :                 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
     574             :                 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
     575             :                 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
     576             :         };
     577             :         size_t i;
     578             : 
     579           0 :         for (i = 0; i < len; i++) {
     580           0 :                 crc ^= buf[i];
     581           0 :                 crc = (crc >> 4) ^ crctab[crc & 0xf];
     582           0 :                 crc = (crc >> 4) ^ crctab[crc & 0xf];
     583             :         }
     584             : 
     585           0 :         return (crc);
     586             : }
     587             : 
     588             : u_int32_t __pure
     589           0 : ether_crc32_be_update(u_int32_t crc, const u_int8_t *buf, size_t len)
     590             : {
     591             :         static const u_int8_t rev[] = {
     592             :                 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
     593             :                 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
     594             :         };
     595             :         static const u_int32_t crctab[] = {
     596             :                 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
     597             :                 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
     598             :                 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
     599             :                 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd
     600             :         };
     601             :         size_t i;
     602             :         u_int8_t data;
     603             : 
     604           0 :         for (i = 0; i < len; i++) {
     605           0 :                 data = buf[i];
     606           0 :                 crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data & 0xf]];
     607           0 :                 crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data >> 4]];
     608             :         }
     609             : 
     610           0 :         return (crc);
     611             : }
     612             : #endif
     613             : 
     614             : u_int32_t
     615           0 : ether_crc32_le(const u_int8_t *buf, size_t len)
     616             : {
     617           0 :         return ether_crc32_le_update(0xffffffff, buf, len);
     618             : }
     619             : 
     620             : u_int32_t
     621           0 : ether_crc32_be(const u_int8_t *buf, size_t len)
     622             : {
     623           0 :         return ether_crc32_be_update(0xffffffff, buf, len);
     624             : }
     625             : 
     626             : u_char  ether_ipmulticast_min[ETHER_ADDR_LEN] =
     627             :     { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
     628             : u_char  ether_ipmulticast_max[ETHER_ADDR_LEN] =
     629             :     { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
     630             : 
     631             : #ifdef INET6
     632             : u_char  ether_ip6multicast_min[ETHER_ADDR_LEN] =
     633             :     { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 };
     634             : u_char  ether_ip6multicast_max[ETHER_ADDR_LEN] =
     635             :     { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff };
     636             : #endif
     637             : 
     638             : /*
     639             :  * Convert a sockaddr into an Ethernet address or range of Ethernet
     640             :  * addresses.
     641             :  */
     642             : int
     643           0 : ether_multiaddr(struct sockaddr *sa, u_int8_t addrlo[ETHER_ADDR_LEN],
     644             :     u_int8_t addrhi[ETHER_ADDR_LEN])
     645             : {
     646             :         struct sockaddr_in *sin;
     647             : #ifdef INET6
     648             :         struct sockaddr_in6 *sin6;
     649             : #endif /* INET6 */
     650             : 
     651           0 :         switch (sa->sa_family) {
     652             : 
     653             :         case AF_UNSPEC:
     654           0 :                 memcpy(addrlo, sa->sa_data, ETHER_ADDR_LEN);
     655           0 :                 memcpy(addrhi, addrlo, ETHER_ADDR_LEN);
     656           0 :                 break;
     657             : 
     658             :         case AF_INET:
     659           0 :                 sin = satosin(sa);
     660           0 :                 if (sin->sin_addr.s_addr == INADDR_ANY) {
     661             :                         /*
     662             :                          * An IP address of INADDR_ANY means listen to
     663             :                          * or stop listening to all of the Ethernet
     664             :                          * multicast addresses used for IP.
     665             :                          * (This is for the sake of IP multicast routers.)
     666             :                          */
     667           0 :                         memcpy(addrlo, ether_ipmulticast_min, ETHER_ADDR_LEN);
     668           0 :                         memcpy(addrhi, ether_ipmulticast_max, ETHER_ADDR_LEN);
     669           0 :                 } else {
     670           0 :                         ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
     671           0 :                         memcpy(addrhi, addrlo, ETHER_ADDR_LEN);
     672             :                 }
     673             :                 break;
     674             : #ifdef INET6
     675             :         case AF_INET6:
     676           0 :                 sin6 = satosin6(sa);
     677           0 :                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
     678             :                         /*
     679             :                          * An IP6 address of 0 means listen to or stop
     680             :                          * listening to all of the Ethernet multicast
     681             :                          * address used for IP6.
     682             :                          *
     683             :                          * (This might not be healthy, given IPv6's reliance on
     684             :                          * multicast for things like neighbor discovery.
     685             :                          * Perhaps initializing all-nodes, solicited nodes, and
     686             :                          * possibly all-routers for this interface afterwards
     687             :                          * is not a bad idea.)
     688             :                          */
     689             : 
     690           0 :                         memcpy(addrlo, ether_ip6multicast_min, ETHER_ADDR_LEN);
     691           0 :                         memcpy(addrhi, ether_ip6multicast_max, ETHER_ADDR_LEN);
     692           0 :                 } else {
     693           0 :                         ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo);
     694           0 :                         memcpy(addrhi, addrlo, ETHER_ADDR_LEN);
     695             :                 }
     696             :                 break;
     697             : #endif
     698             : 
     699             :         default:
     700           0 :                 return (EAFNOSUPPORT);
     701             :         }
     702           0 :         return (0);
     703           0 : }
     704             : 
     705             : /*
     706             :  * Add an Ethernet multicast address or range of addresses to the list for a
     707             :  * given interface.
     708             :  */
     709             : int
     710           0 : ether_addmulti(struct ifreq *ifr, struct arpcom *ac)
     711             : {
     712             :         struct ether_multi *enm;
     713           0 :         u_char addrlo[ETHER_ADDR_LEN];
     714           0 :         u_char addrhi[ETHER_ADDR_LEN];
     715           0 :         int s = splnet(), error;
     716             : 
     717           0 :         error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
     718           0 :         if (error != 0) {
     719           0 :                 splx(s);
     720           0 :                 return (error);
     721             :         }
     722             : 
     723             :         /*
     724             :          * Verify that we have valid Ethernet multicast addresses.
     725             :          */
     726           0 :         if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
     727           0 :                 splx(s);
     728           0 :                 return (EINVAL);
     729             :         }
     730             :         /*
     731             :          * See if the address range is already in the list.
     732             :          */
     733           0 :         ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
     734           0 :         if (enm != NULL) {
     735             :                 /*
     736             :                  * Found it; just increment the reference count.
     737             :                  */
     738           0 :                 ++enm->enm_refcount;
     739           0 :                 splx(s);
     740           0 :                 return (0);
     741             :         }
     742             :         /*
     743             :          * New address or range; malloc a new multicast record
     744             :          * and link it into the interface's multicast list.
     745             :          */
     746           0 :         enm = malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);
     747           0 :         if (enm == NULL) {
     748           0 :                 splx(s);
     749           0 :                 return (ENOBUFS);
     750             :         }
     751           0 :         memcpy(enm->enm_addrlo, addrlo, ETHER_ADDR_LEN);
     752           0 :         memcpy(enm->enm_addrhi, addrhi, ETHER_ADDR_LEN);
     753           0 :         enm->enm_refcount = 1;
     754           0 :         LIST_INSERT_HEAD(&ac->ac_multiaddrs, enm, enm_list);
     755           0 :         ac->ac_multicnt++;
     756           0 :         if (memcmp(addrlo, addrhi, ETHER_ADDR_LEN) != 0)
     757           0 :                 ac->ac_multirangecnt++;
     758           0 :         splx(s);
     759             :         /*
     760             :          * Return ENETRESET to inform the driver that the list has changed
     761             :          * and its reception filter should be adjusted accordingly.
     762             :          */
     763           0 :         return (ENETRESET);
     764           0 : }
     765             : 
     766             : /*
     767             :  * Delete a multicast address record.
     768             :  */
     769             : int
     770           0 : ether_delmulti(struct ifreq *ifr, struct arpcom *ac)
     771             : {
     772             :         struct ether_multi *enm;
     773           0 :         u_char addrlo[ETHER_ADDR_LEN];
     774           0 :         u_char addrhi[ETHER_ADDR_LEN];
     775           0 :         int s = splnet(), error;
     776             : 
     777           0 :         error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
     778           0 :         if (error != 0) {
     779           0 :                 splx(s);
     780           0 :                 return (error);
     781             :         }
     782             : 
     783             :         /*
     784             :          * Look up the address in our list.
     785             :          */
     786           0 :         ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
     787           0 :         if (enm == NULL) {
     788           0 :                 splx(s);
     789           0 :                 return (ENXIO);
     790             :         }
     791           0 :         if (--enm->enm_refcount != 0) {
     792             :                 /*
     793             :                  * Still some claims to this record.
     794             :                  */
     795           0 :                 splx(s);
     796           0 :                 return (0);
     797             :         }
     798             :         /*
     799             :          * No remaining claims to this record; unlink and free it.
     800             :          */
     801           0 :         LIST_REMOVE(enm, enm_list);
     802           0 :         free(enm, M_IFMADDR, sizeof *enm);
     803           0 :         ac->ac_multicnt--;
     804           0 :         if (memcmp(addrlo, addrhi, ETHER_ADDR_LEN) != 0)
     805           0 :                 ac->ac_multirangecnt--;
     806           0 :         splx(s);
     807             :         /*
     808             :          * Return ENETRESET to inform the driver that the list has changed
     809             :          * and its reception filter should be adjusted accordingly.
     810             :          */
     811           0 :         return (ENETRESET);
     812           0 : }

Generated by: LCOV version 1.13