GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ntpd/sensors.c Lines: 0 106 0.0 %
Date: 2017-11-07 Branches: 0 54 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: sensors.c,v 1.52 2016/09/03 11:52:06 reyk Exp $ */
2
3
/*
4
 * Copyright (c) 2006 Henning Brauer <henning@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/queue.h>
21
#include <sys/time.h>
22
#include <sys/sensors.h>
23
#include <sys/sysctl.h>
24
#include <sys/device.h>
25
26
#include <errno.h>
27
#include <fcntl.h>
28
#include <stdio.h>
29
#include <stdlib.h>
30
#include <string.h>
31
#include <unistd.h>
32
33
#include "ntpd.h"
34
35
#define MAXDEVNAMLEN		16
36
37
int	sensor_probe(int, char *, struct sensor *);
38
void	sensor_add(int, char *);
39
void	sensor_remove(struct ntp_sensor *);
40
void	sensor_update(struct ntp_sensor *);
41
42
void
43
sensor_init(void)
44
{
45
	TAILQ_INIT(&conf->ntp_sensors);
46
}
47
48
int
49
sensor_scan(void)
50
{
51
	int		i, n, err;
52
	char		d[MAXDEVNAMLEN];
53
	struct sensor	s;
54
55
	n = 0;
56
	for (i = 0; ; i++)
57
		if ((err = sensor_probe(i, d, &s))) {
58
			if (err == 0)
59
				continue;
60
			if (err == -1)	/* no further sensors */
61
				break;
62
			sensor_add(i, d);
63
			n++;
64
		}
65
66
	return n;
67
}
68
69
/*
70
 * 1 = time sensor!
71
 * 0 = sensor exists... but is not a time sensor
72
 * -1: no sensor here, and no further sensors after this
73
 */
