iosignal.c revision 54359
1/*
2 * ntp_io.c - input/output routines for ntpd.	The socket-opening code
3 *		   was shamelessly stolen from ntpd.
4 */
5
6#ifdef HAVE_CONFIG_H
7# include <config.h>
8#endif
9
10#include <stdio.h>
11#include <signal.h>
12#include <sys/types.h>
13#ifdef HAVE_SYS_PARAM_H
14# include <sys/param.h>
15#endif /* HAVE_SYS_PARAM_H */
16#ifdef HAVE_SYS_TIME_H
17# include <sys/time.h>
18#endif
19#ifdef HAVE_NETINET_IN_H
20# include <netinet/in.h>
21#endif
22#ifdef HAVE_SYS_IOCTL_H
23# include <sys/ioctl.h>
24#endif
25#ifdef HAVE_SYS_SOCKIO_H	/* UXPV: SIOC* #defines (Frank Vance <fvance@waii.com>) */
26# include <sys/sockio.h>
27#endif
28#include <arpa/inet.h>
29
30#if _BSDI_VERSION >= 199510
31# include <ifaddrs.h>
32#endif
33/*	98/06/01  */
34#include "ntp_machine.h"	/*  98/06/01  */
35#include "ntpd.h"
36#include "ntp_io.h"
37#include "ntp_if.h"
38#include "ntp_stdlib.h"
39#include "iosignal.h"
40
41#if defined(HAVE_SIGNALED_IO)
42static int sigio_block_count = 0;
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	(void)input_handler(&ts);
299	errno = saved_errno;
300}
301
302/*
303 * Signal support routines.
304 */
305# ifdef HAVE_SIGACTION
306void
307set_signal(void)
308{
309#  ifdef USE_SIGIO
310	(void) signal_no_reset(SIGIO, sigio_handler);
311# endif
312#  ifdef USE_SIGPOLL
313	(void) signal_no_reset(SIGPOLL, sigio_handler);
314# endif
315}
316
317void
318block_io_and_alarm(void)
319{
320	sigset_t set;
321
322	if (sigemptyset(&set))
323	    msyslog(LOG_ERR, "block_io_and_alarm: sigemptyset() failed: %m");
324#  if defined(USE_SIGIO)
325	if (sigaddset(&set, SIGIO))
326	    msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGIO) failed: %m");
327#  endif
328#  if defined(USE_SIGPOLL)
329	if (sigaddset(&set, SIGPOLL))
330	    msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGPOLL) failed: %m");
331#  endif
332	if (sigaddset(&set, SIGALRM))
333	    msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGALRM) failed: %m");
334
335	if (sigprocmask(SIG_BLOCK, &set, NULL))
336	    msyslog(LOG_ERR, "block_io_and_alarm: sigprocmask() failed: %m");
337}
338
339void
340block_sigio(void)
341{
342	sigset_t set;
343
344	++sigio_block_count;
345	if (sigio_block_count > 1)
346	    msyslog(LOG_INFO, "block_sigio: sigio_block_count > 1");
347	if (sigio_block_count < 1)
348	    msyslog(LOG_INFO, "block_sigio: sigio_block_count < 1");
349
350	if (sigemptyset(&set))
351	    msyslog(LOG_ERR, "block_sigio: sigemptyset() failed: %m");
352#  if defined(USE_SIGIO)
353	if (sigaddset(&set, SIGIO))
354	    msyslog(LOG_ERR, "block_sigio: sigaddset(SIGIO) failed: %m");
355#  endif
356#  if defined(USE_SIGPOLL)
357	if (sigaddset(&set, SIGPOLL))
358	    msyslog(LOG_ERR, "block_sigio: sigaddset(SIGPOLL) failed: %m");
359#  endif
360
361	if (sigprocmask(SIG_BLOCK, &set, NULL))
362	    msyslog(LOG_ERR, "block_sigio: sigprocmask() failed: %m");
363}
364
365void
366unblock_io_and_alarm(void)
367{
368	sigset_t unset;
369
370	if (sigemptyset(&unset))
371	    msyslog(LOG_ERR, "unblock_io_and_alarm: sigemptyset() failed: %m");
372
373#  if defined(USE_SIGIO)
374	if (sigaddset(&unset, SIGIO))
375	    msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGIO) failed: %m");
376#  endif
377#  if defined(USE_SIGPOLL)
378	if (sigaddset(&unset, SIGPOLL))
379	    msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGPOLL) failed: %m");
380#  endif
381	if (sigaddset(&unset, SIGALRM))
382	    msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGALRM) failed: %m");
383
384	if (sigprocmask(SIG_UNBLOCK, &unset, NULL))
385	    msyslog(LOG_ERR, "unblock_io_and_alarm: sigprocmask() failed: %m");
386}
387
388void
389unblock_sigio(void)
390{
391	sigset_t unset;
392
393	--sigio_block_count;
394	if (sigio_block_count > 0)
395	    msyslog(LOG_INFO, "unblock_sigio: sigio_block_count > 0");
396	if (sigio_block_count < 0)
397	    msyslog(LOG_INFO, "unblock_sigio: sigio_block_count < 0");
398
399	if (sigemptyset(&unset))
400	    msyslog(LOG_ERR, "unblock_sigio: sigemptyset() failed: %m");
401
402#  if defined(USE_SIGIO)
403	if (sigaddset(&unset, SIGIO))
404	    msyslog(LOG_ERR, "unblock_sigio: sigaddset(SIGIO) failed: %m");
405#  endif
406#  if defined(USE_SIGPOLL)
407	if (sigaddset(&unset, SIGPOLL))
408	    msyslog(LOG_ERR, "unblock_sigio: sigaddset(SIGPOLL) failed: %m");
409#  endif
410
411	if (sigprocmask(SIG_UNBLOCK, &unset, NULL))
412	    msyslog(LOG_ERR, "unblock_sigio: sigprocmask() failed: %m");
413}
414
415void
416wait_for_signal(void)
417{
418	sigset_t old;
419
420	if (sigprocmask(SIG_UNBLOCK, NULL, &old))
421	    msyslog(LOG_ERR, "wait_for_signal: sigprocmask() failed: %m");
422
423#  if defined(USE_SIGIO)
424	if (sigdelset(&old, SIGIO))
425	    msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGIO) failed: %m");
426#  endif
427#  if defined(USE_SIGPOLL)
428	if (sigdelset(&old, SIGPOLL))
429	    msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGPOLL) failed: %m");
430#  endif
431	if (sigdelset(&old, SIGALRM))
432	    msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGALRM) failed: %m");
433
434	if (sigsuspend(&old) && (errno != EINTR))
435	    msyslog(LOG_ERR, "wait_for_signal: sigsuspend() failed: %m");
436}
437
438# else /* !HAVE_SIGACTION */
439/*
440 * Must be an old bsd system.
441 * We assume there is no SIGPOLL.
442 */
443
444void
445block_io_and_alarm(void)
446{
447	int mask;
448
449	mask = sigmask(SIGIO) | sigmask(SIGALRM);
450	if (sigblock(mask))
451	    msyslog(LOG_ERR, "block_io_and_alarm: sigblock() failed: %m");
452}
453
454void
455block_sigio(void)
456{
457	int mask;
458
459	++sigio_block_count;
460	if (sigio_block_count > 1)
461	    msyslog(LOG_INFO, "block_sigio: sigio_block_count > 1");
462	if (sigio_block_count < 1)
463	    msyslog(LOG_INFO, "block_sigio: sigio_block_count < 1");
464
465	mask = sigmask(SIGIO);
466	if (sigblock(mask))
467	    msyslog(LOG_ERR, "block_sigio: sigblock() failed: %m");
468}
469
470void
471set_signal(void)
472{
473	(void) signal_no_reset(SIGIO, sigio_handler);
474}
475
476void
477unblock_io_and_alarm(void)
478{
479	int mask, omask;
480
481	mask = sigmask(SIGIO) | sigmask(SIGALRM);
482	omask = sigblock(0);
483	omask &= ~mask;
484	(void) sigsetmask(omask);
485}
486
487void
488unblock_sigio(void)
489{
490	int mask, omask;
491
492	--sigio_block_count;
493	if (sigio_block_count > 0)
494	    msyslog(LOG_INFO, "unblock_sigio: sigio_block_count > 0");
495	if (sigio_block_count < 0)
496	    msyslog(LOG_INFO, "unblock_sigio: sigio_block_count < 0");
497	mask = sigmask(SIGIO);
498	omask = sigblock(0);
499	omask &= ~mask;
500	(void) sigsetmask(omask);
501}
502
503void
504wait_for_signal(void)
505{
506	int mask, omask;
507
508	mask = sigmask(SIGIO) | sigmask(SIGALRM);
509	omask = sigblock(0);
510	omask &= ~mask;
511	if (sigpause(omask) && (errno != EINTR))
512	    msyslog(LOG_ERR, "wait_for_signal: sigspause() failed: %m");
513}
514
515# endif /* HAVE_SIGACTION */
516#else
517int  NotAnEmptyCompilationUnit;
518#endif
519