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)
48 static RETSIGTYPE sigio_handler (int);
49
50 /* consistency safegurad to catch BLOCK/UNBLOCK oversights */
51 static int sigio_block_count = 0;
52
53 /* main inputhandler to be called on SIGIO */
54 static 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 */
67 static int sigio_handler_active = 0;
68 # endif
69
70 /*
71 * SIGPOLL and SIGIO ROUTINES.
72 */
73
74
75
76 /*
77 * TTY initialization routines.
78 */
79 int
init_clock_sig(struct refclockio * rio)80 init_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
203 void
init_socket_sig(int fd)204 init_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
286 static RETSIGTYPE
sigio_handler(int sig)287 sigio_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
318 void
set_signal(input_handler_t * input)319 set_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
334 void
block_io_and_alarm(void)335 block_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
356 void
block_sigio(void)357 block_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
385 void
unblock_io_and_alarm(void)386 unblock_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
408 void
unblock_sigio(void)409 unblock_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
438 void
wait_for_signal(void)439 wait_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
467 void
block_io_and_alarm(void)468 block_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
477 void
block_sigio(void)478 block_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
493 void
set_signal(input_handler_t * input)494 set_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
504 void
unblock_io_and_alarm(void)505 unblock_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
515 void
unblock_sigio(void)516 unblock_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
531 void
wait_for_signal(void)532 wait_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
545 int NotAnEmptyCompilationUnit;
546 #endif
547