74
int
75
sensor_probe(int devid, char *dxname, struct sensor *sensor)
76
{
77
	int			mib[5];
78
	size_t			slen, sdlen;
79
	struct sensordev	sensordev;
80
81
	mib[0] = CTL_HW;
82
	mib[1] = HW_SENSORS;
83
	mib[2] = devid;
84
	mib[3] = SENSOR_TIMEDELTA;
85
	mib[4] = 0;
86
87
	sdlen = sizeof(sensordev);
88
	if (sysctl(mib, 3, &sensordev, &sdlen, NULL, 0) == -1) {
89
		if (errno == ENXIO)
90
			return (0);
91
		if (errno == ENOENT)
92
			return (-1);
93
		log_warn("sensor_probe sysctl");
94
	}
95
96
	if (sensordev.maxnumt[SENSOR_TIMEDELTA] == 0)
97
		return (0);
98
99
	strlcpy(dxname, sensordev.xname, MAXDEVNAMLEN);
100
101
	slen = sizeof(*sensor);
102
	if (sysctl(mib, 5, sensor, &slen, NULL, 0) == -1) {
103
		if (errno != ENOENT)
104
			log_warn("sensor_probe sysctl");
105
		return (0);
106
	}
107
108
	return (1);
109
}
110
111
void
112
sensor_add(int sensordev, char *dxname)
113
{
114
	struct ntp_sensor	*s;
115
	struct ntp_conf_sensor	*cs;
116
117
	/* check whether it is already there */
118
	TAILQ_FOREACH(s, &conf->ntp_sensors, entry)
119
		if (!strcmp(s->device, dxname))
120
			return;
121
122
	/* check whether it is requested in the config file */
123
	for (cs = TAILQ_FIRST(&conf->ntp_conf_sensors); cs != NULL &&
124
	    strcmp(cs->device, dxname) && strcmp(cs->device, "*");
125
	    cs = TAILQ_NEXT(cs, entry))
126
		; /* nothing */
127
	if (cs == NULL)
128
		return;
129
130
	if ((s = calloc(1, sizeof(*s))) == NULL)
131
		fatal("sensor_add calloc");
132
133
	s->next = getmonotime();
134
	s->weight = cs->weight;
135
	s->correction = cs->correction;
136
	s->stratum = cs->stratum - 1;
137
	if ((s->device = strdup(dxname)) == NULL)
138
		fatal("sensor_add strdup");
139
	s->sensordevid = sensordev;
140
141
	if (cs->refstr == NULL)
142
		memcpy(&s->refid, SENSOR_DEFAULT_REFID, sizeof(s->refid));
143
	else {
144
		s->refid = 0;
145
		strncpy((char *)&s->refid, cs->refstr, sizeof(s->refid));
146
	}
147
148
	TAILQ_INSERT_TAIL(&conf->ntp_sensors, s, entry);
149
150
	log_debug("sensor %s added (weight %d, correction %.6f, refstr %.4u, "
151
	     "stratum %d)", s->device, s->weight, s->correction / 1e6,
152
	     s->refid, s->stratum);
153
}
154
155
void
156
sensor_remove(struct ntp_sensor *s)
157
{
158
	TAILQ_REMOVE(&conf->ntp_sensors, s, entry);
159
	free(s->device);
160
	free(s);
161
}
162
163
void
164
sensor_query(struct ntp_sensor *s)
165
{
166
	char		 dxname[MAXDEVNAMLEN];
167
	struct sensor	 sensor;
168
169
	if (conf->settime)
170
		s->next = getmonotime() + SENSOR_QUERY_INTERVAL_SETTIME;
171
	else
172
		s->next = getmonotime() + SENSOR_QUERY_INTERVAL;
173
174
	/* rcvd is walltime here, monotime in client.c. not used elsewhere */
175
	if (s->update.rcvd < time(NULL) - SENSOR_DATA_MAXAGE)
176
		s->update.good = 0;
177
178
	if (!sensor_probe(s->sensordevid, dxname, &sensor)) {
179
		sensor_remove(s);
180
		return;
181
	}
182
183
	if (sensor.flags & SENSOR_FINVALID ||
184
	    sensor.status != SENSOR_S_OK)
185
		return;
186
187
	if (strcmp(dxname, s->device)) {
188
		sensor_remove(s);
189
		return;
190
	}
191
192
	if (sensor.tv.tv_sec == s->last)	/* already seen */
193
		return;
194
195
	s->last = sensor.tv.tv_sec;
196
	/*
197
	 * TD = device time
198
	 * TS = system time
199
	 * sensor.value = TS - TD in ns
200
	 * if value is positive, system time is ahead
201
	 */
202
	s->offsets[s->shift].offset = (sensor.value / -1e9) - getoffset() +
203
	    (s->correction / 1e6);
204
	s->offsets[s->shift].rcvd = sensor.tv.tv_sec;
205
	s->offsets[s->shift].good = 1;
206
207
	s->offsets[s->shift].status.send_refid = s->refid;
208
	/* stratum increased when sent out */
209
	s->offsets[s->shift].status.stratum = s->stratum;
210
	s->offsets[s->shift].status.rootdelay = 0;
211
	s->offsets[s->shift].status.rootdispersion = 0;
212
	s->offsets[s->shift].status.reftime = sensor.tv.tv_sec;
213
	s->offsets[s->shift].status.synced = 1;
214
215
	log_debug("sensor %s: offset %f", s->device,
216
	    s->offsets[s->shift].offset);
217
218
	if (++s->shift >= SENSOR_OFFSETS) {
219
		s->shift = 0;
220
		sensor_update(s);
221
	}
222
223
}
224
225
void
226
sensor_update(struct ntp_sensor *s)
227
{
228
	struct ntp_offset	**offsets;
229
	int			  i;
230
231
	if ((offsets = calloc(SENSOR_OFFSETS, sizeof(struct ntp_offset *))) ==
232
	    NULL)
233
		fatal("calloc sensor_update");
234
235
	for (i = 0; i < SENSOR_OFFSETS; i++)
236
		offsets[i] = &s->offsets[i];
237
238
	qsort(offsets, SENSOR_OFFSETS, sizeof(struct ntp_offset *),
239
	    offset_compare);
240
241
	i = SENSOR_OFFSETS / 2;
242
	memcpy(&s->update, offsets[i], sizeof(s->update));
243
	if (SENSOR_OFFSETS % 2 == 0) {
244
		s->update.offset =
245
		    (offsets[i - 1]->offset + offsets[i]->offset) / 2;
246
	}
247
	free(offsets);
248
249
	log_debug("sensor update %s: offset %f", s->device, s->update.offset);
250
	priv_adjtime();
251
}