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