Annotation of XNU/bsd/net/dlil_ethersubr.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  * Copyright (c) 1982, 1989, 1993
        !            24:  *     The Regents of the University of California.  All rights reserved.
        !            25:  *
        !            26:  * Redistribution and use in source and binary forms, with or without
        !            27:  * modification, are permitted provided that the following conditions
        !            28:  * are met:
        !            29:  * 1. Redistributions of source code must retain the above copyright
        !            30:  *    notice, this list of conditions and the following disclaimer.
        !            31:  * 2. Redistributions in binary form must reproduce the above copyright
        !            32:  *    notice, this list of conditions and the following disclaimer in the
        !            33:  *    documentation and/or other materials provided with the distribution.
        !            34:  * 3. All advertising materials mentioning features or use of this software
        !            35:  *    must display the following acknowledgement:
        !            36:  *     This product includes software developed by the University of
        !            37:  *     California, Berkeley and its contributors.
        !            38:  * 4. Neither the name of the University nor the names of its contributors
        !            39:  *    may be used to endorse or promote products derived from this software
        !            40:  *    without specific prior written permission.
        !            41:  *
        !            42:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            43:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            44:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            45:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            46:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            47:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            48:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            49:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            50:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            51:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            52:  * SUCH DAMAGE.
        !            53:  *
        !            54:  */
        !            55: 
        !            56: 
        !            57: 
        !            58: #include <sys/param.h>
        !            59: #include <sys/systm.h>
        !            60: #include <sys/kernel.h>
        !            61: #include <sys/malloc.h>
        !            62: #include <sys/mbuf.h>
        !            63: #include <sys/socket.h>
        !            64: #include <sys/sockio.h>
        !            65: #include <sys/sysctl.h>
        !            66: 
        !            67: #include <net/if.h>
        !            68: #include <net/netisr.h>
        !            69: #include <net/route.h>
        !            70: #include <net/if_llc.h>
        !            71: #include <net/if_dl.h>
        !            72: #include <net/if_types.h>
        !            73: #include <net/ndrv.h>
        !            74: 
        !            75: #if INET
        !            76: #include <netinet/in.h>
        !            77: #include <netinet/in_var.h>
        !            78: #include <netinet/if_ether.h>
        !            79: #include <netinet/in_systm.h>
        !            80: #include <netinet/ip.h>
        !            81: #endif
        !            82: 
        !            83: 
        !            84: #include <sys/socketvar.h>
        !            85: #include <net/if_blue.h>
        !            86: 
        !            87: #include <net/dlil.h>
        !            88: 
        !            89: 
        !            90: #if LLC && CCITT
        !            91: extern struct ifqueue pkintrq;
        !            92: #endif
        !            93: 
        !            94: /* General stuff from if_ethersubr.c - may not need some of it */
        !            95: 
        !            96: #include <netat/at_pat.h>
        !            97: #if NETAT
        !            98: extern struct ifqueue atalkintrq;
        !            99: #endif
        !           100: 
        !           101: 
        !           102: #if BRIDGE
        !           103: #include <net/bridge.h>
        !           104: #endif
        !           105: 
        !           106: /* #include "vlan.h" */
        !           107: #if NVLAN > 0
        !           108: #include <net/if_vlan_var.h>
        !           109: #endif /* NVLAN > 0 */
        !           110: 
        !           111: 
        !           112: extern struct ifnet_blue *blue_if;
        !           113: extern struct mbuf *splitter_input(struct mbuf *, struct ifnet *);
        !           114: 
        !           115: static u_long lo_dlt = 0;
        !           116: static ivedonethis = 0;
        !           117: static int ether_resolvemulti __P((struct ifnet *, struct sockaddr **, 
        !           118:                                    struct sockaddr *));
        !           119: u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
        !           120: 
        !           121: #define IFP2AC(IFP) ((struct arpcom *)IFP)
        !           122: 
        !           123: /* This stuff is new */
        !           124: 
        !           125: #define DB_HEADER_SIZE 20
        !           126: struct en_desc {
        !           127:     short           total_len;
        !           128:     u_short         ethertype;
        !           129:     u_long         dl_tag;
        !           130:     struct ifnet    *ifp;
        !           131:     struct if_proto *proto;
        !           132:     u_long          proto_id_length;
        !           133:     u_long           proto_id_data[8]; /* probably less - proto-id and bitmasks */
        !           134: };
        !           135:     
        !           136: #define LITMUS_SIZE 16
        !           137: #define ETHER_DESC_BLK_SIZE 50
        !           138: #define MAX_INTERFACES 50
        !           139: 
        !           140: /*
        !           141:  * Statics for demux module
        !           142:  */
        !           143: 
        !           144: struct ether_desc_blk_str {
        !           145:     u_long   n_blocks;
        !           146:     u_long   *block_ptr;
        !           147: };
        !           148: 
        !           149: static struct ether_desc_blk_str ether_desc_blk[MAX_INTERFACES];
        !           150: static u_long  litmus_mask[LITMUS_SIZE];
        !           151: static u_long  litmus_length = 0;
        !           152: 
        !           153: 
        !           154: /*
        !           155:  * Temp static for protocol registration XXX
        !           156:  */
        !           157: 
        !           158: #define MAX_EN_COUNT 30
        !           159: 
        !           160: static struct if_proto *en_array[MAX_EN_COUNT];
        !           161: 
        !           162: /*
        !           163:  * This could be done below in-line with heavy casting, but the pointer arithmetic is 
        !           164:  * prone to error.
        !           165:  */
        !           166: 
        !           167: static
        !           168: int  desc_in_bounds(block, current_ptr, offset_length)
        !           169:     u_int  block;
        !           170:     char   *current_ptr;
        !           171:     u_long offset_length;
        !           172: {
        !           173:     u_long end_of_block;
        !           174:     u_long current_ptr_tmp;
        !           175: 
        !           176:     current_ptr_tmp = (u_long) current_ptr;
        !           177:     end_of_block = (u_long) ether_desc_blk[block].block_ptr;
        !           178:     end_of_block += (ETHER_DESC_BLK_SIZE * ether_desc_blk[block].n_blocks);
        !           179:     if ((current_ptr_tmp + offset_length) < end_of_block)
        !           180:        return 1;
        !           181:     else
        !           182:        return 0;
        !           183: }
        !           184: 
        !           185: 
        !           186: /*
        !           187:  * Release all descriptor entries owned by this dl_tag (there may be several).
        !           188:  * Setting the dl_tag to 0 releases the entry. Eventually we should compact-out
        !           189:  * the unused entries.
        !           190:  */
        !           191: static
        !           192: int  ether_del_proto(struct if_proto *proto, u_long dl_tag)
        !           193: {
        !           194:     char *current_ptr = (char *) ether_desc_blk[proto->ifp->family_cookie].block_ptr;
        !           195:     struct en_desc        *ed;
        !           196:     int i;
        !           197:     int found = 0;
        !           198: 
        !           199:     ed = (struct en_desc *) current_ptr;
        !           200: 
        !           201:     while(ed->total_len) {
        !           202:        if (ed->dl_tag == dl_tag) {
        !           203:            found = 1;
        !           204:            ed->dl_tag = 0;
        !           205:        }
        !           206: 
        !           207:        current_ptr += ed->total_len;
        !           208:        ed = (struct en_desc *) current_ptr;
        !           209:     }
        !           210:     
        !           211:     if (found) {
        !           212:        for (i=0; i < MAX_EN_COUNT; i++)
        !           213:            if (en_array[i] == proto) {
        !           214:                en_array[i] = 0;
        !           215:                break;
        !           216:            }
        !           217:        
        !           218:        return 0;
        !           219:     }
        !           220:     else
        !           221:        return ENOENT;
        !           222: }
        !           223: 
        !           224: 
        !           225: 
        !           226: static
        !           227: int  ether_add_proto(struct ddesc_head_str *desc_head, struct if_proto *proto, u_long dl_tag)
        !           228: {
        !           229:    char *current_ptr;
        !           230:    struct dlil_demux_desc  *desc;
        !           231:    u_long                 id_length; /* IN LONGWORDS!!! */
        !           232:    struct en_desc         *ed;
        !           233:    u_long                 *bitmask;
        !           234:    u_long                 *proto_id;
        !           235:    int                    i;
        !           236:    short                  total_length;
        !           237:    u_long                 block_count;
        !           238:    u_long                  *tmp;
        !           239: 
        !           240:    for (i=0; i < MAX_EN_COUNT; i++)
        !           241:        if (en_array[i] == 0) {
        !           242:           en_array[i] = proto;
        !           243:           break;
        !           244:        }
        !           245:    
        !           246:    if (i == MAX_EN_COUNT) {
        !           247:           printf("WARNING: ether_add_proto -- Too many attachments\n");
        !           248:           return ENOMEM;
        !           249:    }
        !           250: 
        !           251:    TAILQ_FOREACH(desc, desc_head, next) {
        !           252:        switch (desc->type) 
        !           253:        {
        !           254:        case DLIL_DESC_RAW:
        !           255:           id_length   = desc->variants.bitmask.proto_id_length;
        !           256:           break;
        !           257:           
        !           258:        case DLIL_DESC_802_2:
        !           259:           id_length = 1; 
        !           260:           break;
        !           261:           
        !           262:        case DLIL_DESC_802_2_SNAP:
        !           263:           id_length = 2;
        !           264:           break;
        !           265:           
        !           266:        default:
        !           267:           return EINVAL;
        !           268:        }
        !           269: 
        !           270: restart:
        !           271:        block_count = ether_desc_blk[proto->ifp->family_cookie].n_blocks;
        !           272:        current_ptr =  (char *) ether_desc_blk[proto->ifp->family_cookie].block_ptr;
        !           273:        ed = (struct en_desc *) current_ptr;
        !           274:        total_length = ((id_length << 2) * 2) + DB_HEADER_SIZE;
        !           275: 
        !           276:        while ((ed->total_len) && (desc_in_bounds(proto->ifp->family_cookie, 
        !           277:                              current_ptr, total_length))) {
        !           278:           if ((ed->dl_tag == 0) && (total_length <= ed->total_len)) 
        !           279:               break;
        !           280:           else
        !           281:               current_ptr += *(short *)current_ptr;
        !           282:           
        !           283:           ed = (struct en_desc *) current_ptr;
        !           284:        }
        !           285: 
        !           286:        if (!desc_in_bounds(proto->ifp->family_cookie, current_ptr, total_length)) {
        !           287: 
        !           288:           tmp = _MALLOC((ETHER_DESC_BLK_SIZE * (block_count + 1)), 
        !           289:                         M_IFADDR, M_NOWAIT);
        !           290:           if (tmp  == 0) {
        !           291:               /*
        !           292:                * Remove any previous descriptors set in the call.
        !           293:                */
        !           294:               ether_del_proto(proto, dl_tag);
        !           295:               return ENOMEM;
        !           296:           }
        !           297: 
        !           298:           bzero(tmp, ETHER_DESC_BLK_SIZE * (block_count + 1));
        !           299:           bcopy(ether_desc_blk[proto->ifp->family_cookie].block_ptr, 
        !           300:                 tmp, (ETHER_DESC_BLK_SIZE * block_count));
        !           301:           FREE(ether_desc_blk[proto->ifp->family_cookie].block_ptr, M_IFADDR);
        !           302:           ether_desc_blk[proto->ifp->family_cookie].n_blocks = block_count + 1;
        !           303:           ether_desc_blk[proto->ifp->family_cookie].block_ptr = tmp;
        !           304:           goto restart;
        !           305:        }
        !           306: 
        !           307:        if (ed->total_len == 0)
        !           308:           ed->total_len = total_length;
        !           309:        ed->ethertype = *((u_short *) desc->native_type);
        !           310: 
        !           311:        ed->dl_tag    = dl_tag;
        !           312:        ed->proto     = proto;
        !           313:        ed->proto_id_length = id_length;
        !           314:        ed->ifp       = proto->ifp;
        !           315: 
        !           316:        switch (desc->type)
        !           317:        {
        !           318:        case DLIL_DESC_RAW:
        !           319:           bcopy(desc->variants.bitmask.proto_id, &ed->proto_id_data[0], (id_length << 2) );
        !           320:           bcopy(desc->variants.bitmask.proto_id_mask, &ed->proto_id_data[id_length],
        !           321:                 (id_length << 2));
        !           322:           break;
        !           323: 
        !           324:        case DLIL_DESC_802_2:
        !           325:           ed->proto_id_data[0] = 0;
        !           326:           bcopy(&desc->variants.desc_802_2, &ed->proto_id_data[0], 3);
        !           327:           ed->proto_id_data[1] = 0xffffff00;
        !           328:           break;
        !           329: 
        !           330:        case DLIL_DESC_802_2_SNAP:
        !           331:           /* XXX Add verification of fixed values here */
        !           332: 
        !           333:           ed->proto_id_data[0] = 0;
        !           334:           ed->proto_id_data[1] = 0;
        !           335:           bcopy(&desc->variants.desc_802_2_SNAP, &ed->proto_id_data[0], 8);
        !           336:           ed->proto_id_data[2] = 0xffffffff;
        !           337:           ed->proto_id_data[3] = 0xffffffff;;
        !           338:           break;  
        !           339:        }
        !           340:        
        !           341:        if (id_length) {
        !           342:           proto_id = (u_long *) &ed->proto_id_data[0];
        !           343:           bitmask  = (u_long *) &ed->proto_id_data[id_length];
        !           344:           for (i=0; i < (id_length); i++) {
        !           345:               litmus_mask[i] &= bitmask[i];
        !           346:               litmus_mask[i] &= proto_id[i];
        !           347:           }
        !           348:           if (id_length > litmus_length)
        !           349:               litmus_length = id_length;
        !           350:        }
        !           351:    }   
        !           352: 
        !           353:    return 0;
        !           354: } 
        !           355: 
        !           356: 
        !           357: static
        !           358: int  ether_shutdown()
        !           359: {
        !           360:     return 0;
        !           361: }
        !           362: 
        !           363: 
        !           364: 
        !           365: 
        !           366: /*
        !           367:  * Process a received Ethernet packet;
        !           368:  * the packet is in the mbuf chain m without
        !           369:  * the ether header, which is provided separately.
        !           370:  */
        !           371: int
        !           372: new_ether_input(m, frame_header, ifp, dl_tag, sync_ok)
        !           373:     struct mbuf  *m;
        !           374:     char         *frame_header;
        !           375:     struct ifnet *ifp;
        !           376:     u_long          dl_tag;
        !           377:     int          sync_ok;
        !           378: 
        !           379: {
        !           380:     register struct ether_header *eh = (struct ether_header *) frame_header;
        !           381:     register struct ifqueue *inq=0;
        !           382:     u_short ether_type;
        !           383:     int s;
        !           384:     u_int16_t ptype = -1;
        !           385:     unsigned char buf[18];
        !           386: 
        !           387: #if ISO || LLC || NETAT
        !           388:     register struct llc *l;
        !           389: #endif
        !           390: 
        !           391: 
        !           392: #if DLIL_BLUEBOX
        !           393: 
        !           394:     /*
        !           395:      * Y-adapter input processing:
        !           396:      *  - Don't split if coming from a dummy if
        !           397:      *  - If coming from a real if, if splitting enabled,
        !           398:      *    then filter the incoming packet
        !           399:      */
        !           400:     if (ifp != (struct ifnet *)blue_if)
        !           401:     {  /* Is splitter turned on? */
        !           402:        if (ifp->if_flags&IFF_SPLITTER)
        !           403:        {       m->m_data -= sizeof(struct ether_header);
        !           404:        m->m_len += sizeof (struct ether_header);
        !           405:        m->m_pkthdr.len += sizeof(struct ether_header);
        !           406:        /*
        !           407:         * Check to see if destined for BlueBox or Rhapsody
        !           408:         * If NULL return, mbuf's been consumed by the BlueBox.
        !           409:         * Otherwise, send on to Rhapsody
        !           410:         */
        !           411:        if ((m = splitter_input(m, ifp)) == NULL)
        !           412:            return EJUSTRETURN;
        !           413:        m->m_data += sizeof(struct ether_header);
        !           414:        m->m_len -= sizeof (struct ether_header);
        !           415:        m->m_pkthdr.len -= sizeof(struct ether_header);
        !           416:        }
        !           417:     } else
        !           418:     {  /* Get the "real" IF */
        !           419:        ifp = ((struct ndrv_cb *)(blue_if->ifb_so->so_pcb))->nd_if;
        !           420:        m->m_pkthdr.rcvif = ifp;
        !           421:        blue_if->pkts_looped_b2r++;
        !           422:     }
        !           423: 
        !           424: #endif
        !           425:     if ((ifp->if_flags & IFF_UP) == 0) {
        !           426:        m_freem(m);
        !           427:        return EJUSTRETURN;
        !           428:     }
        !           429: 
        !           430:     ifp->if_lastchange = time;
        !           431: 
        !           432:     if (eh->ether_dhost[0] & 1) {
        !           433:        if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
        !           434:                 sizeof(etherbroadcastaddr)) == 0)
        !           435:            m->m_flags |= M_BCAST;
        !           436:        else
        !           437:            m->m_flags |= M_MCAST;
        !           438:     }
        !           439:     if (m->m_flags & (M_BCAST|M_MCAST))
        !           440:        ifp->if_imcasts++;
        !           441: 
        !           442:     ether_type = ntohs(eh->ether_type);
        !           443: 
        !           444: #if NVLAN > 0
        !           445:        if (ether_type == vlan_proto) {
        !           446:                if (vlan_input(eh, m) < 0)
        !           447:                        ifp->if_data.ifi_noproto++;
        !           448:                return EJUSTRETURN;
        !           449:        }
        !           450: #endif /* NVLAN > 0 */
        !           451: 
        !           452:     switch (ether_type) {
        !           453: #if INET
        !           454:     case ETHERTYPE_IP:
        !           455:        if (ipflow_fastforward(m))
        !           456:            return EJUSTRETURN;
        !           457:        ptype = mtod(m, struct ip *)->ip_p;
        !           458:        if ((sync_ok == 0) || 
        !           459:            (ptype != IPPROTO_TCP && ptype != IPPROTO_UDP)) {
        !           460:            schednetisr(NETISR_IP); 
        !           461:        }
        !           462: 
        !           463:        inq = &ipintrq;
        !           464:        break;
        !           465: 
        !           466:     case ETHERTYPE_ARP:
        !           467:        schednetisr(NETISR_ARP);
        !           468:        inq = &arpintrq;
        !           469:        break;
        !           470: #endif
        !           471: 
        !           472:     default: {
        !           473: #if NETAT
        !           474:        if (ether_type > ETHERMTU)
        !           475:            return ENOENT;
        !           476:        l = mtod(m, struct llc *);
        !           477:        switch (l->llc_dsap) {
        !           478:        case LLC_SNAP_LSAP:
        !           479: 
        !           480:            /* Temporary hack: check for AppleTalk and AARP packets */
        !           481:            /* WARNING we're checking only on the "ether_type" (the 2 bytes
        !           482:             * of the SNAP header. This shouldn't be a big deal, 
        !           483:             * AppleTalk pat_input is making sure we have the right packets
        !           484:             * because it needs to discrimante AARP from EtherTalk packets.
        !           485:             */
        !           486: 
        !           487:            if (l->llc_ssap == LLC_SNAP_LSAP &&
        !           488:                l->llc_un.type_snap.control == 0x03) {
        !           489: 
        !           490: #ifdef APPLETALK_DEBUG
        !           491:                printf("new_ether_input: SNAP Cntrol type=0x%x Src=%s\n",
        !           492:                       l->llc_un.type_snap.ether_type,
        !           493:                       ether_sprintf(buf, &eh->ether_shost));
        !           494:                printf("                                     Dst=%s\n",
        !           495:                       ether_sprintf(buf, &eh->ether_dhost));
        !           496: #endif /* APPLETALK_DEBUG */
        !           497: 
        !           498:                if ((l->llc_un.type_snap.ether_type == 0x809B) ||
        !           499:                    (l->llc_un.type_snap.ether_type == 0x80F3)) {
        !           500: 
        !           501: 
        !           502:                                /*
        !           503:                                 * note: for AppleTalk we need to pass the enet header of the
        !           504:                                 * packet up stack. To do so, we made sure in that the FULL packet
        !           505:                                 * is copied in the mbuf by the mace driver, and only the m_data and
        !           506:                                 * length have been shifted to make IP and the other guys happy.
        !           507:                                 */
        !           508: 
        !           509:                    m->m_data -= sizeof(*eh);
        !           510:                    m->m_len += sizeof(*eh);
        !           511:                    m->m_pkthdr.len += sizeof(*eh);     
        !           512: #ifdef APPLETALK_DEBUG
        !           513:                    l == (struct llc *)(eh+1);
        !           514:                    if (l->llc_un.type_snap.ether_type == 0x80F3) {
        !           515:                        kprintf("new_ether_input: RCV AppleTalk type=0x%x Src=%s\n",
        !           516:                                l->llc_un.type_snap.ether_type,
        !           517:                                ether_sprintf(buf, &eh->ether_shost));
        !           518:                        kprintf("                                     Dst=%s\n",
        !           519:                                ether_sprintf(buf, &eh->ether_dhost));
        !           520:                    }
        !           521: #endif /* APPLETALK_DEBUG */
        !           522:                    schednetisr(NETISR_APPLETALK);
        !           523:                    inq = &atalkintrq ;
        !           524:                    
        !           525:                    break;
        !           526:                }
        !           527:            }
        !           528:            
        !           529:            break;
        !           530:            
        !           531:            
        !           532:        default:
        !           533:            return ENOENT;
        !           534:        }
        !           535: 
        !           536: #else /*NETAT*/
        !           537:        return ENOENT;
        !           538: #endif /* NETAT */
        !           539: 
        !           540:        }
        !           541:     }
        !           542: 
        !           543:     if (inq == 0)
        !           544:        return ENOENT;
        !           545: 
        !           546:        s = splimp();
        !           547:        if (IF_QFULL(inq)) {
        !           548:                IF_DROP(inq);
        !           549:                m_freem(m);
        !           550:                splx(s);
        !           551:                return EJUSTRETURN;
        !           552:        } else
        !           553:                IF_ENQUEUE(inq, m);
        !           554:        splx(s);
        !           555: 
        !           556:     if ((sync_ok) && 
        !           557:        (ptype == IPPROTO_TCP || ptype == IPPROTO_UDP)) {
        !           558:        extern void ipintr(void);
        !           559: 
        !           560:        s = splnet();
        !           561:        ipintr();
        !           562:        splx(s);
        !           563:     }
        !           564: 
        !           565:     return 0;
        !           566: }
        !           567: 
        !           568: 
        !           569: 
        !           570: 
        !           571: int ether_demux(ifp, m, frame_header, proto)
        !           572:     struct ifnet *ifp;
        !           573:     struct mbuf  *m;
        !           574:     char         *frame_header;
        !           575:     struct if_proto **proto;
        !           576: 
        !           577: {
        !           578:     register struct ether_header *eh = (struct ether_header *)frame_header;
        !           579:     u_short ether_type;
        !           580:     char *current_ptr = (char *) ether_desc_blk[ifp->family_cookie].block_ptr;
        !           581:     struct dlil_demux_desc  *desc;
        !           582:     register u_long          temp;
        !           583:     u_long                 *data;
        !           584:     register struct if_proto *ifproto;
        !           585:     u_long                  i;
        !           586:     struct en_desc          *ed;
        !           587: 
        !           588: 
        !           589:     if (eh->ether_dhost[0] & 1) {
        !           590:        if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
        !           591:                 sizeof(etherbroadcastaddr)) == 0)
        !           592:            m->m_flags |= M_BCAST;
        !           593:        else
        !           594:            m->m_flags |= M_MCAST;
        !           595:     }
        !           596: 
        !           597:     ether_type = ntohs(eh->ether_type);
        !           598: 
        !           599:     /* 
        !           600:      * Search through the connected protocols for a match. 
        !           601:      */
        !           602: 
        !           603: 
        !           604:     data = mtod(m, u_long *);
        !           605:     ed = (struct en_desc *) current_ptr;
        !           606:     while (desc_in_bounds(ifp->family_cookie, current_ptr, DB_HEADER_SIZE)) {
        !           607:        if (ed->total_len == 0)
        !           608:            break;
        !           609: 
        !           610:        if ((ed->dl_tag !=  0) && (ed->ifp == ifp) && 
        !           611:            ((ed->ethertype == ntohs(eh->ether_type)) || (ed->ethertype == 0))) {
        !           612:            if (ed->proto_id_length) {
        !           613:                for (i=0; i < (ed->proto_id_length); i++) {
        !           614:                    temp = ntohs(data[i]) & ed->proto_id_data[ed->proto_id_length + i];
        !           615:                    if ((temp ^ ed->proto_id_data[i]))
        !           616:                        break;
        !           617:                }
        !           618: 
        !           619:                if (i >= (ed->proto_id_length)) {
        !           620:                    *proto = ed->proto;
        !           621:                    return 0;
        !           622:                }
        !           623:            }
        !           624:            else {
        !           625:                *proto = ed->proto;
        !           626:                return 0;
        !           627:            }
        !           628:        }
        !           629:        current_ptr += ed->total_len;
        !           630:        ed = (struct en_desc *) current_ptr;
        !           631:     }
        !           632: 
        !           633: /*
        !           634:     kprintf("ether_demux - No match for <%x><%x><%x><%x><%x><%x><%x<%x>\n",
        !           635:            eh->ether_type,data[0], data[1], data[2], data[3], data[4],data[5],data[6]);
        !           636: */
        !           637: 
        !           638:     return ENOENT;
        !           639: }                      
        !           640: 
        !           641: 
        !           642: 
        !           643: /*
        !           644:  * Ethernet output routine.
        !           645:  * Encapsulate a packet of type family for the local net.
        !           646:  * Use trailer local net encapsulation if enough data in first
        !           647:  * packet leaves a multiple of 512 bytes of data in remainder.
        !           648:  * Assumes that ifp is actually pointer to arpcom structure.
        !           649:  */
        !           650: int
        !           651: ether_frameout(ifp, m, ndest, edst, ether_type)
        !           652:        register struct ifnet   *ifp;
        !           653:        struct mbuf             **m;
        !           654:        struct sockaddr         *ndest;
        !           655:        char                    *edst;
        !           656:        char                    *ether_type;
        !           657: {
        !           658:        register struct ether_header *eh;
        !           659:        int hlen;       /* link layer header lenght */
        !           660:        struct arpcom *ac = IFP2AC(ifp);
        !           661: 
        !           662: 
        !           663:        hlen = ETHER_HDR_LEN;
        !           664: 
        !           665:        /*
        !           666:         * If a simplex interface, and the packet is being sent to our
        !           667:         * Ethernet address or a broadcast address, loopback a copy.
        !           668:         * XXX To make a simplex device behave exactly like a duplex
        !           669:         * device, we should copy in the case of sending to our own
        !           670:         * ethernet address (thus letting the original actually appear
        !           671:         * on the wire). However, we don't do that here for security
        !           672:         * reasons and compatibility with the original behavior.
        !           673:         */
        !           674:        if ((ifp->if_flags & IFF_SIMPLEX) &&
        !           675:            ((*m)->m_flags & M_LOOP)) {
        !           676:            if (lo_dlt == 0) 
        !           677:                dlil_find_dltag(APPLE_IF_FAM_LOOPBACK, 0, PF_INET, &lo_dlt);
        !           678: 
        !           679:            if (lo_dlt) {
        !           680:                if ((*m)->m_flags & M_BCAST) {
        !           681:                    struct mbuf *n = m_copy(*m, 0, (int)M_COPYALL);
        !           682:                    dlil_output(lo_dlt, n, 0, ndest, 0);
        !           683:                } 
        !           684:                else 
        !           685:                {
        !           686:                    if (bcmp(edst,  ac->ac_enaddr, ETHER_ADDR_LEN) == 0) {
        !           687:                        dlil_output(lo_dlt, *m, 0, ndest, 0);
        !           688:                        return EJUSTRETURN;
        !           689:                    }
        !           690:                }
        !           691:            }
        !           692:        }
        !           693: 
        !           694: 
        !           695:        /*
        !           696:         * Add local net header.  If no space in first mbuf,
        !           697:         * allocate another.
        !           698:         */
        !           699:        M_PREPEND(*m, sizeof (struct ether_header), M_DONTWAIT);
        !           700:        if (*m == 0) {
        !           701:            return (EJUSTRETURN);
        !           702:        }
        !           703: 
        !           704: 
        !           705:        eh = mtod(*m, struct ether_header *);
        !           706:        (void)memcpy(&eh->ether_type, ether_type,
        !           707:                sizeof(eh->ether_type));
        !           708:        (void)memcpy(eh->ether_dhost, edst, 6);
        !           709:        (void)memcpy(eh->ether_shost, ac->ac_enaddr,
        !           710:            sizeof(eh->ether_shost));
        !           711: 
        !           712: #if DLIL_BLUEBOX
        !           713:        /*
        !           714:         * We're already to send.  Let's check for the blue box...
        !           715:         */
        !           716:        if (ifp->if_flags&IFF_SPLITTER)
        !           717:        {       
        !           718:            (*m)->m_flags |= 0x10;
        !           719:            if ((*m = splitter_input(*m, ifp)) == NULL) 
        !           720:                return EJUSTRETURN;
        !           721:            else
        !           722:                return (0);
        !           723:        }
        !           724:        else
        !           725: #endif
        !           726:            return 0;
        !           727: }
        !           728: 
        !           729: 
        !           730: static
        !           731: int  ether_add_if(struct ifnet *ifp)
        !           732: {
        !           733:     u_long  i;
        !           734: 
        !           735:     ifp->if_framer = ether_frameout;
        !           736:     ifp->if_demux  = ether_demux;
        !           737: 
        !           738:     for (i=0; i < MAX_INTERFACES; i++)
        !           739:        if (ether_desc_blk[i].n_blocks == 0)
        !           740:            break;
        !           741: 
        !           742:     if (i == MAX_INTERFACES)
        !           743:        return EOVERFLOW;
        !           744: 
        !           745:     ether_desc_blk[i].block_ptr = _MALLOC(ETHER_DESC_BLK_SIZE, M_IFADDR, M_NOWAIT);
        !           746:     if (ether_desc_blk[i].block_ptr == 0)
        !           747:        return ENOMEM;
        !           748: 
        !           749:     ether_desc_blk[i].n_blocks = 1;
        !           750:     bzero(ether_desc_blk[i].block_ptr, ETHER_DESC_BLK_SIZE);
        !           751: 
        !           752:     ifp->family_cookie = i;
        !           753:     
        !           754:     return 0;
        !           755: }
        !           756: 
        !           757: static
        !           758: int  ether_del_if(struct ifnet *ifp)
        !           759: {
        !           760:     if ((ifp->family_cookie < MAX_INTERFACES) &&
        !           761:        (ether_desc_blk[ifp->family_cookie].n_blocks)) {
        !           762:        FREE(ether_desc_blk[ifp->family_cookie].block_ptr, M_IFADDR);
        !           763:        ether_desc_blk[ifp->family_cookie].n_blocks = 0;
        !           764:        return 0;
        !           765:     }
        !           766:     else
        !           767:        return ENOENT;
        !           768: }
        !           769: 
        !           770: 
        !           771: 
        !           772: 
        !           773: int
        !           774: ether_pre_output(ifp, m0, dst_netaddr, route, type, edst, dl_tag )
        !           775:     struct ifnet    *ifp;
        !           776:     struct mbuf     **m0;
        !           777:     struct sockaddr *dst_netaddr;
        !           778:     caddr_t        route;
        !           779:     char           *type;
        !           780:     char            *edst;
        !           781:     u_long         dl_tag;
        !           782: {
        !           783:     struct rtentry  *rt0 = (struct rtentry *) route;
        !           784:     int s;
        !           785:     register struct mbuf *m = *m0;
        !           786:     register struct rtentry *rt;
        !           787:     register struct ether_header *eh;
        !           788:     int off, len = m->m_pkthdr.len;
        !           789:     int hlen;  /* link layer header lenght */
        !           790:     struct arpcom *ac = IFP2AC(ifp);
        !           791: 
        !           792: 
        !           793: 
        !           794:     if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 
        !           795:        return ENETDOWN;
        !           796: 
        !           797:     rt = rt0;
        !           798:     if (rt) {
        !           799:        if ((rt->rt_flags & RTF_UP) == 0) {
        !           800:            rt0 = rt = rtalloc1(dst_netaddr, 1, 0UL);
        !           801:            if (rt0)
        !           802:                rt->rt_refcnt--;
        !           803:            else
        !           804:                return EHOSTUNREACH;
        !           805:        }
        !           806: 
        !           807:        if (rt->rt_flags & RTF_GATEWAY) {
        !           808:            if (rt->rt_gwroute == 0)
        !           809:                goto lookup;
        !           810:            if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
        !           811:                rtfree(rt); rt = rt0;
        !           812:            lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1,
        !           813:                                              0UL);
        !           814:                if ((rt = rt->rt_gwroute) == 0)
        !           815:                    return (EHOSTUNREACH);
        !           816:            }
        !           817:        }
        !           818: 
        !           819:        
        !           820:        if (rt->rt_flags & RTF_REJECT)
        !           821:            if (rt->rt_rmx.rmx_expire == 0 ||
        !           822:                time_second < rt->rt_rmx.rmx_expire)
        !           823:                return (rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
        !           824:     }
        !           825: 
        !           826:     hlen = ETHER_HDR_LEN;
        !           827: 
        !           828:     /*
        !           829:      * Tell ether_frameout it's ok to loop packet unless negated below.
        !           830:      */
        !           831:     m->m_flags |= M_LOOP;
        !           832: 
        !           833:     switch (dst_netaddr->sa_family) {
        !           834: 
        !           835: #if INET
        !           836:     case AF_INET:
        !           837:        if (!arpresolve(ac, rt, m, dst_netaddr, edst, rt0))
        !           838:            return (EJUSTRETURN);       /* if not yet resolved */
        !           839:        off = m->m_pkthdr.len - m->m_len;
        !           840:        *(u_short *)type = htons(ETHERTYPE_IP);
        !           841:        break;
        !           842: #endif
        !           843: 
        !           844:     case AF_UNSPEC:
        !           845:        m->m_flags &= ~M_LOOP;
        !           846:        eh = (struct ether_header *)dst_netaddr->sa_data;
        !           847:        (void)memcpy(edst, eh->ether_dhost, 6);
        !           848:        *(u_short *)type = eh->ether_type;
        !           849:        break;
        !           850:        
        !           851: #if NETAT
        !           852:     case AF_APPLETALK:
        !           853:     {
        !           854:        eh = (struct ether_header *)dst_netaddr->sa_data;
        !           855:        bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, 6);
        !           856:                
        !           857:        *(u_short *)type = m->m_pkthdr.len;
        !           858:     }
        !           859:     break;
        !           860: 
        !           861: #endif /* NETAT */
        !           862: 
        !           863:     default:
        !           864:        kprintf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
        !           865:               dst_netaddr->sa_family);
        !           866: 
        !           867:         return EAFNOSUPPORT;
        !           868:     }
        !           869: 
        !           870:     return (0);
        !           871: }
        !           872: 
        !           873: 
        !           874: 
        !           875: 
        !           876: 
        !           877: int
        !           878: ether_ioctl(dl_tag, ifp, command, data)
        !           879:     u_long       dl_tag;
        !           880:     struct ifnet *ifp;
        !           881:     int          command;
        !           882:     caddr_t      data;
        !           883: {
        !           884:     struct ifaddr *ifa = (struct ifaddr *) data;
        !           885:     struct ifreq *ifr = (struct ifreq *) data;
        !           886:     int error = 0;
        !           887:     boolean_t funnel_state;
        !           888: 
        !           889:     funnel_state = thread_set_funneled(TRUE);
        !           890: 
        !           891:     switch (command) {
        !           892:     case SIOCSIFADDR:
        !           893:        ifp->if_flags |= IFF_UP;
        !           894: 
        !           895:        switch (ifa->ifa_addr->sa_family) {
        !           896: 
        !           897:        case AF_INET:
        !           898: 
        !           899:            if (ifp->if_init)
        !           900:                ifp->if_init(ifp->if_softc);    /* before arpwhohas */
        !           901: 
        !           902: 
        !           903:            arp_ifinit(IFP2AC(ifp), ifa);
        !           904: 
        !           905:            break;
        !           906: 
        !           907:        default:
        !           908:            break;
        !           909:        }
        !           910: 
        !           911:        break;
        !           912: 
        !           913:     case SIOCGIFADDR:
        !           914:     {
        !           915:        struct sockaddr *sa;
        !           916: 
        !           917:        sa = (struct sockaddr *) & ifr->ifr_data;
        !           918:        bcopy(IFP2AC(ifp)->ac_enaddr,
        !           919:              (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
        !           920:     }
        !           921:     break;
        !           922: 
        !           923:     case SIOCSIFMTU:
        !           924:        /*
        !           925:         * Set the interface MTU.
        !           926:         */
        !           927:        if (ifr->ifr_mtu > ETHERMTU) {
        !           928:            error = EINVAL;
        !           929:        } else {
        !           930:            ifp->if_mtu = ifr->ifr_mtu;
        !           931:        }
        !           932:        break;
        !           933:     }
        !           934: 
        !           935:     (void) thread_set_funneled(funnel_state);
        !           936: 
        !           937:     return (error);
        !           938: }
        !           939: 
        !           940: 
        !           941: 
        !           942: 
        !           943: /*
        !           944:  * Y-adapter filter check
        !           945:  * The rules here:
        !           946:  *  For Rhap: return 1
        !           947:  *  For Both: return 0
        !           948:  *  Not for Rhap: return -1
        !           949:  *  Multicast/Broadcast => For Both
        !           950:  *  Atalk address registered
        !           951:  *   filter matches => For Rhap else Not For Rhap
        !           952:  *  IP address registered
        !           953:  *   filter matches => For Rhap else Not For Rhap
        !           954:  *  For Rhap
        !           955:  * Note this is *not* a general filter mechanism in that we know
        !           956:  *  what we *could* be looking for.
        !           957:  * WARNING: this is a big-endian routine.
        !           958:  * Note: ARP and AARP packets are implicitly accepted for "both"
        !           959:  */
        !           960: int
        !           961: Filter_check(struct mbuf **m0)
        !           962: {      register struct BlueFilter *bf;
        !           963:        register unsigned char *p;
        !           964:        register unsigned short *s;
        !           965:        register unsigned long *l;
        !           966:        int total, flags;
        !           967:        struct mbuf *m;
        !           968:        extern struct mbuf *m_pullup(struct mbuf *, int);
        !           969:        extern void kprintf( const char *, ...);
        !           970: #define FILTER_LEN 32
        !           971: 
        !           972:        m = *m0;
        !           973:        flags = m->m_flags;
        !           974:        if (FILTER_LEN > m->m_pkthdr.len)
        !           975:                return(1);
        !           976:        while ((FILTER_LEN > m->m_len) && m->m_next) {
        !           977:                total = m->m_len + (m->m_next)->m_len;
        !           978:                if ((m = m_pullup(m, min(FILTER_LEN, total))) == 0)
        !           979:                        return(-1);
        !           980:        }        
        !           981:        *m0 = m;
        !           982: 
        !           983:        p = mtod(m, unsigned char *);   /* Point to destination media addr */
        !           984:        if (p[0] & 0x01)        /* Multicast/broadcast */
        !           985:                return(0);
        !           986:        s = (unsigned short *)p;
        !           987:        bf = &RhapFilter[BFS_ATALK];
        !           988: #if 0
        !           989:        kprintf("!PKT: %x, %x, %x\n", s[6], s[7],       s[8]);
        !           990: #endif
        !           991: 
        !           992:        if (bf->BF_flags)       /* Filtering Appletalk */
        !           993:        {
        !           994:                l = (unsigned long *)&s[8];
        !           995: #if 0
        !           996:                kprintf("!AT: %x, %x, %x, %x, %x, %x\n", s[6], s[7],
        !           997:                        *l, s[10], s[13], p[30]);
        !           998: #endif
        !           999:                if (s[6] <= ETHERMTU)
        !          1000:                {       if (s[7] == 0xaaaa) /* Could be Atalk */
        !          1001:                        {       /* Verify SNAP header */
        !          1002:                                if (*l == 0x03080007 && s[10] == 0x809b)
        !          1003:                                {       if (s[13] == bf->BF_address &&
        !          1004:                                             p[30] == bf->BF_node)
        !          1005:                                                return(1);
        !          1006:                                } else if (*l == 0x03000000 && s[10] == 0x80f3)
        !          1007:                                        /* AARP pkts aren't net-addressed */
        !          1008:                                        return(0);
        !          1009:                                return(0);
        !          1010:                        } else /* Not for us? */
        !          1011:                                return(0);
        !          1012:                } /* Fall through */
        !          1013:        } /* Fall through */
        !          1014:        bf++;                   /* Look for IP next */
        !          1015:        if (bf->BF_flags)       /* Filtering IP */
        !          1016:        {
        !          1017:                l = (unsigned long *)&s[15];
        !          1018: #if 0
        !          1019:                kprintf("!IP: %x, %x\n", s[6], *l);
        !          1020: #endif
        !          1021:                if (s[6] > ETHERMTU)
        !          1022:                {       if (s[6] == 0x800)      /* Is IP */
        !          1023:                        {       /* Verify IP address */
        !          1024:                                if (*l == bf->BF_address)
        !          1025:                                        return(1);
        !          1026:                                else    /* Not for us */
        !          1027:                                        return(0);
        !          1028:                        } else if (s[6] == 0x806)
        !          1029:                                /* ARP pkts aren't net-addressed */
        !          1030:                                return(0);
        !          1031:                }
        !          1032:        }
        !          1033:        return(0);              /* No filters => Accept */
        !          1034: }
        !          1035: 
        !          1036: 
        !          1037: 
        !          1038: int ether_family_init()
        !          1039: {
        !          1040: 
        !          1041:     int  i;
        !          1042: 
        !          1043:     if (ivedonethis)
        !          1044:        return 0;
        !          1045: 
        !          1046:     ivedonethis = 1;
        !          1047: 
        !          1048: 
        !          1049:     if (dlil_reg_if_modules(APPLE_IF_FAM_ETHERNET, ether_add_if, ether_del_if,
        !          1050:                        ether_add_proto, ether_del_proto,
        !          1051:                            ether_shutdown)) {
        !          1052:        printf("WARNING: ether_family_init -- Can't register if family modules\n");
        !          1053:        return EIO;
        !          1054:     }
        !          1055: 
        !          1056:     for (i=0; i < (LITMUS_SIZE/4); i++)
        !          1057:        litmus_mask[i] = 0xffffffff;
        !          1058: 
        !          1059:     for (i=0; i < MAX_EN_COUNT; i++)
        !          1060:        en_array[i] = (struct if_proto *) 0;
        !          1061: 
        !          1062:     for (i=0; i < MAX_INTERFACES; i++)
        !          1063:        ether_desc_blk[i].n_blocks = 0;
        !          1064: 
        !          1065:     return 0;
        !          1066: }
        !          1067: 
        !          1068: 
        !          1069: 
        !          1070: u_long  ether_attach_inet(struct ifnet *ifp)
        !          1071: {
        !          1072:     struct dlil_proto_reg_str   reg;
        !          1073:     struct dlil_demux_desc      desc;
        !          1074:     struct dlil_demux_desc      desc2;
        !          1075:     u_long                     ip_dl_tag=0;
        !          1076:     u_short en_native=ETHERTYPE_IP;
        !          1077:     u_short arp_native=ETHERTYPE_ARP;
        !          1078:     int   stat;
        !          1079:     int i;
        !          1080: 
        !          1081: 
        !          1082:     for (i=0; i < MAX_EN_COUNT; i++)
        !          1083:        if ((en_array[i]) && (en_array[i]->ifp == ifp) && 
        !          1084:            (en_array[i]->protocol_family == PF_INET)) {
        !          1085:            return en_array[i]->dl_tag;
        !          1086:        }
        !          1087: 
        !          1088:     TAILQ_INIT(&reg.demux_desc_head);
        !          1089:     desc.type = DLIL_DESC_RAW;
        !          1090:     desc.variants.bitmask.proto_id_length = 0;
        !          1091:     desc.variants.bitmask.proto_id = 0;
        !          1092:     desc.variants.bitmask.proto_id_mask = 0;
        !          1093:     desc.native_type = (char *) &en_native;
        !          1094:     TAILQ_INSERT_TAIL(&reg.demux_desc_head, &desc, next);
        !          1095:     reg.interface_family = ifp->if_family;
        !          1096:     reg.unit_number      = ifp->if_unit;
        !          1097:     reg.input            = new_ether_input;
        !          1098:     reg.pre_output       = ether_pre_output;
        !          1099:     reg.event            = 0;
        !          1100:     reg.offer            = 0;
        !          1101:     reg.ioctl            = ether_ioctl;
        !          1102:     reg.default_proto    = 1;
        !          1103:     reg.protocol_family  = PF_INET;
        !          1104: 
        !          1105:     desc2 = desc;
        !          1106:     desc2.native_type = (char *) &arp_native;
        !          1107:     TAILQ_INSERT_TAIL(&reg.demux_desc_head, &desc2, next);
        !          1108: 
        !          1109:     stat = dlil_attach_protocol(&reg, &ip_dl_tag);
        !          1110:     if (stat) {
        !          1111:        printf("WARNING: ether_attach_inet can't attach ip to interface\n");
        !          1112:        return stat;
        !          1113:     }
        !          1114: 
        !          1115:     return ip_dl_tag;
        !          1116: }
        !          1117: 
        !          1118: void ether_attach_at(struct ifnet *ifp, u_long *at_dl_tag, u_long *aarp_dl_tag)
        !          1119: {
        !          1120:     struct dlil_proto_reg_str   reg;
        !          1121:     struct dlil_demux_desc      desc;
        !          1122:     struct dlil_demux_desc      desc2;
        !          1123:     u_short native = 0;           /* 802.2 frames use a length here */
        !          1124:     int   stat;
        !          1125: 
        !          1126:     TAILQ_INIT(&reg.demux_desc_head);
        !          1127:     desc.type = DLIL_DESC_802_2_SNAP;
        !          1128:     desc.variants.desc_802_2_SNAP.dsap = LLC_SNAP_LSAP;
        !          1129:     desc.variants.desc_802_2_SNAP.ssap = LLC_SNAP_LSAP;
        !          1130:     desc.variants.desc_802_2_SNAP.control_code = 0x03;
        !          1131:     desc.variants.desc_802_2_SNAP.org[0] = 0x08;
        !          1132:     desc.variants.desc_802_2_SNAP.org[1] = 0x00;
        !          1133:     desc.variants.desc_802_2_SNAP.org[2] = 0x07;
        !          1134:     desc.variants.desc_802_2_SNAP.protocol_type = 0x809B;
        !          1135:     desc.native_type = (char *) &native;
        !          1136:     TAILQ_INSERT_TAIL(&reg.demux_desc_head, &desc, next);
        !          1137:     reg.interface_family = ifp->if_family;
        !          1138:     reg.unit_number      = ifp->if_unit;
        !          1139:     reg.input            = new_ether_input;
        !          1140:     reg.pre_output       = ether_pre_output;
        !          1141:     reg.event            = 0;
        !          1142:     reg.offer            = 0;
        !          1143:     reg.ioctl            = ether_ioctl;
        !          1144:     reg.default_proto    = 0;
        !          1145:     reg.protocol_family  = PF_APPLETALK;
        !          1146: 
        !          1147:     desc2 = desc;
        !          1148:     desc2.variants.desc_802_2_SNAP.protocol_type = 0x80F3;
        !          1149:     desc2.variants.desc_802_2_SNAP.org[0] = 0;
        !          1150:     desc2.variants.desc_802_2_SNAP.org[1] = 0;
        !          1151:     desc2.variants.desc_802_2_SNAP.org[2] = 0;
        !          1152: 
        !          1153:     TAILQ_INSERT_TAIL(&reg.demux_desc_head, &desc2, next); 
        !          1154: 
        !          1155:     stat = dlil_attach_protocol(&reg, at_dl_tag);
        !          1156:     if (stat) {
        !          1157:        printf("WARNING: ether_attach_at can't attach at to interface\n");
        !          1158:        return;
        !          1159:     }
        !          1160: 
        !          1161:     *aarp_dl_tag = *at_dl_tag;
        !          1162: 
        !          1163: } /* ether_attach_at */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.