kernel tree reorganization stage 1: Major cvs repository work (not logged as
[dragonfly.git] / sys / netproto / atm / uni / uniarp_cache.c
CommitLineData
984263bc
MD
1/*
2 *
3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
6 *
7 *
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
12 *
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
20 *
21 * Copyright 1994-1998 Network Computing Services, Inc.
22 *
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
25 *
26 * @(#) $FreeBSD: src/sys/netatm/uni/uniarp_cache.c,v 1.4 1999/08/28 00:49:02 peter Exp $
d2438d69 27 * @(#) $DragonFly: src/sys/netproto/atm/uni/uniarp_cache.c,v 1.4 2003/08/07 21:54:34 dillon Exp $
984263bc
MD
28 */
29
30/*
31 * ATM Forum UNI Support
32 * ---------------------
33 *
34 * UNI ATMARP support (RFC1577) - ARP cache processing
35 *
36 */
37
d2438d69 38#include <netproto/atm/kern_include.h>
984263bc 39
d2438d69
MD
40#include <netproto/atm/ipatm/ipatm_var.h>
41#include <netproto/atm/ipatm/ipatm_serv.h>
1f2de5d4
MD
42#include "unisig_var.h"
43#include "uniip_var.h"
984263bc 44
984263bc
MD
45/*
46 * Add data to the arp table cache
47 *
48 * Called at splnet.
49 *
50 * Arguments:
51 * uip pointer to UNI IP interface
52 * ip pointer to IP address structure
53 * atm pointer to ATM address structure
54 * atmsub pointer to ATM subaddress structure
55 * origin source of arp information
56 *
57 * Returns:
58 * 0 cache successfully updated
59 * else updated failed - reason indicated
60 *
61 */
62int
63uniarp_cache_svc(uip, ip, atm, atmsub, origin)
64 struct uniip *uip;
65 struct in_addr *ip;
66 Atm_addr *atm;
67 Atm_addr *atmsub;
68 u_int origin;
69{
70 struct ip_nif *inp;
71 struct ipvcc *ivp, *inext, *itail;
72 struct uniarp *nouap, *ipuap;
73 char abuf[64];
74
75#ifdef DIAGNOSTIC
76 strncpy(abuf, unisig_addr_print(atmsub), sizeof(abuf));
77 abuf[sizeof(abuf) - 1] = 0;
78 ATM_DEBUG4("cache_svc: ip=%s, atm=(%s,%s), origin=%d\n",
79 inet_ntoa(*ip), unisig_addr_print(atm), abuf, origin);
80#endif
81
82 /*
83 * Get interface info
84 */
85 inp = uip->uip_ipnif;
86
87 /*
88 * Find both cached entry and 'nomap' entries for this data.
89 */
90 UNIARP_LOOKUP(ip->s_addr, ipuap);
91 for (nouap = uniarp_nomaptab; nouap; nouap = nouap->ua_next) {
92 if (ATM_ADDR_EQUAL(atm, &nouap->ua_dstatm) &&
93 ATM_ADDR_EQUAL(atmsub, &nouap->ua_dstatmsub) &&
94 (nouap->ua_intf == uip))
95 break;
96 }
97
98 /*
99 * If there aren't any entries yet, create one
100 */
101 if ((ipuap == NULL) && (nouap == NULL)) {
102 ipuap = (struct uniarp *)atm_allocate(&uniarp_pool);
103 if (ipuap == NULL)
104 return (ENOMEM);
105 ipuap->ua_dstip.s_addr = ip->s_addr;
106 ipuap->ua_dstatm.address_format = T_ATM_ABSENT;
107 ipuap->ua_dstatmsub.address_format = T_ATM_ABSENT;
108 ipuap->ua_intf = uip;
109 UNIARP_ADD(ipuap);
110 }
111
112 /*
113 * If there's no cached mapping, then make the 'nomap' entry
114 * the new cached entry.
115 */
116 if (ipuap == NULL) {
117 UNLINK(nouap, struct uniarp, uniarp_nomaptab, ua_next);
118 nouap->ua_dstip.s_addr = ip->s_addr;
119 ipuap = nouap;
120 nouap = NULL;
121 UNIARP_ADD(ipuap);
122 }
123
124 /*
125 * We need to check the consistency of the new data with any
126 * cached data. So taking the easy case first, if there isn't
127 * an ATM address in the cache then we can skip all these checks.
128 */
129 if (ipuap->ua_dstatm.address_format != T_ATM_ABSENT) {
130 /*
131 * See if the new data conflicts with what's in the cache
132 */
133 if (ATM_ADDR_EQUAL(atm, &ipuap->ua_dstatm) &&
134 ATM_ADDR_EQUAL(atmsub, &ipuap->ua_dstatmsub) &&
135 (uip == ipuap->ua_intf)) {
136 /*
137 * No conflicts here
138 */
139 goto dataok;
140 }
141
142 /*
143 * Data conflict...how we deal with this depends on
144 * the origins of the conflicting data
145 */
146 if (origin == ipuap->ua_origin) {
147 /*
148 * The new data has equal precedence - if there are
149 * any VCCs using this entry, then we reject this
150 * "duplicate IP address" update.
151 */
152 if (ipuap->ua_ivp != NULL) {
153 strncpy(abuf, unisig_addr_print(atmsub),
154 sizeof(abuf));
155 abuf[sizeof(abuf) - 1] = 0;
156 log(LOG_WARNING,
157 "uniarp: duplicate IP address %s from %s,%s\n",
158 inet_ntoa(*ip), unisig_addr_print(atm),
159 abuf);
160 return (EACCES);
161 }
162
163 } else if (origin > ipuap->ua_origin) {
164 /*
165 * New data's origin has higher precedence,
166 * so accept the new mapping and notify IP/ATM
167 * that a mapping change has occurred. IP/ATM will
168 * close any VCC's which aren't waiting for this map.
169 */
170 ipuap->ua_flags |= UAF_LOCKED;
171 for (ivp = ipuap->ua_ivp; ivp; ivp = inext) {
172 inext = ivp->iv_arpnext;
173 (*inp->inf_arpnotify)(ivp, MAP_CHANGED);
174 }
175 ipuap->ua_flags &= ~UAF_LOCKED;
176 } else {
177 /*
178 * New data is of lesser origin precedence,
179 * so we just reject the update attempt.
180 */
181 return (EACCES);
182 }
183
184 strncpy(abuf, unisig_addr_print(atmsub), sizeof(abuf));
185 abuf[sizeof(abuf) - 1] = 0;
186 log(LOG_WARNING,
187 "uniarp: ATM address for %s changed to %s,%s\n",
188 inet_ntoa(*ip), unisig_addr_print(atm), abuf);
189 }
190
191 /*
192 * Update the cache entry with the new data
193 */
194 ATM_ADDR_COPY(atm, &ipuap->ua_dstatm);
195 ATM_ADDR_COPY(atmsub, &ipuap->ua_dstatmsub);
196 ipuap->ua_intf = uip;
197
198dataok:
199 /*
200 * Update cache data origin
201 */
202 ipuap->ua_origin = MAX(ipuap->ua_origin, origin);
203
204 /*
205 * Ok, now act on this new/updated cache data
206 */
207 ipuap->ua_flags |= UAF_LOCKED;
208
209 /*
210 * Save pointer to last VCC currently on cached entry chain that
211 * will need to be notified of the map becoming valid
212 */
213 itail = NULL;
214 if ((ipuap->ua_flags & UAF_VALID) == 0) {
215
216 for (itail = ipuap->ua_ivp; itail && itail->iv_arpnext;
217 itail = itail->iv_arpnext) {
218 }
219 }
220
221 /*
222 * If there was a 'nomap' entry for this mapping, then we need to
223 * announce the new mapping to them first.
224 */
225 if (nouap) {
226
227 /*
228 * Move the VCCs from this entry to the cache entry and
229 * let them know there's a valid mapping now
230 */
231 for (ivp = nouap->ua_ivp; ivp; ivp = inext) {
232 inext = ivp->iv_arpnext;
233
234 UNLINK(ivp, struct ipvcc, nouap->ua_ivp, iv_arpnext);
235
236 LINK2TAIL(ivp, struct ipvcc, ipuap->ua_ivp, iv_arpnext);
237 ivp->iv_arpent = (struct arpmap *)ipuap;
238
239 (*inp->inf_arpnotify)(ivp, MAP_VALID);
240 }
241
242 /*
243 * Unlink and free the 'nomap' entry
244 */
245 UNLINK(nouap, struct uniarp, uniarp_nomaptab, ua_next);
246 UNIARP_CANCEL(nouap);
247 atm_free((caddr_t)nouap);
248 }
249
250 /*
251 * Now, if this entry wasn't valid, notify the remaining VCCs
252 */
253 if (itail) {
254
255 for (ivp = ipuap->ua_ivp; ivp; ivp = inext) {
256 inext = ivp->iv_arpnext;
257 (*inp->inf_arpnotify)(ivp, MAP_VALID);
258 if (ivp == itail)
259 break;
260 }
261 }
262 ipuap->ua_flags &= ~UAF_LOCKED;
263
264 /*
265 * We now have a valid cache entry, so cancel any retry timer
266 * and reset the aging timeout
267 */
268 UNIARP_CANCEL(ipuap);
269 if ((ipuap->ua_origin == UAO_REGISTER) && (origin != UAO_REGISTER)) {
270 if (((ipuap->ua_flags & UAF_VALID) == 0) ||
271 (ipuap->ua_aging <=
272 UNIARP_SERVER_AGE - UNIARP_MIN_REFRESH)) {
273 ipuap->ua_flags |= UAF_REFRESH;
274 ipuap->ua_aging = UNIARP_SERVER_AGE;
275 ipuap->ua_retry = UNIARP_SERVER_RETRY;
276 }
277 } else {
278 if (uip->uip_arpstate == UIAS_SERVER_ACTIVE) {
279 ipuap->ua_aging = UNIARP_SERVER_AGE;
280 ipuap->ua_retry = UNIARP_SERVER_RETRY;
281 } else {
282 ipuap->ua_aging = UNIARP_CLIENT_AGE;
283 ipuap->ua_retry = UNIARP_CLIENT_RETRY;
284 }
285 ipuap->ua_flags |= UAF_REFRESH;
286 }
287 ipuap->ua_flags |= UAF_VALID;
288 ipuap->ua_flags &= ~UAF_USED;
289 return (0);
290}
291
292
293/*
294 * Process ARP data from a PVC
295 *
296 * The arp table cache is never updated with PVC information.
297 *
298 * Called at splnet.
299 *
300 * Arguments:
301 * ivp pointer to input PVC's IPVCC control block
302 * ip pointer to IP address structure
303 * atm pointer to ATM address structure
304 * atmsub pointer to ATM subaddress structure
305 *
306 * Returns:
307 * none
308 *
309 */
310void
311uniarp_cache_pvc(ivp, ip, atm, atmsub)
312 struct ipvcc *ivp;
313 struct in_addr *ip;
314 Atm_addr *atm;
315 Atm_addr *atmsub;
316{
317 struct ip_nif *inp;
318 struct uniarp *uap;
319
320#ifdef DIAGNOSTIC
321 char buf[64];
322 int vpi = 0, vci = 0;
323
324 if ((ivp->iv_conn) && (ivp->iv_conn->co_connvc)) {
325 vpi = ivp->iv_conn->co_connvc->cvc_vcc->vc_vpi;
326 vci = ivp->iv_conn->co_connvc->cvc_vcc->vc_vci;
327 }
328 strncpy(buf, unisig_addr_print(atmsub), sizeof(buf));
329 buf[sizeof(buf) - 1] = 0;
330 ATM_DEBUG5("cache_pvc: vcc=(%d,%d), ip=%s, atm=(%s,%s)\n",
331 vpi, vci, inet_ntoa(*ip), unisig_addr_print(atm), buf);
332#endif
333
334 /*
335 * Get PVC info
336 */
337 inp = ivp->iv_ipnif;
338 uap = (struct uniarp *)ivp->iv_arpent;
339
340 /*
341 * See if IP address for PVC has changed
342 */
343 if (uap->ua_dstip.s_addr != ip->s_addr) {
344 if (uap->ua_dstip.s_addr != 0)
345 (*inp->inf_arpnotify)(ivp, MAP_CHANGED);
346 uap->ua_dstip.s_addr = ip->s_addr;
347 }
348
349 /*
350 * Let IP/ATM know if address has become valid
351 */
352 if ((uap->ua_flags & UAF_VALID) == 0)
353 (*inp->inf_arpnotify)(ivp, MAP_VALID);
354 uap->ua_flags |= UAF_VALID;
355 uap->ua_aging = UNIARP_CLIENT_AGE;
356 uap->ua_retry = UNIARP_CLIENT_RETRY;
357
358 /*
359 * Save ATM addresses just for debugging
360 */
361 ATM_ADDR_COPY(atm, &uap->ua_dstatm);
362 ATM_ADDR_COPY(atmsub, &uap->ua_dstatmsub);
363
364 return;
365}
366
367
368/*
369 * Validate IP address
370 *
371 * Arguments:
372 * uip pointer to UNI IP interface
373 * ip pointer to IP address structure
374 * origin source of arp information
375 *
376 * Returns:
377 * 0 IP address is acceptable
378 * else invalid IP address
379 *
380 */
381int
382uniarp_validate_ip(uip, ip, origin)
383 struct uniip *uip;
384 struct in_addr *ip;
385 u_int origin;
386{
387 struct uniarp_prf *upp;
388 int i;
389
390
391 /*
392 * Can't be multicast or broadcast address
393 */
394 if (IN_MULTICAST(ntohl(ip->s_addr)) ||
395#if (defined(BSD) && (BSD >= 199306))
396 in_broadcast(*ip, &uip->uip_ipnif->inf_nif->nif_if))
397#else
398 in_broadcast(*ip))
399#endif
400 return (1);
401
402 /*
403 * For ATMARP registration information (including SCSP data),
404 * the address must be allowed by the interface's prefix list.
405 */
406 if ((origin == UAO_REGISTER) || (origin == UAO_SCSP)) {
407 for (i = uip->uip_nprefix, upp = uip->uip_prefix;
408 i; i--, upp++) {
409 if ((ip->s_addr & upp->upf_mask.s_addr) ==
410 upp->upf_addr.s_addr)
411 break;
412 }
413 if (i == 0)
414 return (1);
415 }
416
417 return (0);
418}
419