~ubuntu-branches/ubuntu/precise/netatalk/precise

« back to all changes in this revision

Viewing changes to sys/netatalk/aarp.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Rittau
  • Date: 2004-01-19 12:43:49 UTC
  • Revision ID: james.westby@ubuntu.com-20040119124349-es563jbp0hk0ae51
Tags: upstream-1.6.4
ImportĀ upstreamĀ versionĀ 1.6.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: aarp.c,v 1.3 2002/01/03 17:49:39 sibaz Exp $
 
3
 *
 
4
 * Copyright (c) 1990,1991 Regents of The University of Michigan.
 
5
 * All Rights Reserved.
 
6
 */
 
7
 
 
8
#ifdef HAVE_CONFIG_H
 
9
#include "config.h"
 
10
#endif /* HAVE_CONFIG_H */
 
11
 
 
12
#include <sys/types.h>
 
13
#include <sys/socket.h>
 
14
#include <syslog.h>
 
15
#include <sys/param.h>
 
16
#include <sys/mbuf.h>
 
17
#include <sys/time.h>
 
18
#ifndef _IBMR2
 
19
#include <sys/kernel.h>
 
20
#endif /* _IBMR2 */
 
21
#include <net/if.h>
 
22
#include <net/route.h>
 
23
#include <net/af.h>
 
24
#include <netinet/in.h>
 
25
#undef s_net
 
26
#include <netinet/if_ether.h>
 
27
#ifdef _IBMR2
 
28
#include <netinet/in_netarp.h>
 
29
#include <net/spl.h>
 
30
#include <sys/errno.h>
 
31
#include <sys/err_rec.h>
 
32
#endif /* _IBMR2 */
 
33
 
 
34
#include "at.h"
 
35
#include "at_var.h"
 
36
#include "aarp.h"
 
37
#include "ddp_var.h"
 
38
#include "endian.h"
 
39
#include "phase2.h"
 
40
 
 
41
#ifdef GATEWAY
 
42
#define AARPTAB_BSIZ    16
 
43
#define AARPTAB_NB      37
 
44
#else /* GATEWAY */
 
45
#define AARPTAB_BSIZ    9
 
46
#define AARPTAB_NB      19
 
47
#endif /* GATEWAY */
 
48
#define AARPTAB_SIZE    (AARPTAB_BSIZ * AARPTAB_NB)
 
49
struct aarptab          aarptab[AARPTAB_SIZE];
 
50
int                     aarptab_size = AARPTAB_SIZE;
 
51
 
 
52
#define AARPTAB_HASH(a) \
 
53
    ((((a).s_net << 8 ) + (a).s_node ) % AARPTAB_NB )
 
54
 
 
55
#define AARPTAB_LOOK(aat,addr) { \
 
56
    int         n; \
 
57
    aat = &aarptab[ AARPTAB_HASH(addr) * AARPTAB_BSIZ ]; \
 
58
    for ( n = 0; n < AARPTAB_BSIZ; n++, aat++ ) \
 
59
        if ( aat->aat_ataddr.s_net == (addr).s_net && \
 
60
             aat->aat_ataddr.s_node == (addr).s_node ) \
 
61
            break; \
 
62
        if ( n >= AARPTAB_BSIZ ) \
 
63
            aat = 0; \
 
64
}
 
65
 
 
66
#define AARPT_AGE       (60 * 1)
 
67
#define AARPT_KILLC     20
 
68
#define AARPT_KILLI     3
 
69
 
 
70
#ifdef sun
 
71
extern struct ether_addr        etherbroadcastaddr;
 
72
#else /* sun */
 
73
extern u_char                   etherbroadcastaddr[6];
 
74
#endif /* sun */
 
75
 
 
76
u_char  atmulticastaddr[ 6 ] = {
 
77
    0x09, 0x00, 0x07, 0xff, 0xff, 0xff,
 
78
};
 
79
 
 
80
u_char  at_org_code[ 3 ] = {
 
81
    0x08, 0x00, 0x07,
 
82
};
 
83
u_char  aarp_org_code[ 3 ] = {
 
84
    0x00, 0x00, 0x00,
 
85
};
 
86
 
 
87
aarptimer()
 
88
{
 
89
    struct aarptab      *aat;
 
90
    int                 i, s;
 
91
 
 
92
    timeout( aarptimer, (caddr_t)0, AARPT_AGE * hz );
 
93
    aat = aarptab;
 
94
    for ( i = 0; i < AARPTAB_SIZE; i++, aat++ ) {
 
95
        if ( aat->aat_flags == 0 || ( aat->aat_flags & ATF_PERM ))
 
96
            continue;
 
97
        if ( ++aat->aat_timer < (( aat->aat_flags & ATF_COM ) ?
 
98
                AARPT_KILLC : AARPT_KILLI ))
 
99
            continue;
 
100
        s = splimp();
 
101
        aarptfree( aat );
 
102
        splx( s );
 
103
    }
 
104
}
 
