[BACK]Return to aarp.c CVS log [TXT][DIR] Up to [local] / sys / netatalk

Annotation of sys/netatalk/aarp.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: aarp.c,v 1.7 2006/04/25 05:52:43 tedu Exp $   */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1990,1991 Regents of The University of Michigan.
        !             5:  * All Rights Reserved.
        !             6:  */
        !             7:
        !             8: /*
        !             9:  * The following is the contents of the COPYRIGHT file from the
        !            10:  * netatalk-1.4a2 distribution, from which this file is derived.
        !            11:  */
        !            12: /*
        !            13:  * Copyright (c) 1990,1996 Regents of The University of Michigan.
        !            14:  *
        !            15:  * All Rights Reserved.
        !            16:  *
        !            17:  *    Permission to use, copy, modify, and distribute this software and
        !            18:  *    its documentation for any purpose and without fee is hereby granted,
        !            19:  *    provided that the above copyright notice appears in all copies and
        !            20:  *    that both that copyright notice and this permission notice appear
        !            21:  *    in supporting documentation, and that the name of The University
        !            22:  *    of Michigan not be used in advertising or publicity pertaining to
        !            23:  *    distribution of the software without specific, written prior
        !            24:  *    permission. This software is supplied as is without expressed or
        !            25:  *    implied warranties of any kind.
        !            26:  *
        !            27:  * This product includes software developed by the University of
        !            28:  * California, Berkeley and its contributors.
        !            29:  *
        !            30:  * Solaris code is encumbered by the following:
        !            31:  *
        !            32:  *     Copyright (C) 1996 by Sun Microsystems Computer Co.
        !            33:  *
        !            34:  *     Permission to use, copy, modify, and distribute this software and
        !            35:  *     its documentation for any purpose and without fee is hereby
        !            36:  *     granted, provided that the above copyright notice appear in all
        !            37:  *     copies and that both that copyright notice and this permission
        !            38:  *     notice appear in supporting documentation.  This software is
        !            39:  *     provided "as is" without express or implied warranty.
        !            40:  *
        !            41:  * Research Systems Unix Group
        !            42:  * The University of Michigan
        !            43:  * c/o Wesley Craig
        !            44:  * 535 W. William Street
        !            45:  * Ann Arbor, Michigan
        !            46:  * +1-313-764-2278
        !            47:  * netatalk@umich.edu
        !            48:  */
        !            49: /*
        !            50:  * None of the Solaris code mentioned is included in OpenBSD.
        !            51:  * This code also relies heavily on previous effort in FreeBSD and NetBSD.
        !            52:  */
        !            53:
        !            54: #include <sys/param.h>
        !            55: #include <sys/systm.h>
        !            56: #include <sys/kernel.h>
        !            57: #include <sys/malloc.h>
        !            58: #include <sys/mbuf.h>
        !            59: #include <sys/protosw.h>
        !            60: #include <sys/socket.h>
        !            61: #include <sys/ioctl.h>
        !            62: #include <sys/errno.h>
        !            63: #include <sys/syslog.h>
        !            64: #include <sys/proc.h>
        !            65: #include <sys/timeout.h>
        !            66:
        !            67: #include <net/if.h>
        !            68: #include <net/route.h>
        !            69: #include <netinet/in.h>
        !            70: #undef s_net
        !            71: #include <netinet/if_ether.h>
        !            72: #include <net/if_llc.h>
        !            73:
        !            74: #include <machine/endian.h>
        !            75:
        !            76: #include <netatalk/at.h>
        !            77: #include <netatalk/at_var.h>
        !            78: #include <netatalk/aarp.h>
        !            79: #include <netatalk/ddp_var.h>
        !            80: #include <netatalk/phase2.h>
        !            81: #include <netatalk/at_extern.h>
        !            82:
        !            83: static void aarptimer(void *);
        !            84: struct ifaddr *at_ifawithnet(struct sockaddr_at *, struct ifaddr *);
        !            85: static void aarpwhohas(struct arpcom *, struct sockaddr_at *);
        !            86: int aarpresolve(struct arpcom *, struct mbuf *,
        !            87:                                        struct sockaddr_at *, u_int8_t *);
        !            88: void aarpinput(struct arpcom *, struct mbuf *);
        !            89: static void at_aarpinput(struct arpcom *, struct mbuf *);
        !            90: static void aarptfree(struct aarptab *);
        !            91: struct aarptab *aarptnew(struct at_addr *);
        !            92: void aarpprobe(void *);
        !            93: void aarp_clean(void);
        !            94:
        !            95: #ifdef GATEWAY
        !            96: #define AARPTAB_BSIZ   16
        !            97: #define AARPTAB_NB     37
        !            98: #else
        !            99: #define AARPTAB_BSIZ   9
        !           100: #define AARPTAB_NB     19
        !           101: #endif /* GATEWAY */
        !           102:
        !           103: #define AARPTAB_SIZE   (AARPTAB_BSIZ * AARPTAB_NB)
        !           104: struct aarptab         aarptab[AARPTAB_SIZE];
        !           105: int                    aarptab_size = AARPTAB_SIZE;
        !           106:
        !           107: struct timeout aarpprobe_timeout;
        !           108: struct timeout aarptimer_timeout;
        !           109:
        !           110: #define AARPTAB_HASH(a) \
        !           111:     ((((a).s_net << 8 ) + (a).s_node ) % AARPTAB_NB )
        !           112:
        !           113: #define AARPTAB_LOOK(aat,addr) { \
        !           114:     int                n; \
        !           115:     aat = &aarptab[ AARPTAB_HASH(addr) * AARPTAB_BSIZ ]; \
        !           116:     for ( n = 0; n < AARPTAB_BSIZ; n++, aat++ ) \
        !           117:        if ( aat->aat_ataddr.s_net == (addr).s_net && \
        !           118:             aat->aat_ataddr.s_node == (addr).s_node ) \
        !           119:            break; \
        !           120:        if ( n >= AARPTAB_BSIZ ) \
        !           121:            aat = 0; \
        !           122: }
        !           123:
        !           124: #define AARPT_AGE      (60 * 1)
        !           125: #define AARPT_KILLC    20
        !           126: #define AARPT_KILLI    3
        !           127:
        !           128: u_int8_t       atmulticastaddr[ 6 ] = {
        !           129:     0x09, 0x00, 0x07, 0xff, 0xff, 0xff,
        !           130: };
        !           131:
        !           132: u_int8_t       at_org_code[ 3 ] = {
        !           133:     0x08, 0x00, 0x07,
        !           134: };
        !           135: u_int8_t       aarp_org_code[ 3 ] = {
        !           136:     0x00, 0x00, 0x00,
        !           137: };
        !           138:
        !           139: /*ARGSUSED*/
        !           140: static void
        !           141: aarptimer(v)
        !           142:        void *v;
        !           143: {
        !           144:     struct aarptab     *aat;
        !           145:     int                        i, s;
        !           146:
        !           147:     timeout_add(&aarptimer_timeout, AARPT_AGE * hz);
        !           148:     aat = aarptab;
        !           149:     for ( i = 0; i < AARPTAB_SIZE; i++, aat++ ) {
        !           150:        if ( aat->aat_flags == 0 || ( aat->aat_flags & ATF_PERM ))
        !           151:            continue;
        !           152:        if ( ++aat->aat_timer < (( aat->aat_flags & ATF_COM ) ?
        !           153:                AARPT_KILLC : AARPT_KILLI ))
        !           154:            continue;
        !           155:        s = splnet();
        !           156:        aarptfree( aat );
        !           157:        splx( s );
        !           158:     }
        !           159: }
        !           160:
        !           161: struct ifaddr *
        !           162: at_ifawithnet( sat, ifa )
        !           163:     struct sockaddr_at *sat;
        !           164:     struct ifaddr      *ifa;
        !           165: {
        !           166:     struct sockaddr_at  *sat2;
        !           167:     struct netrange     *nr;
        !           168:
        !           169:     for (; ifa; ifa = ifa->ifa_list.tqe_next ) {
        !           170:        if ( ifa->ifa_addr->sa_family != AF_APPLETALK ) {
        !           171:            continue;
        !           172:        }
        !           173:        sat2 = satosat( ifa->ifa_addr );
        !           174:        if ( sat2->sat_addr.s_net == sat->sat_addr.s_net ) {
        !           175:            break;
        !           176:        }
        !           177:        nr = (struct netrange *)(sat2->sat_zero);
        !           178:        if( (nr->nr_phase == 2 )
        !           179:         && (ntohs(nr->nr_firstnet) <= ntohs(sat->sat_addr.s_net))
        !           180:         && (ntohs(nr->nr_lastnet) >= ntohs(sat->sat_addr.s_net))) {
        !           181:            break;
        !           182:        }
        !           183:     }
        !           184:     return( ifa );
        !           185: }
        !           186:
        !           187: static void
        !           188: aarpwhohas( ac, sat )
        !           189:     struct arpcom      *ac;
        !           190:     struct sockaddr_at *sat;
        !           191: {
        !           192:     struct mbuf                *m;
        !           193:     struct ether_header        *eh;
        !           194:     struct ether_aarp  *ea;
        !           195:     struct at_ifaddr   *aa;
        !           196:     struct llc         *llc;
        !           197:     struct sockaddr    sa;
        !           198:
        !           199:     if (( m = m_gethdr( M_DONTWAIT, MT_DATA )) == NULL ) {
        !           200:        return;
        !           201:     }
        !           202:     m->m_len = sizeof( *ea );
        !           203:     m->m_pkthdr.len = sizeof( *ea );
        !           204:     MH_ALIGN( m, sizeof( *ea ));
        !           205:
        !           206:     ea = mtod( m, struct ether_aarp *);
        !           207:     bzero((caddr_t)ea, sizeof( *ea ));
        !           208:
        !           209:     ea->aarp_hrd = htons( AARPHRD_ETHER );
        !           210:     ea->aarp_pro = htons( ETHERTYPE_AT );
        !           211:     ea->aarp_hln = sizeof( ea->aarp_sha );
        !           212:     ea->aarp_pln = sizeof( ea->aarp_spu );
        !           213:     ea->aarp_op = htons( AARPOP_REQUEST );
        !           214:     bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->aarp_sha,
        !           215:            sizeof( ea->aarp_sha ));
        !           216:
        !           217:     /*
        !           218:      * We need to check whether the output ethernet type should
        !           219:      * be phase 1 or 2. We have the interface that we'll be sending
        !           220:      * the aarp out. We need to find an AppleTalk network on that
        !           221:      * interface with the same address as we're looking for. If the
        !           222:      * net is phase 2, generate an 802.2 and SNAP header.
        !           223:      */
        !           224:     if (( aa = (struct at_ifaddr *)
        !           225:            at_ifawithnet( sat, ac->ac_if.if_addrlist.tqh_first )) == NULL ) {
        !           226:        m_freem( m );
        !           227:        return;
        !           228:     }
        !           229:
        !           230:     eh = (struct ether_header *)sa.sa_data;
        !           231:
        !           232:     if ( aa->aa_flags & AFA_PHASE2 ) {
        !           233:        bcopy((caddr_t)atmulticastaddr, (caddr_t)eh->ether_dhost,
        !           234:                sizeof( eh->ether_dhost ));
        !           235:        eh->ether_type = htons(AT_LLC_SIZE + sizeof(struct ether_aarp));
        !           236:        M_PREPEND( m, AT_LLC_SIZE, M_DONTWAIT );
        !           237:        if (!m)
        !           238:            return;
        !           239:
        !           240:        llc = mtod( m, struct llc *);
        !           241:        llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
        !           242:        llc->llc_control = LLC_UI;
        !           243:        bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
        !           244:        llc->llc_ether_type = htons( ETHERTYPE_AARP );
        !           245:
        !           246:        bcopy( &AA_SAT( aa )->sat_addr.s_net, ea->aarp_spnet,
        !           247:                sizeof( ea->aarp_spnet ));
        !           248:        ea->aarp_spnode = AA_SAT( aa )->sat_addr.s_node;
        !           249:        bcopy( &sat->sat_addr.s_net, ea->aarp_tpnet,
        !           250:                sizeof( ea->aarp_tpnet ));
        !           251:        ea->aarp_tpnode = sat->sat_addr.s_node;
        !           252:     } else {
        !           253:        bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
        !           254:                sizeof( eh->ether_dhost ));
        !           255:        eh->ether_type = htons( ETHERTYPE_AARP );
        !           256:
        !           257:        ea->aarp_spa = AA_SAT( aa )->sat_addr.s_node;
        !           258:        ea->aarp_tpa = sat->sat_addr.s_node;
        !           259:     }
        !           260:
        !           261:     sa.sa_len = sizeof( struct sockaddr );
        !           262:     sa.sa_family = AF_UNSPEC;
        !           263:     /* XXX The NULL should be a struct rtentry. TBD */
        !           264:     (*ac->ac_if.if_output)(&ac->ac_if, m, &sa , NULL);
        !           265: }
        !           266:
        !           267: int
        !           268: aarpresolve( ac, m, destsat, desten )
        !           269:     struct arpcom      *ac;
        !           270:     struct mbuf                *m;
        !           271:     struct sockaddr_at *destsat;
        !           272:     u_int8_t           *desten;
        !           273: {
        !           274:     struct at_ifaddr   *aa;
        !           275:     struct aarptab     *aat;
        !           276:     int                        s;
        !           277:
        !           278:     if ( at_broadcast( destsat )) {
        !           279:        if (( aa = (struct at_ifaddr *)at_ifawithnet( destsat,
        !           280:                ((struct ifnet *)ac)->if_addrlist.tqh_first )) == NULL ) {
        !           281:            m_freem( m );
        !           282:            return( 0 );
        !           283:        }
        !           284:        if ( aa->aa_flags & AFA_PHASE2 ) {
        !           285:            bcopy( (caddr_t)atmulticastaddr, (caddr_t)desten,
        !           286:                    sizeof( atmulticastaddr ));
        !           287:        } else {
        !           288:            bcopy( (caddr_t)etherbroadcastaddr, (caddr_t)desten,
        !           289:                    sizeof( etherbroadcastaddr ));
        !           290:        }
        !           291:        return( 1 );
        !           292:     }
        !           293:
        !           294:     s = splnet();
        !           295:     AARPTAB_LOOK( aat, destsat->sat_addr );
        !           296:     if ( aat == 0 ) {                  /* No entry */
        !           297:        aat = aarptnew( &destsat->sat_addr );
        !           298:        if ( aat == 0 ) { /* XXX allocate more */
        !           299:            panic( "aarpresolve: no free entry" );
        !           300:        }
        !           301:        aat->aat_hold = m;
        !           302:        aarpwhohas( ac, destsat );
        !           303:        splx( s );
        !           304:        return( 0 );
        !           305:     }
        !           306:     /* found an entry */
        !           307:     aat->aat_timer = 0;
        !           308:     if ( aat->aat_flags & ATF_COM ) {  /* entry is COMplete */
        !           309:        bcopy( (caddr_t)aat->aat_enaddr, (caddr_t)desten,
        !           310:                sizeof( aat->aat_enaddr ));
        !           311:        splx( s );
        !           312:        return( 1 );
        !           313:     }
        !           314:     /* entry has not completed */
        !           315:     if ( aat->aat_hold ) {
        !           316:        m_freem( aat->aat_hold );
        !           317:     }
        !           318:     aat->aat_hold = m;
        !           319:     aarpwhohas( ac, destsat );
        !           320:     splx( s );
        !           321:     return( 0 );
        !           322: }
        !           323:
        !           324: void
        !           325: aarpinput( ac, m )
        !           326:     struct arpcom      *ac;
        !           327:     struct mbuf                *m;
        !           328: {
        !           329:     struct arphdr      *ar;
        !           330:
        !           331:     if ( ac->ac_if.if_flags & IFF_NOARP )
        !           332:        goto out;
        !           333:
        !           334:     if ( m->m_len < sizeof( struct arphdr )) {
        !           335:        goto out;
        !           336:     }
        !           337:
        !           338:     ar = mtod( m, struct arphdr *);
        !           339:     if ( ntohs( ar->ar_hrd ) != AARPHRD_ETHER ) {
        !           340:        goto out;
        !           341:     }
        !           342:
        !           343:     if ( m->m_len < sizeof( struct arphdr ) + 2 * ar->ar_hln +
        !           344:            2 * ar->ar_pln ) {
        !           345:        goto out;
        !           346:     }
        !           347:
        !           348:     switch( ntohs( ar->ar_pro )) {
        !           349:     case ETHERTYPE_AT :
        !           350:        at_aarpinput( ac, m );
        !           351:        return;
        !           352:
        !           353:     default:
        !           354:        break;
        !           355:     }
        !           356:
        !           357: out:
        !           358:     m_freem( m );
        !           359: }
        !           360:
        !           361:
        !           362: static void
        !           363: at_aarpinput( ac, m )
        !           364:     struct arpcom      *ac;
        !           365:     struct mbuf                *m;
        !           366: {
        !           367:     struct ether_aarp  *ea;
        !           368:     struct at_ifaddr   *aa;
        !           369:     struct aarptab     *aat;
        !           370:     struct ether_header        *eh;
        !           371:     struct llc         *llc;
        !           372:     struct sockaddr_at sat;
        !           373:     struct sockaddr    sa;
        !           374:     struct at_addr     spa, tpa, ma;
        !           375:     int                        op;
        !           376:     u_int16_t          net;
        !           377:
        !           378:     ea = mtod( m, struct ether_aarp *);
        !           379:
        !           380:     /* Check to see if from my hardware address */
        !           381:     if ( !bcmp(( caddr_t )ea->aarp_sha, ( caddr_t )ac->ac_enaddr,
        !           382:            sizeof( ac->ac_enaddr ))) {
        !           383:        m_freem( m );
        !           384:        return;
        !           385:     }
        !           386:
        !           387:     /*
        !           388:      * Check if from broadcast address.  This could be a more robust
        !           389:      * check, since we could look for multicasts. XXX
        !           390:      */
        !           391:     if ( !bcmp(( caddr_t )ea->aarp_sha, ( caddr_t )etherbroadcastaddr,
        !           392:            sizeof( etherbroadcastaddr ))) {
        !           393:        log( LOG_ERR,
        !           394:                "aarp: source is broadcast!\n" );
        !           395:        m_freem( m );
        !           396:        return;
        !           397:     }
        !           398:
        !           399:     op = ntohs( ea->aarp_op );
        !           400:     bcopy( ea->aarp_tpnet, &net, sizeof( net ));
        !           401:
        !           402:     if ( net != 0 ) {
        !           403:        sat.sat_len = sizeof(struct sockaddr_at);
        !           404:        sat.sat_family = AF_APPLETALK;
        !           405:        sat.sat_addr.s_net = net;
        !           406:        if (( aa = (struct at_ifaddr *)at_ifawithnet( &sat,
        !           407:                ac->ac_if.if_addrlist.tqh_first )) == NULL ) {
        !           408:            m_freem( m );
        !           409:            return;
        !           410:        }
        !           411:        bcopy( ea->aarp_spnet, &spa.s_net, sizeof( spa.s_net ));
        !           412:        bcopy( ea->aarp_tpnet, &tpa.s_net, sizeof( tpa.s_net ));
        !           413:     } else {
        !           414:        /*
        !           415:         * Since we don't know the net, we just look for the first
        !           416:         * phase 1 address on the interface.
        !           417:         */
        !           418:        for ( aa = (struct at_ifaddr *)ac->ac_if.if_addrlist.tqh_first; aa;
        !           419:                aa = (struct at_ifaddr *)aa->aa_ifa.ifa_list.tqe_next ) {
        !           420:            if ( AA_SAT( aa )->sat_family == AF_APPLETALK &&
        !           421:                    ( aa->aa_flags & AFA_PHASE2 ) == 0 ) {
        !           422:                break;
        !           423:            }
        !           424:        }
        !           425:        if ( aa == NULL ) {
        !           426:            m_freem( m );
        !           427:            return;
        !           428:        }
        !           429:        tpa.s_net = spa.s_net = AA_SAT( aa )->sat_addr.s_net;
        !           430:     }
        !           431:
        !           432:     spa.s_node = ea->aarp_spnode;
        !           433:     tpa.s_node = ea->aarp_tpnode;
        !           434:     ma.s_net = AA_SAT( aa )->sat_addr.s_net;
        !           435:     ma.s_node = AA_SAT( aa )->sat_addr.s_node;
        !           436:
        !           437:     /*
        !           438:      * This looks like it's from us.
        !           439:      */
        !           440:     if ( spa.s_net == ma.s_net && spa.s_node == ma.s_node ) {
        !           441:        if ( aa->aa_flags & AFA_PROBING ) {
        !           442:            /*
        !           443:             * We're probing, someone either responded to our probe, or
        !           444:             * probed for the same address we'd like to use. Change the
        !           445:             * address we're probing for.
        !           446:             */
        !           447:            timeout_del(&aarpprobe_timeout);
        !           448:            wakeup( aa );
        !           449:            m_freem( m );
        !           450:            return;
        !           451:        } else if ( op != AARPOP_PROBE ) {
        !           452:            /*
        !           453:             * This is not a probe, and we're not probing. This means
        !           454:             * that someone's saying they have the same source address
        !           455:             * as the one we're using. Get upset...
        !           456:             */
        !           457:            /* XXX use ether_ntoa */
        !           458:            log( LOG_ERR,
        !           459:                    "aarp: duplicate AT address!! %x:%x:%x:%x:%x:%x\n",
        !           460:                    ea->aarp_sha[ 0 ], ea->aarp_sha[ 1 ], ea->aarp_sha[ 2 ],
        !           461:                    ea->aarp_sha[ 3 ], ea->aarp_sha[ 4 ], ea->aarp_sha[ 5 ]);
        !           462:            m_freem( m );
        !           463:            return;
        !           464:        }
        !           465:     }
        !           466:
        !           467:     AARPTAB_LOOK( aat, spa );
        !           468:     if ( aat ) {
        !           469:        if ( op == AARPOP_PROBE ) {
        !           470:            /*
        !           471:             * Someone's probing for spa, dealocate the one we've got,
        !           472:             * so that if the prober keeps the address, we'll be able
        !           473:             * to arp for him.
        !           474:             */
        !           475:            aarptfree( aat );
        !           476:            m_freem( m );
        !           477:            return;
        !           478:        }
        !           479:
        !           480:        bcopy(( caddr_t )ea->aarp_sha, ( caddr_t )aat->aat_enaddr,
        !           481:                sizeof( ea->aarp_sha ));
        !           482:        aat->aat_flags |= ATF_COM;
        !           483:        if ( aat->aat_hold ) {
        !           484:            sat.sat_len = sizeof(struct sockaddr_at);
        !           485:            sat.sat_family = AF_APPLETALK;
        !           486:            sat.sat_addr = spa;
        !           487:            /* XXX the NULL should be a struct rtentry */
        !           488:            (*ac->ac_if.if_output)( &ac->ac_if, aat->aat_hold,
        !           489:                    (struct sockaddr *)&sat, NULL );
        !           490:            aat->aat_hold = 0;
        !           491:        }
        !           492:     }
        !           493:
        !           494:     if ( aat == 0 && tpa.s_net == ma.s_net && tpa.s_node == ma.s_node
        !           495:            && op != AARPOP_PROBE ) {
        !           496:        if ( (aat = aarptnew( &spa ))) {
        !           497:            bcopy(( caddr_t )ea->aarp_sha, ( caddr_t )aat->aat_enaddr,
        !           498:                    sizeof( ea->aarp_sha ));
        !           499:            aat->aat_flags |= ATF_COM;
        !           500:        }
        !           501:     }
        !           502:
        !           503:     /*
        !           504:      * Don't respond to responses, and never respond if we're
        !           505:      * still probing.
        !           506:      */
        !           507:     if ( tpa.s_net != ma.s_net || tpa.s_node != ma.s_node ||
        !           508:            op == AARPOP_RESPONSE || ( aa->aa_flags & AFA_PROBING )) {
        !           509:        m_freem( m );
        !           510:        return;
        !           511:     }
        !           512:
        !           513:     bcopy(( caddr_t )ea->aarp_sha, ( caddr_t )ea->aarp_tha,
        !           514:            sizeof( ea->aarp_sha ));
        !           515:     bcopy(( caddr_t )ac->ac_enaddr, ( caddr_t )ea->aarp_sha,
        !           516:            sizeof( ea->aarp_sha ));
        !           517:
        !           518:     /* XXX FreeBSD has an 'XXX' here but no comment as to why. */
        !           519:     eh = (struct ether_header *)sa.sa_data;
        !           520:     bcopy(( caddr_t )ea->aarp_tha, ( caddr_t )eh->ether_dhost,
        !           521:            sizeof( eh->ether_dhost ));
        !           522:
        !           523:     if ( aa->aa_flags & AFA_PHASE2 ) {
        !           524:        eh->ether_type = htons( AT_LLC_SIZE +
        !           525:                sizeof( struct ether_aarp ));
        !           526:        M_PREPEND( m, AT_LLC_SIZE, M_DONTWAIT );
        !           527:        if ( m == NULL ) {
        !           528:            return;
        !           529:        }
        !           530:        llc = mtod( m, struct llc *);
        !           531:        llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
        !           532:        llc->llc_control = LLC_UI;
        !           533:        bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
        !           534:        llc->llc_ether_type = htons( ETHERTYPE_AARP );
        !           535:
        !           536:        bcopy( ea->aarp_spnet, ea->aarp_tpnet, sizeof( ea->aarp_tpnet ));
        !           537:        bcopy( &ma.s_net, ea->aarp_spnet, sizeof( ea->aarp_spnet ));
        !           538:     } else {
        !           539:        eh->ether_type = htons( ETHERTYPE_AARP );
        !           540:     }
        !           541:
        !           542:     ea->aarp_tpnode = ea->aarp_spnode;
        !           543:     ea->aarp_spnode = ma.s_node;
        !           544:     ea->aarp_op = htons( AARPOP_RESPONSE );
        !           545:
        !           546:     sa.sa_len = sizeof( struct sockaddr );
        !           547:     sa.sa_family = AF_UNSPEC;
        !           548:     /* XXX the NULL should be a struct rtentry */
        !           549:     (*ac->ac_if.if_output)( &ac->ac_if, m, &sa, NULL );
        !           550:     return;
        !           551: }
        !           552:
        !           553: static void
        !           554: aarptfree( aat )
        !           555:     struct aarptab     *aat;
        !           556: {
        !           557:
        !           558:     if ( aat->aat_hold )
        !           559:        m_freem( aat->aat_hold );
        !           560:     aat->aat_hold = 0;
        !           561:     aat->aat_timer = aat->aat_flags = 0;
        !           562:     aat->aat_ataddr.s_net = 0;
        !           563:     aat->aat_ataddr.s_node = 0;
        !           564: }
        !           565:
        !           566: struct aarptab *
        !           567: aarptnew( addr )
        !           568:     struct at_addr     *addr;
        !           569: {
        !           570:     int                        n;
        !           571:     int                        oldest = -1;
        !           572:     struct aarptab     *aat, *aato = NULL;
        !           573:     static int         first = 1;
        !           574:
        !           575:     if ( first ) {
        !           576:        first = 0;
        !           577:        timeout_set(&aarptimer_timeout, aarptimer, NULL);
        !           578:        timeout_add(&aarptimer_timeout, hz);
        !           579:     }
        !           580:     aat = &aarptab[ AARPTAB_HASH( *addr ) * AARPTAB_BSIZ ];
        !           581:     for ( n = 0; n < AARPTAB_BSIZ; n++, aat++ ) {
        !           582:        if ( aat->aat_flags == 0 )
        !           583:            goto out;
        !           584:        if ( aat->aat_flags & ATF_PERM )
        !           585:            continue;
        !           586:        if ((int) aat->aat_timer > oldest ) {
        !           587:            oldest = aat->aat_timer;
        !           588:            aato = aat;
        !           589:        }
        !           590:     }
        !           591:     if ( aato == NULL )
        !           592:        return( NULL );
        !           593:     aat = aato;
        !           594:     aarptfree( aat );
        !           595: out:
        !           596:     aat->aat_ataddr = *addr;
        !           597:     aat->aat_flags = ATF_INUSE;
        !           598:     return( aat );
        !           599: }
        !           600:
        !           601: void
        !           602: aarpprobe( arg )
        !           603:     void       *arg;
        !           604: {
        !           605:     struct arpcom      *ac = (struct arpcom *) arg;
        !           606:     struct mbuf                *m;
        !           607:     struct ether_header        *eh;
        !           608:     struct ether_aarp  *ea;
        !           609:     struct at_ifaddr   *aa;
        !           610:     struct llc         *llc;
        !           611:     struct sockaddr    sa;
        !           612:
        !           613:     /*
        !           614:      * We need to check whether the output ethernet type should
        !           615:      * be phase 1 or 2. We have the interface that we'll be sending
        !           616:      * the aarp out. We need to find an AppleTalk network on that
        !           617:      * interface with the same address as we're looking for. If the
        !           618:      * net is phase 2, generate an 802.2 and SNAP header.
        !           619:      */
        !           620:     for ( aa = (struct at_ifaddr *)ac->ac_if.if_addrlist.tqh_first; aa;
        !           621:            aa = (struct at_ifaddr *)aa->aa_ifa.ifa_list.tqe_next) {
        !           622:        if ( AA_SAT( aa )->sat_family == AF_APPLETALK &&
        !           623:                ( aa->aa_flags & AFA_PROBING )) {
        !           624:            break;
        !           625:        }
        !           626:     }
        !           627:     if ( aa == NULL ) {                /* serious error XXX */
        !           628:        printf( "aarpprobe why did this happen?!\n" );
        !           629:        return;
        !           630:     }
        !           631:
        !           632:     if ( aa->aa_probcnt <= 0 ) {
        !           633:        aa->aa_flags &= ~AFA_PROBING;
        !           634:        wakeup( aa );
        !           635:        return;
        !           636:     } else {
        !           637:        timeout_set(&aarpprobe_timeout, aarpprobe, ac);
        !           638:        timeout_add(&aarpprobe_timeout, hz / 5);
        !           639:     }
        !           640:
        !           641:     if (( m = m_gethdr( M_DONTWAIT, MT_DATA )) == NULL ) {
        !           642:        return;
        !           643:     }
        !           644:     m->m_len = sizeof( *ea );
        !           645:     m->m_pkthdr.len = sizeof( *ea );
        !           646:     MH_ALIGN( m, sizeof( *ea ));
        !           647:
        !           648:     ea = mtod( m, struct ether_aarp *);
        !           649:     bzero((caddr_t)ea, sizeof( *ea ));
        !           650:
        !           651:     ea->aarp_hrd = htons( AARPHRD_ETHER );
        !           652:     ea->aarp_pro = htons( ETHERTYPE_AT );
        !           653:     ea->aarp_hln = sizeof( ea->aarp_sha );
        !           654:     ea->aarp_pln = sizeof( ea->aarp_spu );
        !           655:     ea->aarp_op = htons( AARPOP_PROBE );
        !           656:     bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->aarp_sha,
        !           657:            sizeof( ea->aarp_sha ));
        !           658:
        !           659:     eh = (struct ether_header *)sa.sa_data;
        !           660:
        !           661:     if ( aa->aa_flags & AFA_PHASE2 ) {
        !           662:        bcopy((caddr_t)atmulticastaddr, (caddr_t)eh->ether_dhost,
        !           663:                sizeof( eh->ether_dhost ));
        !           664:        eh->ether_type = htons( AT_LLC_SIZE +
        !           665:                sizeof( struct ether_aarp ));
        !           666:        M_PREPEND( m, AT_LLC_SIZE, M_DONTWAIT );
        !           667:        if (!m)
        !           668:            return;
        !           669:
        !           670:        llc = mtod( m, struct llc *);
        !           671:        llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
        !           672:        llc->llc_control = LLC_UI;
        !           673:        bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
        !           674:        llc->llc_ether_type = htons( ETHERTYPE_AARP );
        !           675:
        !           676:        bcopy( &AA_SAT( aa )->sat_addr.s_net, ea->aarp_spnet,
        !           677:                sizeof( ea->aarp_spnet ));
        !           678:        bcopy( &AA_SAT( aa )->sat_addr.s_net, ea->aarp_tpnet,
        !           679:                sizeof( ea->aarp_tpnet ));
        !           680:        ea->aarp_spnode = ea->aarp_tpnode = AA_SAT( aa )->sat_addr.s_node;
        !           681:     } else {
        !           682:        bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
        !           683:                sizeof( eh->ether_dhost ));
        !           684:        eh->ether_type = htons( ETHERTYPE_AARP );
        !           685:        ea->aarp_spa = ea->aarp_tpa = AA_SAT( aa )->sat_addr.s_node;
        !           686:     }
        !           687:
        !           688:     sa.sa_len = sizeof( struct sockaddr );
        !           689:     sa.sa_family = AF_UNSPEC;
        !           690:     /* XXX the NULL should be a struct rtentry */
        !           691:     (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, NULL );
        !           692:     aa->aa_probcnt--;
        !           693: }
        !           694:
        !           695: void
        !           696: aarp_clean(void)
        !           697: {
        !           698:     struct aarptab     *aat;
        !           699:     int                        i;
        !           700:
        !           701:     timeout_del(&aarptimer_timeout);
        !           702:     for ( i = 0, aat = aarptab; i < AARPTAB_SIZE; i++, aat++ ) {
        !           703:        if ( aat->aat_hold ) {
        !           704:            m_freem( aat->aat_hold );
        !           705:        }
        !           706:     }
        !           707: }

CVSweb