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 547