iosignal.c revision 82498
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;
30extern	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 */
69int
70init_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
193void
194init_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
276RETSIGTYPE
277sigio_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
293void
294set_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
304void
305block_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
326void
327block_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
352void
353unblock_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
375void
376unblock_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
402void
403wait_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
431void
432block_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
441void
442block_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
457void
458set_signal(void)
459{
460	(void) signal_no_reset(SIGIO, sigio_handler);
461}
462
463void
464unblock_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
474void
475unblock_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
490void
491wait_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
504int  NotAnEmptyCompilationUnit;
505#endif
506