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