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.4 2007/11/25 01:28:23 swildner 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>
71 char *scsp_config_file
= SCSPD_CONFIG
;
72 FILE *scsp_log_file
= (FILE *)0;
73 int scsp_log_syslog
= 0;
74 Scsp_server
*scsp_server_head
= (Scsp_server
*)0;
75 Scsp_pending
*scsp_pending_head
= (Scsp_pending
*)0;
76 int scsp_max_socket
= -1;
77 int scsp_debug_mode
= 0;
78 int scsp_trace_mode
= 0;
84 static int scsp_hup_signal
= 0;
85 static int scsp_int_signal
= 0;
89 * SIGHUP signal handler
109 * SIGINT signal handler
129 * Process command line parameters
132 * argc number of command-line arguments
133 * argv list of pointers to command-line arguments
140 initialize(int argc
, char **argv
)
146 * Save program name, ignoring any path components
148 if ((prog
= (char *)strrchr(argv
[0], '/')) != NULL
)
154 * Make sure we're being invoked by the super user
158 fprintf(stderr
, "%s: You must be root to run this program\n",
164 * Check for command-line options
166 for (i
= 1; i
< argc
; i
++) {
167 if (strcmp(argv
[i
], "-d") == 0) {
169 * -d option -- set debug mode
172 } else if (strcmp(argv
[i
], "-f") == 0) {
174 * -f option -- set config file name
178 fprintf(stderr
, "%s: Configuration file name missing\n",
182 scsp_config_file
= argv
[i
];
183 } else if (strncmp(argv
[i
], "-T", 2) == 0) {
185 * -T option -- trace options
187 for (cp
= &argv
[i
][2]; *cp
; cp
++) {
189 scsp_trace_mode
|= SCSP_TRACE_CAFSM
;
191 scsp_trace_mode
|= SCSP_TRACE_HFSM
;
193 scsp_trace_mode
|= SCSP_TRACE_CFSM
;
195 scsp_trace_mode
|= SCSP_TRACE_CA_MSG
;
197 scsp_trace_mode
|= SCSP_TRACE_HELLO_MSG
;
199 scsp_trace_mode
|= SCSP_TRACE_IF_MSG
;
201 fprintf(stderr
, "Invalid trace specification '%c' ignored\n",
206 * Error -- unrecognized option
208 fprintf(stderr
, "%s: Unrecognized option \"%s\"\n",
217 * Daemon housekeeping
230 int dpid
, fd
, file_count
, rc
;
233 * Ignore selected signals
236 signal(SIGTTOU
, SIG_IGN
);
239 signal(SIGTTIN
, SIG_IGN
);
242 signal(SIGTSTP
, SIG_IGN
);
245 signal(SIGPIPE
, SIG_IGN
);
250 * Don't put the daemon into the background if
251 * we're in debug mode
257 * Put the daemon into the background
261 scsp_log(LOG_ERR
, "fork failed");
266 * This is the parent process--just exit and let
267 * the daughter do all the work
273 * Disassociate from any controlling terminal
275 rc
= setpgrp(0, getpid());
277 scsp_log(LOG_ERR
, "can't change process group");
280 fd
= open(_PATH_TTY
, O_RDWR
);
282 ioctl(fd
, TIOCNOTTY
, (char *)0);
287 * Close all open file descriptors
289 file_count
= getdtablesize();
290 for (fd
=0; fd
<file_count
; fd
++) {
301 * Move to a safe directory
306 * Clear the file mode creation mask
312 * Set up signal handlers
314 rc
= (int)signal(SIGHUP
, scsp_sighup
);
316 scsp_log(LOG_ERR
, "SIGHUP signal setup failed");
320 rc
= (int)signal(SIGINT
, scsp_sigint
);
322 scsp_log(LOG_ERR
, "SIGINT signal setup failed");
327 * Set up syslog for error logging
329 if (scsp_log_syslog
|| !scsp_log_file
) {
330 openlog(prog
, LOG_PID
| LOG_CONS
, LOG_DAEMON
);
332 scsp_log(LOG_INFO
, "Starting SCSP daemon");
339 * Process command line parameters, read configuration file, connect
340 * to configured clients, process data from DCSs.
343 * argc number of command-line arguments
344 * argv list of pointers to command-line arguments
351 main(int argc
, char **argv
)
353 int i
, rc
, scsp_server_lsock
;
356 Scsp_pending
*next_psp
, *psp
;
357 fd_set read_set
, write_set
, except_set
;
360 * Process command line arguments
362 initialize(argc
, argv
);
365 * Put the daemon into the background
370 * Process configuration file
372 rc
= scsp_config(scsp_config_file
);
374 scsp_log(LOG_ERR
, "Found %d error%s in configuration file",
375 rc
, ((rc
== 1) ? "" : "s"));
380 * Open the trace file if we need one
382 if (scsp_trace_mode
) {
387 * Listen for connections from clients
389 scsp_server_lsock
= scsp_server_listen();
390 if (scsp_server_lsock
== -1) {
391 scsp_log(LOG_ERR
, "server listen failed");
396 * Main program loop -- we wait for:
397 * a server listen to complete
398 * a DCS listen to complete
399 * a DCS connect to complete
405 * Set up the file descriptor sets and select to wait
410 FD_ZERO(&except_set
);
411 FD_SET(scsp_server_lsock
, &read_set
);
412 for (ssp
= scsp_server_head
; ssp
; ssp
= ssp
->ss_next
) {
413 if (ssp
->ss_dcs_lsock
!= -1)
414 FD_SET(ssp
->ss_dcs_lsock
, &read_set
);
415 if (ssp
->ss_sock
!= -1)
416 FD_SET(ssp
->ss_sock
, &read_set
);
417 for (dcsp
= ssp
->ss_dcs
; dcsp
;
418 dcsp
= dcsp
->sd_next
) {
419 if (dcsp
->sd_sock
!= -1) {
420 if (dcsp
->sd_hello_state
==
422 FD_SET(dcsp
->sd_sock
,
425 FD_SET(dcsp
->sd_sock
,
430 for (psp
= scsp_pending_head
; psp
; psp
= psp
->sp_next
) {
431 FD_SET(psp
->sp_sock
, &read_set
);
433 rc
= select(scsp_max_socket
+ 1, &read_set
,
434 &write_set
, &except_set
,
435 (struct timeval
*)0);
438 * Select error--check for possible signals
440 if (harp_timer_exec
) {
442 * Timer tick--process it
446 } else if (scsp_hup_signal
) {
448 * SIGHUP signal--reconfigure
453 } else if (scsp_int_signal
) {
455 * SIGINT signal--dump control blocks
460 } else if (errno
== EINTR
) {
462 * EINTR--just ignore it
467 * Other error--this is a problem
469 scsp_log(LOG_ERR
, "Select failed");
475 * Check the read set for connections from servers
477 if (FD_ISSET(scsp_server_lsock
, &read_set
)) {
478 FD_CLR(scsp_server_lsock
, &read_set
);
479 rc
= scsp_server_accept(scsp_server_lsock
);
483 * Check the write set for new connections to DCSs
485 for (i
= 0; i
<= scsp_max_socket
; i
++) {
486 if (FD_ISSET(i
, &write_set
)) {
487 FD_CLR(i
, &write_set
);
488 if ((dcsp
= scsp_find_dcs(i
)) != NULL
) {
497 * Check the read set for connections from DCSs
499 for (ssp
= scsp_server_head
; ssp
; ssp
= ssp
->ss_next
) {
500 if (ssp
->ss_dcs_lsock
!= -1 &&
501 FD_ISSET(ssp
->ss_dcs_lsock
,
503 FD_CLR(ssp
->ss_dcs_lsock
, &read_set
);
504 dcsp
= scsp_dcs_accept(ssp
);
514 * Check the read set for data from pending servers
516 for (psp
= scsp_pending_head
; psp
; psp
= next_psp
) {
517 next_psp
= psp
->sp_next
;
518 if (FD_ISSET(psp
->sp_sock
, &read_set
)) {
519 FD_CLR(psp
->sp_sock
, &read_set
);
520 rc
= scsp_pending_read(psp
);
525 * Check the read set for data from servers or DCSs
527 for (i
= 0; i
<= scsp_max_socket
; i
++) {
528 if (FD_ISSET(i
, &read_set
)) {
529 if ((ssp
= scsp_find_server(i
)) != NULL
) {
530 rc
= scsp_server_read(ssp
);
531 } else if ((dcsp
= scsp_find_dcs(i
)) != NULL
) {
532 rc
= scsp_dcs_read(dcsp
);