1 /* $NetBSD: aarp.c,v 1.40 2017/12/09 10:14:04 maxv 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.40 2017/12/09 10:14:04 maxv 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 /* We should also check ar_hln and ar_pln. */ 355 if ((m = m_pullup(m, sizeof(struct ether_aarp))) == NULL) { 356 return; 357 } 358 359 ea = mtod(m, struct ether_aarp *); 360 361 /* Check to see if from my hardware address */ 362 if (!memcmp(ea->aarp_sha, CLLADDR(ifp->if_sadl), sizeof(ea->aarp_sha))) { 363 m_freem(m); 364 return; 365 } 366 op = ntohs(ea->aarp_op); 367 memcpy(&net, ea->aarp_tpnet, sizeof(net)); 368 369 if (net != 0) { /* should be ATADDR_ANYNET? */ 370 sat.sat_len = sizeof(struct sockaddr_at); 371 sat.sat_family = AF_APPLETALK; 372 sat.sat_addr.s_net = net; 373 374 s = pserialize_read_enter(); 375 ifa = at_ifawithnet(&sat, ifp); 376 if (ifa == NULL) { 377 pserialize_read_exit(s); 378 m_freem(m); 379 return; 380 } 381 ifa_acquire(ifa, &psref); 382 pserialize_read_exit(s); 383 aa = (struct at_ifaddr *)ifa; 384 385 memcpy(&spa.s_net, ea->aarp_spnet, sizeof(spa.s_net)); 386 memcpy(&tpa.s_net, ea->aarp_tpnet, sizeof(tpa.s_net)); 387 } else { 388 /* 389 * Since we don't know the net, we just look for the first 390 * phase 1 address on the interface. 391 */ 392 s = pserialize_read_enter(); 393 IFADDR_READER_FOREACH(ifa, ifp) { 394 aa = (struct at_ifaddr *)ifa; 395 if (AA_SAT(aa)->sat_family == AF_APPLETALK && 396 (aa->aa_flags & AFA_PHASE2) == 0) { 397 ifa_acquire(ifa, &psref); 398 break; 399 } 400 } 401 pserialize_read_exit(s); 402 403 if (ifa == NULL) { 404 m_freem(m); 405 return; 406 } 407 tpa.s_net = spa.s_net = AA_SAT(aa)->sat_addr.s_net; 408 } 409 410 spa.s_node = ea->aarp_spnode; 411 tpa.s_node = ea->aarp_tpnode; 412 ma.s_net = AA_SAT(aa)->sat_addr.s_net; 413 ma.s_node = AA_SAT(aa)->sat_addr.s_node; 414 415 /* 416 * This looks like it's from us. 417 */ 418 if (spa.s_net == ma.s_net && spa.s_node == ma.s_node) { 419 if (aa->aa_flags & AFA_PROBING) { 420 /* 421 * We're probing, someone either responded to our 422 * probe, or probed for the same address we'd like 423 * to use. Change the address we're probing for. 424 */ 425 callout_stop(&aa->aa_probe_ch); 426 wakeup(aa); 427 m_freem(m); 428 goto out; 429 } else if (op != AARPOP_PROBE) { 430 /* 431 * This is not a probe, and we're not probing. 432 * This means that someone's saying they have the same 433 * source address as the one we're using. Get upset... 434 */ 435 log(LOG_ERR, "aarp: duplicate AT address!! %s\n", 436 ether_sprintf(ea->aarp_sha)); 437 m_freem(m); 438 goto out; 439 } 440 } 441 AARPTAB_LOOK(aat, spa); 442 if (aat) { 443 if (op == AARPOP_PROBE) { 444 /* 445 * Someone's probing for spa, deallocate the one we've 446 * got, so that if the prober keeps the address, we'll 447 * be able to arp for him. 448 */ 449 aarptfree(aat); 450 m_freem(m); 451 goto out; 452 } 453 memcpy(aat->aat_enaddr, ea->aarp_sha, sizeof(ea->aarp_sha)); 454 aat->aat_flags |= ATF_COM; 455 if (aat->aat_hold) { 456 sat.sat_len = sizeof(struct sockaddr_at); 457 sat.sat_family = AF_APPLETALK; 458 sat.sat_addr = spa; 459 if_output_lock(ifp, ifp, aat->aat_hold, 460 (struct sockaddr *) & sat, NULL); /* XXX */ 461 aat->aat_hold = 0; 462 } 463 } 464 if (aat == 0 && tpa.s_net == ma.s_net && tpa.s_node == ma.s_node 465 && op != AARPOP_PROBE) { 466 if ((aat = aarptnew(&spa)) != NULL) { 467 memcpy(aat->aat_enaddr, ea->aarp_sha, 468 sizeof(ea->aarp_sha)); 469 aat->aat_flags |= ATF_COM; 470 } 471 } 472 /* 473 * Don't respond to responses, and never respond if we're 474 * still probing. 475 */ 476 if (tpa.s_net != ma.s_net || tpa.s_node != ma.s_node || 477 op == AARPOP_RESPONSE || (aa->aa_flags & AFA_PROBING)) { 478 m_freem(m); 479 goto out; 480 } 481 482 /* 483 * Prepare and send AARP-response. 484 */ 485 m->m_len = sizeof(*ea); 486 m->m_pkthdr.len = sizeof(*ea); 487 memcpy(ea->aarp_tha, ea->aarp_sha, sizeof(ea->aarp_sha)); 488 memcpy(ea->aarp_sha, CLLADDR(ifp->if_sadl), sizeof(ea->aarp_sha)); 489 490 /* XXX */ 491 eh = (struct ether_header *) sa.sa_data; 492 memcpy(eh->ether_dhost, ea->aarp_tha, sizeof(eh->ether_dhost)); 493 494 if (aa->aa_flags & AFA_PHASE2) { 495 M_PREPEND(m, sizeof(struct llc), M_DONTWAIT); 496 if (m == NULL) 497 goto out; 498 499 llc = mtod(m, struct llc *); 500 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP; 501 llc->llc_control = LLC_UI; 502 memcpy(llc->llc_org_code, aarp_org_code, sizeof(aarp_org_code)); 503 llc->llc_ether_type = htons(ETHERTYPE_AARP); 504 505 memcpy(ea->aarp_tpnet, ea->aarp_spnet, sizeof(ea->aarp_tpnet)); 506 memcpy(ea->aarp_spnet, &ma.s_net, sizeof(ea->aarp_spnet)); 507 eh->ether_type = 0; /* if_output will treat as 802 */ 508 } else { 509 eh->ether_type = htons(ETHERTYPE_AARP); 510 } 511 512 ea->aarp_tpnode = ea->aarp_spnode; 513 ea->aarp_spnode = ma.s_node; 514 ea->aarp_op = htons(AARPOP_RESPONSE); 515 516 sa.sa_len = sizeof(struct sockaddr); 517 sa.sa_family = AF_UNSPEC; 518 (*ifp->if_output) (ifp, m, &sa, NULL); /* XXX */ 519 out: 520 ifa_release(ifa, &psref); 521 return; 522 } 523 524 static void 525 aarptfree(struct aarptab *aat) 526 { 527 528 if (aat->aat_hold) 529 m_freem(aat->aat_hold); 530 aat->aat_hold = 0; 531 aat->aat_timer = aat->aat_flags = 0; 532 aat->aat_ataddr.s_net = 0; 533 aat->aat_ataddr.s_node = 0; 534 } 535 536 static struct aarptab * 537 aarptnew(const struct at_addr *addr) 538 { 539 int n; 540 int oldest = -1; 541 struct aarptab *aat, *aato = NULL; 542 static int first = 1; 543 544 if (first) { 545 first = 0; 546 callout_init(&aarptimer_callout, 0); 547 callout_reset(&aarptimer_callout, hz, aarptimer, NULL); 548 } 549 aat = &aarptab[AARPTAB_HASH(*addr) * AARPTAB_BSIZ]; 550 for (n = 0; n < AARPTAB_BSIZ; n++, aat++) { 551 if (aat->aat_flags == 0) 552 goto out; 553 if (aat->aat_flags & ATF_PERM) 554 continue; 555 if ((int) aat->aat_timer > oldest) { 556 oldest = aat->aat_timer; 557 aato = aat; 558 } 559 } 560 if (aato == NULL) 561 return (NULL); 562 aat = aato; 563 aarptfree(aat); 564 out: 565 aat->aat_ataddr = *addr; 566 aat->aat_flags = ATF_INUSE; 567 return (aat); 568 } 569 570 571 void 572 aarpprobe(void *arp) 573 { 574 struct mbuf *m; 575 struct ether_header *eh; 576 struct ether_aarp *ea; 577 struct ifaddr *ia; 578 struct at_ifaddr *aa; 579 struct llc *llc; 580 struct sockaddr sa; 581 struct ifnet *ifp = arp; 582 583 mutex_enter(softnet_lock); 584 585 /* 586 * We need to check whether the output ethernet type should 587 * be phase 1 or 2. We have the interface that we'll be sending 588 * the aarp out. We need to find an AppleTalk network on that 589 * interface with the same address as we're looking for. If the 590 * net is phase 2, generate an 802.2 and SNAP header. 591 */ 592 IFADDR_READER_FOREACH(ia, ifp) { 593 aa = (struct at_ifaddr *)ia; 594 if (AA_SAT(aa)->sat_family == AF_APPLETALK && 595 (aa->aa_flags & AFA_PROBING)) 596 break; 597 } 598 if (ia == NULL) { /* serious error XXX */ 599 printf("aarpprobe why did this happen?!\n"); 600 mutex_exit(softnet_lock); 601 return; 602 } 603 if (aa->aa_probcnt <= 0) { 604 aa->aa_flags &= ~AFA_PROBING; 605 wakeup(aa); 606 mutex_exit(softnet_lock); 607 return; 608 } else { 609 callout_reset(&aa->aa_probe_ch, hz / 5, aarpprobe, arp); 610 } 611 612 if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) { 613 mutex_exit(softnet_lock); 614 return; 615 } 616 617 MCLAIM(m, &aarp_mowner); 618 m->m_len = sizeof(*ea); 619 m->m_pkthdr.len = sizeof(*ea); 620 MH_ALIGN(m, sizeof(*ea)); 621 622 ea = mtod(m, struct ether_aarp *); 623 memset(ea, 0, sizeof(*ea)); 624 625 ea->aarp_hrd = htons(AARPHRD_ETHER); 626 ea->aarp_pro = htons(ETHERTYPE_ATALK); 627 ea->aarp_hln = sizeof(ea->aarp_sha); 628 ea->aarp_pln = sizeof(ea->aarp_spu); 629 ea->aarp_op = htons(AARPOP_PROBE); 630 memcpy(ea->aarp_sha, CLLADDR(ifp->if_sadl), sizeof(ea->aarp_sha)); 631 632 eh = (struct ether_header *) sa.sa_data; 633 634 if (aa->aa_flags & AFA_PHASE2) { 635 memcpy(eh->ether_dhost, atmulticastaddr, 636 sizeof(eh->ether_dhost)); 637 eh->ether_type = 0; /* if_output will treat as 802 */ 638 M_PREPEND(m, sizeof(struct llc), M_DONTWAIT); 639 if (!m) { 640 mutex_exit(softnet_lock); 641 return; 642 } 643 644 llc = mtod(m, struct llc *); 645 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP; 646 llc->llc_control = LLC_UI; 647 memcpy(llc->llc_org_code, aarp_org_code, sizeof(aarp_org_code)); 648 llc->llc_ether_type = htons(ETHERTYPE_AARP); 649 650 memcpy(ea->aarp_spnet, &AA_SAT(aa)->sat_addr.s_net, 651 sizeof(ea->aarp_spnet)); 652 memcpy(ea->aarp_tpnet, &AA_SAT(aa)->sat_addr.s_net, 653 sizeof(ea->aarp_tpnet)); 654 ea->aarp_spnode = ea->aarp_tpnode = 655 AA_SAT(aa)->sat_addr.s_node; 656 } else { 657 memcpy(eh->ether_dhost, etherbroadcastaddr, 658 sizeof(eh->ether_dhost)); 659 eh->ether_type = htons(ETHERTYPE_AARP); 660 ea->aarp_spa = ea->aarp_tpa = AA_SAT(aa)->sat_addr.s_node; 661 } 662 663 #ifdef NETATALKDEBUG 664 printf("aarp: sending probe for %u.%u\n", 665 ntohs(AA_SAT(aa)->sat_addr.s_net), 666 AA_SAT(aa)->sat_addr.s_node); 667 #endif /* NETATALKDEBUG */ 668 669 sa.sa_len = sizeof(struct sockaddr); 670 sa.sa_family = AF_UNSPEC; 671 (*ifp->if_output) (ifp, m, &sa, NULL); /* XXX */ 672 aa->aa_probcnt--; 673 mutex_exit(softnet_lock); 674 } 675 676 void 677 aarp_clean(void) 678 { 679 struct aarptab *aat; 680 int i; 681 682 callout_stop(&aarptimer_callout); 683 for (i = 0, aat = aarptab; i < AARPTAB_SIZE; i++, aat++) 684 if (aat->aat_hold) 685 m_freem(aat->aat_hold); 686 } 687