[BACK]Return to if_ethersubr.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / net

Annotation of src/sys/net/if_ethersubr.c, Revision 1.50

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

CVSweb <webmaster@jp.NetBSD.org>