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 *
| 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.
| 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.
|
145 */ 146struct at_ifaddr *
| 148 */ 149struct at_ifaddr *
|
147at_ifawithnet(struct sockaddr_at *sat)
| 150at_ifawithnet_locked(struct sockaddr_at *sat)
|
148{ 149 struct at_ifaddr *aa; 150 struct sockaddr_at *sat2; 151 152 AT_IFADDR_LOCK_ASSERT(); 153 154 for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) { 155 sat2 = &(aa->aa_addr); 156 if (sat2->sat_addr.s_net == sat->sat_addr.s_net) 157 break; 158 if ((aa->aa_flags & AFA_PHASE2) && 159 (ntohs(aa->aa_firstnet) <= ntohs(sat->sat_addr.s_net)) && 160 (ntohs(aa->aa_lastnet) >= ntohs(sat->sat_addr.s_net))) 161 break; 162 } 163 return (aa); 164} 165
| 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
|
166static void 167aarpwhohas(struct ifnet *ifp, struct sockaddr_at *sat) 168{ 169 struct mbuf *m; 170 struct ether_header *eh; 171 struct ether_aarp *ea; 172 struct at_ifaddr *aa; 173 struct llc *llc; 174 struct sockaddr sa; 175 176 AARPTAB_UNLOCK_ASSERT(); 177 m = m_gethdr(M_DONTWAIT, MT_DATA); 178 if (m == NULL) 179 return; 180#ifdef MAC 181 mac_netatalk_aarp_send(ifp, m); 182#endif 183 m->m_len = sizeof(*ea); 184 m->m_pkthdr.len = sizeof(*ea); 185 MH_ALIGN(m, sizeof(*ea)); 186 187 ea = mtod(m, struct ether_aarp *); 188 bzero((caddr_t)ea, sizeof(*ea)); 189 190 ea->aarp_hrd = htons(AARPHRD_ETHER); 191 ea->aarp_pro = htons(ETHERTYPE_AT); 192 ea->aarp_hln = sizeof(ea->aarp_sha); 193 ea->aarp_pln = sizeof(ea->aarp_spu); 194 ea->aarp_op = htons(AARPOP_REQUEST); 195 bcopy(IF_LLADDR(ifp), (caddr_t)ea->aarp_sha, sizeof(ea->aarp_sha)); 196 197 /* 198 * We need to check whether the output ethernet type should be phase 199 * 1 or 2. We have the interface that we'll be sending the aarp out. 200 * We need to find an AppleTalk network on that interface with the 201 * same address as we're looking for. If the net is phase 2, 202 * generate an 802.2 and SNAP header. 203 */
| 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) {
|
207 m_freem(m); 208 return; 209 } 210 211 eh = (struct ether_header *)sa.sa_data; 212 213 if (aa->aa_flags & AFA_PHASE2) { 214 bcopy(atmulticastaddr, eh->ether_dhost, 215 sizeof(eh->ether_dhost)); 216 eh->ether_type = htons(sizeof(struct llc) + 217 sizeof(struct ether_aarp)); 218 M_PREPEND(m, sizeof(struct llc), M_DONTWAIT); 219 if (m == 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);
|
221 return; 222 } 223 llc = mtod(m, struct llc *); 224 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP; 225 llc->llc_control = LLC_UI; 226 bcopy(aarp_org_code, llc->llc_org_code, 227 sizeof(aarp_org_code)); 228 llc->llc_ether_type = htons(ETHERTYPE_AARP); 229 bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_spnet, 230 sizeof(ea->aarp_spnet)); 231 bcopy(&sat->sat_addr.s_net, ea->aarp_tpnet, 232 sizeof(ea->aarp_tpnet)); 233 ea->aarp_spnode = AA_SAT(aa)->sat_addr.s_node; 234 ea->aarp_tpnode = sat->sat_addr.s_node; 235 } else { 236 bcopy(ifp->if_broadcastaddr, (caddr_t)eh->ether_dhost, 237 sizeof(eh->ether_dhost)); 238 eh->ether_type = htons(ETHERTYPE_AARP); 239 ea->aarp_spa = AA_SAT(aa)->sat_addr.s_node; 240 ea->aarp_tpa = sat->sat_addr.s_node; 241 } 242 243#ifdef NETATALKDEBUG 244 printf("aarp: sending request for %u.%u\n", 245 ntohs(AA_SAT(aa)->sat_addr.s_net), AA_SAT(aa)->sat_addr.s_node); 246#endif /* NETATALKDEBUG */
| 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);
|
248 249 sa.sa_len = sizeof(struct sockaddr); 250 sa.sa_family = AF_UNSPEC; 251 ifp->if_output(ifp, m, &sa, NULL); 252} 253 254int 255aarpresolve(struct ifnet *ifp, struct mbuf *m, struct sockaddr_at *destsat, 256 u_char *desten) 257{ 258 struct at_ifaddr *aa; 259 struct aarptab *aat; 260 261 AT_IFADDR_RLOCK(); 262 if (at_broadcast(destsat)) { 263 m->m_flags |= M_BCAST;
| 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) {
|
265 AT_IFADDR_RUNLOCK(); 266 m_freem(m); 267 return (0); 268 } 269 if (aa->aa_flags & AFA_PHASE2) 270 bcopy(atmulticastaddr, (caddr_t)desten, 271 sizeof(atmulticastaddr)); 272 else 273 bcopy(ifp->if_broadcastaddr, (caddr_t)desten, 274 sizeof(ifp->if_addrlen)); 275 AT_IFADDR_RUNLOCK(); 276 return (1); 277 } 278 AT_IFADDR_RUNLOCK(); 279 280 AARPTAB_LOCK(); 281 AARPTAB_LOOK(aat, destsat->sat_addr); 282 if (aat == NULL) { 283 /* No entry. */ 284 aat = aarptnew(&destsat->sat_addr); 285 286 /* We should fail more gracefully. */ 287 if (aat == NULL) 288 panic("aarpresolve: no free entry"); 289 goto done; 290 } 291 292 /* Found an entry. */ 293 aat->aat_timer = 0; 294 if (aat->aat_flags & ATF_COM) { 295 /* Entry is COMplete. */ 296 bcopy((caddr_t)aat->aat_enaddr, (caddr_t)desten, 297 sizeof(aat->aat_enaddr)); 298 AARPTAB_UNLOCK(); 299 return (1); 300 } 301 302 /* Entry has not completed. */ 303 if (aat->aat_hold) 304 m_freem(aat->aat_hold); 305done: 306 aat->aat_hold = m; 307 AARPTAB_UNLOCK(); 308 aarpwhohas(ifp, destsat); 309 return (0); 310} 311 312void 313aarpintr(struct mbuf *m) 314{ 315 struct arphdr *ar; 316 struct ifnet *ifp; 317 318 ifp = m->m_pkthdr.rcvif; 319 if (ifp->if_flags & IFF_NOARP) 320 goto out; 321 322 if (m->m_len < sizeof(struct arphdr)) 323 goto out; 324 325 ar = mtod(m, struct arphdr *); 326 if (ntohs(ar->ar_hrd) != AARPHRD_ETHER) 327 goto out; 328 329 if (m->m_len < sizeof(struct arphdr) + 2 * ar->ar_hln + 330 2 * ar->ar_pln) 331 goto out; 332 333 switch(ntohs(ar->ar_pro)) { 334 case ETHERTYPE_AT: 335 at_aarpinput(ifp, m); 336 return; 337 default: 338 break; 339 } 340 341out: 342 m_freem(m); 343} 344 345static void 346at_aarpinput(struct ifnet *ifp, struct mbuf *m) 347{ 348 struct ether_aarp *ea; 349 struct at_ifaddr *aa; 350 struct aarptab *aat; 351 struct ether_header *eh; 352 struct llc *llc; 353 struct sockaddr_at sat; 354 struct sockaddr sa; 355 struct at_addr spa, tpa, ma; 356 int op; 357 u_short net; 358 359 ea = mtod(m, struct ether_aarp *); 360 361 /* Check to see if from my hardware address. */ 362 if (!bcmp((caddr_t)ea->aarp_sha, IF_LLADDR(ifp), ETHER_ADDR_LEN)) { 363 m_freem(m); 364 return; 365 } 366 367 /* Don't accept requests from broadcast address. */ 368 if (!bcmp(ea->aarp_sha, ifp->if_broadcastaddr, ifp->if_addrlen)) { 369 log(LOG_ERR, "aarp: source link address is broadcast\n"); 370 m_freem(m); 371 return; 372 } 373 374 op = ntohs(ea->aarp_op); 375 bcopy(ea->aarp_tpnet, &net, sizeof(net)); 376 377 if (net != 0) { 378 /* Should be ATADDR_ANYNET? */ 379 sat.sat_len = sizeof(struct sockaddr_at); 380 sat.sat_family = AF_APPLETALK; 381 sat.sat_addr.s_net = net;
| 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) {
|
385 m_freem(m); 386 return; 387 }
| 399 m_freem(m); 400 return; 401 }
|
388 ifa_ref(&aa->aa_ifa); 389 AT_IFADDR_RUNLOCK();
| |
390 bcopy(ea->aarp_spnet, &spa.s_net, sizeof(spa.s_net)); 391 bcopy(ea->aarp_tpnet, &tpa.s_net, sizeof(tpa.s_net)); 392 } else { 393 /* 394 * Since we don't know the net, we just look for the first 395 * phase 1 address on the interface. 396 */ 397 IF_ADDR_LOCK(ifp); 398 for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead); 399 aa; 400 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) { 401 if (AA_SAT(aa)->sat_family == AF_APPLETALK && 402 (aa->aa_flags & AFA_PHASE2) == 0) { 403 break; 404 } 405 } 406 if (aa == NULL) { 407 IF_ADDR_UNLOCK(ifp); 408 m_freem(m); 409 return; 410 } 411 ifa_ref(&aa->aa_ifa); 412 IF_ADDR_UNLOCK(ifp); 413 tpa.s_net = spa.s_net = AA_SAT(aa)->sat_addr.s_net; 414 } 415 416 spa.s_node = ea->aarp_spnode; 417 tpa.s_node = ea->aarp_tpnode; 418 ma.s_net = AA_SAT(aa)->sat_addr.s_net; 419 ma.s_node = AA_SAT(aa)->sat_addr.s_node; 420 421 /* 422 * This looks like it's from us. 423 */ 424 if (spa.s_net == ma.s_net && spa.s_node == ma.s_node) { 425 if (aa->aa_flags & AFA_PROBING) { 426 /* 427 * We're probing, someone either responded to our 428 * probe, or probed for the same address we'd like to 429 * use. Change the address we're probing for. 430 */ 431 callout_stop(&aa->aa_callout); 432 wakeup(aa); 433 ifa_free(&aa->aa_ifa); 434 m_freem(m); 435 return; 436 } else if (op != AARPOP_PROBE) { 437 /* 438 * This is not a probe, and we're not probing. This 439 * means that someone's saying they have the same 440 * source address as the one we're using. Get upset. 441 */ 442 ifa_free(&aa->aa_ifa); 443 log(LOG_ERR, 444 "aarp: duplicate AT address!! %x:%x:%x:%x:%x:%x\n", 445 ea->aarp_sha[0], ea->aarp_sha[1], 446 ea->aarp_sha[2], ea->aarp_sha[3], 447 ea->aarp_sha[4], ea->aarp_sha[5]); 448 m_freem(m); 449 return; 450 } 451 } 452 453 AARPTAB_LOCK(); 454 AARPTAB_LOOK(aat, spa); 455 if (aat != NULL) { 456 if (op == AARPOP_PROBE) { 457 /* 458 * Someone's probing for spa, dealocate the one we've 459 * got, so that if the prober keeps the address, 460 * we'll be able to arp for him. 461 */ 462 aarptfree(aat); 463 AARPTAB_UNLOCK(); 464 ifa_free(&aa->aa_ifa); 465 m_freem(m); 466 return; 467 } 468 469 bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr, 470 sizeof(ea->aarp_sha)); 471 aat->aat_flags |= ATF_COM; 472 if (aat->aat_hold) { 473 struct mbuf *mhold = aat->aat_hold; 474 aat->aat_hold = NULL; 475 AARPTAB_UNLOCK(); 476 sat.sat_len = sizeof(struct sockaddr_at); 477 sat.sat_family = AF_APPLETALK; 478 sat.sat_addr = spa; 479 (*ifp->if_output)(ifp, mhold, 480 (struct sockaddr *)&sat, NULL); /* XXX */ 481 } else 482 AARPTAB_UNLOCK(); 483 } else if ((tpa.s_net == ma.s_net) && (tpa.s_node == ma.s_node) 484 && (op != AARPOP_PROBE) && ((aat = aarptnew(&spa)) != NULL)) { 485 bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr, 486 sizeof(ea->aarp_sha)); 487 aat->aat_flags |= ATF_COM; 488 AARPTAB_UNLOCK(); 489 } else 490 AARPTAB_UNLOCK(); 491 492 /* 493 * Don't respond to responses, and never respond if we're still 494 * probing. 495 */ 496 if (tpa.s_net != ma.s_net || tpa.s_node != ma.s_node || 497 op == AARPOP_RESPONSE || (aa->aa_flags & AFA_PROBING)) { 498 ifa_free(&aa->aa_ifa); 499 m_freem(m); 500 return; 501 } 502 503 bcopy((caddr_t)ea->aarp_sha, (caddr_t)ea->aarp_tha, 504 sizeof(ea->aarp_sha)); 505 bcopy(IF_LLADDR(ifp), (caddr_t)ea->aarp_sha, sizeof(ea->aarp_sha)); 506 507 /* XXX */ 508 eh = (struct ether_header *)sa.sa_data; 509 bcopy((caddr_t)ea->aarp_tha, (caddr_t)eh->ether_dhost, 510 sizeof(eh->ether_dhost)); 511 512 if (aa->aa_flags & AFA_PHASE2) { 513 eh->ether_type = htons(sizeof(struct llc) + 514 sizeof(struct ether_aarp)); 515 M_PREPEND(m, sizeof(struct llc), M_DONTWAIT); 516 if (m == NULL) { 517 ifa_free(&aa->aa_ifa); 518 return; 519 } 520 llc = mtod(m, struct llc *); 521 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP; 522 llc->llc_control = LLC_UI; 523 bcopy(aarp_org_code, llc->llc_org_code, 524 sizeof(aarp_org_code)); 525 llc->llc_ether_type = htons(ETHERTYPE_AARP); 526 527 bcopy(ea->aarp_spnet, ea->aarp_tpnet, 528 sizeof(ea->aarp_tpnet)); 529 bcopy(&ma.s_net, ea->aarp_spnet, sizeof(ea->aarp_spnet)); 530 } else 531 eh->ether_type = htons(ETHERTYPE_AARP); 532 ifa_free(&aa->aa_ifa); 533 534 ea->aarp_tpnode = ea->aarp_spnode; 535 ea->aarp_spnode = ma.s_node; 536 ea->aarp_op = htons(AARPOP_RESPONSE); 537 538 sa.sa_len = sizeof(struct sockaddr); 539 sa.sa_family = AF_UNSPEC; 540 (*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */ 541 return; 542} 543 544static void 545aarptfree(struct aarptab *aat) 546{ 547 548 AARPTAB_LOCK_ASSERT(); 549 if (aat->aat_hold) 550 m_freem(aat->aat_hold); 551 aat->aat_hold = NULL; 552 aat->aat_timer = aat->aat_flags = 0; 553 aat->aat_ataddr.s_net = 0; 554 aat->aat_ataddr.s_node = 0; 555} 556 557struct aarptab * 558aarptnew(struct at_addr *addr) 559{ 560 int n; 561 int oldest = -1; 562 struct aarptab *aat, *aato = NULL; 563 static int first = 1; 564 565 AARPTAB_LOCK_ASSERT(); 566 if (first) { 567 first = 0; 568 aarptimer_ch = timeout(aarptimer, (caddr_t)0, hz); 569 } 570 aat = &aarptab[AARPTAB_HASH(*addr) * AARPTAB_BSIZ]; 571 for (n = 0; n < AARPTAB_BSIZ; n++, aat++) { 572 if (aat->aat_flags == 0) 573 goto out; 574 if (aat->aat_flags & ATF_PERM) 575 continue; 576 if ((int) aat->aat_timer > oldest) { 577 oldest = aat->aat_timer; 578 aato = aat; 579 } 580 } 581 if (aato == NULL) 582 return (NULL); 583 aat = aato; 584 aarptfree(aat); 585out: 586 aat->aat_ataddr = *addr; 587 aat->aat_flags = ATF_INUSE; 588 return (aat); 589} 590 591 592void 593aarpprobe(void *arg) 594{ 595 struct ifnet *ifp = arg; 596 struct mbuf *m; 597 struct ether_header *eh; 598 struct ether_aarp *ea; 599 struct at_ifaddr *aa; 600 struct llc *llc; 601 struct sockaddr sa; 602 603 /* 604 * We need to check whether the output ethernet type should be phase 605 * 1 or 2. We have the interface that we'll be sending the aarp out. 606 * We need to find an AppleTalk network on that interface with the 607 * same address as we're looking for. If the net is phase 2, 608 * generate an 802.2 and SNAP header. 609 */ 610 AARPTAB_LOCK(); 611 for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead); aa; 612 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) { 613 if (AA_SAT(aa)->sat_family == AF_APPLETALK && 614 (aa->aa_flags & AFA_PROBING)) 615 break; 616 } 617 if (aa == NULL) { 618 /* Serious error XXX. */ 619 AARPTAB_UNLOCK(); 620 printf("aarpprobe why did this happen?!\n"); 621 return; 622 } 623 624 if (aa->aa_probcnt <= 0) { 625 aa->aa_flags &= ~AFA_PROBING; 626 wakeup(aa); 627 AARPTAB_UNLOCK(); 628 return; 629 } else 630 callout_reset(&aa->aa_callout, hz / 5, aarpprobe, ifp); 631 ifa_ref(&aa->aa_ifa); 632 AARPTAB_UNLOCK(); 633 634 m = m_gethdr(M_DONTWAIT, MT_DATA); 635 if (m == NULL) { 636 ifa_free(&aa->aa_ifa); 637 return; 638 } 639#ifdef MAC 640 mac_netatalk_aarp_send(ifp, m); 641#endif 642 m->m_len = sizeof(*ea); 643 m->m_pkthdr.len = sizeof(*ea); 644 MH_ALIGN(m, sizeof(*ea)); 645 646 ea = mtod(m, struct ether_aarp *); 647 bzero((caddr_t)ea, sizeof(*ea)); 648 649 ea->aarp_hrd = htons(AARPHRD_ETHER); 650 ea->aarp_pro = htons(ETHERTYPE_AT); 651 ea->aarp_hln = sizeof(ea->aarp_sha); 652 ea->aarp_pln = sizeof(ea->aarp_spu); 653 ea->aarp_op = htons(AARPOP_PROBE); 654 bcopy(IF_LLADDR(ifp), (caddr_t)ea->aarp_sha, 655 sizeof(ea->aarp_sha)); 656 657 eh = (struct ether_header *)sa.sa_data; 658 659 if (aa->aa_flags & AFA_PHASE2) { 660 bcopy(atmulticastaddr, eh->ether_dhost, 661 sizeof(eh->ether_dhost)); 662 eh->ether_type = htons(sizeof(struct llc) + 663 sizeof(struct ether_aarp)); 664 M_PREPEND(m, sizeof(struct llc), M_WAIT); 665 llc = mtod(m, struct llc *); 666 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP; 667 llc->llc_control = LLC_UI; 668 bcopy(aarp_org_code, llc->llc_org_code, 669 sizeof(aarp_org_code)); 670 llc->llc_ether_type = htons(ETHERTYPE_AARP); 671 672 bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_spnet, 673 sizeof(ea->aarp_spnet)); 674 bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_tpnet, 675 sizeof(ea->aarp_tpnet)); 676 ea->aarp_spnode = ea->aarp_tpnode = 677 AA_SAT(aa)->sat_addr.s_node; 678 } else { 679 bcopy(ifp->if_broadcastaddr, (caddr_t)eh->ether_dhost, 680 sizeof(eh->ether_dhost)); 681 eh->ether_type = htons(ETHERTYPE_AARP); 682 ea->aarp_spa = ea->aarp_tpa = AA_SAT(aa)->sat_addr.s_node; 683 } 684 685#ifdef NETATALKDEBUG 686 printf("aarp: sending probe for %u.%u\n", 687 ntohs(AA_SAT(aa)->sat_addr.s_net), AA_SAT(aa)->sat_addr.s_node); 688#endif /* NETATALKDEBUG */ 689 ifa_free(&aa->aa_ifa); 690 691 sa.sa_len = sizeof(struct sockaddr); 692 sa.sa_family = AF_UNSPEC; 693 (*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */ 694 aa->aa_probcnt--; 695} 696 697void 698aarp_clean(void) 699{ 700 struct aarptab *aat; 701 int i; 702 703 untimeout(aarptimer, 0, aarptimer_ch); 704 AARPTAB_LOCK(); 705 for (i = 0, aat = aarptab; i < AARPTAB_SIZE; i++, aat++) { 706 if (aat->aat_hold) { 707 m_freem(aat->aat_hold); 708 aat->aat_hold = NULL; 709 } 710 } 711 AARPTAB_UNLOCK(); 712}
| 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}
|