2 * Copyright (c) 1990,1991 Regents of The University of Michigan.
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.24 2008/05/14 11:59:24 sephe Exp $
11 #include <sys/param.h>
12 #include <sys/systm.h>
14 #include <sys/kernel.h>
15 #include <sys/socket.h>
16 #include <sys/syslog.h>
18 #include <sys/thread2.h>
19 #include <sys/msgport2.h>
20 #include <sys/mplock2.h>
23 #include <net/netisr.h>
25 #include <netinet/in.h>
27 #include <netinet/if_ether.h>
33 #include "at_extern.h"
35 static void aarptfree( struct aarptab *aat);
36 static void at_aarpinput( struct arpcom *ac, struct mbuf *m);
38 #define AARPTAB_BSIZ 9
40 #define AARPTAB_SIZE (AARPTAB_BSIZ * AARPTAB_NB)
41 static struct aarptab aarptab[AARPTAB_SIZE];
43 #define AARPTAB_HASH(a) \
44 ((((a).s_net << 8 ) + (a).s_node ) % AARPTAB_NB )
46 #define AARPTAB_LOOK(aat,addr) { \
48 aat = &aarptab[ AARPTAB_HASH(addr) * AARPTAB_BSIZ ]; \
49 for ( n = 0; n < AARPTAB_BSIZ; n++, aat++ ) \
50 if ( aat->aat_ataddr.s_net == (addr).s_net && \
51 aat->aat_ataddr.s_node == (addr).s_node ) \
53 if ( n >= AARPTAB_BSIZ ) \
57 #define AARPT_AGE (60 * 1)
58 #define AARPT_KILLC 20
61 static u_char atmulticastaddr[ 6 ] = {
62 0x09, 0x00, 0x07, 0xff, 0xff, 0xff,
65 u_char at_org_code[ 3 ] = {
68 u_char aarp_org_code[ 3 ] = {
72 static struct callout aarptimer_ch;
75 aarptimer(void *ignored)
81 for ( i = 0; i < AARPTAB_SIZE; i++, aat++ ) {
82 if ( aat->aat_flags == 0 || ( aat->aat_flags & ATF_PERM ))
84 if ( ++aat->aat_timer < (( aat->aat_flags & ATF_COM ) ?
85 AARPT_KILLC : AARPT_KILLI ))
91 callout_reset(&aarptimer_ch, AARPT_AGE * hz, aarptimer, NULL);
95 * search through the network addresses to find one that includes
96 * the given network.. remember to take netranges into
100 at_ifawithnet(struct sockaddr_at *sat)
102 struct at_ifaddr *aa;
103 struct sockaddr_at *sat2;
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 ) {
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))) {
120 aarpwhohas(struct arpcom *ac, struct sockaddr_at *sat)
123 struct ether_header *eh;
124 struct ether_aarp *ea;
125 struct at_ifaddr *aa;
129 if (( m = m_gethdr( MB_DONTWAIT, MT_DATA )) == NULL ) {
132 m->m_len = sizeof( *ea );
133 m->m_pkthdr.len = sizeof( *ea );
134 MH_ALIGN( m, sizeof( *ea ));
136 ea = mtod( m, struct ether_aarp *);
137 bzero((caddr_t)ea, sizeof( *ea ));
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(ac->ac_enaddr, ea->aarp_sha, sizeof ea->aarp_sha);
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.
153 if ((aa = at_ifawithnet( sat )) == NULL) {
158 eh = (struct ether_header *)sa.sa_data;
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 );
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;
178 bcopy(ac->ac_if.if_broadcastaddr, eh->ether_dhost,
179 ac->ac_if.if_addrlen);
180 eh->ether_type = htons( ETHERTYPE_AARP );
182 ea->aarp_spa = AA_SAT( aa )->sat_addr.s_node;
183 ea->aarp_tpa = sat->sat_addr.s_node;
187 kprintf("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 */
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 */
199 aarpresolve(struct arpcom *ac, struct mbuf *m, struct sockaddr_at *destsat,
202 struct at_ifaddr *aa;
205 if (at_broadcast(destsat)) {
206 m->m_flags |= M_BCAST;
207 if ((aa = at_ifawithnet(destsat)) == NULL) {
211 if (aa->aa_flags & AFA_PHASE2)
212 bcopy(atmulticastaddr, desten, sizeof atmulticastaddr);
214 bcopy(ac->ac_if.if_broadcastaddr, desten, ac->ac_if.if_addrlen);
219 AARPTAB_LOOK( aat, destsat->sat_addr );
220 if (aat == NULL) { /* No entry */
221 aat = aarptnew( &destsat->sat_addr );
223 panic("aarpresolve: no free entry");
226 aarpwhohas(ac, destsat);
232 if (aat->aat_flags & ATF_COM) { /* entry is COMplete */
233 bcopy(aat->aat_enaddr, desten, sizeof aat->aat_enaddr);
237 /* entry has not completed */
239 m_freem(aat->aat_hold);
242 aarpwhohas(ac, destsat);
248 aarpintr(struct netmsg *msg)
250 struct mbuf *m = ((struct netmsg_packet *)msg)->nm_packet;
256 ac = (struct arpcom *)m->m_pkthdr.rcvif;
257 if ( ac->ac_if.if_flags & IFF_NOARP )
260 if ( m->m_len < sizeof( struct arphdr )) {
264 ar = mtod( m, struct arphdr *);
265 if ( ntohs( ar->ar_hrd ) != AARPHRD_ETHER ) {
269 if ( m->m_len < sizeof( struct arphdr ) + 2 * ar->ar_hln +
274 switch( ntohs( ar->ar_pro )) {
276 at_aarpinput( ac, m );
287 /* msg was embedded in the mbuf, do not reply! */
291 at_aarpinput( struct arpcom *ac, struct mbuf *m)
293 struct ether_aarp *ea;
294 struct at_ifaddr *aa = NULL;
296 struct ether_header *eh;
298 struct sockaddr_at sat;
300 struct at_addr spa, tpa, ma;
304 ea = mtod( m, struct ether_aarp *);
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 ))) {
313 op = ntohs(ea->aarp_op);
314 bcopy(ea->aarp_tpnet, &net, sizeof net);
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) {
324 bcopy(ea->aarp_spnet, &spa.s_net, sizeof spa.s_net);
325 bcopy(ea->aarp_tpnet, &tpa.s_net, sizeof tpa.s_net);
327 struct ifaddr_container *ifac;
330 * Since we don't know the net, we just look for the first
331 * phase 1 address on the interface.
333 TAILQ_FOREACH(ifac, &ac->ac_if.if_addrheads[mycpuid], ifa_link) {
334 aa = (struct at_ifaddr *)(ifac->ifa);
335 if ( AA_SAT( aa )->sat_family == AF_APPLETALK &&
336 ( aa->aa_flags & AFA_PHASE2 ) == 0 ) {
344 tpa.s_net = spa.s_net = AA_SAT( aa )->sat_addr.s_net;
347 spa.s_node = ea->aarp_spnode;
348 tpa.s_node = ea->aarp_tpnode;
349 ma.s_net = AA_SAT( aa )->sat_addr.s_net;
350 ma.s_node = AA_SAT( aa )->sat_addr.s_node;
353 * This looks like it's from us.
355 if ( spa.s_net == ma.s_net && spa.s_node == ma.s_node ) {
356 if ( aa->aa_flags & AFA_PROBING ) {
358 * We're probing, someone either responded to our probe, or
359 * probed for the same address we'd like to use. Change the
360 * address we're probing for.
362 callout_stop(&aa->aa_ch);
366 } else if ( op != AARPOP_PROBE ) {
368 * This is not a probe, and we're not probing. This means
369 * that someone's saying they have the same source address
370 * as the one we're using. Get upset...
373 "aarp: duplicate AT address!! %x:%x:%x:%x:%x:%x\n",
374 ea->aarp_sha[ 0 ], ea->aarp_sha[ 1 ], ea->aarp_sha[ 2 ],
375 ea->aarp_sha[ 3 ], ea->aarp_sha[ 4 ], ea->aarp_sha[ 5 ]);
381 AARPTAB_LOOK( aat, spa );
383 if ( op == AARPOP_PROBE ) {
385 * Someone's probing for spa, dealocate the one we've got,
386 * so that if the prober keeps the address, we'll be able
394 bcopy(( caddr_t )ea->aarp_sha, ( caddr_t )aat->aat_enaddr,
395 sizeof( ea->aarp_sha ));
396 aat->aat_flags |= ATF_COM;
397 if ( aat->aat_hold ) {
398 struct mbuf *mhold = aat->aat_hold;
399 aat->aat_hold = NULL;
400 sat.sat_len = sizeof(struct sockaddr_at);
401 sat.sat_family = AF_APPLETALK;
403 ac->ac_if.if_output(&ac->ac_if, mhold,
404 (struct sockaddr *)&sat, NULL); /* XXX */
406 } else if ((tpa.s_net == ma.s_net)
407 && (tpa.s_node == ma.s_node)
408 && (op != AARPOP_PROBE)
409 && ((aat = aarptnew( &spa )) != NULL)) {
410 bcopy(( caddr_t )ea->aarp_sha, ( caddr_t )aat->aat_enaddr,
411 sizeof( ea->aarp_sha ));
412 aat->aat_flags |= ATF_COM;
416 * Don't respond to responses, and never respond if we're
419 if ( tpa.s_net != ma.s_net || tpa.s_node != ma.s_node ||
420 op == AARPOP_RESPONSE || ( aa->aa_flags & AFA_PROBING )) {
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 ));
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 ));
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 ), MB_DONTWAIT );
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 );
448 bcopy( ea->aarp_spnet, ea->aarp_tpnet, sizeof( ea->aarp_tpnet ));
449 bcopy( &ma.s_net, ea->aarp_spnet, sizeof( ea->aarp_spnet ));
451 eh->ether_type = htons( ETHERTYPE_AARP );
454 ea->aarp_tpnode = ea->aarp_spnode;
455 ea->aarp_spnode = ma.s_node;
456 ea->aarp_op = htons( AARPOP_RESPONSE );
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 */
465 aarptfree(struct aarptab *aat)
469 m_freem( aat->aat_hold );
470 aat->aat_hold = NULL;
471 aat->aat_timer = aat->aat_flags = 0;
472 aat->aat_ataddr.s_net = 0;
473 aat->aat_ataddr.s_node = 0;
477 aarptnew(struct at_addr *addr)
481 struct aarptab *aat, *aato = NULL;
482 static int first = 1;
486 callout_init(&aarptimer_ch);
487 callout_reset(&aarptimer_ch, hz, aarptimer, NULL);
489 aat = &aarptab[ AARPTAB_HASH( *addr ) * AARPTAB_BSIZ ];
490 for ( n = 0; n < AARPTAB_BSIZ; n++, aat++ ) {
491 if ( aat->aat_flags == 0 )
493 if ( aat->aat_flags & ATF_PERM )
495 if ((int) aat->aat_timer > oldest ) {
496 oldest = aat->aat_timer;
505 aat->aat_ataddr = *addr;
506 aat->aat_flags = ATF_INUSE;
514 struct arpcom *ac = arg;
516 struct ether_header *eh;
517 struct ether_aarp *ea;
518 struct ifaddr_container *ifac;
519 struct at_ifaddr *aa = NULL;
524 * We need to check whether the output ethernet type should
525 * be phase 1 or 2. We have the interface that we'll be sending
526 * the aarp out. We need to find an AppleTalk network on that
527 * interface with the same address as we're looking for. If the
528 * net is phase 2, generate an 802.2 and SNAP header.
530 TAILQ_FOREACH(ifac, &ac->ac_if.if_addrheads[mycpuid], ifa_link) {
531 aa = (struct at_ifaddr *)(ifac->ifa);
532 if ( AA_SAT( aa )->sat_family == AF_APPLETALK &&
533 ( aa->aa_flags & AFA_PROBING )) {
537 if ( aa == NULL ) { /* serious error XXX */
538 kprintf( "aarpprobe why did this happen?!\n" );
542 if ( aa->aa_probcnt <= 0 ) {
543 aa->aa_flags &= ~AFA_PROBING;
547 callout_reset(&aa->aa_ch, hz / 5, aarpprobe, ac);
550 if (( m = m_gethdr( MB_DONTWAIT, MT_DATA )) == NULL ) {
553 m->m_len = sizeof( *ea );
554 m->m_pkthdr.len = sizeof( *ea );
555 MH_ALIGN( m, sizeof( *ea ));
557 ea = mtod( m, struct ether_aarp *);
558 bzero((caddr_t)ea, sizeof( *ea ));
560 ea->aarp_hrd = htons( AARPHRD_ETHER );
561 ea->aarp_pro = htons( ETHERTYPE_AT );
562 ea->aarp_hln = sizeof( ea->aarp_sha );
563 ea->aarp_pln = sizeof( ea->aarp_spu );
564 ea->aarp_op = htons( AARPOP_PROBE );
565 bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->aarp_sha,
566 sizeof( ea->aarp_sha ));
568 eh = (struct ether_header *)sa.sa_data;
570 if ( aa->aa_flags & AFA_PHASE2 ) {
571 bcopy((caddr_t)atmulticastaddr, (caddr_t)eh->ether_dhost,
572 sizeof( eh->ether_dhost ));
573 eh->ether_type = htons( sizeof( struct llc ) +
574 sizeof( struct ether_aarp ));
575 M_PREPEND( m, sizeof( struct llc ), MB_WAIT );
577 llc = mtod( m, struct llc *);
578 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
579 llc->llc_control = LLC_UI;
580 bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
581 llc->llc_ether_type = htons( ETHERTYPE_AARP );
583 bcopy( &AA_SAT( aa )->sat_addr.s_net, ea->aarp_spnet,
584 sizeof( ea->aarp_spnet ));
585 bcopy( &AA_SAT( aa )->sat_addr.s_net, ea->aarp_tpnet,
586 sizeof( ea->aarp_tpnet ));
587 ea->aarp_spnode = ea->aarp_tpnode = AA_SAT( aa )->sat_addr.s_node;
589 bcopy(ac->ac_if.if_broadcastaddr, eh->ether_dhost,
590 ac->ac_if.if_addrlen);
591 eh->ether_type = htons( ETHERTYPE_AARP );
592 ea->aarp_spa = ea->aarp_tpa = AA_SAT( aa )->sat_addr.s_node;
596 kprintf("aarp: sending probe for %u.%u\n",
597 ntohs(AA_SAT( aa )->sat_addr.s_net),
598 AA_SAT( aa )->sat_addr.s_node);
599 #endif /* NETATALKDEBUG */
601 sa.sa_len = sizeof( struct sockaddr );
602 sa.sa_family = AF_UNSPEC;
603 ac->ac_if.if_output(&ac->ac_if, m, &sa, NULL); /* XXX */
613 callout_stop(&aarptimer_ch);
614 for ( i = 0, aat = aarptab; i < AARPTAB_SIZE; i++, aat++ ) {
615 if ( aat->aat_hold ) {
616 m_freem( aat->aat_hold );
617 aat->aat_hold = NULL;