1 /* $NetBSD: altqd.c,v 1.8 2005/06/17 12:02:00 peter Exp $ */
2 /* $KAME: altqd.c,v 1.10 2002/02/20 10:42:26 kjc Exp $ */
4 * Copyright (c) 2001 Theo de Raadt
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * Copyright (C) 1997-2002
28 * Sony Computer Science Laboratories, Inc. All rights reserved.
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
39 * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
40 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
42 * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
43 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
44 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
45 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
47 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
48 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 #include <sys/param.h>
53 #include <sys/socket.h>
71 #include <altq/altq.h>
73 #include "quip_server.h"
76 #define ALTQD_PID_FILE "/var/run/altqd.pid"
80 static volatile sig_atomic_t gotsig_hup
, gotsig_int
, gotsig_term
;
82 static void usage(void);
83 static void sig_handler(int);
88 fprintf(stderr
, "usage: %s [-dv] [-f config]\n", getprogname());
107 * we have lost an API connection.
108 * a subsequent output operation will catch EPIPE.
115 main(int argc
, char **argv
)
117 int i
, c
, maxfd
, rval
, qpsock
;
119 FILE *fp
, *client
[MAX_CLIENT
];
124 for (i
= 0; i
< MAX_CLIENT
; i
++)
127 while ((c
= getopt(argc
, argv
, "f:vdl:")) != -1) {
130 altqconfigfile
= optarg
;
134 m_debug
|= DEBUG_ALTQ
;
141 l_debug
= atoi(optarg
);
148 signal(SIGINT
, sig_handler
);
149 signal(SIGTERM
, sig_handler
);
150 signal(SIGHUP
, sig_handler
);
151 signal(SIGPIPE
, sig_handler
);
154 openlog("altqd", LOG_PID
, LOG_DAEMON
);
156 if (qcmd_init() != 0) {
163 * open a unix domain socket for altqd clients
165 if ((qpsock
= socket(AF_LOCAL
, SOCK_STREAM
, 0)) < 0)
166 LOG(LOG_ERR
, errno
, "can't open unix domain socket");
168 struct sockaddr_un addr
;
170 bzero(&addr
, sizeof(addr
));
171 addr
.sun_family
= AF_LOCAL
;
172 strlcpy(addr
.sun_path
, QUIP_PATH
, sizeof(addr
.sun_path
));
174 if (bind(qpsock
, (struct sockaddr
*)&addr
,
176 LOG(LOG_ERR
, errno
, "can't bind to %s", QUIP_PATH
);
180 chmod(QUIP_PATH
, 0666);
181 if (listen(qpsock
, SOMAXCONN
) < 0) {
182 LOG(LOG_ERR
, errno
, "can't listen to %s", QUIP_PATH
);
191 /* save pid to the pid file (/var/tmp/altqd.pid) */
196 if ((fp
= fopen(ALTQD_PID_FILE
, "w")) != NULL
) {
197 fprintf(fp
, "%d\n", getpid());
200 LOG(LOG_WARNING
, errno
, "can't open pid file");
206 /* interactive mode */
208 printf("\nEnter ? or command:\n");
209 printf("altqd %s> ", cur_ifname());
214 * go into the command mode.
219 FD_SET(fileno(fp
), &fds
);
220 maxfd
= MAX(maxfd
, fileno(fp
) + 1);
223 FD_SET(qpsock
, &fds
);
224 maxfd
= MAX(maxfd
, qpsock
+ 1);
232 LOG(LOG_INFO
, 0, "reinitializing altqd...");
233 if (qcmd_init() != 0) {
234 LOG(LOG_INFO
, 0, "reinitialization failed");
238 if (gotsig_term
|| gotsig_int
) {
239 LOG(LOG_INFO
, 0, "Exiting on signal %d",
240 gotsig_term
? SIGTERM
: SIGINT
);
244 FD_COPY(&fds
, &rfds
);
245 if (select(maxfd
, &rfds
, NULL
, NULL
, NULL
) < 0) {
252 * if there is command input, read the input line,
253 * parse it, and execute.
255 if (fp
&& FD_ISSET(fileno(fp
), &rfds
)) {
256 rval
= do_command(fp
);
258 /* quit command or eof on input */
259 LOG(LOG_INFO
, 0, "Exiting.");
260 } else if (fp
== stdin
)
261 printf("altqd %s> ", cur_ifname());
263 } else if (qpsock
>= 0 && FD_ISSET(qpsock
, &rfds
)) {
265 * quip connection request from client via unix
266 * domain socket; get a new socket for this
267 * connection and add it to the select list.
269 int newsock
= accept(qpsock
, NULL
, NULL
);
272 LOG(LOG_ERR
, errno
, "accept");
275 FD_SET(newsock
, &fds
);
276 for (i
= 0; i
< MAX_CLIENT
; i
++)
277 if (client
[i
] == NULL
) {
278 client
[i
] = fdopen(newsock
, "r+");
281 maxfd
= MAX(maxfd
, newsock
+ 1);
284 * check input from a client via unix domain socket
286 for (i
= 0; i
< MAX_CLIENT
; i
++) {
289 if (client
[i
] == NULL
)
291 fd
= fileno(client
[i
]);
292 if (FD_ISSET(fd
, &rfds
)) {
293 if (quip_input(client
[i
]) != 0 ||
294 fflush(client
[i
]) != 0) {
295 /* connection closed */
305 /* cleanup and exit */
311 for (i
= 0; i
< MAX_CLIENT
; i
++)
312 if (client
[i
] != NULL
)
313 (void)fclose(client
[i
]);
316 /* if we have a pid file, remove it */
317 unlink(ALTQD_PID_FILE
);