2 * Copyright (c) 1985, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * @(#)correct.c 8.1 (Berkeley) 6/6/93
34 * $FreeBSD: src/usr.sbin/timed/timed/correct.c,v 1.4 1999/08/28 01:20:17 peter Exp $
35 * $DragonFly: src/usr.sbin/timed/timed/correct.c,v 1.8 2004/09/05 02:20:15 dillon Exp $
40 #include <sys/types.h>
41 #include <sys/times.h>
43 static void adjclock(struct timeval *);
46 * sends to the slaves the corrections for their clocks after fixing our
54 struct timeval adjlocal;
58 mstotvround(&adjlocal, avdelta);
60 for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {
61 if (htp->delta != HOSTDOWN) {
62 corr = avdelta - htp->delta;
63 /* If the other machine is off in the weeds, set its time directly.
64 * If a slave gets the wrong day, the original code would simply
65 * fix the minutes. If you fix a network partition, you can get
66 * into such situations.
69 || corr >= MAXADJ*1000
70 || corr <= -MAXADJ*1000) {
72 gettimeofday(&to.tsp_time,0);
73 timevaladd(&to.tsp_time, &adjlocal);
74 to.tsp_type = TSP_SETTIME;
76 mstotvround(&to.tsp_time, corr);
77 to.tsp_type = TSP_ADJTIME;
79 strlcpy(to.tsp_name, hostname, sizeof(to.tsp_name));
80 answer = acksend(&to, &htp->addr, htp->name,
83 htp->delta = HOSTDOWN;
85 "no reply to time correction from %s",
87 if (++htp->noanswer >= LOSTHOST) {
90 "purging %s for not answering\n",
101 * adjust our own clock now that we are not sending it out
108 adjclock(struct timeval *corr)
110 static int passes = 0;
111 static int smoother = 0;
112 long delta; /* adjustment in usec */
117 if (!timerisset(corr))
121 if (adj.tv_sec < MAXADJ && adj.tv_sec > - MAXADJ) {
122 delta = adj.tv_sec*1000000 + adj.tv_usec;
123 /* If the correction is less than the minimum round
124 * trip time for an ICMP packet, and thus
125 * less than the likely error in the measurement,
126 * do not do the entire correction. Do half
127 * or a quarter of it.
130 if (delta > -MIN_ROUND*1000
131 && delta < MIN_ROUND*1000) {
134 ndelta = delta >> smoother;
137 "trimming delta %ld usec to %ld\n",
139 adj.tv_usec = ndelta;
141 } else if (smoother > 0) {
144 if (0 > adjtime(corr, 0)) {
145 syslog(LOG_ERR, "adjtime: %m");
148 && (delta < -BIG_ADJ || delta > BIG_ADJ)) {
152 "large time adjustment of %+.3f sec",
157 "clock correction %ld sec too large to adjust",
159 gettimeofday(&now, 0);
160 timevaladd(&now, corr);
161 if (settimeofday(&now, 0) < 0)
162 syslog(LOG_ERR, "settimeofday: %m");
167 /* adjust the time in a message by the time it
171 adj_msg_time(struct tsp *msg, struct timeval *now)
173 msg->tsp_time.tv_sec += (now->tv_sec - from_when.tv_sec);
174 msg->tsp_time.tv_usec += (now->tv_usec - from_when.tv_usec);
176 while (msg->tsp_time.tv_usec < 0) {
177 msg->tsp_time.tv_sec--;
178 msg->tsp_time.tv_usec += 1000000;
180 while (msg->tsp_time.tv_usec >= 1000000) {
181 msg->tsp_time.tv_sec++;
182 msg->tsp_time.tv_usec -= 1000000;