2 * ===================================
3 * HARP | Host ATM Research Platform
4 * ===================================
7 * This Host ATM Research Platform ("HARP") file (the "Software") is
8 * made available by Network Computing Services, Inc. ("NetworkCS")
9 * "AS IS". NetworkCS does not provide maintenance, improvements or
10 * support of any kind.
12 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
13 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
14 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
15 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
16 * In no event shall NetworkCS be responsible for any damages, including
17 * but not limited to consequential damages, arising from or relating to
18 * any use of the Software or related support.
20 * Copyright 1994-1998 Network Computing Services, Inc.
22 * Copies of this Software may be made, however, the above copyright
23 * notice must be reproduced on all copies.
27 * ATM Forum UNI Support
28 * ---------------------
30 * UNI ATMARP support (RFC1577) - ARP cache processing
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/types.h>
39 #include <sys/errno.h>
41 #include <sys/socket.h>
42 #include <sys/socketvar.h>
43 #include <sys/syslog.h>
45 #include <netinet/in.h>
46 #include <netatm/port.h>
47 #include <netatm/queue.h>
48 #include <netatm/atm.h>
49 #include <netatm/atm_sys.h>
50 #include <netatm/atm_sap.h>
51 #include <netatm/atm_cm.h>
52 #include <netatm/atm_if.h>
53 #include <netatm/atm_vc.h>
54 #include <netatm/atm_ioctl.h>
55 #include <netatm/atm_sigmgr.h>
56 #include <netatm/atm_stack.h>
57 #include <netatm/atm_pcb.h>
58 #include <netatm/atm_var.h>
60 #include <netatm/ipatm/ipatm_var.h>
61 #include <netatm/ipatm/ipatm_serv.h>
62 #include <netatm/uni/unisig_var.h>
63 #include <netatm/uni/uniip_var.h>
66 * Add data to the arp table cache
71 * uip pointer to UNI IP interface
72 * ip pointer to IP address structure
73 * atm pointer to ATM address structure
74 * atmsub pointer to ATM subaddress structure
75 * origin source of arp information
78 * 0 cache successfully updated
79 * else updated failed - reason indicated
83 uniarp_cache_svc(uip, ip, atm, atmsub, origin)
91 struct ipvcc *ivp, *inext, *itail;
92 struct uniarp *nouap, *ipuap;
96 strncpy(abuf, unisig_addr_print(atmsub), sizeof(abuf));
97 abuf[sizeof(abuf) - 1] = 0;
98 ATM_DEBUG4("cache_svc: ip=%s, atm=(%s,%s), origin=%d\n",
99 inet_ntoa(*ip), unisig_addr_print(atm), abuf, origin);
105 inp = uip->uip_ipnif;
108 * Find both cached entry and 'nomap' entries for this data.
110 UNIARP_LOOKUP(ip->s_addr, ipuap);
111 for (nouap = uniarp_nomaptab; nouap; nouap = nouap->ua_next) {
112 if (ATM_ADDR_EQUAL(atm, &nouap->ua_dstatm) &&
113 ATM_ADDR_EQUAL(atmsub, &nouap->ua_dstatmsub) &&
114 (nouap->ua_intf == uip))
119 * If there aren't any entries yet, create one
120 * May be called from netisr - don't wait.
122 if ((ipuap == NULL) && (nouap == NULL)) {
123 ipuap = uma_zalloc(uniarp_zone, M_NOWAIT);
126 ipuap->ua_dstip.s_addr = ip->s_addr;
127 ipuap->ua_dstatm.address_format = T_ATM_ABSENT;
128 ipuap->ua_dstatmsub.address_format = T_ATM_ABSENT;
129 ipuap->ua_intf = uip;
134 * If there's no cached mapping, then make the 'nomap' entry
135 * the new cached entry.
138 UNLINK(nouap, struct uniarp, uniarp_nomaptab, ua_next);
139 nouap->ua_dstip.s_addr = ip->s_addr;
146 * We need to check the consistency of the new data with any
147 * cached data. So taking the easy case first, if there isn't
148 * an ATM address in the cache then we can skip all these checks.
150 if (ipuap->ua_dstatm.address_format != T_ATM_ABSENT) {
152 * See if the new data conflicts with what's in the cache
154 if (ATM_ADDR_EQUAL(atm, &ipuap->ua_dstatm) &&
155 ATM_ADDR_EQUAL(atmsub, &ipuap->ua_dstatmsub) &&
156 (uip == ipuap->ua_intf)) {
164 * Data conflict...how we deal with this depends on
165 * the origins of the conflicting data
167 if (origin == ipuap->ua_origin) {
169 * The new data has equal precedence - if there are
170 * any VCCs using this entry, then we reject this
171 * "duplicate IP address" update.
173 if (ipuap->ua_ivp != NULL) {
174 strncpy(abuf, unisig_addr_print(atmsub),
176 abuf[sizeof(abuf) - 1] = 0;
178 "uniarp: duplicate IP address %s from %s,%s\n",
179 inet_ntoa(*ip), unisig_addr_print(atm),
184 } else if (origin > ipuap->ua_origin) {
186 * New data's origin has higher precedence,
187 * so accept the new mapping and notify IP/ATM
188 * that a mapping change has occurred. IP/ATM will
189 * close any VCC's which aren't waiting for this map.
191 ipuap->ua_flags |= UAF_LOCKED;
192 for (ivp = ipuap->ua_ivp; ivp; ivp = inext) {
193 inext = ivp->iv_arpnext;
194 (*inp->inf_arpnotify)(ivp, MAP_CHANGED);
196 ipuap->ua_flags &= ~UAF_LOCKED;
199 * New data is of lesser origin precedence,
200 * so we just reject the update attempt.
205 strncpy(abuf, unisig_addr_print(atmsub), sizeof(abuf));
206 abuf[sizeof(abuf) - 1] = 0;
208 "uniarp: ATM address for %s changed to %s,%s\n",
209 inet_ntoa(*ip), unisig_addr_print(atm), abuf);
213 * Update the cache entry with the new data
215 ATM_ADDR_COPY(atm, &ipuap->ua_dstatm);
216 ATM_ADDR_COPY(atmsub, &ipuap->ua_dstatmsub);
217 ipuap->ua_intf = uip;
221 * Update cache data origin
223 ipuap->ua_origin = MAX(ipuap->ua_origin, origin);
226 * Ok, now act on this new/updated cache data
228 ipuap->ua_flags |= UAF_LOCKED;
231 * Save pointer to last VCC currently on cached entry chain that
232 * will need to be notified of the map becoming valid
235 if ((ipuap->ua_flags & UAF_VALID) == 0) {
237 for (itail = ipuap->ua_ivp; itail && itail->iv_arpnext;
238 itail = itail->iv_arpnext) {
243 * If there was a 'nomap' entry for this mapping, then we need to
244 * announce the new mapping to them first.
249 * Move the VCCs from this entry to the cache entry and
250 * let them know there's a valid mapping now
252 for (ivp = nouap->ua_ivp; ivp; ivp = inext) {
253 inext = ivp->iv_arpnext;
255 UNLINK(ivp, struct ipvcc, nouap->ua_ivp, iv_arpnext);
257 LINK2TAIL(ivp, struct ipvcc, ipuap->ua_ivp, iv_arpnext);
258 ivp->iv_arpent = (struct arpmap *)ipuap;
260 (*inp->inf_arpnotify)(ivp, MAP_VALID);
264 * Unlink and free the 'nomap' entry
266 UNLINK(nouap, struct uniarp, uniarp_nomaptab, ua_next);
267 UNIARP_CANCEL(nouap);
268 uma_zfree(uniarp_zone, nouap);
272 * Now, if this entry wasn't valid, notify the remaining VCCs
276 for (ivp = ipuap->ua_ivp; ivp; ivp = inext) {
277 inext = ivp->iv_arpnext;
278 (*inp->inf_arpnotify)(ivp, MAP_VALID);
283 ipuap->ua_flags &= ~UAF_LOCKED;
286 * We now have a valid cache entry, so cancel any retry timer
287 * and reset the aging timeout
289 UNIARP_CANCEL(ipuap);
290 if ((ipuap->ua_origin == UAO_REGISTER) && (origin != UAO_REGISTER)) {
291 if (((ipuap->ua_flags & UAF_VALID) == 0) ||
293 UNIARP_SERVER_AGE - UNIARP_MIN_REFRESH)) {
294 ipuap->ua_flags |= UAF_REFRESH;
295 ipuap->ua_aging = UNIARP_SERVER_AGE;
296 ipuap->ua_retry = UNIARP_SERVER_RETRY;
299 if (uip->uip_arpstate == UIAS_SERVER_ACTIVE) {
300 ipuap->ua_aging = UNIARP_SERVER_AGE;
301 ipuap->ua_retry = UNIARP_SERVER_RETRY;
303 ipuap->ua_aging = UNIARP_CLIENT_AGE;
304 ipuap->ua_retry = UNIARP_CLIENT_RETRY;
306 ipuap->ua_flags |= UAF_REFRESH;
308 ipuap->ua_flags |= UAF_VALID;
309 ipuap->ua_flags &= ~UAF_USED;
315 * Process ARP data from a PVC
317 * The arp table cache is never updated with PVC information.
322 * ivp pointer to input PVC's IPVCC control block
323 * ip pointer to IP address structure
324 * atm pointer to ATM address structure
325 * atmsub pointer to ATM subaddress structure
332 uniarp_cache_pvc(ivp, ip, atm, atmsub)
343 int vpi = 0, vci = 0;
345 if ((ivp->iv_conn) && (ivp->iv_conn->co_connvc)) {
346 vpi = ivp->iv_conn->co_connvc->cvc_vcc->vc_vpi;
347 vci = ivp->iv_conn->co_connvc->cvc_vcc->vc_vci;
349 strncpy(buf, unisig_addr_print(atmsub), sizeof(buf));
350 buf[sizeof(buf) - 1] = 0;
351 ATM_DEBUG5("cache_pvc: vcc=(%d,%d), ip=%s, atm=(%s,%s)\n",
352 vpi, vci, inet_ntoa(*ip), unisig_addr_print(atm), buf);
359 uap = (struct uniarp *)ivp->iv_arpent;
362 * See if IP address for PVC has changed
364 if (uap->ua_dstip.s_addr != ip->s_addr) {
365 if (uap->ua_dstip.s_addr != 0)
366 (*inp->inf_arpnotify)(ivp, MAP_CHANGED);
367 uap->ua_dstip.s_addr = ip->s_addr;
371 * Let IP/ATM know if address has become valid
373 if ((uap->ua_flags & UAF_VALID) == 0)
374 (*inp->inf_arpnotify)(ivp, MAP_VALID);
375 uap->ua_flags |= UAF_VALID;
376 uap->ua_aging = UNIARP_CLIENT_AGE;
377 uap->ua_retry = UNIARP_CLIENT_RETRY;
380 * Save ATM addresses just for debugging
382 ATM_ADDR_COPY(atm, &uap->ua_dstatm);
383 ATM_ADDR_COPY(atmsub, &uap->ua_dstatmsub);
390 * Validate IP address
393 * uip pointer to UNI IP interface
394 * ip pointer to IP address structure
395 * origin source of arp information
398 * 0 IP address is acceptable
399 * else invalid IP address
403 uniarp_validate_ip(uip, ip, origin)
408 struct uniarp_prf *upp;
413 * Can't be multicast or broadcast address
415 if (IN_MULTICAST(ntohl(ip->s_addr)) ||
416 in_broadcast(*ip, &uip->uip_ipnif->inf_nif->nif_if))
420 * For ATMARP registration information (including SCSP data),
421 * the address must be allowed by the interface's prefix list.
423 if ((origin == UAO_REGISTER) || (origin == UAO_SCSP)) {
424 for (i = uip->uip_nprefix, upp = uip->uip_prefix;
426 if ((ip->s_addr & upp->upf_mask.s_addr) ==
427 upp->upf_addr.s_addr)