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