diff options
Diffstat (limited to 'usr.sbin/atm/atmarpd/atmarpd.c')
-rw-r--r-- | usr.sbin/atm/atmarpd/atmarpd.c | 409 |
1 files changed, 409 insertions, 0 deletions
diff --git a/usr.sbin/atm/atmarpd/atmarpd.c b/usr.sbin/atm/atmarpd/atmarpd.c new file mode 100644 index 0000000..72ebb52 --- /dev/null +++ b/usr.sbin/atm/atmarpd/atmarpd.c @@ -0,0 +1,409 @@ +/* + * + * =================================== + * 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. + * + * @(#) $Id: atmarpd.c,v 1.5 1998/08/13 20:11:13 johnc Exp $ + * + */ + +/* + * Server Cache Synchronization Protocol (SCSP) Support + * ---------------------------------------------------- + * + * SCSP-ATMARP server interface: main line code + * + */ + +#ifndef lint +static char *RCSid = "@(#) $Id: atmarpd.c,v 1.5 1998/08/13 20:11:13 johnc Exp $"; +#endif + +#include <sys/types.h> +#include <sys/param.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <syslog.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in.h> +#include <sys/ttycom.h> +#include <netatm/queue.h> +#include <netatm/atm.h> +#include <netatm/atm_if.h> +#include <netatm/atm_sap.h> +#include <netatm/atm_sys.h> +#include <netatm/atm_ioctl.h> + +#include <libatm.h> +#include "../scspd/scsp_msg.h" +#include "../scspd/scsp_if.h" +#include "../scspd/scsp_var.h" +#include "atmarp_var.h" + + +/* + * Global variables + */ +char *prog; +int atmarp_debug_mode = 0; +int atmarp_max_socket = 0; +Atmarp_intf *atmarp_intf_head = (Atmarp_intf *)0; +Atmarp_slis *atmarp_slis_head = (Atmarp_slis *)0; +FILE *atmarp_log_file = (FILE *)0; +char *atmarp_log_file_name = (char *)0; +Harp_timer cache_timer, perm_timer; + + + +/* + * Print a usage message + * + * Arguments: + * none + * + * Returns: + * exits, does not return + * + */ +void +usage() +{ + fprintf(stderr, "usage: %s [-d] [-l <log_file>] <net_intf> ...\n", prog); + exit(1); +} + + +/* + * Process command line parameters + * + * Arguments: + * argc number of command-line arguments + * argv list of pointers to command-line arguments + * + * Returns: + * none + * + */ +static void +initialize(argc, argv) + int argc; + char *argv[]; + +{ + int i, rc; + + /* + * Save program name, ignoring any path components + */ + if (prog = (char *)strrchr(argv[0], '/')) + 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); + } + + /* + * Scan arguments, checking for options + */ + for (i = 1; i < argc; i++) { + if (argv[i][0] == '-') { + if (strcmp(argv[i], "-d") == 0) { + atmarp_debug_mode = TRUE; + } else if (strcmp(argv[i], "-l") == 0) { + i++; + if (i >= argc) { + fprintf(stderr, "%s: Log file name missing\n", + prog); + exit(1); + } + atmarp_log_file_name = argv[i]; + } else { + fprintf(stderr, "%s: Unrecognized option \"%s\"\n", + prog, argv[i]); + exit(1); + } + } else { + /* + * Parameter is a network interface name + */ + rc = atmarp_cfg_netif(argv[i]); + if (rc) { + fprintf(stderr, "%s: Error configuring network interface %s\n", + prog, argv[i]); + exit(1); + } + } + } + + /* + * Make sure we had at least one interface configured + */ + if (!atmarp_intf_head) { + usage(); + } +} + + +/* + * Daemon housekeeping + * + * Arguments: + * None + * + * Returns: + * None + * + */ +static void +start_daemon() + +{ + 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 + + /* + * Skip putting things into the background if we're + * in debugging mode + */ + if (atmarp_debug_mode) + goto daemon_bypass; + + /* + * Set up syslog for error logging + */ + if (!atmarp_log_file) { + openlog(prog, LOG_PID | LOG_CONS, LOG_DAEMON); + } + + /* + * Put the daemon into the background + */ + dpid = fork(); + if (dpid < 0) { + atmarp_log(LOG_ERR, "fork failed"); + exit(1); + } + 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) { + atmarp_log(LOG_ERR, "can't change process group"); + exit(1); + } + fd = open("/dev/tty", O_RDWR); + if (fd >= 0) { + ioctl(fd, TIOCNOTTY, (char *)0); + close(fd); + } + + /* + * Close all open file descriptors + */ + file_count = getdtablesize(); + for (fd=0; fd<file_count; fd++) { + close(fd); + } + + /* + * Open log file, if specified + */ + if (atmarp_log_file_name) { + atmarp_log_file = fopen(atmarp_log_file_name, "a"); + if (!atmarp_log_file) { + atmarp_log(LOG_ERR, "%s: Can't open log file \'%s\'\n", + prog, atmarp_log_file_name); + exit(1); + } + } + + /* + * Set up and start interval timer + */ +daemon_bypass: + init_timer(); + + /* + * Move to a safe directory + */ + chdir(ATMARP_DIR); + + /* + * Clear the file mode creation mask + */ + umask(0); + + + /* + * Set up signal handlers + */ + rc = (int)signal(SIGINT, atmarp_sigint); + if (rc == -1) { + atmarp_log(LOG_ERR, "SIGINT signal setup failed"); + exit(1); + } +} + + +/* + * Main line code + * + * The ATMARP server resides in the kernel, while SCSP runs as a daemon + * in user space. This program exists to provide an interface between + * the two. It periodically polls the kernel to get the ATMARP cache + * and passes information about new entries to SCSP. It also accepts + * new information from SCSP and passes it to the kernel. + * + * Arguments: + * argc number of command-line arguments + * argv list of pointers to command-line arguments + * + * Returns: + * none + * + */ +main(argc, argv) + int argc; + char *argv[]; + +{ + int i, rc; + fd_set read_set, write_set, except_set; + Atmarp_intf *aip; + + /* + * Process command line arguments + */ + initialize(argc, argv); + + /* + * Put the daemon into the background + */ + start_daemon(); + + /* + * Start the cache update timer + */ + HARP_TIMER(&cache_timer, ATMARP_CACHE_INTERVAL, + atmarp_cache_timeout); + + /* + * Start the permanent cache entry timer + */ + HARP_TIMER(&perm_timer, ATMARP_PERM_INTERVAL, + atmarp_perm_timeout); + + /* + * Establish a connection to SCSP for each interface. If a + * connect fails, it will be retried when the cache update + * timer fires. + */ + for (aip = atmarp_intf_head; aip; aip = aip->ai_next) { + if (atmarp_if_ready(aip)) { + (void)atmarp_scsp_connect(aip); + } + } + + /* + * Read the cache from the kernel + */ + atmarp_get_updated_cache(); + + /* + * Main program loop -- wait for data to come in from SCSP. + * When the timer fires, it will be handled elsewhere. + */ + while (1) { + /* + * Wait for input from SCSP + */ + FD_ZERO(&read_set); + FD_ZERO(&write_set); + FD_ZERO(&except_set); + for (aip = atmarp_intf_head; aip; aip = aip->ai_next) { + if (aip->ai_scsp_sock != -1) { + FD_SET(aip->ai_scsp_sock, &read_set); + } + } + rc = select(atmarp_max_socket + 1, + &read_set, &write_set, + &except_set, (struct timeval *)0); + if (rc < 0) { + if (harp_timer_exec) { + timer_proc(); + continue; + } else if (errno = EINTR) { + continue; + } else { + atmarp_log(LOG_ERR, "Select failed"); + abort(); + } + } + + /* + * Read and process the input from SCSP + */ + for (i = 0; i <= atmarp_max_socket; i++) { + if (FD_ISSET(i, &read_set)) { + aip = atmarp_find_intf_sock(i); + if (aip) + rc = atmarp_scsp_read(aip); + } + } + } +} |