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