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.
26 * @(#) $FreeBSD: src/usr.sbin/atm/scspd/scspd.c,v 1.3.2.1 2000/12/11 01:03:29 obrien Exp $
27 * @(#) $DragonFly: src/usr.sbin/atm/scspd/scspd.c,v 1.3 2003/11/15 20:33:43 eirikn Exp $
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>
70 char *scsp_config_file = SCSPD_CONFIG;
71 FILE *scsp_log_file = (FILE *)0;
72 int scsp_log_syslog = 0;
73 Scsp_server *scsp_server_head = (Scsp_server *)0;
74 Scsp_pending *scsp_pending_head = (Scsp_pending *)0;
75 int scsp_max_socket = -1;
76 int scsp_debug_mode = 0;
77 int scsp_trace_mode = 0;
83 static int scsp_hup_signal = 0;
84 static int scsp_int_signal = 0;
88 * SIGHUP signal handler
108 * SIGINT signal handler
128 * Process command line parameters
131 * argc number of command-line arguments
132 * argv list of pointers to command-line arguments
139 initialize(int argc, char **argv)
145 * Save program name, ignoring any path components
147 if ((prog = (char *)strrchr(argv[0], '/')) != NULL)
153 * Make sure we're being invoked by the super user
157 fprintf(stderr, "%s: You must be root to run this program\n",
163 * Check for command-line options
165 for (i = 1; i < argc; i++) {
166 if (strcmp(argv[i], "-d") == 0) {
168 * -d option -- set debug mode
171 } else if (strcmp(argv[i], "-f") == 0) {
173 * -f option -- set config file name
177 fprintf(stderr, "%s: Configuration file name missing\n",
181 scsp_config_file = argv[i];
182 } else if (strncmp(argv[i], "-T", 2) == 0) {
184 * -T option -- trace options
186 for (cp = &argv[i][2]; *cp; cp++) {
188 scsp_trace_mode |= SCSP_TRACE_CAFSM;
190 scsp_trace_mode |= SCSP_TRACE_HFSM;
192 scsp_trace_mode |= SCSP_TRACE_CFSM;
194 scsp_trace_mode |= SCSP_TRACE_CA_MSG;
196 scsp_trace_mode |= SCSP_TRACE_HELLO_MSG;
198 scsp_trace_mode |= SCSP_TRACE_IF_MSG;
200 fprintf(stderr, "Invalid trace specification '%c' ignored\n",
205 * Error -- unrecognized option
207 fprintf(stderr, "%s: Unrecognized option \"%s\"\n",
216 * Daemon housekeeping
229 int dpid, fd, file_count, rc;
232 * Ignore selected signals
235 signal(SIGTTOU, SIG_IGN);
238 signal(SIGTTIN, SIG_IGN);
241 signal(SIGTSTP, SIG_IGN);
244 signal(SIGPIPE, SIG_IGN);
249 * Don't put the daemon into the background if
250 * we're in debug mode
256 * Put the daemon into the background
260 scsp_log(LOG_ERR, "fork failed");
265 * This is the parent process--just exit and let
266 * the daughter do all the work
272 * Disassociate from any controlling terminal
274 rc = setpgrp(0, getpid());
276 scsp_log(LOG_ERR, "can't change process group");
279 fd = open(_PATH_TTY, O_RDWR);
281 ioctl(fd, TIOCNOTTY, (char *)0);
286 * Close all open file descriptors
288 file_count = getdtablesize();
289 for (fd=0; fd<file_count; fd++) {
300 * Move to a safe directory
305 * Clear the file mode creation mask
311 * Set up signal handlers
313 rc = (int)signal(SIGHUP, scsp_sighup);
315 scsp_log(LOG_ERR, "SIGHUP signal setup failed");
319 rc = (int)signal(SIGINT, scsp_sigint);
321 scsp_log(LOG_ERR, "SIGINT signal setup failed");
326 * Set up syslog for error logging
328 if (scsp_log_syslog || !scsp_log_file) {
329 openlog(prog, LOG_PID | LOG_CONS, LOG_DAEMON);
331 scsp_log(LOG_INFO, "Starting SCSP daemon");
338 * Process command line parameters, read configuration file, connect
339 * to configured clients, process data from DCSs.
342 * argc number of command-line arguments
343 * argv list of pointers to command-line arguments
350 main(int argc, char **argv)
352 int i, rc, scsp_server_lsock;
355 Scsp_pending *next_psp, *psp;
356 fd_set read_set, write_set, except_set;
359 * Process command line arguments
361 initialize(argc, argv);
364 * Put the daemon into the background
369 * Process configuration file
371 rc = scsp_config(scsp_config_file);
373 scsp_log(LOG_ERR, "Found %d error%s in configuration file",
374 rc, ((rc == 1) ? "" : "s"));
379 * Open the trace file if we need one
381 if (scsp_trace_mode) {
386 * Listen for connections from clients
388 scsp_server_lsock = scsp_server_listen();
389 if (scsp_server_lsock == -1) {
390 scsp_log(LOG_ERR, "server listen failed");
395 * Main program loop -- we wait for:
396 * a server listen to complete
397 * a DCS listen to complete
398 * a DCS connect to complete
404 * Set up the file descriptor sets and select to wait
409 FD_ZERO(&except_set);
410 FD_SET(scsp_server_lsock, &read_set);
411 for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
412 if (ssp->ss_dcs_lsock != -1)
413 FD_SET(ssp->ss_dcs_lsock, &read_set);
414 if (ssp->ss_sock != -1)
415 FD_SET(ssp->ss_sock, &read_set);
416 for (dcsp = ssp->ss_dcs; dcsp;
417 dcsp = dcsp->sd_next) {
418 if (dcsp->sd_sock != -1) {
419 if (dcsp->sd_hello_state ==
421 FD_SET(dcsp->sd_sock,
424 FD_SET(dcsp->sd_sock,
429 for (psp = scsp_pending_head; psp; psp = psp->sp_next) {
430 FD_SET(psp->sp_sock, &read_set);
432 rc = select(scsp_max_socket + 1, &read_set,
433 &write_set, &except_set,
434 (struct timeval *)0);
437 * Select error--check for possible signals
439 if (harp_timer_exec) {
441 * Timer tick--process it
445 } else if (scsp_hup_signal) {
447 * SIGHUP signal--reconfigure
452 } else if (scsp_int_signal) {
454 * SIGINT signal--dump control blocks
459 } else if (errno == EINTR) {
461 * EINTR--just ignore it
466 * Other error--this is a problem
468 scsp_log(LOG_ERR, "Select failed");
474 * Check the read set for connections from servers
476 if (FD_ISSET(scsp_server_lsock, &read_set)) {
477 FD_CLR(scsp_server_lsock, &read_set);
478 rc = scsp_server_accept(scsp_server_lsock);
482 * Check the write set for new connections to DCSs
484 for (i = 0; i <= scsp_max_socket; i++) {
485 if (FD_ISSET(i, &write_set)) {
486 FD_CLR(i, &write_set);
487 if ((dcsp = scsp_find_dcs(i)) != NULL) {
496 * Check the read set for connections from DCSs
498 for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
499 if (ssp->ss_dcs_lsock != -1 &&
500 FD_ISSET(ssp->ss_dcs_lsock,
502 FD_CLR(ssp->ss_dcs_lsock, &read_set);
503 dcsp = scsp_dcs_accept(ssp);
513 * Check the read set for data from pending servers
515 for (psp = scsp_pending_head; psp; psp = next_psp) {
516 next_psp = psp->sp_next;
517 if (FD_ISSET(psp->sp_sock, &read_set)) {
518 FD_CLR(psp->sp_sock, &read_set);
519 rc = scsp_pending_read(psp);
524 * Check the read set for data from servers or DCSs
526 for (i = 0; i <= scsp_max_socket; i++) {
527 if (FD_ISSET(i, &read_set)) {
528 if ((ssp = scsp_find_server(i)) != NULL) {
529 rc = scsp_server_read(ssp);
530 } else if ((dcsp = scsp_find_dcs(i)) != NULL) {
531 rc = scsp_dcs_read(dcsp);