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 $
27 * @(#) $DragonFly: src/sys/netproto/atm/uni/uniarp_cache.c,v 1.3 2003/08/07 21:17:35 dillon 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 "unisig_var.h"
43 #include "uniip_var.h"
46 * Add data to the arp table cache
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
58 * 0 cache successfully updated
59 * else updated failed - reason indicated
63 uniarp_cache_svc(uip, ip, atm, atmsub, origin)
71 struct ipvcc *ivp, *inext, *itail;
72 struct uniarp *nouap, *ipuap;
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);
88 * Find both cached entry and 'nomap' entries for this data.
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))
99 * If there aren't any entries yet, create one
101 if ((ipuap == NULL) && (nouap == NULL)) {
102 ipuap = (struct uniarp *)atm_allocate(&uniarp_pool);
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;
113 * If there's no cached mapping, then make the 'nomap' entry
114 * the new cached entry.
117 UNLINK(nouap, struct uniarp, uniarp_nomaptab, ua_next);
118 nouap->ua_dstip.s_addr = ip->s_addr;
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.
129 if (ipuap->ua_dstatm.address_format != T_ATM_ABSENT) {
131 * See if the new data conflicts with what's in the cache
133 if (ATM_ADDR_EQUAL(atm, &ipuap->ua_dstatm) &&
134 ATM_ADDR_EQUAL(atmsub, &ipuap->ua_dstatmsub) &&
135 (uip == ipuap->ua_intf)) {
143 * Data conflict...how we deal with this depends on
144 * the origins of the conflicting data
146 if (origin == ipuap->ua_origin) {
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.
152 if (ipuap->ua_ivp != NULL) {
153 strncpy(abuf, unisig_addr_print(atmsub),
155 abuf[sizeof(abuf) - 1] = 0;
157 "uniarp: duplicate IP address %s from %s,%s\n",
158 inet_ntoa(*ip), unisig_addr_print(atm),
163 } else if (origin > ipuap->ua_origin) {
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.
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);
175 ipuap->ua_flags &= ~UAF_LOCKED;
178 * New data is of lesser origin precedence,
179 * so we just reject the update attempt.
184 strncpy(abuf, unisig_addr_print(atmsub), sizeof(abuf));
185 abuf[sizeof(abuf) - 1] = 0;
187 "uniarp: ATM address for %s changed to %s,%s\n",
188 inet_ntoa(*ip), unisig_addr_print(atm), abuf);
192 * Update the cache entry with the new data
194 ATM_ADDR_COPY(atm, &ipuap->ua_dstatm);
195 ATM_ADDR_COPY(atmsub, &ipuap->ua_dstatmsub);
196 ipuap->ua_intf = uip;
200 * Update cache data origin
202 ipuap->ua_origin = MAX(ipuap->ua_origin, origin);
205 * Ok, now act on this new/updated cache data
207 ipuap->ua_flags |= UAF_LOCKED;
210 * Save pointer to last VCC currently on cached entry chain that
211 * will need to be notified of the map becoming valid
214 if ((ipuap->ua_flags & UAF_VALID) == 0) {
216 for (itail = ipuap->ua_ivp; itail && itail->iv_arpnext;
217 itail = itail->iv_arpnext) {
222 * If there was a 'nomap' entry for this mapping, then we need to
223 * announce the new mapping to them first.
228 * Move the VCCs from this entry to the cache entry and
229 * let them know there's a valid mapping now
231 for (ivp = nouap->ua_ivp; ivp; ivp = inext) {
232 inext = ivp->iv_arpnext;
234 UNLINK(ivp, struct ipvcc, nouap->ua_ivp, iv_arpnext);
236 LINK2TAIL(ivp, struct ipvcc, ipuap->ua_ivp, iv_arpnext);
237 ivp->iv_arpent = (struct arpmap *)ipuap;
239 (*inp->inf_arpnotify)(ivp, MAP_VALID);
243 * Unlink and free the 'nomap' entry
245 UNLINK(nouap, struct uniarp, uniarp_nomaptab, ua_next);
246 UNIARP_CANCEL(nouap);
247 atm_free((caddr_t)nouap);
251 * Now, if this entry wasn't valid, notify the remaining VCCs
255 for (ivp = ipuap->ua_ivp; ivp; ivp = inext) {
256 inext = ivp->iv_arpnext;
257 (*inp->inf_arpnotify)(ivp, MAP_VALID);
262 ipuap->ua_flags &= ~UAF_LOCKED;
265 * We now have a valid cache entry, so cancel any retry timer
266 * and reset the aging timeout
268 UNIARP_CANCEL(ipuap);
269 if ((ipuap->ua_origin == UAO_REGISTER) && (origin != UAO_REGISTER)) {
270 if (((ipuap->ua_flags & UAF_VALID) == 0) ||
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;
278 if (uip->uip_arpstate == UIAS_SERVER_ACTIVE) {
279 ipuap->ua_aging = UNIARP_SERVER_AGE;
280 ipuap->ua_retry = UNIARP_SERVER_RETRY;
282 ipuap->ua_aging = UNIARP_CLIENT_AGE;
283 ipuap->ua_retry = UNIARP_CLIENT_RETRY;
285 ipuap->ua_flags |= UAF_REFRESH;
287 ipuap->ua_flags |= UAF_VALID;
288 ipuap->ua_flags &= ~UAF_USED;
294 * Process ARP data from a PVC
296 * The arp table cache is never updated with PVC information.
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
311 uniarp_cache_pvc(ivp, ip, atm, atmsub)
322 int vpi = 0, vci = 0;
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;
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);
338 uap = (struct uniarp *)ivp->iv_arpent;
341 * See if IP address for PVC has changed
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;
350 * Let IP/ATM know if address has become valid
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;
359 * Save ATM addresses just for debugging
361 ATM_ADDR_COPY(atm, &uap->ua_dstatm);
362 ATM_ADDR_COPY(atmsub, &uap->ua_dstatmsub);
369 * Validate IP address
372 * uip pointer to UNI IP interface
373 * ip pointer to IP address structure
374 * origin source of arp information
377 * 0 IP address is acceptable
378 * else invalid IP address
382 uniarp_validate_ip(uip, ip, origin)
387 struct uniarp_prf *upp;
392 * Can't be multicast or broadcast address
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))
403 * For ATMARP registration information (including SCSP data),
404 * the address must be allowed by the interface's prefix list.
406 if ((origin == UAO_REGISTER) || (origin == UAO_SCSP)) {
407 for (i = uip->uip_nprefix, upp = uip->uip_prefix;
409 if ((ip->s_addr & upp->upf_mask.s_addr) ==
410 upp->upf_addr.s_addr)