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); +}