1 /* $NetBSD: iosignal.c,v 1.1.1.1 2009/12/13 16:55:03 kardel 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 int sigio_block_count = 0; 51 # if defined(HAVE_SIGACTION) 52 /* 53 * If sigaction() is used for signal handling and a signal is 54 * pending then the kernel blocks the signal before it calls 55 * the signal handler. 56 * 57 * The variable below is used to take care that the SIGIO signal 58 * is not unintentionally unblocked inside the sigio_handler() 59 * if the handler executes a piece of code that is normally 60 * bracketed by BLOCKIO()/UNBLOCKIO() calls. 61 */ 62 static int sigio_handler_active = 0; 63 # endif 64 extern void input_handler (l_fp *); 65 66 /* 67 * SIGPOLL and SIGIO ROUTINES. 68 */ 69 70 /* 71 * Some systems (MOST) define SIGPOLL == SIGIO, others SIGIO == SIGPOLL, and 72 * a few have separate SIGIO and SIGPOLL signals. This code checks for the 73 * SIGIO == SIGPOLL case at compile time. 74 * Do not define USE_SIGPOLL or USE_SIGIO. 75 * these are interal only to iosignal.c! 76 */ 77 # if defined(USE_SIGPOLL) 78 # undef USE_SIGPOLL 79 # endif 80 # if defined(USE_SIGIO) 81 # undef USE_SIGIO 82 # endif 83 84 # if defined(USE_TTY_SIGPOLL) || defined(USE_UDP_SIGPOLL) 85 # define USE_SIGPOLL 86 # endif 87 88 # if !defined(USE_TTY_SIGPOLL) || !defined(USE_UDP_SIGPOLL) 89 # define USE_SIGIO 90 # endif 91 92 # if defined(USE_SIGIO) && defined(USE_SIGPOLL) 93 # if SIGIO == SIGPOLL 94 # define USE_SIGIO 95 # undef USE_SIGPOLL 96 # endif /* SIGIO == SIGPOLL */ 97 # endif /* USE_SIGIO && USE_SIGIO */ 98 99 100 /* 101 * TTY initialization routines. 102 */ 103 int 104 init_clock_sig( 105 struct refclockio *rio 106 ) 107 { 108 # ifdef USE_TTY_SIGPOLL 109 { 110 /* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */ 111 if (ioctl(rio->fd, I_SETSIG, S_INPUT) < 0) 112 { 113 msyslog(LOG_ERR, 114 "init_clock_sig: ioctl(I_SETSIG, S_INPUT) failed: %m"); 115 return 1; 116 } 117 return 0; 118 } 119 # else 120 /* 121 * Special cases first! 122 */ 123 /* Was: defined(SYS_HPUX) */ 124 # if defined(FIOSSAIOOWN) && defined(FIOSNBIO) && defined(FIOSSAIOSTAT) 125 #define CLOCK_DONE 126 { 127 int pgrp, on = 1; 128 129 /* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */ 130 pgrp = getpid(); 131 if (ioctl(rio->fd, FIOSSAIOOWN, (char *)&pgrp) == -1) 132 { 133 msyslog(LOG_ERR, "ioctl(FIOSSAIOOWN) fails for clock I/O: %m"); 134 exit(1); 135 /*NOTREACHED*/ 136 } 137 138 /* 139 * set non-blocking, async I/O on the descriptor 140 */ 141 if (ioctl(rio->fd, FIOSNBIO, (char *)&on) == -1) 142 { 143 msyslog(LOG_ERR, "ioctl(FIOSNBIO) fails for clock I/O: %m"); 144 exit(1); 145 /*NOTREACHED*/ 146 } 147 148 if (ioctl(rio->fd, FIOSSAIOSTAT, (char *)&on) == -1) 149 { 150 msyslog(LOG_ERR, "ioctl(FIOSSAIOSTAT) fails for clock I/O: %m"); 151 exit(1); 152 /*NOTREACHED*/ 153 } 154 return 0; 155 } 156 # endif /* SYS_HPUX: FIOSSAIOOWN && FIOSNBIO && FIOSSAIOSTAT */ 157 /* Was: defined(SYS_AIX) && !defined(_BSD) */ 158 # if !defined(_BSD) && defined(_AIX) && defined(FIOASYNC) && defined(FIOSETOWN) 159 /* 160 * SYSV compatibility mode under AIX. 161 */ 162 #define CLOCK_DONE 163 { 164 int pgrp, on = 1; 165 166 /* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */ 167 if (ioctl(rio->fd, FIOASYNC, (char *)&on) == -1) 168 { 169 msyslog(LOG_ERR, "ioctl(FIOASYNC) fails for clock I/O: %m"); 170 return 1; 171 } 172 pgrp = -getpid(); 173 if (ioctl(rio->fd, FIOSETOWN, (char*)&pgrp) == -1) 174 { 175 msyslog(LOG_ERR, "ioctl(FIOSETOWN) fails for clock I/O: %m"); 176 return 1; 177 } 178 179 if (fcntl(rio->fd, F_SETFL, FNDELAY|FASYNC) < 0) 180 { 181 msyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails for clock I/O: %m"); 182 return 1; 183 } 184 return 0; 185 } 186 # endif /* AIX && !BSD: !_BSD && FIOASYNC && FIOSETOWN */ 187 # ifndef CLOCK_DONE 188 { 189 /* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */ 190 # if defined(TIOCSCTTY) && defined(USE_FSETOWNCTTY) 191 /* 192 * there are, however, always exceptions to the rules 193 * one is, that OSF accepts SETOWN on TTY fd's only, iff they are 194 * CTTYs. SunOS and HPUX do not semm to have this restriction. 195 * another question is: how can you do multiple SIGIO from several 196 * ttys (as they all should be CTTYs), wondering... 197 * 198 * kd 95-07-16 199 */ 200 if (ioctl(rio->fd, TIOCSCTTY, 0) == -1) 201 { 202 msyslog(LOG_ERR, "ioctl(TIOCSCTTY, 0) fails for clock I/O: %m"); 203 return 1; 204 } 205 # endif /* TIOCSCTTY && USE_FSETOWNCTTY */ 206 207 if (fcntl(rio->fd, F_SETOWN, getpid()) == -1) 208 { 209 msyslog(LOG_ERR, "fcntl(F_SETOWN) fails for clock I/O: %m"); 210 return 1; 211 } 212 213 if (fcntl(rio->fd, F_SETFL, FNDELAY|FASYNC) < 0) 214 { 215 msyslog(LOG_ERR, 216 "fcntl(FNDELAY|FASYNC) fails for clock I/O: %m"); 217 return 1; 218 } 219 return 0; 220 } 221 # endif /* CLOCK_DONE */ 222 # endif /* !USE_TTY_SIGPOLL */ 223 } 224 225 226 227 void 228 init_socket_sig( 229 int fd 230 ) 231 { 232 # ifdef USE_UDP_SIGPOLL 233 { 234 if (ioctl(fd, I_SETSIG, S_INPUT) < 0) 235 { 236 msyslog(LOG_ERR, 237 "init_socket_sig: ioctl(I_SETSIG, S_INPUT) failed: %m"); 238 exit(1); 239 } 240 } 241 # else /* USE_UDP_SIGPOLL */ 242 { 243 int pgrp; 244 # ifdef FIOASYNC 245 int on = 1; 246 # endif 247 248 # if defined(FIOASYNC) 249 if (ioctl(fd, FIOASYNC, (char *)&on) == -1) 250 { 251 msyslog(LOG_ERR, "ioctl(FIOASYNC) fails: %m"); 252 exit(1); 253 /*NOTREACHED*/ 254 } 255 # elif defined(FASYNC) 256 { 257 int flags; 258 259 if ((flags = fcntl(fd, F_GETFL, 0)) == -1) 260 { 261 msyslog(LOG_ERR, "fcntl(F_GETFL) fails: %m"); 262 exit(1); 263 /*NOTREACHED*/ 264 } 265 if (fcntl(fd, F_SETFL, flags|FASYNC) < 0) 266 { 267 msyslog(LOG_ERR, "fcntl(...|FASYNC) fails: %m"); 268 exit(1); 269 /*NOTREACHED*/ 270 } 271 } 272 # else 273 # include "Bletch: Need asynchronous I/O!" 274 # endif 275 276 # ifdef UDP_BACKWARDS_SETOWN 277 pgrp = -getpid(); 278 # else 279 pgrp = getpid(); 280 # endif 281 282 # if defined(SIOCSPGRP) 283 if (ioctl(fd, SIOCSPGRP, (char *)&pgrp) == -1) 284 { 285 msyslog(LOG_ERR, "ioctl(SIOCSPGRP) fails: %m"); 286 exit(1); 287 /*NOTREACHED*/ 288 } 289 # elif defined(FIOSETOWN) 290 if (ioctl(fd, FIOSETOWN, (char*)&pgrp) == -1) 291 { 292 msyslog(LOG_ERR, "ioctl(FIOSETOWN) fails: %m"); 293 exit(1); 294 /*NOTREACHED*/ 295 } 296 # elif defined(F_SETOWN) 297 if (fcntl(fd, F_SETOWN, pgrp) == -1) 298 { 299 msyslog(LOG_ERR, "fcntl(F_SETOWN) fails: %m"); 300 exit(1); 301 /*NOTREACHED*/ 302 } 303 # else 304 # include "Bletch: Need to set process(group) to receive SIG(IO|POLL)" 305 # endif 306 } 307 # endif /* USE_UDP_SIGPOLL */ 308 } 309 310 RETSIGTYPE 311 sigio_handler( 312 int sig 313 ) 314 { 315 int saved_errno = errno; 316 l_fp ts; 317 318 get_systime(&ts); 319 320 # if defined(HAVE_SIGACTION) 321 sigio_handler_active++; 322 if (sigio_handler_active != 1) /* This should never happen! */ 323 msyslog(LOG_ERR, "sigio_handler: sigio_handler_active != 1"); 324 # endif 325 326 (void)input_handler(&ts); 327 328 # if defined(HAVE_SIGACTION) 329 sigio_handler_active--; 330 if (sigio_handler_active != 0) /* This should never happen! */ 331 msyslog(LOG_ERR, "sigio_handler: sigio_handler_active != 0"); 332 # endif 333 334 errno = saved_errno; 335 } 336 337 /* 338 * Signal support routines. 339 */ 340 # ifdef HAVE_SIGACTION 341 void 342 set_signal(void) 343 { 344 # ifdef USE_SIGIO 345 (void) signal_no_reset(SIGIO, sigio_handler); 346 # endif 347 # ifdef USE_SIGPOLL 348 (void) signal_no_reset(SIGPOLL, sigio_handler); 349 # endif 350 } 351 352 void 353 block_io_and_alarm(void) 354 { 355 sigset_t set; 356 357 if (sigemptyset(&set)) 358 msyslog(LOG_ERR, "block_io_and_alarm: sigemptyset() failed: %m"); 359 # if defined(USE_SIGIO) 360 if (sigaddset(&set, SIGIO)) 361 msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGIO) failed: %m"); 362 # endif 363 # if defined(USE_SIGPOLL) 364 if (sigaddset(&set, SIGPOLL)) 365 msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGPOLL) failed: %m"); 366 # endif 367 if (sigaddset(&set, SIGALRM)) 368 msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGALRM) failed: %m"); 369 370 if (sigprocmask(SIG_BLOCK, &set, NULL)) 371 msyslog(LOG_ERR, "block_io_and_alarm: sigprocmask() failed: %m"); 372 } 373 374 void 375 block_sigio(void) 376 { 377 if ( sigio_handler_active == 0 ) /* not called from within signal handler */ 378 { 379 sigset_t set; 380 381 ++sigio_block_count; 382 if (sigio_block_count > 1) 383 msyslog(LOG_INFO, "block_sigio: sigio_block_count > 1"); 384 if (sigio_block_count < 1) 385 msyslog(LOG_INFO, "block_sigio: sigio_block_count < 1"); 386 387 if (sigemptyset(&set)) 388 msyslog(LOG_ERR, "block_sigio: sigemptyset() failed: %m"); 389 # if defined(USE_SIGIO) 390 if (sigaddset(&set, SIGIO)) 391 msyslog(LOG_ERR, "block_sigio: sigaddset(SIGIO) failed: %m"); 392 # endif 393 # if defined(USE_SIGPOLL) 394 if (sigaddset(&set, SIGPOLL)) 395 msyslog(LOG_ERR, "block_sigio: sigaddset(SIGPOLL) failed: %m"); 396 # endif 397 398 if (sigprocmask(SIG_BLOCK, &set, NULL)) 399 msyslog(LOG_ERR, "block_sigio: sigprocmask() failed: %m"); 400 } 401 } 402 403 void 404 unblock_io_and_alarm(void) 405 { 406 sigset_t unset; 407 408 if (sigemptyset(&unset)) 409 msyslog(LOG_ERR, "unblock_io_and_alarm: sigemptyset() failed: %m"); 410 411 # if defined(USE_SIGIO) 412 if (sigaddset(&unset, SIGIO)) 413 msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGIO) failed: %m"); 414 # endif 415 # if defined(USE_SIGPOLL) 416 if (sigaddset(&unset, SIGPOLL)) 417 msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGPOLL) failed: %m"); 418 # endif 419 if (sigaddset(&unset, SIGALRM)) 420 msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGALRM) failed: %m"); 421 422 if (sigprocmask(SIG_UNBLOCK, &unset, NULL)) 423 msyslog(LOG_ERR, "unblock_io_and_alarm: sigprocmask() failed: %m"); 424 } 425 426 void 427 unblock_sigio(void) 428 { 429 if ( sigio_handler_active == 0 ) /* not called from within signal handler */ 430 { 431 sigset_t unset; 432 433 --sigio_block_count; 434 if (sigio_block_count > 0) 435 msyslog(LOG_INFO, "unblock_sigio: sigio_block_count > 0"); 436 if (sigio_block_count < 0) 437 msyslog(LOG_INFO, "unblock_sigio: sigio_block_count < 0"); 438 439 if (sigemptyset(&unset)) 440 msyslog(LOG_ERR, "unblock_sigio: sigemptyset() failed: %m"); 441 442 # if defined(USE_SIGIO) 443 if (sigaddset(&unset, SIGIO)) 444 msyslog(LOG_ERR, "unblock_sigio: sigaddset(SIGIO) failed: %m"); 445 # endif 446 # if defined(USE_SIGPOLL) 447 if (sigaddset(&unset, SIGPOLL)) 448 msyslog(LOG_ERR, "unblock_sigio: sigaddset(SIGPOLL) failed: %m"); 449 # endif 450 451 if (sigprocmask(SIG_UNBLOCK, &unset, NULL)) 452 msyslog(LOG_ERR, "unblock_sigio: sigprocmask() failed: %m"); 453 } 454 } 455 456 void 457 wait_for_signal(void) 458 { 459 sigset_t old; 460 461 if (sigprocmask(SIG_UNBLOCK, NULL, &old)) 462 msyslog(LOG_ERR, "wait_for_signal: sigprocmask() failed: %m"); 463 464 # if defined(USE_SIGIO) 465 if (sigdelset(&old, SIGIO)) 466 msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGIO) failed: %m"); 467 # endif 468 # if defined(USE_SIGPOLL) 469 if (sigdelset(&old, SIGPOLL)) 470 msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGPOLL) failed: %m"); 471 # endif 472 if (sigdelset(&old, SIGALRM)) 473 msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGALRM) failed: %m"); 474 475 if (sigsuspend(&old) && (errno != EINTR)) 476 msyslog(LOG_ERR, "wait_for_signal: sigsuspend() failed: %m"); 477 } 478 479 # else /* !HAVE_SIGACTION */ 480 /* 481 * Must be an old bsd system. 482 * We assume there is no SIGPOLL. 483 */ 484 485 void 486 block_io_and_alarm(void) 487 { 488 int mask; 489 490 mask = sigmask(SIGIO) | sigmask(SIGALRM); 491 if (sigblock(mask)) 492 msyslog(LOG_ERR, "block_io_and_alarm: sigblock() failed: %m"); 493 } 494 495 void 496 block_sigio(void) 497 { 498 int mask; 499 500 ++sigio_block_count; 501 if (sigio_block_count > 1) 502 msyslog(LOG_INFO, "block_sigio: sigio_block_count > 1"); 503 if (sigio_block_count < 1) 504 msyslog(LOG_INFO, "block_sigio: sigio_block_count < 1"); 505 506 mask = sigmask(SIGIO); 507 if (sigblock(mask)) 508 msyslog(LOG_ERR, "block_sigio: sigblock() failed: %m"); 509 } 510 511 void 512 set_signal(void) 513 { 514 (void) signal_no_reset(SIGIO, sigio_handler); 515 } 516 517 void 518 unblock_io_and_alarm(void) 519 { 520 int mask, omask; 521 522 mask = sigmask(SIGIO) | sigmask(SIGALRM); 523 omask = sigblock(0); 524 omask &= ~mask; 525 (void) sigsetmask(omask); 526 } 527 528 void 529 unblock_sigio(void) 530 { 531 int mask, omask; 532 533 --sigio_block_count; 534 if (sigio_block_count > 0) 535 msyslog(LOG_INFO, "unblock_sigio: sigio_block_count > 0"); 536 if (sigio_block_count < 0) 537 msyslog(LOG_INFO, "unblock_sigio: sigio_block_count < 0"); 538 mask = sigmask(SIGIO); 539 omask = sigblock(0); 540 omask &= ~mask; 541 (void) sigsetmask(omask); 542 } 543 544 void 545 wait_for_signal(void) 546 { 547 int mask, omask; 548 549 mask = sigmask(SIGIO) | sigmask(SIGALRM); 550 omask = sigblock(0); 551 omask &= ~mask; 552 if (sigpause(omask) && (errno != EINTR)) 553 msyslog(LOG_ERR, "wait_for_signal: sigspause() failed: %m"); 554 } 555 556 # endif /* HAVE_SIGACTION */ 557 #else 558 int NotAnEmptyCompilationUnit; 559 #endif 560