xref: /openbsd/usr.sbin/sasyncd/sasyncd.c (revision f6aab3d8)
1 /*	$OpenBSD: sasyncd.c,v 1.28 2018/04/10 15:58:21 cheloha Exp $	*/
2 
3 /*
4  * Copyright (c) 2005 H�kan Olsson.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
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.
15  *
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.
26  */
27 
28 /*
29  * This code was written under funding by Multicom Security AB.
30  */
31 
32 
33 #include <sys/types.h>
34 
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <pwd.h>
38 #include <signal.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <time.h>
43 #include <unistd.h>
44 
45 #include "sasyncd.h"
46 
47 volatile sig_atomic_t	daemon_shutdown = 0;
48 
49 /* Called by signal handler for controlled daemon shutdown. */
50 static void
51 sasyncd_stop(int s)
52 {
53 	daemon_shutdown++;
54 }
55 
56 static int
57 sasyncd_run(pid_t ppid)
58 {
59 	struct timespec	*timeout, ts;
60 	fd_set		*rfds, *wfds;
61 	size_t		 fdsetsize;
62 	int		 maxfd, n;
63 
64 	n = getdtablesize();
65 	fdsetsize = howmany(n, NFDBITS) * sizeof(fd_mask);
66 
67 	rfds = malloc(fdsetsize);
68 	if (!rfds) {
69 		log_err("malloc(%lu) failed", (unsigned long)fdsetsize);
70 		return -1;
71 	}
72 
73 	wfds = malloc(fdsetsize);
74 	if (!wfds) {
75 		log_err("malloc(%lu) failed", (unsigned long)fdsetsize);
76 		free(rfds);
77 		return -1;
78 	}
79 
80 	control_setrun();
81 
82 	signal(SIGINT, sasyncd_stop);
83 	signal(SIGTERM, sasyncd_stop);
84 
85 	timer_add("carp_undemote", CARP_DEMOTE_MAXTIME,
86 	    monitor_carpundemote, NULL);
87 
88 	while (!daemon_shutdown) {
89 		memset(rfds, 0, fdsetsize);
90 		memset(wfds, 0, fdsetsize);
91 		maxfd = net_set_rfds(rfds);
92 		n = net_set_pending_wfds(wfds);
93 		if (n > maxfd)
94 			maxfd = n;
95 
96 		pfkey_set_rfd(rfds);
97 		pfkey_set_pending_wfd(wfds);
98 		if (cfgstate.pfkey_socket + 1 > maxfd)
99 			maxfd = cfgstate.pfkey_socket + 1;
100 
101 		carp_set_rfd(rfds);
102 		if (cfgstate.route_socket + 1 > maxfd)
103 			maxfd = cfgstate.route_socket + 1;
104 
105 		timeout = &ts;
106 		timer_next_event(&ts);
107 
108 		n = pselect(maxfd, rfds, wfds, NULL, timeout, NULL);
109 		if (n == -1) {
110 			if (errno != EINTR) {
111 				log_err("select()");
112 				sleep(1);
113 			}
114 		} else if (n) {
115 			net_handle_messages(rfds);
116 			net_send_messages(wfds);
117 			pfkey_read_message(rfds);
118 			pfkey_send_message(wfds);
119 			carp_read_message(rfds);
120 		}
121 		timer_run();
122 
123 		/* Mostly for debugging. */
124 		if (getppid() != ppid) {
125 			log_msg(0, "sasyncd: parent died");
126 			daemon_shutdown++;
127 		}
128 	}
129 	free(rfds);
130 	free(wfds);
131 	return 0;
132 }
133 
134 __dead static void
135 usage(void)
136 {
137 	extern char *__progname;
138 
139 	fprintf(stderr, "usage: %s [-dnv] [-c config-file]\n", __progname);
140 	exit(1);
141 }
142 
143 int
144 main(int argc, char **argv)
145 {
146 	extern char	*__progname;
147 	char		*cfgfile = 0;
148 	int		 ch, noaction = 0;
149 
150 	if (geteuid() != 0) {
151 		/* No point in continuing. */
152 		fprintf(stderr, "%s: This daemon needs to be run as root.\n",
153 		    __progname);
154 		return 1;
155 	}
156 
157 	while ((ch = getopt(argc, argv, "c:dnv")) != -1) {
158 		switch (ch) {
159 		case 'c':
160 			if (cfgfile)
161 				usage();
162 			cfgfile = optarg;
163 			break;
164 		case 'd':
165 			cfgstate.debug++;
166 			break;
167 		case 'n':
168 			noaction = 1;
169 			break;
170 		case 'v':
171 			cfgstate.verboselevel++;
172 			break;
173 		default:
174 			usage();
175 		}
176 	}
177 	argc -= optind;
178 	argv += optind;
179 
180 	if (argc > 0)
181 		usage();
182 
183 	log_init(__progname);
184 	timer_init();
185 
186 	cfgstate.runstate = INIT;
187 	LIST_INIT(&cfgstate.peerlist);
188 
189 	cfgstate.listen_port = SASYNCD_DEFAULT_PORT;
190 	cfgstate.flags |= CTL_DEFAULT;
191 
192 	if (!cfgfile)
193 		cfgfile = SASYNCD_CFGFILE;
194 
195 	if (conf_parse_file(cfgfile) == 0 ) {
196 		if (!cfgstate.sharedkey) {
197 			fprintf(stderr, "config: "
198 			    "no shared key specified, cannot continue\n");
199 			exit(1);
200 		}
201 		if (!cfgstate.carp_ifname || !*cfgstate.carp_ifname) {
202 			fprintf(stderr, "config: "
203 			    "no carp interface specified, cannot continue\n");
204 			exit(1);
205 		}
206 	} else {
207 		exit(1);
208 	}
209 
210 	if (noaction) {
211 		fprintf(stderr, "configuration OK\n");
212 		exit(0);
213 	}
214 
215 	carp_demote(CARP_INC, 0);
216 
217 	if (carp_init())
218 		return 1;
219 	if (pfkey_init(0))
220 		return 1;
221 	if (net_init())
222 		return 1;
223 
224 	if (!cfgstate.debug)
225 		if (daemon(1, 0)) {
226 			perror("daemon()");
227 			exit(1);
228 		}
229 
230 	if (monitor_init()) {
231 		/* Parent, with privileges. */
232 		monitor_loop();
233 		exit(0);
234 	}
235 
236 	/* Child, no privileges left. Run main loop. */
237 	sasyncd_run(getppid());
238 
239 	/* Shutdown. */
240 	log_msg(0, "shutting down...");
241 
242 	net_shutdown();
243 	pfkey_shutdown();
244 	return 0;
245 }
246