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