105
 
 
106
struct ifaddr *
 
107
at_ifawithnet( sat, ifa )
 
108
    struct sockaddr_at  *sat;
 
109
    struct ifaddr       *ifa;
 
110
{
 
111
    struct at_ifaddr    *aa;
 
112
 
 
113
    for (; ifa; ifa = ifa->ifa_next ) {
 
114
#ifdef BSD4_4
 
115
        if ( ifa->ifa_addr->sa_family != AF_APPLETALK ) {
 
116
            continue;
 
117
        }
 
118
        if ( satosat( ifa->ifa_addr )->sat_addr.s_net ==
 
119
                sat->sat_addr.s_net ) {
 
120
            break;
 
121
        }
 
122
#else /* BSD4_4 */
 
123
        if ( ifa->ifa_addr.sa_family != AF_APPLETALK ) {
 
124
            continue;
 
125
        }
 
126
        aa = (struct at_ifaddr *)ifa;
 
127
        if ( ntohs( sat->sat_addr.s_net ) >= ntohs( aa->aa_firstnet ) &&
 
128
                ntohs( sat->sat_addr.s_net ) <= ntohs( aa->aa_lastnet )) {
 
129
            break;
 
130
        }
 
131
#endif /* BSD4_4 */
 
132
    }
 
133
    return( ifa );
 
134
}
 
135
 
 
136
aarpwhohas( ac, sat )
 
137
    struct arpcom       *ac;
 
138
    struct sockaddr_at  *sat;
 
139
{
 
140
    struct mbuf         *m;
 
141
    struct ether_header *eh;
 
142
    struct ether_aarp   *ea;
 
143
    struct at_ifaddr    *aa;
 
144
    struct llc          *llc;
 
145
    struct sockaddr     sa;
 
146
 
 
147
#ifdef BSD4_4
 
148
    if (( m = m_gethdr( M_DONTWAIT, MT_DATA )) == NULL ) {
 
149
        return;
 
150
    }
 
151
    m->m_len = sizeof( *ea );
 
152
    m->m_pkthdr.len = sizeof( *ea );
 
153
    MH_ALIGN( m, sizeof( *ea ));
 
154
#else /* BSD4_4 */
 
155
    if (( m = m_get( M_DONTWAIT, MT_DATA )) == NULL ) {
 
156
        return;
 
157
    }
 
158
    m->m_len = sizeof( *ea );
 
159
    m->m_off = MMAXOFF - sizeof( *ea );
 
160
#endif /* BSD4_4 */
 
161
 
 
162
    ea = mtod( m, struct ether_aarp *);
 
163
    bzero((caddr_t)ea, sizeof( *ea ));
 
164
 
 
165
    ea->aarp_hrd = htons( AARPHRD_ETHER );
 
166
    ea->aarp_pro = htons( ETHERTYPE_AT );
 
167
    ea->aarp_hln = sizeof( ea->aarp_sha );
 
168
    ea->aarp_pln = sizeof( ea->aarp_spu );
 
169
    ea->aarp_op = htons( AARPOP_REQUEST );
 
170
#ifdef sun
 
171
    bcopy((caddr_t)&ac->ac_enaddr, (caddr_t)ea->aarp_sha,
 
172
            sizeof( ea->aarp_sha ));
 
173
#else /* sun */
 
174
    bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->aarp_sha,
 
175
            sizeof( ea->aarp_sha ));
 
176
#endif /* sun */
 
177
 
 
178
    /*
 
179
     * We need to check whether the output ethernet type should
 
180
     * be phase 1 or 2. We have the interface that we'll be sending
 
181
     * the aarp out. We need to find an AppleTalk network on that
 
182
     * interface with the same address as we're looking for. If the
 
183
     * net is phase 2, generate an 802.2 and SNAP header.
 
184
     */
 
185
    if (( aa = (struct at_ifaddr *)at_ifawithnet( sat, ac->ac_if.if_addrlist ))
 
186
            == NULL ) {
 
187
        m_freem( m );
 
188
        return;
 
189
    }
 
190
 
 
191
    eh = (struct ether_header *)sa.sa_data;
 
