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