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) 50static 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 */ 62static int sigio_handler_active = 0; 63# endif 64extern 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 */ 103int 104init_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 227void 228init_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 310RETSIGTYPE 311sigio_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 341void 342set_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 352void 353block_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 374void 375block_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 403void 404unblock_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 426void 427unblock_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 456void 457wait_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 485void 486block_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 495void 496block_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 511void 512set_signal(void) 513{ 514 (void) signal_no_reset(SIGIO, sigio_handler); 515} 516 517void 518unblock_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 528void 529unblock_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 544void 545wait_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 558int NotAnEmptyCompilationUnit; 559#endif 560