diff options
Diffstat (limited to 'usr.sbin/atm/atmarpd/atmarp_subr.c')
-rw-r--r-- | usr.sbin/atm/atmarpd/atmarp_subr.c | 962 |
1 files changed, 962 insertions, 0 deletions
diff --git a/usr.sbin/atm/atmarpd/atmarp_subr.c b/usr.sbin/atm/atmarpd/atmarp_subr.c new file mode 100644 index 000000000000..3cc20e05f5ba --- /dev/null +++ b/usr.sbin/atm/atmarpd/atmarp_subr.c @@ -0,0 +1,962 @@ +/* + * + * =================================== + * 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. + * + * @(#) $Id: atmarp_subr.c,v 1.6 1998/08/13 20:11:11 johnc Exp $ + * + */ + + +/* + * Server Cache Synchronization Protocol (SCSP) Support + * ---------------------------------------------------- + * + * SCSP-ATMARP server interface: misc. subroutines + * + */ + + +#ifndef lint +static char *RCSid = "@(#) $Id: atmarp_subr.c,v 1.6 1998/08/13 20:11:11 johnc Exp $"; +#endif + +#include <sys/types.h> +#include <sys/param.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <sys/socket.h> +#include <sys/sockio.h> +#include <net/if.h> +#include <netinet/in.h> +#include <netatm/port.h> +#include <netatm/queue.h> +#include <netatm/atm.h> +#include <netatm/atm_if.h> +#include <netatm/atm_sap.h> +#include <netatm/atm_sigmgr.h> +#include <netatm/atm_sys.h> +#include <netatm/atm_ioctl.h> +#include <netatm/uni/unisig_var.h> +#include <netatm/uni/uniip_var.h> + +#include <libatm.h> +#include "../scspd/scsp_msg.h" +#include "../scspd/scsp_if.h" +#include "../scspd/scsp_var.h" +#include "atmarp_var.h" + + +/* + * Find an ATMARP interface, given its socket number + * + * Arguments: + * sd socket descriptor + * + * Returns: + * 0 failure + * else pointer to interface associated with socket + * + */ +Atmarp_intf * +atmarp_find_intf_sock(sd) + int sd; +{ + Atmarp_intf *aip; + + /* + * Loop through the list of interfaces + */ + for (aip = atmarp_intf_head; aip; aip = aip->ai_next) { + if (aip->ai_scsp_sock == sd) + break; + } + + return(aip); +} + + +/* + * Find an ATMARP interface, given its name + * + * Arguments: + * name pointer to network interface name + * + * Returns: + * 0 failure + * else pointer to interface associated with name + * + */ +Atmarp_intf * +atmarp_find_intf_name(name) + char *name; +{ + Atmarp_intf *aip; + + /* + * Loop through the list of interfaces + */ + for (aip = atmarp_intf_head; aip; aip = aip->ai_next) { + if (strcmp(name, aip->ai_intf) == 0) + break; + } + + return(aip); +} + + +/* + * Clear the mark field on all ATMARP cache entries + * + * Arguments: + * none + * + * Returns: + * none + * + */ +void +atmarp_clear_marks() + +{ + int i; + Atmarp_intf *aip; + Atmarp *aap; + + /* + * Loop through list of interfaces + */ + for (aip = atmarp_intf_head; aip; aip = aip->ai_next) { + /* + * Clear mark on every entry in the interface's cache + */ + for (i = 0; i < ATMARP_HASHSIZ; i++ ) { + for (aap = aip->ai_arptbl[i]; aap; + aap = aap->aa_next) { + aap->aa_mark = 0; + } + } + } +} + + +/* + * Check whether the host system is an ATMARP server for + * the LIS associated with a given interface + * + * Arguments: + * aip pointer to an ATMARP interface control block + * + * Returns: + * 1 host is a server + * 0 host is not a server + * + */ +int +atmarp_is_server(aip) + Atmarp_intf *aip; +{ + int rc; + int buf_len = sizeof(struct air_asrv_rsp); + struct atminfreq air; + struct air_asrv_rsp *asrv_info; + + /* + * Get interface information from the kernel + */ + strcpy(air.air_int_intf, aip->ai_intf); + air.air_opcode = AIOCS_INF_ASV; + buf_len = do_info_ioctl(&air, buf_len); + if (buf_len < 0) + return(0); + + /* + * Check the interface's ATMARP server address + */ + asrv_info = (struct air_asrv_rsp *) air.air_buf_addr; + rc = (asrv_info->asp_addr.address_format == T_ATM_ABSENT) && + (asrv_info->asp_subaddr.address_format == + T_ATM_ABSENT); + UM_FREE(asrv_info); + return(rc); +} + + +/* + * Check whether an interface is up and ready for service + * + * Arguments: + * aip pointer to network interface block + * + * Returns: + * 0 interface not ready, errno has reason + * 1 interface is ready to go (interface block is updated) + * + */ +int +atmarp_if_ready(aip) + Atmarp_intf *aip; +{ + int i, len, mtu, rc, sel; + Atmarp *aap = (Atmarp *)0; + struct atminfreq air; + struct air_netif_rsp *netif_rsp = (struct air_netif_rsp *)0; + struct air_int_rsp *intf_rsp = (struct air_int_rsp *)0; + struct sockaddr_in *ip_addr; + struct sockaddr_in subnet_mask; + Atm_addr_nsap *anp; + + /* + * Get the IP address and physical interface name + * associated with the network interface + */ + UM_ZERO(&air, sizeof(struct atminfreq)); + air.air_opcode = AIOCS_INF_NIF; + strcpy(air.air_netif_intf, aip->ai_intf); + len = do_info_ioctl(&air, sizeof(struct air_netif_rsp)); + if (len <= 0) { + goto if_ready_fail; + } + netif_rsp = (struct air_netif_rsp *)air.air_buf_addr; + + ip_addr = (struct sockaddr_in *)&netif_rsp->anp_proto_addr; + if (ip_addr->sin_family != AF_INET || + ip_addr->sin_addr.s_addr == 0) { + errno = EAFNOSUPPORT; + goto if_ready_fail; + } + + /* + * Get the MTU for the network interface + */ + mtu = get_mtu(aip->ai_intf); + if (mtu < 0) { + goto if_ready_fail; + } + + + /* + * Get the subnet mask associated with the + * network interface + */ + rc = get_subnet_mask(aip->ai_intf, &subnet_mask); + if (rc || subnet_mask.sin_family != AF_INET) { + goto if_ready_fail; + } + + /* + * Get physical interface information + */ + UM_ZERO(&air, sizeof(struct atminfreq)); + air.air_opcode = AIOCS_INF_INT; + strcpy(air.air_int_intf, netif_rsp->anp_phy_intf); + len = do_info_ioctl(&air, sizeof(struct air_int_rsp)); + if (len <= 0) { + goto if_ready_fail; + } + intf_rsp = (struct air_int_rsp *)air.air_buf_addr; + + /* + * Check the signalling manager + */ + if (intf_rsp->anp_sig_proto != ATM_SIG_UNI30 && + intf_rsp->anp_sig_proto != ATM_SIG_UNI31 && + intf_rsp->anp_sig_proto != ATM_SIG_UNI40) { + errno = EINVAL; + goto if_ready_fail; + } + + /* + * Check the interface state + */ + if (intf_rsp->anp_sig_state != UNISIG_ACTIVE) { + errno = EINVAL; + goto if_ready_fail; + } + + /* + * Check the address format + */ + if (intf_rsp->anp_addr.address_format != T_ATM_ENDSYS_ADDR && + !(intf_rsp->anp_addr.address_format == + T_ATM_E164_ADDR && + intf_rsp->anp_subaddr.address_format == + T_ATM_ENDSYS_ADDR)) { + errno = EINVAL; + goto if_ready_fail; + } + + /* + * Find the selector byte value for the interface + */ + for (i=0; i<strlen(aip->ai_intf); i++) { + if (aip->ai_intf[i] >= '0' && + aip->ai_intf[i] <= '9') + break; + } + sel = atoi(&aip->ai_intf[i]); + + /* + * Make sure we're the server for this interface's LIS + */ + if (!atmarp_is_server(aip)) { + rc = EINVAL; + goto if_ready_fail; + } + + /* + * If we already have the interface active and the address + * hasn't changed, return + */ + if (aip->ai_state != AI_STATE_NULL && + bcmp((caddr_t) &((struct sockaddr_in *) + &netif_rsp->anp_proto_addr)->sin_addr, + (caddr_t)&aip->ai_ip_addr, + sizeof(aip->ai_ip_addr)) == 0 && + ATM_ADDR_EQUAL(&intf_rsp->anp_addr, + &aip->ai_atm_addr) && + ATM_ADDR_EQUAL(&intf_rsp->anp_subaddr, + &aip->ai_atm_subaddr)) { + return(1); + } + + /* + * Delete any existing ATMARP cache entry for this interface + */ + ATMARP_LOOKUP(aip, aip->ai_ip_addr.s_addr, aap); + if (aap) { + ATMARP_DELETE(aip, aap); + UM_FREE(aap); + } + + /* + * Update the interface entry + */ + aip->ai_ip_addr = ((struct sockaddr_in *) + &netif_rsp->anp_proto_addr)->sin_addr; + aip->ai_subnet_mask = subnet_mask.sin_addr; + aip->ai_mtu = mtu + 8; + ATM_ADDR_COPY(&intf_rsp->anp_addr, + &aip->ai_atm_addr); + ATM_ADDR_COPY(&intf_rsp->anp_subaddr, + &aip->ai_atm_subaddr); + anp = (Atm_addr_nsap *)aip->ai_atm_addr.address; + if (aip->ai_atm_addr.address_format == T_ATM_ENDSYS_ADDR) { + anp->aan_sel = sel; + } else if (aip->ai_atm_addr.address_format == + T_ATM_E164_ADDR && + aip->ai_atm_subaddr.address_format == + T_ATM_ENDSYS_ADDR) { + anp->aan_sel = sel; + } + + /* + * Get a new ATMARP cache for the interface + */ + aap = (Atmarp *)UM_ALLOC(sizeof(Atmarp)); + if (!aap) { + atmarp_mem_err("atmarp_if_ready: sizeof(Atmarp)"); + } + UM_ZERO(aap, sizeof(Atmarp)); + + /* + * Fill out the entry + */ + aap->aa_dstip = aip->ai_ip_addr; + ATM_ADDR_COPY(&intf_rsp->anp_addr, &aap->aa_dstatm); + ATM_ADDR_COPY(&intf_rsp->anp_subaddr, + &aap->aa_dstatmsub); + aap->aa_key.key_len = SCSP_ATMARP_KEY_LEN; + scsp_cache_key(&aap->aa_dstatm, &aap->aa_dstip, + SCSP_ATMARP_KEY_LEN, aap->aa_key.key); + aap->aa_oid.id_len = SCSP_ATMARP_ID_LEN; + aap->aa_seq = SCSP_CSA_SEQ_MIN; + UM_COPY(&aap->aa_dstip.s_addr, aap->aa_oid.id, + SCSP_ATMARP_ID_LEN); + aap->aa_intf = aip; + aap->aa_flags = AAF_SERVER; + aap->aa_origin = UAO_LOCAL; + + /* + * Add the entry to the cache + */ + ATMARP_ADD(aip, aap); + + /* + * Free dynamic data + */ + UM_FREE(netif_rsp); + UM_FREE(intf_rsp); + + return(1); + +if_ready_fail: + if (netif_rsp) + UM_FREE(netif_rsp); + if (intf_rsp) + UM_FREE(intf_rsp); + + return(0); +} + + +/* + * Copy an ATMARP cache entry from kernel format into an entry + * suitable for our cache + * + * Arguments: + * cp pointer to kernel entry + * + * Returns: + * pointer to a new cache entry + * 0 error + * + */ +Atmarp * +atmarp_copy_cache_entry(cp) + struct air_arp_rsp *cp; + +{ + struct sockaddr_in *ipp; + Atmarp_intf *aip; + Atmarp *aap; + + /* + * Sanity checks + */ + if (!cp) + return((Atmarp *)0); + aip = atmarp_find_intf_name(cp->aap_intf); + if (!aip) + return((Atmarp *)0); + + /* + * Get a new cache entry + */ + aap = (Atmarp *)UM_ALLOC(sizeof(Atmarp)); + if (!aap) { + errno = ENOMEM; + return((Atmarp *)0); + } + UM_ZERO(aap, sizeof(Atmarp)); + aap->aa_intf = aip; + + /* + * Copy fields from the kernel entry to the new entry + */ + ipp = (struct sockaddr_in *)&cp->aap_arp_addr; + UM_COPY(&ipp->sin_addr.s_addr, &aap->aa_dstip.s_addr, + sizeof(aap->aa_dstip.s_addr)); + ATM_ADDR_COPY(&cp->aap_addr, &aap->aa_dstatm); + ATM_ADDR_COPY(&cp->aap_subaddr, &aap->aa_dstatmsub); + if (cp->aap_origin == UAO_PERM) + aap->aa_flags |= AAF_PERM; + aap->aa_origin = cp->aap_origin; + + /* + * Set up fields for SCSP + */ + aap->aa_key.key_len = SCSP_ATMARP_KEY_LEN; + scsp_cache_key(&cp->aap_addr, &aap->aa_dstip, + SCSP_ATMARP_KEY_LEN, (char *)aap->aa_key.key); + aap->aa_oid.id_len = SCSP_ATMARP_ID_LEN; + UM_COPY(&aip->ai_ip_addr.s_addr, aap->aa_oid.id, + SCSP_ATMARP_ID_LEN); + aap->aa_seq = SCSP_CSA_SEQ_MIN; + + return(aap); +} + + +/* + * Send an updated ATMARP cache entry to the kernel + * + * Arguments: + * aap pointer to updated entry + * + * Returns: + * 0 success + * errno reason for failure + * + */ +int +atmarp_update_kernel(aap) + Atmarp *aap; +{ + int rc = 0, sd; + struct atmaddreq aar; + struct sockaddr_in *ipp; + + /* + * Build ioctl request + */ + UM_ZERO(&aar, sizeof(aar)); + aar.aar_opcode = AIOCS_ADD_ARP; + strncpy(aar.aar_arp_intf, aap->aa_intf->ai_intf, + sizeof(aar.aar_arp_intf)); + aar.aar_arp_origin = UAO_SCSP; + ATM_ADDR_COPY(&aap->aa_dstatm, &aar.aar_arp_addr); + ipp = (struct sockaddr_in *)&aar.aar_arp_dst; + ipp->sin_family = AF_INET; +#if (defined(BSD) && (BSD >= 199103)) + ipp->sin_len = sizeof(struct sockaddr_in); +#endif + ipp->sin_addr = aap->aa_dstip; + + /* + * Pass the new mapping to the kernel + */ + sd = socket(AF_ATM, SOCK_DGRAM, 0); + if (sd < 0) { + return(errno); + } + if (ioctl(sd, AIOCADD, (caddr_t)&aar) < 0) { + rc = errno; + } + + (void)close(sd); + return(rc); +} + + +/* + * Read the ATMARP cache from the kernel and scan it, processing + * all entries + * + * Arguments: + * none + * + * Returns: + * none + * + */ +void +atmarp_get_updated_cache() +{ + int i, len, rc; + struct atminfreq air; + struct air_arp_rsp *cp; + struct sockaddr_in *ipp; + Atmarp_intf *aip; + Atmarp *aap; + + /* + * Set up the request + */ + air.air_opcode = AIOCS_INF_ARP; + air.air_arp_flags = ARP_RESET_REF; + ipp = (struct sockaddr_in *)&air.air_arp_addr; +#if (defined(BSD) && (BSD >= 199103)) + ipp->sin_len = sizeof(struct sockaddr_in); +#endif + ipp->sin_family = AF_INET; + ipp->sin_addr.s_addr = INADDR_ANY; + + /* + * Issue an ATMARP information request IOCTL + */ + len = do_info_ioctl(&air, sizeof(struct air_arp_rsp) * 200); + if (len < 0) { + return; + } + + /* + * Clear marks on all our cache entries + */ + atmarp_clear_marks(); + + /* + * Loop through the cache, processing each entry + */ + for (cp = (struct air_arp_rsp *) air.air_buf_addr; + len > 0; + cp++, len -= sizeof(struct air_arp_rsp)) { + atmarp_process_cache_entry(cp); + } + + /* + * Now delete any old entries that aren't in the kernel's + * cache any more + */ + for (aip = atmarp_intf_head; aip; aip = aip->ai_next) { + for (i = 0; i < ATMARP_HASHSIZ; i++) { + for (aap = aip->ai_arptbl[i]; aap; + aap = aap->aa_next) { + /* + * Don't delete the entry for the server + */ + if (aap->aa_flags & AAF_SERVER) + continue; + /* + * Delete any entry that isn't marked + */ + if (!aap->aa_mark) { + rc = atmarp_scsp_update(aap, + SCSP_ASTATE_DEL); + if (rc == 0) + ATMARP_DELETE(aip, aap); + } + } + } + } + + /* + * Free the ioctl response + */ + UM_FREE(air.air_buf_addr); +} + + +/* + * Process an ATMARP cache entry from the kernel. If we already + * have the entry in our local cache, update it, otherwise, add + * it. In either case, mark our local copy so we know it's still + * in the kernel's cache. + * + * Arguments: + * cp pointer to kernel's cache entry + * + * Returns: + * none + * + */ +void +atmarp_process_cache_entry(cp) + struct air_arp_rsp *cp; + +{ + int rc; + struct sockaddr_in *ipp = (struct sockaddr_in *)&cp->aap_arp_addr; + Atmarp_intf *aip; + Atmarp *aap; + + /* + * See whether the entry is for an interface that's + * both configured and up + */ + aip = atmarp_find_intf_name(cp->aap_intf); + if (!aip || aip->ai_state != AI_STATE_UP) + return; + + /* + * Make sure the entry is valid + */ + if (!(cp->aap_flags & ARPF_VALID)) + return; + + /* + * See whether we have the entry in our cache already + */ + ATMARP_LOOKUP(aip, ipp->sin_addr.s_addr, aap); + if (aap) { + /* + * We already have this in our cache--update it + */ + aap->aa_mark = 1; + if ((cp->aap_flags & ARPF_REFRESH) && + cp->aap_origin != UAO_SCSP) { + aap->aa_seq++; + rc = atmarp_scsp_update(aap, SCSP_ASTATE_UPD); + } + } else { + /* + * This is a new entry--add it to the cache + */ + aap = atmarp_copy_cache_entry(cp); + if (!aap) + return; + ATMARP_ADD(aip, aap); + aap->aa_mark = 1; + rc = atmarp_scsp_update(aap, SCSP_ASTATE_NEW); + } + + return; +} + + +/* + * Print an SCSP ID + * + * Arguments: + * df pointer to a FILE for the dump + * ip pointer to the SCSP ID to print + * + * Returns: + * None + * + */ +static void +print_scsp_id(df, ip) + FILE *df; + Scsp_id *ip; +{ + int i; + + fprintf(df, "\t next: 0x%0x\n", (u_long)ip->next); + fprintf(df, "\t id_len: %d\n", ip->id_len); + fprintf(df, "\t id: 0x"); + for (i = 0; i < ip->id_len; i++) { + fprintf(df, "%0x ", ip->id[i]); + } + fprintf(df, "\n"); +} + + +/* + * Print an SCSP cacke key + * + * Arguments: + * df pointer to a FILE for the dump + * cp pointer to the cacke key to print + * + * Returns: + * None + * + */ +static void +print_scsp_cache_key(df, cp) + FILE *df; + Scsp_ckey *cp; +{ + int i; + + fprintf(df, "\t key_len: %d\n", cp->key_len); + fprintf(df, "\t key: 0x"); + for (i = 0; i < cp->key_len; i++) { + fprintf(df, "%0x ", cp->key[i]); + } + fprintf(df, "\n"); +} + + +/* + * Print an ATMARP interface entry + * + * Arguments: + * df pointer to a FILE for the dump + * aip pointer to interface entry + * + * Returns: + * None + * + */ +void +print_atmarp_intf(df, aip) + FILE *df; + Atmarp_intf *aip; +{ + if (!aip) { + fprintf(df, "print_atmarp_intf: NULL interface entry address\n"); + return; + } + + fprintf(df, "ATMARP network interface entry at 0x%0x\n", + (u_long)aip); + fprintf(df, "\tai_next: 0x%0x\n", + (u_long)aip->ai_next); + fprintf(df, "\tai_intf: %s\n", aip->ai_intf); + fprintf(df, "\tai_ip_addr: %s\n", + format_ip_addr(&aip->ai_ip_addr)); + fprintf(df, "\tai_subnet_mask: %s\n", + inet_ntoa(aip->ai_subnet_mask)); + fprintf(df, "\tai_mtu: %d\n", aip->ai_mtu); + fprintf(df, "\tai_atm_addr: %s\n", + format_atm_addr(&aip->ai_atm_addr)); + fprintf(df, "\tai_atm_subaddr: %s\n", + format_atm_addr(&aip->ai_atm_subaddr)); + fprintf(df, "\tai_scsp_sock: %d\n", aip->ai_scsp_sock); + fprintf(df, "\tai_scsp_sockname: %s\n", aip->ai_scsp_sockname); + fprintf(df, "\tai_state: %d\n", aip->ai_state); + fprintf(df, "\tai_mark: %d\n", aip->ai_mark); +} + + +/* + * Print an ATMARP cache entry + * + * Arguments: + * df pointer to a FILE for the dump + * aap pointer to cache entry + * + * Returns: + * None + * + */ +void +print_atmarp_cache(df, aap) + FILE *df; + Atmarp *aap; +{ + if (!aap) { + fprintf(df, "print_atmarp_cache: NULL ATMARP entry address\n"); + return; + } + + fprintf(df, "ATMARP entry at 0x%0x\n", (u_long)aap); + fprintf(df, "\taa_next: 0x%0x\n", (u_long)aap->aa_next); + fprintf(df, "\taa_dstip: %s\n", inet_ntoa(aap->aa_dstip)); + fprintf(df, "\taa_dstatm: %s\n", + format_atm_addr(&aap->aa_dstatm)); + fprintf(df, "\taa_dstatmsub: %s\n", + format_atm_addr(&aap->aa_dstatmsub)); + fprintf(df, "\taa_key:\n"); + print_scsp_cache_key(df, &aap->aa_key); + fprintf(df, "\taa_oid:\n"); + print_scsp_id(df, &aap->aa_oid); + fprintf(df, "\taa_seq: %d (0x%x)\n", aap->aa_seq, + aap->aa_seq); + fprintf(df, "\taa_intf: 0x%0x\n", (u_long)aap->aa_intf); + fprintf(df, "\taa_flags: "); + if (aap->aa_flags & AAF_PERM) + fprintf(df, "Permanent "); + if (aap->aa_flags & AAF_SERVER) + fprintf(df, "Server "); + fprintf(df, "\n"); + fprintf(df, "\taa_origin: %d\n", aap->aa_origin); + fprintf(df, "\taa_mark: %d\n", aap->aa_mark); +} + + +/* + * Print the entire ATMARP cache + * + * Arguments: + * df pointer to a FILE for the dump + * aip pointer to interface whose cache is to be printed + * + * Returns: + * None + * + */ +void +dump_atmarp_cache(df, aip) + FILE *df; + Atmarp_intf *aip; +{ + int i; + Atmarp *aap; + + if (!aip) { + fprintf(df, "dump_atmarp_cache: NULL interface address\n"); + return; + } + + fprintf(df, "ATMARP cache for interface %s\n", aip->ai_intf); + for (i=0; i<ATMARP_HASHSIZ; i++) { + for (aap=aip->ai_arptbl[i]; aap; aap=aap->aa_next) { + print_atmarp_cache(df, aap); + } + } +} + + +#ifdef NOTDEF +/* + * Print an ATMARP super-LIS entry + * + * Arguments: + * df pointer to a FILE for the dump + * asp pointer to super-LIS entry to be printed + * + * Returns: + * None + * + */ +void +print_atmarp_slis(df, asp) + FILE *df; + Atmarp_slis *asp; +{ + Atmarp_intf **aipp; + + if (!asp) { + fprintf(df, "print_atmarp_slis: NULL SLIS address\n"); + return; + } + + fprintf(df, "SLIS entry at 0x%0x\n", (u_long)asp); + fprintf(df, "\tas_next: 0x%0x\n", (u_long)asp->as_next); + fprintf(df, "\tas_name: %s\n", asp->as_name); + fprintf(df, "\tas_cnt: %d\n", asp->as_cnt); + for (aipp = &asp->as_intfs; *aipp; aipp++) { + fprintf(df, "\t%s (%s)\n", (*aipp)->ai_name, + (*aipp)->ai_intf); + } +} +#endif + + +/* + * Dump ATMARPD information + * + * Called as the result of a SIGINT signal. + * + * Arguments: + * sig signal number + * + * Returns: + * None + * + */ +void +atmarp_sigint(sig) + int sig; +{ + Atmarp_intf *aip; + FILE *df; + char fname[64]; + static int dump_no = 0; + + /* + * Build a file name + */ + UM_ZERO(fname, sizeof(fname)); + sprintf(fname, "/tmp/atmarpd.%d.%03d.out", getpid(), dump_no++); + + /* + * Open the output file + */ + df = fopen(fname, "w"); + if (df == (FILE *)0) + return; + + /* + * Dump the interface control blocks and + * associated ATMARP caches + */ + for (aip = atmarp_intf_head; aip; aip = aip->ai_next) { + print_atmarp_intf(df, aip); + fprintf(df, "\n"); + dump_atmarp_cache(df, aip); + fprintf(df, "\n"); + } + + /* + * Close the output file + */ + (void)fclose(df); +} |