192
 
 
193
    if ( aa->aa_flags & AFA_PHASE2 ) {
 
194
#ifdef sun
 
195
        bcopy((caddr_t)atmulticastaddr, (caddr_t)&eh->ether_dhost,
 
196
                sizeof( eh->ether_dhost ));
 
197
#else /* sun */
 
198
        bcopy((caddr_t)atmulticastaddr, (caddr_t)eh->ether_dhost,
 
199
                sizeof( eh->ether_dhost ));
 
200
#endif /* sun */
 
201
#if defined( sun ) && defined( i386 )
 
202
        eh->ether_type = htons( sizeof( struct llc ) +
 
203
                sizeof( struct ether_aarp ));
 
204
#else /* sun && i386 */
 
205
        eh->ether_type = sizeof( struct llc ) + sizeof( struct ether_aarp );
 
206
#endif /* sun && i386 */
 
207
#ifdef BSD4_4
 
208
        M_PREPEND( m, sizeof( struct llc ), M_WAIT );
 
209
#else /* BSD4_4 */
 
210
        m->m_len += sizeof( struct llc );
 
211
        m->m_off -= sizeof( struct llc );
 
212
#endif /* BSD4_4 */
 
213
        llc = mtod( m, struct llc *);
 
214
        llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
 
215
        llc->llc_control = LLC_UI;
 
216
        bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
 
217
        llc->llc_ether_type = htons( ETHERTYPE_AARP );
 
218
 
 
219
        
 
220
        bcopy( &AA_SAT( aa )->sat_addr.s_net, ea->aarp_spnet,
 
221
                sizeof( ea->aarp_spnet ));
 
222
        ea->aarp_spnode = AA_SAT( aa )->sat_addr.s_node;
 
223
        bcopy( &sat->sat_addr.s_net, ea->aarp_tpnet,
 
224
                sizeof( ea->aarp_tpnet ));
 
225
        ea->aarp_tpnode = sat->sat_addr.s_node;
 
226
    } else {
 
227
#ifdef sun
 
228
        bcopy((caddr_t)&etherbroadcastaddr, (caddr_t)&eh->ether_dhost,
 
229
                sizeof( eh->ether_dhost ));
 
230
#else /* sun */
 
231
        bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
 
232
                sizeof( eh->ether_dhost ));
 
233
#endif /* sun */
 
234
#if defined( sun ) && defined( i386 )
 
235
        eh->ether_type = htons( ETHERTYPE_AARP );
 
236
#else /* sun && i386 */
 
237
        eh->ether_type = ETHERTYPE_AARP;
 
238
#endif /* sun && i386 */
 
239
 
 
240
        ea->aarp_spa = AA_SAT( aa )->sat_addr.s_node;
 
241
        ea->aarp_tpa = sat->sat_addr.s_node;
 
242
    }
 
243
 
 
244
#ifdef BSD4_4
 
245
    sa.sa_len = sizeof( struct sockaddr );
 
246
#endif /* BSD4_4 */
 
247
    sa.sa_family = AF_UNSPEC;
 
248
    (*ac->ac_if.if_output)(&ac->ac_if, m, &sa );
 
249
}
 
250
 
 
251
aarpresolve( ac, m, destsat, desten )
 
252
    struct arpcom       *ac;
 
253
    struct mbuf         *m;
 
254
    struct sockaddr_at  *destsat;
 
255
#ifdef sun
 
256
    struct ether_addr   *desten;
 
257
#else /* sun */
 
258
    u_char              *desten;
 
259
#endif /* sun */
 
260
{
 
261
    struct at_ifaddr    *aa;
 
262
    struct ifaddr       ifa;
 
263
    struct aarptab      *aat;
 
264
    int                 s;
 
265
 
 
266
    if ( at_broadcast( destsat )) {
 
267
        if (( aa = (struct at_ifaddr *)at_ifawithnet( destsat,
 
268
                ((struct ifnet *)ac)->if_addrlist )) == NULL ) {
 
269
            m_freem( m );
 
270
            return( 0 );
 
271
        }
 
272
        if ( aa->aa_flags & AFA_PHASE2 ) {
 
273
            bcopy( (caddr_t)atmulticastaddr, (caddr_t)desten,
 
274
                    sizeof( atmulticastaddr ));
 
275
        } else {
 
276
#ifdef sun
 
277
            bcopy( (caddr_t)&etherbroadcastaddr, (caddr_t)desten,
 
278
                    sizeof( etherbroadcastaddr ));
 
279
#else /* sun */
 
280
            bcopy( (caddr_t)etherbroadcastaddr, (caddr_t)desten,
 
281
                    sizeof( etherbroadcastaddr ));
 
282
#endif /* sun */
 
283
        }
 
284
        return( 1 );
 
285
    }
 
286
 
 
287
    s = splimp();
 
288
    AARPTAB_LOOK( aat, destsat->sat_addr );
 
289
    if ( aat == 0 ) {                   /* No entry */
 
290
        aat = aarptnew( &destsat->sat_addr );
 
291
        if ( aat == 0 ) {
 
292
            panic( "aarpresolve: no free entry" );
 
293
        }
 
294
        aat->aat_hold = m;
 
295
        aarpwhohas( ac, destsat );
 
296
        splx( s );
 
297
        return( 0 );
 
298
    }
 
299
    /* found an entry */
 
300
    aat->aat_timer = 0;
 
301
    if ( aat->aat_flags & ATF_COM ) {   /* entry is COMplete */
 
302
        bcopy( (caddr_t)aat->aat_enaddr, (caddr_t)desten,
 
303
                sizeof( aat->aat_enaddr ));
 
304
        splx( s );
 
305
        return( 1 );
 
306
    }
 
307
    /* entry has not completed */
 
308
    if ( aat->aat_hold ) {
 
309
        m_freem( aat->aat_hold );
 
310
    }
 
311
    aat->aat_hold = m;
 
312
    aarpwhohas( ac, destsat );
 
313
    splx( s );
 
314
    return( 0 );
 
315
}
 
