aboutsummaryrefslogtreecommitdiff
path: root/ntpd/ntp_proto.c
diff options
context:
space:
mode:
Diffstat (limited to 'ntpd/ntp_proto.c')
-rw-r--r--ntpd/ntp_proto.c104
1 files changed, 97 insertions, 7 deletions
diff --git a/ntpd/ntp_proto.c b/ntpd/ntp_proto.c
index 577b5fb0af5a..40624066746f 100644
--- a/ntpd/ntp_proto.c
+++ b/ntpd/ntp_proto.c
@@ -14,6 +14,7 @@
#include "ntp_control.h"
#include "ntp_string.h"
#include "ntp_leapsec.h"
+#include "refidsmear.h"
#include <stdio.h>
#ifdef HAVE_LIBSCF_H
@@ -61,7 +62,8 @@ typedef struct peer_select_tag {
* System variables are declared here. Unless specified otherwise, all
* times are in seconds.
*/
-u_char sys_leap; /* system leap indicator */
+u_char sys_leap; /* system leap indicator, use set_sys_leap() to change this */
+u_char xmt_leap; /* leap indicator sent in client requests, set up by set_sys_leap() */
u_char sys_stratum; /* system stratum */
s_char sys_precision; /* local clock precision (log2 s) */
double sys_rootdelay; /* roundtrip delay to primary source */
@@ -70,6 +72,11 @@ u_int32 sys_refid; /* reference id (network byte order) */
l_fp sys_reftime; /* last update time */
struct peer *sys_peer; /* current peer */
+#ifdef LEAP_SMEAR
+struct leap_smear_info leap_smear;
+#endif
+int leap_sec_in_progress;
+
/*
* Rate controls. Leaky buckets are used to throttle the packet
* transmission rates in order to protect busy servers such as at NIST
@@ -151,6 +158,33 @@ void pool_name_resolved (int, int, void *, const char *,
const struct addrinfo *);
#endif /* WORKER */
+void
+set_sys_leap(u_char new_sys_leap) {
+ sys_leap = new_sys_leap;
+ xmt_leap = sys_leap;
+
+ /*
+ * Under certain conditions we send faked leap bits to clients, so
+ * eventually change xmt_leap below, but never change LEAP_NOTINSYNC.
+ */
+ if (xmt_leap != LEAP_NOTINSYNC) {
+ if (leap_sec_in_progress) {
+ /* always send "not sync" */
+ xmt_leap = LEAP_NOTINSYNC;
+ }
+#ifdef LEAP_SMEAR
+ else {
+ /*
+ * If leap smear is enabled in general we must never send a leap second warning
+ * to clients, so make sure we only send "in sync".
+ */
+ if (leap_smear.enabled)
+ xmt_leap = LEAP_NOWARNING;
+ }
+#endif /* LEAP_SMEAR */
+ }
+}
+
/*
* transmit - transmit procedure called by poll timeout
@@ -1909,7 +1943,7 @@ clock_update(
*/
case 2:
clear_all();
- sys_leap = LEAP_NOTINSYNC;
+ set_sys_leap(LEAP_NOTINSYNC);
sys_stratum = STRATUM_UNSPEC;
memcpy(&sys_refid, "STEP", 4);
sys_rootdelay = 0;
@@ -1930,7 +1964,7 @@ clock_update(
* process.
*/
if (sys_leap == LEAP_NOTINSYNC) {
- sys_leap = LEAP_NOWARNING;
+ set_sys_leap(LEAP_NOWARNING);
#ifdef AUTOKEY
if (crypto_flags)
crypto_update();
@@ -2424,7 +2458,7 @@ clock_select(void)
osys_peer = sys_peer;
sys_survivors = 0;
#ifdef LOCKCLOCK
- sys_leap = LEAP_NOTINSYNC;
+ set_sys_leap(LEAP_NOTINSYNC);
sys_stratum = STRATUM_UNSPEC;
memcpy(&sys_refid, "DOWN", 4);
#endif /* LOCKCLOCK */
@@ -3407,6 +3441,16 @@ peer_xmit(
}
+#ifdef LEAP_SMEAR
+
+static void
+leap_smear_add_offs(l_fp *t, l_fp *t_recv) {
+ L_ADD(t, &leap_smear.offset);
+}
+
+#endif /* LEAP_SMEAR */
+
+
/*
* fast_xmit - Send packet for nonpersistent association. Note that
* neither the source or destination can be a broadcast address.
@@ -3468,18 +3512,60 @@ fast_xmit(
* This is a normal packet. Use the system variables.
*/
} else {
- xpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap,
+#ifdef LEAP_SMEAR
+ /*
+ * Make copies of the variables which can be affected by smearing.
+ */
+ l_fp this_ref_time;
+ l_fp this_recv_time;
+#endif
+
+ /*
+ * If we are inside the leap smear interval we add the current smear offset to
+ * the packet receive time, to the packet transmit time, and eventually to the
+ * reftime to make sure the reftime isn't later than the transmit/receive times.
+ */
+ xpkt.li_vn_mode = PKT_LI_VN_MODE(xmt_leap,
PKT_VERSION(rpkt->li_vn_mode), xmode);
+
xpkt.stratum = STRATUM_TO_PKT(sys_stratum);
xpkt.ppoll = max(rpkt->ppoll, ntp_minpoll);
xpkt.precision = sys_precision;
xpkt.refid = sys_refid;
xpkt.rootdelay = HTONS_FP(DTOFP(sys_rootdelay));
xpkt.rootdisp = HTONS_FP(DTOUFP(sys_rootdisp));
+
+#ifdef LEAP_SMEAR
+ this_ref_time = sys_reftime;
+ if (leap_smear.in_progress) {
+ leap_smear_add_offs(&this_ref_time, NULL);
+ xpkt.refid = convertLFPToRefID(leap_smear.offset);
+ DPRINTF(2, ("fast_xmit: leap_smear.in_progress: refid %8x, smear %s\n",
+ ntohl(xpkt.refid),
+ lfptoa(&leap_smear.offset, 8)
+ ));
+ }
+ HTONL_FP(&this_ref_time, &xpkt.reftime);
+#else
HTONL_FP(&sys_reftime, &xpkt.reftime);
+#endif
+
xpkt.org = rpkt->xmt;
+
+#ifdef LEAP_SMEAR
+ this_recv_time = rbufp->recv_time;
+ if (leap_smear.in_progress)
+ leap_smear_add_offs(&this_recv_time, NULL);
+ HTONL_FP(&this_recv_time, &xpkt.rec);
+#else
HTONL_FP(&rbufp->recv_time, &xpkt.rec);
+#endif
+
get_systime(&xmt_tx);
+#ifdef LEAP_SMEAR
+ if (leap_smear.in_progress)
+ leap_smear_add_offs(&xmt_tx, &this_recv_time);
+#endif
HTONL_FP(&xmt_tx, &xpkt.xmt);
}
@@ -3988,7 +4074,7 @@ init_proto(void)
* Fill in the sys_* stuff. Default is don't listen to
* broadcasting, require authentication.
*/
- sys_leap = LEAP_NOTINSYNC;
+ set_sys_leap(LEAP_NOTINSYNC);
sys_stratum = STRATUM_UNSPEC;
memcpy(&sys_refid, "INIT", 4);
sys_peer = NULL;
@@ -4062,8 +4148,12 @@ proto_config(
case PROTO_MONITOR: /* monitoring (monitor) */
if (value)
mon_start(MON_ON);
- else
+ else {
mon_stop(MON_ON);
+ if (mon_enabled)
+ msyslog(LOG_WARNING,
+ "restrict: 'monitor' cannot be disabled while 'limited' is enabled");
+ }
break;
case PROTO_NTP: /* NTP discipline (ntp) */