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