From: Harlan Stenn Date: Thu, 14 Jun 2007 05:40:14 +0000 (-0400) Subject: Leap file fixes from Dave Mills X-Git-Tag: NTP_4_2_5P49~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0e909aaa22a8b2eb97611ec59df657b253052afe;p=thirdparty%2Fntp.git Leap file fixes from Dave Mills bk: 4670d4beZKM2hDQD3TySou_OCkk35g --- diff --git a/ChangeLog b/ChangeLog index b03cae2d9..d7d5b2730 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ +* Leap file fixes from Dave Mills. * [Bug 858] Recent leapfile changes broke without OPENSSL. * Use a char for DIR_SEP, not a string. * [Bug 850] driftfile parsing changes. diff --git a/include/ntpd.h b/include/ntpd.h index 83e146dc4..4d0771ab3 100644 --- a/include/ntpd.h +++ b/include/ntpd.h @@ -122,7 +122,6 @@ extern void loop_config (int, double); extern void huffpuff (void); extern u_long sys_clocktime; extern u_int sys_tai; -extern u_long sys_leapin; /* ntp_monitor.c */ extern void init_mon (void); @@ -183,6 +182,8 @@ extern void peer_clear (struct peer *, char *); extern void process_packet (struct peer *, struct pkt *); extern void clock_select (void); extern void kod_proto (void); +extern u_long leap_ins; +extern u_long leap_sec; /* * there seems to be a bug in the IRIX 4 compiler which prevents @@ -238,6 +239,7 @@ extern void record_loop_stats (double, double, double, double, int); extern void record_clock_stats (struct sockaddr_storage *, const char *); extern void record_raw_stats (struct sockaddr_storage *, struct sockaddr_storage *, l_fp *, l_fp *, l_fp *, l_fp *); extern void record_sys_stats (void); +extern u_long leap_month(u_long); extern void record_crypto_stats (struct sockaddr_storage *, const char *); #ifdef DEBUG extern void record_timing_stats (const char *); diff --git a/ntpd/ntp_proto.c b/ntpd/ntp_proto.c index 1ab9200a2..9f387a53d 100644 --- a/ntpd/ntp_proto.c +++ b/ntpd/ntp_proto.c @@ -67,6 +67,8 @@ double sys_jitter; /* system jitter (s) */ static int sys_hopper; /* anticlockhop counter */ static int sys_maxhop = MAXHOP; /* anticlockhop counter threshold */ int leap_next; /* leap consensus */ +u_long leap_ins; /* seconds ar next leap */ +u_long leap_sec; /* leap countdown */ keyid_t sys_private; /* private value for session seed */ int sys_manycastserver; /* respond to manycast client pkts */ int peer_ntpdate; /* active peers in ntpdate mode */ @@ -1261,6 +1263,7 @@ clock_update(void) u_char oleap; u_char ostratum; double dtemp; + l_fp now; /* * There must be a system peer at this point. If we just changed @@ -1308,16 +1311,36 @@ clock_update(void) /* * Clock was slewed. Update the system stratum, leap bits, root - * delay, root dispersion, reference ID and reference time. If - * the leap changes, we gotta reroll the keys. Except for - * reference clocks, the minimum dispersion increment is not - * less than sys_mindisp. + * delay, root dispersion, reference ID and reference time. + * Except for reference clocks, the minimum dispersion increment + * is not less than sys_mindisp. If a leap is anticipated, read + * the system clock because the time now might not be the time + * at the last offset measurement. */ case 1: - sys_leap = leap_next; + sys_stratum = min(sys_peer->stratum + 1, STRATUM_UNSPEC); sys_reftime = sys_peer->rec; + get_systime(&now); + + /* + * If no leap is scheduled and the number of upstream + * leap bits is at least the sanity threshold, schedule + * a leap for the end of the current month. If from the + * leapseconds file schedule a leap for the last entry + * in the file, but only if it is in the future. + */ + if (leap_sec == 0) { + if (leap_next >= sys_minsane) { + leap_sec = leap_month(now.l_ui); + } else if (leap_ins != 0) { + if (now.l_ui < leap_ins) { + leap_sec = leap_ins - now.l_ui; + sys_tai--; + } + } + } /* * In orphan mode the stratum defaults to the orphan @@ -2166,18 +2189,18 @@ clock_select(void) * What remains is a list usually not greater than sys_minclock * peers. We want only a peer at the lowest stratum to become * the system peer, although all survivors are eligible for the - * combining algorithm. Consider each peer in turn and OR the - * leap bits on the assumption that, if some of them honk - * nonzero bits, they must know what they are doing. Check for - * prefer and pps peers at any stratum. Note that the head of - * the list is at the lowest stratum and that unsynchronized - * peers cannot survive this far. + * combining algorithm. Consider each peer in turn and compute + * the total number of leap bits. Check for prefer and pps peers + * at any stratum. Note that the head of the list is at the + * lowest stratum and that unsynchronized peers cannot survive + * this far. */ leap_next = 0; for (i = 0; i < nlist; i++) { peer = peer_list[i]; sys_survivors++; - leap_next |= peer->leap; + if (peer->leap == LEAP_ADDSECOND) + leap_next++; peer->status = CTL_PST_SEL_SYNCCAND; if (peer->flags & FLAG_PREFER) sys_prefer = peer; diff --git a/ntpd/ntp_timer.c b/ntpd/ntp_timer.c index 54a5be21b..e29db71cf 100644 --- a/ntpd/ntp_timer.c +++ b/ntpd/ntp_timer.c @@ -310,8 +310,15 @@ timer(void) /* * Leapseconds. */ - if (sys_tai > 0 && current_time == sys_leapin) - loop_config(LOOP_LEAP, sys_tai); + if (leap_sec > 0) { + if (leap_sec < 86400 * 28) + sys_leap = LEAP_ADDSECOND; + if (leap_sec < 86400) + loop_config(LOOP_LEAP, sys_tai); + leap_sec--; + } else { + sys_leap = LEAP_NOWARNING; + } /* * Garbage collect expired keys. diff --git a/ntpd/ntp_util.c b/ntpd/ntp_util.c index f7da0cb80..9a5484333 100644 --- a/ntpd/ntp_util.c +++ b/ntpd/ntp_util.c @@ -755,12 +755,62 @@ leap_file( msyslog(LOG_INFO, "Leapseconds format error in %s", cp); } else { sys_tai = offset; - sys_leapin = leapsec; + leap_ins = leapsec; msyslog(LOG_INFO, "TAI offset %d s at %lu from %s", - sys_tai, sys_leapin, cp); + sys_tai, leap_ins, cp); } } +/* + * leap_month - returns the number of seconds until the end of the month + */ +#define L_DAY 86400 /* seconds per day */ +#define L_YEAR L_DAY * 365 /* days per year */ +#define L_LYEAR L_YEAR + 1 /* days per leap year */ +#define L_4YEAR L_LYEAR + 3 * L_YEAR /* days per leap cycle */ +#define L_CENT (u_long)L_4YEAR * 25 /* days per century */ + +u_long +leap_month( + u_long sec /* current NTP second */ + ) +{ + u_long ltemp; + u_long *ptr; + u_long year[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, + 31}; + u_long lyear[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, + 31}; + + /* + * Find current leap cycle + */ + ltemp = sec; + while (ltemp > L_CENT) + ltemp -= L_CENT; + while (ltemp > L_4YEAR) + ltemp -= L_4YEAR; + + /* + * If in leap year, use leap table + */ + if (ltemp < L_LYEAR) { + ptr = lyear; + } else { + ptr = year; + ltemp -= L_LYEAR; + while (ltemp > L_YEAR) + ltemp -= L_YEAR; + } + while (ltemp > *ptr) + ltemp -= *ptr++; + + /* The result is the number of seconds until the end of the + * month when the leap is to occur. + */ + return (ltemp); +} + #ifdef DEBUG_TIMING /*