1/*- 2 * Copyright (c) 1985, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 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. 20 * 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 31 * SUCH DAMAGE. 32 */ 33 34#ifndef lint 35#if 0 36static char sccsid[] = "@(#)correct.c 8.1 (Berkeley) 6/6/93"; 37#endif 38__attribute__((__used__)) 39static const char rcsid[] = 40 "$FreeBSD: src/usr.sbin/timed/timed/correct.c,v 1.8 2007/11/07 10:53:41 kevlo Exp $"; 41#endif /* not lint */ 42#include <sys/cdefs.h> 43 44#include "globals.h" 45#include <math.h> 46#include <sys/types.h> 47#include <sys/times.h> 48 49static void adjclock(struct timeval *); 50 51/* 52 * sends to the slaves the corrections for their clocks after fixing our 53 * own 54 */ 55void 56correct(avdelta) 57 long avdelta; 58{ 59 struct hosttbl *htp; 60 int corr; 61 struct timeval adjlocal, tmptv; 62 struct tsp to; 63 struct tsp *answer; 64 65 mstotvround(&adjlocal, avdelta); 66 67 for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) { 68 if (htp->delta != HOSTDOWN) { 69 corr = avdelta - htp->delta; 70/* If the other machine is off in the weeds, set its time directly. 71 * If a slave gets the wrong day, the original code would simply 72 * fix the minutes. If you fix a network partition, you can get 73 * into such situations. 74 */ 75 if (htp->need_set 76 || corr >= MAXADJ*1000 77 || corr <= -MAXADJ*1000) { 78 htp->need_set = 0; 79 (void)gettimeofday(&tmptv,0); 80 timevaladd(&tmptv, &adjlocal); 81 to.tsp_time.tv_sec = tmptv.tv_sec; 82 to.tsp_time.tv_usec = tmptv.tv_usec; 83 to.tsp_type = TSP_SETTIME; 84 } else { 85 tmptv.tv_sec = to.tsp_time.tv_sec; 86 tmptv.tv_usec = to.tsp_time.tv_usec; 87 mstotvround(&tmptv, corr); 88 to.tsp_time.tv_sec = tmptv.tv_sec; 89 to.tsp_time.tv_usec = tmptv.tv_usec; 90 to.tsp_type = TSP_ADJTIME; 91 } 92 (void)strcpy(to.tsp_name, hostname); 93 answer = acksend(&to, &htp->addr, htp->name, 94 TSP_ACK, 0, 0); 95 if (!answer) { 96 htp->delta = HOSTDOWN; 97 syslog(LOG_WARNING, 98 "no reply to time correction from %s", 99 htp->name); 100 if (++htp->noanswer >= LOSTHOST) { 101 if (trace) { 102 fprintf(fd, 103 "purging %s for not answering\n", 104 htp->name); 105 (void)fflush(fd); 106 } 107 htp = remmach(htp); 108 } 109 } 110 } 111 } 112 113 /* 114 * adjust our own clock now that we are not sending it out 115 */ 116 adjclock(&adjlocal); 117} 118 119 120static void 121adjclock(corr) 122 struct timeval *corr; 123{ 124 static int passes = 0; 125 static int smoother = 0; 126 long delta; /* adjustment in usec */ 127 long ndelta; 128 struct timeval now; 129 struct timeval adj; 130 131 if (!timerisset(corr)) 132 return; 133 134 adj = *corr; 135 if (adj.tv_sec < MAXADJ && adj.tv_sec > - MAXADJ) { 136 delta = adj.tv_sec*1000000 + adj.tv_usec; 137 /* If the correction is less than the minimum round 138 * trip time for an ICMP packet, and thus 139 * less than the likely error in the measurement, 140 * do not do the entire correction. Do half 141 * or a quarter of it. 142 */ 143 144 if (delta > -MIN_ROUND*1000 145 && delta < MIN_ROUND*1000) { 146 if (smoother <= 4) 147 smoother++; 148 ndelta = delta >> smoother; 149 if (trace) 150 fprintf(fd, 151 "trimming delta %ld usec to %ld\n", 152 delta, ndelta); 153 adj.tv_usec = ndelta; 154 adj.tv_sec = 0; 155 } else if (smoother > 0) { 156 smoother--; 157 } 158 if (0 > adjtime(corr, 0)) { 159 syslog(LOG_ERR, "adjtime: %m"); 160 } 161 if (passes > 1 162 && (delta < -BIG_ADJ || delta > BIG_ADJ)) { 163 smoother = 0; 164 passes = 0; 165 syslog(LOG_WARNING, 166 "large time adjustment of %+.3f sec", 167 delta/1000000.0); 168 } 169 } else { 170 syslog(LOG_WARNING, 171 "clock correction %ld sec too large to adjust", 172 adj.tv_sec); 173 (void) gettimeofday(&now, 0); 174 timevaladd(&now, corr); 175 if (settimeofday(&now, 0) < 0) 176 syslog(LOG_ERR, "settimeofday: %m"); 177 } 178} 179 180 181/* adjust the time in a message by the time it 182 * spent in the queue 183 */ 184void 185adj_msg_time(msg, now) 186 struct tsp *msg; 187 struct timeval *now; 188{ 189 msg->tsp_time.tv_sec += (now->tv_sec - from_when.tv_sec); 190 msg->tsp_time.tv_usec += (now->tv_usec - from_when.tv_usec); 191 192 while (msg->tsp_time.tv_usec < 0) { 193 msg->tsp_time.tv_sec--; 194 msg->tsp_time.tv_usec += 1000000; 195 } 196 while (msg->tsp_time.tv_usec >= 1000000) { 197 msg->tsp_time.tv_sec++; 198 msg->tsp_time.tv_usec -= 1000000; 199 } 200} 201