/* * * =================================== * 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. * * @(#) $FreeBSD: src/usr.sbin/atm/scspd/scspd.c,v 1.3.2.1 2000/12/11 01:03:29 obrien Exp $ * @(#) $DragonFly: src/usr.sbin/atm/scspd/scspd.c,v 1.3 2003/11/15 20:33:43 eirikn Exp $ */ /* * Server Cache Synchronization Protocol (SCSP) Support * ---------------------------------------------------- * * SCSP server daemon main line code * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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(int sig) { /* * Flag the signal */ scsp_hup_signal = 1; } /* * SIGINT signal handler * * Arguments: * sig signal number * * Returns: * none * */ void scsp_sigint(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(int argc, char **argv) { int i; char *cp; /* * Save program name, ignoring any path components */ if ((prog = (char *)strrchr(argv[0], '/')) != NULL) 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(void) { 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(_PATH_TTY, O_RDWR); if (fd >= 0) { ioctl(fd, TIOCNOTTY, (char *)0); close(fd); } /* * Close all open file descriptors */ file_count = getdtablesize(); for (fd=0; fdss_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)) != NULL) { 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)) != NULL) { rc = scsp_server_read(ssp); } else if ((dcsp = scsp_find_dcs(i)) != NULL) { rc = scsp_dcs_read(dcsp); } } } } }