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