From 80548b02924e3b81ece0360f016b94600641ad7b Mon Sep 17 00:00:00 2001 From: henning <> Date: Sat, 18 Sep 2004 20:01:38 +0000 Subject: [PATCH] add a new -s option, that tells ntpd to set the time using settimeofday() once at startup. ntpd delays daemonizing until it has done the intial time setting (or ran into the timeout) in this mode to make sure stuff started later in rc is not subject to time jumps. this eleminates the need to run rdate -n beforehands. with some input from & ok ryan and bob, march music from mickey --- src/usr.sbin/ntpd/client.c | 6 ++- src/usr.sbin/ntpd/ntp.c | 27 +++++++++++-- src/usr.sbin/ntpd/ntpd.8 | 12 +++++- src/usr.sbin/ntpd/ntpd.c | 80 +++++++++++++++++++++++++++++++------- src/usr.sbin/ntpd/ntpd.h | 9 +++-- 5 files changed, 109 insertions(+), 25 deletions(-) diff --git a/src/usr.sbin/ntpd/client.c b/src/usr.sbin/ntpd/client.c index 10a95fed..816f72f9 100644 --- a/src/usr.sbin/ntpd/client.c +++ b/src/usr.sbin/ntpd/client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: client.c,v 1.33 2004/09/14 22:01:28 henning Exp $ */ +/* $OpenBSD: client.c,v 1.34 2004/09/18 20:01:38 henning Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -154,7 +154,7 @@ client_query(struct ntp_peer *p) } int -client_dispatch(struct ntp_peer *p) +client_dispatch(struct ntp_peer *p, u_int8_t settime) { struct sockaddr_storage fsa; socklen_t fsa_len; @@ -251,6 +251,8 @@ client_dispatch(struct ntp_peer *p) } client_update(p); + if (settime) + ntp_settime(p->reply[p->shift].offset); log_debug("reply from %s: offset %f delay %f, " "next query %ds", log_sockaddr((struct sockaddr *)&fsa), diff --git a/src/usr.sbin/ntpd/ntp.c b/src/usr.sbin/ntpd/ntp.c index 568178b2..1f955e2b 100644 --- a/src/usr.sbin/ntpd/ntp.c +++ b/src/usr.sbin/ntpd/ntp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ntp.c,v 1.32 2004/09/18 07:33:14 henning Exp $ */ +/* $OpenBSD: ntp.c,v 1.33 2004/09/18 20:01:38 henning Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -19,6 +19,8 @@ #include #include +#include +#include #include #include #include @@ -56,7 +58,7 @@ ntp_sighdlr(int sig) pid_t ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf) { - int nfds, i, j, idx_peers, timeout; + int nfds, i, j, idx_peers, timeout, nullfd; u_int pfd_elms = 0, idx2peer_elms = 0; u_int listener_cnt, new_cnt; pid_t pid; @@ -84,11 +86,21 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf) if ((pw = getpwnam(NTPD_USER)) == NULL) fatal(NULL); + if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1) + fatal(NULL); + if (chroot(pw->pw_dir) == -1) fatal("chroot"); if (chdir("/") == -1) fatal("chdir(\"/\")"); + if (!nconf->debug) { + dup2(nullfd, STDIN_FILENO); + dup2(nullfd, STDOUT_FILENO); + dup2(nullfd, STDERR_FILENO); + } + close(nullfd); + setproctitle("ntp engine"); conf = nconf; @@ -228,8 +240,8 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf) for (; nfds > 0 && j < i; j++) if (pfd[j].revents & POLLIN) { nfds--; - if (client_dispatch(idx2peer[j - idx_peers]) == - -1) + if (client_dispatch(idx2peer[j - idx_peers], + conf->settime) == -1) ntp_quit = 1; } } @@ -361,6 +373,13 @@ ntp_adjtime(void) p->update.good = 0; } +void +ntp_settime(double offset) +{ + imsg_compose(ibuf_main, IMSG_SETTIME, 0, 0, &offset, sizeof(offset)); + conf->settime = 0; +} + void ntp_host_dns(char *name, u_int32_t peerid) { diff --git a/src/usr.sbin/ntpd/ntpd.8 b/src/usr.sbin/ntpd/ntpd.8 index 4717842e..4a93b4d9 100644 --- a/src/usr.sbin/ntpd/ntpd.8 +++ b/src/usr.sbin/ntpd/ntpd.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ntpd.8,v 1.5 2004/07/13 19:51:38 jmc Exp $ +.\" $OpenBSD: ntpd.8,v 1.6 2004/09/18 20:01:38 henning Exp $ .\" .\" Copyright (c) 2003, 2004 Henning Brauer .\" @@ -23,7 +23,7 @@ .Sh SYNOPSIS .Nm ntpd .Bk -words -.Op Fl d +.Op Fl ds .Op Fl f Ar file .Ek .Sh DESCRIPTION @@ -38,6 +38,10 @@ and the Network Time Protocol version 3, as described in RFC 1305. .Pp .Nm +uses the +.Xr adjtime 2 , +system call to correct the local system time without causing time jumps. +.Nm is usually started at boot time, and can be enabled by setting the following in .Pa /etc/rc.conf.local : @@ -71,6 +75,10 @@ Use as the configuration file, instead of the default .Pa /etc/ntpd.conf . +.It Fl s +Set the time immediately once at startup to allow for a large time correction, +eleminating the need to run rdate before starting +.Nm . .El .Sh FILES .Bl -tag -width "/etc/ntpd.confXXX" -compact diff --git a/src/usr.sbin/ntpd/ntpd.c b/src/usr.sbin/ntpd/ntpd.c index c69c19c5..f4955903 100644 --- a/src/usr.sbin/ntpd/ntpd.c +++ b/src/usr.sbin/ntpd/ntpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ntpd.c,v 1.17 2004/09/15 19:21:25 henning Exp $ */ +/* $OpenBSD: ntpd.c,v 1.18 2004/09/18 20:01:38 henning Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -37,8 +37,9 @@ void sighdlr(int); void usage(void); int main(int, char *[]); int check_child(pid_t, const char *); -int dispatch_imsg(void); +int dispatch_imsg(struct ntpd_conf *); void ntpd_adjtime(double); +void ntpd_settime(double); volatile sig_atomic_t quit = 0; volatile sig_atomic_t reconfig = 0; @@ -67,7 +68,7 @@ usage(void) { extern char *__progname; - fprintf(stderr, "usage: %s [-d] [-f file]\n", __progname); + fprintf(stderr, "usage: %s [-d] [-f file] [-s]\n", __progname); exit(1); } @@ -81,8 +82,7 @@ main(int argc, char *argv[]) struct pollfd pfd[POLL_MAX]; pid_t chld_pid = 0, pid; char *conffile; - int debug = 0; - int ch, nfds; + int ch, nfds, timeout = INFTIM; int pipe_chld[2]; conffile = CONFFILE; @@ -91,14 +91,17 @@ main(int argc, char *argv[]) log_init(1); /* log to stderr until daemonized */ - while ((ch = getopt(argc, argv, "df:")) != -1) { + while ((ch = getopt(argc, argv, "df:s")) != -1) { switch (ch) { case 'd': - debug = 1; + conf.debug = 1; break; case 'f': conffile = optarg; break; + case 's': + conf.settime = 1; + break; default: usage(); /* NOTREACHED */ @@ -119,10 +122,12 @@ main(int argc, char *argv[]) } endpwent(); - log_init(debug); - - if (!debug) - daemon(1, 0); + if (!conf.settime) { + log_init(conf.debug); + if (!conf.debug) + daemon(1, 0); + } else + timeout = 15 * 1000; if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_chld) == -1) fatal("socketpair"); @@ -149,12 +154,22 @@ main(int argc, char *argv[]) if (ibuf->w.queued) pfd[PFD_PIPE].events |= POLLOUT; - if ((nfds = poll(pfd, 1, INFTIM)) == -1) + if ((nfds = poll(pfd, 1, timeout)) == -1) if (errno != EINTR) { log_warn("poll error"); quit = 1; } + if (nfds == 0 && conf.settime) { + log_debug("no reply received, skipping initial time" + "setting"); + conf.settime = 0; + timeout = INFTIM; + log_init(conf.debug); + if (!conf.debug) + daemon(1, 0); + } + if (nfds > 0 && (pfd[PFD_PIPE].revents & POLLOUT)) if (msgbuf_write(&ibuf->w) < 0) { log_warn("pipe write error (to child"); @@ -163,7 +178,7 @@ main(int argc, char *argv[]) if (nfds > 0 && pfd[PFD_PIPE].revents & POLLIN) { nfds--; - if (dispatch_imsg() == -1) + if (dispatch_imsg(&conf) == -1) quit = 1; } @@ -213,7 +228,7 @@ check_child(pid_t pid, const char *pname) } int -dispatch_imsg(void) +dispatch_imsg(struct ntpd_conf *conf) { struct imsg imsg; int n, cnt; @@ -244,6 +259,19 @@ dispatch_imsg(void) memcpy(&d, imsg.data, sizeof(d)); ntpd_adjtime(d); break; + case IMSG_SETTIME: + if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(d)) + fatal("invalid IMSG_SETTIME received"); + if (!conf->settime) + break; + memcpy(&d, imsg.data, sizeof(d)); + ntpd_settime(d); + /* daemonize now */ + log_init(conf->debug); + if (!conf->debug) + daemon(1, 0); + conf->settime = 0; + break; case IMSG_HOST_DNS: name = imsg.data; if (imsg.hdr.len != strlen(name) + 1 + IMSG_HEADER_SIZE) @@ -278,3 +306,27 @@ ntpd_adjtime(double d) if (adjtime(&tv, NULL) == -1) log_warn("adjtime failed"); } + +void +ntpd_settime(double d) +{ + struct timeval tv, curtime; + char buf[80]; + time_t tval; + + d_to_tv(d, &tv); + if (gettimeofday(&curtime, NULL) == -1) + log_warn("gettimeofday"); + curtime.tv_sec += tv.tv_sec; + curtime.tv_usec += tv.tv_usec; + if (curtime.tv_usec > 1000000) { + curtime.tv_sec++; + curtime.tv_usec -= 1000000; + } + if (settimeofday(&curtime, NULL) == -1) + log_warn("settimeofday"); + tval = curtime.tv_sec; + strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y", + localtime(&tval)); + log_info("set local clock to %s (offset %fs)", buf, d); +} diff --git a/src/usr.sbin/ntpd/ntpd.h b/src/usr.sbin/ntpd/ntpd.h index d571ba9f..19705d8a 100644 --- a/src/usr.sbin/ntpd/ntpd.h +++ b/src/usr.sbin/ntpd/ntpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ntpd.h,v 1.37 2004/09/18 07:33:14 henning Exp $ */ +/* $OpenBSD: ntpd.h,v 1.38 2004/09/18 20:01:38 henning Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -109,8 +109,9 @@ struct ntp_peer { struct ntpd_conf { TAILQ_HEAD(listen_addrs, listen_addr) listen_addrs; TAILQ_HEAD(ntp_peers, ntp_peer) ntp_peers; - u_int8_t opts; u_int8_t listen_all; + u_int8_t settime; + u_int8_t debug; struct ntp_status status; }; @@ -149,6 +150,7 @@ struct imsgbuf { enum imsg_type { IMSG_NONE, IMSG_ADJTIME, + IMSG_SETTIME, IMSG_HOST_DNS }; @@ -200,6 +202,7 @@ void imsg_free(struct imsg *); /* ntp.c */ pid_t ntp_main(int[2], struct ntpd_conf *); void ntp_adjtime(void); +void ntp_settime(double); void ntp_host_dns(char *, u_int32_t); /* parse.y */ @@ -224,7 +227,7 @@ int client_peer_init(struct ntp_peer *); int client_addr_init(struct ntp_peer *); int client_nextaddr(struct ntp_peer *); int client_query(struct ntp_peer *); -int client_dispatch(struct ntp_peer *); +int client_dispatch(struct ntp_peer *, u_int8_t); /* util.c */ double gettime(void);