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_vcm.c,v 1.5 2000/01/17 20:49:55 mks Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/uni/uniarp_vcm.c,v 1.5 2005/06/02 22:37:52 dillon Exp $
31 * ATM Forum UNI Support
32 * ---------------------
34 * UNI ATMARP support (RFC1577) - Virtual Channel Management
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 "uniip_var.h"
47 static struct attr_llc uniarp_llc = {
52 {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06}
56 static struct t_atm_cause uniarp_cause = {
59 T_ATM_CAUSE_TEMPORARY_FAILURE,
65 * Process a new PVC requiring ATMARP support
67 * This function is called after IP/ATM has successfully opened a PVC which
68 * requires ATMARP support. We will send an InATMARP request over the PVC
69 * to elicit a response from the PVC's ATMARP peer informing us of its
70 * network address. This information will also be used by IP/ATM in order
71 * to complete its address-to-VC mapping table.
74 * ivp pointer to PVC's IPVCC control block
77 * MAP_PROCEEDING - OK so far, querying for peer's mapping
78 * MAP_FAILED - error, unable to allocate resources
89 ATM_DEBUG1("uniarp_pvcopen: ivp=%p\n", ivp);
91 ivp->iv_arpent = NULL;
96 if ((ivp->iv_flags & IVF_LLC) == 0)
102 uip = (struct uniip *)ivp->iv_ipnif->inf_isintf;
107 * Get an arp map entry
109 uap = (struct uniarp *)atm_allocate(&uniarp_pool);
114 * Create our CM connection
116 err = atm_cm_addllc(&uniarp_endpt, ivp, &uniarp_llc,
117 ivp->iv_conn, &ivp->iv_arpconn);
120 * We don't take no (or maybe) for an answer
122 if (ivp->iv_arpconn) {
123 (void) atm_cm_release(ivp->iv_arpconn, &uniarp_cause);
124 ivp->iv_arpconn = NULL;
126 atm_free((caddr_t)uap);
131 * Get map entry set up
134 uap->ua_dstatm.address_format = T_ATM_ABSENT;
135 uap->ua_dstatmsub.address_format = T_ATM_ABSENT;
139 * Put ivp on arp entry chain
141 LINK2TAIL(ivp, struct ipvcc, uap->ua_ivp, iv_arpnext);
142 ivp->iv_arpent = (struct arpmap *)uap;
145 * Put arp entry on pvc chain
147 LINK2TAIL(uap, struct uniarp, uniarp_pvctab, ua_next);
150 * Send Inverse ATMARP request
152 (void) uniarp_inarp_req(uip, &uap->ua_dstatm, &uap->ua_dstatmsub, ivp);
157 uap->ua_aging = UNIARP_REVALID_AGE;
160 return (MAP_PROCEEDING);
165 * Process a new outgoing SVC requiring ATMARP support
167 * This function is called by the IP/ATM module to resolve a destination
168 * IP address to an ATM address in order to open an SVC to that destination.
169 * If a valid mapping is already in our cache, then we just tell the caller
170 * about it and that's that. Otherwise, we have to allocate a new arp entry
171 * and issue a query for the mapping.
174 * ivp pointer to SVC's IPVCC control block
175 * dst pointer to destination IP address
178 * MAP_VALID - Got the answer, returned via iv_arpent field.
179 * MAP_PROCEEDING - OK so far, querying for peer's mapping
180 * MAP_FAILED - error, unable to allocate resources
184 uniarp_svcout(ivp, dst)
193 ATM_DEBUG2("uniarp_svcout: ivp=%p,dst=0x%x\n", ivp, dst->s_addr);
195 ivp->iv_arpent = NULL;
200 uip = (struct uniip *)ivp->iv_ipnif->inf_isintf;
207 * Lookup IP destination address
209 UNIARP_LOOKUP(dst->s_addr, uap);
213 * We've got an entry, verify interface
215 if (uap->ua_intf != uip) {
221 * Chain this vcc onto entry
223 LINK2TAIL(ivp, struct ipvcc, uap->ua_ivp, iv_arpnext);
224 ivp->iv_arpent = (struct arpmap *)uap;
225 uap->ua_flags |= UAF_USED;
227 if (uap->ua_flags & UAF_VALID) {
229 * Entry is valid, we're done
235 * We're already looking for this address
238 return (MAP_PROCEEDING);
243 * No info in the cache. If we're the server, then
244 * we're already authoritative, so just deny request.
245 * If we're a client but the server VCC isn't open we
246 * also deny the request.
248 if (uip->uip_arpstate != UIAS_CLIENT_ACTIVE) {
254 * We're a client with an open VCC to the server, get a new arp entry
256 uap = (struct uniarp *)atm_allocate(&uniarp_pool);
265 uap->ua_dstip.s_addr = dst->s_addr;
266 uap->ua_dstatm.address_format = T_ATM_ABSENT;
267 uap->ua_dstatm.address_length = 0;
268 uap->ua_dstatmsub.address_format = T_ATM_ABSENT;
269 uap->ua_dstatmsub.address_length = 0;
273 * Link ipvcc to arp entry for later notification
275 LINK2TAIL(ivp, struct ipvcc, uap->ua_ivp, iv_arpnext);
276 ivp->iv_arpent = (struct arpmap *)uap;
277 uap->ua_flags |= UAF_USED;
280 * Add arp entry to table
285 * Issue arp request for this address
287 (void) uniarp_arp_req(uip, dst);
292 UNIARP_TIMER(uap, UNIARP_ARP_RETRY);
295 return (MAP_PROCEEDING);
300 * Process a new incoming SVC requiring ATMARP support
302 * This function is called by the IP/ATM module to resolve a caller's ATM
303 * address to its IP address for an incoming call in order to allow a
304 * bi-directional flow of IP packets on the SVC. If a valid mapping is
305 * already in our cache, then we will use it. Otherwise, we have to allocate
306 * a new arp entry and wait for the SVC to become active so that we can issue
307 * an InATMARP to the peer.
310 * ivp pointer to SVC's IPVCC control block
311 * dst pointer to caller's ATM address
312 * dstsub pointer to caller's ATM subaddress
315 * MAP_VALID - Got the answer, returned via iv_arpent field.
316 * MAP_PROCEEDING - OK so far, querying for peer's mapping
317 * MAP_FAILED - error, unable to allocate resources
321 uniarp_svcin(ivp, dst, dstsub)
332 ATM_DEBUG1("uniarp_svcin: ivp=%p\n", ivp);
335 * Clear ARP entry field
337 ivp->iv_arpent = NULL;
342 if ((ivp->iv_flags & IVF_LLC) == 0)
348 uip = (struct uniip *)ivp->iv_ipnif->inf_isintf;
355 * Make sure we're configured as a client or server
357 if (uip->uip_arpstate == UIAS_NOTCONF) {
363 * If we know the caller's ATM address, look it up
366 if (dst->address_format != T_ATM_ABSENT) {
367 for (i = 0; (i < UNIARP_HASHSIZ) && (found == 0); i++) {
368 for (uap = uniarp_arptab[i]; uap; uap = uap->ua_next) {
369 if (ATM_ADDR_EQUAL(dst, &uap->ua_dstatm) &&
370 ATM_ADDR_EQUAL(dstsub, &uap->ua_dstatmsub)){
377 for (uap = uniarp_nomaptab; uap; uap = uap->ua_next) {
378 if (ATM_ADDR_EQUAL(dst, &uap->ua_dstatm) &&
379 ATM_ADDR_EQUAL(dstsub, &uap->ua_dstatmsub))
387 * We've got an entry, verify interface
389 if (uap->ua_intf != uip) {
395 * Chain the vcc onto this entry
397 LINK2TAIL(ivp, struct ipvcc, uap->ua_ivp, iv_arpnext);
398 ivp->iv_arpent = (struct arpmap *)uap;
399 uap->ua_flags |= UAF_USED;
401 if (uap->ua_flags & UAF_VALID) {
403 * Entry is valid, we're done
409 * We're already looking for this address
412 return (MAP_PROCEEDING);
417 * No info in the cache - get a new arp entry
419 uap = (struct uniarp *)atm_allocate(&uniarp_pool);
428 ATM_ADDR_COPY(dst, &uap->ua_dstatm);
429 ATM_ADDR_COPY(dstsub, &uap->ua_dstatmsub);
433 * Link ipvcc to arp entry for later notification
435 LINK2TAIL(ivp, struct ipvcc, uap->ua_ivp, iv_arpnext);
436 ivp->iv_arpent = (struct arpmap *)uap;
437 uap->ua_flags |= UAF_USED;
440 * Add arp entry to 'nomap' table
442 LINK2TAIL(uap, struct uniarp, uniarp_nomaptab, ua_next);
447 * Now we just wait for SVC to become active
449 return (MAP_PROCEEDING);
454 * Process ARP SVC activation notification
456 * This function is called by the IP/ATM module whenever a previously
457 * opened SVC has successfully been connected.
460 * ivp pointer to SVC's IPVCC control block
463 * 0 activation processing successful
464 * errno activation failed - reason indicated
468 uniarp_svcactive(ivp)
478 ATM_DEBUG1("uniarp_svcactive: ivp=%p\n", ivp);
481 uip = (struct uniip *)inp->inf_isintf;
482 uap = (struct uniarp *)ivp->iv_arpent;
485 * First, we need to create our CM connection
487 err = atm_cm_addllc(&uniarp_endpt, ivp, &uniarp_llc,
488 ivp->iv_conn, &ivp->iv_arpconn);
491 * We don't take no (or maybe) for an answer
493 if (ivp->iv_arpconn) {
494 (void) atm_cm_release(ivp->iv_arpconn, &uniarp_cause);
495 ivp->iv_arpconn = NULL;
501 * Is this the client->server vcc??
503 if (uip->uip_arpsvrvcc == ivp) {
506 * Yep, go into the client registration phase
508 uip->uip_arpstate = UIAS_CLIENT_REGISTER;
511 * To register ourselves, RFC1577 says we should wait
512 * around for the server to send us an InATMARP_Request.
513 * However, draft-1577+ just has us send an ATMARP_Request
514 * for our own address. To keep everyone happy, we'll go
515 * with both and see what works!
517 (void) uniarp_arp_req(uip, &(IA_SIN(inp->inf_addr)->sin_addr));
522 UNIIP_ARP_TIMER(uip, 1 * ATM_HZ);
529 * Send an InATMARP_Request on this VCC to find out/notify who's at
530 * the other end. If we're the server, this will start off the
531 * RFC1577 registration procedure. If we're a client, then this
532 * SVC is for user data and it's pretty likely that both ends are
533 * going to be sending packets. So, if we're the caller, we'll be
534 * nice and let the callee know right away who we are. If we're the
535 * callee, let's find out asap the caller's IP address.
537 (void) uniarp_inarp_req(uip, &uap->ua_dstatm, &uap->ua_dstatmsub, ivp);
540 * Start retry timer if entry isn't valid yet
542 if (((uap->ua_flags & UAF_VALID) == 0) &&
543 ((uap->ua_time.ti_flag & TIF_QUEUED) == 0))
544 UNIARP_TIMER(uap, UNIARP_ARP_RETRY);
554 * This function is called just prior to IP/ATM closing a VCC which
555 * supports ATMARP. We'll sever our links to the VCC and then
556 * figure out how much more cleanup we need to do for now.
559 * ivp pointer to VCC's IPVCC control block
572 ATM_DEBUG1("uniarp_vcclose: ivp=%p\n", ivp);
575 * Close our CM connection
577 if (ivp->iv_arpconn) {
578 (void) atm_cm_release(ivp->iv_arpconn, &uniarp_cause);
579 ivp->iv_arpconn = NULL;
585 if ((uap = (struct uniarp *)ivp->iv_arpent) == NULL)
592 * If this is the arpserver VCC, then schedule ourselves to
593 * reopen the connection soon
595 if (uip->uip_arpsvrvcc == ivp) {
596 uip->uip_arpsvrvcc = NULL;
597 uip->uip_arpstate = UIAS_CLIENT_POPEN;
598 UNIIP_ARP_CANCEL(uip);
599 UNIIP_ARP_TIMER(uip, 5 * ATM_HZ);
603 * Remove IP VCC from chain
605 UNLINK(ivp, struct ipvcc, uap->ua_ivp, iv_arpnext);
608 * SVCs and PVCs are handled separately
610 if (ivp->iv_flags & IVF_SVC) {
612 * If the mapping is currently valid or in use, or if there
613 * are other VCCs still using this mapping, we're done for now
615 if ((uap->ua_flags & (UAF_VALID | UAF_LOCKED)) ||
616 (uap->ua_origin >= UAO_PERM) ||
617 (uap->ua_ivp != NULL)) {
625 if (uap->ua_dstip.s_addr == 0) {
626 UNLINK(uap, struct uniarp, uniarp_nomaptab, ua_next);
632 * Remove entry from pvc table
634 UNLINK(uap, struct uniarp, uniarp_pvctab, ua_next);
640 * Finally, free the entry
642 atm_free((caddr_t)uap);
650 * Process ATMARP VCC Connected Notification
653 * toku owner's connection token (ipvcc protocol block)
660 uniarp_connected(toku)
665 * Since we only do atm_cm_addllc()'s on active connections,
666 * we should never get called here...
668 panic("uniarp_connected");
673 * Process ATMARP VCC Cleared Notification
676 * toku owner's connection token (ipvcc protocol block)
677 * cause pointer to cause code
684 uniarp_cleared(toku, cause)
686 struct t_atm_cause *cause;
688 struct ipvcc *ivp = toku;
693 * We're done with VCC
695 ivp->iv_arpconn = NULL;
698 * If IP is finished with VCC, then we'll free it
700 if (ivp->iv_state == IPVCC_FREE)
701 atm_free((caddr_t)ivp);