[BACK]Return to if_ethersubr.c CVS log [TXT][DIR] Up to [local] / sys / net

Annotation of sys/net/if_ethersubr.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: if_ethersubr.c,v 1.110 2007/06/06 10:04:36 henning 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 <machine/cpu.h>
        !            91:
        !            92: #include <net/if.h>
        !            93: #include <net/netisr.h>
        !            94: #include <net/route.h>
        !            95: #include <net/if_llc.h>
        !            96: #include <net/if_dl.h>
        !            97: #include <net/if_media.h>
        !            98: #include <net/if_types.h>
        !            99:
        !           100: #include <netinet/in.h>
        !           101: #ifdef INET
        !           102: #include <netinet/in_var.h>
        !           103: #endif
        !           104: #include <netinet/if_ether.h>
        !           105: #include <netinet/ip_ipsp.h>
        !           106:
        !           107: #if NBPFILTER > 0
        !           108: #include <net/bpf.h>
        !           109: #endif
        !           110:
        !           111: #include "bridge.h"
        !           112: #if NBRIDGE > 0
        !           113: #include <net/if_bridge.h>
        !           114: #endif
        !           115:
        !           116: #include "vlan.h"
        !           117: #if NVLAN > 0
        !           118: #include <net/if_vlan_var.h>
        !           119: #endif /* NVLAN > 0 */
        !           120:
        !           121: #include "carp.h"
        !           122: #if NCARP > 0
        !           123: #include <netinet/ip_carp.h>
        !           124: #endif
        !           125:
        !           126: #include "pppoe.h"
        !           127: #if NPPPOE > 0
        !           128: #include <net/if_pppoe.h>
        !           129: #endif
        !           130:
        !           131: #include "trunk.h"
        !           132: #if NTRUNK > 0
        !           133: #include <net/if_trunk.h>
        !           134: #endif
        !           135:
        !           136: #ifdef INET6
        !           137: #ifndef INET
        !           138: #include <netinet/in.h>
        !           139: #endif
        !           140: #include <netinet6/in6_var.h>
        !           141: #include <netinet6/nd6.h>
        !           142: #endif
        !           143:
        !           144: #ifdef NETATALK
        !           145: #include <netatalk/at.h>
        !           146: #include <netatalk/at_var.h>
        !           147: #include <netatalk/at_extern.h>
        !           148:
        !           149: extern u_char  at_org_code[ 3 ];
        !           150: extern u_char  aarp_org_code[ 3 ];
        !           151: #endif /* NETATALK */
        !           152:
        !           153: u_char etherbroadcastaddr[ETHER_ADDR_LEN] =
        !           154:     { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
        !           155: #define senderr(e) { error = (e); goto bad;}
        !           156:
        !           157:
        !           158: int
        !           159: ether_ioctl(ifp, arp, cmd, data)
        !           160:        struct ifnet *ifp;
        !           161:        struct arpcom *arp;
        !           162:        u_long cmd;
        !           163:        caddr_t data;
        !           164: {
        !           165:        struct ifaddr *ifa = (struct ifaddr *)data;
        !           166:        int     error = 0;
        !           167:
        !           168:        switch (cmd) {
        !           169:
        !           170:        case SIOCSIFADDR:
        !           171:                switch (ifa->ifa_addr->sa_family) {
        !           172: #ifdef NETATALK
        !           173:                case AF_APPLETALK:
        !           174:                        /* Nothing to do. */
        !           175:                        break;
        !           176: #endif /* NETATALK */
        !           177:                }
        !           178:                break;
        !           179:        default:
        !           180:                break;
        !           181:        }
        !           182:
        !           183:        return error;
        !           184: }
        !           185:
        !           186: /*
        !           187:  * Ethernet output routine.
        !           188:  * Encapsulate a packet of type family for the local net.
        !           189:  * Assumes that ifp is actually pointer to arpcom structure.
        !           190:  */
        !           191: int
        !           192: ether_output(ifp0, m0, dst, rt0)
        !           193:        struct ifnet *ifp0;
        !           194:        struct mbuf *m0;
        !           195:        struct sockaddr *dst;
        !           196:        struct rtentry *rt0;
        !           197: {
        !           198:        u_int16_t etype;
        !           199:        int s, len, error = 0, hdrcmplt = 0;
        !           200:        u_char edst[ETHER_ADDR_LEN], esrc[ETHER_ADDR_LEN];
        !           201:        struct mbuf *m = m0;
        !           202:        struct rtentry *rt;
        !           203:        struct mbuf *mcopy = (struct mbuf *)0;
        !           204:        struct ether_header *eh;
        !           205:        struct arpcom *ac = (struct arpcom *)ifp0;
        !           206:        short mflags;
        !           207:        struct ifnet *ifp = ifp0;
        !           208:
        !           209: #if NTRUNK > 0
        !           210:        if (ifp->if_type == IFT_IEEE8023ADLAG)
        !           211:                senderr(EBUSY);
        !           212: #endif
        !           213:
        !           214: #if NCARP > 0
        !           215:        if (ifp->if_type == IFT_CARP) {
        !           216:                struct ifaddr *ifa;
        !           217:
        !           218:                /* loop back if this is going to the carp interface */
        !           219:                if (dst != NULL && LINK_STATE_IS_UP(ifp0->if_link_state) &&
        !           220:                    (ifa = ifa_ifwithaddr(dst)) != NULL &&
        !           221:                    ifa->ifa_ifp == ifp0)
        !           222:                        return (looutput(ifp0, m, dst, rt0));
        !           223:
        !           224:                ifp = ifp->if_carpdev;
        !           225:                ac = (struct arpcom *)ifp;
        !           226:
        !           227:                if ((ifp0->if_flags & (IFF_UP|IFF_RUNNING)) !=
        !           228:                    (IFF_UP|IFF_RUNNING))
        !           229:                        senderr(ENETDOWN);
        !           230:        }
        !           231: #endif /* NCARP > 0 */
        !           232:
        !           233:        if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
        !           234:                senderr(ENETDOWN);
        !           235:        if ((rt = rt0) != NULL) {
        !           236:                if ((rt->rt_flags & RTF_UP) == 0) {
        !           237:                        if ((rt0 = rt = rtalloc1(dst, 1, 0)) != NULL)
        !           238:                                rt->rt_refcnt--;
        !           239:                        else
        !           240:                                senderr(EHOSTUNREACH);
        !           241:                }
        !           242:                if (rt->rt_flags & RTF_GATEWAY) {
        !           243:                        if (rt->rt_gwroute == 0)
        !           244:                                goto lookup;
        !           245:                        if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
        !           246:                                rtfree(rt); rt = rt0;
        !           247:                        lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, 0);
        !           248:                                if ((rt = rt->rt_gwroute) == 0)
        !           249:                                        senderr(EHOSTUNREACH);
        !           250:                        }
        !           251:                }
        !           252:                if (rt->rt_flags & RTF_REJECT)
        !           253:                        if (rt->rt_rmx.rmx_expire == 0 ||
        !           254:                            time_second < rt->rt_rmx.rmx_expire)
        !           255:                                senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
        !           256:        }
        !           257:
        !           258:        switch (dst->sa_family) {
        !           259:
        !           260: #ifdef INET
        !           261:        case AF_INET:
        !           262:                if (!arpresolve(ac, rt, m, dst, edst))
        !           263:                        return (0);     /* if not yet resolved */
        !           264:                /* If broadcasting on a simplex interface, loopback a copy */
        !           265:                if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
        !           266:                    !m->m_pkthdr.pf.routed)
        !           267:                        mcopy = m_copy(m, 0, (int)M_COPYALL);
        !           268:                etype = htons(ETHERTYPE_IP);
        !           269:                break;
        !           270: #endif
        !           271: #ifdef INET6
        !           272:        case AF_INET6:
        !           273:                if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)edst))
        !           274:                        return (0); /* it must be impossible, but... */
        !           275:                etype = htons(ETHERTYPE_IPV6);
        !           276:                break;
        !           277: #endif
        !           278: #ifdef NETATALK
        !           279:        case AF_APPLETALK: {
        !           280:                struct at_ifaddr *aa;
        !           281:
        !           282:                if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst)) {
        !           283: #ifdef NETATALKDEBUG
        !           284:                        extern char *prsockaddr(struct sockaddr *);
        !           285:                        printf("aarpresolv: failed for %s\n", prsockaddr(dst));
        !           286: #endif /* NETATALKDEBUG */
        !           287:                        return (0);
        !           288:                }
        !           289:
        !           290:                /*
        !           291:                 * ifaddr is the first thing in at_ifaddr
        !           292:                 */
        !           293:                aa = (struct at_ifaddr *)at_ifawithnet(
        !           294:                        (struct sockaddr_at *)dst,
        !           295:                        TAILQ_FIRST(&ifp->if_addrlist));
        !           296:                if (aa == 0)
        !           297:                        goto bad;
        !           298:
        !           299:                /*
        !           300:                 * In the phase 2 case, we need to prepend an mbuf for the llc
        !           301:                 * header. Since we must preserve the value of m, which is
        !           302:                 * passed to us by value, we m_copy() the first mbuf,
        !           303:                 * and use it for our llc header.
        !           304:                 */
        !           305:                if (aa->aa_flags & AFA_PHASE2) {
        !           306:                        struct llc llc;
        !           307:
        !           308:                        M_PREPEND(m, AT_LLC_SIZE, M_DONTWAIT);
        !           309:                        if (m == NULL)
        !           310:                                return (0);
        !           311:                        /*
        !           312:                         * FreeBSD doesn't count the LLC len in
        !           313:                         * ifp->obytes, so they increment a length
        !           314:                         * field here. We don't do this.
        !           315:                         */
        !           316:                        llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
        !           317:                        llc.llc_control = LLC_UI;
        !           318:                        bcopy(at_org_code, llc.llc_snap.org_code,
        !           319:                                sizeof(at_org_code));
        !           320:                        llc.llc_snap.ether_type = htons( ETHERTYPE_AT );
        !           321:                        bcopy(&llc, mtod(m, caddr_t), AT_LLC_SIZE);
        !           322:                        etype = htons(m->m_pkthdr.len);
        !           323:                } else {
        !           324:                        etype = htons(ETHERTYPE_AT);
        !           325:                }
        !           326:                } break;
        !           327: #endif /* NETATALK */
        !           328:        case pseudo_AF_HDRCMPLT:
        !           329:                hdrcmplt = 1;
        !           330:                eh = (struct ether_header *)dst->sa_data;
        !           331:                bcopy((caddr_t)eh->ether_shost, (caddr_t)esrc, sizeof(esrc));
        !           332:                /* FALLTHROUGH */
        !           333:
        !           334:        case AF_UNSPEC:
        !           335:                eh = (struct ether_header *)dst->sa_data;
        !           336:                bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof(edst));
        !           337:                /* AF_UNSPEC doesn't swap the byte order of the ether_type. */
        !           338:                etype = eh->ether_type;
        !           339:                break;
        !           340:
        !           341:        default:
        !           342:                printf("%s: can't handle af%d\n", ifp->if_xname,
        !           343:                        dst->sa_family);
        !           344:                senderr(EAFNOSUPPORT);
        !           345:        }
        !           346:
        !           347:        /* XXX Should we feed-back an unencrypted IPsec packet ? */
        !           348:        if (mcopy)
        !           349:                (void) looutput(ifp, mcopy, dst, rt);
        !           350:
        !           351:        /*
        !           352:         * Add local net header.  If no space in first mbuf,
        !           353:         * allocate another.
        !           354:         */
        !           355:        M_PREPEND(m, ETHER_HDR_LEN, M_DONTWAIT);
        !           356:        if (m == 0)
        !           357:                senderr(ENOBUFS);
        !           358:        eh = mtod(m, struct ether_header *);
        !           359:        bcopy((caddr_t)&etype,(caddr_t)&eh->ether_type,
        !           360:                sizeof(eh->ether_type));
        !           361:        bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof(edst));
        !           362:        if (hdrcmplt)
        !           363:                bcopy((caddr_t)esrc, (caddr_t)eh->ether_shost,
        !           364:                    sizeof(eh->ether_shost));
        !           365:        else
        !           366:                bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost,
        !           367:                    sizeof(eh->ether_shost));
        !           368:
        !           369: #if NCARP > 0
        !           370:        if (ifp0 != ifp && ifp0->if_type == IFT_CARP &&
        !           371:            !(ifp0->if_flags & IFF_LINK1)) {
        !           372:                bcopy((caddr_t)((struct arpcom *)ifp0)->ac_enaddr,
        !           373:                    (caddr_t)eh->ether_shost, sizeof(eh->ether_shost));
        !           374:        }
        !           375: #endif
        !           376:
        !           377: #if NBRIDGE > 0
        !           378:        /*
        !           379:         * Interfaces that are bridge members need special handling
        !           380:         * for output.
        !           381:         */
        !           382:        if (ifp->if_bridge) {
        !           383:                struct m_tag *mtag;
        !           384:
        !           385:                /*
        !           386:                 * Check if this packet has already been sent out through
        !           387:                 * this bridge, in which case we simply send it out
        !           388:                 * without further bridge processing.
        !           389:                 */
        !           390:                for (mtag = m_tag_find(m, PACKET_TAG_BRIDGE, NULL); mtag;
        !           391:                    mtag = m_tag_find(m, PACKET_TAG_BRIDGE, mtag)) {
        !           392: #ifdef DEBUG
        !           393:                        /* Check that the information is there */
        !           394:                        if (mtag->m_tag_len != sizeof(caddr_t)) {
        !           395:                                error = EINVAL;
        !           396:                                goto bad;
        !           397:                        }
        !           398: #endif
        !           399:                        if (!bcmp(&ifp->if_bridge, mtag + 1, sizeof(caddr_t)))
        !           400:                                break;
        !           401:                }
        !           402:                if (mtag == NULL) {
        !           403:                        /* Attach a tag so we can detect loops */
        !           404:                        mtag = m_tag_get(PACKET_TAG_BRIDGE, sizeof(caddr_t),
        !           405:                            M_NOWAIT);
        !           406:                        if (mtag == NULL) {
        !           407:                                error = ENOBUFS;
        !           408:                                goto bad;
        !           409:                        }
        !           410:                        bcopy(&ifp->if_bridge, mtag + 1, sizeof(caddr_t));
        !           411:                        m_tag_prepend(m, mtag);
        !           412:                        error = bridge_output(ifp, m, NULL, NULL);
        !           413:                        return (error);
        !           414:                }
        !           415:        }
        !           416: #endif
        !           417:
        !           418:        mflags = m->m_flags;
        !           419:        len = m->m_pkthdr.len;
        !           420:        s = splnet();
        !           421:        /*
        !           422:         * Queue message on interface, and start output if interface
        !           423:         * not yet active.
        !           424:         */
        !           425:        IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
        !           426:        if (error) {
        !           427:                /* mbuf is already freed */
        !           428:                splx(s);
        !           429:                return (error);
        !           430:        }
        !           431:        ifp->if_obytes += len + ETHER_HDR_LEN;
        !           432: #if NCARP > 0
        !           433:        if (ifp != ifp0)
        !           434:                ifp0->if_obytes += len + ETHER_HDR_LEN;
        !           435: #endif /* NCARP > 0 */
        !           436:        if (mflags & M_MCAST)
        !           437:                ifp->if_omcasts++;
        !           438:        if ((ifp->if_flags & IFF_OACTIVE) == 0)
        !           439:                (*ifp->if_start)(ifp);
        !           440:        splx(s);
        !           441:        return (error);
        !           442:
        !           443: bad:
        !           444:        if (m)
        !           445:                m_freem(m);
        !           446:        return (error);
        !           447: }
        !           448:
        !           449: /*
        !           450:  * Process a received Ethernet packet;
        !           451:  * the packet is in the mbuf chain m without
        !           452:  * the ether header, which is provided separately.
        !           453:  */
        !           454: void
        !           455: ether_input(ifp, eh, m)
        !           456:        struct ifnet *ifp;
        !           457:        struct ether_header *eh;
        !           458:        struct mbuf *m;
        !           459: {
        !           460:        struct ifqueue *inq;
        !           461:        u_int16_t etype;
        !           462:        int s, llcfound = 0;
        !           463:        struct llc *l;
        !           464:        struct arpcom *ac;
        !           465: #if NTRUNK > 0
        !           466:        int i = 0;
        !           467: #endif
        !           468: #if NPPPOE > 0
        !           469:        struct ether_header *eh_tmp;
        !           470: #endif
        !           471:
        !           472:        if (eh == NULL) {
        !           473:                eh = mtod(m, struct ether_header *);
        !           474:                m_adj(m, ETHER_HDR_LEN);
        !           475:        }
        !           476:
        !           477: #if NTRUNK > 0
        !           478:        /* Handle input from a trunk port */
        !           479:        while (ifp->if_type == IFT_IEEE8023ADLAG) {
        !           480:                if (++i > TRUNK_MAX_STACKING ||
        !           481:                    trunk_input(ifp, eh, m) != 0) {
        !           482:                        if (m)
        !           483:                                m_freem(m);
        !           484:                        return;
        !           485:                }
        !           486:
        !           487:                /* Has been set to the trunk interface */
        !           488:                ifp = m->m_pkthdr.rcvif;
        !           489:        }
        !           490: #endif
        !           491:
        !           492:        if ((ifp->if_flags & IFF_UP) == 0) {
        !           493:                m_freem(m);
        !           494:                return;
        !           495:        }
        !           496:        if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
        !           497:                if ((ifp->if_flags & IFF_SIMPLEX) == 0) {
        !           498:                        struct ifaddr *ifa;
        !           499:                        struct sockaddr_dl *sdl = NULL;
        !           500:
        !           501:                        TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
        !           502:                                if ((sdl =
        !           503:                                    (struct sockaddr_dl *)ifa->ifa_addr) &&
        !           504:                                    sdl->sdl_family == AF_LINK)
        !           505:                                        break;
        !           506:                        }
        !           507:                        /*
        !           508:                         * If this is not a simplex interface, drop the packet
        !           509:                         * if it came from us.
        !           510:                         */
        !           511:                        if (sdl && bcmp(LLADDR(sdl), eh->ether_shost,
        !           512:                            ETHER_ADDR_LEN) == 0) {
        !           513:                                m_freem(m);
        !           514:                                return;
        !           515:                        }
        !           516:                }
        !           517:
        !           518:                if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
        !           519:                    sizeof(etherbroadcastaddr)) == 0)
        !           520:                        m->m_flags |= M_BCAST;
        !           521:                else
        !           522:                        m->m_flags |= M_MCAST;
        !           523:                ifp->if_imcasts++;
        !           524:        }
        !           525:
        !           526:        ifp->if_ibytes += m->m_pkthdr.len + sizeof(*eh);
        !           527:
        !           528:        etype = ntohs(eh->ether_type);
        !           529:
        !           530: #if NVLAN > 0
        !           531:        if (etype == ETHERTYPE_VLAN && (vlan_input(eh, m) == 0))
        !           532:                return;
        !           533: #endif
        !           534:
        !           535: #if NBRIDGE > 0
        !           536:        /*
        !           537:         * Tap the packet off here for a bridge, if configured and
        !           538:         * active for this interface.  bridge_input returns
        !           539:         * NULL if it has consumed the packet, otherwise, it
        !           540:         * gets processed as normal.
        !           541:         */
        !           542:        if (ifp->if_bridge) {
        !           543:                if (m->m_flags & M_PROTO1)
        !           544:                        m->m_flags &= ~M_PROTO1;
        !           545:                else {
        !           546:                        m = bridge_input(ifp, eh, m);
        !           547:                        if (m == NULL)
        !           548:                                return;
        !           549:                        /* The bridge has determined it's for us. */
        !           550:                        ifp = m->m_pkthdr.rcvif;
        !           551:                }
        !           552:        }
        !           553: #endif
        !           554:
        !           555: #if NVLAN > 0
        !           556:        if (etype == ETHERTYPE_VLAN) {
        !           557:                /* The bridge did not want the vlan frame either, drop it. */
        !           558:                ifp->if_noproto++;
        !           559:                m_freem(m);
        !           560:                return;
        !           561:        }
        !           562: #endif /* NVLAN > 0 */
        !           563:
        !           564: #if NCARP > 0
        !           565:        if (ifp->if_carp) {
        !           566:                if (ifp->if_type != IFT_CARP &&
        !           567:                    (carp_input(m, (u_int8_t *)&eh->ether_shost,
        !           568:                    (u_int8_t *)&eh->ether_dhost, eh->ether_type) == 0))
        !           569:                        return;
        !           570:                /* Always clear multicast flags if received on a carp address */
        !           571:                else if (ifp->if_type == IFT_CARP &&
        !           572:                    ifp->if_flags & IFF_LINK2 &&
        !           573:                    m->m_flags & (M_BCAST|M_MCAST) &&
        !           574:                    !bcmp(((struct arpcom *)ifp)->ac_enaddr,
        !           575:                    (caddr_t)eh->ether_dhost, ETHER_ADDR_LEN))
        !           576:                        m->m_flags &= ~(M_BCAST|M_MCAST);
        !           577:        }
        !           578: #endif /* NCARP > 0 */
        !           579:
        !           580:        ac = (struct arpcom *)ifp;
        !           581:
        !           582:        /*
        !           583:         * If packet has been filtered by the bpf listener, drop it now
        !           584:         */
        !           585:        if (m->m_flags & M_FILDROP) {
        !           586:                m_free(m);
        !           587:                return;
        !           588:        }
        !           589:
        !           590:        /*
        !           591:         * If packet is unicast and we're in promiscuous mode, make sure it
        !           592:         * is for us.  Drop otherwise.
        !           593:         */
        !           594:        if ((m->m_flags & (M_BCAST|M_MCAST)) == 0 &&
        !           595:            (ifp->if_flags & IFF_PROMISC)) {
        !           596:                if (bcmp(ac->ac_enaddr, (caddr_t)eh->ether_dhost,
        !           597:                    ETHER_ADDR_LEN)) {
        !           598:                        m_freem(m);
        !           599:                        return;
        !           600:                }
        !           601:        }
        !           602:
        !           603: decapsulate:
        !           604:
        !           605:        switch (etype) {
        !           606: #ifdef INET
        !           607:        case ETHERTYPE_IP:
        !           608:                schednetisr(NETISR_IP);
        !           609:                inq = &ipintrq;
        !           610:                break;
        !           611:
        !           612:        case ETHERTYPE_ARP:
        !           613:                if (ifp->if_flags & IFF_NOARP)
        !           614:                        goto dropanyway;
        !           615:                schednetisr(NETISR_ARP);
        !           616:                inq = &arpintrq;
        !           617:                break;
        !           618:
        !           619:        case ETHERTYPE_REVARP:
        !           620:                if (ifp->if_flags & IFF_NOARP)
        !           621:                        goto dropanyway;
        !           622:                revarpinput(m); /* XXX queue? */
        !           623:                return;
        !           624:
        !           625: #endif
        !           626: #ifdef INET6
        !           627:        /*
        !           628:         * Schedule IPv6 software interrupt for incoming IPv6 packet.
        !           629:         */
        !           630:        case ETHERTYPE_IPV6:
        !           631:                schednetisr(NETISR_IPV6);
        !           632:                inq = &ip6intrq;
        !           633:                break;
        !           634: #endif /* INET6 */
        !           635: #ifdef NETATALK
        !           636:        case ETHERTYPE_AT:
        !           637:                schednetisr(NETISR_ATALK);
        !           638:                inq = &atintrq1;
        !           639:                break;
        !           640:        case ETHERTYPE_AARP:
        !           641:                /* probably this should be done with a NETISR as well */
        !           642:                /* XXX queue this */
        !           643:                aarpinput((struct arpcom *)ifp, m);
        !           644:                return;
        !           645: #endif
        !           646: #if NPPPOE > 0
        !           647:        case ETHERTYPE_PPPOEDISC:
        !           648:        case ETHERTYPE_PPPOE:
        !           649:                /* XXX we dont have this flag */
        !           650:                /*
        !           651:                if (m->m_flags & M_PROMISC) {
        !           652:                        m_freem(m);
        !           653:                        return;
        !           654:                }
        !           655:                */
        !           656: #ifndef PPPOE_SERVER
        !           657:                if (m->m_flags & (M_MCAST | M_BCAST)) {
        !           658:                        m_freem(m);
        !           659:                        return;
        !           660:                }
        !           661: #endif
        !           662:                M_PREPEND(m, sizeof(*eh), M_DONTWAIT);
        !           663:                if (m == NULL)
        !           664:                        return;
        !           665:
        !           666:                eh_tmp = mtod(m, struct ether_header *);
        !           667:                bcopy(eh, eh_tmp, sizeof(struct ether_header));
        !           668:
        !           669:                if (etype == ETHERTYPE_PPPOEDISC)
        !           670:                        inq = &ppoediscinq;
        !           671:                else
        !           672:                        inq = &ppoeinq;
        !           673:
        !           674:                schednetisr(NETISR_PPPOE);
        !           675:                break;
        !           676: #endif /* NPPPOE > 0 */
        !           677:        default:
        !           678:                if (llcfound || etype > ETHERMTU)
        !           679:                        goto dropanyway;
        !           680:                llcfound = 1;
        !           681:                l = mtod(m, struct llc *);
        !           682:                switch (l->llc_dsap) {
        !           683:                case LLC_SNAP_LSAP:
        !           684: #ifdef NETATALK
        !           685:                        /*
        !           686:                         * Some protocols (like Appletalk) need special
        !           687:                         * handling depending on if they are type II
        !           688:                         * or SNAP encapsulated. Everything else
        !           689:                         * gets handled by stripping off the SNAP header
        !           690:                         * and going back up to decapsulate.
        !           691:                         */
        !           692:                        if (l->llc_control == LLC_UI &&
        !           693:                            l->llc_ssap == LLC_SNAP_LSAP &&
        !           694:                            Bcmp(&(l->llc_snap.org_code)[0],
        !           695:                            at_org_code, sizeof(at_org_code)) == 0 &&
        !           696:                            ntohs(l->llc_snap.ether_type) == ETHERTYPE_AT) {
        !           697:                                inq = &atintrq2;
        !           698:                                m_adj(m, AT_LLC_SIZE);
        !           699:                                schednetisr(NETISR_ATALK);
        !           700:                                break;
        !           701:                        }
        !           702:
        !           703:                        if (l->llc_control == LLC_UI &&
        !           704:                            l->llc_ssap == LLC_SNAP_LSAP &&
        !           705:                            Bcmp(&(l->llc_snap.org_code)[0],
        !           706:                            aarp_org_code, sizeof(aarp_org_code)) == 0 &&
        !           707:                            ntohs(l->llc_snap.ether_type) == ETHERTYPE_AARP) {
        !           708:                                m_adj(m, AT_LLC_SIZE);
        !           709:                                /* XXX Really this should use netisr too */
        !           710:                                aarpinput((struct arpcom *)ifp, m);
        !           711:                                return;
        !           712:                        }
        !           713: #endif /* NETATALK */
        !           714:                        if (l->llc_control == LLC_UI &&
        !           715:                            l->llc_dsap == LLC_SNAP_LSAP &&
        !           716:                            l->llc_ssap == LLC_SNAP_LSAP) {
        !           717:                                /* SNAP */
        !           718:                                if (m->m_pkthdr.len > etype)
        !           719:                                        m_adj(m, etype - m->m_pkthdr.len);
        !           720:                                m->m_data += 6;         /* XXX */
        !           721:                                m->m_len -= 6;          /* XXX */
        !           722:                                m->m_pkthdr.len -= 6;   /* XXX */
        !           723:                                M_PREPEND(m, sizeof(*eh), M_DONTWAIT);
        !           724:                                if (m == 0)
        !           725:                                        return;
        !           726:                                *mtod(m, struct ether_header *) = *eh;
        !           727:                                goto decapsulate;
        !           728:                        }
        !           729:                        goto dropanyway;
        !           730:                dropanyway:
        !           731:                default:
        !           732:                        m_freem(m);
        !           733:                        return;
        !           734:                }
        !           735:        }
        !           736:
        !           737:        s = splnet();
        !           738:        IF_INPUT_ENQUEUE(inq, m);
        !           739:        splx(s);
        !           740: }
        !           741:
        !           742: /*
        !           743:  * Convert Ethernet address to printable (loggable) representation.
        !           744:  */
        !           745: static char digits[] = "0123456789abcdef";
        !           746: char *
        !           747: ether_sprintf(ap)
        !           748:        u_char *ap;
        !           749: {
        !           750:        int i;
        !           751:        static char etherbuf[ETHER_ADDR_LEN * 3];
        !           752:        char *cp = etherbuf;
        !           753:
        !           754:        for (i = 0; i < ETHER_ADDR_LEN; i++) {
        !           755:                *cp++ = digits[*ap >> 4];
        !           756:                *cp++ = digits[*ap++ & 0xf];
        !           757:                *cp++ = ':';
        !           758:        }
        !           759:        *--cp = 0;
        !           760:        return (etherbuf);
        !           761: }
        !           762:
        !           763: /*
        !           764:  * Perform common duties while attaching to interface list
        !           765:  */
        !           766: void
        !           767: ether_ifattach(ifp)
        !           768:        struct ifnet *ifp;
        !           769: {
        !           770:
        !           771:        /*
        !           772:         * Any interface which provides a MAC address which is obviously
        !           773:         * invalid gets whacked, so that users will notice.
        !           774:         */
        !           775:        if (ETHER_IS_MULTICAST(((struct arpcom *)ifp)->ac_enaddr)) {
        !           776:                ((struct arpcom *)ifp)->ac_enaddr[0] = 0x00;
        !           777:                ((struct arpcom *)ifp)->ac_enaddr[1] = 0xfe;
        !           778:                ((struct arpcom *)ifp)->ac_enaddr[2] = 0xe1;
        !           779:                ((struct arpcom *)ifp)->ac_enaddr[3] = 0xba;
        !           780:                ((struct arpcom *)ifp)->ac_enaddr[4] = 0xd0;
        !           781:                /*
        !           782:                 * XXX use of random() by anything except the scheduler is
        !           783:                 * normally invalid, but this is boot time, so pre-scheduler,
        !           784:                 * and the random subsystem is not alive yet
        !           785:                 */
        !           786:                ((struct arpcom *)ifp)->ac_enaddr[5] = (u_char)random() & 0xff;
        !           787:        }
        !           788:
        !           789:        ifp->if_type = IFT_ETHER;
        !           790:        ifp->if_addrlen = ETHER_ADDR_LEN;
        !           791:        ifp->if_hdrlen = ETHER_HDR_LEN;
        !           792:        ifp->if_mtu = ETHERMTU;
        !           793:        ifp->if_output = ether_output;
        !           794:
        !           795:        if (ifp->if_hardmtu == 0)
        !           796:                ifp->if_hardmtu = ETHERMTU;
        !           797:
        !           798:        if_alloc_sadl(ifp);
        !           799:        bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
        !           800:            LLADDR(ifp->if_sadl), ifp->if_addrlen);
        !           801:        LIST_INIT(&((struct arpcom *)ifp)->ac_multiaddrs);
        !           802: #if NBPFILTER > 0
        !           803:        bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, ETHER_HDR_LEN);
        !           804: #endif
        !           805: }
        !           806:
        !           807: void
        !           808: ether_ifdetach(ifp)
        !           809:        struct ifnet *ifp;
        !           810: {
        !           811:        struct arpcom *ac = (struct arpcom *)ifp;
        !           812:        struct ether_multi *enm;
        !           813:
        !           814:        for (enm = LIST_FIRST(&ac->ac_multiaddrs);
        !           815:            enm != LIST_END(&ac->ac_multiaddrs);
        !           816:            enm = LIST_FIRST(&ac->ac_multiaddrs)) {
        !           817:                LIST_REMOVE(enm, enm_list);
        !           818:                free(enm, M_IFMADDR);
        !           819:        }
        !           820:
        !           821: #if 0
        !           822:        /* moved to if_detach() */
        !           823:        if_free_sadl(ifp);
        !           824: #endif
        !           825: }
        !           826:
        !           827: #if 0
        !           828: /*
        !           829:  * This is for reference.  We have table-driven versions of the
        !           830:  * crc32 generators, which are faster than the double-loop.
        !           831:  */
        !           832: u_int32_t
        !           833: ether_crc32_le(const u_int8_t *buf, size_t len)
        !           834: {
        !           835:        u_int32_t c, crc, carry;
        !           836:        size_t i, j;
        !           837:
        !           838:        crc = 0xffffffffU;      /* initial value */
        !           839:
        !           840:        for (i = 0; i < len; i++) {
        !           841:                c = buf[i];
        !           842:                for (j = 0; j < 8; j++) {
        !           843:                        carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01);
        !           844:                        crc >>= 1;
        !           845:                        c >>= 1;
        !           846:                        if (carry)
        !           847:                                crc = (crc ^ ETHER_CRC_POLY_LE);
        !           848:                }
        !           849:        }
        !           850:
        !           851:        return (crc);
        !           852: }
        !           853:
        !           854: u_int32_t
        !           855: ether_crc32_be(const u_int8_t *buf, size_t len)
        !           856: {
        !           857:        u_int32_t c, crc, carry;
        !           858:        size_t i, j;
        !           859:
        !           860:        crc = 0xffffffffU;      /* initial value */
        !           861:
        !           862:        for (i = 0; i < len; i++) {
        !           863:                c = buf[i];
        !           864:                for (j = 0; j < 8; j++) {
        !           865:                        carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01);
        !           866:                        crc <<= 1;
        !           867:                        c >>= 1;
        !           868:                        if (carry)
        !           869:                                crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
        !           870:                }
        !           871:        }
        !           872:
        !           873:        return (crc);
        !           874: }
        !           875: #else
        !           876: u_int32_t
        !           877: ether_crc32_le(const u_int8_t *buf, size_t len)
        !           878: {
        !           879:        static const u_int32_t crctab[] = {
        !           880:                0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
        !           881:                0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
        !           882:                0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
        !           883:                0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
        !           884:        };
        !           885:        size_t i;
        !           886:        u_int32_t crc;
        !           887:
        !           888:        crc = 0xffffffffU;      /* initial value */
        !           889:
        !           890:        for (i = 0; i < len; i++) {
        !           891:                crc ^= buf[i];
        !           892:                crc = (crc >> 4) ^ crctab[crc & 0xf];
        !           893:                crc = (crc >> 4) ^ crctab[crc & 0xf];
        !           894:        }
        !           895:
        !           896:        return (crc);
        !           897: }
        !           898:
        !           899: u_int32_t
        !           900: ether_crc32_be(const u_int8_t *buf, size_t len)
        !           901: {
        !           902:        static const u_int8_t rev[] = {
        !           903:                0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
        !           904:                0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
        !           905:        };
        !           906:        static const u_int32_t crctab[] = {
        !           907:                0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
        !           908:                0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
        !           909:                0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
        !           910:                0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd
        !           911:        };
        !           912:        size_t i;
        !           913:        u_int32_t crc;
        !           914:        u_int8_t data;
        !           915:
        !           916:        crc = 0xffffffffU;      /* initial value */
        !           917:        for (i = 0; i < len; i++) {
        !           918:                data = buf[i];
        !           919:                crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data & 0xf]];
        !           920:                crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data >> 4]];
        !           921:        }
        !           922:
        !           923:        return (crc);
        !           924: }
        !           925: #endif
        !           926:
        !           927: #ifdef INET
        !           928: u_char ether_ipmulticast_min[ETHER_ADDR_LEN] =
        !           929:     { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
        !           930: u_char ether_ipmulticast_max[ETHER_ADDR_LEN] =
        !           931:     { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
        !           932: #endif
        !           933:
        !           934: #ifdef INET6
        !           935: u_char ether_ip6multicast_min[ETHER_ADDR_LEN] =
        !           936:     { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 };
        !           937: u_char ether_ip6multicast_max[ETHER_ADDR_LEN] =
        !           938:     { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff };
        !           939: #endif
        !           940:
        !           941: /*
        !           942:  * Convert a sockaddr into an Ethernet address or range of Ethernet
        !           943:  * addresses.
        !           944:  */
        !           945: int
        !           946: ether_multiaddr(struct sockaddr *sa, u_int8_t addrlo[ETHER_ADDR_LEN],
        !           947:     u_int8_t addrhi[ETHER_ADDR_LEN])
        !           948: {
        !           949: #ifdef INET
        !           950:        struct sockaddr_in *sin;
        !           951: #endif /* INET */
        !           952: #ifdef INET6
        !           953:        struct sockaddr_in6 *sin6;
        !           954: #endif /* INET6 */
        !           955:
        !           956:        switch (sa->sa_family) {
        !           957:
        !           958:        case AF_UNSPEC:
        !           959:                bcopy(sa->sa_data, addrlo, ETHER_ADDR_LEN);
        !           960:                bcopy(addrlo, addrhi, ETHER_ADDR_LEN);
        !           961:                break;
        !           962:
        !           963: #ifdef INET
        !           964:        case AF_INET:
        !           965:                sin = satosin(sa);
        !           966:                if (sin->sin_addr.s_addr == INADDR_ANY) {
        !           967:                        /*
        !           968:                         * An IP address of INADDR_ANY means listen to
        !           969:                         * or stop listening to all of the Ethernet
        !           970:                         * multicast addresses used for IP.
        !           971:                         * (This is for the sake of IP multicast routers.)
        !           972:                         */
        !           973:                        bcopy(ether_ipmulticast_min, addrlo, ETHER_ADDR_LEN);
        !           974:                        bcopy(ether_ipmulticast_max, addrhi, ETHER_ADDR_LEN);
        !           975:                } else {
        !           976:                        ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
        !           977:                        bcopy(addrlo, addrhi, ETHER_ADDR_LEN);
        !           978:                }
        !           979:                break;
        !           980: #endif
        !           981: #ifdef INET6
        !           982:        case AF_INET6:
        !           983:                sin6 = satosin6(sa);
        !           984:                if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
        !           985:                        /*
        !           986:                         * An IP6 address of 0 means listen to or stop
        !           987:                         * listening to all of the Ethernet multicast
        !           988:                         * address used for IP6.
        !           989:                         *
        !           990:                         * (This might not be healthy, given IPv6's reliance on
        !           991:                         * multicast for things like neighbor discovery.
        !           992:                         * Perhaps initializing all-nodes, solicited nodes, and
        !           993:                         * possibly all-routers for this interface afterwards
        !           994:                         * is not a bad idea.)
        !           995:                         */
        !           996:
        !           997:                        bcopy(ether_ip6multicast_min, addrlo, ETHER_ADDR_LEN);
        !           998:                        bcopy(ether_ip6multicast_max, addrhi, ETHER_ADDR_LEN);
        !           999:                } else {
        !          1000:                        ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo);
        !          1001:                        bcopy(addrlo, addrhi, ETHER_ADDR_LEN);
        !          1002:                }
        !          1003:                break;
        !          1004: #endif
        !          1005:
        !          1006:        default:
        !          1007:                return (EAFNOSUPPORT);
        !          1008:        }
        !          1009:        return (0);
        !          1010: }
        !          1011:
        !          1012: /*
        !          1013:  * Add an Ethernet multicast address or range of addresses to the list for a
        !          1014:  * given interface.
        !          1015:  */
        !          1016: int
        !          1017: ether_addmulti(ifr, ac)
        !          1018:        struct ifreq *ifr;
        !          1019:        struct arpcom *ac;
        !          1020: {
        !          1021:        struct ether_multi *enm;
        !          1022:        u_char addrlo[ETHER_ADDR_LEN];
        !          1023:        u_char addrhi[ETHER_ADDR_LEN];
        !          1024:        int s = splnet(), error;
        !          1025:
        !          1026:        error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
        !          1027:        if (error != 0) {
        !          1028:                splx(s);
        !          1029:                return (error);
        !          1030:        }
        !          1031:
        !          1032:        /*
        !          1033:         * Verify that we have valid Ethernet multicast addresses.
        !          1034:         */
        !          1035:        if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
        !          1036:                splx(s);
        !          1037:                return (EINVAL);
        !          1038:        }
        !          1039:        /*
        !          1040:         * See if the address range is already in the list.
        !          1041:         */
        !          1042:        ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
        !          1043:        if (enm != NULL) {
        !          1044:                /*
        !          1045:                 * Found it; just increment the reference count.
        !          1046:                 */
        !          1047:                ++enm->enm_refcount;
        !          1048:                splx(s);
        !          1049:                return (0);
        !          1050:        }
        !          1051:        /*
        !          1052:         * New address or range; malloc a new multicast record
        !          1053:         * and link it into the interface's multicast list.
        !          1054:         */
        !          1055:        enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);
        !          1056:        if (enm == NULL) {
        !          1057:                splx(s);
        !          1058:                return (ENOBUFS);
        !          1059:        }
        !          1060:        bcopy(addrlo, enm->enm_addrlo, ETHER_ADDR_LEN);
        !          1061:        bcopy(addrhi, enm->enm_addrhi, ETHER_ADDR_LEN);
        !          1062:        enm->enm_ac = ac;
        !          1063:        enm->enm_refcount = 1;
        !          1064:        LIST_INSERT_HEAD(&ac->ac_multiaddrs, enm, enm_list);
        !          1065:        ac->ac_multicnt++;
        !          1066:        if (bcmp(addrlo, addrhi, ETHER_ADDR_LEN) != 0)
        !          1067:                ac->ac_multirangecnt++;
        !          1068:        splx(s);
        !          1069:        /*
        !          1070:         * Return ENETRESET to inform the driver that the list has changed
        !          1071:         * and its reception filter should be adjusted accordingly.
        !          1072:         */
        !          1073:        return (ENETRESET);
        !          1074: }
        !          1075:
        !          1076: /*
        !          1077:  * Delete a multicast address record.
        !          1078:  */
        !          1079: int
        !          1080: ether_delmulti(ifr, ac)
        !          1081:        struct ifreq *ifr;
        !          1082:        struct arpcom *ac;
        !          1083: {
        !          1084:        struct ether_multi *enm;
        !          1085:        u_char addrlo[ETHER_ADDR_LEN];
        !          1086:        u_char addrhi[ETHER_ADDR_LEN];
        !          1087:        int s = splnet(), error;
        !          1088:
        !          1089:        error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
        !          1090:        if (error != 0) {
        !          1091:                splx(s);
        !          1092:                return (error);
        !          1093:        }
        !          1094:
        !          1095:        /*
        !          1096:         * Look up the address in our list.
        !          1097:         */
        !          1098:        ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
        !          1099:        if (enm == NULL) {
        !          1100:                splx(s);
        !          1101:                return (ENXIO);
        !          1102:        }
        !          1103:        if (--enm->enm_refcount != 0) {
        !          1104:                /*
        !          1105:                 * Still some claims to this record.
        !          1106:                 */
        !          1107:                splx(s);
        !          1108:                return (0);
        !          1109:        }
        !          1110:        /*
        !          1111:         * No remaining claims to this record; unlink and free it.
        !          1112:         */
        !          1113:        LIST_REMOVE(enm, enm_list);
        !          1114:        free(enm, M_IFMADDR);
        !          1115:        ac->ac_multicnt--;
        !          1116:        if (bcmp(addrlo, addrhi, ETHER_ADDR_LEN) != 0)
        !          1117:                ac->ac_multirangecnt--;
        !          1118:        splx(s);
        !          1119:        /*
        !          1120:         * Return ENETRESET to inform the driver that the list has changed
        !          1121:         * and its reception filter should be adjusted accordingly.
        !          1122:         */
        !          1123:        return (ENETRESET);
        !          1124: }

CVSweb