3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
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.
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.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/netatm/uni/uniarp_cache.c,v 1.4 1999/08/28 00:49:02 peter Exp $
31 * ATM Forum UNI Support
32 * ---------------------
34 * UNI ATMARP support (RFC1577) - ARP cache processing
38 #include <netatm/kern_include.h>
40 #include <netatm/ipatm/ipatm_var.h>
41 #include <netatm/ipatm/ipatm_serv.h>
42 #include <netatm/uni/unisig_var.h>
43 #include <netatm/uni/uniip_var.h>
46 __RCSID("@(#) $FreeBSD: src/sys/netatm/uni/uniarp_cache.c,v 1.4 1999/08/28 00:49:02 peter Exp $");
51 * Add data to the arp table cache
56 * uip pointer to UNI IP interface
57 * ip pointer to IP address structure
58 * atm pointer to ATM address structure
59 * atmsub pointer to ATM subaddress structure
60 * origin source of arp information
63 * 0 cache successfully updated
64 * else updated failed - reason indicated
68 uniarp_cache_svc(uip, ip, atm, atmsub, origin)
76 struct ipvcc *ivp, *inext, *itail;
77 struct uniarp *nouap, *ipuap;
81 strncpy(abuf, unisig_addr_print(atmsub), sizeof(abuf));
82 abuf[sizeof(abuf) - 1] = 0;
83 ATM_DEBUG4("cache_svc: ip=%s, atm=(%s,%s), origin=%d\n",
84 inet_ntoa(*ip), unisig_addr_print(atm), abuf, origin);
93 * Find both cached entry and 'nomap' entries for this data.
95 UNIARP_LOOKUP(ip->s_addr, ipuap);
96 for (nouap = uniarp_nomaptab; nouap; nouap = nouap->ua_next) {
97 if (ATM_ADDR_EQUAL(atm, &nouap->ua_dstatm) &&
98 ATM_ADDR_EQUAL(atmsub, &nouap->ua_dstatmsub) &&
99 (nouap->ua_intf == uip))
104 * If there aren't any entries yet, create one
106 if ((ipuap == NULL) && (nouap == NULL)) {
107 ipuap = (struct uniarp *)atm_allocate(&uniarp_pool);
110 ipuap->ua_dstip.s_addr = ip->s_addr;
111 ipuap->ua_dstatm.address_format = T_ATM_ABSENT;
112 ipuap->ua_dstatmsub.address_format = T_ATM_ABSENT;
113 ipuap->ua_intf = uip;
118 * If there's no cached mapping, then make the 'nomap' entry
119 * the new cached entry.
122 UNLINK(nouap, struct uniarp, uniarp_nomaptab, ua_next);
123 nouap->ua_dstip.s_addr = ip->s_addr;
130 * We need to check the consistency of the new data with any
131 * cached data. So taking the easy case first, if there isn't
132 * an ATM address in the cache then we can skip all these checks.
134 if (ipuap->ua_dstatm.address_format != T_ATM_ABSENT) {
136 * See if the new data conflicts with what's in the cache
138 if (ATM_ADDR_EQUAL(atm, &ipuap->ua_dstatm) &&
139 ATM_ADDR_EQUAL(atmsub, &ipuap->ua_dstatmsub) &&
140 (uip == ipuap->ua_intf)) {
148 * Data conflict...how we deal with this depends on
149 * the origins of the conflicting data
151 if (origin == ipuap->ua_origin) {
153 * The new data has equal precedence - if there are
154 * any VCCs using this entry, then we reject this
155 * "duplicate IP address" update.
157 if (ipuap->ua_ivp != NULL) {
158 strncpy(abuf, unisig_addr_print(atmsub),
160 abuf[sizeof(abuf) - 1] = 0;
162 "uniarp: duplicate IP address %s from %s,%s\n",
163 inet_ntoa(*ip), unisig_addr_print(atm),
168 } else if (origin > ipuap->ua_origin) {
170 * New data's origin has higher precedence,
171 * so accept the new mapping and notify IP/ATM
172 * that a mapping change has occurred. IP/ATM will
173 * close any VCC's which aren't waiting for this map.
175 ipuap->ua_flags |= UAF_LOCKED;
176 for (ivp = ipuap->ua_ivp; ivp; ivp = inext) {
177 inext = ivp->iv_arpnext;
178 (*inp->inf_arpnotify)(ivp, MAP_CHANGED);
180 ipuap->ua_flags &= ~UAF_LOCKED;
183 * New data is of lesser origin precedence,
184 * so we just reject the update attempt.
189 strncpy(abuf, unisig_addr_print(atmsub), sizeof(abuf));
190 abuf[sizeof(abuf) - 1] = 0;
192 "uniarp: ATM address for %s changed to %s,%s\n",
193 inet_ntoa(*ip), unisig_addr_print(atm), abuf);
197 * Update the cache entry with the new data
199 ATM_ADDR_COPY(atm, &ipuap->ua_dstatm);
200 ATM_ADDR_COPY(atmsub, &ipuap->ua_dstatmsub);
201 ipuap->ua_intf = uip;
205 * Update cache data origin
207 ipuap->ua_origin = MAX(ipuap->ua_origin, origin);
210 * Ok, now act on this new/updated cache data
212 ipuap->ua_flags |= UAF_LOCKED;
215 * Save pointer to last VCC currently on cached entry chain that
216 * will need to be notified of the map becoming valid
219 if ((ipuap->ua_flags & UAF_VALID) == 0) {
221 for (itail = ipuap->ua_ivp; itail && itail->iv_arpnext;
222 itail = itail->iv_arpnext) {
227 * If there was a 'nomap' entry for this mapping, then we need to
228 * announce the new mapping to them first.
233 * Move the VCCs from this entry to the cache entry and
234 * let them know there's a valid mapping now
236 for (ivp = nouap->ua_ivp; ivp; ivp = inext) {
237 inext = ivp->iv_arpnext;
239 UNLINK(ivp, struct ipvcc, nouap->ua_ivp, iv_arpnext);
241 LINK2TAIL(ivp, struct ipvcc, ipuap->ua_ivp, iv_arpnext);
242 ivp->iv_arpent = (struct arpmap *)ipuap;
244 (*inp->inf_arpnotify)(ivp, MAP_VALID);
248 * Unlink and free the 'nomap' entry
250 UNLINK(nouap, struct uniarp, uniarp_nomaptab, ua_next);
251 UNIARP_CANCEL(nouap);
252 atm_free((caddr_t)nouap);
256 * Now, if this entry wasn't valid, notify the remaining VCCs
260 for (ivp = ipuap->ua_ivp; ivp; ivp = inext) {
261 inext = ivp->iv_arpnext;
262 (*inp->inf_arpnotify)(ivp, MAP_VALID);
267 ipuap->ua_flags &= ~UAF_LOCKED;
270 * We now have a valid cache entry, so cancel any retry timer
271 * and reset the aging timeout
273 UNIARP_CANCEL(ipuap);
274 if ((ipuap->ua_origin == UAO_REGISTER) && (origin != UAO_REGISTER)) {
275 if (((ipuap->ua_flags & UAF_VALID) == 0) ||
277 UNIARP_SERVER_AGE - UNIARP_MIN_REFRESH)) {
278 ipuap->ua_flags |= UAF_REFRESH;
279 ipuap->ua_aging = UNIARP_SERVER_AGE;
280 ipuap->ua_retry = UNIARP_SERVER_RETRY;
283 if (uip->uip_arpstate == UIAS_SERVER_ACTIVE) {
284 ipuap->ua_aging = UNIARP_SERVER_AGE;
285 ipuap->ua_retry = UNIARP_SERVER_RETRY;
287 ipuap->ua_aging = UNIARP_CLIENT_AGE;
288 ipuap->ua_retry = UNIARP_CLIENT_RETRY;
290 ipuap->ua_flags |= UAF_REFRESH;
292 ipuap->ua_flags |= UAF_VALID;
293 ipuap->ua_flags &= ~UAF_USED;
299 * Process ARP data from a PVC
301 * The arp table cache is never updated with PVC information.
306 * ivp pointer to input PVC's IPVCC control block
307 * ip pointer to IP address structure
308 * atm pointer to ATM address structure
309 * atmsub pointer to ATM subaddress structure
316 uniarp_cache_pvc(ivp, ip, atm, atmsub)
327 int vpi = 0, vci = 0;
329 if ((ivp->iv_conn) && (ivp->iv_conn->co_connvc)) {
330 vpi = ivp->iv_conn->co_connvc->cvc_vcc->vc_vpi;
331 vci = ivp->iv_conn->co_connvc->cvc_vcc->vc_vci;
333 strncpy(buf, unisig_addr_print(atmsub), sizeof(buf));
334 buf[sizeof(buf) - 1] = 0;
335 ATM_DEBUG5("cache_pvc: vcc=(%d,%d), ip=%s, atm=(%s,%s)\n",
336 vpi, vci, inet_ntoa(*ip), unisig_addr_print(atm), buf);
343 uap = (struct uniarp *)ivp->iv_arpent;
346 * See if IP address for PVC has changed
348 if (uap->ua_dstip.s_addr != ip->s_addr) {
349 if (uap->ua_dstip.s_addr != 0)
350 (*inp->inf_arpnotify)(ivp, MAP_CHANGED);
351 uap->ua_dstip.s_addr = ip->s_addr;
355 * Let IP/ATM know if address has become valid
357 if ((uap->ua_flags & UAF_VALID) == 0)
358 (*inp->inf_arpnotify)(ivp, MAP_VALID);
359 uap->ua_flags |= UAF_VALID;
360 uap->ua_aging = UNIARP_CLIENT_AGE;
361 uap->ua_retry = UNIARP_CLIENT_RETRY;
364 * Save ATM addresses just for debugging
366 ATM_ADDR_COPY(atm, &uap->ua_dstatm);
367 ATM_ADDR_COPY(atmsub, &uap->ua_dstatmsub);
374 * Validate IP address
377 * uip pointer to UNI IP interface
378 * ip pointer to IP address structure
379 * origin source of arp information
382 * 0 IP address is acceptable
383 * else invalid IP address
387 uniarp_validate_ip(uip, ip, origin)
392 struct uniarp_prf *upp;
397 * Can't be multicast or broadcast address
399 if (IN_MULTICAST(ntohl(ip->s_addr)) ||
400 #if (defined(BSD) && (BSD >= 199306))
401 in_broadcast(*ip, &uip->uip_ipnif->inf_nif->nif_if))
408 * For ATMARP registration information (including SCSP data),
409 * the address must be allowed by the interface's prefix list.
411 if ((origin == UAO_REGISTER) || (origin == UAO_SCSP)) {
412 for (i = uip->uip_nprefix, upp = uip->uip_prefix;
414 if ((ip->s_addr & upp->upf_mask.s_addr) ==
415 upp->upf_addr.s_addr)