[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

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