1 /* $NetBSD: iosignal.c,v 1.4 2016/01/08 21:35:38 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