+* 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.
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);
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
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 *);
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 */
u_char oleap;
u_char ostratum;
double dtemp;
+ l_fp now;
/*
* There must be a system peer at this point. If we just changed
/*
* 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
* 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;
/*
* 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.
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
/*