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