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