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;