From 21382f5e23a32114e8d20243676351db288766db Mon Sep 17 00:00:00 2001 From: henning <> Date: Fri, 26 May 2006 00:33:16 +0000 Subject: [PATCH] add support for timedelta sensors, which pretty much means udcf(4) right now. untested due to lack of hardware, and it wouldn't have worked in the plane anyways. work in progress, currently picks up and uses all sensors it finds, config file bits to be added soon. theo fine with this going in --- src/usr.sbin/ntpd/Makefile | 4 +- src/usr.sbin/ntpd/ntp.c | 37 +++++++++- src/usr.sbin/ntpd/ntpd.h | 20 ++++- src/usr.sbin/ntpd/sensors.c | 143 ++++++++++++++++++++++++++++++++++++ 4 files changed, 199 insertions(+), 5 deletions(-) create mode 100644 src/usr.sbin/ntpd/sensors.c diff --git a/src/usr.sbin/ntpd/Makefile b/src/usr.sbin/ntpd/Makefile index 86cb8cc8..95265504 100644 --- a/src/usr.sbin/ntpd/Makefile +++ b/src/usr.sbin/ntpd/Makefile @@ -1,10 +1,10 @@ -# $OpenBSD: Makefile,v 1.7 2004/07/04 11:01:49 alexander Exp $ +# $OpenBSD: Makefile,v 1.8 2006/05/26 00:33:16 henning Exp $ .PATH: ${.CURDIR}/.. PROG= ntpd SRCS= ntpd.c buffer.c log.c imsg.c ntp.c ntp_msg.c parse.y config.c \ - server.c client.c util.c + server.c client.c sensors.c util.c CFLAGS+= -Wall -I${.CURDIR} CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes CFLAGS+= -Wmissing-declarations diff --git a/src/usr.sbin/ntpd/ntp.c b/src/usr.sbin/ntpd/ntp.c index 3990cd10..3fdeb0dc 100644 --- a/src/usr.sbin/ntpd/ntp.c +++ b/src/usr.sbin/ntpd/ntp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ntp.c,v 1.70 2006/05/25 19:30:45 henning Exp $ */ +/* $OpenBSD: ntp.c,v 1.71 2006/05/26 00:33:16 henning Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -65,6 +65,7 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf) int a, b, nfds, i, j, idx_peers, timeout, nullfd; u_int pfd_elms = 0, idx2peer_elms = 0; u_int listener_cnt, new_cnt, sent_cnt, trial_cnt; + u_int sensors_cnt = 0; pid_t pid; struct pollfd *pfd = NULL; struct passwd *pw; @@ -72,6 +73,7 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf) struct listen_addr *la; struct ntp_peer *p; struct ntp_peer **idx2peer = NULL; + struct ntp_sensor *s, *next_s; struct timespec tp; struct stat stb; time_t nextaction; @@ -146,6 +148,9 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf) conf->status.precision = a; conf->scale = 1; + sensor_init(conf); + sensor_scan(conf); + log_info("ntp engine ready"); peer_cnt = 0; @@ -227,8 +232,16 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf) } } + sensors_cnt = 0; + TAILQ_FOREACH(s, &conf->ntp_sensors, entry) { + sensors_cnt++; + if (s->next > 0 && s->next < nextaction) + nextaction = s->next; + } + if (conf->settime && - ((trial_cnt > 0 && sent_cnt == 0) || peer_cnt == 0)) + ((trial_cnt > 0 && sent_cnt == 0) || + (peer_cnt == 0 && sensors_cnt == 0))) priv_settime(0); /* no good peers, don't wait */ if (ibuf_main->w.queued > 0) @@ -270,6 +283,13 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf) conf->settime) == -1) ntp_quit = 1; } + + for (s = TAILQ_FIRST(&conf->ntp_sensors); s != NULL; + s = next_s) { + next_s = TAILQ_NEXT(s, entry); + if (sensor_query(s) == -1) + sensor_remove(conf, s); + } } msgbuf_write(&ibuf_main->w); @@ -392,6 +412,7 @@ void priv_adjtime(void) { struct ntp_peer *p; + struct ntp_sensor *s; int offset_cnt = 0, i = 0; struct ntp_offset **offsets; double offset_median; @@ -404,6 +425,12 @@ priv_adjtime(void) offset_cnt++; } + TAILQ_FOREACH(s, &conf->ntp_sensors, entry) { + if (!s->update.good) + continue; + offset_cnt++; + } + if ((offsets = calloc(offset_cnt, sizeof(struct ntp_offset *))) == NULL) fatal("calloc priv_adjtime"); @@ -413,6 +440,12 @@ priv_adjtime(void) offsets[i++] = &p->update; } + TAILQ_FOREACH(s, &conf->ntp_sensors, entry) { + if (!s->update.good) + continue; + offsets[i++] = &s->update; + } + qsort(offsets, offset_cnt, sizeof(struct ntp_offset *), offset_compare); if (offset_cnt > 0) { diff --git a/src/usr.sbin/ntpd/ntpd.h b/src/usr.sbin/ntpd/ntpd.h index 7466a69a..ce0d55ba 100644 --- a/src/usr.sbin/ntpd/ntpd.h +++ b/src/usr.sbin/ntpd/ntpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ntpd.h,v 1.62 2006/05/25 19:25:46 henning Exp $ */ +/* $OpenBSD: ntpd.h,v 1.63 2006/05/26 00:33:16 henning Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -58,6 +58,9 @@ #define SETTIME_TIMEOUT 15 /* max seconds to wait with -s */ #define LOG_NEGLIGEE 128 /* negligible drift to not log (ms) */ +#define SENSOR_DATA_MAXAGE 15*60 +#define SENSOR_QUERY_INTERVAL 30 + enum client_state { STATE_NONE, STATE_DNS_INPROGRESS, @@ -123,9 +126,18 @@ struct ntp_peer { int lasterror; }; +struct ntp_sensor { + TAILQ_ENTRY(ntp_sensor) entry; + struct ntp_offset update; + time_t next; + char *device; + int sensorid; +}; + struct ntpd_conf { TAILQ_HEAD(listen_addrs, listen_addr) listen_addrs; TAILQ_HEAD(ntp_peers, ntp_peer) ntp_peers; + TAILQ_HEAD(ntp_sensors, ntp_sensor) ntp_sensors; struct ntp_status status; u_int8_t listen_all; u_int8_t settime; @@ -259,3 +271,9 @@ double lfp_to_d(struct l_fixedpt); struct l_fixedpt d_to_lfp(double); double sfp_to_d(struct s_fixedpt); struct s_fixedpt d_to_sfp(double); + +/* sensors.c */ +void sensor_init(struct ntpd_conf *); +void sensor_scan(struct ntpd_conf *); +void sensor_remove(struct ntpd_conf *, struct ntp_sensor *); +int sensor_query(struct ntp_sensor *); diff --git a/src/usr.sbin/ntpd/sensors.c b/src/usr.sbin/ntpd/sensors.c new file mode 100644 index 00000000..21395dfc --- /dev/null +++ b/src/usr.sbin/ntpd/sensors.c @@ -0,0 +1,143 @@ +/* $OpenBSD: sensors.c,v 1.1 2006/05/26 00:33:16 henning Exp $ */ + +/* + * Copyright (c) 2006 Henning Brauer + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ntpd.h" + +#define SENSORS_MAX 255 + +void sensor_add(struct ntpd_conf *, struct sensor *); + +void +sensor_init(struct ntpd_conf *conf) +{ + TAILQ_INIT(&conf->ntp_sensors); +} + +void +sensor_scan(struct ntpd_conf *conf) +{ + struct sensor sensor; + int i; + int mib[3]; + size_t len; + + mib[0] = CTL_HW; + mib[1] = HW_SENSORS; + + for (i = 0; i < SENSORS_MAX; i++) { + mib[2] = i; + len = sizeof(sensor); + if (sysctl(mib, 3, &sensor, &len, NULL, 0) == -1) { + if (errno != ENOENT) + log_warn("sensor_scan sysctl"); + break; + } + + if (sensor.type == SENSOR_TIMEDELTA) + sensor_add(conf, &sensor); + } +} + +void +sensor_add(struct ntpd_conf *conf, struct sensor *sensor) +{ + struct ntp_sensor *s; + + /* check wether it is already there */ + TAILQ_FOREACH(s, &conf->ntp_sensors, entry) + if (!strcmp(s->device, sensor->device)) + return; + + if ((s = calloc(1, sizeof(*s))) == NULL) + fatal("sensor_add calloc"); + + s->next = time(NULL); + if ((s->device = strdup(sensor->device)) == NULL) + fatal("sensor_add strdup"); + s->sensorid = sensor->num; + + TAILQ_INSERT_TAIL(&conf->ntp_sensors, s, entry); + + log_debug("sensor %s added", s->device); +} + +void +sensor_remove(struct ntpd_conf *conf, struct ntp_sensor *s) +{ + TAILQ_REMOVE(&conf->ntp_sensors, s, entry); + free(s->device); + free(s); +} + +int +sensor_query(struct ntp_sensor *s) +{ + struct sensor sensor; + int mib[3]; + size_t len; + + s->next = time(NULL) + SENSOR_QUERY_INTERVAL; + if (s->update.rcvd < time(NULL) - SENSOR_DATA_MAXAGE) + s->update.good = 0; + + mib[0] = CTL_HW; + mib[1] = HW_SENSORS; + mib[2] = s->sensorid; + len = sizeof(sensor); + if (sysctl(mib, 3, &sensor, &len, NULL, 0) == -1) { + log_warn("sensor_query sysctl"); + return (0); + } + + if (sensor.flags & SENSOR_FINVALID || + sensor.status != SENSOR_S_OK) + return (0); + + if (sensor.type != SENSOR_TIMEDELTA || + strcmp(sensor.device, s->device)) + return (-1); /* causes sensor removal */ + + if (sensor.tv.tv_sec == s->update.rcvd) /* already seen */ + return (0); + + s->update.offset = 0 - (float)sensor.value / 1000000000.0; + s->update.status.stratum = 0; /* increased when sent out */ + s->update.status.rootdelay = 0; + s->update.status.rootdispersion = 0; + s->update.status.reftime = sensor.tv.tv_sec; + + /* XXX 4 char, 'DCF ', 'GPS ', 'PPS ' and the like */ + s->update.status.refid = 0; + s->update.rcvd = sensor.tv.tv_sec; + s->update.good = 1; + + log_debug("sensor %s: offset %f", s->device, s->update.offset); + + return (0); +}