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