diff options
Diffstat (limited to 'usr.sbin/atm/scspd/scsp_config.c')
-rw-r--r-- | usr.sbin/atm/scspd/scsp_config.c | 1160 |
1 files changed, 1160 insertions, 0 deletions
diff --git a/usr.sbin/atm/scspd/scsp_config.c b/usr.sbin/atm/scspd/scsp_config.c new file mode 100644 index 000000000000..99eca7af628a --- /dev/null +++ b/usr.sbin/atm/scspd/scsp_config.c @@ -0,0 +1,1160 @@ +/* + * + * =================================== + * 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: scsp_config.c,v 1.3 1998/08/13 20:11:14 johnc Exp $ + * + */ + +/* + * Server Cache Synchronization Protocol (SCSP) Support + * ---------------------------------------------------- + * + * Configuration file processing + * + */ + +#ifndef lint +static char *RCSid = "@(#) $Id: scsp_config.c,v 1.3 1998/08/13 20:11:14 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 <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_sys.h> +#include <netatm/atm_ioctl.h> + +#include <libatm.h> +#include "scsp_msg.h" +#include "scsp_if.h" +#include "scsp_var.h" + + +/* + * Global variables + */ +FILE *cfg_file; +Scsp_server *current_server; +Scsp_dcs *current_dcs; + + + +/* + * Process the configuration file + * + * This routine is called when the daemon starts, and it can also be + * called while it is running, as the result of a SIGHUP signal. It + * therefore has to be capable of both configuring the daemon from + * scratch and modifying the configuration of a running daemon. + * + * Arguments: + * cfn configuration file name + * + * Returns: + * 0 configuration read with no errors + * else error found in configuration file + * + */ +int +scsp_config(cfn) + char *cfn; +{ + int rc; + Scsp_server *ssp, *snext; + + /* + * Open the configuration file + */ + cfg_file = fopen(cfn, "r"); + if (!cfg_file) { + scsp_log(LOG_ERR, "can't open config file %s", + (void *)cfn); + exit(1); + } + + /* + * Initialize current interface pointer + */ + current_server = (Scsp_server *)0; + + /* + * Clear marks on any existing servers + */ + for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) { + ssp->ss_mark = 0; + } + + /* + * Scan the configuration file, processing each line as + * it is read + */ + rc = yyparse(); + + /* + * Close the configuration file + */ + fclose(cfg_file); + + /* + * Delete any server entries that weren't updated + */ + for (ssp = scsp_server_head; ssp; ssp = snext) { + snext = ssp->ss_next; + if (!ssp->ss_mark) + scsp_server_delete(ssp); + } + + return(rc); +} + + +/* + * Prepare for SCSP DCS setup + * + * This routine is called from yyparse() when a DCS command is found. + * + * Arguments: + * none + * + * Returns: + * 0 success + * 1 error encountered + * + */ +int +start_dcs() +{ + Scsp_dcs *dcsp; + + /* + * Make sure we have a current server block + */ + if (!current_server) { + parse_error("server not found"); + return(1); + } + + /* + * Allocate a DCS block + */ + dcsp = (Scsp_dcs *)UM_ALLOC(sizeof(Scsp_dcs)); + if (!dcsp) { + scsp_mem_err("start_dcs: sizeof(Scsp_dcs)"); + } + UM_ZERO(dcsp, sizeof(Scsp_dcs)); + + /* + * Fill out DCS links and default values + */ + dcsp->sd_server = current_server; + dcsp->sd_addr.address_format = T_ATM_ABSENT; + dcsp->sd_subaddr.address_format = T_ATM_ABSENT; + dcsp->sd_sock = -1; + dcsp->sd_ca_rexmt_int = SCSP_CAReXmitInterval; + dcsp->sd_csus_rexmt_int = SCSP_CSUSReXmitInterval; + dcsp->sd_hops = SCSP_CSA_HOP_CNT; + dcsp->sd_csu_rexmt_int = SCSP_CSUReXmitInterval; + dcsp->sd_csu_rexmt_max = SCSP_CSUReXmitMax; + LINK2TAIL(dcsp, Scsp_dcs, current_server->ss_dcs, sd_next); + + current_dcs = dcsp; + return(0); +} + + +/* + * Finish up server configuration + * + * This routine is called from yyparse() to at the end of a DCS + * command. It checks that required fields are set and finishes + * up the DCS block. + * + * Arguments: + * none + * + * Returns: + * 0 success + * 1 error encountered + * + */ +int +finish_dcs() +{ + int rc = 0; + Scsp_dcs *dcsp; + Scsp_server *ssp; + + /* + * Make sure we have a current server block and DCS block + */ + if (!current_server) { + parse_error("server not found"); + return(1); + } + + if (!current_dcs) { + parse_error("server not found"); + return(1); + } + ssp = current_server; + dcsp = current_dcs; + + /* + * Make sure the DCS ID is set + */ + if (dcsp->sd_dcsid.id_len == 0) { + parse_error("DCS ID not set"); + rc++; + } + + /* + * Make sure the ATM address is set + */ + if (dcsp->sd_addr.address_format == T_ATM_ABSENT) { + parse_error("DCS ATM address not set"); + rc++; + } + + current_dcs = (Scsp_dcs *)0; + return(rc); +} + + +/* + * Configure DCS ATM address + * + * This routine is called from yyparse() to process an ATMaddr command. + * + * Arguments: + * ap pointer to DCS's ATM address (in ASCII) + * sap pointer to DCS's ATM subaddress (in ASCII) + * + * Returns: + * 0 success + * 1 error encountered + * + */ +int +set_dcs_addr(ap, sap) + char *ap, *sap; +{ + Scsp_dcs *dcsp; + Atm_addr addr, subaddr; + + /* + * Make sure we have a current server block and DCS block + */ + if (!current_server) { + parse_error("server not found"); + return(1); + } + + if (!current_dcs) { + parse_error("server not found"); + return(1); + } + dcsp = current_dcs; + + /* + * Initialize + */ + UM_ZERO(&addr, sizeof(addr)); + addr.address_format = T_ATM_ABSENT; + UM_ZERO(&subaddr, sizeof(subaddr)); + subaddr.address_format = T_ATM_ABSENT; + + /* + * Convert the ATM address from character to internal format + */ + if (ap) { + addr.address_length = get_hex_atm_addr(ap, + (u_char *)addr.address, strlen(ap)); + if (addr.address_length == 0) { + parse_error("invalid ATM address"); + return(1); + } + if (addr.address_length == sizeof(Atm_addr_nsap)) { + addr.address_format = T_ATM_ENDSYS_ADDR; + } else if (addr.address_length <= + sizeof(Atm_addr_e164)) { + addr.address_format = T_ATM_E164_ADDR; + } else { + parse_error("invalid ATM address"); + return(1); + } + } + + /* + * Convert the ATM subaddress from character to internal format + */ + if (sap) { + subaddr.address_length = get_hex_atm_addr(sap, + (u_char *)subaddr.address, strlen(sap)); + if (subaddr.address_length == 0) { + parse_error("invalid ATM address"); + return(1); + } + if (subaddr.address_length == sizeof(Atm_addr_nsap)) { + subaddr.address_format = T_ATM_ENDSYS_ADDR; + } else if (subaddr.address_length <= + sizeof(Atm_addr_e164)) { + subaddr.address_format = T_ATM_E164_ADDR; + } else { + parse_error("invalid ATM subaddress"); + return(1); + } + } + + /* + * Make sure we have a legal ATM address type combination + */ + if (((addr.address_format != T_ATM_ENDSYS_ADDR) || + (subaddr.address_format != T_ATM_ABSENT)) && + ((addr.address_format != T_ATM_E164_ADDR) || + (subaddr.address_format != T_ATM_ENDSYS_ADDR))) { + parse_error("invalid address/subaddress combination"); + return(1); + } + + /* + * Save the address and subaddress + */ + ATM_ADDR_COPY(&addr, &dcsp->sd_addr); + ATM_ADDR_COPY(&subaddr, &dcsp->sd_subaddr); + + return(0); +} + + +/* + * Configure CA retransmit interval for DCS + * + * This routine is called from yyparse() to process a CAReXmitInt + * command. + * + * Arguments: + * val time interval + * + * Returns: + * 0 success + * 1 error encountered + * + */ +int +set_dcs_ca_rexmit(val) + int val; +{ + Scsp_dcs *dcsp; + + /* + * Make sure we have a current server block and DCS block + */ + if (!current_server) { + parse_error("server not found"); + return(1); + } + + if (!current_dcs) { + parse_error("server not found"); + return(1); + } + dcsp = current_dcs; + + + /* + * Validate the interval + */ + if (val <= 0 || val > 1024) { + parse_error("invalid CA retransmit interval"); + return(1); + } + + /* + * Set CA retransmit interval + */ + dcsp->sd_ca_rexmt_int = val; + + return(0); +} + + +/* + * Configure CSUS retransmit interval for DCS + * + * This routine is called from yyparse() to process a CSUSReXmitInt + * command. + * + * Arguments: + * val time interval + * + * Returns: + * 0 success + * 1 error encountered + * + */ +int +set_dcs_csus_rexmit(val) + int val; +{ + Scsp_dcs *dcsp; + + /* + * Make sure we have a current server block and DCS block + */ + if (!current_server) { + parse_error("server not found"); + return(1); + } + + if (!current_dcs) { + parse_error("server not found"); + return(1); + } + dcsp = current_dcs; + + + /* + * Validate the interval + */ + if (val <= 0 || val > 1024) { + parse_error("invalid CSUS retransmit interval"); + return(1); + } + + /* + * Set CSUS retransmit interval + */ + dcsp->sd_csus_rexmt_int = val; + + return(0); +} + + +/* + * Configure CSU retransmit interval for DCS + * + * This routine is called from yyparse() to process a CSUReXmitInt + * command. + * + * Arguments: + * val time interval + * + * Returns: + * 0 success + * 1 error encountered + * + */ +int +set_dcs_csu_rexmit(val) + int val; +{ + Scsp_dcs *dcsp; + + /* + * Make sure we have a current server block and DCS block + */ + if (!current_server) { + parse_error("server not found"); + return(1); + } + + if (!current_dcs) { + parse_error("server not found"); + return(1); + } + dcsp = current_dcs; + + + /* + * Validate the interval + */ + if (val <= 0 || val > 1024) { + parse_error("invalid CSU retransmit interval"); + return(1); + } + + /* + * Set CSU retransmit interval + */ + dcsp->sd_csu_rexmt_int = val; + + return(0); +} + + +/* + * Configure CSU retransmit limit for DCS + * + * This routine is called from yyparse() to process a CSUReXmitMax + * command. + * + * Arguments: + * val time interval + * + * Returns: + * 0 success + * 1 error encountered + * + */ +int +set_dcs_csu_rexmit_max(val) + int val; +{ + Scsp_dcs *dcsp; + + /* + * Make sure we have a current server block and DCS block + */ + if (!current_server) { + parse_error("server not found"); + return(1); + } + + if (!current_dcs) { + parse_error("server not found"); + return(1); + } + dcsp = current_dcs; + + + /* + * Validate the interval + */ + if (val <= 0 || val > 1024) { + parse_error("invalid CSU retransmit maximum"); + return(1); + } + + /* + * Set CSU retransmit limit + */ + dcsp->sd_csu_rexmt_max = val; + + return(0); +} + + +/* + * Configure Hello dead factor for DCS + * + * This routine is called from yyparse() to process a HelloDead + * command. + * + * Arguments: + * val number of times Hello interval has to expire before + * a DCS is considered dead + * + * Returns: + * 0 success + * 1 error encountered + * + */ +int +set_dcs_hello_df(val) + int val; +{ + Scsp_dcs *dcsp; + + /* + * Make sure we have a current server block and DCS block + */ + if (!current_server) { + parse_error("server not found"); + return(1); + } + + if (!current_dcs) { + parse_error("server not found"); + return(1); + } + dcsp = current_dcs; + + + /* + * Validate the limit + */ + if (val <= 0 || val > 1024) { + parse_error("invalid Hello dead factor"); + return(1); + } + + /* + * Set Hello dead factor + */ + dcsp->sd_hello_df = val; + + return(0); +} + + +/* + * Configure Hello interval for DCS + * + * This routine is called from yyparse() to process a HelloInt + * command. + * + * Arguments: + * val time interval + * + * Returns: + * 0 success + * 1 error encountered + * + */ +int +set_dcs_hello_int(val) + int val; +{ + Scsp_dcs *dcsp; + + /* + * Make sure we have a current server block and DCS block + */ + if (!current_server) { + parse_error("server not found"); + return(1); + } + + if (!current_dcs) { + parse_error("server not found"); + return(1); + } + dcsp = current_dcs; + + + /* + * Validate the interval + */ + if (val <= 0 || val > 1024) { + parse_error("invalid Hello interval"); + return(1); + } + + /* + * Set Hello interval + */ + dcsp->sd_hello_int = val; + + return(0); +} + + +/* + * Configure hop count for SCSP server + * + * This routine is called from yyparse() to process a Hops command. + * + * Arguments: + * hops number of hops + * + * Returns: + * 0 success + * 1 error encountered + * + */ +int +set_dcs_hops(hops) + int hops; +{ + Scsp_dcs *dcsp; + + /* + * Make sure we have a current server block and DCS block + */ + if (!current_server) { + parse_error("server not found"); + return(1); + } + + if (!current_dcs) { + parse_error("server not found"); + return(1); + } + dcsp = current_dcs; + + + /* + * Validate the count + */ + if (hops <= 0 || hops > 1024) { + parse_error("invalid hop count"); + return(1); + } + + /* + * Set hop count + */ + dcsp->sd_hops = hops; + + return(0); +} + + +/* + * Configure DCS ID + * + * This routine is called from yyparse() to process an ID command. + * + * Arguments: + * name pointer to DCS's DNS name or IP address (in ASCII) + * + * Returns: + * 0 success + * 1 error encountered + * + */ +int +set_dcs_id(name) + char *name; +{ + Scsp_dcs *dcsp; + Scsp_server *ssp; + struct sockaddr_in *ip_addr; + + /* + * Make sure we have a current server block and DCS block + */ + if (!current_server) { + parse_error("server not found"); + return(1); + } + + if (!current_dcs) { + parse_error("server not found"); + return(1); + } + ssp = current_server; + dcsp = current_dcs; + + /* + * Convert the DNS name or IP address + */ + ip_addr = get_ip_addr(name); + if (!ip_addr) { + parse_error("invalid DCS IP address"); + return(1); + } + + /* + * Verify the address length + */ + if (ssp->ss_id_len != sizeof(ip_addr->sin_addr)) { + parse_error("invalid DCS ID length"); + return(1); + } + + /* + * Set the ID in the DCS block + */ + dcsp->sd_dcsid.id_len = ssp->ss_id_len; + UM_COPY(&ip_addr->sin_addr, dcsp->sd_dcsid.id, ssp->ss_id_len); + + return(0); +} + + +/* + * Configure network interface for SCSP server + * + * This routine is called from yyparse() to process a Netif command. + * It verifies the network interface name, gets interface information + * from the kernel, and sets the appropriate fields in the server + * control block. + * + * Arguments: + * netif pointer to network interface name + * + * Returns: + * 0 success + * 1 error encountered + * + */ +int +set_intf(netif) + char *netif; +{ + int rc; + Scsp_server *ssp; + + /* + * Get the current network interface address + */ + ssp = current_server; + if (!ssp) { + parse_error("Server not found"); + rc = 1; + goto set_intf_done; + } + + /* + * Make sure we're configuring a valid + * network interface + */ + rc = verify_nif_name(netif); + if (rc == 0) { + parse_error("%s is not a valid network interface", + (void *)netif); + rc = 1; + goto set_intf_done; + } else if (rc < 0) { + scsp_log(LOG_ERR, "Netif name verify error"); + exit(1); + } + + /* + * Save the server's network interface name + */ + strcpy(ssp->ss_intf, netif); + rc = 0; + +set_intf_done: + return(rc); +} + + +/* + * Configure protocol for SCSP server + * + * This routine is called from yyparse() to process a Protocol command. + * + * Arguments: + * proto SCSP protocol being configured + * + * Returns: + * 0 success + * 1 error encountered + * + */ +int +set_protocol(proto) + int proto; +{ + Scsp_server *ssp; + + /* + * Get address of current server block + */ + ssp = current_server; + if (!ssp) { + parse_error("server not found"); + return(1); + } + + /* + * Process based on protocol ID + */ + switch(proto) { + case SCSP_PROTO_ATMARP: + ssp->ss_pid = proto; + ssp->ss_id_len = SCSP_ATMARP_ID_LEN; + ssp->ss_ckey_len = SCSP_ATMARP_KEY_LEN; + break; + case SCSP_PROTO_NHRP: + ssp->ss_pid = proto; + ssp->ss_id_len = SCSP_NHRP_ID_LEN; + ssp->ss_ckey_len = SCSP_NHRP_KEY_LEN; + break; + case SCSP_PROTO_MARS: + case SCSP_PROTO_DHCP: + case SCSP_PROTO_LNNI: + default: + parse_error("invalid protocol"); + return(1); + } + + return(0); +} + + +/* + * Configure server group for SCSP server + * + * This routine is called from yyparse() to process a ServerGroupID + * command. + * + * Arguments: + * sgid server group id + * + * Returns: + * 0 success + * 1 error encountered + * + */ +int +set_server_group(sgid) + int sgid; +{ + Scsp_server *ssp; + + /* + * Get address of current server block + */ + ssp = current_server; + if (!ssp) { + parse_error("server not found"); + return(1); + } + + /* + * Validate server group ID + */ + if (sgid <= 0) { + parse_error("invalid server group ID"); + return(1); + } + + /* + * Save the ID + */ + ssp->ss_sgid = sgid; + + return(0); +} + + +/* + * Prepare for SCSP server setup + * + * This routine is called from yyparse() when a Server statment is + * found. + * + * Arguments: + * name pointer to LIS name + * + * Returns: + * 0 success + * else error encountered + * + */ +int +start_server(name) + char *name; +{ + int i; + Scsp_server *ssp; + Scsp_dcs *dcsp, *next_dcs; + Scsp_cse *csep, *next_cse; + + /* + * See if we already have an entry for this name + */ + for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) { + if (strcasecmp(ssp->ss_name, name) == 0) + break; + } + + if (ssp) { + /* + * Log the fact that we're updating the entry + */ + scsp_log(LOG_INFO, "updating server entry for %s", + (void *)name); + + /* + * Free the existing cache + */ + for (i = 0; i < SCSP_HASHSZ; i++) { + for (csep = ssp->ss_cache[i]; csep; + csep = next_cse) { + next_cse = csep->sc_next; + UNLINK(csep, Scsp_cse, ssp->ss_cache[i], + sc_next); + UM_FREE(csep); + } + } + + /* + * Delete existing DCS blocks + */ + for (dcsp = ssp->ss_dcs; dcsp; dcsp = next_dcs) { + next_dcs = dcsp->sd_next; + scsp_dcs_delete(dcsp); + } + } else { + /* + * Get a new server entry + */ + ssp = (Scsp_server *)UM_ALLOC(sizeof(Scsp_server)); + if (!ssp) { + scsp_log(LOG_ERR, "unable to allocate server entry"); + exit(1); + } + UM_ZERO(ssp, sizeof(Scsp_server)); + ssp->ss_sock = -1; + ssp->ss_dcs_lsock = -1; + + /* + * Set the name + */ + ssp->ss_name = strdup(name); + + /* + * Link in the new interface entry + */ + LINK2TAIL(ssp, Scsp_server, scsp_server_head, + ss_next); + } + + /* + * If the mark is already set, this is a duplicate command + */ + if (ssp->ss_mark) { + parse_error("duplicate server \"%s\"", name); + return(1); + } + + /* + * Make this the current interface + */ + current_server = ssp; + + return(0); +} + + +/* + * Finish up server configuration + * + * This routine is called from yyparse() when the end of a server + * statement is reached. It checks that required fields are set + * and marks the entry as processed. + * + * Arguments: + * None + * + * Returns: + * 0 OK + * 1 Error + * + */ +int +finish_server() +{ + int rc = 0; + Scsp_server *ssp; + + /* + * Get the current network interface address + */ + ssp = current_server; + if (!ssp) { + parse_error("Server not found"); + rc++; + } + + /* + * Mark the interface as processed + */ + ssp->ss_mark = 1; + + /* + * Make sure the interface has been configured + */ + if (ssp->ss_intf == (char *)0) { + parse_error("netif missing from server specification"); + rc++; + } + + /* + * Make sure the protocol is set + */ + if (ssp->ss_pid == 0) { + parse_error("protocol missing from server specification"); + rc++; + } + + /* + * Make sure the server group is set + */ + if (ssp->ss_sgid == 0) { + parse_error("server group ID missing from server specification"); + rc++; + } + + /* + * Make sure at least one DCS is configured + */ + if (ssp->ss_dcs == (Scsp_dcs *)0) { + parse_error("no DCS configured for server"); + rc++; + } + + /* + * Mark the end of the server + */ + current_server = (Scsp_server *)0; + + return(rc); +} + + +/* + * Configure log file for SCSP server + * + * This routine is called from yyparse() to process a log File command. + * + * Arguments: + * file name of logging file + * + * Returns: + * 0 success + * 1 error encountered + * + */ +int +set_log_file(file) + char *file; +{ + /* + * Make sure we haven't already got a log file + */ + if (scsp_log_file) { + parse_error("multiple log files specified"); + return(1); + } + + /* + * Open the file + */ + scsp_log_file = fopen(file, "a"); + if (!scsp_log_file) { + parse_error("can't open log file"); + return(1); + } + + return(0); +} |