File: [local] / src / usr.sbin / sasyncd / sasyncd.c (download)
Revision 1.28, Tue Apr 10 15:58:21 2018 UTC (6 years, 2 months ago) by cheloha
Branch: MAIN
CVS Tags: OPENBSD_7_5_BASE, OPENBSD_7_5, OPENBSD_7_4_BASE, OPENBSD_7_4, OPENBSD_7_3_BASE, OPENBSD_7_3, OPENBSD_7_2_BASE, OPENBSD_7_2, OPENBSD_7_1_BASE, OPENBSD_7_1, OPENBSD_7_0_BASE, OPENBSD_7_0, OPENBSD_6_9_BASE, OPENBSD_6_9, OPENBSD_6_8_BASE, OPENBSD_6_8, OPENBSD_6_7_BASE, OPENBSD_6_7, OPENBSD_6_6_BASE, OPENBSD_6_6, OPENBSD_6_5_BASE, OPENBSD_6_5, OPENBSD_6_4_BASE, OPENBSD_6_4, HEAD Changes since 1.27: +7 -6 lines
Schedule events against the monotonic clock.
So that events fire punctually, even if the system clock is changed.
ok jca@
|
/* $OpenBSD: sasyncd.c,v 1.28 2018/04/10 15:58:21 cheloha Exp $ */
/*
* Copyright (c) 2005 Håkan Olsson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This code was written under funding by Multicom Security AB.
*/
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include "sasyncd.h"
volatile sig_atomic_t daemon_shutdown = 0;
/* Called by signal handler for controlled daemon shutdown. */
static void
sasyncd_stop(int s)
{
daemon_shutdown++;
}
static int
sasyncd_run(pid_t ppid)
{
struct timespec *timeout, ts;
fd_set *rfds, *wfds;
size_t fdsetsize;
int maxfd, n;
n = getdtablesize();
fdsetsize = howmany(n, NFDBITS) * sizeof(fd_mask);
rfds = malloc(fdsetsize);
if (!rfds) {
log_err("malloc(%lu) failed", (unsigned long)fdsetsize);
return -1;
}
wfds = malloc(fdsetsize);
if (!wfds) {
log_err("malloc(%lu) failed", (unsigned long)fdsetsize);
free(rfds);
return -1;
}
control_setrun();
signal(SIGINT, sasyncd_stop);
signal(SIGTERM, sasyncd_stop);
timer_add("carp_undemote", CARP_DEMOTE_MAXTIME,
monitor_carpundemote, NULL);
while (!daemon_shutdown) {
memset(rfds, 0, fdsetsize);
memset(wfds, 0, fdsetsize);
maxfd = net_set_rfds(rfds);
n = net_set_pending_wfds(wfds);
if (n > maxfd)
maxfd = n;
pfkey_set_rfd(rfds);
pfkey_set_pending_wfd(wfds);
if (cfgstate.pfkey_socket + 1 > maxfd)
maxfd = cfgstate.pfkey_socket + 1;
carp_set_rfd(rfds);
if (cfgstate.route_socket + 1 > maxfd)
maxfd = cfgstate.route_socket + 1;
timeout = &ts;
timer_next_event(&ts);
n = pselect(maxfd, rfds, wfds, NULL, timeout, NULL);
if (n == -1) {
if (errno != EINTR) {
log_err("select()");
sleep(1);
}
} else if (n) {
net_handle_messages(rfds);
net_send_messages(wfds);
pfkey_read_message(rfds);
pfkey_send_message(wfds);
carp_read_message(rfds);
}
timer_run();
/* Mostly for debugging. */
if (getppid() != ppid) {
log_msg(0, "sasyncd: parent died");
daemon_shutdown++;
}
}
free(rfds);
free(wfds);
return 0;
}
__dead static void
usage(void)
{
extern char *__progname;
fprintf(stderr, "usage: %s [-dnv] [-c config-file]\n", __progname);
exit(1);
}
int
main(int argc, char **argv)
{
extern char *__progname;
char *cfgfile = 0;
int ch, noaction = 0;
if (geteuid() != 0) {
/* No point in continuing. */
fprintf(stderr, "%s: This daemon needs to be run as root.\n",
__progname);
return 1;
}
while ((ch = getopt(argc, argv, "c:dnv")) != -1) {
switch (ch) {
case 'c':
if (cfgfile)
usage();
cfgfile = optarg;
break;
case 'd':
cfgstate.debug++;
break;
case 'n':
noaction = 1;
break;
case 'v':
cfgstate.verboselevel++;
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc > 0)
usage();
log_init(__progname);
timer_init();
cfgstate.runstate = INIT;
LIST_INIT(&cfgstate.peerlist);
cfgstate.listen_port = SASYNCD_DEFAULT_PORT;
cfgstate.flags |= CTL_DEFAULT;
if (!cfgfile)
cfgfile = SASYNCD_CFGFILE;
if (conf_parse_file(cfgfile) == 0 ) {
if (!cfgstate.sharedkey) {
fprintf(stderr, "config: "
"no shared key specified, cannot continue\n");
exit(1);
}
if (!cfgstate.carp_ifname || !*cfgstate.carp_ifname) {
fprintf(stderr, "config: "
"no carp interface specified, cannot continue\n");
exit(1);
}
} else {
exit(1);
}
if (noaction) {
fprintf(stderr, "configuration OK\n");
exit(0);
}
carp_demote(CARP_INC, 0);
if (carp_init())
return 1;
if (pfkey_init(0))
return 1;
if (net_init())
return 1;
if (!cfgstate.debug)
if (daemon(1, 0)) {
perror("daemon()");
exit(1);
}
if (monitor_init()) {
/* Parent, with privileges. */
monitor_loop();
exit(0);
}
/* Child, no privileges left. Run main loop. */
sasyncd_run(getppid());
/* Shutdown. */
log_msg(0, "shutting down...");
net_shutdown();
pfkey_shutdown();
return 0;
}