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