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