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