1/*- 2 * Copyright (c) 2004-2009 Robert N. M. Watson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * Copyright (c) 1990,1991,1994 Regents of The University of Michigan. 27 * All Rights Reserved. 28 * 29 * Permission to use, copy, modify, and distribute this software and 30 * its documentation for any purpose and without fee is hereby granted, 31 * provided that the above copyright notice appears in all copies and 32 * that both that copyright notice and this permission notice appear 33 * in supporting documentation, and that the name of The University 34 * of Michigan not be used in advertising or publicity pertaining to 35 * distribution of the software without specific, written prior 36 * permission. This software is supplied as is without expressed or 37 * implied warranties of any kind. 38 * 39 * This product includes software developed by the University of 40 * California, Berkeley and its contributors. 41 * 42 * Research Systems Unix Group 43 * The University of Michigan 44 * c/o Wesley Craig 45 * 535 W. William Street 46 * Ann Arbor, Michigan 47 * +1-313-764-2278 48 * netatalk@umich.edu 49 *
|
50 * $FreeBSD: head/sys/netatalk/aarp.c 194619 2009-06-22 10:23:54Z rwatson $
|
50 * $FreeBSD: head/sys/netatalk/aarp.c 194819 2009-06-24 10:32:44Z rwatson $ |
51 */ 52 53#include "opt_atalk.h" 54 55#include <sys/param.h> 56#include <sys/systm.h> 57#include <sys/mbuf.h> 58#include <sys/kernel.h> 59#include <sys/socket.h> 60#include <sys/syslog.h> 61 62#include <net/if.h> 63#include <net/if_dl.h> 64 65#include <netinet/in.h> 66#undef s_net 67#include <netinet/if_ether.h> 68 69#include <netatalk/at.h> 70#include <netatalk/at_var.h> 71#include <netatalk/aarp.h> 72#include <netatalk/phase2.h> 73#include <netatalk/at_extern.h> 74 75#include <security/mac/mac_framework.h> 76 77static void aarptfree(struct aarptab *aat); 78static void at_aarpinput(struct ifnet *ifp, struct mbuf *m); 79 80#define AARPTAB_BSIZ 9 81#define AARPTAB_NB 19 82#define AARPTAB_SIZE (AARPTAB_BSIZ * AARPTAB_NB) 83static struct aarptab aarptab[AARPTAB_SIZE]; 84 85struct mtx aarptab_mtx; 86MTX_SYSINIT(aarptab_mtx, &aarptab_mtx, "aarptab_mtx", MTX_DEF); 87 88#define AARPTAB_HASH(a) ((((a).s_net << 8) + (a).s_node) % AARPTAB_NB) 89 90#define AARPTAB_LOOK(aat, addr) do { \ 91 int n; \ 92 \ 93 AARPTAB_LOCK_ASSERT(); \ 94 aat = &aarptab[ AARPTAB_HASH(addr) * AARPTAB_BSIZ ]; \ 95 for (n = 0; n < AARPTAB_BSIZ; n++, aat++) { \ 96 if (aat->aat_ataddr.s_net == (addr).s_net && \ 97 aat->aat_ataddr.s_node == (addr).s_node) \ 98 break; \ 99 } \ 100 if (n >= AARPTAB_BSIZ) \ 101 aat = NULL; \ 102} while (0) 103 104#define AARPT_AGE (60 * 1) 105#define AARPT_KILLC 20 106#define AARPT_KILLI 3 107 108static const u_char atmulticastaddr[6] = { 109 0x09, 0x00, 0x07, 0xff, 0xff, 0xff, 110}; 111 112u_char at_org_code[3] = { 113 0x08, 0x00, 0x07, 114}; 115const u_char aarp_org_code[3] = { 116 0x00, 0x00, 0x00, 117}; 118 119static struct callout_handle aarptimer_ch = 120 CALLOUT_HANDLE_INITIALIZER(&aarptimer_ch); 121 122static void 123aarptimer(void *ignored) 124{ 125 struct aarptab *aat; 126 int i; 127 128 aarptimer_ch = timeout(aarptimer, NULL, AARPT_AGE * hz); 129 aat = aarptab; 130 AARPTAB_LOCK(); 131 for (i = 0; i < AARPTAB_SIZE; i++, aat++) { 132 if (aat->aat_flags == 0 || (aat->aat_flags & ATF_PERM)) 133 continue; 134 if (++aat->aat_timer < ((aat->aat_flags & ATF_COM) ? 135 AARPT_KILLC : AARPT_KILLI)) 136 continue; 137 aarptfree(aat); 138 } 139 AARPTAB_UNLOCK(); 140} 141 142/* 143 * Search through the network addresses to find one that includes the given 144 * network. Remember to take netranges into consideration.
|
145 * 146 * The _locked variant relies on the caller holding the at_ifaddr lock; the 147 * unlocked variant returns a reference that the caller must dispose of. |
148 */ 149struct at_ifaddr *
|
147at_ifawithnet(struct sockaddr_at *sat)
|
150at_ifawithnet_locked(struct sockaddr_at *sat) |
151{ 152 struct at_ifaddr *aa; 153 struct sockaddr_at *sat2; 154 155 AT_IFADDR_LOCK_ASSERT(); 156 157 for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) { 158 sat2 = &(aa->aa_addr); 159 if (sat2->sat_addr.s_net == sat->sat_addr.s_net) 160 break; 161 if ((aa->aa_flags & AFA_PHASE2) && 162 (ntohs(aa->aa_firstnet) <= ntohs(sat->sat_addr.s_net)) && 163 (ntohs(aa->aa_lastnet) >= ntohs(sat->sat_addr.s_net))) 164 break; 165 } 166 return (aa); 167} 168
|
169struct at_ifaddr * 170at_ifawithnet(struct sockaddr_at *sat) 171{ 172 struct at_ifaddr *aa; 173 174 AT_IFADDR_RLOCK(); 175 aa = at_ifawithnet_locked(sat); 176 if (aa != NULL) 177 ifa_ref(&aa->aa_ifa); 178 AT_IFADDR_RUNLOCK(); 179 return (aa); 180} 181 |
182static void 183aarpwhohas(struct ifnet *ifp, struct sockaddr_at *sat) 184{ 185 struct mbuf *m; 186 struct ether_header *eh; 187 struct ether_aarp *ea; 188 struct at_ifaddr *aa; 189 struct llc *llc; 190 struct sockaddr sa; 191 192 AARPTAB_UNLOCK_ASSERT(); 193 m = m_gethdr(M_DONTWAIT, MT_DATA); 194 if (m == NULL) 195 return; 196#ifdef MAC 197 mac_netatalk_aarp_send(ifp, m); 198#endif 199 m->m_len = sizeof(*ea); 200 m->m_pkthdr.len = sizeof(*ea); 201 MH_ALIGN(m, sizeof(*ea)); 202 203 ea = mtod(m, struct ether_aarp *); 204 bzero((caddr_t)ea, sizeof(*ea)); 205 206 ea->aarp_hrd = htons(AARPHRD_ETHER); 207 ea->aarp_pro = htons(ETHERTYPE_AT); 208 ea->aarp_hln = sizeof(ea->aarp_sha); 209 ea->aarp_pln = sizeof(ea->aarp_spu); 210 ea->aarp_op = htons(AARPOP_REQUEST); 211 bcopy(IF_LLADDR(ifp), (caddr_t)ea->aarp_sha, sizeof(ea->aarp_sha)); 212 213 /* 214 * We need to check whether the output ethernet type should be phase 215 * 1 or 2. We have the interface that we'll be sending the aarp out. 216 * We need to find an AppleTalk network on that interface with the 217 * same address as we're looking for. If the net is phase 2, 218 * generate an 802.2 and SNAP header. 219 */
|
204 AT_IFADDR_RLOCK();
205 if ((aa = at_ifawithnet(sat)) == NULL) {
206 AT_IFADDR_RUNLOCK();
|
220 aa = at_ifawithnet(sat); 221 if (aa == NULL) { |
222 m_freem(m); 223 return; 224 } 225 226 eh = (struct ether_header *)sa.sa_data; 227 228 if (aa->aa_flags & AFA_PHASE2) { 229 bcopy(atmulticastaddr, eh->ether_dhost, 230 sizeof(eh->ether_dhost)); 231 eh->ether_type = htons(sizeof(struct llc) + 232 sizeof(struct ether_aarp)); 233 M_PREPEND(m, sizeof(struct llc), M_DONTWAIT); 234 if (m == NULL) {
|
220 AT_IFADDR_RUNLOCK();
|
235 ifa_free(&aa->aa_ifa); |
236 return; 237 } 238 llc = mtod(m, struct llc *); 239 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP; 240 llc->llc_control = LLC_UI; 241 bcopy(aarp_org_code, llc->llc_org_code, 242 sizeof(aarp_org_code)); 243 llc->llc_ether_type = htons(ETHERTYPE_AARP); 244 bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_spnet, 245 sizeof(ea->aarp_spnet)); 246 bcopy(&sat->sat_addr.s_net, ea->aarp_tpnet, 247 sizeof(ea->aarp_tpnet)); 248 ea->aarp_spnode = AA_SAT(aa)->sat_addr.s_node; 249 ea->aarp_tpnode = sat->sat_addr.s_node; 250 } else { 251 bcopy(ifp->if_broadcastaddr, (caddr_t)eh->ether_dhost, 252 sizeof(eh->ether_dhost)); 253 eh->ether_type = htons(ETHERTYPE_AARP); 254 ea->aarp_spa = AA_SAT(aa)->sat_addr.s_node; 255 ea->aarp_tpa = sat->sat_addr.s_node; 256 } 257 258#ifdef NETATALKDEBUG 259 printf("aarp: sending request for %u.%u\n", 260 ntohs(AA_SAT(aa)->sat_addr.s_net), AA_SAT(aa)->sat_addr.s_node); 261#endif /* NETATALKDEBUG */
|
247 AT_IFADDR_RUNLOCK();
|
262 ifa_free(&aa->aa_ifa); |
263 264 sa.sa_len = sizeof(struct sockaddr); 265 sa.sa_family = AF_UNSPEC; 266 ifp->if_output(ifp, m, &sa, NULL); 267} 268 269int 270aarpresolve(struct ifnet *ifp, struct mbuf *m, struct sockaddr_at *destsat, 271 u_char *desten) 272{ 273 struct at_ifaddr *aa; 274 struct aarptab *aat; 275 276 AT_IFADDR_RLOCK(); 277 if (at_broadcast(destsat)) { 278 m->m_flags |= M_BCAST;
|
264 if ((aa = at_ifawithnet(destsat)) == NULL) {
|
279 if ((aa = at_ifawithnet_locked(destsat)) == NULL) { |
280 AT_IFADDR_RUNLOCK(); 281 m_freem(m); 282 return (0); 283 } 284 if (aa->aa_flags & AFA_PHASE2) 285 bcopy(atmulticastaddr, (caddr_t)desten, 286 sizeof(atmulticastaddr)); 287 else 288 bcopy(ifp->if_broadcastaddr, (caddr_t)desten, 289 sizeof(ifp->if_addrlen)); 290 AT_IFADDR_RUNLOCK(); 291 return (1); 292 } 293 AT_IFADDR_RUNLOCK(); 294 295 AARPTAB_LOCK(); 296 AARPTAB_LOOK(aat, destsat->sat_addr); 297 if (aat == NULL) { 298 /* No entry. */ 299 aat = aarptnew(&destsat->sat_addr); 300 301 /* We should fail more gracefully. */ 302 if (aat == NULL) 303 panic("aarpresolve: no free entry"); 304 goto done; 305 } 306 307 /* Found an entry. */ 308 aat->aat_timer = 0; 309 if (aat->aat_flags & ATF_COM) { 310 /* Entry is COMplete. */ 311 bcopy((caddr_t)aat->aat_enaddr, (caddr_t)desten, 312 sizeof(aat->aat_enaddr)); 313 AARPTAB_UNLOCK(); 314 return (1); 315 } 316 317 /* Entry has not completed. */ 318 if (aat->aat_hold) 319 m_freem(aat->aat_hold); 320done: 321 aat->aat_hold = m; 322 AARPTAB_UNLOCK(); 323 aarpwhohas(ifp, destsat); 324 return (0); 325} 326 327void 328aarpintr(struct mbuf *m) 329{ 330 struct arphdr *ar; 331 struct ifnet *ifp; 332 333 ifp = m->m_pkthdr.rcvif; 334 if (ifp->if_flags & IFF_NOARP) 335 goto out; 336 337 if (m->m_len < sizeof(struct arphdr)) 338 goto out; 339 340 ar = mtod(m, struct arphdr *); 341 if (ntohs(ar->ar_hrd) != AARPHRD_ETHER) 342 goto out; 343 344 if (m->m_len < sizeof(struct arphdr) + 2 * ar->ar_hln + 345 2 * ar->ar_pln) 346 goto out; 347 348 switch(ntohs(ar->ar_pro)) { 349 case ETHERTYPE_AT: 350 at_aarpinput(ifp, m); 351 return; 352 default: 353 break; 354 } 355 356out: 357 m_freem(m); 358} 359 360static void 361at_aarpinput(struct ifnet *ifp, struct mbuf *m) 362{ 363 struct ether_aarp *ea; 364 struct at_ifaddr *aa; 365 struct aarptab *aat; 366 struct ether_header *eh; 367 struct llc *llc; 368 struct sockaddr_at sat; 369 struct sockaddr sa; 370 struct at_addr spa, tpa, ma; 371 int op; 372 u_short net; 373 374 ea = mtod(m, struct ether_aarp *); 375 376 /* Check to see if from my hardware address. */ 377 if (!bcmp((caddr_t)ea->aarp_sha, IF_LLADDR(ifp), ETHER_ADDR_LEN)) { 378 m_freem(m); 379 return; 380 } 381 382 /* Don't accept requests from broadcast address. */ 383 if (!bcmp(ea->aarp_sha, ifp->if_broadcastaddr, ifp->if_addrlen)) { 384 log(LOG_ERR, "aarp: source link address is broadcast\n"); 385 m_freem(m); 386 return; 387 } 388 389 op = ntohs(ea->aarp_op); 390 bcopy(ea->aarp_tpnet, &net, sizeof(net)); 391 392 if (net != 0) { 393 /* Should be ATADDR_ANYNET? */ 394 sat.sat_len = sizeof(struct sockaddr_at); 395 sat.sat_family = AF_APPLETALK; 396 sat.sat_addr.s_net = net;
|
382 AT_IFADDR_RLOCK();
383 if ((aa = at_ifawithnet(&sat)) == NULL) {
384 AT_IFADDR_RUNLOCK();
|
397 aa = at_ifawithnet(&sat); 398 if (aa == NULL) { |
399 m_freem(m); 400 return; 401 }
|
388 ifa_ref(&aa->aa_ifa);
389 AT_IFADDR_RUNLOCK();
|
402 bcopy(ea->aarp_spnet, &spa.s_net, sizeof(spa.s_net)); 403 bcopy(ea->aarp_tpnet, &tpa.s_net, sizeof(tpa.s_net)); 404 } else { 405 /* 406 * Since we don't know the net, we just look for the first 407 * phase 1 address on the interface. 408 */ 409 IF_ADDR_LOCK(ifp); 410 for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead); 411 aa; 412 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) { 413 if (AA_SAT(aa)->sat_family == AF_APPLETALK && 414 (aa->aa_flags & AFA_PHASE2) == 0) { 415 break; 416 } 417 } 418 if (aa == NULL) { 419 IF_ADDR_UNLOCK(ifp); 420 m_freem(m); 421 return; 422 } 423 ifa_ref(&aa->aa_ifa); 424 IF_ADDR_UNLOCK(ifp); 425 tpa.s_net = spa.s_net = AA_SAT(aa)->sat_addr.s_net; 426 } 427 428 spa.s_node = ea->aarp_spnode; 429 tpa.s_node = ea->aarp_tpnode; 430 ma.s_net = AA_SAT(aa)->sat_addr.s_net; 431 ma.s_node = AA_SAT(aa)->sat_addr.s_node; 432 433 /* 434 * This looks like it's from us. 435 */ 436 if (spa.s_net == ma.s_net && spa.s_node == ma.s_node) { 437 if (aa->aa_flags & AFA_PROBING) { 438 /* 439 * We're probing, someone either responded to our 440 * probe, or probed for the same address we'd like to 441 * use. Change the address we're probing for. 442 */ 443 callout_stop(&aa->aa_callout); 444 wakeup(aa); 445 ifa_free(&aa->aa_ifa); 446 m_freem(m); 447 return; 448 } else if (op != AARPOP_PROBE) { 449 /* 450 * This is not a probe, and we're not probing. This 451 * means that someone's saying they have the same 452 * source address as the one we're using. Get upset. 453 */ 454 ifa_free(&aa->aa_ifa); 455 log(LOG_ERR, 456 "aarp: duplicate AT address!! %x:%x:%x:%x:%x:%x\n", 457 ea->aarp_sha[0], ea->aarp_sha[1], 458 ea->aarp_sha[2], ea->aarp_sha[3], 459 ea->aarp_sha[4], ea->aarp_sha[5]); 460 m_freem(m); 461 return; 462 } 463 } 464 465 AARPTAB_LOCK(); 466 AARPTAB_LOOK(aat, spa); 467 if (aat != NULL) { 468 if (op == AARPOP_PROBE) { 469 /* 470 * Someone's probing for spa, dealocate the one we've 471 * got, so that if the prober keeps the address, 472 * we'll be able to arp for him. 473 */ 474 aarptfree(aat); 475 AARPTAB_UNLOCK(); 476 ifa_free(&aa->aa_ifa); 477 m_freem(m); 478 return; 479 } 480 481 bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr, 482 sizeof(ea->aarp_sha)); 483 aat->aat_flags |= ATF_COM; 484 if (aat->aat_hold) { 485 struct mbuf *mhold = aat->aat_hold; 486 aat->aat_hold = NULL; 487 AARPTAB_UNLOCK(); 488 sat.sat_len = sizeof(struct sockaddr_at); 489 sat.sat_family = AF_APPLETALK; 490 sat.sat_addr = spa; 491 (*ifp->if_output)(ifp, mhold, 492 (struct sockaddr *)&sat, NULL); /* XXX */ 493 } else 494 AARPTAB_UNLOCK(); 495 } else if ((tpa.s_net == ma.s_net) && (tpa.s_node == ma.s_node) 496 && (op != AARPOP_PROBE) && ((aat = aarptnew(&spa)) != NULL)) { 497 bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr, 498 sizeof(ea->aarp_sha)); 499 aat->aat_flags |= ATF_COM; 500 AARPTAB_UNLOCK(); 501 } else 502 AARPTAB_UNLOCK(); 503 504 /* 505 * Don't respond to responses, and never respond if we're still 506 * probing. 507 */ 508 if (tpa.s_net != ma.s_net || tpa.s_node != ma.s_node || 509 op == AARPOP_RESPONSE || (aa->aa_flags & AFA_PROBING)) { 510 ifa_free(&aa->aa_ifa); 511 m_freem(m); 512 return; 513 } 514 515 bcopy((caddr_t)ea->aarp_sha, (caddr_t)ea->aarp_tha, 516 sizeof(ea->aarp_sha)); 517 bcopy(IF_LLADDR(ifp), (caddr_t)ea->aarp_sha, sizeof(ea->aarp_sha)); 518 519 /* XXX */ 520 eh = (struct ether_header *)sa.sa_data; 521 bcopy((caddr_t)ea->aarp_tha, (caddr_t)eh->ether_dhost, 522 sizeof(eh->ether_dhost)); 523 524 if (aa->aa_flags & AFA_PHASE2) { 525 eh->ether_type = htons(sizeof(struct llc) + 526 sizeof(struct ether_aarp)); 527 M_PREPEND(m, sizeof(struct llc), M_DONTWAIT); 528 if (m == NULL) { 529 ifa_free(&aa->aa_ifa); 530 return; 531 } 532 llc = mtod(m, struct llc *); 533 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP; 534 llc->llc_control = LLC_UI; 535 bcopy(aarp_org_code, llc->llc_org_code, 536 sizeof(aarp_org_code)); 537 llc->llc_ether_type = htons(ETHERTYPE_AARP); 538 539 bcopy(ea->aarp_spnet, ea->aarp_tpnet, 540 sizeof(ea->aarp_tpnet)); 541 bcopy(&ma.s_net, ea->aarp_spnet, sizeof(ea->aarp_spnet)); 542 } else 543 eh->ether_type = htons(ETHERTYPE_AARP); 544 ifa_free(&aa->aa_ifa); 545 546 ea->aarp_tpnode = ea->aarp_spnode; 547 ea->aarp_spnode = ma.s_node; 548 ea->aarp_op = htons(AARPOP_RESPONSE); 549 550 sa.sa_len = sizeof(struct sockaddr); 551 sa.sa_family = AF_UNSPEC; 552 (*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */ 553 return; 554} 555 556static void 557aarptfree(struct aarptab *aat) 558{ 559 560 AARPTAB_LOCK_ASSERT(); 561 if (aat->aat_hold) 562 m_freem(aat->aat_hold); 563 aat->aat_hold = NULL; 564 aat->aat_timer = aat->aat_flags = 0; 565 aat->aat_ataddr.s_net = 0; 566 aat->aat_ataddr.s_node = 0; 567} 568 569struct aarptab * 570aarptnew(struct at_addr *addr) 571{ 572 int n; 573 int oldest = -1; 574 struct aarptab *aat, *aato = NULL; 575 static int first = 1; 576 577 AARPTAB_LOCK_ASSERT(); 578 if (first) { 579 first = 0; 580 aarptimer_ch = timeout(aarptimer, (caddr_t)0, hz); 581 } 582 aat = &aarptab[AARPTAB_HASH(*addr) * AARPTAB_BSIZ]; 583 for (n = 0; n < AARPTAB_BSIZ; n++, aat++) { 584 if (aat->aat_flags == 0) 585 goto out; 586 if (aat->aat_flags & ATF_PERM) 587 continue; 588 if ((int) aat->aat_timer > oldest) { 589 oldest = aat->aat_timer; 590 aato = aat; 591 } 592 } 593 if (aato == NULL) 594 return (NULL); 595 aat = aato; 596 aarptfree(aat); 597out: 598 aat->aat_ataddr = *addr; 599 aat->aat_flags = ATF_INUSE; 600 return (aat); 601} 602 603 604void 605aarpprobe(void *arg) 606{ 607 struct ifnet *ifp = arg; 608 struct mbuf *m; 609 struct ether_header *eh; 610 struct ether_aarp *ea; 611 struct at_ifaddr *aa; 612 struct llc *llc; 613 struct sockaddr sa; 614 615 /* 616 * We need to check whether the output ethernet type should be phase 617 * 1 or 2. We have the interface that we'll be sending the aarp out. 618 * We need to find an AppleTalk network on that interface with the 619 * same address as we're looking for. If the net is phase 2, 620 * generate an 802.2 and SNAP header. 621 */ 622 AARPTAB_LOCK(); 623 for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead); aa; 624 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) { 625 if (AA_SAT(aa)->sat_family == AF_APPLETALK && 626 (aa->aa_flags & AFA_PROBING)) 627 break; 628 } 629 if (aa == NULL) { 630 /* Serious error XXX. */ 631 AARPTAB_UNLOCK(); 632 printf("aarpprobe why did this happen?!\n"); 633 return; 634 } 635 636 if (aa->aa_probcnt <= 0) { 637 aa->aa_flags &= ~AFA_PROBING; 638 wakeup(aa); 639 AARPTAB_UNLOCK(); 640 return; 641 } else 642 callout_reset(&aa->aa_callout, hz / 5, aarpprobe, ifp); 643 ifa_ref(&aa->aa_ifa); 644 AARPTAB_UNLOCK(); 645 646 m = m_gethdr(M_DONTWAIT, MT_DATA); 647 if (m == NULL) { 648 ifa_free(&aa->aa_ifa); 649 return; 650 } 651#ifdef MAC 652 mac_netatalk_aarp_send(ifp, m); 653#endif 654 m->m_len = sizeof(*ea); 655 m->m_pkthdr.len = sizeof(*ea); 656 MH_ALIGN(m, sizeof(*ea)); 657 658 ea = mtod(m, struct ether_aarp *); 659 bzero((caddr_t)ea, sizeof(*ea)); 660 661 ea->aarp_hrd = htons(AARPHRD_ETHER); 662 ea->aarp_pro = htons(ETHERTYPE_AT); 663 ea->aarp_hln = sizeof(ea->aarp_sha); 664 ea->aarp_pln = sizeof(ea->aarp_spu); 665 ea->aarp_op = htons(AARPOP_PROBE); 666 bcopy(IF_LLADDR(ifp), (caddr_t)ea->aarp_sha, 667 sizeof(ea->aarp_sha)); 668 669 eh = (struct ether_header *)sa.sa_data; 670 671 if (aa->aa_flags & AFA_PHASE2) { 672 bcopy(atmulticastaddr, eh->ether_dhost, 673 sizeof(eh->ether_dhost)); 674 eh->ether_type = htons(sizeof(struct llc) + 675 sizeof(struct ether_aarp)); 676 M_PREPEND(m, sizeof(struct llc), M_WAIT); 677 llc = mtod(m, struct llc *); 678 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP; 679 llc->llc_control = LLC_UI; 680 bcopy(aarp_org_code, llc->llc_org_code, 681 sizeof(aarp_org_code)); 682 llc->llc_ether_type = htons(ETHERTYPE_AARP); 683 684 bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_spnet, 685 sizeof(ea->aarp_spnet)); 686 bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_tpnet, 687 sizeof(ea->aarp_tpnet)); 688 ea->aarp_spnode = ea->aarp_tpnode = 689 AA_SAT(aa)->sat_addr.s_node; 690 } else { 691 bcopy(ifp->if_broadcastaddr, (caddr_t)eh->ether_dhost, 692 sizeof(eh->ether_dhost)); 693 eh->ether_type = htons(ETHERTYPE_AARP); 694 ea->aarp_spa = ea->aarp_tpa = AA_SAT(aa)->sat_addr.s_node; 695 } 696 697#ifdef NETATALKDEBUG 698 printf("aarp: sending probe for %u.%u\n", 699 ntohs(AA_SAT(aa)->sat_addr.s_net), AA_SAT(aa)->sat_addr.s_node); 700#endif /* NETATALKDEBUG */ 701 ifa_free(&aa->aa_ifa); 702 703 sa.sa_len = sizeof(struct sockaddr); 704 sa.sa_family = AF_UNSPEC; 705 (*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */ 706 aa->aa_probcnt--; 707} 708 709void 710aarp_clean(void) 711{ 712 struct aarptab *aat; 713 int i; 714 715 untimeout(aarptimer, 0, aarptimer_ch); 716 AARPTAB_LOCK(); 717 for (i = 0, aat = aarptab; i < AARPTAB_SIZE; i++, aat++) { 718 if (aat->aat_hold) { 719 m_freem(aat->aat_hold); 720 aat->aat_hold = NULL; 721 } 722 } 723 AARPTAB_UNLOCK(); 724}
|