xref: /freebsd/contrib/ntp/libntp/iosignal.c (revision daf1cffce2e07931f27c6c6998652e90df6ba87e)
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)
42 static int sigio_block_count = 0;
43 extern	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  */
82 int
83 init_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 
206 void
207 init_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 
289 RETSIGTYPE
290 sigio_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
306 void
307 set_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 
317 void
318 block_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 
339 void
340 block_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 
365 void
366 unblock_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 
388 void
389 unblock_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 
415 void
416 wait_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 
444 void
445 block_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 
454 void
455 block_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 
470 void
471 set_signal(void)
472 {
473 	(void) signal_no_reset(SIGIO, sigio_handler);
474 }
475 
476 void
477 unblock_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 
487 void
488 unblock_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 
503 void
504 wait_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
517 int  NotAnEmptyCompilationUnit;
518 #endif
519