aarp.c revision 1.45 1 1.45 dholland /* $NetBSD: aarp.c,v 1.45 2023/07/31 01:23:04 dholland 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.45 dholland __KERNEL_RCSID(0, "$NetBSD: aarp.c,v 1.45 2023/07/31 01:23:04 dholland 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.45 dholland aat = &aarptab[AARPTAB_HASH(addr) * AARPTAB_BSIZ]; \
77 1.45 dholland for (n = 0; n < AARPTAB_BSIZ; n++, aat++) { \
78 1.45 dholland if (aat->aat_ataddr.s_net == (addr).s_net && \
79 1.45 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.45 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.1 christos if (aat->aat_hold)
302 1.1 christos m_freem(aat->aat_hold);
303 1.1 christos aat->aat_hold = m;
304 1.1 christos aarpwhohas(ifp, destsat);
305 1.1 christos splx(s);
306 1.1 christos
307 1.1 christos return 0;
308 1.1 christos }
309 1.1 christos
310 1.1 christos void
311 1.28 dsl aarpinput(struct ifnet *ifp, struct mbuf *m)
312 1.1 christos {
313 1.1 christos struct arphdr *ar;
314 1.1 christos
315 1.1 christos if (ifp->if_flags & IFF_NOARP)
316 1.1 christos goto out;
317 1.1 christos
318 1.1 christos if (m->m_len < sizeof(struct arphdr))
319 1.1 christos goto out;
320 1.1 christos
321 1.1 christos ar = mtod(m, struct arphdr *);
322 1.1 christos if (ntohs(ar->ar_hrd) != AARPHRD_ETHER)
323 1.1 christos goto out;
324 1.1 christos
325 1.1 christos if (m->m_len < sizeof(struct arphdr) + 2 * ar->ar_hln + 2 * ar->ar_pln)
326 1.1 christos goto out;
327 1.1 christos
328 1.1 christos switch (ntohs(ar->ar_pro)) {
329 1.3 kim case ETHERTYPE_ATALK:
330 1.1 christos at_aarpinput(ifp, m);
331 1.1 christos return;
332 1.1 christos
333 1.1 christos default:
334 1.1 christos break;
335 1.1 christos }
336 1.1 christos
337 1.1 christos out:
338 1.1 christos m_freem(m);
339 1.1 christos }
340 1.1 christos
341 1.1 christos static void
342 1.28 dsl at_aarpinput(struct ifnet *ifp, struct mbuf *m)
343 1.1 christos {
344 1.1 christos struct ether_aarp *ea;
345 1.1 christos struct at_ifaddr *aa;
346 1.1 christos struct aarptab *aat;
347 1.1 christos struct ether_header *eh;
348 1.1 christos struct llc *llc;
349 1.1 christos struct sockaddr_at sat;
350 1.1 christos struct sockaddr sa;
351 1.1 christos struct at_addr spa, tpa, ma;
352 1.1 christos int op;
353 1.1 christos u_int16_t net;
354 1.39 ozaki int s;
355 1.39 ozaki struct psref psref;
356 1.39 ozaki struct ifaddr *ifa;
357 1.1 christos
358 1.40 maxv /* We should also check ar_hln and ar_pln. */
359 1.40 maxv if ((m = m_pullup(m, sizeof(struct ether_aarp))) == NULL) {
360 1.40 maxv return;
361 1.40 maxv }
362 1.40 maxv
363 1.1 christos ea = mtod(m, struct ether_aarp *);
364 1.1 christos
365 1.1 christos /* Check to see if from my hardware address */
366 1.30 cegger if (!memcmp(ea->aarp_sha, CLLADDR(ifp->if_sadl), sizeof(ea->aarp_sha))) {
367 1.1 christos m_freem(m);
368 1.1 christos return;
369 1.1 christos }
370 1.1 christos op = ntohs(ea->aarp_op);
371 1.33 tsutsui memcpy(&net, ea->aarp_tpnet, sizeof(net));
372 1.1 christos
373 1.1 christos if (net != 0) { /* should be ATADDR_ANYNET? */
374 1.1 christos sat.sat_len = sizeof(struct sockaddr_at);
375 1.1 christos sat.sat_family = AF_APPLETALK;
376 1.1 christos sat.sat_addr.s_net = net;
377 1.39 ozaki
378 1.39 ozaki s = pserialize_read_enter();
379 1.39 ozaki ifa = at_ifawithnet(&sat, ifp);
380 1.39 ozaki if (ifa == NULL) {
381 1.39 ozaki pserialize_read_exit(s);
382 1.1 christos m_freem(m);
383 1.1 christos return;
384 1.1 christos }
385 1.39 ozaki ifa_acquire(ifa, &psref);
386 1.39 ozaki pserialize_read_exit(s);
387 1.39 ozaki aa = (struct at_ifaddr *)ifa;
388 1.39 ozaki
389 1.33 tsutsui memcpy(&spa.s_net, ea->aarp_spnet, sizeof(spa.s_net));
390 1.33 tsutsui memcpy(&tpa.s_net, ea->aarp_tpnet, sizeof(tpa.s_net));
391 1.1 christos } else {
392 1.1 christos /*
393 1.1 christos * Since we don't know the net, we just look for the first
394 1.1 christos * phase 1 address on the interface.
395 1.1 christos */
396 1.39 ozaki s = pserialize_read_enter();
397 1.39 ozaki IFADDR_READER_FOREACH(ifa, ifp) {
398 1.39 ozaki aa = (struct at_ifaddr *)ifa;
399 1.1 christos if (AA_SAT(aa)->sat_family == AF_APPLETALK &&
400 1.39 ozaki (aa->aa_flags & AFA_PHASE2) == 0) {
401 1.39 ozaki ifa_acquire(ifa, &psref);
402 1.1 christos break;
403 1.39 ozaki }
404 1.1 christos }
405 1.39 ozaki pserialize_read_exit(s);
406 1.39 ozaki
407 1.39 ozaki if (ifa == NULL) {
408 1.1 christos m_freem(m);
409 1.1 christos return;
410 1.1 christos }
411 1.1 christos tpa.s_net = spa.s_net = AA_SAT(aa)->sat_addr.s_net;
412 1.1 christos }
413 1.1 christos
414 1.1 christos spa.s_node = ea->aarp_spnode;
415 1.1 christos tpa.s_node = ea->aarp_tpnode;
416 1.1 christos ma.s_net = AA_SAT(aa)->sat_addr.s_net;
417 1.1 christos ma.s_node = AA_SAT(aa)->sat_addr.s_node;
418 1.1 christos
419 1.1 christos /*
420 1.1 christos * This looks like it's from us.
421 1.1 christos */
422 1.1 christos if (spa.s_net == ma.s_net && spa.s_node == ma.s_node) {
423 1.1 christos if (aa->aa_flags & AFA_PROBING) {
424 1.1 christos /*
425 1.1 christos * We're probing, someone either responded to our
426 1.1 christos * probe, or probed for the same address we'd like
427 1.1 christos * to use. Change the address we're probing for.
428 1.1 christos */
429 1.5 thorpej callout_stop(&aa->aa_probe_ch);
430 1.1 christos wakeup(aa);
431 1.1 christos m_freem(m);
432 1.39 ozaki goto out;
433 1.1 christos } else if (op != AARPOP_PROBE) {
434 1.1 christos /*
435 1.1 christos * This is not a probe, and we're not probing.
436 1.1 christos * This means that someone's saying they have the same
437 1.1 christos * source address as the one we're using. Get upset...
438 1.1 christos */
439 1.1 christos log(LOG_ERR, "aarp: duplicate AT address!! %s\n",
440 1.1 christos ether_sprintf(ea->aarp_sha));
441 1.1 christos m_freem(m);
442 1.39 ozaki goto out;
443 1.1 christos }
444 1.1 christos }
445 1.1 christos AARPTAB_LOOK(aat, spa);
446 1.1 christos if (aat) {
447 1.1 christos if (op == AARPOP_PROBE) {
448 1.1 christos /*
449 1.11 wiz * Someone's probing for spa, deallocate the one we've
450 1.1 christos * got, so that if the prober keeps the address, we'll
451 1.1 christos * be able to arp for him.
452 1.1 christos */
453 1.1 christos aarptfree(aat);
454 1.1 christos m_freem(m);
455 1.39 ozaki goto out;
456 1.1 christos }
457 1.33 tsutsui memcpy(aat->aat_enaddr, ea->aarp_sha, sizeof(ea->aarp_sha));
458 1.1 christos aat->aat_flags |= ATF_COM;
459 1.1 christos if (aat->aat_hold) {
460 1.1 christos sat.sat_len = sizeof(struct sockaddr_at);
461 1.1 christos sat.sat_family = AF_APPLETALK;
462 1.1 christos sat.sat_addr = spa;
463 1.37 knakahar if_output_lock(ifp, ifp, aat->aat_hold,
464 1.1 christos (struct sockaddr *) & sat, NULL); /* XXX */
465 1.1 christos aat->aat_hold = 0;
466 1.1 christos }
467 1.1 christos }
468 1.1 christos if (aat == 0 && tpa.s_net == ma.s_net && tpa.s_node == ma.s_node
469 1.1 christos && op != AARPOP_PROBE) {
470 1.1 christos if ((aat = aarptnew(&spa)) != NULL) {
471 1.33 tsutsui memcpy(aat->aat_enaddr, ea->aarp_sha,
472 1.1 christos sizeof(ea->aarp_sha));
473 1.1 christos aat->aat_flags |= ATF_COM;
474 1.1 christos }
475 1.1 christos }
476 1.1 christos /*
477 1.1 christos * Don't respond to responses, and never respond if we're
478 1.1 christos * still probing.
479 1.1 christos */
480 1.1 christos if (tpa.s_net != ma.s_net || tpa.s_node != ma.s_node ||
481 1.1 christos op == AARPOP_RESPONSE || (aa->aa_flags & AFA_PROBING)) {
482 1.1 christos m_freem(m);
483 1.39 ozaki goto out;
484 1.1 christos }
485 1.34 tsutsui
486 1.34 tsutsui /*
487 1.34 tsutsui * Prepare and send AARP-response.
488 1.34 tsutsui */
489 1.34 tsutsui m->m_len = sizeof(*ea);
490 1.34 tsutsui m->m_pkthdr.len = sizeof(*ea);
491 1.33 tsutsui memcpy(ea->aarp_tha, ea->aarp_sha, sizeof(ea->aarp_sha));
492 1.33 tsutsui memcpy(ea->aarp_sha, CLLADDR(ifp->if_sadl), sizeof(ea->aarp_sha));
493 1.1 christos
494 1.1 christos /* XXX */
495 1.1 christos eh = (struct ether_header *) sa.sa_data;
496 1.33 tsutsui memcpy(eh->ether_dhost, ea->aarp_tha, sizeof(eh->ether_dhost));
497 1.1 christos
498 1.1 christos if (aa->aa_flags & AFA_PHASE2) {
499 1.1 christos M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
500 1.1 christos if (m == NULL)
501 1.39 ozaki goto out;
502 1.1 christos
503 1.1 christos llc = mtod(m, struct llc *);
504 1.1 christos llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
505 1.1 christos llc->llc_control = LLC_UI;
506 1.33 tsutsui memcpy(llc->llc_org_code, aarp_org_code, sizeof(aarp_org_code));
507 1.1 christos llc->llc_ether_type = htons(ETHERTYPE_AARP);
508 1.1 christos
509 1.33 tsutsui memcpy(ea->aarp_tpnet, ea->aarp_spnet, sizeof(ea->aarp_tpnet));
510 1.33 tsutsui memcpy(ea->aarp_spnet, &ma.s_net, sizeof(ea->aarp_spnet));
511 1.4 matt eh->ether_type = 0; /* if_output will treat as 802 */
512 1.1 christos } else {
513 1.1 christos eh->ether_type = htons(ETHERTYPE_AARP);
514 1.1 christos }
515 1.1 christos
516 1.1 christos ea->aarp_tpnode = ea->aarp_spnode;
517 1.1 christos ea->aarp_spnode = ma.s_node;
518 1.1 christos ea->aarp_op = htons(AARPOP_RESPONSE);
519 1.1 christos
520 1.1 christos sa.sa_len = sizeof(struct sockaddr);
521 1.1 christos sa.sa_family = AF_UNSPEC;
522 1.1 christos (*ifp->if_output) (ifp, m, &sa, NULL); /* XXX */
523 1.39 ozaki out:
524 1.39 ozaki ifa_release(ifa, &psref);
525 1.1 christos return;
526 1.1 christos }
527 1.1 christos
528 1.1 christos static void
529 1.28 dsl aarptfree(struct aarptab *aat)
530 1.1 christos {
531 1.1 christos
532 1.1 christos if (aat->aat_hold)
533 1.1 christos m_freem(aat->aat_hold);
534 1.1 christos aat->aat_hold = 0;
535 1.1 christos aat->aat_timer = aat->aat_flags = 0;
536 1.1 christos aat->aat_ataddr.s_net = 0;
537 1.1 christos aat->aat_ataddr.s_node = 0;
538 1.1 christos }
539 1.1 christos
540 1.1 christos static struct aarptab *
541 1.22 dyoung aarptnew(const struct at_addr *addr)
542 1.1 christos {
543 1.1 christos int n;
544 1.1 christos int oldest = -1;
545 1.1 christos struct aarptab *aat, *aato = NULL;
546 1.1 christos static int first = 1;
547 1.1 christos
548 1.1 christos if (first) {
549 1.1 christos first = 0;
550 1.24 ad callout_init(&aarptimer_callout, 0);
551 1.5 thorpej callout_reset(&aarptimer_callout, hz, aarptimer, NULL);
552 1.1 christos }
553 1.1 christos aat = &aarptab[AARPTAB_HASH(*addr) * AARPTAB_BSIZ];
554 1.1 christos for (n = 0; n < AARPTAB_BSIZ; n++, aat++) {
555 1.1 christos if (aat->aat_flags == 0)
556 1.1 christos goto out;
557 1.1 christos if (aat->aat_flags & ATF_PERM)
558 1.1 christos continue;
559 1.1 christos if ((int) aat->aat_timer > oldest) {
560 1.1 christos oldest = aat->aat_timer;
561 1.1 christos aato = aat;
562 1.1 christos }
563 1.1 christos }
564 1.1 christos if (aato == NULL)
565 1.1 christos return (NULL);
566 1.1 christos aat = aato;
567 1.1 christos aarptfree(aat);
568 1.1 christos out:
569 1.1 christos aat->aat_ataddr = *addr;
570 1.1 christos aat->aat_flags = ATF_INUSE;
571 1.1 christos return (aat);
572 1.1 christos }
573 1.1 christos
574 1.1 christos
575 1.1 christos void
576 1.28 dsl aarpprobe(void *arp)
577 1.1 christos {
578 1.1 christos struct mbuf *m;
579 1.1 christos struct ether_header *eh;
580 1.1 christos struct ether_aarp *ea;
581 1.23 dyoung struct ifaddr *ia;
582 1.1 christos struct at_ifaddr *aa;
583 1.1 christos struct llc *llc;
584 1.1 christos struct sockaddr sa;
585 1.1 christos struct ifnet *ifp = arp;
586 1.1 christos
587 1.27 ad mutex_enter(softnet_lock);
588 1.27 ad
589 1.1 christos /*
590 1.1 christos * We need to check whether the output ethernet type should
591 1.1 christos * be phase 1 or 2. We have the interface that we'll be sending
592 1.1 christos * the aarp out. We need to find an AppleTalk network on that
593 1.1 christos * interface with the same address as we're looking for. If the
594 1.1 christos * net is phase 2, generate an 802.2 and SNAP header.
595 1.1 christos */
596 1.38 ozaki IFADDR_READER_FOREACH(ia, ifp) {
597 1.23 dyoung aa = (struct at_ifaddr *)ia;
598 1.1 christos if (AA_SAT(aa)->sat_family == AF_APPLETALK &&
599 1.1 christos (aa->aa_flags & AFA_PROBING))
600 1.1 christos break;
601 1.1 christos }
602 1.23 dyoung if (ia == NULL) { /* serious error XXX */
603 1.1 christos printf("aarpprobe why did this happen?!\n");
604 1.27 ad mutex_exit(softnet_lock);
605 1.1 christos return;
606 1.1 christos }
607 1.1 christos if (aa->aa_probcnt <= 0) {
608 1.1 christos aa->aa_flags &= ~AFA_PROBING;
609 1.1 christos wakeup(aa);
610 1.27 ad mutex_exit(softnet_lock);
611 1.1 christos return;
612 1.1 christos } else {
613 1.5 thorpej callout_reset(&aa->aa_probe_ch, hz / 5, aarpprobe, arp);
614 1.1 christos }
615 1.1 christos
616 1.27 ad if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) {
617 1.27 ad mutex_exit(softnet_lock);
618 1.1 christos return;
619 1.27 ad }
620 1.12 matt
621 1.12 matt MCLAIM(m, &aarp_mowner);
622 1.1 christos m->m_len = sizeof(*ea);
623 1.1 christos m->m_pkthdr.len = sizeof(*ea);
624 1.43 maxv m_align(m, sizeof(*ea));
625 1.1 christos
626 1.1 christos ea = mtod(m, struct ether_aarp *);
627 1.31 cegger memset(ea, 0, sizeof(*ea));
628 1.1 christos
629 1.1 christos ea->aarp_hrd = htons(AARPHRD_ETHER);
630 1.3 kim ea->aarp_pro = htons(ETHERTYPE_ATALK);
631 1.1 christos ea->aarp_hln = sizeof(ea->aarp_sha);
632 1.1 christos ea->aarp_pln = sizeof(ea->aarp_spu);
633 1.1 christos ea->aarp_op = htons(AARPOP_PROBE);
634 1.33 tsutsui memcpy(ea->aarp_sha, CLLADDR(ifp->if_sadl), sizeof(ea->aarp_sha));
635 1.1 christos
636 1.1 christos eh = (struct ether_header *) sa.sa_data;
637 1.1 christos
638 1.1 christos if (aa->aa_flags & AFA_PHASE2) {
639 1.33 tsutsui memcpy(eh->ether_dhost, atmulticastaddr,
640 1.1 christos sizeof(eh->ether_dhost));
641 1.4 matt eh->ether_type = 0; /* if_output will treat as 802 */
642 1.13 itojun M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
643 1.27 ad if (!m) {
644 1.27 ad mutex_exit(softnet_lock);
645 1.13 itojun return;
646 1.27 ad }
647 1.13 itojun
648 1.1 christos llc = mtod(m, struct llc *);
649 1.1 christos llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
650 1.1 christos llc->llc_control = LLC_UI;
651 1.33 tsutsui memcpy(llc->llc_org_code, aarp_org_code, sizeof(aarp_org_code));
652 1.1 christos llc->llc_ether_type = htons(ETHERTYPE_AARP);
653 1.1 christos
654 1.33 tsutsui memcpy(ea->aarp_spnet, &AA_SAT(aa)->sat_addr.s_net,
655 1.1 christos sizeof(ea->aarp_spnet));
656 1.33 tsutsui memcpy(ea->aarp_tpnet, &AA_SAT(aa)->sat_addr.s_net,
657 1.1 christos sizeof(ea->aarp_tpnet));
658 1.1 christos ea->aarp_spnode = ea->aarp_tpnode =
659 1.1 christos AA_SAT(aa)->sat_addr.s_node;
660 1.1 christos } else {
661 1.33 tsutsui memcpy(eh->ether_dhost, etherbroadcastaddr,
662 1.1 christos sizeof(eh->ether_dhost));
663 1.1 christos eh->ether_type = htons(ETHERTYPE_AARP);
664 1.1 christos ea->aarp_spa = ea->aarp_tpa = AA_SAT(aa)->sat_addr.s_node;
665 1.1 christos }
666 1.1 christos
667 1.1 christos #ifdef NETATALKDEBUG
668 1.1 christos printf("aarp: sending probe for %u.%u\n",
669 1.1 christos ntohs(AA_SAT(aa)->sat_addr.s_net),
670 1.1 christos AA_SAT(aa)->sat_addr.s_node);
671 1.1 christos #endif /* NETATALKDEBUG */
672 1.1 christos
673 1.1 christos sa.sa_len = sizeof(struct sockaddr);
674 1.1 christos sa.sa_family = AF_UNSPEC;
675 1.1 christos (*ifp->if_output) (ifp, m, &sa, NULL); /* XXX */
676 1.1 christos aa->aa_probcnt--;
677 1.27 ad mutex_exit(softnet_lock);
678 1.1 christos }
679