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