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