Home | History | Annotate | Line # | Download | only in libntp
      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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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