Dispatch upper-half protocol request handling.
[dragonfly.git] / sys / netproto / atalk / aarp.c
1 /*
2  * Copyright (c) 1990,1991 Regents of The University of Michigan.
3  * All Rights Reserved.
4  *
5  * $FreeBSD: src/sys/netatalk/aarp.c,v 1.12.2.2 2001/06/23 20:43:09 iedowse Exp $
6  * $DragonFly: src/sys/netproto/atalk/aarp.c,v 1.7 2004/03/06 01:58:56 hsu Exp $
7  */
8
9 #include "opt_atalk.h"
10
11 #include <sys/param.h>
12 #include <sys/systm.h>
13 #include <sys/mbuf.h>
14 #include <sys/kernel.h>
15 #include <sys/socket.h>
16 #include <sys/syslog.h>
17
18 #include <net/if.h>
19 #include <net/netisr.h>
20
21 #include <netinet/in.h>
22 #undef s_net
23 #include <netinet/if_ether.h>
24
25 #include "at.h"
26 #include "at_var.h"
27 #include "aarp.h"
28 #include "phase2.h"
29 #include "at_extern.h"
30
31 static void aarptfree( struct aarptab *aat);
32 static void at_aarpinput( struct arpcom *ac, struct mbuf *m);
33
34 #define AARPTAB_BSIZ    9
35 #define AARPTAB_NB      19
36 #define AARPTAB_SIZE    (AARPTAB_BSIZ * AARPTAB_NB)
37 static struct aarptab   aarptab[AARPTAB_SIZE];
38
39 #define AARPTAB_HASH(a) \
40     ((((a).s_net << 8 ) + (a).s_node ) % AARPTAB_NB )
41
42 #define AARPTAB_LOOK(aat,addr) { \
43     int         n; \
44     aat = &aarptab[ AARPTAB_HASH(addr) * AARPTAB_BSIZ ]; \
45     for ( n = 0; n < AARPTAB_BSIZ; n++, aat++ ) \
46         if ( aat->aat_ataddr.s_net == (addr).s_net && \
47              aat->aat_ataddr.s_node == (addr).s_node ) \
48             break; \
49         if ( n >= AARPTAB_BSIZ ) \
50             aat = 0; \
51 }
52
53 #define AARPT_AGE       (60 * 1)
54 #define AARPT_KILLC     20
55 #define AARPT_KILLI     3
56
57 # if !defined( __DragonFly__ )
58 extern u_char                   etherbroadcastaddr[6];
59 # endif __DragonFly__
60
61 static u_char atmulticastaddr[ 6 ] = {
62     0x09, 0x00, 0x07, 0xff, 0xff, 0xff,
63 };
64
65 u_char  at_org_code[ 3 ] = {
66     0x08, 0x00, 0x07,
67 };
68 u_char  aarp_org_code[ 3 ] = {
69     0x00, 0x00, 0x00,
70 };
71
72 static struct callout_handle aarptimer_ch =
73     CALLOUT_HANDLE_INITIALIZER(&aarptimer_ch);
74
75 static void
76 aarptimer(void *ignored)
77 {
78     struct aarptab      *aat;
79     int                 i, s;
80
81     aarptimer_ch = timeout( aarptimer, (caddr_t)0, AARPT_AGE * hz );
82     aat = aarptab;
83     for ( i = 0; i < AARPTAB_SIZE; i++, aat++ ) {
84         if ( aat->aat_flags == 0 || ( aat->aat_flags & ATF_PERM ))
85             continue;
86         if ( ++aat->aat_timer < (( aat->aat_flags & ATF_COM ) ?
87                 AARPT_KILLC : AARPT_KILLI ))
88             continue;
89         s = splimp();
90         aarptfree( aat );
91         splx( s );
92     }
93 }
94
95 /* 
96  * search through the network addresses to find one that includes
97  * the given network.. remember to take netranges into
98  * consideration.
99  */
100 struct at_ifaddr *
101 at_ifawithnet(struct sockaddr_at  *sat )
102 {
103     struct at_ifaddr    *aa;
104     struct sockaddr_at  *sat2;
105
106         for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
107                 sat2 = &(aa->aa_addr);
108                 if ( sat2->sat_addr.s_net == sat->sat_addr.s_net ) {
109                         break;
110                 }
111                 if( (aa->aa_flags & AFA_PHASE2 )
112                 && (ntohs(aa->aa_firstnet) <= ntohs(sat->sat_addr.s_net))
113                 && (ntohs(aa->aa_lastnet) >= ntohs(sat->sat_addr.s_net))) {
114                         break;
115                 }
116         }
117         return( aa );
118 }
119
120 static void
121 aarpwhohas( struct arpcom *ac, struct sockaddr_at *sat )
122 {
123     struct mbuf         *m;
124     struct ether_header *eh;
125     struct ether_aarp   *ea;
126     struct at_ifaddr    *aa;
127     struct llc          *llc;
128     struct sockaddr     sa;
129
130     if (( m = m_gethdr( M_DONTWAIT, MT_DATA )) == NULL ) {
131         return;
132     }
133     m->m_len = sizeof( *ea );
134     m->m_pkthdr.len = sizeof( *ea );
135     MH_ALIGN( m, sizeof( *ea ));
136
137     ea = mtod( m, struct ether_aarp *);
138     bzero((caddr_t)ea, sizeof( *ea ));
139
140     ea->aarp_hrd = htons( AARPHRD_ETHER );
141     ea->aarp_pro = htons( ETHERTYPE_AT );
142     ea->aarp_hln = sizeof( ea->aarp_sha );
143     ea->aarp_pln = sizeof( ea->aarp_spu );
144     ea->aarp_op = htons( AARPOP_REQUEST );
145     bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->aarp_sha,
146             sizeof( ea->aarp_sha ));
147
148     /*
149      * We need to check whether the output ethernet type should
150      * be phase 1 or 2. We have the interface that we'll be sending
151      * the aarp out. We need to find an AppleTalk network on that
152      * interface with the same address as we're looking for. If the
153      * net is phase 2, generate an 802.2 and SNAP header.
154      */
155     if ((aa = at_ifawithnet( sat )) == NULL) {
156         m_freem( m );
157         return;
158     }
159
160     eh = (struct ether_header *)sa.sa_data;
161
162     if ( aa->aa_flags & AFA_PHASE2 ) {
163         bcopy((caddr_t)atmulticastaddr, (caddr_t)eh->ether_dhost,
164                 sizeof( eh->ether_dhost ));
165         eh->ether_type = htons(sizeof(struct llc) + sizeof(struct ether_aarp));
166         M_PREPEND( m, sizeof( struct llc ), M_WAIT );
167         llc = mtod( m, struct llc *);
168         llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
169         llc->llc_control = LLC_UI;
170         bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
171         llc->llc_ether_type = htons( ETHERTYPE_AARP );
172
173         bcopy( &AA_SAT( aa )->sat_addr.s_net, ea->aarp_spnet,
174                sizeof( ea->aarp_spnet ));
175         bcopy( &sat->sat_addr.s_net, ea->aarp_tpnet,
176                sizeof( ea->aarp_tpnet ));
177         ea->aarp_spnode = AA_SAT( aa )->sat_addr.s_node;
178         ea->aarp_tpnode = sat->sat_addr.s_node;
179     } else {
180         bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
181                 sizeof( eh->ether_dhost ));
182         eh->ether_type = htons( ETHERTYPE_AARP );
183
184         ea->aarp_spa = AA_SAT( aa )->sat_addr.s_node;
185         ea->aarp_tpa = sat->sat_addr.s_node;
186     }
187
188 #ifdef NETATALKDEBUG
189     printf("aarp: sending request for %u.%u\n",
190            ntohs(AA_SAT( aa )->sat_addr.s_net),
191            AA_SAT( aa )->sat_addr.s_node);
192 #endif /* NETATALKDEBUG */
193
194     sa.sa_len = sizeof( struct sockaddr );
195     sa.sa_family = AF_UNSPEC;
196     (*ac->ac_if.if_output)(&ac->ac_if,
197         m, &sa, NULL);  /* XXX NULL should be routing information */
198 }
199
200 int
201 aarpresolve( ac, m, destsat, desten )
202     struct arpcom       *ac;
203     struct mbuf         *m;
204     struct sockaddr_at  *destsat;
205     u_char              *desten;
206 {
207     struct at_ifaddr    *aa;
208     struct aarptab      *aat;
209     int                 s;
210
211     if ( at_broadcast( destsat )) {
212         m->m_flags |= M_BCAST;
213         if ((aa = at_ifawithnet( destsat )) == NULL)  {
214             m_freem( m );
215             return( 0 );
216         }
217         if ( aa->aa_flags & AFA_PHASE2 ) {
218             bcopy( (caddr_t)atmulticastaddr, (caddr_t)desten,
219                     sizeof( atmulticastaddr ));
220         } else {
221             bcopy( (caddr_t)etherbroadcastaddr, (caddr_t)desten,
222                     sizeof( etherbroadcastaddr ));
223         }
224         return( 1 );
225     }
226
227     s = splimp();
228     AARPTAB_LOOK( aat, destsat->sat_addr );
229     if ( aat == 0 ) {                   /* No entry */
230         aat = aarptnew( &destsat->sat_addr );
231         if ( aat == 0 ) {
232             panic( "aarpresolve: no free entry" );
233         }
234         aat->aat_hold = m;
235         aarpwhohas( ac, destsat );
236         splx( s );
237         return( 0 );
238     }
239     /* found an entry */
240     aat->aat_timer = 0;
241     if ( aat->aat_flags & ATF_COM ) {   /* entry is COMplete */
242         bcopy( (caddr_t)aat->aat_enaddr, (caddr_t)desten,
243                 sizeof( aat->aat_enaddr ));
244         splx( s );
245         return( 1 );
246     }
247     /* entry has not completed */
248     if ( aat->aat_hold ) {
249         m_freem( aat->aat_hold );
250     }
251     aat->aat_hold = m;
252     aarpwhohas( ac, destsat );
253     splx( s );
254     return( 0 );
255 }
256
257 void
258 aarpintr(struct netmsg *msg)
259 {
260     struct mbuf *m = ((struct netmsg_packet *)msg)->nm_packet;   
261     struct arphdr       *ar;
262     struct arpcom       *ac;
263
264     ac = (struct arpcom *)m->m_pkthdr.rcvif;
265     if ( ac->ac_if.if_flags & IFF_NOARP )
266         goto out;
267
268     if ( m->m_len < sizeof( struct arphdr )) {
269         goto out;
270     }
271
272     ar = mtod( m, struct arphdr *);
273     if ( ntohs( ar->ar_hrd ) != AARPHRD_ETHER ) {
274         goto out;
275     }
276     
277     if ( m->m_len < sizeof( struct arphdr ) + 2 * ar->ar_hln +
278             2 * ar->ar_pln ) {
279         goto out;
280     }
281     
282     switch( ntohs( ar->ar_pro )) {
283     case ETHERTYPE_AT :
284         at_aarpinput( ac, m );
285         return;
286
287     default:
288         break;
289     }
290
291 out:
292     m_freem( m );
293 }
294
295 static void
296 at_aarpinput( struct arpcom *ac, struct mbuf *m)
297 {
298     struct ether_aarp   *ea;
299     struct at_ifaddr    *aa;
300     struct aarptab      *aat;
301     struct ether_header *eh;
302     struct llc          *llc;
303     struct sockaddr_at  sat;
304     struct sockaddr     sa;
305     struct at_addr      spa, tpa, ma;
306     int                 op;
307     u_short             net;
308
309     ea = mtod( m, struct ether_aarp *);
310
311     /* Check to see if from my hardware address */
312     if ( !bcmp(( caddr_t )ea->aarp_sha, ( caddr_t )ac->ac_enaddr,
313             sizeof( ac->ac_enaddr ))) {
314         m_freem( m );
315         return;
316     }
317
318     op = ntohs( ea->aarp_op );
319     bcopy( ea->aarp_tpnet, &net, sizeof( net ));
320
321     if ( net != 0 ) { /* should be ATADDR_ANYNET? */
322         sat.sat_len = sizeof(struct sockaddr_at);
323         sat.sat_family = AF_APPLETALK;
324         sat.sat_addr.s_net = net;
325         if ((aa = at_ifawithnet( &sat )) == NULL) {
326             m_freem( m );
327             return;
328         }
329         bcopy( ea->aarp_spnet, &spa.s_net, sizeof( spa.s_net ));
330         bcopy( ea->aarp_tpnet, &tpa.s_net, sizeof( tpa.s_net ));
331     } else {
332         /*
333          * Since we don't know the net, we just look for the first
334          * phase 1 address on the interface.
335          */
336         for (aa = (struct at_ifaddr *)ac->ac_if.if_addrhead.tqh_first; aa;
337                 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) {
338             if ( AA_SAT( aa )->sat_family == AF_APPLETALK &&
339                     ( aa->aa_flags & AFA_PHASE2 ) == 0 ) {
340                 break;
341             }
342         }
343         if ( aa == NULL ) {
344             m_freem( m );
345             return;
346         }
347         tpa.s_net = spa.s_net = AA_SAT( aa )->sat_addr.s_net;
348     }
349
350     spa.s_node = ea->aarp_spnode;
351     tpa.s_node = ea->aarp_tpnode;
352     ma.s_net = AA_SAT( aa )->sat_addr.s_net;
353     ma.s_node = AA_SAT( aa )->sat_addr.s_node;
354
355     /*
356      * This looks like it's from us.
357      */
358     if ( spa.s_net == ma.s_net && spa.s_node == ma.s_node ) {
359         if ( aa->aa_flags & AFA_PROBING ) {
360             /*
361              * We're probing, someone either responded to our probe, or
362              * probed for the same address we'd like to use. Change the
363              * address we're probing for.
364              */
365             untimeout( aarpprobe, ac, aa->aa_ch );
366             wakeup( aa );
367             m_freem( m );
368             return;
369         } else if ( op != AARPOP_PROBE ) {
370             /*
371              * This is not a probe, and we're not probing. This means
372              * that someone's saying they have the same source address
373              * as the one we're using. Get upset...
374              */
375             log( LOG_ERR,
376                     "aarp: duplicate AT address!! %x:%x:%x:%x:%x:%x\n",
377                     ea->aarp_sha[ 0 ], ea->aarp_sha[ 1 ], ea->aarp_sha[ 2 ],
378                     ea->aarp_sha[ 3 ], ea->aarp_sha[ 4 ], ea->aarp_sha[ 5 ]);
379             m_freem( m );
380             return;
381         }
382     }
383
384     AARPTAB_LOOK( aat, spa );
385     if ( aat ) {
386         if ( op == AARPOP_PROBE ) {
387             /*
388              * Someone's probing for spa, dealocate the one we've got,
389              * so that if the prober keeps the address, we'll be able
390              * to arp for him.
391              */
392             aarptfree( aat );
393             m_freem( m );
394             return;
395         }
396
397         bcopy(( caddr_t )ea->aarp_sha, ( caddr_t )aat->aat_enaddr,
398                 sizeof( ea->aarp_sha ));
399         aat->aat_flags |= ATF_COM;
400         if ( aat->aat_hold ) {
401             struct mbuf *mhold = aat->aat_hold;
402             aat->aat_hold = NULL;
403             sat.sat_len = sizeof(struct sockaddr_at);
404             sat.sat_family = AF_APPLETALK;
405             sat.sat_addr = spa;
406             (*ac->ac_if.if_output)( &ac->ac_if, mhold,
407                     (struct sockaddr *)&sat, NULL); /* XXX */
408         }
409     } else if ((tpa.s_net == ma.s_net)
410            && (tpa.s_node == ma.s_node)
411            && (op != AARPOP_PROBE)
412            && ((aat = aarptnew( &spa )) != NULL)) {
413                 bcopy(( caddr_t )ea->aarp_sha, ( caddr_t )aat->aat_enaddr,
414                     sizeof( ea->aarp_sha ));
415                 aat->aat_flags |= ATF_COM;
416     }
417
418     /*
419      * Don't respond to responses, and never respond if we're
420      * still probing.
421      */
422     if ( tpa.s_net != ma.s_net || tpa.s_node != ma.s_node ||
423             op == AARPOP_RESPONSE || ( aa->aa_flags & AFA_PROBING )) {
424         m_freem( m );
425         return;
426     }
427
428     bcopy(( caddr_t )ea->aarp_sha, ( caddr_t )ea->aarp_tha,
429             sizeof( ea->aarp_sha ));
430     bcopy(( caddr_t )ac->ac_enaddr, ( caddr_t )ea->aarp_sha,
431             sizeof( ea->aarp_sha ));
432
433     /* XXX */
434     eh = (struct ether_header *)sa.sa_data;
435     bcopy(( caddr_t )ea->aarp_tha, ( caddr_t )eh->ether_dhost,
436             sizeof( eh->ether_dhost ));
437
438     if ( aa->aa_flags & AFA_PHASE2 ) {
439         eh->ether_type = htons( sizeof( struct llc ) +
440                 sizeof( struct ether_aarp ));
441         M_PREPEND( m, sizeof( struct llc ), M_DONTWAIT );
442         if ( m == NULL ) {
443             return;
444         }
445         llc = mtod( m, struct llc *);
446         llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
447         llc->llc_control = LLC_UI;
448         bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
449         llc->llc_ether_type = htons( ETHERTYPE_AARP );
450
451         bcopy( ea->aarp_spnet, ea->aarp_tpnet, sizeof( ea->aarp_tpnet ));
452         bcopy( &ma.s_net, ea->aarp_spnet, sizeof( ea->aarp_spnet ));
453     } else {
454         eh->ether_type = htons( ETHERTYPE_AARP );
455     }
456
457     ea->aarp_tpnode = ea->aarp_spnode;
458     ea->aarp_spnode = ma.s_node;
459     ea->aarp_op = htons( AARPOP_RESPONSE );
460
461     sa.sa_len = sizeof( struct sockaddr );
462     sa.sa_family = AF_UNSPEC;
463     (*ac->ac_if.if_output)( &ac->ac_if, m, &sa, NULL); /* XXX */
464     return;
465 }
466
467 static void
468 aarptfree( struct aarptab *aat)
469 {
470
471     if ( aat->aat_hold )
472         m_freem( aat->aat_hold );
473     aat->aat_hold = NULL;
474     aat->aat_timer = aat->aat_flags = 0;
475     aat->aat_ataddr.s_net = 0;
476     aat->aat_ataddr.s_node = 0;
477 }
478
479     struct aarptab *
480 aarptnew( addr )
481     struct at_addr      *addr;
482 {
483     int                 n;
484     int                 oldest = -1;
485     struct aarptab      *aat, *aato = NULL;
486     static int          first = 1;
487
488     if ( first ) {
489         first = 0;
490         aarptimer_ch = timeout( aarptimer, (caddr_t)0, hz );
491     }
492     aat = &aarptab[ AARPTAB_HASH( *addr ) * AARPTAB_BSIZ ];
493     for ( n = 0; n < AARPTAB_BSIZ; n++, aat++ ) {
494         if ( aat->aat_flags == 0 )
495             goto out;
496         if ( aat->aat_flags & ATF_PERM )
497             continue;
498         if ((int) aat->aat_timer > oldest ) {
499             oldest = aat->aat_timer;
500             aato = aat;
501         }
502     }
503     if ( aato == NULL )
504         return( NULL );
505     aat = aato;
506     aarptfree( aat );
507 out:
508     aat->aat_ataddr = *addr;
509     aat->aat_flags = ATF_INUSE;
510     return( aat );
511 }
512
513
514 void
515 aarpprobe( void *arg )
516 {
517     struct arpcom       *ac = arg;
518     struct mbuf         *m;
519     struct ether_header *eh;
520     struct ether_aarp   *ea;
521     struct at_ifaddr    *aa;
522     struct llc          *llc;
523     struct sockaddr     sa;
524
525     /*
526      * We need to check whether the output ethernet type should
527      * be phase 1 or 2. We have the interface that we'll be sending
528      * the aarp out. We need to find an AppleTalk network on that
529      * interface with the same address as we're looking for. If the
530      * net is phase 2, generate an 802.2 and SNAP header.
531      */
532     for (aa = (struct at_ifaddr *)ac->ac_if.if_addrhead.tqh_first; aa;
533             aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) {
534         if ( AA_SAT( aa )->sat_family == AF_APPLETALK &&
535                 ( aa->aa_flags & AFA_PROBING )) {
536             break;
537         }
538     }
539     if ( aa == NULL ) {         /* serious error XXX */
540         printf( "aarpprobe why did this happen?!\n" );
541         return;
542     }
543
544     if ( aa->aa_probcnt <= 0 ) {
545         aa->aa_flags &= ~AFA_PROBING;
546         wakeup( aa );
547         return;
548     } else {
549         aa->aa_ch = timeout( aarpprobe, (caddr_t)ac, hz / 5 );
550     }
551
552     if (( m = m_gethdr( M_DONTWAIT, MT_DATA )) == NULL ) {
553         return;
554     }
555     m->m_len = sizeof( *ea );
556     m->m_pkthdr.len = sizeof( *ea );
557     MH_ALIGN( m, sizeof( *ea ));
558
559     ea = mtod( m, struct ether_aarp *);
560     bzero((caddr_t)ea, sizeof( *ea ));
561
562     ea->aarp_hrd = htons( AARPHRD_ETHER );
563     ea->aarp_pro = htons( ETHERTYPE_AT );
564     ea->aarp_hln = sizeof( ea->aarp_sha );
565     ea->aarp_pln = sizeof( ea->aarp_spu );
566     ea->aarp_op = htons( AARPOP_PROBE );
567     bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->aarp_sha,
568             sizeof( ea->aarp_sha ));
569
570     eh = (struct ether_header *)sa.sa_data;
571
572     if ( aa->aa_flags & AFA_PHASE2 ) {
573         bcopy((caddr_t)atmulticastaddr, (caddr_t)eh->ether_dhost,
574                 sizeof( eh->ether_dhost ));
575         eh->ether_type = htons( sizeof( struct llc ) +
576                 sizeof( struct ether_aarp ));
577         M_PREPEND( m, sizeof( struct llc ), M_WAIT );
578         /* XXX-MBUF */
579         llc = mtod( m, struct llc *);
580         llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
581         llc->llc_control = LLC_UI;
582         bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
583         llc->llc_ether_type = htons( ETHERTYPE_AARP );
584
585         bcopy( &AA_SAT( aa )->sat_addr.s_net, ea->aarp_spnet,
586                 sizeof( ea->aarp_spnet ));
587         bcopy( &AA_SAT( aa )->sat_addr.s_net, ea->aarp_tpnet,
588                 sizeof( ea->aarp_tpnet ));
589         ea->aarp_spnode = ea->aarp_tpnode = AA_SAT( aa )->sat_addr.s_node;
590     } else {
591         bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
592                 sizeof( eh->ether_dhost ));
593         eh->ether_type = htons( ETHERTYPE_AARP );
594         ea->aarp_spa = ea->aarp_tpa = AA_SAT( aa )->sat_addr.s_node;
595     }
596
597 #ifdef NETATALKDEBUG
598     printf("aarp: sending probe for %u.%u\n",
599            ntohs(AA_SAT( aa )->sat_addr.s_net),
600            AA_SAT( aa )->sat_addr.s_node);
601 #endif /* NETATALKDEBUG */
602
603     sa.sa_len = sizeof( struct sockaddr );
604     sa.sa_family = AF_UNSPEC;
605     (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, NULL); /* XXX */
606     aa->aa_probcnt--;
607 }
608
609 void
610 aarp_clean(void)
611 {
612     struct aarptab      *aat;
613     int                 i;
614
615     untimeout( aarptimer, 0, aarptimer_ch );
616     for ( i = 0, aat = aarptab; i < AARPTAB_SIZE; i++, aat++ ) {
617         if ( aat->aat_hold ) {
618             m_freem( aat->aat_hold );
619             aat->aat_hold = NULL;
620         }
621     }
622 }