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.6 2006/01/14 13:36:39 swildner Exp $
31 * ATM Forum UNI Support
32 * ---------------------
34 * UNI ATMARP support (RFC1577) - ARP cache processing
38 #include <netproto/atm/kern_include.h>
40 #include <netproto/atm/ipatm/ipatm_var.h>
41 #include <netproto/atm/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(struct uniip *uip, struct in_addr *ip, Atm_addr *atm,
64 Atm_addr *atmsub, u_int origin)
67 struct ipvcc *ivp, *inext, *itail;
68 struct uniarp *nouap, *ipuap;
72 strncpy(abuf, unisig_addr_print(atmsub), sizeof(abuf));
73 abuf[sizeof(abuf) - 1] = 0;
74 ATM_DEBUG4("cache_svc: ip=%s, atm=(%s,%s), origin=%d\n",
75 inet_ntoa(*ip), unisig_addr_print(atm), abuf, origin);
84 * Find both cached entry and 'nomap' entries for this data.
86 UNIARP_LOOKUP(ip->s_addr, ipuap);
87 for (nouap = uniarp_nomaptab; nouap; nouap = nouap->ua_next) {
88 if (ATM_ADDR_EQUAL(atm, &nouap->ua_dstatm) &&
89 ATM_ADDR_EQUAL(atmsub, &nouap->ua_dstatmsub) &&
90 (nouap->ua_intf == uip))
95 * If there aren't any entries yet, create one
97 if ((ipuap == NULL) && (nouap == NULL)) {
98 ipuap = (struct uniarp *)atm_allocate(&uniarp_pool);
101 ipuap->ua_dstip.s_addr = ip->s_addr;
102 ipuap->ua_dstatm.address_format = T_ATM_ABSENT;
103 ipuap->ua_dstatmsub.address_format = T_ATM_ABSENT;
104 ipuap->ua_intf = uip;
109 * If there's no cached mapping, then make the 'nomap' entry
110 * the new cached entry.
113 UNLINK(nouap, struct uniarp, uniarp_nomaptab, ua_next);
114 nouap->ua_dstip.s_addr = ip->s_addr;
121 * We need to check the consistency of the new data with any
122 * cached data. So taking the easy case first, if there isn't
123 * an ATM address in the cache then we can skip all these checks.
125 if (ipuap->ua_dstatm.address_format != T_ATM_ABSENT) {
127 * See if the new data conflicts with what's in the cache
129 if (ATM_ADDR_EQUAL(atm, &ipuap->ua_dstatm) &&
130 ATM_ADDR_EQUAL(atmsub, &ipuap->ua_dstatmsub) &&
131 (uip == ipuap->ua_intf)) {
139 * Data conflict...how we deal with this depends on
140 * the origins of the conflicting data
142 if (origin == ipuap->ua_origin) {
144 * The new data has equal precedence - if there are
145 * any VCCs using this entry, then we reject this
146 * "duplicate IP address" update.
148 if (ipuap->ua_ivp != NULL) {
149 strncpy(abuf, unisig_addr_print(atmsub),
151 abuf[sizeof(abuf) - 1] = 0;
153 "uniarp: duplicate IP address %s from %s,%s\n",
154 inet_ntoa(*ip), unisig_addr_print(atm),
159 } else if (origin > ipuap->ua_origin) {
161 * New data's origin has higher precedence,
162 * so accept the new mapping and notify IP/ATM
163 * that a mapping change has occurred. IP/ATM will
164 * close any VCC's which aren't waiting for this map.
166 ipuap->ua_flags |= UAF_LOCKED;
167 for (ivp = ipuap->ua_ivp; ivp; ivp = inext) {
168 inext = ivp->iv_arpnext;
169 (*inp->inf_arpnotify)(ivp, MAP_CHANGED);
171 ipuap->ua_flags &= ~UAF_LOCKED;
174 * New data is of lesser origin precedence,
175 * so we just reject the update attempt.
180 strncpy(abuf, unisig_addr_print(atmsub), sizeof(abuf));
181 abuf[sizeof(abuf) - 1] = 0;
183 "uniarp: ATM address for %s changed to %s,%s\n",
184 inet_ntoa(*ip), unisig_addr_print(atm), abuf);
188 * Update the cache entry with the new data
190 ATM_ADDR_COPY(atm, &ipuap->ua_dstatm);
191 ATM_ADDR_COPY(atmsub, &ipuap->ua_dstatmsub);
192 ipuap->ua_intf = uip;
196 * Update cache data origin
198 ipuap->ua_origin = MAX(ipuap->ua_origin, origin);
201 * Ok, now act on this new/updated cache data
203 ipuap->ua_flags |= UAF_LOCKED;
206 * Save pointer to last VCC currently on cached entry chain that
207 * will need to be notified of the map becoming valid
210 if ((ipuap->ua_flags & UAF_VALID) == 0) {
212 for (itail = ipuap->ua_ivp; itail && itail->iv_arpnext;
213 itail = itail->iv_arpnext) {
218 * If there was a 'nomap' entry for this mapping, then we need to
219 * announce the new mapping to them first.
224 * Move the VCCs from this entry to the cache entry and
225 * let them know there's a valid mapping now
227 for (ivp = nouap->ua_ivp; ivp; ivp = inext) {
228 inext = ivp->iv_arpnext;
230 UNLINK(ivp, struct ipvcc, nouap->ua_ivp, iv_arpnext);
232 LINK2TAIL(ivp, struct ipvcc, ipuap->ua_ivp, iv_arpnext);
233 ivp->iv_arpent = (struct arpmap *)ipuap;
235 (*inp->inf_arpnotify)(ivp, MAP_VALID);
239 * Unlink and free the 'nomap' entry
241 UNLINK(nouap, struct uniarp, uniarp_nomaptab, ua_next);
242 UNIARP_CANCEL(nouap);
243 atm_free((caddr_t)nouap);
247 * Now, if this entry wasn't valid, notify the remaining VCCs
251 for (ivp = ipuap->ua_ivp; ivp; ivp = inext) {
252 inext = ivp->iv_arpnext;
253 (*inp->inf_arpnotify)(ivp, MAP_VALID);
258 ipuap->ua_flags &= ~UAF_LOCKED;
261 * We now have a valid cache entry, so cancel any retry timer
262 * and reset the aging timeout
264 UNIARP_CANCEL(ipuap);
265 if ((ipuap->ua_origin == UAO_REGISTER) && (origin != UAO_REGISTER)) {
266 if (((ipuap->ua_flags & UAF_VALID) == 0) ||
268 UNIARP_SERVER_AGE - UNIARP_MIN_REFRESH)) {
269 ipuap->ua_flags |= UAF_REFRESH;
270 ipuap->ua_aging = UNIARP_SERVER_AGE;
271 ipuap->ua_retry = UNIARP_SERVER_RETRY;
274 if (uip->uip_arpstate == UIAS_SERVER_ACTIVE) {
275 ipuap->ua_aging = UNIARP_SERVER_AGE;
276 ipuap->ua_retry = UNIARP_SERVER_RETRY;
278 ipuap->ua_aging = UNIARP_CLIENT_AGE;
279 ipuap->ua_retry = UNIARP_CLIENT_RETRY;
281 ipuap->ua_flags |= UAF_REFRESH;
283 ipuap->ua_flags |= UAF_VALID;
284 ipuap->ua_flags &= ~UAF_USED;
290 * Process ARP data from a PVC
292 * The arp table cache is never updated with PVC information.
297 * ivp pointer to input PVC's IPVCC control block
298 * ip pointer to IP address structure
299 * atm pointer to ATM address structure
300 * atmsub pointer to ATM subaddress structure
307 uniarp_cache_pvc(struct ipvcc *ivp, struct in_addr *ip, Atm_addr *atm,
315 int vpi = 0, vci = 0;
317 if ((ivp->iv_conn) && (ivp->iv_conn->co_connvc)) {
318 vpi = ivp->iv_conn->co_connvc->cvc_vcc->vc_vpi;
319 vci = ivp->iv_conn->co_connvc->cvc_vcc->vc_vci;
321 strncpy(buf, unisig_addr_print(atmsub), sizeof(buf));
322 buf[sizeof(buf) - 1] = 0;
323 ATM_DEBUG5("cache_pvc: vcc=(%d,%d), ip=%s, atm=(%s,%s)\n",
324 vpi, vci, inet_ntoa(*ip), unisig_addr_print(atm), buf);
331 uap = (struct uniarp *)ivp->iv_arpent;
334 * See if IP address for PVC has changed
336 if (uap->ua_dstip.s_addr != ip->s_addr) {
337 if (uap->ua_dstip.s_addr != 0)
338 (*inp->inf_arpnotify)(ivp, MAP_CHANGED);
339 uap->ua_dstip.s_addr = ip->s_addr;
343 * Let IP/ATM know if address has become valid
345 if ((uap->ua_flags & UAF_VALID) == 0)
346 (*inp->inf_arpnotify)(ivp, MAP_VALID);
347 uap->ua_flags |= UAF_VALID;
348 uap->ua_aging = UNIARP_CLIENT_AGE;
349 uap->ua_retry = UNIARP_CLIENT_RETRY;
352 * Save ATM addresses just for debugging
354 ATM_ADDR_COPY(atm, &uap->ua_dstatm);
355 ATM_ADDR_COPY(atmsub, &uap->ua_dstatmsub);
362 * Validate IP address
365 * uip pointer to UNI IP interface
366 * ip pointer to IP address structure
367 * origin source of arp information
370 * 0 IP address is acceptable
371 * else invalid IP address
375 uniarp_validate_ip(struct uniip *uip, struct in_addr *ip, u_int origin)
377 struct uniarp_prf *upp;
382 * Can't be multicast or broadcast address
384 if (IN_MULTICAST(ntohl(ip->s_addr)) ||
385 in_broadcast(*ip, &uip->uip_ipnif->inf_nif->nif_if))
389 * For ATMARP registration information (including SCSP data),
390 * the address must be allowed by the interface's prefix list.
392 if ((origin == UAO_REGISTER) || (origin == UAO_SCSP)) {
393 for (i = uip->uip_nprefix, upp = uip->uip_prefix;
395 if ((ip->s_addr & upp->upf_mask.s_addr) ==
396 upp->upf_addr.s_addr)