316
 
 
317
aarpinput( ac, m )
 
318
    struct arpcom       *ac;
 
319
    struct mbuf         *m;
 
320
{
 
321
    struct arphdr       *ar;
 
322
 
 
323
    if ( ac->ac_if.if_flags & IFF_NOARP )
 
324
        goto out;
 
325
 
 
326
#ifndef BSD4_4
 
327
    IF_ADJ( m );
 
328
#endif /* BSD4_4 */
 
329
 
 
330
    if ( m->m_len < sizeof( struct arphdr )) {
 
331
        goto out;
 
332
    }
 
333
 
 
334
    ar = mtod( m, struct arphdr *);
 
335
    if ( ntohs( ar->ar_hrd ) != AARPHRD_ETHER ) {
 
336
        goto out;
 
337
    }
 
338
    
 
339
    if ( m->m_len < sizeof( struct arphdr ) + 2 * ar->ar_hln +
 
340
            2 * ar->ar_pln ) {
 
341
        goto out;
 
342
    }
 
343
    
 
344
    switch( ntohs( ar->ar_pro )) {
 
345
    case ETHERTYPE_AT :
 
346
        at_aarpinput( ac, m );
 
347
        return;
 
348
 
 
349
    default:
 
350
        break;
 
351
    }
 
352
 
 
353
out:
 
354
    m_freem( m );
 
355
}
 
356
 
 
357
 
 
358
at_aarpinput( ac, m )
 
359
    struct arpcom       *ac;
 
360
    struct mbuf         *m;
 
