3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
32 * Server Cache Synchronization Protocol (SCSP) Support
33 * ----------------------------------------------------
35 * SCSP server daemon main line code
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/socket.h>
43 #include <sys/ttycom.h>
45 #include <netinet/in.h>
46 #include <netatm/queue.h>
47 #include <netatm/atm.h>
48 #include <netatm/atm_if.h>
49 #include <netatm/atm_sap.h>
50 #include <netatm/atm_sys.h>
51 #include <netatm/atm_ioctl.h>
68 __RCSID("@(#) $FreeBSD$");
76 char *scsp_config_file = SCSPD_CONFIG;
77 FILE *scsp_log_file = (FILE *)0;
78 int scsp_log_syslog = 0;
79 Scsp_server *scsp_server_head = (Scsp_server *)0;
80 Scsp_pending *scsp_pending_head = (Scsp_pending *)0;
81 int scsp_max_socket = -1;
82 int scsp_debug_mode = 0;
83 int scsp_trace_mode = 0;
89 static int scsp_hup_signal = 0;
90 static int scsp_int_signal = 0;
94 * SIGHUP signal handler
115 * SIGINT signal handler
136 * Process command line parameters
139 * argc number of command-line arguments
140 * argv list of pointers to command-line arguments
147 initialize(argc, argv)
155 * Save program name, ignoring any path components
157 if ((prog = (char *)strrchr(argv[0], '/')) != NULL)
163 * Make sure we're being invoked by the super user
167 fprintf(stderr, "%s: You must be root to run this program\n",
173 * Check for command-line options
175 for (i = 1; i < argc; i++) {
176 if (strcmp(argv[i], "-d") == 0) {
178 * -d option -- set debug mode
181 } else if (strcmp(argv[i], "-f") == 0) {
183 * -f option -- set config file name
187 fprintf(stderr, "%s: Configuration file name missing\n",
191 scsp_config_file = argv[i];
192 } else if (strncmp(argv[i], "-T", 2) == 0) {
194 * -T option -- trace options
196 for (cp = &argv[i][2]; *cp; cp++) {
198 scsp_trace_mode |= SCSP_TRACE_CAFSM;
200 scsp_trace_mode |= SCSP_TRACE_HFSM;
202 scsp_trace_mode |= SCSP_TRACE_CFSM;
204 scsp_trace_mode |= SCSP_TRACE_CA_MSG;
206 scsp_trace_mode |= SCSP_TRACE_HELLO_MSG;
208 scsp_trace_mode |= SCSP_TRACE_IF_MSG;
210 fprintf(stderr, "Invalid trace specification '%c' ignored\n",
215 * Error -- unrecognized option
217 fprintf(stderr, "%s: Unrecognized option \"%s\"\n",
226 * Daemon housekeeping
239 int dpid, fd, file_count, rc;
242 * Ignore selected signals
245 signal(SIGTTOU, SIG_IGN);
248 signal(SIGTTIN, SIG_IGN);
251 signal(SIGTSTP, SIG_IGN);
254 signal(SIGPIPE, SIG_IGN);
259 * Don't put the daemon into the background if
260 * we're in debug mode
266 * Put the daemon into the background
270 scsp_log(LOG_ERR, "fork failed");
275 * This is the parent process--just exit and let
276 * the daughter do all the work
282 * Disassociate from any controlling terminal
284 rc = setpgrp(0, getpid());
286 scsp_log(LOG_ERR, "can't change process group");
289 fd = open(_PATH_TTY, O_RDWR);
291 ioctl(fd, TIOCNOTTY, (char *)0);
296 * Close all open file descriptors
298 file_count = getdtablesize();
299 for (fd=0; fd<file_count; fd++) {
310 * Move to a safe directory
315 * Clear the file mode creation mask
321 * Set up signal handlers
323 if (signal(SIGHUP, scsp_sighup) == SIG_ERR) {
324 scsp_log(LOG_ERR, "SIGHUP signal setup failed");
328 if (signal(SIGINT, scsp_sigint) == SIG_ERR) {
329 scsp_log(LOG_ERR, "SIGINT signal setup failed");
334 * Set up syslog for error logging
336 if (scsp_log_syslog || !scsp_log_file) {
337 openlog(prog, LOG_PID | LOG_CONS, LOG_DAEMON);
339 scsp_log(LOG_INFO, "Starting SCSP daemon");
346 * Process command line parameters, read configuration file, connect
347 * to configured clients, process data from DCSs.
350 * argc number of command-line arguments
351 * argv list of pointers to command-line arguments
363 int i, rc, scsp_server_lsock;
366 Scsp_pending *next_psp, *psp;
367 fd_set read_set, write_set, except_set;
370 * Process command line arguments
372 initialize(argc, argv);
375 * Put the daemon into the background
380 * Process configuration file
382 rc = scsp_config(scsp_config_file);
384 scsp_log(LOG_ERR, "Found %d error%s in configuration file",
385 rc, ((rc == 1) ? "" : "s"));
390 * Open the trace file if we need one
392 if (scsp_trace_mode) {
397 * Listen for connections from clients
399 scsp_server_lsock = scsp_server_listen();
400 if (scsp_server_lsock == -1) {
401 scsp_log(LOG_ERR, "server listen failed");
406 * Main program loop -- we wait for:
407 * a server listen to complete
408 * a DCS listen to complete
409 * a DCS connect to complete
415 * Set up the file descriptor sets and select to wait
420 FD_ZERO(&except_set);
421 FD_SET(scsp_server_lsock, &read_set);
422 for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
423 if (ssp->ss_dcs_lsock != -1)
424 FD_SET(ssp->ss_dcs_lsock, &read_set);
425 if (ssp->ss_sock != -1)
426 FD_SET(ssp->ss_sock, &read_set);
427 for (dcsp = ssp->ss_dcs; dcsp;
428 dcsp = dcsp->sd_next) {
429 if (dcsp->sd_sock != -1) {
430 if (dcsp->sd_hello_state ==
432 FD_SET(dcsp->sd_sock,
435 FD_SET(dcsp->sd_sock,
440 for (psp = scsp_pending_head; psp; psp = psp->sp_next) {
441 FD_SET(psp->sp_sock, &read_set);
443 rc = select(scsp_max_socket + 1, &read_set,
444 &write_set, &except_set,
445 (struct timeval *)0);
448 * Select error--check for possible signals
450 if (harp_timer_exec) {
452 * Timer tick--process it
456 } else if (scsp_hup_signal) {
458 * SIGHUP signal--reconfigure
463 } else if (scsp_int_signal) {
465 * SIGINT signal--dump control blocks
470 } else if (errno == EINTR) {
472 * EINTR--just ignore it
477 * Other error--this is a problem
479 scsp_log(LOG_ERR, "Select failed");
485 * Check the read set for connections from servers
487 if (FD_ISSET(scsp_server_lsock, &read_set)) {
488 FD_CLR(scsp_server_lsock, &read_set);
489 rc = scsp_server_accept(scsp_server_lsock);
493 * Check the write set for new connections to DCSs
495 for (i = 0; i <= scsp_max_socket; i++) {
496 if (FD_ISSET(i, &write_set)) {
497 FD_CLR(i, &write_set);
498 if ((dcsp = scsp_find_dcs(i)) != NULL) {
507 * Check the read set for connections from DCSs
509 for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
510 if (ssp->ss_dcs_lsock != -1 &&
511 FD_ISSET(ssp->ss_dcs_lsock,
513 FD_CLR(ssp->ss_dcs_lsock, &read_set);
514 dcsp = scsp_dcs_accept(ssp);
524 * Check the read set for data from pending servers
526 for (psp = scsp_pending_head; psp; psp = next_psp) {
527 next_psp = psp->sp_next;
528 if (FD_ISSET(psp->sp_sock, &read_set)) {
529 FD_CLR(psp->sp_sock, &read_set);
530 rc = scsp_pending_read(psp);
535 * Check the read set for data from servers or DCSs
537 for (i = 0; i <= scsp_max_socket; i++) {
538 if (FD_ISSET(i, &read_set)) {
539 if ((ssp = scsp_find_server(i)) != NULL) {
540 rc = scsp_server_read(ssp);
541 } else if ((dcsp = scsp_find_dcs(i)) != NULL) {
542 rc = scsp_dcs_read(dcsp);