1/*- 2 * Copyright (c) 2004-2005 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 *
| 1/*- 2 * Copyright (c) 2004-2005 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 *
|
51 */ 52 53#include "opt_atalk.h" 54#include "opt_mac.h" 55 56#include <sys/param.h> 57#include <sys/systm.h> 58#include <sys/mbuf.h> 59#include <sys/kernel.h> 60#include <sys/socket.h> 61#include <sys/syslog.h> 62 63#include <net/if.h> 64#include <net/if_dl.h> 65 66#include <netinet/in.h> 67#undef s_net 68#include <netinet/if_ether.h> 69 70#include <netatalk/at.h> 71#include <netatalk/at_var.h> 72#include <netatalk/aarp.h> 73#include <netatalk/phase2.h> 74#include <netatalk/at_extern.h> 75 76#include <security/mac/mac_framework.h> 77 78static void aarptfree(struct aarptab *aat); 79static void at_aarpinput(struct ifnet *ifp, struct mbuf *m); 80 81#define AARPTAB_BSIZ 9 82#define AARPTAB_NB 19 83#define AARPTAB_SIZE (AARPTAB_BSIZ * AARPTAB_NB) 84static struct aarptab aarptab[AARPTAB_SIZE]; 85 86struct mtx aarptab_mtx; 87MTX_SYSINIT(aarptab_mtx, &aarptab_mtx, "aarptab_mtx", MTX_DEF); 88 89#define AARPTAB_HASH(a) ((((a).s_net << 8) + (a).s_node) % AARPTAB_NB) 90 91#define AARPTAB_LOOK(aat, addr) do { \ 92 int n; \ 93 \ 94 AARPTAB_LOCK_ASSERT(); \ 95 aat = &aarptab[ AARPTAB_HASH(addr) * AARPTAB_BSIZ ]; \ 96 for (n = 0; n < AARPTAB_BSIZ; n++, aat++) { \ 97 if (aat->aat_ataddr.s_net == (addr).s_net && \ 98 aat->aat_ataddr.s_node == (addr).s_node) \ 99 break; \ 100 } \ 101 if (n >= AARPTAB_BSIZ) \ 102 aat = NULL; \ 103} while (0) 104 105#define AARPT_AGE (60 * 1) 106#define AARPT_KILLC 20 107#define AARPT_KILLI 3 108 109static const u_char atmulticastaddr[6] = { 110 0x09, 0x00, 0x07, 0xff, 0xff, 0xff, 111}; 112 113u_char at_org_code[3] = { 114 0x08, 0x00, 0x07, 115}; 116const u_char aarp_org_code[3] = { 117 0x00, 0x00, 0x00, 118}; 119 120static struct callout_handle aarptimer_ch = 121 CALLOUT_HANDLE_INITIALIZER(&aarptimer_ch); 122 123static void 124aarptimer(void *ignored) 125{ 126 struct aarptab *aat; 127 int i; 128 129 aarptimer_ch = timeout(aarptimer, NULL, AARPT_AGE * hz); 130 aat = aarptab; 131 AARPTAB_LOCK(); 132 for (i = 0; i < AARPTAB_SIZE; i++, aat++) { 133 if (aat->aat_flags == 0 || (aat->aat_flags & ATF_PERM)) 134 continue; 135 if (++aat->aat_timer < ((aat->aat_flags & ATF_COM) ? 136 AARPT_KILLC : AARPT_KILLI)) 137 continue; 138 aarptfree(aat); 139 } 140 AARPTAB_UNLOCK(); 141} 142 143/* 144 * Search through the network addresses to find one that includes the given 145 * network. Remember to take netranges into consideration. 146 */ 147struct at_ifaddr * 148at_ifawithnet(struct sockaddr_at *sat) 149{ 150 struct at_ifaddr *aa; 151 struct sockaddr_at *sat2; 152 153 for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) { 154 sat2 = &(aa->aa_addr); 155 if (sat2->sat_addr.s_net == sat->sat_addr.s_net) 156 break; 157 if ((aa->aa_flags & AFA_PHASE2) && 158 (ntohs(aa->aa_firstnet) <= ntohs(sat->sat_addr.s_net)) && 159 (ntohs(aa->aa_lastnet) >= ntohs(sat->sat_addr.s_net))) 160 break; 161 } 162 return (aa); 163} 164 165static void 166aarpwhohas(struct ifnet *ifp, struct sockaddr_at *sat) 167{ 168 struct mbuf *m; 169 struct ether_header *eh; 170 struct ether_aarp *ea; 171 struct at_ifaddr *aa; 172 struct llc *llc; 173 struct sockaddr sa; 174 175 AARPTAB_UNLOCK_ASSERT(); 176 m = m_gethdr(M_DONTWAIT, MT_DATA); 177 if (m == NULL) 178 return; 179#ifdef MAC 180 mac_netatalk_aarp_send(ifp, m); 181#endif 182 m->m_len = sizeof(*ea); 183 m->m_pkthdr.len = sizeof(*ea); 184 MH_ALIGN(m, sizeof(*ea)); 185 186 ea = mtod(m, struct ether_aarp *); 187 bzero((caddr_t)ea, sizeof(*ea)); 188 189 ea->aarp_hrd = htons(AARPHRD_ETHER); 190 ea->aarp_pro = htons(ETHERTYPE_AT); 191 ea->aarp_hln = sizeof(ea->aarp_sha); 192 ea->aarp_pln = sizeof(ea->aarp_spu); 193 ea->aarp_op = htons(AARPOP_REQUEST); 194 bcopy(IF_LLADDR(ifp), (caddr_t)ea->aarp_sha, sizeof(ea->aarp_sha)); 195 196 /* 197 * We need to check whether the output ethernet type should be phase 198 * 1 or 2. We have the interface that we'll be sending the aarp out. 199 * We need to find an AppleTalk network on that interface with the 200 * same address as we're looking for. If the net is phase 2, 201 * generate an 802.2 and SNAP header. 202 */ 203 if ((aa = at_ifawithnet(sat)) == NULL) { 204 m_freem(m); 205 return; 206 } 207 208 eh = (struct ether_header *)sa.sa_data; 209 210 if (aa->aa_flags & AFA_PHASE2) { 211 bcopy(atmulticastaddr, eh->ether_dhost, 212 sizeof(eh->ether_dhost)); 213 eh->ether_type = htons(sizeof(struct llc) + 214 sizeof(struct ether_aarp)); 215 M_PREPEND(m, sizeof(struct llc), M_DONTWAIT); 216 if (m == NULL) 217 return; 218 llc = mtod(m, struct llc *); 219 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP; 220 llc->llc_control = LLC_UI; 221 bcopy(aarp_org_code, llc->llc_org_code, 222 sizeof(aarp_org_code)); 223 llc->llc_ether_type = htons(ETHERTYPE_AARP); 224 bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_spnet, 225 sizeof(ea->aarp_spnet)); 226 bcopy(&sat->sat_addr.s_net, ea->aarp_tpnet, 227 sizeof(ea->aarp_tpnet)); 228 ea->aarp_spnode = AA_SAT(aa)->sat_addr.s_node; 229 ea->aarp_tpnode = sat->sat_addr.s_node; 230 } else { 231 bcopy(ifp->if_broadcastaddr, (caddr_t)eh->ether_dhost, 232 sizeof(eh->ether_dhost)); 233 eh->ether_type = htons(ETHERTYPE_AARP); 234 ea->aarp_spa = AA_SAT(aa)->sat_addr.s_node; 235 ea->aarp_tpa = sat->sat_addr.s_node; 236 } 237 238#ifdef NETATALKDEBUG 239 printf("aarp: sending request for %u.%u\n", 240 ntohs(AA_SAT(aa)->sat_addr.s_net), AA_SAT(aa)->sat_addr.s_node); 241#endif /* NETATALKDEBUG */ 242 243 sa.sa_len = sizeof(struct sockaddr); 244 sa.sa_family = AF_UNSPEC; 245 ifp->if_output(ifp, m, &sa, NULL); 246} 247 248int 249aarpresolve(struct ifnet *ifp, struct mbuf *m, struct sockaddr_at *destsat, 250 u_char *desten) 251{ 252 struct at_ifaddr *aa; 253 struct aarptab *aat; 254 255 if (at_broadcast(destsat)) { 256 m->m_flags |= M_BCAST; 257 if ((aa = at_ifawithnet(destsat)) == NULL) { 258 m_freem(m); 259 return (0); 260 } 261 if (aa->aa_flags & AFA_PHASE2) 262 bcopy(atmulticastaddr, (caddr_t)desten, 263 sizeof(atmulticastaddr)); 264 else 265 bcopy(ifp->if_broadcastaddr, (caddr_t)desten, 266 sizeof(ifp->if_addrlen)); 267 return (1); 268 } 269 270 AARPTAB_LOCK(); 271 AARPTAB_LOOK(aat, destsat->sat_addr); 272 if (aat == NULL) { 273 /* No entry. */ 274 aat = aarptnew(&destsat->sat_addr); 275 276 /* We should fail more gracefully. */ 277 if (aat == NULL) 278 panic("aarpresolve: no free entry"); 279 goto done; 280 } 281 282 /* Found an entry. */ 283 aat->aat_timer = 0; 284 if (aat->aat_flags & ATF_COM) { 285 /* Entry is COMplete. */ 286 bcopy((caddr_t)aat->aat_enaddr, (caddr_t)desten, 287 sizeof(aat->aat_enaddr)); 288 AARPTAB_UNLOCK(); 289 return (1); 290 } 291 292 /* Entry has not completed. */ 293 if (aat->aat_hold) 294 m_freem(aat->aat_hold); 295done: 296 aat->aat_hold = m; 297 AARPTAB_UNLOCK(); 298 aarpwhohas(ifp, destsat); 299 return (0); 300} 301 302void 303aarpintr(struct mbuf *m) 304{ 305 struct arphdr *ar; 306 struct ifnet *ifp; 307 308 ifp = m->m_pkthdr.rcvif; 309 if (ifp->if_flags & IFF_NOARP) 310 goto out; 311 312 if (m->m_len < sizeof(struct arphdr)) 313 goto out; 314 315 ar = mtod(m, struct arphdr *); 316 if (ntohs(ar->ar_hrd) != AARPHRD_ETHER) 317 goto out; 318 319 if (m->m_len < sizeof(struct arphdr) + 2 * ar->ar_hln + 320 2 * ar->ar_pln) 321 goto out; 322 323 switch(ntohs(ar->ar_pro)) { 324 case ETHERTYPE_AT: 325 at_aarpinput(ifp, m); 326 return; 327 default: 328 break; 329 } 330 331out: 332 m_freem(m); 333} 334 335static void 336at_aarpinput(struct ifnet *ifp, struct mbuf *m) 337{ 338 struct ether_aarp *ea; 339 struct at_ifaddr *aa; 340 struct aarptab *aat; 341 struct ether_header *eh; 342 struct llc *llc; 343 struct sockaddr_at sat; 344 struct sockaddr sa; 345 struct at_addr spa, tpa, ma; 346 int op; 347 u_short net; 348 349 ea = mtod(m, struct ether_aarp *); 350 351 /* Check to see if from my hardware address. */ 352 if (!bcmp((caddr_t)ea->aarp_sha, IF_LLADDR(ifp), ETHER_ADDR_LEN)) { 353 m_freem(m); 354 return; 355 } 356 357 /* Don't accept requests from broadcast address. */ 358 if (!bcmp(ea->aarp_sha, ifp->if_broadcastaddr, ifp->if_addrlen)) { 359 log(LOG_ERR, "aarp: source link address is broadcast\n"); 360 m_freem(m); 361 return; 362 } 363 364 op = ntohs(ea->aarp_op); 365 bcopy(ea->aarp_tpnet, &net, sizeof(net)); 366 367 if (net != 0) { 368 /* Should be ATADDR_ANYNET? */ 369 sat.sat_len = sizeof(struct sockaddr_at); 370 sat.sat_family = AF_APPLETALK; 371 sat.sat_addr.s_net = net; 372 if ((aa = at_ifawithnet(&sat)) == NULL) { 373 m_freem(m); 374 return; 375 } 376 bcopy(ea->aarp_spnet, &spa.s_net, sizeof(spa.s_net)); 377 bcopy(ea->aarp_tpnet, &tpa.s_net, sizeof(tpa.s_net)); 378 } else { 379 /* 380 * Since we don't know the net, we just look for the first 381 * phase 1 address on the interface. 382 */ 383 for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead); 384 aa; 385 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) { 386 if (AA_SAT(aa)->sat_family == AF_APPLETALK && 387 (aa->aa_flags & AFA_PHASE2) == 0) { 388 break; 389 } 390 } 391 if (aa == NULL) { 392 m_freem(m); 393 return; 394 } 395 tpa.s_net = spa.s_net = AA_SAT(aa)->sat_addr.s_net; 396 } 397 398 spa.s_node = ea->aarp_spnode; 399 tpa.s_node = ea->aarp_tpnode; 400 ma.s_net = AA_SAT(aa)->sat_addr.s_net; 401 ma.s_node = AA_SAT(aa)->sat_addr.s_node; 402 403 /* 404 * This looks like it's from us. 405 */ 406 if (spa.s_net == ma.s_net && spa.s_node == ma.s_node) { 407 if (aa->aa_flags & AFA_PROBING) { 408 /* 409 * We're probing, someone either responded to our 410 * probe, or probed for the same address we'd like to 411 * use. Change the address we're probing for. 412 */ 413 callout_stop(&aa->aa_callout); 414 wakeup(aa); 415 m_freem(m); 416 return; 417 } else if (op != AARPOP_PROBE) { 418 /* 419 * This is not a probe, and we're not probing. This 420 * means that someone's saying they have the same 421 * source address as the one we're using. Get upset. 422 */ 423 log(LOG_ERR, 424 "aarp: duplicate AT address!! %x:%x:%x:%x:%x:%x\n", 425 ea->aarp_sha[0], ea->aarp_sha[1], 426 ea->aarp_sha[2], ea->aarp_sha[3], 427 ea->aarp_sha[4], ea->aarp_sha[5]); 428 m_freem(m); 429 return; 430 } 431 } 432 433 AARPTAB_LOCK(); 434 AARPTAB_LOOK(aat, spa); 435 if (aat != NULL) { 436 if (op == AARPOP_PROBE) { 437 /* 438 * Someone's probing for spa, dealocate the one we've 439 * got, so that if the prober keeps the address, 440 * we'll be able to arp for him. 441 */ 442 aarptfree(aat); 443 AARPTAB_UNLOCK(); 444 m_freem(m); 445 return; 446 } 447 448 bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr, 449 sizeof(ea->aarp_sha)); 450 aat->aat_flags |= ATF_COM; 451 if (aat->aat_hold) { 452 struct mbuf *mhold = aat->aat_hold; 453 aat->aat_hold = NULL; 454 AARPTAB_UNLOCK(); 455 sat.sat_len = sizeof(struct sockaddr_at); 456 sat.sat_family = AF_APPLETALK; 457 sat.sat_addr = spa; 458 (*ifp->if_output)(ifp, mhold, 459 (struct sockaddr *)&sat, NULL); /* XXX */ 460 } else 461 AARPTAB_UNLOCK(); 462 } else if ((tpa.s_net == ma.s_net) && (tpa.s_node == ma.s_node) 463 && (op != AARPOP_PROBE) && ((aat = aarptnew(&spa)) != NULL)) { 464 bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr, 465 sizeof(ea->aarp_sha)); 466 aat->aat_flags |= ATF_COM; 467 AARPTAB_UNLOCK(); 468 } else 469 AARPTAB_UNLOCK(); 470 471 /* 472 * Don't respond to responses, and never respond if we're still 473 * probing. 474 */ 475 if (tpa.s_net != ma.s_net || tpa.s_node != ma.s_node || 476 op == AARPOP_RESPONSE || (aa->aa_flags & AFA_PROBING)) { 477 m_freem(m); 478 return; 479 } 480 481 bcopy((caddr_t)ea->aarp_sha, (caddr_t)ea->aarp_tha, 482 sizeof(ea->aarp_sha)); 483 bcopy(IF_LLADDR(ifp), (caddr_t)ea->aarp_sha, sizeof(ea->aarp_sha)); 484 485 /* XXX */ 486 eh = (struct ether_header *)sa.sa_data; 487 bcopy((caddr_t)ea->aarp_tha, (caddr_t)eh->ether_dhost, 488 sizeof(eh->ether_dhost)); 489 490 if (aa->aa_flags & AFA_PHASE2) { 491 eh->ether_type = htons(sizeof(struct llc) + 492 sizeof(struct ether_aarp)); 493 M_PREPEND(m, sizeof(struct llc), M_DONTWAIT); 494 if (m == NULL) 495 return; 496 llc = mtod(m, struct llc *); 497 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP; 498 llc->llc_control = LLC_UI; 499 bcopy(aarp_org_code, llc->llc_org_code, 500 sizeof(aarp_org_code)); 501 llc->llc_ether_type = htons(ETHERTYPE_AARP); 502 503 bcopy(ea->aarp_spnet, ea->aarp_tpnet, 504 sizeof(ea->aarp_tpnet)); 505 bcopy(&ma.s_net, ea->aarp_spnet, sizeof(ea->aarp_spnet)); 506 } else 507 eh->ether_type = htons(ETHERTYPE_AARP); 508 509 ea->aarp_tpnode = ea->aarp_spnode; 510 ea->aarp_spnode = ma.s_node; 511 ea->aarp_op = htons(AARPOP_RESPONSE); 512 513 sa.sa_len = sizeof(struct sockaddr); 514 sa.sa_family = AF_UNSPEC; 515 (*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */ 516 return; 517} 518 519static void 520aarptfree(struct aarptab *aat) 521{ 522 523 AARPTAB_LOCK_ASSERT(); 524 if (aat->aat_hold) 525 m_freem(aat->aat_hold); 526 aat->aat_hold = NULL; 527 aat->aat_timer = aat->aat_flags = 0; 528 aat->aat_ataddr.s_net = 0; 529 aat->aat_ataddr.s_node = 0; 530} 531 532struct aarptab * 533aarptnew(struct at_addr *addr) 534{ 535 int n; 536 int oldest = -1; 537 struct aarptab *aat, *aato = NULL; 538 static int first = 1; 539 540 AARPTAB_LOCK_ASSERT(); 541 if (first) { 542 first = 0; 543 aarptimer_ch = timeout(aarptimer, (caddr_t)0, hz); 544 } 545 aat = &aarptab[AARPTAB_HASH(*addr) * AARPTAB_BSIZ]; 546 for (n = 0; n < AARPTAB_BSIZ; n++, aat++) { 547 if (aat->aat_flags == 0) 548 goto out; 549 if (aat->aat_flags & ATF_PERM) 550 continue; 551 if ((int) aat->aat_timer > oldest) { 552 oldest = aat->aat_timer; 553 aato = aat; 554 } 555 } 556 if (aato == NULL) 557 return (NULL); 558 aat = aato; 559 aarptfree(aat); 560out: 561 aat->aat_ataddr = *addr; 562 aat->aat_flags = ATF_INUSE; 563 return (aat); 564} 565 566 567void 568aarpprobe(void *arg) 569{ 570 struct ifnet *ifp = arg; 571 struct mbuf *m; 572 struct ether_header *eh; 573 struct ether_aarp *ea; 574 struct at_ifaddr *aa; 575 struct llc *llc; 576 struct sockaddr sa; 577 578 /* 579 * We need to check whether the output ethernet type should be phase 580 * 1 or 2. We have the interface that we'll be sending the aarp out. 581 * We need to find an AppleTalk network on that interface with the 582 * same address as we're looking for. If the net is phase 2, 583 * generate an 802.2 and SNAP header. 584 */ 585 AARPTAB_LOCK(); 586 for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead); aa; 587 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) { 588 if (AA_SAT(aa)->sat_family == AF_APPLETALK && 589 (aa->aa_flags & AFA_PROBING)) 590 break; 591 } 592 if (aa == NULL) { 593 /* Serious error XXX. */ 594 AARPTAB_UNLOCK(); 595 printf("aarpprobe why did this happen?!\n"); 596 return; 597 } 598 599 if (aa->aa_probcnt <= 0) { 600 aa->aa_flags &= ~AFA_PROBING; 601 wakeup(aa); 602 AARPTAB_UNLOCK(); 603 return; 604 } else 605 callout_reset(&aa->aa_callout, hz / 5, aarpprobe, ifp); 606 AARPTAB_UNLOCK(); 607 608 m = m_gethdr(M_DONTWAIT, MT_DATA); 609 if (m == NULL) 610 return; 611#ifdef MAC 612 mac_netatalk_aarp_send(ifp, m); 613#endif 614 m->m_len = sizeof(*ea); 615 m->m_pkthdr.len = sizeof(*ea); 616 MH_ALIGN(m, sizeof(*ea)); 617 618 ea = mtod(m, struct ether_aarp *); 619 bzero((caddr_t)ea, sizeof(*ea)); 620 621 ea->aarp_hrd = htons(AARPHRD_ETHER); 622 ea->aarp_pro = htons(ETHERTYPE_AT); 623 ea->aarp_hln = sizeof(ea->aarp_sha); 624 ea->aarp_pln = sizeof(ea->aarp_spu); 625 ea->aarp_op = htons(AARPOP_PROBE); 626 bcopy(IF_LLADDR(ifp), (caddr_t)ea->aarp_sha, 627 sizeof(ea->aarp_sha)); 628 629 eh = (struct ether_header *)sa.sa_data; 630 631 if (aa->aa_flags & AFA_PHASE2) { 632 bcopy(atmulticastaddr, eh->ether_dhost, 633 sizeof(eh->ether_dhost)); 634 eh->ether_type = htons(sizeof(struct llc) + 635 sizeof(struct ether_aarp));
| 51 */ 52 53#include "opt_atalk.h" 54#include "opt_mac.h" 55 56#include <sys/param.h> 57#include <sys/systm.h> 58#include <sys/mbuf.h> 59#include <sys/kernel.h> 60#include <sys/socket.h> 61#include <sys/syslog.h> 62 63#include <net/if.h> 64#include <net/if_dl.h> 65 66#include <netinet/in.h> 67#undef s_net 68#include <netinet/if_ether.h> 69 70#include <netatalk/at.h> 71#include <netatalk/at_var.h> 72#include <netatalk/aarp.h> 73#include <netatalk/phase2.h> 74#include <netatalk/at_extern.h> 75 76#include <security/mac/mac_framework.h> 77 78static void aarptfree(struct aarptab *aat); 79static void at_aarpinput(struct ifnet *ifp, struct mbuf *m); 80 81#define AARPTAB_BSIZ 9 82#define AARPTAB_NB 19 83#define AARPTAB_SIZE (AARPTAB_BSIZ * AARPTAB_NB) 84static struct aarptab aarptab[AARPTAB_SIZE]; 85 86struct mtx aarptab_mtx; 87MTX_SYSINIT(aarptab_mtx, &aarptab_mtx, "aarptab_mtx", MTX_DEF); 88 89#define AARPTAB_HASH(a) ((((a).s_net << 8) + (a).s_node) % AARPTAB_NB) 90 91#define AARPTAB_LOOK(aat, addr) do { \ 92 int n; \ 93 \ 94 AARPTAB_LOCK_ASSERT(); \ 95 aat = &aarptab[ AARPTAB_HASH(addr) * AARPTAB_BSIZ ]; \ 96 for (n = 0; n < AARPTAB_BSIZ; n++, aat++) { \ 97 if (aat->aat_ataddr.s_net == (addr).s_net && \ 98 aat->aat_ataddr.s_node == (addr).s_node) \ 99 break; \ 100 } \ 101 if (n >= AARPTAB_BSIZ) \ 102 aat = NULL; \ 103} while (0) 104 105#define AARPT_AGE (60 * 1) 106#define AARPT_KILLC 20 107#define AARPT_KILLI 3 108 109static const u_char atmulticastaddr[6] = { 110 0x09, 0x00, 0x07, 0xff, 0xff, 0xff, 111}; 112 113u_char at_org_code[3] = { 114 0x08, 0x00, 0x07, 115}; 116const u_char aarp_org_code[3] = { 117 0x00, 0x00, 0x00, 118}; 119 120static struct callout_handle aarptimer_ch = 121 CALLOUT_HANDLE_INITIALIZER(&aarptimer_ch); 122 123static void 124aarptimer(void *ignored) 125{ 126 struct aarptab *aat; 127 int i; 128 129 aarptimer_ch = timeout(aarptimer, NULL, AARPT_AGE * hz); 130 aat = aarptab; 131 AARPTAB_LOCK(); 132 for (i = 0; i < AARPTAB_SIZE; i++, aat++) { 133 if (aat->aat_flags == 0 || (aat->aat_flags & ATF_PERM)) 134 continue; 135 if (++aat->aat_timer < ((aat->aat_flags & ATF_COM) ? 136 AARPT_KILLC : AARPT_KILLI)) 137 continue; 138 aarptfree(aat); 139 } 140 AARPTAB_UNLOCK(); 141} 142 143/* 144 * Search through the network addresses to find one that includes the given 145 * network. Remember to take netranges into consideration. 146 */ 147struct at_ifaddr * 148at_ifawithnet(struct sockaddr_at *sat) 149{ 150 struct at_ifaddr *aa; 151 struct sockaddr_at *sat2; 152 153 for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) { 154 sat2 = &(aa->aa_addr); 155 if (sat2->sat_addr.s_net == sat->sat_addr.s_net) 156 break; 157 if ((aa->aa_flags & AFA_PHASE2) && 158 (ntohs(aa->aa_firstnet) <= ntohs(sat->sat_addr.s_net)) && 159 (ntohs(aa->aa_lastnet) >= ntohs(sat->sat_addr.s_net))) 160 break; 161 } 162 return (aa); 163} 164 165static void 166aarpwhohas(struct ifnet *ifp, struct sockaddr_at *sat) 167{ 168 struct mbuf *m; 169 struct ether_header *eh; 170 struct ether_aarp *ea; 171 struct at_ifaddr *aa; 172 struct llc *llc; 173 struct sockaddr sa; 174 175 AARPTAB_UNLOCK_ASSERT(); 176 m = m_gethdr(M_DONTWAIT, MT_DATA); 177 if (m == NULL) 178 return; 179#ifdef MAC 180 mac_netatalk_aarp_send(ifp, m); 181#endif 182 m->m_len = sizeof(*ea); 183 m->m_pkthdr.len = sizeof(*ea); 184 MH_ALIGN(m, sizeof(*ea)); 185 186 ea = mtod(m, struct ether_aarp *); 187 bzero((caddr_t)ea, sizeof(*ea)); 188 189 ea->aarp_hrd = htons(AARPHRD_ETHER); 190 ea->aarp_pro = htons(ETHERTYPE_AT); 191 ea->aarp_hln = sizeof(ea->aarp_sha); 192 ea->aarp_pln = sizeof(ea->aarp_spu); 193 ea->aarp_op = htons(AARPOP_REQUEST); 194 bcopy(IF_LLADDR(ifp), (caddr_t)ea->aarp_sha, sizeof(ea->aarp_sha)); 195 196 /* 197 * We need to check whether the output ethernet type should be phase 198 * 1 or 2. We have the interface that we'll be sending the aarp out. 199 * We need to find an AppleTalk network on that interface with the 200 * same address as we're looking for. If the net is phase 2, 201 * generate an 802.2 and SNAP header. 202 */ 203 if ((aa = at_ifawithnet(sat)) == NULL) { 204 m_freem(m); 205 return; 206 } 207 208 eh = (struct ether_header *)sa.sa_data; 209 210 if (aa->aa_flags & AFA_PHASE2) { 211 bcopy(atmulticastaddr, eh->ether_dhost, 212 sizeof(eh->ether_dhost)); 213 eh->ether_type = htons(sizeof(struct llc) + 214 sizeof(struct ether_aarp)); 215 M_PREPEND(m, sizeof(struct llc), M_DONTWAIT); 216 if (m == NULL) 217 return; 218 llc = mtod(m, struct llc *); 219 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP; 220 llc->llc_control = LLC_UI; 221 bcopy(aarp_org_code, llc->llc_org_code, 222 sizeof(aarp_org_code)); 223 llc->llc_ether_type = htons(ETHERTYPE_AARP); 224 bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_spnet, 225 sizeof(ea->aarp_spnet)); 226 bcopy(&sat->sat_addr.s_net, ea->aarp_tpnet, 227 sizeof(ea->aarp_tpnet)); 228 ea->aarp_spnode = AA_SAT(aa)->sat_addr.s_node; 229 ea->aarp_tpnode = sat->sat_addr.s_node; 230 } else { 231 bcopy(ifp->if_broadcastaddr, (caddr_t)eh->ether_dhost, 232 sizeof(eh->ether_dhost)); 233 eh->ether_type = htons(ETHERTYPE_AARP); 234 ea->aarp_spa = AA_SAT(aa)->sat_addr.s_node; 235 ea->aarp_tpa = sat->sat_addr.s_node; 236 } 237 238#ifdef NETATALKDEBUG 239 printf("aarp: sending request for %u.%u\n", 240 ntohs(AA_SAT(aa)->sat_addr.s_net), AA_SAT(aa)->sat_addr.s_node); 241#endif /* NETATALKDEBUG */ 242 243 sa.sa_len = sizeof(struct sockaddr); 244 sa.sa_family = AF_UNSPEC; 245 ifp->if_output(ifp, m, &sa, NULL); 246} 247 248int 249aarpresolve(struct ifnet *ifp, struct mbuf *m, struct sockaddr_at *destsat, 250 u_char *desten) 251{ 252 struct at_ifaddr *aa; 253 struct aarptab *aat; 254 255 if (at_broadcast(destsat)) { 256 m->m_flags |= M_BCAST; 257 if ((aa = at_ifawithnet(destsat)) == NULL) { 258 m_freem(m); 259 return (0); 260 } 261 if (aa->aa_flags & AFA_PHASE2) 262 bcopy(atmulticastaddr, (caddr_t)desten, 263 sizeof(atmulticastaddr)); 264 else 265 bcopy(ifp->if_broadcastaddr, (caddr_t)desten, 266 sizeof(ifp->if_addrlen)); 267 return (1); 268 } 269 270 AARPTAB_LOCK(); 271 AARPTAB_LOOK(aat, destsat->sat_addr); 272 if (aat == NULL) { 273 /* No entry. */ 274 aat = aarptnew(&destsat->sat_addr); 275 276 /* We should fail more gracefully. */ 277 if (aat == NULL) 278 panic("aarpresolve: no free entry"); 279 goto done; 280 } 281 282 /* Found an entry. */ 283 aat->aat_timer = 0; 284 if (aat->aat_flags & ATF_COM) { 285 /* Entry is COMplete. */ 286 bcopy((caddr_t)aat->aat_enaddr, (caddr_t)desten, 287 sizeof(aat->aat_enaddr)); 288 AARPTAB_UNLOCK(); 289 return (1); 290 } 291 292 /* Entry has not completed. */ 293 if (aat->aat_hold) 294 m_freem(aat->aat_hold); 295done: 296 aat->aat_hold = m; 297 AARPTAB_UNLOCK(); 298 aarpwhohas(ifp, destsat); 299 return (0); 300} 301 302void 303aarpintr(struct mbuf *m) 304{ 305 struct arphdr *ar; 306 struct ifnet *ifp; 307 308 ifp = m->m_pkthdr.rcvif; 309 if (ifp->if_flags & IFF_NOARP) 310 goto out; 311 312 if (m->m_len < sizeof(struct arphdr)) 313 goto out; 314 315 ar = mtod(m, struct arphdr *); 316 if (ntohs(ar->ar_hrd) != AARPHRD_ETHER) 317 goto out; 318 319 if (m->m_len < sizeof(struct arphdr) + 2 * ar->ar_hln + 320 2 * ar->ar_pln) 321 goto out; 322 323 switch(ntohs(ar->ar_pro)) { 324 case ETHERTYPE_AT: 325 at_aarpinput(ifp, m); 326 return; 327 default: 328 break; 329 } 330 331out: 332 m_freem(m); 333} 334 335static void 336at_aarpinput(struct ifnet *ifp, struct mbuf *m) 337{ 338 struct ether_aarp *ea; 339 struct at_ifaddr *aa; 340 struct aarptab *aat; 341 struct ether_header *eh; 342 struct llc *llc; 343 struct sockaddr_at sat; 344 struct sockaddr sa; 345 struct at_addr spa, tpa, ma; 346 int op; 347 u_short net; 348 349 ea = mtod(m, struct ether_aarp *); 350 351 /* Check to see if from my hardware address. */ 352 if (!bcmp((caddr_t)ea->aarp_sha, IF_LLADDR(ifp), ETHER_ADDR_LEN)) { 353 m_freem(m); 354 return; 355 } 356 357 /* Don't accept requests from broadcast address. */ 358 if (!bcmp(ea->aarp_sha, ifp->if_broadcastaddr, ifp->if_addrlen)) { 359 log(LOG_ERR, "aarp: source link address is broadcast\n"); 360 m_freem(m); 361 return; 362 } 363 364 op = ntohs(ea->aarp_op); 365 bcopy(ea->aarp_tpnet, &net, sizeof(net)); 366 367 if (net != 0) { 368 /* Should be ATADDR_ANYNET? */ 369 sat.sat_len = sizeof(struct sockaddr_at); 370 sat.sat_family = AF_APPLETALK; 371 sat.sat_addr.s_net = net; 372 if ((aa = at_ifawithnet(&sat)) == NULL) { 373 m_freem(m); 374 return; 375 } 376 bcopy(ea->aarp_spnet, &spa.s_net, sizeof(spa.s_net)); 377 bcopy(ea->aarp_tpnet, &tpa.s_net, sizeof(tpa.s_net)); 378 } else { 379 /* 380 * Since we don't know the net, we just look for the first 381 * phase 1 address on the interface. 382 */ 383 for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead); 384 aa; 385 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) { 386 if (AA_SAT(aa)->sat_family == AF_APPLETALK && 387 (aa->aa_flags & AFA_PHASE2) == 0) { 388 break; 389 } 390 } 391 if (aa == NULL) { 392 m_freem(m); 393 return; 394 } 395 tpa.s_net = spa.s_net = AA_SAT(aa)->sat_addr.s_net; 396 } 397 398 spa.s_node = ea->aarp_spnode; 399 tpa.s_node = ea->aarp_tpnode; 400 ma.s_net = AA_SAT(aa)->sat_addr.s_net; 401 ma.s_node = AA_SAT(aa)->sat_addr.s_node; 402 403 /* 404 * This looks like it's from us. 405 */ 406 if (spa.s_net == ma.s_net && spa.s_node == ma.s_node) { 407 if (aa->aa_flags & AFA_PROBING) { 408 /* 409 * We're probing, someone either responded to our 410 * probe, or probed for the same address we'd like to 411 * use. Change the address we're probing for. 412 */ 413 callout_stop(&aa->aa_callout); 414 wakeup(aa); 415 m_freem(m); 416 return; 417 } else if (op != AARPOP_PROBE) { 418 /* 419 * This is not a probe, and we're not probing. This 420 * means that someone's saying they have the same 421 * source address as the one we're using. Get upset. 422 */ 423 log(LOG_ERR, 424 "aarp: duplicate AT address!! %x:%x:%x:%x:%x:%x\n", 425 ea->aarp_sha[0], ea->aarp_sha[1], 426 ea->aarp_sha[2], ea->aarp_sha[3], 427 ea->aarp_sha[4], ea->aarp_sha[5]); 428 m_freem(m); 429 return; 430 } 431 } 432 433 AARPTAB_LOCK(); 434 AARPTAB_LOOK(aat, spa); 435 if (aat != NULL) { 436 if (op == AARPOP_PROBE) { 437 /* 438 * Someone's probing for spa, dealocate the one we've 439 * got, so that if the prober keeps the address, 440 * we'll be able to arp for him. 441 */ 442 aarptfree(aat); 443 AARPTAB_UNLOCK(); 444 m_freem(m); 445 return; 446 } 447 448 bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr, 449 sizeof(ea->aarp_sha)); 450 aat->aat_flags |= ATF_COM; 451 if (aat->aat_hold) { 452 struct mbuf *mhold = aat->aat_hold; 453 aat->aat_hold = NULL; 454 AARPTAB_UNLOCK(); 455 sat.sat_len = sizeof(struct sockaddr_at); 456 sat.sat_family = AF_APPLETALK; 457 sat.sat_addr = spa; 458 (*ifp->if_output)(ifp, mhold, 459 (struct sockaddr *)&sat, NULL); /* XXX */ 460 } else 461 AARPTAB_UNLOCK(); 462 } else if ((tpa.s_net == ma.s_net) && (tpa.s_node == ma.s_node) 463 && (op != AARPOP_PROBE) && ((aat = aarptnew(&spa)) != NULL)) { 464 bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr, 465 sizeof(ea->aarp_sha)); 466 aat->aat_flags |= ATF_COM; 467 AARPTAB_UNLOCK(); 468 } else 469 AARPTAB_UNLOCK(); 470 471 /* 472 * Don't respond to responses, and never respond if we're still 473 * probing. 474 */ 475 if (tpa.s_net != ma.s_net || tpa.s_node != ma.s_node || 476 op == AARPOP_RESPONSE || (aa->aa_flags & AFA_PROBING)) { 477 m_freem(m); 478 return; 479 } 480 481 bcopy((caddr_t)ea->aarp_sha, (caddr_t)ea->aarp_tha, 482 sizeof(ea->aarp_sha)); 483 bcopy(IF_LLADDR(ifp), (caddr_t)ea->aarp_sha, sizeof(ea->aarp_sha)); 484 485 /* XXX */ 486 eh = (struct ether_header *)sa.sa_data; 487 bcopy((caddr_t)ea->aarp_tha, (caddr_t)eh->ether_dhost, 488 sizeof(eh->ether_dhost)); 489 490 if (aa->aa_flags & AFA_PHASE2) { 491 eh->ether_type = htons(sizeof(struct llc) + 492 sizeof(struct ether_aarp)); 493 M_PREPEND(m, sizeof(struct llc), M_DONTWAIT); 494 if (m == NULL) 495 return; 496 llc = mtod(m, struct llc *); 497 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP; 498 llc->llc_control = LLC_UI; 499 bcopy(aarp_org_code, llc->llc_org_code, 500 sizeof(aarp_org_code)); 501 llc->llc_ether_type = htons(ETHERTYPE_AARP); 502 503 bcopy(ea->aarp_spnet, ea->aarp_tpnet, 504 sizeof(ea->aarp_tpnet)); 505 bcopy(&ma.s_net, ea->aarp_spnet, sizeof(ea->aarp_spnet)); 506 } else 507 eh->ether_type = htons(ETHERTYPE_AARP); 508 509 ea->aarp_tpnode = ea->aarp_spnode; 510 ea->aarp_spnode = ma.s_node; 511 ea->aarp_op = htons(AARPOP_RESPONSE); 512 513 sa.sa_len = sizeof(struct sockaddr); 514 sa.sa_family = AF_UNSPEC; 515 (*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */ 516 return; 517} 518 519static void 520aarptfree(struct aarptab *aat) 521{ 522 523 AARPTAB_LOCK_ASSERT(); 524 if (aat->aat_hold) 525 m_freem(aat->aat_hold); 526 aat->aat_hold = NULL; 527 aat->aat_timer = aat->aat_flags = 0; 528 aat->aat_ataddr.s_net = 0; 529 aat->aat_ataddr.s_node = 0; 530} 531 532struct aarptab * 533aarptnew(struct at_addr *addr) 534{ 535 int n; 536 int oldest = -1; 537 struct aarptab *aat, *aato = NULL; 538 static int first = 1; 539 540 AARPTAB_LOCK_ASSERT(); 541 if (first) { 542 first = 0; 543 aarptimer_ch = timeout(aarptimer, (caddr_t)0, hz); 544 } 545 aat = &aarptab[AARPTAB_HASH(*addr) * AARPTAB_BSIZ]; 546 for (n = 0; n < AARPTAB_BSIZ; n++, aat++) { 547 if (aat->aat_flags == 0) 548 goto out; 549 if (aat->aat_flags & ATF_PERM) 550 continue; 551 if ((int) aat->aat_timer > oldest) { 552 oldest = aat->aat_timer; 553 aato = aat; 554 } 555 } 556 if (aato == NULL) 557 return (NULL); 558 aat = aato; 559 aarptfree(aat); 560out: 561 aat->aat_ataddr = *addr; 562 aat->aat_flags = ATF_INUSE; 563 return (aat); 564} 565 566 567void 568aarpprobe(void *arg) 569{ 570 struct ifnet *ifp = arg; 571 struct mbuf *m; 572 struct ether_header *eh; 573 struct ether_aarp *ea; 574 struct at_ifaddr *aa; 575 struct llc *llc; 576 struct sockaddr sa; 577 578 /* 579 * We need to check whether the output ethernet type should be phase 580 * 1 or 2. We have the interface that we'll be sending the aarp out. 581 * We need to find an AppleTalk network on that interface with the 582 * same address as we're looking for. If the net is phase 2, 583 * generate an 802.2 and SNAP header. 584 */ 585 AARPTAB_LOCK(); 586 for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead); aa; 587 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) { 588 if (AA_SAT(aa)->sat_family == AF_APPLETALK && 589 (aa->aa_flags & AFA_PROBING)) 590 break; 591 } 592 if (aa == NULL) { 593 /* Serious error XXX. */ 594 AARPTAB_UNLOCK(); 595 printf("aarpprobe why did this happen?!\n"); 596 return; 597 } 598 599 if (aa->aa_probcnt <= 0) { 600 aa->aa_flags &= ~AFA_PROBING; 601 wakeup(aa); 602 AARPTAB_UNLOCK(); 603 return; 604 } else 605 callout_reset(&aa->aa_callout, hz / 5, aarpprobe, ifp); 606 AARPTAB_UNLOCK(); 607 608 m = m_gethdr(M_DONTWAIT, MT_DATA); 609 if (m == NULL) 610 return; 611#ifdef MAC 612 mac_netatalk_aarp_send(ifp, m); 613#endif 614 m->m_len = sizeof(*ea); 615 m->m_pkthdr.len = sizeof(*ea); 616 MH_ALIGN(m, sizeof(*ea)); 617 618 ea = mtod(m, struct ether_aarp *); 619 bzero((caddr_t)ea, sizeof(*ea)); 620 621 ea->aarp_hrd = htons(AARPHRD_ETHER); 622 ea->aarp_pro = htons(ETHERTYPE_AT); 623 ea->aarp_hln = sizeof(ea->aarp_sha); 624 ea->aarp_pln = sizeof(ea->aarp_spu); 625 ea->aarp_op = htons(AARPOP_PROBE); 626 bcopy(IF_LLADDR(ifp), (caddr_t)ea->aarp_sha, 627 sizeof(ea->aarp_sha)); 628 629 eh = (struct ether_header *)sa.sa_data; 630 631 if (aa->aa_flags & AFA_PHASE2) { 632 bcopy(atmulticastaddr, eh->ether_dhost, 633 sizeof(eh->ether_dhost)); 634 eh->ether_type = htons(sizeof(struct llc) + 635 sizeof(struct ether_aarp));
|