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