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