aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/atm/scspd/scsp_config.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/atm/scspd/scsp_config.c')
-rw-r--r--usr.sbin/atm/scspd/scsp_config.c1160
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);
+}