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