Browse Source

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@
OPENBSD_6_6
otto 5 years ago
parent
commit
0225e4f1d7
5 changed files with 92 additions and 14 deletions
  1. +53
    -5
      src/usr.sbin/ntpd/client.c
  2. +6
    -3
      src/usr.sbin/ntpd/constraint.c
  3. +2
    -2
      src/usr.sbin/ntpd/ntp.c
  4. +23
    -2
      src/usr.sbin/ntpd/ntpd.c
  5. +8
    -2
      src/usr.sbin/ntpd/ntpd.h

+ 53
- 5
src/usr.sbin/ntpd/client.c View File

@ -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;


+ 6
- 3
src/usr.sbin/ntpd/constraint.c View File

@ -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) {


+ 2
- 2
src/usr.sbin/ntpd/ntp.c View File

@ -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;
}


+ 23
- 2
src/usr.sbin/ntpd/ntpd.c View File

@ -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;


+ 8
- 2
src/usr.sbin/ntpd/ntpd.h View File

@ -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);


Loading…
Cancel
Save