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