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