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