root/netatalk/aarp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. aarptimer
  2. at_ifawithnet
  3. aarpwhohas
  4. aarpresolve
  5. aarpinput
  6. at_aarpinput
  7. aarptfree
  8. aarptnew
  9. aarpprobe
  10. aarp_clean

    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 }

/* [<][>][^][v][top][bottom][index][help] */