diff options
Diffstat (limited to 'sys/netatm/uni/uniarp_vcm.c')
-rw-r--r-- | sys/netatm/uni/uniarp_vcm.c | 723 |
1 files changed, 0 insertions, 723 deletions
diff --git a/sys/netatm/uni/uniarp_vcm.c b/sys/netatm/uni/uniarp_vcm.c deleted file mode 100644 index 08cc8ef..0000000 --- a/sys/netatm/uni/uniarp_vcm.c +++ /dev/null @@ -1,723 +0,0 @@ -/*- - * =================================== - * HARP | Host ATM Research Platform - * =================================== - * - * - * This Host ATM Research Platform ("HARP") file (the "Software") is - * made available by Network Computing Services, Inc. ("NetworkCS") - * "AS IS". NetworkCS does not provide maintenance, improvements or - * support of any kind. - * - * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED, - * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE - * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE. - * In no event shall NetworkCS be responsible for any damages, including - * but not limited to consequential damages, arising from or relating to - * any use of the Software or related support. - * - * Copyright 1994-1998 Network Computing Services, Inc. - * - * Copies of this Software may be made, however, the above copyright - * notice must be reproduced on all copies. - */ - -/* - * ATM Forum UNI Support - * --------------------- - * - * UNI ATMARP support (RFC1577) - Virtual Channel Management - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/systm.h> -#include <sys/time.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <net/if.h> -#include <netinet/in.h> -#include <netinet/in_var.h> -#include <netatm/port.h> -#include <netatm/queue.h> -#include <netatm/atm.h> -#include <netatm/atm_sys.h> -#include <netatm/atm_sap.h> -#include <netatm/atm_cm.h> -#include <netatm/atm_if.h> -#include <netatm/atm_ioctl.h> -#include <netatm/atm_stack.h> -#include <netatm/atm_pcb.h> -#include <netatm/atm_var.h> - -#include <netatm/ipatm/ipatm_var.h> -#include <netatm/ipatm/ipatm_serv.h> -#include <netatm/uni/uniip_var.h> - -#include <vm/uma.h> - -extern uma_zone_t unisig_vc_zone; - -/* - * Local variables - */ -static struct attr_llc uniarp_llc = { - T_ATM_PRESENT, - { - T_ATM_LLC_SHARING, - 8, - {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06} - } -}; - -static struct t_atm_cause uniarp_cause = { - T_ATM_ITU_CODING, - T_ATM_LOC_USER, - T_ATM_CAUSE_TEMPORARY_FAILURE, - {0, 0, 0, 0} -}; - - -/* - * Process a new PVC requiring ATMARP support - * - * This function is called after IP/ATM has successfully opened a PVC which - * requires ATMARP support. We will send an InATMARP request over the PVC - * to elicit a response from the PVC's ATMARP peer informing us of its - * network address. This information will also be used by IP/ATM in order - * to complete its address-to-VC mapping table. - * - * Arguments: - * ivp pointer to PVC's IPVCC control block - * - * Returns: - * MAP_PROCEEDING - OK so far, querying for peer's mapping - * MAP_FAILED - error, unable to allocate resources - * - */ -int -uniarp_pvcopen(ivp) - struct ipvcc *ivp; -{ - struct uniip *uip; - struct uniarp *uap; - int s, err; - - ATM_DEBUG1("uniarp_pvcopen: ivp=%p\n", ivp); - - ivp->iv_arpent = NULL; - - /* - * Check things out - */ - if ((ivp->iv_flags & IVF_LLC) == 0) - return (MAP_FAILED); - - /* - * Get uni interface - */ - uip = (struct uniip *)ivp->iv_ipnif->inf_isintf; - if (uip == NULL) - return (MAP_FAILED); - - /* - * Get an arp map entry - */ - uap = uma_zalloc(uniarp_zone, M_WAITOK | M_ZERO); - if (uap == NULL) - return (MAP_FAILED); - - /* - * Create our CM connection - */ - err = atm_cm_addllc(&uniarp_endpt, ivp, &uniarp_llc, - ivp->iv_conn, &ivp->iv_arpconn); - if (err) { - /* - * We don't take no (or maybe) for an answer - */ - if (ivp->iv_arpconn) { - (void) atm_cm_release(ivp->iv_arpconn, &uniarp_cause); - ivp->iv_arpconn = NULL; - } - uma_zfree(uniarp_zone, uap); - return (MAP_FAILED); - } - - /* - * Get map entry set up - */ - s = splnet(); - uap->ua_dstatm.address_format = T_ATM_ABSENT; - uap->ua_dstatmsub.address_format = T_ATM_ABSENT; - uap->ua_intf = uip; - - /* - * Put ivp on arp entry chain - */ - LINK2TAIL(ivp, struct ipvcc, uap->ua_ivp, iv_arpnext); - ivp->iv_arpent = (struct arpmap *)uap; - - /* - * Put arp entry on pvc chain - */ - LINK2TAIL(uap, struct uniarp, uniarp_pvctab, ua_next); - - /* - * Send Inverse ATMARP request - */ - (void) uniarp_inarp_req(uip, &uap->ua_dstatm, &uap->ua_dstatmsub, ivp); - - /* - * Start resend timer - */ - uap->ua_aging = UNIARP_REVALID_AGE; - - (void) splx(s); - return (MAP_PROCEEDING); -} - - -/* - * Process a new outgoing SVC requiring ATMARP support - * - * This function is called by the IP/ATM module to resolve a destination - * IP address to an ATM address in order to open an SVC to that destination. - * If a valid mapping is already in our cache, then we just tell the caller - * about it and that's that. Otherwise, we have to allocate a new arp entry - * and issue a query for the mapping. - * - * Arguments: - * ivp pointer to SVC's IPVCC control block - * dst pointer to destination IP address - * - * Returns: - * MAP_VALID - Got the answer, returned via iv_arpent field. - * MAP_PROCEEDING - OK so far, querying for peer's mapping - * MAP_FAILED - error, unable to allocate resources - * - */ -int -uniarp_svcout(ivp, dst) - struct ipvcc *ivp; - struct in_addr *dst; -{ - struct uniip *uip; - struct uniarp *uap; - int s = splnet(); - - ATM_DEBUG2("uniarp_svcout: ivp=%p,dst=0x%x\n", ivp, dst->s_addr); - - ivp->iv_arpent = NULL; - - /* - * Get uni interface - */ - uip = (struct uniip *)ivp->iv_ipnif->inf_isintf; - if (uip == NULL) { - (void) splx(s); - return (MAP_FAILED); - } - - /* - * Lookup IP destination address - */ - UNIARP_LOOKUP(dst->s_addr, uap); - - if (uap) { - /* - * We've got an entry, verify interface - */ - if (uap->ua_intf != uip) { - (void) splx(s); - return (MAP_FAILED); - } - - /* - * Chain this vcc onto entry - */ - LINK2TAIL(ivp, struct ipvcc, uap->ua_ivp, iv_arpnext); - ivp->iv_arpent = (struct arpmap *)uap; - uap->ua_flags |= UAF_USED; - - if (uap->ua_flags & UAF_VALID) { - /* - * Entry is valid, we're done - */ - (void) splx(s); - return (MAP_VALID); - } else { - /* - * We're already looking for this address - */ - (void) splx(s); - return (MAP_PROCEEDING); - } - } - - /* - * No info in the cache. If we're the server, then - * we're already authoritative, so just deny request. - * If we're a client but the server VCC isn't open we - * also deny the request. - */ - if (uip->uip_arpstate != UIAS_CLIENT_ACTIVE) { - (void) splx(s); - return (MAP_FAILED); - } - - /* - * We're a client with an open VCC to the server, get a new arp entry - * May be called from timeout - don't wait. - */ - uap = uma_zalloc(uniarp_zone, M_NOWAIT); - if (uap == NULL) { - (void) splx(s); - return (MAP_FAILED); - } - - /* - * Get entry set up - */ - uap->ua_dstip.s_addr = dst->s_addr; - uap->ua_dstatm.address_format = T_ATM_ABSENT; - uap->ua_dstatm.address_length = 0; - uap->ua_dstatmsub.address_format = T_ATM_ABSENT; - uap->ua_dstatmsub.address_length = 0; - uap->ua_intf = uip; - - /* - * Link ipvcc to arp entry for later notification - */ - LINK2TAIL(ivp, struct ipvcc, uap->ua_ivp, iv_arpnext); - ivp->iv_arpent = (struct arpmap *)uap; - uap->ua_flags |= UAF_USED; - - /* - * Add arp entry to table - */ - UNIARP_ADD(uap); - - /* - * Issue arp request for this address - */ - (void) uniarp_arp_req(uip, dst); - - /* - * Start retry timer - */ - UNIARP_TIMER(uap, UNIARP_ARP_RETRY); - - (void) splx(s); - return (MAP_PROCEEDING); -} - - -/* - * Process a new incoming SVC requiring ATMARP support - * - * This function is called by the IP/ATM module to resolve a caller's ATM - * address to its IP address for an incoming call in order to allow a - * bi-directional flow of IP packets on the SVC. If a valid mapping is - * already in our cache, then we will use it. Otherwise, we have to allocate - * a new arp entry and wait for the SVC to become active so that we can issue - * an InATMARP to the peer. - * - * Arguments: - * ivp pointer to SVC's IPVCC control block - * dst pointer to caller's ATM address - * dstsub pointer to caller's ATM subaddress - * - * Returns: - * MAP_VALID - Got the answer, returned via iv_arpent field. - * MAP_PROCEEDING - OK so far, querying for peer's mapping - * MAP_FAILED - error, unable to allocate resources - * - */ -int -uniarp_svcin(ivp, dst, dstsub) - struct ipvcc *ivp; - Atm_addr *dst; - Atm_addr *dstsub; -{ - struct uniip *uip; - struct uniarp *uap; - int found = 0, i, s = splnet(); - - ATM_DEBUG1("uniarp_svcin: ivp=%p\n", ivp); - - /* - * Clear ARP entry field - */ - ivp->iv_arpent = NULL; - - /* - * Check things out - */ - if ((ivp->iv_flags & IVF_LLC) == 0) - return (MAP_FAILED); - - /* - * Get uni interface - */ - uip = (struct uniip *)ivp->iv_ipnif->inf_isintf; - if (uip == NULL) { - (void) splx(s); - return (MAP_FAILED); - } - - /* - * Make sure we're configured as a client or server - */ - if (uip->uip_arpstate == UIAS_NOTCONF) { - (void) splx(s); - return (MAP_FAILED); - } - - /* - * If we know the caller's ATM address, look it up - */ - uap = NULL; - if (dst->address_format != T_ATM_ABSENT) { - for (i = 0; (i < UNIARP_HASHSIZ) && (found == 0); i++) { - for (uap = uniarp_arptab[i]; uap; uap = uap->ua_next) { - if (ATM_ADDR_EQUAL(dst, &uap->ua_dstatm) && - ATM_ADDR_EQUAL(dstsub, &uap->ua_dstatmsub)){ - found = 1; - break; - } - } - } - if (uap == NULL) { - for (uap = uniarp_nomaptab; uap; uap = uap->ua_next) { - if (ATM_ADDR_EQUAL(dst, &uap->ua_dstatm) && - ATM_ADDR_EQUAL(dstsub, &uap->ua_dstatmsub)) - break; - } - } - } - - if (uap) { - /* - * We've got an entry, verify interface - */ - if (uap->ua_intf != uip) { - (void) splx(s); - return (MAP_FAILED); - } - - /* - * Chain the vcc onto this entry - */ - LINK2TAIL(ivp, struct ipvcc, uap->ua_ivp, iv_arpnext); - ivp->iv_arpent = (struct arpmap *)uap; - uap->ua_flags |= UAF_USED; - - if (uap->ua_flags & UAF_VALID) { - /* - * Entry is valid, we're done - */ - (void) splx(s); - return (MAP_VALID); - } else { - /* - * We're already looking for this address - */ - (void) splx(s); - return (MAP_PROCEEDING); - } - } - - /* - * No info in the cache - get a new arp entry - * May be called from timeout - don't wait. - */ - uap = uma_zalloc(uniarp_zone, M_NOWAIT | M_ZERO); - if (uap == NULL) { - (void) splx(s); - return (MAP_FAILED); - } - - /* - * Get entry set up - */ - ATM_ADDR_COPY(dst, &uap->ua_dstatm); - ATM_ADDR_COPY(dstsub, &uap->ua_dstatmsub); - uap->ua_intf = uip; - - /* - * Link ipvcc to arp entry for later notification - */ - LINK2TAIL(ivp, struct ipvcc, uap->ua_ivp, iv_arpnext); - ivp->iv_arpent = (struct arpmap *)uap; - uap->ua_flags |= UAF_USED; - - /* - * Add arp entry to 'nomap' table - */ - LINK2TAIL(uap, struct uniarp, uniarp_nomaptab, ua_next); - - (void) splx(s); - - /* - * Now we just wait for SVC to become active - */ - return (MAP_PROCEEDING); -} - - -/* - * Process ARP SVC activation notification - * - * This function is called by the IP/ATM module whenever a previously - * opened SVC has successfully been connected. - * - * Arguments: - * ivp pointer to SVC's IPVCC control block - * - * Returns: - * 0 activation processing successful - * errno activation failed - reason indicated - * - */ -int -uniarp_svcactive(ivp) - struct ipvcc *ivp; -{ - struct ip_nif *inp; - struct uniip *uip; - struct uniarp *uap; - int err, s = splnet(); - - ATM_DEBUG1("uniarp_svcactive: ivp=%p\n", ivp); - - inp = ivp->iv_ipnif; - uip = (struct uniip *)inp->inf_isintf; - uap = (struct uniarp *)ivp->iv_arpent; - - /* - * First, we need to create our CM connection - */ - err = atm_cm_addllc(&uniarp_endpt, ivp, &uniarp_llc, - ivp->iv_conn, &ivp->iv_arpconn); - if (err) { - /* - * We don't take no (or maybe) for an answer - */ - if (ivp->iv_arpconn) { - (void) atm_cm_release(ivp->iv_arpconn, &uniarp_cause); - ivp->iv_arpconn = NULL; - } - return (err); - } - - /* - * Is this the client->server vcc?? - */ - if (uip->uip_arpsvrvcc == ivp) { - - /* - * Yep, go into the client registration phase - */ - uip->uip_arpstate = UIAS_CLIENT_REGISTER; - - /* - * To register ourselves, RFC1577 says we should wait - * around for the server to send us an InATMARP_Request. - * However, draft-1577+ just has us send an ATMARP_Request - * for our own address. To keep everyone happy, we'll go - * with both and see what works! - */ - (void) uniarp_arp_req(uip, &(IA_SIN(inp->inf_addr)->sin_addr)); - - /* - * Start retry timer - */ - UNIIP_ARP_TIMER(uip, 1 * ATM_HZ); - - (void) splx(s); - return (0); - } - - /* - * Send an InATMARP_Request on this VCC to find out/notify who's at - * the other end. If we're the server, this will start off the - * RFC1577 registration procedure. If we're a client, then this - * SVC is for user data and it's pretty likely that both ends are - * going to be sending packets. So, if we're the caller, we'll be - * nice and let the callee know right away who we are. If we're the - * callee, let's find out asap the caller's IP address. - */ - (void) uniarp_inarp_req(uip, &uap->ua_dstatm, &uap->ua_dstatmsub, ivp); - - /* - * Start retry timer if entry isn't valid yet - */ - if (((uap->ua_flags & UAF_VALID) == 0) && - ((uap->ua_time.ti_flag & TIF_QUEUED) == 0)) - UNIARP_TIMER(uap, UNIARP_ARP_RETRY); - - (void) splx(s); - return (0); -} - - -/* - * Process VCC close - * - * This function is called just prior to IP/ATM closing a VCC which - * supports ATMARP. We'll sever our links to the VCC and then - * figure out how much more cleanup we need to do for now. - * - * Arguments: - * ivp pointer to VCC's IPVCC control block - * - * Returns: - * none - * - */ -void -uniarp_vcclose(ivp) - struct ipvcc *ivp; -{ - struct uniip *uip; - struct uniarp *uap; - int s; - - ATM_DEBUG1("uniarp_vcclose: ivp=%p\n", ivp); - - /* - * Close our CM connection - */ - if (ivp->iv_arpconn) { - (void) atm_cm_release(ivp->iv_arpconn, &uniarp_cause); - ivp->iv_arpconn = NULL; - } - - /* - * Get atmarp entry - */ - if ((uap = (struct uniarp *)ivp->iv_arpent) == NULL) - return; - uip = uap->ua_intf; - - s = splnet(); - - /* - * If this is the arpserver VCC, then schedule ourselves to - * reopen the connection soon - */ - if (uip->uip_arpsvrvcc == ivp) { - uip->uip_arpsvrvcc = NULL; - uip->uip_arpstate = UIAS_CLIENT_POPEN; - UNIIP_ARP_CANCEL(uip); - UNIIP_ARP_TIMER(uip, 5 * ATM_HZ); - } - - /* - * Remove IP VCC from chain - */ - UNLINK(ivp, struct ipvcc, uap->ua_ivp, iv_arpnext); - - /* - * SVCs and PVCs are handled separately - */ - if (ivp->iv_flags & IVF_SVC) { - /* - * If the mapping is currently valid or in use, or if there - * are other VCCs still using this mapping, we're done for now - */ - if ((uap->ua_flags & (UAF_VALID | UAF_LOCKED)) || - (uap->ua_origin >= UAO_PERM) || - (uap->ua_ivp != NULL)) { - (void) splx(s); - return; - } - - /* - * Unlink the entry - */ - if (uap->ua_dstip.s_addr == 0) { - UNLINK(uap, struct uniarp, uniarp_nomaptab, ua_next); - } else { - UNIARP_DELETE(uap); - } - } else { - /* - * Remove entry from pvc table - */ - UNLINK(uap, struct uniarp, uniarp_pvctab, ua_next); - } - - UNIARP_CANCEL(uap); - - /* - * Finally, free the entry - */ - uma_zfree(uniarp_zone, uap); - (void) splx(s); - return; -} - - -/* - * Process ATMARP VCC Connected Notification - * - * Arguments: - * toku owner's connection token (ipvcc protocol block) - * - * Returns: - * none - * - */ -void -uniarp_connected(toku) - void *toku; -{ - - /* - * Since we only do atm_cm_addllc()'s on active connections, - * we should never get called here... - */ - panic("uniarp_connected"); -} - - -/* - * Process ATMARP VCC Cleared Notification - * - * Arguments: - * toku owner's connection token (ipvcc protocol block) - * cause pointer to cause code - * - * Returns: - * none - * - */ -void -uniarp_cleared(toku, cause) - void *toku; - struct t_atm_cause *cause; -{ - struct ipvcc *ivp = toku; - int s; - - s = splnet(); - - /* - * We're done with VCC - */ - ivp->iv_arpconn = NULL; - - /* - * If IP is finished with VCC, then we'll free it - */ - if (ivp->iv_state == IPVCC_FREE) - uma_zfree(unisig_vc_zone, ivp); - (void) splx(s); -} - |