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