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