Home | History | Annotate | Line # | Download | only in altqd
altqd.c revision 1.2
      1  1.1  thorpej /*	$KAME: altqd.c,v 1.2 2000/10/18 09:15:15 kjc Exp $	*/
      2  1.1  thorpej /*
      3  1.1  thorpej  * Copyright (C) 1997-2000
      4  1.1  thorpej  *	Sony Computer Science Laboratories, Inc.  All rights reserved.
      5  1.1  thorpej  *
      6  1.1  thorpej  * Redistribution and use in source and binary forms, with or without
      7  1.1  thorpej  * modification, are permitted provided that the following conditions
      8  1.1  thorpej  * are met:
      9  1.1  thorpej  * 1. Redistributions of source code must retain the above copyright
     10  1.1  thorpej  *    notice, this list of conditions and the following disclaimer.
     11  1.1  thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     12  1.1  thorpej  *    notice, this list of conditions and the following disclaimer in the
     13  1.1  thorpej  *    documentation and/or other materials provided with the distribution.
     14  1.1  thorpej  *
     15  1.1  thorpej  * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
     16  1.1  thorpej  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     17  1.1  thorpej  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     18  1.1  thorpej  * ARE DISCLAIMED.  IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
     19  1.1  thorpej  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20  1.1  thorpej  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     21  1.1  thorpej  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22  1.1  thorpej  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23  1.1  thorpej  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24  1.1  thorpej  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25  1.1  thorpej  * SUCH DAMAGE.
     26  1.1  thorpej  */
     27  1.1  thorpej /*******************************************************************
     28  1.1  thorpej 
     29  1.1  thorpej   Copyright (c) 1996 by the University of Southern California
     30  1.1  thorpej   All rights reserved.
     31  1.1  thorpej 
     32  1.1  thorpej   Permission to use, copy, modify, and distribute this software and its
     33  1.1  thorpej   documentation in source and binary forms for any purpose and without
     34  1.1  thorpej   fee is hereby granted, provided that both the above copyright notice
     35  1.1  thorpej   and this permission notice appear in all copies. and that any
     36  1.1  thorpej   documentation, advertising materials, and other materials related to
     37  1.1  thorpej   such distribution and use acknowledge that the software was developed
     38  1.1  thorpej   in part by the University of Southern California, Information
     39  1.1  thorpej   Sciences Institute.  The name of the University may not be used to
     40  1.1  thorpej   endorse or promote products derived from this software without
     41  1.1  thorpej   specific prior written permission.
     42  1.1  thorpej 
     43  1.1  thorpej   THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about
     44  1.1  thorpej   the suitability of this software for any purpose.  THIS SOFTWARE IS
     45  1.1  thorpej   PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
     46  1.1  thorpej   INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
     47  1.1  thorpej   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     48  1.1  thorpej 
     49  1.1  thorpej   Other copyrights might apply to parts of this software and are so
     50  1.1  thorpej   noted when applicable.
     51  1.1  thorpej 
     52  1.1  thorpej ********************************************************************/
     53  1.1  thorpej 
     54  1.1  thorpej #include <stdio.h>
     55  1.1  thorpej #include <stdlib.h>
     56  1.1  thorpej #include <unistd.h>
     57  1.1  thorpej #include <string.h>
     58  1.1  thorpej #include <ctype.h>
     59  1.1  thorpej #include <errno.h>
     60  1.1  thorpej #include <signal.h>
     61  1.1  thorpej #include <fcntl.h>
     62  1.1  thorpej #include <syslog.h>
     63  1.1  thorpej #include <err.h>
     64  1.1  thorpej 
     65  1.1  thorpej #include <sys/param.h>
     66  1.1  thorpej #include <sys/socket.h>
     67  1.1  thorpej #include <sys/un.h>
     68  1.1  thorpej #include <sys/stat.h>
     69  1.1  thorpej 
     70  1.1  thorpej #include <net/if.h>
     71  1.1  thorpej #include <netinet/in.h>
     72  1.1  thorpej #include <arpa/inet.h>
     73  1.1  thorpej 
     74  1.1  thorpej #include <altq/altq.h>
     75  1.1  thorpej #include "altq_qop.h"
     76  1.1  thorpej #include "quip_server.h"
     77  1.1  thorpej 
     78  1.1  thorpej #define  ALTQD_PID_FILE	  "/var/run/altqd.pid"
     79  1.1  thorpej 
     80  1.1  thorpej static int altqd_socket = -1;
     81  1.1  thorpej #define MAX_CLIENT		10
     82  1.1  thorpej static FILE *client[MAX_CLIENT];
     83  1.1  thorpej 
     84  1.1  thorpej /* for command mode */
     85  1.1  thorpej int             T;  		/* Current Thread number */
     86  1.1  thorpej FILE		*infp;		/* Input file pointer */
     87  1.1  thorpej char           *infile = NULL;  /* command input file.  stdin if NULL. */
     88  1.1  thorpej fd_set		fds, t_fds;
     89  1.1  thorpej 
     90  1.1  thorpej #define  DEFAULT_DEBUG_MASK	0
     91  1.1  thorpej #define  DEFAULT_LOGGING_LEVEL	LOG_INFO
     92  1.1  thorpej 
     93  1.1  thorpej static void usage(void)
     94  1.1  thorpej {
     95  1.1  thorpej 	fprintf(stderr, "usage: altqd [options]\n");
     96  1.1  thorpej 	fprintf(stderr, "    options:\n");
     97  1.1  thorpej 	fprintf(stderr, "    -f config_file	: set config file\n");
     98  1.1  thorpej 	fprintf(stderr, "    -v			: verbose (no daemonize)\n");
     99  1.1  thorpej 	fprintf(stderr, "    -d			: debug (no daemonize)\n");
    100  1.1  thorpej }
    101  1.1  thorpej 
    102  1.1  thorpej static void
    103  1.1  thorpej sig_handler(int sig)
    104  1.1  thorpej {
    105  1.1  thorpej 	if (sig == SIGPIPE) {
    106  1.1  thorpej 		/*
    107  1.1  thorpej 		 * we have lost an API connection.
    108  1.1  thorpej 		 * a subsequent output operation will catch EPIPE.
    109  1.1  thorpej 		 */
    110  1.1  thorpej 		return;
    111  1.1  thorpej 	}
    112  1.1  thorpej 
    113  1.1  thorpej 	qcmd_destroyall();
    114  1.1  thorpej 
    115  1.1  thorpej 	if (sig == SIGHUP) {
    116  1.1  thorpej 		printf("reinitializing altqd...\n");
    117  1.1  thorpej 		qcmd_init();
    118  1.1  thorpej 		return;
    119  1.1  thorpej 	}
    120  1.1  thorpej 
    121  1.1  thorpej 	fprintf(stderr, "Exiting on signal %d\n", sig);
    122  1.1  thorpej 
    123  1.1  thorpej 	/* if we have a pid file, remove it */
    124  1.1  thorpej 	if (daemonize) {
    125  1.1  thorpej 		unlink(ALTQD_PID_FILE);
    126  1.1  thorpej 		closelog();
    127  1.1  thorpej 	}
    128  1.1  thorpej 
    129  1.1  thorpej 	if (altqd_socket >= 0) {
    130  1.1  thorpej 		close(altqd_socket);
    131  1.1  thorpej 		altqd_socket = -1;
    132  1.1  thorpej 	}
    133  1.1  thorpej 
    134  1.1  thorpej 	exit(0);
    135  1.1  thorpej }
    136  1.1  thorpej 
    137  1.1  thorpej int main(int argc, char **argv)
    138  1.1  thorpej {
    139  1.1  thorpej 	int		c;
    140  1.1  thorpej 	int		i, maxfd;
    141  1.1  thorpej 	extern char	*optarg;
    142  1.1  thorpej 
    143  1.1  thorpej 	m_debug = DEFAULT_DEBUG_MASK;
    144  1.1  thorpej 	l_debug = DEFAULT_LOGGING_LEVEL;
    145  1.1  thorpej 
    146  1.1  thorpej 	while ((c = getopt(argc, argv, "f:vDdl:")) != -1) {
    147  1.1  thorpej 		switch (c) {
    148  1.1  thorpej 		case 'f':
    149  1.1  thorpej 			altqconfigfile = optarg;
    150  1.1  thorpej 			break;
    151  1.1  thorpej 
    152  1.1  thorpej 		case 'D':	/* -D => dummy mode */
    153  1.1  thorpej 			Debug_mode = 1;
    154  1.1  thorpej 			printf("Debug mode set.\n");
    155  1.1  thorpej 			break;
    156  1.1  thorpej 
    157  1.1  thorpej 		case 'v':
    158  1.1  thorpej 			l_debug = LOG_DEBUG;
    159  1.1  thorpej 			m_debug |= DEBUG_ALTQ;
    160  1.1  thorpej 			daemonize = 0;
    161  1.1  thorpej 			break;
    162  1.1  thorpej 
    163  1.1  thorpej 		case 'd':
    164  1.1  thorpej 			daemonize = 0;
    165  1.1  thorpej 			break;
    166  1.1  thorpej 
    167  1.1  thorpej 		case 'l':
    168  1.1  thorpej 			l_debug = atoi(optarg);
    169  1.1  thorpej 			break;
    170  1.1  thorpej 
    171  1.1  thorpej 		default:
    172  1.1  thorpej 			usage();
    173  1.1  thorpej 		}
    174  1.1  thorpej 	}
    175  1.1  thorpej 
    176  1.1  thorpej 	signal(SIGINT, sig_handler);
    177  1.1  thorpej 	signal(SIGTERM, sig_handler);
    178  1.1  thorpej 	signal(SIGHUP, sig_handler);
    179  1.1  thorpej 	signal(SIGPIPE, sig_handler);
    180  1.1  thorpej 
    181  1.1  thorpej 	if (daemonize)
    182  1.2    lukem 		openlog("altqd", LOG_PID, LOG_DAEMON);
    183  1.1  thorpej 
    184  1.1  thorpej 	if (qcmd_init() != 0) {
    185  1.1  thorpej 		if (daemonize)
    186  1.1  thorpej 			closelog();
    187  1.1  thorpej 		exit(1);
    188  1.1  thorpej 	}
    189  1.1  thorpej 
    190  1.1  thorpej 	/*
    191  1.1  thorpej 	 * open a unix domain socket for altqd clients
    192  1.1  thorpej 	 */
    193  1.1  thorpej 	for (i = 0; i < MAX_CLIENT; i++)
    194  1.1  thorpej 		client[i] = NULL;
    195  1.1  thorpej 	if ((altqd_socket = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0)
    196  1.1  thorpej 		LOG(LOG_ERR, errno, "can't open unix domain socket\n");
    197  1.1  thorpej 	else {
    198  1.1  thorpej 		struct sockaddr_un addr;
    199  1.1  thorpej 
    200  1.1  thorpej 		unlink(QUIP_PATH);
    201  1.1  thorpej 		bzero(&addr, sizeof(addr));
    202  1.1  thorpej 		addr.sun_family = AF_LOCAL;
    203  1.1  thorpej 		strcpy(addr.sun_path, QUIP_PATH);
    204  1.1  thorpej 		if (bind(altqd_socket, (struct sockaddr *)&addr,
    205  1.1  thorpej 			 sizeof(addr)) < 0) {
    206  1.1  thorpej 			LOG(LOG_ERR, errno, "can't bind to %s\n",
    207  1.1  thorpej 			    QUIP_PATH);
    208  1.1  thorpej 			altqd_socket = -1;
    209  1.1  thorpej 		}
    210  1.1  thorpej 		chmod(QUIP_PATH, 0666);
    211  1.1  thorpej 		if (listen(altqd_socket, SOMAXCONN) < 0) {
    212  1.1  thorpej 			LOG(LOG_ERR, errno, "can't listen to %s\n",
    213  1.1  thorpej 			    QUIP_PATH);
    214  1.1  thorpej 			altqd_socket = -1;
    215  1.1  thorpej 		}
    216  1.1  thorpej 	}
    217  1.1  thorpej 
    218  1.1  thorpej 	if (daemonize) {
    219  1.1  thorpej 		FILE *fp;
    220  1.1  thorpej 
    221  1.1  thorpej 		printf("altqd: going into the daemon mode.\n");
    222  1.1  thorpej 
    223  1.1  thorpej 		daemon(0, 0);
    224  1.1  thorpej 
    225  1.1  thorpej 		/* save pid to the pid file (/var/tmp/altqd.pid) */
    226  1.1  thorpej 		if ((fp = fopen(ALTQD_PID_FILE, "w")) != NULL) {
    227  1.1  thorpej 			fprintf(fp, "%d\n", getpid());
    228  1.1  thorpej 			fclose(fp);
    229  1.1  thorpej 		}
    230  1.1  thorpej 		else
    231  1.1  thorpej 			warn("can't open pid file: %s: %s",
    232  1.1  thorpej 			     ALTQD_PID_FILE, strerror(errno));
    233  1.1  thorpej 	} else {
    234  1.1  thorpej 		/* interactive mode */
    235  1.1  thorpej 		if (infile) {
    236  1.1  thorpej 			if (NULL == (infp = fopen(infile, "r"))) {
    237  1.1  thorpej 				perror("Cannot open input file");
    238  1.1  thorpej 				exit(1);
    239  1.1  thorpej 			}
    240  1.1  thorpej 		} else {
    241  1.1  thorpej 			infp = stdin;
    242  1.1  thorpej 			printf("\nEnter ? or command:\n");
    243  1.1  thorpej 			printf("altqd %s> ", cur_ifname());
    244  1.1  thorpej 		}
    245  1.1  thorpej 		fflush(stdout);
    246  1.1  thorpej 	}
    247  1.1  thorpej 
    248  1.1  thorpej 	/*
    249  1.1  thorpej 	 * go into the command mode.
    250  1.1  thorpej 	 * the code below is taken from rtap of rsvpd.
    251  1.1  thorpej 	 */
    252  1.1  thorpej 	FD_ZERO(&fds);
    253  1.1  thorpej 	maxfd = 0;
    254  1.1  thorpej 	if (infp != NULL) {
    255  1.1  thorpej 		FD_SET(fileno(infp), &fds);
    256  1.1  thorpej 		maxfd = MAX(maxfd, fileno(infp) + 1);
    257  1.1  thorpej 	}
    258  1.1  thorpej 	if (altqd_socket >= 0) {
    259  1.1  thorpej 		FD_SET(altqd_socket, &fds);
    260  1.1  thorpej 		maxfd = MAX(maxfd, altqd_socket + 1);
    261  1.1  thorpej 	}
    262  1.1  thorpej 	while (1) {
    263  1.1  thorpej 		int rc;
    264  1.1  thorpej 
    265  1.1  thorpej 		FD_COPY(&fds, &t_fds);
    266  1.1  thorpej 		rc = select(maxfd, &t_fds, NULL, NULL, NULL);
    267  1.1  thorpej 		if (rc < 0) {
    268  1.1  thorpej 			if (errno != EINTR) {
    269  1.1  thorpej 				perror("select");
    270  1.1  thorpej 				exit(1);
    271  1.1  thorpej 			}
    272  1.1  thorpej 			continue;
    273  1.1  thorpej 		}
    274  1.1  thorpej 
    275  1.1  thorpej 		/*
    276  1.1  thorpej 		 * If there is control input, read the input line,
    277  1.1  thorpej 		 * parse it, and execute.
    278  1.1  thorpej 		 */
    279  1.1  thorpej 		if (infp != NULL && FD_ISSET(fileno(infp), &t_fds)) {
    280  1.1  thorpej 			rc = DoCommand(infile, infp);
    281  1.1  thorpej 			if (rc == 0) {
    282  1.1  thorpej 				/*
    283  1.1  thorpej 				 * EOF on input.  If reading from file,
    284  1.1  thorpej 				 * go to stdin; else exit.
    285  1.1  thorpej 				 */
    286  1.1  thorpej 				if (infile) {
    287  1.1  thorpej 					infp = stdin;
    288  1.1  thorpej 					infile = NULL;
    289  1.1  thorpej 					printf("\nEnter ? or command:\n");
    290  1.1  thorpej 				FD_SET(fileno(infp), &fds);
    291  1.1  thorpej 				} else {
    292  1.1  thorpej 					LOG(LOG_INFO, 0, "Exiting.\n");
    293  1.1  thorpej 					(void) qcmd_destroyall();
    294  1.1  thorpej 					exit(0);
    295  1.1  thorpej 				}
    296  1.1  thorpej 			} else if (infp == stdin)
    297  1.1  thorpej 				printf("altqd %s> ", cur_ifname());
    298  1.1  thorpej 			fflush(stdout);
    299  1.1  thorpej 		} else if (altqd_socket >= 0 && FD_ISSET(altqd_socket, &t_fds)) {
    300  1.1  thorpej 			/*
    301  1.1  thorpej 			 * quip connection request from client via unix
    302  1.1  thorpej 			 * domain socket; get a new socket for this
    303  1.1  thorpej 			 * connection and add it to the select list.
    304  1.1  thorpej 			 */
    305  1.1  thorpej 			int newsock = accept(altqd_socket, NULL, NULL);
    306  1.1  thorpej 			if (newsock == -1) {
    307  1.1  thorpej 				LOG(LOG_ERR, errno, "accept error\n");
    308  1.1  thorpej 				continue;
    309  1.1  thorpej 			}
    310  1.1  thorpej 			FD_SET(newsock, &fds);
    311  1.1  thorpej 			for (i = 0; i < MAX_CLIENT; i++)
    312  1.1  thorpej 				if (client[i] == NULL) {
    313  1.1  thorpej 					client[i] = fdopen(newsock, "r+");
    314  1.1  thorpej 					break;
    315  1.1  thorpej 				}
    316  1.1  thorpej 			maxfd = MAX(maxfd, newsock + 1);
    317  1.1  thorpej 		} else {
    318  1.1  thorpej 			/*
    319  1.1  thorpej 			 * check input from a client via unix domain socket
    320  1.1  thorpej 			 */
    321  1.1  thorpej 			for (i = 0; i <= MAX_CLIENT; i++) {
    322  1.1  thorpej 				int fd;
    323  1.1  thorpej 
    324  1.1  thorpej 				if (client[i] == NULL)
    325  1.1  thorpej 					continue;
    326  1.1  thorpej 				fd = fileno(client[i]);
    327  1.1  thorpej 				if (FD_ISSET(fd, &t_fds)) {
    328  1.1  thorpej 					if (quip_input(client[i]) != 0 ||
    329  1.1  thorpej 					    fflush(client[i]) != 0) {
    330  1.1  thorpej 						/* connection closed */
    331  1.1  thorpej 						fclose(client[i]);
    332  1.1  thorpej 						client[i] = NULL;
    333  1.1  thorpej 						FD_CLR(fd, &fds);
    334  1.1  thorpej 					}
    335  1.1  thorpej 				}
    336  1.1  thorpej 			}
    337  1.1  thorpej 		}
    338  1.1  thorpej 	}
    339  1.1  thorpej }
    340