xref: /freebsd/contrib/ntp/libntp/iosignal.c (revision 224ba2bd)
1 /*
2  * ntp_io.c - input/output routines for ntpd.	The socket-opening code
3  *		   was shamelessly stolen from ntpd.
4  */
5 
6 #include "ntp_machine.h"
7 #include "ntpd.h"
8 #include "ntp_io.h"
9 #include "ntp_if.h"
10 #include "ntp_stdlib.h"
11 #include "iosignal.h"
12 
13 #include <stdio.h>
14 #include <signal.h>
15 #ifdef HAVE_SYS_PARAM_H
16 # include <sys/param.h>
17 #endif /* HAVE_SYS_PARAM_H */
18 #ifdef HAVE_SYS_IOCTL_H
19 # include <sys/ioctl.h>
20 #endif
21 
22 #include <arpa/inet.h>
23 
24 #if _BSDI_VERSION >= 199510
25 # include <ifaddrs.h>
26 #endif
27 
28 #if defined(HAVE_SIGNALED_IO)
29 static int sigio_block_count = 0;
30 extern	void	input_handler	P((l_fp *));
31 
32 /*
33  * SIGPOLL and SIGIO ROUTINES.
34  */
35 
36  /*
37  * Some systems (MOST) define SIGPOLL == SIGIO, others SIGIO == SIGPOLL, and
38  * a few have separate SIGIO and SIGPOLL signals.  This code checks for the
39  * SIGIO == SIGPOLL case at compile time.
40  * Do not defined USE_SIGPOLL or USE_SIGIO.
41  * these are interal only to ntp_io.c!
42  */
43 # if defined(USE_SIGPOLL)
44 #  undef USE_SIGPOLL
45 # endif
46 # if defined(USE_SIGIO)
47 #  undef USE_SIGIO
48 # endif
49 
50 # if defined(USE_TTY_SIGPOLL) || defined(USE_UDP_SIGPOLL)
51 #  define USE_SIGPOLL
52 # endif
53 
54 # if !defined(USE_TTY_SIGPOLL) || !defined(USE_UDP_SIGPOLL)
55 #  define USE_SIGIO
56 # endif
57 
58 # if defined(USE_SIGIO) && defined(USE_SIGPOLL)
59 #  if SIGIO == SIGPOLL
60 #	define USE_SIGIO
61 #	undef USE_SIGPOLL
62 #  endif /* SIGIO == SIGPOLL */
63 # endif /* USE_SIGIO && USE_SIGIO */
64 
65 
66 /*
67  * TTY initialization routines.
68  */
69 int
70 init_clock_sig(
71 	struct refclockio *rio
72 	)
73 {
74 # ifdef USE_TTY_SIGPOLL
75 	{
76 		/* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
77 		if (ioctl(rio->fd, I_SETSIG, S_INPUT) < 0)
78 		{
79 			msyslog(LOG_ERR,
80 				"init_clock_sig: ioctl(I_SETSIG, S_INPUT) failed: %m");
81 			return 1;
82 		}
83 		return 0;
84 	}
85 # else
86 	/*
87 	 * Special cases first!
88 	 */
89 	/* Was: defined(SYS_HPUX) */
90 #  if defined(FIOSSAIOOWN) && defined(FIOSNBIO) && defined(FIOSSAIOSTAT)
91 #define CLOCK_DONE
92 	{
93 		int pgrp, on = 1;
94 
95 		/* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
96 		pgrp = getpid();
97 		if (ioctl(rio->fd, FIOSSAIOOWN, (char *)&pgrp) == -1)
98 		{
99 			msyslog(LOG_ERR, "ioctl(FIOSSAIOOWN) fails for clock I/O: %m");
100 			exit(1);
101 			/*NOTREACHED*/
102 		}
103 
104 		/*
105 		 * set non-blocking, async I/O on the descriptor
106 		 */
107 		if (ioctl(rio->fd, FIOSNBIO, (char *)&on) == -1)
108 		{
109 			msyslog(LOG_ERR, "ioctl(FIOSNBIO) fails for clock I/O: %m");
110 			exit(1);
111 			/*NOTREACHED*/
112 		}
113 
114 		if (ioctl(rio->fd, FIOSSAIOSTAT, (char *)&on) == -1)
115 		{
116 			msyslog(LOG_ERR, "ioctl(FIOSSAIOSTAT) fails for clock I/O: %m");
117 			exit(1);
118 			/*NOTREACHED*/
119 		}
120 		return 0;
121 	}
122 #  endif /* SYS_HPUX: FIOSSAIOOWN && FIOSNBIO && FIOSSAIOSTAT */
123 	/* Was: defined(SYS_AIX) && !defined(_BSD) */
124 #  if !defined(_BSD) && defined(_AIX) && defined(FIOASYNC) && defined(FIOSETOWN)
125 	/*
126 	 * SYSV compatibility mode under AIX.
127 	 */
128 #define CLOCK_DONE
129 	{
130 		int pgrp, on = 1;
131 
132 		/* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
133 		if (ioctl(rio->fd, FIOASYNC, (char *)&on) == -1)
134 		{
135 			msyslog(LOG_ERR, "ioctl(FIOASYNC) fails for clock I/O: %m");
136 			return 1;
137 		}
138 		pgrp = -getpid();
139 		if (ioctl(rio->fd, FIOSETOWN, (char*)&pgrp) == -1)
140 		{
141 			msyslog(LOG_ERR, "ioctl(FIOSETOWN) fails for clock I/O: %m");
142 			return 1;
143 		}
144 
145 		if (fcntl(rio->fd, F_SETFL, FNDELAY|FASYNC) < 0)
146 		{
147 			msyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails for clock I/O: %m");
148 			return 1;
149 		}
150 		return 0;
151 	}
152 #  endif /* AIX && !BSD: !_BSD && FIOASYNC && FIOSETOWN */
153 #  ifndef  CLOCK_DONE
154 	{
155 		/* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
156 #	if defined(TIOCSCTTY) && defined(USE_FSETOWNCTTY)
157 		/*
158 		 * there are, however, always exceptions to the rules
159 		 * one is, that OSF accepts SETOWN on TTY fd's only, iff they are
160 		 * CTTYs. SunOS and HPUX do not semm to have this restriction.
161 		 * another question is: how can you do multiple SIGIO from several
162 		 * ttys (as they all should be CTTYs), wondering...
163 		 *
164 		 * kd 95-07-16
165 		 */
166 		if (ioctl(rio->fd, TIOCSCTTY, 0) == -1)
167 		{
168 			msyslog(LOG_ERR, "ioctl(TIOCSCTTY, 0) fails for clock I/O: %m");
169 			return 1;
170 		}
171 #	endif /* TIOCSCTTY && USE_FSETOWNCTTY */
172 
173 		if (fcntl(rio->fd, F_SETOWN, getpid()) == -1)
174 		{
175 			msyslog(LOG_ERR, "fcntl(F_SETOWN) fails for clock I/O: %m");
176 			return 1;
177 		}
178 
179 		if (fcntl(rio->fd, F_SETFL, FNDELAY|FASYNC) < 0)
180 		{
181 			msyslog(LOG_ERR,
182 				"fcntl(FNDELAY|FASYNC) fails for clock I/O: %m");
183 			return 1;
184 		}
185 		return 0;
186 	}
187 #  endif /* CLOCK_DONE */
188 # endif /* !USE_TTY_SIGPOLL  */
189 }
190 
191 
192 
193 void
194 init_socket_sig(
195 	int fd
196 	)
197 {
198 # ifdef USE_UDP_SIGPOLL
199 	{
200 		if (ioctl(fd, I_SETSIG, S_INPUT) < 0)
201 		{
202 			msyslog(LOG_ERR,
203 				"init_socket_sig: ioctl(I_SETSIG, S_INPUT) failed: %m");
204 			exit(1);
205 		}
206 	}
207 # else /* USE_UDP_SIGPOLL */
208 	{
209 		int pgrp;
210 # ifdef FIOASYNC
211 		int on = 1;
212 # endif
213 
214 #  if defined(FIOASYNC)
215 		if (ioctl(fd, FIOASYNC, (char *)&on) == -1)
216 		{
217 			msyslog(LOG_ERR, "ioctl(FIOASYNC) fails: %m");
218 			exit(1);
219 			/*NOTREACHED*/
220 		}
221 #  elif defined(FASYNC)
222 		{
223 			int flags;
224 
225 			if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
226 			{
227 				msyslog(LOG_ERR, "fcntl(F_GETFL) fails: %m");
228 				exit(1);
229 				/*NOTREACHED*/
230 			}
231 			if (fcntl(fd, F_SETFL, flags|FASYNC) < 0)
232 			{
233 				msyslog(LOG_ERR, "fcntl(...|FASYNC) fails: %m");
234 				exit(1);
235 				/*NOTREACHED*/
236 			}
237 		}
238 #  else
239 #	include "Bletch: Need asynchronous I/O!"
240 #  endif
241 
242 #  ifdef UDP_BACKWARDS_SETOWN
243 		pgrp = -getpid();
244 #  else
245 		pgrp = getpid();
246 #  endif
247 
248 #  if defined(SIOCSPGRP)
249 		if (ioctl(fd, SIOCSPGRP, (char *)&pgrp) == -1)
250 		{
251 			msyslog(LOG_ERR, "ioctl(SIOCSPGRP) fails: %m");
252 			exit(1);
253 			/*NOTREACHED*/
254 		}
255 #  elif defined(FIOSETOWN)
256 		if (ioctl(fd, FIOSETOWN, (char*)&pgrp) == -1)
257 		{
258 			msyslog(LOG_ERR, "ioctl(FIOSETOWN) fails: %m");
259 			exit(1);
260 			/*NOTREACHED*/
261 		}
262 #  elif defined(F_SETOWN)
263 		if (fcntl(fd, F_SETOWN, pgrp) == -1)
264 		{
265 			msyslog(LOG_ERR, "fcntl(F_SETOWN) fails: %m");
266 			exit(1);
267 			/*NOTREACHED*/
268 		}
269 #  else
270 #	include "Bletch: Need to set process(group) to receive SIG(IO|POLL)"
271 #  endif
272 	}
273 # endif /* USE_UDP_SIGPOLL */
274 }
275 
276 RETSIGTYPE
277 sigio_handler(
278 	int sig
279 	)
280 {
281 	int saved_errno = errno;
282 	l_fp ts;
283 
284 	get_systime(&ts);
285 	(void)input_handler(&ts);
286 	errno = saved_errno;
287 }
288 
289 /*
290  * Signal support routines.
291  */
292 # ifdef HAVE_SIGACTION
293 void
294 set_signal(void)
295 {
296 #  ifdef USE_SIGIO
297 	(void) signal_no_reset(SIGIO, sigio_handler);
298 # endif
299 #  ifdef USE_SIGPOLL
300 	(void) signal_no_reset(SIGPOLL, sigio_handler);
301 # endif
302 }
303 
304 void
305 block_io_and_alarm(void)
306 {
307 	sigset_t set;
308 
309 	if (sigemptyset(&set))
310 	    msyslog(LOG_ERR, "block_io_and_alarm: sigemptyset() failed: %m");
311 #  if defined(USE_SIGIO)
312 	if (sigaddset(&set, SIGIO))
313 	    msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGIO) failed: %m");
314 #  endif
315 #  if defined(USE_SIGPOLL)
316 	if (sigaddset(&set, SIGPOLL))
317 	    msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGPOLL) failed: %m");
318 #  endif
319 	if (sigaddset(&set, SIGALRM))
320 	    msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGALRM) failed: %m");
321 
322 	if (sigprocmask(SIG_BLOCK, &set, NULL))
323 	    msyslog(LOG_ERR, "block_io_and_alarm: sigprocmask() failed: %m");
324 }
325 
326 void
327 block_sigio(void)
328 {
329 	sigset_t set;
330 
331 	++sigio_block_count;
332 	if (sigio_block_count > 1)
333 	    msyslog(LOG_INFO, "block_sigio: sigio_block_count > 1");
334 	if (sigio_block_count < 1)
335 	    msyslog(LOG_INFO, "block_sigio: sigio_block_count < 1");
336 
337 	if (sigemptyset(&set))
338 	    msyslog(LOG_ERR, "block_sigio: sigemptyset() failed: %m");
339 #  if defined(USE_SIGIO)
340 	if (sigaddset(&set, SIGIO))
341 	    msyslog(LOG_ERR, "block_sigio: sigaddset(SIGIO) failed: %m");
342 #  endif
343 #  if defined(USE_SIGPOLL)
344 	if (sigaddset(&set, SIGPOLL))
345 	    msyslog(LOG_ERR, "block_sigio: sigaddset(SIGPOLL) failed: %m");
346 #  endif
347 
348 	if (sigprocmask(SIG_BLOCK, &set, NULL))
349 	    msyslog(LOG_ERR, "block_sigio: sigprocmask() failed: %m");
350 }
351 
352 void
353 unblock_io_and_alarm(void)
354 {
355 	sigset_t unset;
356 
357 	if (sigemptyset(&unset))
358 	    msyslog(LOG_ERR, "unblock_io_and_alarm: sigemptyset() failed: %m");
359 
360 #  if defined(USE_SIGIO)
361 	if (sigaddset(&unset, SIGIO))
362 	    msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGIO) failed: %m");
363 #  endif
364 #  if defined(USE_SIGPOLL)
365 	if (sigaddset(&unset, SIGPOLL))
366 	    msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGPOLL) failed: %m");
367 #  endif
368 	if (sigaddset(&unset, SIGALRM))
369 	    msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGALRM) failed: %m");
370 
371 	if (sigprocmask(SIG_UNBLOCK, &unset, NULL))
372 	    msyslog(LOG_ERR, "unblock_io_and_alarm: sigprocmask() failed: %m");
373 }
374 
375 void
376 unblock_sigio(void)
377 {
378 	sigset_t unset;
379 
380 	--sigio_block_count;
381 	if (sigio_block_count > 0)
382 	    msyslog(LOG_INFO, "unblock_sigio: sigio_block_count > 0");
383 	if (sigio_block_count < 0)
384 	    msyslog(LOG_INFO, "unblock_sigio: sigio_block_count < 0");
385 
386 	if (sigemptyset(&unset))
387 	    msyslog(LOG_ERR, "unblock_sigio: sigemptyset() failed: %m");
388 
389 #  if defined(USE_SIGIO)
390 	if (sigaddset(&unset, SIGIO))
391 	    msyslog(LOG_ERR, "unblock_sigio: sigaddset(SIGIO) failed: %m");
392 #  endif
393 #  if defined(USE_SIGPOLL)
394 	if (sigaddset(&unset, SIGPOLL))
395 	    msyslog(LOG_ERR, "unblock_sigio: sigaddset(SIGPOLL) failed: %m");
396 #  endif
397 
398 	if (sigprocmask(SIG_UNBLOCK, &unset, NULL))
399 	    msyslog(LOG_ERR, "unblock_sigio: sigprocmask() failed: %m");
400 }
401 
402 void
403 wait_for_signal(void)
404 {
405 	sigset_t old;
406 
407 	if (sigprocmask(SIG_UNBLOCK, NULL, &old))
408 	    msyslog(LOG_ERR, "wait_for_signal: sigprocmask() failed: %m");
409 
410 #  if defined(USE_SIGIO)
411 	if (sigdelset(&old, SIGIO))
412 	    msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGIO) failed: %m");
413 #  endif
414 #  if defined(USE_SIGPOLL)
415 	if (sigdelset(&old, SIGPOLL))
416 	    msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGPOLL) failed: %m");
417 #  endif
418 	if (sigdelset(&old, SIGALRM))
419 	    msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGALRM) failed: %m");
420 
421 	if (sigsuspend(&old) && (errno != EINTR))
422 	    msyslog(LOG_ERR, "wait_for_signal: sigsuspend() failed: %m");
423 }
424 
425 # else /* !HAVE_SIGACTION */
426 /*
427  * Must be an old bsd system.
428  * We assume there is no SIGPOLL.
429  */
430 
431 void
432 block_io_and_alarm(void)
433 {
434 	int mask;
435 
436 	mask = sigmask(SIGIO) | sigmask(SIGALRM);
437 	if (sigblock(mask))
438 	    msyslog(LOG_ERR, "block_io_and_alarm: sigblock() failed: %m");
439 }
440 
441 void
442 block_sigio(void)
443 {
444 	int mask;
445 
446 	++sigio_block_count;
447 	if (sigio_block_count > 1)
448 	    msyslog(LOG_INFO, "block_sigio: sigio_block_count > 1");
449 	if (sigio_block_count < 1)
450 	    msyslog(LOG_INFO, "block_sigio: sigio_block_count < 1");
451 
452 	mask = sigmask(SIGIO);
453 	if (sigblock(mask))
454 	    msyslog(LOG_ERR, "block_sigio: sigblock() failed: %m");
455 }
456 
457 void
458 set_signal(void)
459 {
460 	(void) signal_no_reset(SIGIO, sigio_handler);
461 }
462 
463 void
464 unblock_io_and_alarm(void)
465 {
466 	int mask, omask;
467 
468 	mask = sigmask(SIGIO) | sigmask(SIGALRM);
469 	omask = sigblock(0);
470 	omask &= ~mask;
471 	(void) sigsetmask(omask);
472 }
473 
474 void
475 unblock_sigio(void)
476 {
477 	int mask, omask;
478 
479 	--sigio_block_count;
480 	if (sigio_block_count > 0)
481 	    msyslog(LOG_INFO, "unblock_sigio: sigio_block_count > 0");
482 	if (sigio_block_count < 0)
483 	    msyslog(LOG_INFO, "unblock_sigio: sigio_block_count < 0");
484 	mask = sigmask(SIGIO);
485 	omask = sigblock(0);
486 	omask &= ~mask;
487 	(void) sigsetmask(omask);
488 }
489 
490 void
491 wait_for_signal(void)
492 {
493 	int mask, omask;
494 
495 	mask = sigmask(SIGIO) | sigmask(SIGALRM);
496 	omask = sigblock(0);
497 	omask &= ~mask;
498 	if (sigpause(omask) && (errno != EINTR))
499 	    msyslog(LOG_ERR, "wait_for_signal: sigspause() failed: %m");
500 }
501 
502 # endif /* HAVE_SIGACTION */
503 #else
504 int  NotAnEmptyCompilationUnit;
505 #endif
506