diff options
Diffstat (limited to 'lib/libatm/ioctl_subr.c')
-rw-r--r-- | lib/libatm/ioctl_subr.c | 515 |
1 files changed, 515 insertions, 0 deletions
diff --git a/lib/libatm/ioctl_subr.c b/lib/libatm/ioctl_subr.c new file mode 100644 index 0000000..a77d79f --- /dev/null +++ b/lib/libatm/ioctl_subr.c @@ -0,0 +1,515 @@ +/* + * + * =================================== + * 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: ioctl_subr.c,v 1.2 1998/07/10 17:09:20 root Exp $ + * + */ + +/* + * User Space Library Functions + * ---------------------------- + * + * IOCTL subroutines + * + */ + +#ifndef lint +static char *RCSid = "@(#) $Id: ioctl_subr.c,v 1.2 1998/07/10 17:09:20 root Exp $"; +#endif + +#include <sys/types.h> +#include <sys/param.h> + +#include <errno.h> +#include <sys/socket.h> +#include <sys/sockio.h> +#include <net/if.h> +#include <netinet/in.h> +#include <netatm/port.h> +#include <netatm/atm.h> +#include <netatm/atm_if.h> +#include <netatm/atm_sap.h> +#include <netatm/atm_sys.h> +#include <netatm/atm_ioctl.h> + +#include "libatm.h" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +extern char *prog; + + +/* + * Issue an informational IOCTL + * + * The user fills out the opcode and any subtype information. This + * routine will allocate a buffer and issue the IOCTL. If the request + * fails because the buffer wasn't big enough, this routine will double + * the buffer size and retry the request repeatedly. The buffer must + * be freed by the caller. + * + * Arguments: + * req pointer to an ATM information request IOCTL structure + * buf_len length of buffer to be allocated + * + * Returns: + * -1 error encountered (reason in errno) + * int length of the returned VCC information + * + */ +int +do_info_ioctl(req, buf_len) + struct atminfreq *req; + int buf_len; +{ + int rc, s; + caddr_t buf; + + /* + * Open a socket for the IOCTL + */ + s = socket(AF_ATM, SOCK_DGRAM, 0); + if (s < 0) { + return(-1); + } + + /* + * Get memory for returned information + */ +mem_retry: + buf = (caddr_t)UM_ALLOC(buf_len); + if (buf == NULL) { + errno = ENOMEM; + return(-1); + } + + /* + * Set the buffer address and length in the request + */ + req->air_buf_addr = buf; + req->air_buf_len = buf_len; + + /* + * Issue the IOCTL + */ + rc = ioctl(s, AIOCINFO, (caddr_t)req); + if (rc) { + UM_FREE(buf); + if (errno == ENOSPC) { + buf_len = buf_len * 2; + goto mem_retry; + } + return(-1); + } + (void)close(s); + /* + * Set a pointer to the returned info in the request + * and return its length + */ + req->air_buf_addr = buf; + return(req->air_buf_len); +} + + +/* + * Get VCC information + * + * Arguments: + * intf pointer to interface name (or null string) + * vccp pointer to a pointer to a struct air_vcc_rsp for the + * address of the returned VCC information + * + * Returns: + * int length of the retuned VCC information + * + */ +int +get_vcc_info(intf, vccp) + char *intf; + struct air_vcc_rsp **vccp; +{ + int buf_len = sizeof(struct air_vcc_rsp) * 100; + struct atminfreq air; + + /* + * Initialize IOCTL request + */ + air.air_opcode = AIOCS_INF_VCC; + UM_ZERO(air.air_vcc_intf, sizeof(air.air_vcc_intf)); + if (intf != NULL && strlen(intf) != 0) + strcpy(air.air_vcc_intf, intf); + + buf_len = do_info_ioctl(&air, buf_len); + + /* + * Return a pointer to the VCC info and its length + */ + *vccp = (struct air_vcc_rsp *) air.air_buf_addr; + return(buf_len); +} + + +/* + * Count number of open VCCs + * + * Issue a AIOCS_INF_VCC to get info on all open VCCs. Count them and + * return the answer. + * + * Arguments: + * intf pointer to interface name (or null string) + * + * Returns: + * int number of VCCs + * + */ +int +count_vccs ( intf ) +char *intf; +{ + int vcc_info_len; + int count = 0; + char *cp; + struct air_vcc_rsp *vcc_info, *vcc_info_base; + + vcc_info_len = get_vcc_info ( intf, &vcc_info ); + if ( !vcc_info ) + return ( 0 ); + vcc_info_base = vcc_info; + + for ( ; vcc_info_len >= sizeof ( struct air_vcc_rsp ); + vcc_info_len -= sizeof ( struct air_vcc_rsp ), + vcc_info++ ) { + count++; + } + free ( vcc_info_base ); + return ( count ); +} + + +/* + * Get subnet mask + * + * Arguments: + * intf pointer to an interface name + * mask pointer to a struct sockaddr_in to receive the mask + * + * Returns: + * 0 good completion + * -1 error + * + */ +int +get_subnet_mask(intf, mask) + char *intf; + struct sockaddr_in *mask; +{ + int rc, s; + struct ifreq req; + struct sockaddr_in *ip_mask; + + /* + * Check parameters + */ + if (!intf || !mask || + strlen(intf) == 0 || + strlen(intf) > IFNAMSIZ-1) + return(-1); + + /* + * Open a socket for the IOCTL + */ + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) + return(-1); + + /* + * Set up and issue the IOCTL + */ + UM_ZERO(&req, sizeof(req)); + strcpy(req.ifr_name, intf); + rc = ioctl(s, SIOCGIFNETMASK, (caddr_t)&req); + (void)close(s); + if (rc) + return(-1); + + /* + * Give the answer back to the caller + */ + ip_mask = (struct sockaddr_in *)&req.ifr_addr; + *mask = *ip_mask; + mask->sin_family = AF_INET; + + return(0); +} + + +/* + * Get an interface's MTU + * + * Arguments: + * intf pointer to an interface name + * mtu pointer to an int to receive the MTU + * + * Returns: + * >= 0 interface MTU + * -1 error + * + */ +int +get_mtu(intf) + char *intf; +{ + int rc, s; + struct ifreq req; + + /* + * Check parameters + */ + if (!intf || strlen(intf) == 0 || + strlen(intf) > IFNAMSIZ-1) + return(-1); + + /* + * Open a socket for the IOCTL + */ + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) + return(-1); + + /* + * Set up and issue the IOCTL + */ + UM_ZERO(&req, sizeof(req)); + strcpy(req.ifr_name, intf); + rc = ioctl(s, SIOCGIFMTU, (caddr_t)&req); + (void)close(s); + + /* + * Set the appropriate return value + */ + if (rc) + return(-1); + else + return(req.ifr_mtu); +} + + +/* + * Verify netif name + * + * This routine issues an IOCTL to check whether the passed string is + * a valid network interface name. + * + * Arguments: + * req pointer to an ATM information request IOCTL structure + * + * Returns: + * -1 error encountered + * FALSE (0) the string is not a NIF name + * TRUE (> 0) the string is a valid NIF name + * + */ +int +verify_nif_name(name) + char *name; +{ + int rc, s; + caddr_t buf; + struct atminfreq air; + struct air_netif_rsp *nif_info; + + /* + * Check whether name is of a valid length + */ + if (strlen(name) > IFNAMSIZ - 1 || + strlen(name) < 1) { + return(FALSE); + } + + /* + * Open a socket for the IOCTL + */ + s = socket(AF_ATM, SOCK_DGRAM, 0); + if (s < 0) { + return(-1); + } + + /* + * Get memory for returned information + */ + nif_info = (struct air_netif_rsp *)UM_ALLOC( + sizeof(struct air_netif_rsp)); + if (nif_info == NULL) { + errno = ENOMEM; + return(-1); + } + + /* + * Set up the request + */ + air.air_opcode = AIOCS_INF_NIF; + air.air_buf_addr = (caddr_t)nif_info; + air.air_buf_len = sizeof(struct air_netif_rsp); + UM_ZERO(air.air_netif_intf, sizeof(air.air_netif_intf)); + strcpy(air.air_netif_intf, name); + + /* + * Issue the IOCTL + */ + rc = ioctl(s, AIOCINFO, (caddr_t)&air); + UM_FREE(nif_info); + (void)close(s); + + /* + * Base return value on IOCTL return code + */ + if (rc) + return(FALSE); + else + return(TRUE); +} + +/* + * Get Config information + * + * Arguments: + * intf pointer to interface name (or null string) + * cfgp pointer to a pointer to a struct air_cfg_rsp for the + * address of the returned Config information + * + * Returns: + * int length of returned Config information + * + */ +int +get_cfg_info ( intf, cfgp ) + char *intf; + struct air_cfg_rsp **cfgp; +{ + int buf_len = sizeof(struct air_cfg_rsp) * 4; + struct atminfreq air; + + /* + * Initialize IOCTL request + */ + air.air_opcode = AIOCS_INF_CFG; + UM_ZERO ( air.air_cfg_intf, sizeof(air.air_cfg_intf)); + if ( intf != NULL && strlen(intf) != 0 ) + strcpy ( air.air_cfg_intf, intf ); + + buf_len = do_info_ioctl ( &air, buf_len ); + + /* + * Return a pointer to the Config info and its length + */ + *cfgp = (struct air_cfg_rsp *) air.air_buf_addr; + return ( buf_len ); + +} + +/* + * Get Physical Interface information + * + * Arguments: + * intf pointer to interface name (or null string) + * intp pointer to a pointer to a struct air_cfg_rsp for the + * address of the returned Config information + * + * Returns: + * int length of returned Config information + * + */ +int +get_intf_info ( intf, intp ) + char *intf; + struct air_int_rsp **intp; +{ + int buf_len = sizeof(struct air_int_rsp) * 4; + struct atminfreq air; + + /* + * Initialize IOCTL request + */ + air.air_opcode = AIOCS_INF_INT; + UM_ZERO ( air.air_int_intf, sizeof(air.air_int_intf)); + if ( intf != NULL && strlen(intf) != 0 ) + strcpy ( air.air_int_intf, intf ); + + buf_len = do_info_ioctl ( &air, buf_len ); + + /* + * Return a pointer to the Physical Interface info and its length + */ + *intp = (struct air_int_rsp *) air.air_buf_addr; + return ( buf_len ); + +} + + +/* + * Get Netif information + * + * Arguments: + * intf pointer to interface name (or null string) + * netp pointer to a pointer to a struct air_netif_rsp for the + * address of the returned Netif information + * + * Returns: + * int length of returned Netif information + * + */ +int +get_netif_info ( intf, netp ) + char *intf; + struct air_netif_rsp **netp; +{ + int buf_len = sizeof(struct air_netif_rsp) * 10; + struct atminfreq air; + + /* + * Initialize IOCTL request + */ + air.air_opcode = AIOCS_INF_NIF; + UM_ZERO ( air.air_int_intf, sizeof(air.air_int_intf) ); + if ( intf != NULL && strlen(intf) != 0 ) + strcpy ( air.air_int_intf, intf ); + + buf_len = do_info_ioctl ( &air, buf_len ); + + /* + * Return a pointer to the Netif info and its length + */ + *netp = (struct air_netif_rsp *) air.air_buf_addr; + return ( buf_len ); + +} + + |