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