summaryrefslogtreecommitdiffstats
path: root/usr.sbin/ntpd
diff options
context:
space:
mode:
authorotto <otto@openbsd.org>2019-06-09 08:40:54 +0000
committerotto <otto@openbsd.org>2019-06-09 08:40:54 +0000
commit841516aa3fae8096a68917fda7bbc03d0b74bf05 (patch)
tree693caac8f649d34e8fcf612edd9a073560f06f85 /usr.sbin/ntpd
parenttook me a few to figure out how to reproduce THIS one specifically (diff)
downloadwireguard-openbsd-841516aa3fae8096a68917fda7bbc03d0b74bf05.tar.xz
wireguard-openbsd-841516aa3fae8096a68917fda7bbc03d0b74bf05.zip
Introducing autmatic settime mode: if some preconditions are met
(booting, constraint(s) defined) set the time but only if the clock should be moved forward by more than a minute, based on ntp replies that satisfied the constraints. Tested by many; ok deraadt@
Diffstat (limited to 'usr.sbin/ntpd')
-rw-r--r--usr.sbin/ntpd/client.c58
-rw-r--r--usr.sbin/ntpd/constraint.c9
-rw-r--r--usr.sbin/ntpd/ntp.c4
-rw-r--r--usr.sbin/ntpd/ntpd.c25
-rw-r--r--usr.sbin/ntpd/ntpd.h10
5 files changed, 92 insertions, 14 deletions
diff --git a/usr.sbin/ntpd/client.c b/usr.sbin/ntpd/client.c
index 476a804fcee..990d34b0b70 100644
--- a/usr.sbin/ntpd/client.c
+++ b/usr.sbin/ntpd/client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: client.c,v 1.106 2019/05/29 18:48:33 otto Exp $ */
+/* $OpenBSD: client.c,v 1.107 2019/06/09 08:40:54 otto Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -29,6 +29,8 @@
#include "ntpd.h"
int client_update(struct ntp_peer *);
+int auto_cmp(const void *, const void *);
+void handle_auto(double);
void set_deadline(struct ntp_peer *, time_t);
void
@@ -213,7 +215,47 @@ client_query(struct ntp_peer *p)
}
int
-client_dispatch(struct ntp_peer *p, u_int8_t settime)
+auto_cmp(const void *a, const void *b)
+{
+ double at = *(const double *)a;
+ double bt = *(const double *)b;
+ return at < bt ? -1 : (at > bt ? 1 : 0);
+}
+
+void
+handle_auto(double offset)
+{
+ static int count;
+ static double v[AUTO_REPLIES];
+
+ /*
+ * It happens the (constraint) resolves initially fail, don't give up
+ * but see if we get validatd replies later.
+ */
+ if (conf->constraint_median == 0)
+ return;
+
+ if (offset < AUTO_THRESHOLD) {
+ /* don't bother */
+ priv_settime(0);
+ return;
+ }
+ /* collect some more */
+ v[count++] = offset;
+ if (count < AUTO_REPLIES)
+ return;
+
+ /* we have enough */
+ qsort(v, count, sizeof(double), auto_cmp);
+ if (AUTO_REPLIES % 2 == 0)
+ offset = (v[AUTO_REPLIES / 2 - 1] + v[AUTO_REPLIES / 2]) / 2;
+ else
+ offset = v[AUTO_REPLIES / 2];
+ priv_settime(offset);
+}
+
+int
+client_dispatch(struct ntp_peer *p, u_int8_t settime, u_int8_t automatic)
{
struct ntp_msg msg;
struct msghdr somsg;
@@ -385,7 +427,9 @@ client_dispatch(struct ntp_peer *p, u_int8_t settime)
if (p->trustlevel < TRUSTLEVEL_PATHETIC)
interval = scale_interval(INTERVAL_QUERY_PATHETIC);
else if (p->trustlevel < TRUSTLEVEL_AGGRESSIVE)
- interval = scale_interval(INTERVAL_QUERY_AGGRESSIVE);
+ interval = (conf->settime && conf->automatic) ?
+ INTERVAL_QUERY_ULTRA_VIOLENCE :
+ scale_interval(INTERVAL_QUERY_AGGRESSIVE);
else
interval = scale_interval(INTERVAL_QUERY_NORMAL);
@@ -408,8 +452,12 @@ client_dispatch(struct ntp_peer *p, u_int8_t settime)
(long long)interval);
client_update(p);
- if (settime)
- priv_settime(p->reply[p->shift].offset);
+ if (settime) {
+ if (automatic)
+ handle_auto(p->reply[p->shift].offset);
+ else
+ priv_settime(p->reply[p->shift].offset);
+ }
if (++p->shift >= OFFSET_ARRAY_SIZE)
p->shift = 0;
diff --git a/usr.sbin/ntpd/constraint.c b/usr.sbin/ntpd/constraint.c
index 13c05f92bd7..804d79a693f 100644
--- a/usr.sbin/ntpd/constraint.c
+++ b/usr.sbin/ntpd/constraint.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: constraint.c,v 1.44 2019/05/30 13:42:19 otto Exp $ */
+/* $OpenBSD: constraint.c,v 1.45 2019/06/09 08:40:54 otto Exp $ */
/*
* Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
@@ -157,8 +157,11 @@ constraint_query(struct constraint *cstr)
/* Proceed and query the time */
break;
case STATE_DNS_TEMPFAIL:
- /* Retry resolving the address */
- constraint_init(cstr);
+ if (now > cstr->last + CONSTRAINT_RETRY_INTERVAL) {
+ /* Retry resolving the address */
+ constraint_init(cstr);
+ return 0;
+ }
return (-1);
case STATE_QUERY_SENT:
if (cstr->last + CONSTRAINT_SCAN_TIMEOUT > now) {
diff --git a/usr.sbin/ntpd/ntp.c b/usr.sbin/ntpd/ntp.c
index 25670f84731..e1052fabeab 100644
--- a/usr.sbin/ntpd/ntp.c
+++ b/usr.sbin/ntpd/ntp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ntp.c,v 1.152 2019/05/30 13:42:19 otto Exp $ */
+/* $OpenBSD: ntp.c,v 1.153 2019/06/09 08:40:54 otto Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -394,7 +394,7 @@ ntp_main(struct ntpd_conf *nconf, struct passwd *pw, int argc, char **argv)
if (pfd[j].revents & (POLLIN|POLLERR)) {
nfds--;
if (client_dispatch(idx2peer[j - idx_peers],
- conf->settime) == -1) {
+ conf->settime, conf->automatic) == -1) {
log_warn("pipe write error (settime)");
ntp_quit = 1;
}
diff --git a/usr.sbin/ntpd/ntpd.c b/usr.sbin/ntpd/ntpd.c
index 44c4f72f3fb..84117207f1e 100644
--- a/usr.sbin/ntpd/ntpd.c
+++ b/usr.sbin/ntpd/ntpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ntpd.c,v 1.120 2019/01/14 16:30:21 florian Exp $ */
+/* $OpenBSD: ntpd.c,v 1.121 2019/06/09 08:40:54 otto Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -20,6 +20,7 @@
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/socket.h>
+#include <sys/sysctl.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <netinet/in.h>
@@ -41,6 +42,7 @@
void sighdlr(int);
__dead void usage(void);
+int auto_preconditions(const struct ntpd_conf *);
int main(int, char *[]);
void check_child(void);
int dispatch_imsg(struct ntpd_conf *, int, char **);
@@ -102,6 +104,19 @@ usage(void)
exit(1);
}
+int
+auto_preconditions(const struct ntpd_conf *cnf)
+{
+ int mib[2] = { CTL_KERN, KERN_SECURELVL };
+ int constraints, securelevel;
+ size_t sz = sizeof(int);
+
+ if (sysctl(mib, 2, &securelevel, &sz, NULL, 0) < 0)
+ err(1, "sysctl");
+ constraints = !TAILQ_EMPTY(&cnf->constraints);
+ return !cnf->settime && constraints && securelevel == 0;
+}
+
#define POLL_MAX 8
#define PFD_PIPE 0
#define PFD_MAX 1
@@ -185,6 +200,10 @@ main(int argc, char *argv[])
if ((pw = getpwnam(NTPD_USER)) == NULL)
errx(1, "unknown user %s", NTPD_USER);
+ lconf.automatic = auto_preconditions(&lconf);
+ if (lconf.automatic)
+ lconf.settime = 1;
+
if (pname != NULL) {
/* Remove our proc arguments, so child doesn't need to. */
if (sanitize_argv(&argc0, &argv0) == -1)
@@ -209,7 +228,6 @@ main(int argc, char *argv[])
if (setpriority(PRIO_PROCESS, 0, -20) == -1)
warn("can't set priority");
-
reset_adjtime();
if (!lconf.settime) {
log_init(lconf.debug, LOG_DAEMON);
@@ -495,6 +513,9 @@ ntpd_settime(double d)
char buf[80];
time_t tval;
+ if (d == 0)
+ return;
+
if (gettimeofday(&curtime, NULL) == -1) {
log_warn("gettimeofday");
return;
diff --git a/usr.sbin/ntpd/ntpd.h b/usr.sbin/ntpd/ntpd.h
index 031a647c284..e7b52805e0c 100644
--- a/usr.sbin/ntpd/ntpd.h
+++ b/usr.sbin/ntpd/ntpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ntpd.h,v 1.140 2019/05/29 18:48:33 otto Exp $ */
+/* $OpenBSD: ntpd.h,v 1.141 2019/06/09 08:40:54 otto Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -43,6 +43,7 @@
#define INTERVAL_QUERY_NORMAL 30 /* sync to peers every n secs */
#define INTERVAL_QUERY_PATHETIC 60
#define INTERVAL_QUERY_AGGRESSIVE 5
+#define INTERVAL_QUERY_ULTRA_VIOLENCE 1 /* used at startup for auto */
#define TRUSTLEVEL_BADPEER 6
#define TRUSTLEVEL_PATHETIC 2
@@ -66,6 +67,9 @@
#define MAX_DISPLAY_WIDTH 80 /* max chars in ctl_show report line */
#define FILTER_ADJFREQ 0x01 /* set after doing adjfreq */
+#define AUTO_REPLIES 4 /* # of ntp replies we want for auto */
+#define AUTO_THRESHOLD 60 /* dont bother auto setting < this */
+
#define SENSOR_DATA_MAXAGE (15*60)
#define SENSOR_QUERY_INTERVAL 15
@@ -74,6 +78,7 @@
#define SENSOR_DEFAULT_REFID "HARD"
#define CONSTRAINT_ERROR_MARGIN (4)
+#define CONSTRAINT_RETRY_INTERVAL (15)
#define CONSTRAINT_SCAN_INTERVAL (15*60)
#define CONSTRAINT_SCAN_TIMEOUT (10)
#define CONSTRAINT_MARGIN (2.0*60)
@@ -228,6 +233,7 @@ struct ntpd_conf {
int verbose;
u_int8_t listen_all;
u_int8_t settime;
+ u_int8_t automatic;
u_int8_t noaction;
u_int8_t filters;
time_t constraint_last;
@@ -349,7 +355,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 *, u_int8_t);
+int client_dispatch(struct ntp_peer *, u_int8_t, u_int8_t);
void client_log_error(struct ntp_peer *, const char *, int);
void set_next(struct ntp_peer *, time_t);