]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/atm/scspd/scspd.c
This commit was generated by cvs2svn to compensate for changes in r169808,
[FreeBSD/FreeBSD.git] / usr.sbin / atm / scspd / scspd.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
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.
12  *
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.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
26  *      @(#) $FreeBSD$
27  *
28  */
29
30
31 /*
32  * Server Cache Synchronization Protocol (SCSP) Support
33  * ----------------------------------------------------
34  *
35  * SCSP server daemon main line code
36  *
37  */
38
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/socket.h>
42 #include <sys/stat.h>
43 #include <sys/ttycom.h>
44 #include <net/if.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>
52  
53 #include <errno.h>
54 #include <fcntl.h>
55 #include <libatm.h>
56 #include <paths.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <syslog.h>
61 #include <unistd.h>
62
63 #include "scsp_msg.h"
64 #include "scsp_if.h"
65 #include "scsp_var.h"
66
67 #ifndef lint
68 __RCSID("@(#) $FreeBSD$");
69 #endif
70
71
72 /*
73  * Global variables
74  */
75 char            *prog;
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;
84
85
86 /*
87  * Local variables
88  */
89 static int      scsp_hup_signal = 0;
90 static int      scsp_int_signal = 0;
91
92
93 /*
94  * SIGHUP signal handler
95  *
96  * Arguments:
97  *      sig     signal number
98  *
99  * Returns:
100  *      none
101  *
102  */
103 void
104 scsp_sighup(sig)
105         int     sig;
106 {
107         /*
108          * Flag the signal
109          */
110         scsp_hup_signal = 1;
111 }
112
113
114 /*
115  * SIGINT signal handler
116  *
117  * Arguments:
118  *      sig     signal number
119  *
120  * Returns:
121  *      none
122  *
123  */
124 void
125 scsp_sigint(sig)
126         int     sig;
127 {
128         /*
129          * Flag the signal
130          */
131         scsp_int_signal = 1;
132 }
133
134
135 /*
136  * Process command line parameters
137  *
138  * Arguments:
139  *      argc    number of command-line arguments
140  *      argv    list of pointers to command-line arguments
141  *
142  * Returns:
143  *      none
144  *
145  */
146 void
147 initialize(argc, argv)
148         int     argc;
149         char    **argv;
150 {
151         int     i;
152         char    *cp;
153
154         /*
155          * Save program name, ignoring any path components
156          */
157         if ((prog = (char *)strrchr(argv[0], '/')) != NULL)
158                 prog++;
159         else
160                 prog = argv[0];
161
162         /*
163          * Make sure we're being invoked by the super user
164          */
165         i = getuid();
166         if (i != 0) {
167                 fprintf(stderr, "%s: You must be root to run this program\n",
168                                 prog);
169                 exit(1);
170         }
171
172         /*
173          * Check for command-line options
174          */
175         for (i = 1; i < argc; i++) {
176                 if (strcmp(argv[i], "-d") == 0) {
177                         /*
178                          * -d option -- set debug mode
179                          */
180                         scsp_debug_mode = 1;
181                 } else if (strcmp(argv[i], "-f") == 0) {
182                         /*
183                          * -f option -- set config file name
184                          */
185                         i++;
186                         if (i >= argc) {
187                                 fprintf(stderr, "%s: Configuration file name missing\n",
188                                                 prog);
189                                 exit(1);
190                         }
191                         scsp_config_file = argv[i];
192                 } else if (strncmp(argv[i], "-T", 2) == 0) {
193                         /*
194                          * -T option -- trace options
195                          */
196                         for (cp = &argv[i][2]; *cp; cp++) {
197                                 if (*cp == 'c')
198                                         scsp_trace_mode |= SCSP_TRACE_CAFSM;
199                                 else if (*cp == 'h')
200                                         scsp_trace_mode |= SCSP_TRACE_HFSM;
201                                 else if (*cp == 'i')
202                                         scsp_trace_mode |= SCSP_TRACE_CFSM;
203                                 else if (*cp == 'C')
204                                         scsp_trace_mode |= SCSP_TRACE_CA_MSG;
205                                 else if (*cp == 'H')
206                                         scsp_trace_mode |= SCSP_TRACE_HELLO_MSG;
207                                 else if (*cp == 'I')
208                                         scsp_trace_mode |= SCSP_TRACE_IF_MSG;
209                                 else
210                                         fprintf(stderr, "Invalid trace specification '%c' ignored\n",
211                                                         *cp);
212                         }
213                 } else {
214                         /*
215                          * Error -- unrecognized option
216                          */
217                         fprintf(stderr, "%s: Unrecognized option \"%s\"\n",
218                                         prog, argv[i]);
219                         exit(1);
220                 }
221         }
222 }
223
224
225 /*
226  * Daemon housekeeping
227  *
228  * Arguments:
229  *      None
230  *
231  * Returns:
232  *      None
233  *
234  */
235 static void
236 start_daemon()
237
238 {
239         int     dpid, fd, file_count, rc;
240
241         /*
242          * Ignore selected signals
243          */
244 #ifdef SIGTTOU
245         signal(SIGTTOU, SIG_IGN);
246 #endif
247 #ifdef SIGTTIN
248         signal(SIGTTIN, SIG_IGN);
249 #endif
250 #ifdef SIGTSTP
251         signal(SIGTSTP, SIG_IGN);
252 #endif
253 #ifdef SIGPIPE
254         signal(SIGPIPE, SIG_IGN);
255 #endif
256
257
258         /*
259          * Don't put the daemon into the background if
260          * we're in debug mode
261          */
262         if (scsp_debug_mode)
263                 goto daemon_bypass;
264
265         /*
266          * Put the daemon into the background
267          */
268         dpid = fork();
269         if (dpid < 0) {
270                 scsp_log(LOG_ERR, "fork failed");
271                 abort();
272         }
273         if (dpid > 0) {
274                 /*
275                  * This is the parent process--just exit and let
276                  * the daughter do all the work
277                  */
278                 exit(0);
279         }
280
281         /*
282          * Disassociate from any controlling terminal
283          */
284         rc = setpgrp(0, getpid());
285         if (rc <0) {
286                 scsp_log(LOG_ERR, "can't change process group");
287                 exit(1);
288         }
289         fd = open(_PATH_TTY, O_RDWR);
290         if (fd >= 0) {
291                 ioctl(fd, TIOCNOTTY, (char *)0);
292                 close(fd);
293         }
294
295         /*
296          * Close all open file descriptors
297          */
298         file_count = getdtablesize();
299         for (fd=0; fd<file_count; fd++) {
300                 close(fd);
301         }
302
303         /*
304          * Set up timers
305          */
306 daemon_bypass:
307         init_timer();
308
309         /*
310          * Move to a safe directory
311          */
312         chdir(SCSPD_DIR);
313
314         /*
315          * Clear the file mode creation mask
316          */
317         umask(0);
318
319
320         /*
321          * Set up signal handlers
322          */
323         if (signal(SIGHUP, scsp_sighup) == SIG_ERR) {
324                 scsp_log(LOG_ERR, "SIGHUP signal setup failed");
325                 exit(1);
326         }
327
328         if (signal(SIGINT, scsp_sigint) == SIG_ERR) {
329                 scsp_log(LOG_ERR, "SIGINT signal setup failed");
330                 exit(1);
331         }
332
333         /*
334          * Set up syslog for error logging
335          */
336         if (scsp_log_syslog || !scsp_log_file) {
337                 openlog(prog, LOG_PID | LOG_CONS, LOG_DAEMON);
338         }
339         scsp_log(LOG_INFO, "Starting SCSP daemon");
340 }
341
342
343 /*
344  * Main line code
345  *
346  * Process command line parameters, read configuration file, connect
347  * to configured clients, process data from DCSs.
348  *
349  * Arguments:
350  *      argc    number of command-line arguments
351  *      argv    list of pointers to command-line arguments
352  *
353  * Returns:
354  *      none
355  *
356  */
357 int
358 main(argc, argv)
359         int     argc;
360         char    *argv[];
361
362 {
363         int             i, rc, scsp_server_lsock;
364         Scsp_server     *ssp;
365         Scsp_dcs        *dcsp;
366         Scsp_pending    *next_psp, *psp;
367         fd_set          read_set, write_set, except_set;
368
369         /*
370          * Process command line arguments
371          */
372         initialize(argc, argv);
373
374         /*
375          * Put the daemon into the background
376          */
377         start_daemon();
378
379         /*
380          * Process configuration file
381          */
382         rc = scsp_config(scsp_config_file);
383         if (rc) {
384                 scsp_log(LOG_ERR, "Found %d error%s in configuration file",
385                                 rc, ((rc == 1) ? "" : "s"));
386                 exit(1);
387         }
388
389         /*
390          * Open the trace file if we need one
391          */
392         if (scsp_trace_mode) {
393                 scsp_open_trace();
394         }
395
396         /*
397          * Listen for connections from clients
398          */
399         scsp_server_lsock = scsp_server_listen();
400         if (scsp_server_lsock == -1) {
401                 scsp_log(LOG_ERR, "server listen failed");
402                 abort();
403         }
404
405         /*
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
410          *      data from a server
411          *      data from a DCS
412          */
413         while (1) {
414                 /*
415                  * Set up the file descriptor sets and select to wait
416                  * for input
417                  */
418                 FD_ZERO(&read_set);
419                 FD_ZERO(&write_set);
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 ==
431                                                         SCSP_HFSM_DOWN )
432                                                 FD_SET(dcsp->sd_sock,
433                                                         &write_set);
434                                         else
435                                                 FD_SET(dcsp->sd_sock,
436                                                         &read_set);
437                                 }
438                         }
439                 }
440                 for (psp = scsp_pending_head; psp; psp = psp->sp_next) {
441                         FD_SET(psp->sp_sock, &read_set);
442                 }
443                 rc = select(scsp_max_socket + 1, &read_set,
444                                 &write_set, &except_set,
445                                 (struct timeval *)0);
446                 if (rc < 0) {
447                         /*
448                          * Select error--check for possible signals
449                          */
450                         if (harp_timer_exec) {
451                                 /*
452                                  * Timer tick--process it
453                                  */
454                                 timer_proc();
455                                 continue;
456                         } else if (scsp_hup_signal) {
457                                 /*
458                                  * SIGHUP signal--reconfigure
459                                  */
460                                 scsp_hup_signal = 0;
461                                 scsp_reconfigure();
462                                 continue;
463                         } else if (scsp_int_signal) {
464                                 /*
465                                  * SIGINT signal--dump control blocks
466                                  */
467                                 print_scsp_dump();
468                                 scsp_int_signal = 0;
469                                 continue;
470                         } else if (errno == EINTR) {
471                                 /*
472                                  * EINTR--just ignore it
473                                  */
474                                 continue;
475                         } else {
476                                 /*
477                                  * Other error--this is a problem
478                                  */
479                                 scsp_log(LOG_ERR, "Select failed");
480                                 abort();
481                         }
482                 }
483
484                 /*
485                  * Check the read set for connections from servers
486                  */
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);
490                 }
491
492                 /*
493                  * Check the write set for new connections to DCSs
494                  */
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) {
499                                         rc = scsp_hfsm(dcsp,
500                                                 SCSP_HFSM_VC_ESTAB,
501                                                 (Scsp_msg *)0);
502                                 }
503                         }
504                 }
505
506                 /*
507                  * Check the read set for connections from DCSs
508                  */
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,
512                                                 &read_set)) {
513                                 FD_CLR(ssp->ss_dcs_lsock, &read_set);
514                                 dcsp = scsp_dcs_accept(ssp);
515                                 if (dcsp) {
516                                         rc = scsp_hfsm(dcsp,
517                                                 SCSP_HFSM_VC_ESTAB,
518                                                 (Scsp_msg *)0);
519                                 }
520                         }
521                 }
522
523                 /*
524                  * Check the read set for data from pending servers
525                  */
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);
531                         }
532                 }
533
534                 /*
535                  * Check the read set for data from servers or DCSs
536                  */
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);
543                                 }
544                         }
545                 }
546         }
547 }