]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ntp/libntp/iosignal.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / ntp / libntp / iosignal.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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