FreeBSD-5.3/usr.sbin/atm/atmarpd/atmarpd.c

Compare this file to the similar file:
Show the results in this format:

/*
 *
 * ===================================
 * 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.
 *
 *	@(#) $FreeBSD: src/usr.sbin/atm/atmarpd/atmarpd.c,v 1.6 2003/07/29 13:40:52 harti Exp $
 *
 */

/*
 * Server Cache Synchronization Protocol (SCSP) Support
 * ----------------------------------------------------
 *
 * SCSP-ATMARP server interface: main line code
 *
 */

#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/ttycom.h>
#include <net/if.h>
#include <netinet/in.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 <errno.h>
#include <fcntl.h>
#include <libatm.h>
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>

#include "../scspd/scsp_msg.h"
#include "../scspd/scsp_if.h"
#include "../scspd/scsp_var.h"
#include "atmarp_var.h"

#ifndef lint
__RCSID("@(#) $FreeBSD: src/usr.sbin/atm/atmarpd/atmarpd.c,v 1.6 2003/07/29 13:40:52 harti Exp $");
#endif


/*
 * 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], '/')) != NULL)
		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(_PATH_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
	 */
	if (signal(SIGINT, atmarp_sigint) == SIG_ERR) {
		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
 *
 */
int
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);
			}
		}
	}
}