361
{
 
362
    struct mbuf         *m0;
 
363
    struct ether_aarp   *ea;
 
364
    struct at_ifaddr    *aa;
 
365
    struct aarptab      *aat;
 
366
    struct ether_header *eh;
 
367
    struct llc          *llc;
 
368
    struct sockaddr_at  sat;
 
369
    struct sockaddr     sa;
 
370
    struct at_addr      spa, tpa, ma;
 
371
    int                 op, s;
 
372
    u_short             net;
 
373
 
 
374
    ea = mtod( m, struct ether_aarp *);
 
375
 
 
376
    /* Check to see if from my hardware address */
 
377
#ifdef sun
 
378
    if ( !bcmp(( caddr_t )ea->aarp_sha, ( caddr_t )&ac->ac_enaddr,
 
379
            sizeof( ac->ac_enaddr ))) {
 
380
        m_freem( m );
 
381
        return;
 
382
    }
 
383
#else /* sun */
 
384
    if ( !bcmp(( caddr_t )ea->aarp_sha, ( caddr_t )ac->ac_enaddr,
 
385
            sizeof( ac->ac_enaddr ))) {
 
386
        m_freem( m );
 
387
        return;
 
388
    }
 
389
#endif /* sun */
 
390
 
 
391
    /*
 
392
     * Check if from broadcast address.  This could be a more robust
 
393
     * check, since we could look for multicasts.
 
394
     */
 
395
#ifdef sun
 
396
    if ( !bcmp(( caddr_t )ea->aarp_sha, ( caddr_t )&etherbroadcastaddr,
 
397
            sizeof( etherbroadcastaddr ))) {
 
398
        log( LOG_ERR, "aarp: source is broadcast!\n" );
 
399
        m_freem( m );
 
400
        return;
 
401
    }
 
402
#else /* sun */
 
403
    if ( !bcmp(( caddr_t )ea->aarp_sha, ( caddr_t )etherbroadcastaddr,
 
404
            sizeof( etherbroadcastaddr ))) {
 
405
#ifndef _IBMR2
 
406
#ifdef ultrix
 
407
        mprintf( LOG_ERR,
 
408
#else /* ultrix */
 
409
        log( LOG_ERR,
 
410
#endif /* ultrix */
 
411
                "aarp: source is broadcast!\n" );
 
412
#endif /* ! _IBMR2 */
 
413
        m_freem( m );
 
414
        return;
 
415
    }
 
416
#endif /* sun */
 
417
 
 
418
    op = ntohs( ea->aarp_op );
 
419
    bcopy( ea->aarp_tpnet, &net, sizeof( net ));
 
420
 
 
421
    if ( net != 0 ) {
 
422
        sat.sat_family = AF_APPLETALK;
 
423
        sat.sat_addr.s_net = net;
 
424
        if (( aa = (struct at_ifaddr *)at_ifawithnet( &sat,
 
425
                ac->ac_if.if_addrlist )) == NULL ) {
 
426
            m_freem( m );
 
427
            return;
 
428
        }
 
429
        bcopy( ea->aarp_spnet, &spa.s_net, sizeof( spa.s_net ));
 
430
        bcopy( ea->aarp_tpnet, &tpa.s_net, sizeof( tpa.s_net ));
 
431
    } else {
 
432
        /*
 
433
         * Since we don't know the net, we just look for the first
 
434
         * phase 1 address on the interface.
 
435
         */
 
436
        for ( aa = (struct at_ifaddr *)ac->ac_if.if_addrlist; aa;
 
437
                aa = (struct at_ifaddr *)aa->aa_ifa.ifa_next ) {
 
438
            if ( AA_SAT( aa )->sat_family == AF_APPLETALK &&
 
439
                    ( aa->aa_flags & AFA_PHASE2 ) == 0 ) {
 
440
                break;
 
441
            }
 
442
        }
 
443
        if ( aa == NULL ) {
 
444
            m_freem( m );
 
445
            return;
 
446
        }
 
447
        tpa.s_net = spa.s_net = AA_SAT( aa )->sat_addr.s_net;
 
448
    }
 
449
 
 
450
    spa.s_node = ea->aarp_spnode;
 
451
    tpa.s_node = ea->aarp_tpnode;
 
452
    ma.s_net = AA_SAT( aa )->sat_addr.s_net;
 
453
    ma.s_node = AA_SAT( aa )->sat_addr.s_node;
 
454
 
 
455
    /*
 
456
     * This looks like it's from us.
 
457
     */
 
458
    if ( spa.s_net == ma.s_net && spa.s_node == ma.s_node ) {
 
459
        if ( aa->aa_flags & AFA_PROBING ) {
 
460
            /*
 
461
             * We're probing, someone either responded to our probe, or
 
462
             * probed for the same address we'd like to use. Change the
 
463
             * address we're probing for.
 
464
             */
 
465
            untimeout( aarpprobe, ac );
 
466
            wakeup( aa );
 
467
            m_freem( m );
 
468
            return;
 
469
        } else if ( op != AARPOP_PROBE ) {
 
470
            /*
 
471
             * This is not a probe, and we're not probing. This means
 
472
             * that someone's saying they have the same source address
 
473
             * as the one we're using. Get upset...
 
474
             */
 
475
#ifndef _IBMR2
 
476
#ifdef ultrix
 
477
            mprintf( LOG_ERR,
 
478
#else /* ultrix */
 
479
            log( LOG_ERR,
 
480
#endif /* ultrix */
 
481
                    "aarp: duplicate AT address!! %x:%x:%x:%x:%x:%x\n",
 
482
                    ea->aarp_sha[ 0 ], ea->aarp_sha[ 1 ], ea->aarp_sha[ 2 ],
 
483
                    ea->aarp_sha[ 3 ], ea->aarp_sha[ 4 ], ea->aarp_sha[ 5 ]);
 
484
#endif /* ! _IBMR2 */
 
485
            m_freem( m );
 
486
            return;
 
487
        }
 
488
    }
 
489
 
 
490
    AARPTAB_LOOK( aat, spa );
 
491
    if ( aat ) {
 
492
        if ( op == AARPOP_PROBE ) {
 
493
            /*
 
494
             * Someone's probing for spa, dealocate the one we've got,
 
495
             * so that if the prober keeps the address, we'll be able
 
496
             * to arp for him.
 
497
             */
 
498
            aarptfree( aat );
 
499
            m_freem( m );
 
500
            return;
 
501
        }
 
502
 
 
503
        bcopy(( caddr_t )ea->aarp_sha, ( caddr_t )aat->aat_enaddr,
 
504
                sizeof( ea->aarp_sha ));
 
505
        aat->aat_flags |= ATF_COM;
 
506
        if ( aat->aat_hold ) {
 
507
#ifdef _IBMR2
 
508
            /*
 
509
             * Like in ddp_output(), we can't rely on the if_output
 
510
             * routine to resolve AF_APPLETALK addresses, on the rs6k.
 
511
             * So, we fill the destination ethernet address here.
 
512
             *
 
513
             * This should really be replaced with something like
 
514
             * rsif_output(). XXX Will have to be for phase 2.
 
515
             */
 
516
             /* XXX maybe fill in the rest of the frame header */
 
517
            sat.sat_family = AF_UNSPEC;
 
518
            bcopy( aat->aat_enaddr, (*(struct sockaddr *)&sat).sa_data,
 
519
                    sizeof( aat->aat_enaddr ));
 
520
#else /* _IBMR2 */
 
521
            sat.sat_family = AF_APPLETALK;
 
522
            sat.sat_addr = spa;
 
523
#endif /* _IBMR2 */
 
524
            (*ac->ac_if.if_output)( &ac->ac_if, aat->aat_hold,
 
525
                    (struct sockaddr *)&sat );
 
526
            aat->aat_hold = 0;
 
527
        }
 
528
    }
 
529
 
 
530
    if ( aat == 0 && tpa.s_net == ma.s_net && tpa.s_node == ma.s_node
 
531
            && op != AARPOP_PROBE ) {
 
532
        if ( aat = aarptnew( &spa )) {
 
533
            bcopy(( caddr_t )ea->aarp_sha, ( caddr_t )aat->aat_enaddr,
 
534
                    sizeof( ea->aarp_sha ));
 
535
            aat->aat_flags |= ATF_COM;
 
536
        }
 
537
    }
 
538
 
 
539
    /*
 
540
     * Don't respond to responses, and never respond if we're
 
541
     * still probing.
 
542
     */
 
543
    if ( tpa.s_net != ma.s_net || tpa.s_node != ma.s_node ||
 
544
            op == AARPOP_RESPONSE || ( aa->aa_flags & AFA_PROBING )) {
 
545
        m_freem( m );
 
546
        return;
 
547
    }
 
548
 
 
549
    bcopy(( caddr_t )ea->aarp_sha, ( caddr_t )ea->aarp_tha,
 
550
            sizeof( ea->aarp_sha ));
 
551
#ifdef sun
 
552
    bcopy(( caddr_t )&ac->ac_enaddr, ( caddr_t )ea->aarp_sha,
 
553
            sizeof( ea->aarp_sha ));
 
554
#else /* sun */
 
555
    bcopy(( caddr_t )ac->ac_enaddr, ( caddr_t )ea->aarp_sha,
 
556
            sizeof( ea->aarp_sha ));
 
557
#endif /* sun */
 
558
 
 
559
    eh = (struct ether_header *)sa.sa_data;
 
560
#ifdef sun
 
561
    bcopy(( caddr_t )ea->aarp_tha, ( caddr_t )&eh->ether_dhost,
 
562
            sizeof( eh->ether_dhost ));
 
563
#else /* sun */
 
564
    bcopy(( caddr_t )ea->aarp_tha, ( caddr_t )eh->ether_dhost,
 
565
            sizeof( eh->ether_dhost ));
 
566
#endif /* sun */
 
567
 
 
568
    if ( aa->aa_flags & AFA_PHASE2 ) {
 
569
#if defined( sun ) && defined( i386 )
 
570
        eh->ether_type = htons( sizeof( struct llc ) +
 
571
                sizeof( struct ether_aarp ));
 
572
#else /* sun && i386 */
 
573
        eh->ether_type = sizeof( struct llc ) + sizeof( struct ether_aarp );
 
574
#endif /* sun && i386 */
 
575
#ifdef BSD4_4
 
576
        M_PREPEND( m, sizeof( struct llc ), M_DONTWAIT );
 
577
        if ( m == NULL ) {
 
578
            m_freem( m );
 
579
            return;
 
580
        }
 
581
#else /* BSD4_4 */
 
582
        MGET( m0, M_DONTWAIT, MT_HEADER );
 
583
        if ( m0 == NULL ) {
 
584
            m_freem( m );
 
585
            return;
 
586
        }
 
587
        m0->m_next = m;
 
588
        m = m0;
 
589
        m->m_off = MMAXOFF - sizeof( struct llc );
 
590
        m->m_len = sizeof ( struct llc );
 
591
#endif /* BSD4_4 */
 
592
        llc = mtod( m, struct llc *);
 
593
        llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
 
594
        llc->llc_control = LLC_UI;
 
595
        bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
 
596
        llc->llc_ether_type = htons( ETHERTYPE_AARP );
 
597
 
 
598
        bcopy( ea->aarp_spnet, ea->aarp_tpnet, sizeof( ea->aarp_tpnet ));
 
599
        bcopy( &ma.s_net, ea->aarp_spnet, sizeof( ea->aarp_spnet ));
 
600
    } else {
 
601
#if defined( sun ) && defined( i386 )
 
602
        eh->ether_type = htons( ETHERTYPE_AARP );
 
603
#else /* sun && i386 */
 
604
        eh->ether_type = ETHERTYPE_AARP;
 
605
#endif /* sun && i386 */
 
606
    }
 
607
 
 
608
    ea->aarp_tpnode = ea->aarp_spnode;
 
609
    ea->aarp_spnode = ma.s_node;
 
610
    ea->aarp_op = htons( AARPOP_RESPONSE );
 
611
 
 
612
#ifdef BSD4_4
 
613
    sa.sa_len = sizeof( struct sockaddr );
 
614
#endif /* BSD4_4 */
 
615
    sa.sa_family = AF_UNSPEC;
 
616
    (*ac->ac_if.if_output)( &ac->ac_if, m, &sa );
 
617
    return;
 
618
}
 
619
 
 
620
aarptfree( aat )
 
621
    struct aarptab      *aat;
 
622
{
 
623
 
 
624
    if ( aat->aat_hold )
 
625
        m_freem( aat->aat_hold );
 
626
    aat->aat_hold = 0;
 
627
    aat->aat_timer = aat->aat_flags = 0;
 
628
    aat->aat_ataddr.s_net = 0;
 
629
    aat->aat_ataddr.s_node = 0;
 
630
}
 
631
 
 
632
    struct aarptab *
 
633
aarptnew( addr )
 
634
    struct at_addr      *addr;
 
635
{
 
636
    int                 n;
 
637
    int                 oldest = -1;
 
638
    struct aarptab      *aat, *aato = NULL;
 
639
    static int          first = 1;
 
640
 
 
641
    if ( first ) {
 
642
        first = 0;
 
643
        timeout( aarptimer, (caddr_t)0, hz );
 
644
    }
 
645
    aat = &aarptab[ AARPTAB_HASH( *addr ) * AARPTAB_BSIZ ];
 
646
    for ( n = 0; n < AARPTAB_BSIZ; n++, aat++ ) {
 
647
        if ( aat->aat_flags == 0 )
 
648
            goto out;
 
649
        if ( aat->aat_flags & ATF_PERM )
 
650
            continue;
 
651
        if ((int) aat->aat_timer > oldest ) {
 
652
            oldest = aat->aat_timer;
 
653
            aato = aat;
 
654
        }
 
655
    }
 
656
    if ( aato == NULL )
 
657
        return( NULL );
 
658
    aat = aato;
 
659
    aarptfree( aat );
 
660
out:
 
661
    aat->aat_ataddr = *addr;
 
662
    aat->aat_flags = ATF_INUSE;
 
663
    return( aat );
 
664
}
 
665
 
 
666
aarpprobe( ac )
 
667
    struct arpcom       *ac;
 
668
{
 
669
    struct mbuf         *m;
 
670
    struct ether_header *eh;
 
671
    struct ether_aarp   *ea;
 
672
    struct at_ifaddr    *aa;
 
673
    struct llc          *llc;
 
674
    struct sockaddr     sa;
 
675
 
 
676
    /*
 
677
     * We need to check whether the output ethernet type should
 
678
     * be phase 1 or 2. We have the interface that we'll be sending
 
679
     * the aarp out. We need to find an AppleTalk network on that
 
680
     * interface with the same address as we're looking for. If the
 
681
     * net is phase 2, generate an 802.2 and SNAP header.
 
682
     */
 
683
    for ( aa = (struct at_ifaddr *)ac->ac_if.if_addrlist; aa;
 
684
            aa = (struct at_ifaddr *)aa->aa_ifa.ifa_next ) {
 
685
        if ( AA_SAT( aa )->sat_family == AF_APPLETALK &&
 
686
                ( aa->aa_flags & AFA_PROBING )) {
 
687
            break;
 
688
        }
 
689
    }
 
690
    if ( aa == NULL ) {         /* serious error XXX */
 
691
        printf( "aarpprobe why did this happen?!\n" );
 
692
        return;
 
693
    }
 
694
 
 
695
    if ( aa->aa_probcnt <= 0 ) {
 
696
        aa->aa_flags &= ~AFA_PROBING;
 
697
        wakeup( aa );
 
698
        return;
 
699
    } else {
 
700
        timeout( aarpprobe, (caddr_t)ac, hz / 5 );
 
701
    }
 
702
 
 
703
#ifdef BSD4_4
 
704
    if (( m = m_gethdr( M_DONTWAIT, MT_DATA )) == NULL ) {
 
705
        return;
 
706
    }
 
707
    m->m_len = sizeof( *ea );
 
708
    m->m_pkthdr.len = sizeof( *ea );
 
709
    MH_ALIGN( m, sizeof( *ea ));
 
710
#else /* BSD4_4 */
 
711
    if (( m = m_get( M_DONTWAIT, MT_DATA )) == NULL ) {
 
712
        return;
 
713
    }
 
714
    m->m_len = sizeof( *ea );
 
715
    m->m_off = MMAXOFF - sizeof( *ea );
 
716
#endif /* BSD4_4 */
 
717
 
 
718
    ea = mtod( m, struct ether_aarp *);
 
719
    bzero((caddr_t)ea, sizeof( *ea ));
 
720
 
 
721
    ea->aarp_hrd = htons( AARPHRD_ETHER );
 
722
    ea->aarp_pro = htons( ETHERTYPE_AT );
 
723
    ea->aarp_hln = sizeof( ea->aarp_sha );
 
724
    ea->aarp_pln = sizeof( ea->aarp_spu );
 
725
    ea->aarp_op = htons( AARPOP_PROBE );
 
726
#ifdef sun
 
727
    bcopy((caddr_t)&ac->ac_enaddr, (caddr_t)ea->aarp_sha,
 
728
            sizeof( ea->aarp_sha ));
 
729
#else /* sun */
 
730
    bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->aarp_sha,
 
731
            sizeof( ea->aarp_sha ));
 
732
#endif /* sun */
 
733
 
 
734
    eh = (struct ether_header *)sa.sa_data;
 
735
 
 
736
    if ( aa->aa_flags & AFA_PHASE2 ) {
 
737
#ifdef sun
 
738
        bcopy((caddr_t)atmulticastaddr, (caddr_t)&eh->ether_dhost,
 
739
                sizeof( eh->ether_dhost ));
 
740
#else /* sun */
 
741
        bcopy((caddr_t)atmulticastaddr, (caddr_t)eh->ether_dhost,
 
742
                sizeof( eh->ether_dhost ));
 
743
#endif /* sun */
 
744
#if defined( sun ) && defined( i386 )
 
745
        eh->ether_type = htons( sizeof( struct llc ) +
 
746
                sizeof( struct ether_aarp ));
 
747
#else /* sun && i386 */
 
748
        eh->ether_type = sizeof( struct llc ) + sizeof( struct ether_aarp );
 
749
#endif /* sun && i386 */
 
750
#ifdef BSD4_4
 
751
        M_PREPEND( m, sizeof( struct llc ), M_WAIT );
 
752
#else /* BSD4_4 */
 
753
        m->m_len += sizeof( struct llc );
 
754
        m->m_off -= sizeof( struct llc );
 
755
#endif /* BSD4_4 */
 
756
        llc = mtod( m, struct llc *);
 
757
        llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
 
758
        llc->llc_control = LLC_UI;
 
759
        bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
 
760
        llc->llc_ether_type = htons( ETHERTYPE_AARP );
 
761
 
 
762
        bcopy( &AA_SAT( aa )->sat_addr.s_net, ea->aarp_spnet,
 
763
                sizeof( ea->aarp_spnet ));
 
764
        bcopy( &AA_SAT( aa )->sat_addr.s_net, ea->aarp_tpnet,
 
765
                sizeof( ea->aarp_tpnet ));
 
766
        ea->aarp_spnode = ea->aarp_tpnode = AA_SAT( aa )->sat_addr.s_node;
 
767
    } else {
 
768
#ifdef sun
 
769
        bcopy((caddr_t)&etherbroadcastaddr, (caddr_t)&eh->ether_dhost,
 
770
                sizeof( eh->ether_dhost ));
 
771
#else /* sun */
 
772
        bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
 
773
                sizeof( eh->ether_dhost ));
 
774
#endif /* sun */
 
775
#if defined( sun ) && defined( i386 )
 
776
        eh->ether_type = htons( ETHERTYPE_AARP );
 
777
#else /* sun && i386 */
 
778
        eh->ether_type = ETHERTYPE_AARP;
 
779
#endif /* sun && i386 */
 
780
        ea->aarp_spa = ea->aarp_tpa = AA_SAT( aa )->sat_addr.s_node;
 
781
    }
 
782
 
 
783
#ifdef BSD4_4
 
784
    sa.sa_len = sizeof( struct sockaddr );
 
785
#endif /* BSD4_4 */
 
786
    sa.sa_family = AF_UNSPEC;
 
787
    (*ac->ac_if.if_output)(&ac->ac_if, m, &sa );
 
788
    aa->aa_probcnt--;
 
789
}
 
790
 
 
791
aarp_clean()
 
792
{
 
793
    struct aarptab      *aat;
 
794
    int                 i;
 
795
 
 
796
    untimeout( aarptimer, 0 );
 
797
    for ( i = 0, aat = aarptab; i < AARPTAB_SIZE; i++, aat++ ) {
 
798
        if ( aat->aat_hold ) {
 
799
            m_freem( aat->aat_hold );
 
800
        }
 
801
    }
 
802
}