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