diff options
author | phk <phk@FreeBSD.org> | 1998-09-15 08:23:17 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 1998-09-15 08:23:17 +0000 |
commit | c3dd1fa899d435ea4bf79897f646a93cb80c94ac (patch) | |
tree | 98dfbc96e3c6aa7ff1f322855f6484c4e609819d /usr.sbin/atm/scspd/scspd.c | |
parent | 9ed6892f4808d56de443849229e151f8f7ad43b0 (diff) | |
download | FreeBSD-src-c3dd1fa899d435ea4bf79897f646a93cb80c94ac.zip FreeBSD-src-c3dd1fa899d435ea4bf79897f646a93cb80c94ac.tar.gz |
Add new files for HARP3
Host ATM Research Platform (HARP), Network Computing Services, Inc.
This software was developed with the support of the Defense Advanced
Research Projects Agency (DARPA).
Diffstat (limited to 'usr.sbin/atm/scspd/scspd.c')
-rw-r--r-- | usr.sbin/atm/scspd/scspd.c | 545 |
1 files changed, 545 insertions, 0 deletions
diff --git a/usr.sbin/atm/scspd/scspd.c b/usr.sbin/atm/scspd/scspd.c new file mode 100644 index 0000000..74fe868 --- /dev/null +++ b/usr.sbin/atm/scspd/scspd.c @@ -0,0 +1,545 @@ +/* + * + * =================================== + * 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: scspd.c,v 1.6 1998/08/21 18:08:25 johnc Exp $ + * + */ + + +/* + * Server Cache Synchronization Protocol (SCSP) Support + * ---------------------------------------------------- + * + * SCSP server daemon main line code + * + */ + + +#ifndef lint +static char *RCSid = "@(#) $Id: scspd.c,v 1.6 1998/08/21 18:08:25 johnc Exp $"; +#endif + +#include <sys/types.h> +#include <sys/param.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <syslog.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in.h> +#include <sys/ttycom.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 + */ +char *prog; +char *scsp_config_file = SCSPD_CONFIG; +FILE *scsp_log_file = (FILE *)0; +int scsp_log_syslog = 0; +Scsp_server *scsp_server_head = (Scsp_server *)0; +Scsp_pending *scsp_pending_head = (Scsp_pending *)0; +int scsp_max_socket = -1; +int scsp_debug_mode = 0; +int scsp_trace_mode = 0; + + +/* + * Local variables + */ +static int scsp_hup_signal = 0; +static int scsp_int_signal = 0; + + +/* + * SIGHUP signal handler + * + * Arguments: + * sig signal number + * + * Returns: + * none + * + */ +void +scsp_sighup(sig) + int sig; +{ + /* + * Flag the signal + */ + scsp_hup_signal = 1; +} + + +/* + * SIGINT signal handler + * + * Arguments: + * sig signal number + * + * Returns: + * none + * + */ +void +scsp_sigint(sig) + int sig; +{ + /* + * Flag the signal + */ + scsp_int_signal = 1; +} + + +/* + * Process command line parameters + * + * Arguments: + * argc number of command-line arguments + * argv list of pointers to command-line arguments + * + * Returns: + * none + * + */ +void +initialize(argc, argv) + int argc; + char **argv; +{ + int i; + char *cp; + + /* + * Save program name, ignoring any path components + */ + if (prog = (char *)strrchr(argv[0], '/')) + prog++; + else + prog = argv[0]; + + /* + * Make sure we're being invoked by the super user + */ + i = getuid(); + if (i != 0) { + fprintf(stderr, "%s: You must be root to run this program\n", + prog); + exit(1); + } + + /* + * Check for command-line options + */ + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-d") == 0) { + /* + * -d option -- set debug mode + */ + scsp_debug_mode = 1; + } else if (strcmp(argv[i], "-f") == 0) { + /* + * -f option -- set config file name + */ + i++; + if (i >= argc) { + fprintf(stderr, "%s: Configuration file name missing\n", + prog); + exit(1); + } + scsp_config_file = argv[i]; + } else if (strncmp(argv[i], "-T", 2) == 0) { + /* + * -T option -- trace options + */ + for (cp = &argv[i][2]; *cp; cp++) { + if (*cp == 'c') + scsp_trace_mode |= SCSP_TRACE_CAFSM; + else if (*cp == 'h') + scsp_trace_mode |= SCSP_TRACE_HFSM; + else if (*cp == 'i') + scsp_trace_mode |= SCSP_TRACE_CFSM; + else if (*cp == 'C') + scsp_trace_mode |= SCSP_TRACE_CA_MSG; + else if (*cp == 'H') + scsp_trace_mode |= SCSP_TRACE_HELLO_MSG; + else if (*cp == 'I') + scsp_trace_mode |= SCSP_TRACE_IF_MSG; + else + fprintf(stderr, "Invalid trace specification '%c' ignored\n", + *cp); + } + } else { + /* + * Error -- unrecognized option + */ + fprintf(stderr, "%s: Unrecognized option \"%s\"\n", + prog, argv[i]); + exit(1); + } + } +} + + +/* + * Daemon housekeeping + * + * Arguments: + * None + * + * Returns: + * None + * + */ +static void +start_daemon() + +{ + int dpid, fd, file_count, rc; + + /* + * Ignore selected signals + */ +#ifdef SIGTTOU + signal(SIGTTOU, SIG_IGN); +#endif +#ifdef SIGTTIN + signal(SIGTTIN, SIG_IGN); +#endif +#ifdef SIGTSTP + signal(SIGTSTP, SIG_IGN); +#endif +#ifdef SIGPIPE + signal(SIGPIPE, SIG_IGN); +#endif + + + /* + * Don't put the daemon into the background if + * we're in debug mode + */ + if (scsp_debug_mode) + goto daemon_bypass; + + /* + * Put the daemon into the background + */ + dpid = fork(); + if (dpid < 0) { + scsp_log(LOG_ERR, "fork failed"); + abort(); + } + if (dpid > 0) { + /* + * This is the parent process--just exit and let + * the daughter do all the work + */ + exit(0); + } + + /* + * Disassociate from any controlling terminal + */ + rc = setpgrp(0, getpid()); + if (rc <0) { + scsp_log(LOG_ERR, "can't change process group"); + exit(1); + } + fd = open("/dev/tty", O_RDWR); + if (fd >= 0) { + ioctl(fd, TIOCNOTTY, (char *)0); + close(fd); + } + + /* + * Close all open file descriptors + */ + file_count = getdtablesize(); + for (fd=0; fd<file_count; fd++) { + close(fd); + } + + /* + * Set up timers + */ +daemon_bypass: + init_timer(); + + /* + * Move to a safe directory + */ + chdir(SCSPD_DIR); + + /* + * Clear the file mode creation mask + */ + umask(0); + + + /* + * Set up signal handlers + */ + rc = (int)signal(SIGHUP, scsp_sighup); + if (rc == -1) { + scsp_log(LOG_ERR, "SIGHUP signal setup failed"); + exit(1); + } + + rc = (int)signal(SIGINT, scsp_sigint); + if (rc == -1) { + scsp_log(LOG_ERR, "SIGINT signal setup failed"); + exit(1); + } + + /* + * Set up syslog for error logging + */ + if (scsp_log_syslog || !scsp_log_file) { + openlog(prog, LOG_PID | LOG_CONS, LOG_DAEMON); + } + scsp_log(LOG_INFO, "Starting SCSP daemon"); +} + + +/* + * Main line code + * + * Process command line parameters, read configuration file, connect + * to configured clients, process data from DCSs. + * + * Arguments: + * argc number of command-line arguments + * argv list of pointers to command-line arguments + * + * Returns: + * none + * + */ +main(argc, argv) + int argc; + char *argv[]; + +{ + int i, rc, scsp_server_lsock; + Scsp_server *ssp; + Scsp_dcs *dcsp; + Scsp_pending *next_psp, *psp; + fd_set read_set, write_set, except_set; + + /* + * Process command line arguments + */ + initialize(argc, argv); + + /* + * Put the daemon into the background + */ + start_daemon(); + + /* + * Process configuration file + */ + rc = scsp_config(scsp_config_file); + if (rc) { + scsp_log(LOG_ERR, "Found %d error%s in configuration file", + rc, ((rc == 1) ? "" : "s")); + exit(1); + } + + /* + * Open the trace file if we need one + */ + if (scsp_trace_mode) { + scsp_open_trace(); + } + + /* + * Listen for connections from clients + */ + scsp_server_lsock = scsp_server_listen(); + if (scsp_server_lsock == -1) { + scsp_log(LOG_ERR, "server listen failed"); + abort(); + } + + /* + * Main program loop -- we wait for: + * a server listen to complete + * a DCS listen to complete + * a DCS connect to complete + * data from a server + * data from a DCS + */ + while (1) { + /* + * Set up the file descriptor sets and select to wait + * for input + */ + FD_ZERO(&read_set); + FD_ZERO(&write_set); + FD_ZERO(&except_set); + FD_SET(scsp_server_lsock, &read_set); + for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) { + if (ssp->ss_dcs_lsock != -1) + FD_SET(ssp->ss_dcs_lsock, &read_set); + if (ssp->ss_sock != -1) + FD_SET(ssp->ss_sock, &read_set); + for (dcsp = ssp->ss_dcs; dcsp; + dcsp = dcsp->sd_next) { + if (dcsp->sd_sock != -1) { + if (dcsp->sd_hello_state == + SCSP_HFSM_DOWN ) + FD_SET(dcsp->sd_sock, + &write_set); + else + FD_SET(dcsp->sd_sock, + &read_set); + } + } + } + for (psp = scsp_pending_head; psp; psp = psp->sp_next) { + FD_SET(psp->sp_sock, &read_set); + } + rc = select(scsp_max_socket + 1, &read_set, + &write_set, &except_set, + (struct timeval *)0); + if (rc < 0) { + /* + * Select error--check for possible signals + */ + if (harp_timer_exec) { + /* + * Timer tick--process it + */ + timer_proc(); + continue; + } else if (scsp_hup_signal) { + /* + * SIGHUP signal--reconfigure + */ + scsp_hup_signal = 0; + scsp_reconfigure(); + continue; + } else if (scsp_int_signal) { + /* + * SIGINT signal--dump control blocks + */ + print_scsp_dump(); + scsp_int_signal = 0; + continue; + } else if (errno == EINTR) { + /* + * EINTR--just ignore it + */ + continue; + } else { + /* + * Other error--this is a problem + */ + scsp_log(LOG_ERR, "Select failed"); + abort(); + } + } + + /* + * Check the read set for connections from servers + */ + if (FD_ISSET(scsp_server_lsock, &read_set)) { + FD_CLR(scsp_server_lsock, &read_set); + rc = scsp_server_accept(scsp_server_lsock); + } + + /* + * Check the write set for new connections to DCSs + */ + for (i = 0; i <= scsp_max_socket; i++) { + if (FD_ISSET(i, &write_set)) { + FD_CLR(i, &write_set); + if (dcsp = scsp_find_dcs(i)) { + rc = scsp_hfsm(dcsp, + SCSP_HFSM_VC_ESTAB, + (Scsp_msg *)0); + } + } + } + + /* + * Check the read set for connections from DCSs + */ + for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) { + if (ssp->ss_dcs_lsock != -1 && + FD_ISSET(ssp->ss_dcs_lsock, + &read_set)) { + FD_CLR(ssp->ss_dcs_lsock, &read_set); + dcsp = scsp_dcs_accept(ssp); + if (dcsp) { + rc = scsp_hfsm(dcsp, + SCSP_HFSM_VC_ESTAB, + (Scsp_msg *)0); + } + } + } + + /* + * Check the read set for data from pending servers + */ + for (psp = scsp_pending_head; psp; psp = next_psp) { + next_psp = psp->sp_next; + if (FD_ISSET(psp->sp_sock, &read_set)) { + FD_CLR(psp->sp_sock, &read_set); + rc = scsp_pending_read(psp); + } + } + + /* + * Check the read set for data from servers or DCSs + */ + for (i = 0; i <= scsp_max_socket; i++) { + if (FD_ISSET(i, &read_set)) { + if (ssp = scsp_find_server(i)) { + rc = scsp_server_read(ssp); + } else if (dcsp = scsp_find_dcs(i)) { + rc = scsp_dcs_read(dcsp); + } + } + } + } +} |