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