[ntp:bk-ntp-stable-send] BitKeeper diffs

stenn at whimsy.udel.edu stenn at whimsy.udel.edu
Tue Apr 26 23:54:17 UTC 2016


#### ChangeSet ####
2016-04-26 23:24:25+00:00, stenn at psp-deb1.ntp.org
  4.2.8p7 documentation cleanup

==== ChangeLog ====
2016-04-26 23:24:19+00:00, stenn at psp-deb1.ntp.org +9 -9
  4.2.8p7 documentation cleanup

--- 1.1818/ChangeLog	2016-04-21 19:29:09 -04:00
+++ 1.1819/ChangeLog	2016-04-26 19:24:19 -04:00
@@ -5,9 +5,18 @@ 
   time. Include passive servers in this check. HStenn.
 * [Sec 2945] Additional KoD packet checks.  HStenn.
 * [Sec 2978] Interleave can be partially triggered.  HStenn.
+* [Sec 3007] Validate crypto-NAKs.  Danny Mayer.
 * [Sec 3008] Always check the return value of ctl_getitem().
   - initial work by HStenn
   - Additional cleanup of ctl_getitem by perlinger at ntp.org
+* [Sec 3009] Crafted addpeer with hmode > 7 causes OOB error. perlinger at ntp.org
+   - added more stringent checks on packet content
+* [Sec 3010] remote configuration trustedkey/requestkey values
+  are not properly validated. perlinger at ntp.org
+  - sidekick: Ignore keys that have an unsupported MAC algorithm
+    but are otherwise well-formed
+* [Sec 3011] Duplicate IPs on unconfig directives will cause an assertion botch
+  - graciously accept the same IP multiple times. perlinger at ntp.org
 * [Sec 3020] Refclock impersonation.  HStenn.
 * [Bug 2831]  Segmentation Fault in DNS lookup during startup. perlinger at ntp.org
   - fixed yet another race condition in the threaded resolver code.
@@ -21,15 +30,6 @@ 
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
 * [Bug 2999] out-of-bounds access in 'is_safe_filename()'. perlinger at ntp.org
-* [Bug 3007] Validate crypto-NAKs.  Danny Mayer.
-* [Bug 3009] Crafted addpeer with hmode > 7 causes OOB error. perlinger at ntp.org
-   - added more stringent checks on packet content
-* [Bug 3010] remote configuration trustedkey/requestkey values
-  are not properly validated. perlinger at ntp.org
-  - sidekick: Ignore keys that have an unsupported MAC algorithm
-    but are otherwise well-formed
-* [Bug 3011] Duplicate IPs on unconfig directives will cause an assertion botch
-  - graciously accept the same IP multiple times. perlinger at ntp.org
 * [Bug 3013] Fix for ssl_init.c SHA1 test. perlinger at ntp.org
   - Patch provided by Ch. Weisgerber
 * [Bug 3015] ntpq: config-from-file: "request contains an unprintable character"

==== NEWS ====
2016-04-26 23:24:19+00:00, stenn at psp-deb1.ntp.org +123 -36
  4.2.8p7 documentation cleanup

--- 1.168/NEWS	2016-04-21 19:42:26 -04:00
+++ 1.169/NEWS	2016-04-26 19:24:19 -04:00
@@ -18,13 +18,14 @@ following 9 low- and medium-severity vul
 In addition to bug fixes and enhancements, this release fixes the
 following 9 low- and medium-severity vulnerabilities:
 
-* Improve NTP security against buffer comparison timing attacks
+* Improve NTP security against buffer comparison timing attacks,
+  AKA: authdecrypt-timing
    Date Resolved: Stable (4.2.8p7) 26 Apr 2016; Dev (4.3.92) 26 Apr 2016
    References: Sec 2879 / CVE-2016-1550
    Affects: All ntp-4 releases up to, but not including 4.2.8p7, and
 	4.3.0 up to, but not including 4.3.92
-   CVSSv2: 2.6 - (AV:L/AC:H/Au:N/C:P/I:P/A:N)
-   CVSSv3: 4.0 - CVSS:3.0/AV:L/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N
+   CVSSv2: LOW 2.6 - (AV:L/AC:H/Au:N/C:P/I:P/A:N)
+   CVSSv3: MED 4.0 - CVSS:3.0/AV:L/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N
    Summary: Packet authentication tests have been performed using
 	memcmp() or possibly bcmp(), and it is potentially possible
 	for a local or perhaps LAN-based attacker to send a packet with
@@ -37,17 +38,17 @@ following 9 low- and medium-severity vul
    Credit: This weakness was discovered independently by Loganaden
    	Velvindron, and Matthew Van Gundy and Stephen Gray of Cisco ASIG.
 
-* Clients that receive a KoD should validate the origin timestamp field.
-   References: Sec 2901 / CVE-2015-7704, CVE-2015-7705
+* Zero origin timestamp bypass: Additional KoD checks.
+   References: Sec 2945 / Sec 2901 / CVE-2015-8138
    Affects: All ntp-4 releases up to, but not including 4.2.8p7,
-   Summary: Improvements to the fixes incorporated into 4.2.8p4 and 4.3.77.
+   Summary: Improvements to the fixes incorporated in t 4.2.8p6 and 4.3.92.
 
 * peer associations were broken by the fix for NtpBug2899
    Date Resolved: Stable (4.2.8p7) 26 Apr 2016; Dev (4.3.92) 26 Apr 2016
    References: Sec 2952 / CVE-2015-7704
    Affects: All ntp-4 releases up to, but not including 4.2.8p7, and
    	4.3.0 up to, but not including 4.3.92
-   CVSSv2: 4.3 - (AV:N/AC:M/Au:N/C:N/I:N/A:P)
+   CVSSv2: MED 4.3 - (AV:N/AC:M/Au:N/C:N/I:N/A:P)
    Summary: The fix for NtpBug2952 in ntp-4.2.8p5 to address broken peer
    	associations did not address all of the issues.
    Mitigation:
@@ -59,23 +60,43 @@ following 9 low- and medium-severity vul
         Monitor your ntpd instances. 
    Credit: This problem was discovered by Michael Tatarinov.
 
-* Skeleton key: passive server with trusted key can serve time.
-   References: Sec 2936 / CVE-2015-7974
-   Affects: All ntp-4 releases up to, but not including 4.2.8p7,
-   Summary: Improvements to the fixes incorporated in t 4.2.8p6 and 4.3.90.
-
-* Zero origin timestamp bypass: Additional KoD checks.
-   References: Sec 2945 / CVE-2015-8138
-   Affects: All ntp-4 releases up to, but not including 4.2.8p7,
-   Summary: Improvements to the fixes incorporated in t 4.2.8p6 and 4.3.92.
+* Validate crypto-NAKs, AKA: CRYPTO-NAK DoS
+   Date Resolved: Stable (4.2.8p7) 26 Apr 2016; Dev (4.3.92) 26 Apr 2016
+   References: Sec 3007 / CVE-2016-1547 / VU#718152
+   Affects: All ntp-4 releases up to, but not including 4.2.8p7, and
+	4.3.0 up to, but not including 4.3.92
+   CVSS2: MED 4.3 - (AV:N/AC:M/Au:N/C:N/I:N/A:P)
+   CVSS3: MED 3.7 - CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L
+   Summary: For ntp-4 versions up to but not including ntp-4.2.8p7, an
+	off-path attacker can cause a preemptable client association to
+	be demobilized by sending a crypto NAK packet to a victim client
+	with a spoofed source address of an existing associated peer.
+	This is true even if authentication is enabled.
+
+	Furthermore, if the attacker keeps sending crypto NAK packets,
+	for example one every second, the victim never has a chance to
+	reestablish the association and synchronize time with that
+	legitimate server.
+
+	For ntp-4.2.8 thru ntp-4.2.8p6 there is less risk because more
+	stringent checks are performed on incoming packets, but there
+	are still ways to exploit this vulnerability in versions before
+	ntp-4.2.8p7.
+   Mitigation:
+	Implement BCP-38.
+	Upgrade to 4.2.8p7, or later, from the NTP Project Download Page
+	    or the NTP Public Services Project Download Page
+	Properly monitor your =ntpd= instances
+   Credit: This weakness was discovered by Stephen Gray and
+   	Matthew Van Gundy of Cisco ASIG.
 
 * ctl_getitem() return value not always checked
    Date Resolved: Stable (4.2.8p7) 26 Apr 2016; Dev (4.3.92) 26 Apr 2016
    References: Sec 3008 / CVE-2016-2519
    Affects: All ntp-4 releases up to, but not including 4.2.8p7, and
 	4.3.0 up to, but not including 4.3.92
-   CVSSv2: 4.9 - (AV:N/AC:H/Au:S/C:N/I:N/A:C)
-   CVSSv3: 4.2 - CVSS:3.0/AV:N/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:H
+   CVSSv2: MED 4.9 - (AV:N/AC:H/Au:S/C:N/I:N/A:C)
+   CVSSv3: MED 4.2 - CVSS:3.0/AV:N/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:H
    Summary: ntpq and ntpdc can be used to store and retrieve information
    	in ntpd. It is possible to store a data value that is larger
 	than the size of the buffer that the ctl_getitem() function of
@@ -97,6 +118,68 @@ following 9 low- and medium-severity vul
     Credit: This weakness was discovered by Yihan Lian of the Cloud
     	Security Team, Qihoo 360. 
 
+* Crafted addpeer with hmode > 7 causes array wraparound with MATCH_ASSOC 
+   Date Resolved: Stable (4.2.8p7) 26 Apr 2016; Dev (4.3.92) 26 Apr 2016
+   References: Sec 3009 / CVE-2016-2518 / VU#718152
+   Affects: All ntp-4 releases up to, but not including 4.2.8p7, and
+	4.3.0 up to, but not including 4.3.92
+   CVSS2: LOW 2.1 - (AV:N/AC:H/Au:S/C:N/I:N/A:P)
+   CVSS3: LOW 2.0 - CVSS:3.0/AV:N/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:L
+   Summary: Using a crafted packet to create a peer association with
+   	hmode > 7 causes the MATCH_ASSOC() lookup to make an
+	out-of-bounds reference.
+   Mitigation:
+	Implement BCP-38.
+	Upgrade to 4.2.8p7, or later, from the NTP Project Download Page
+	    or the NTP Public Services Project Download Page
+	Properly monitor your ntpd instances
+   Credit: This weakness was discovered by Yihan Lian of the Cloud
+   	Security Team, Qihoo 360.
+
+* remote configuration trustedkey/requestkey/controlkey values are not
+	properly validated
+   Date Resolved: Stable (4.2.8p7) 26 Apr 2016; Dev (4.3.92) 26 Apr 2016
+   References: Sec 3010 / CVE-2016-2517 / VU#718152
+   Affects: All ntp-4 releases up to, but not including 4.2.8p7, and
+	4.3.0 up to, but not including 4.3.92
+   CVSS2: MED 4.9 - (AV:N/AC:H/Au:S/C:N/I:N/A:C)
+   CVSS3: MED 4.2 - CVSS:3.0/AV:N/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:H
+   Summary: If ntpd was expressly configured to allow for remote
+   	configuration, a malicious user who knows the controlkey for
+	ntpq or the requestkey for ntpdc (if mode7 is expressly enabled)
+	can create a session with ntpd and then send a crafted packet to
+	ntpd that will change the value of the trustedkey, controlkey,
+	or requestkey to a value that will prevent any subsequent
+	authentication with ntpd until ntpd is restarted.
+   Mitigation:
+	Implement BCP-38.
+	Upgrade to 4.2.8p7, or later, from the NTP Project Download Page
+	    or the NTP Public Services Project Download Page
+	Properly monitor your =ntpd= instances
+   Credit: This weakness was discovered by Yihan Lian of the Cloud
+   	Security Team, Qihoo 360.
+
+* Duplicate IPs on unconfig directives will cause an assertion botch in ntpd
+   Date Resolved: Stable (4.2.8p7) 26 Apr 2016; Dev (4.3.92) 26 Apr 2016
+   References: Sec 3011 / CVE-2016-2516 / VU#718152
+   Affects: All ntp-4 releases up to, but not including 4.2.8p7, and
+   	4.3.0 up to, but not including 4.3.92
+   CVSS2: MED 6.3 - (AV:N/AC:M/Au:S/C:N/I:N/A:C)
+   CVSS3: MED 4.2 - CVSS:3.0/AV:N/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:H
+   Summary: If ntpd was expressly configured to allow for remote
+   	configuration, a malicious user who knows the controlkey for
+	ntpq or the requestkey for ntpdc (if mode7 is expressly enabled)
+	can create a session with ntpd and if an existing association is
+	unconfigured using the same IP twice on the unconfig directive
+	line, ntpd will abort.
+   Mitigation:
+	Implement BCP-38.
+	Upgrade to 4.2.8p7, or later, from the NTP Project Download Page
+	    or the NTP Public Services Project Download Page
+	Properly monitor your ntpd instances
+   Credit: This weakness was discovered by Yihan Lian of the Cloud
+   	Security Team, Qihoo 360.
+
 * Refclock impersonation vulnerability
    Date Resolved: Stable (4.2.8p7) 26 Apr 2016; Dev (4.3.92) 26 Apr 2016
    References: Sec 3020 / CVE-2016-1551
@@ -104,8 +187,8 @@ following 9 low- and medium-severity vul
 	not including 4.2.8p7, and 4.3.0 up to but not including 4.3.92.
 	By "very limited number of OSes" we mean no general-purpose OSes
 	have yet been identified that have this vulnerability.
-   CVSSv2: 2.6 - (AV:N/AC:H/Au:N/C:N/I:P/A:N)
-   CVSSv3: 3.7 - CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N
+   CVSSv2: LOW 2.6 - (AV:N/AC:H/Au:N/C:N/I:P/A:N)
+   CVSSv3: LOW 3.7 - CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N
    Summary: While most OSes implement martian packet filtering in their
    	network stack, at least regarding 127.0.0.0/8, some will allow
 	packets claiming to be from 127.0.0.0/8 that arrive over a
@@ -127,6 +210,19 @@ Two other vulnerabilities have been repo
    Credit: This weakness was discovered by Matt Street and others of
    	Cisco ASIG. 
 
+The following issues were fixed in earlier releases and contain
+improvements in 4.2.8p7:
+
+* Clients that receive a KoD should validate the origin timestamp field.
+   References: Sec 2901 / CVE-2015-7704, CVE-2015-7705
+   Affects: All ntp-4 releases up to, but not including 4.2.8p7,
+   Summary: Improvements to the fixes incorporated into 4.2.8p4 and 4.3.77.
+
+* Skeleton key: passive server with trusted key can serve time.
+   References: Sec 2936 / CVE-2015-7974
+   Affects: All ntp-4 releases up to, but not including 4.2.8p7,
+   Summary: Improvements to the fixes incorporated in t 4.2.8p6 and 4.3.90.
+
 Two other vulnerabilities have been reported, and the mitigations
 for these are as follows:
 
@@ -134,8 +230,8 @@ for these are as follows:
    Date Resolved: Stable (4.2.8p7) 26 Apr 2016; Dev (4.3.92) 26 Apr 2016
    References: Sec 2978 / CVE-2016-1548
    Affects: All ntp-4 releases.
-   CVSSv2: 6.4 - (AV:N/AC:L/Au:N/C:N/I:P/A:P)
-   CVSSv3: 7.2 - CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:L/A:L
+   CVSSv2: MED 6.4 - (AV:N/AC:L/Au:N/C:N/I:P/A:P)
+   CVSSv3: MED 7.2 - CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:L/A:L
    Summary: It is possible to change the time of an ntpd client or deny
    	service to an ntpd client by forcing it to change from basic
 	client/server mode to interleaved symmetric mode. An attacker
@@ -156,11 +252,12 @@ for these are as follows:
    	and separately by Jonathan Gardner of Cisco ASIG.
 
 * Sybil vulnerability: ephemeral association attack
-   -Date Resolved: Stable (4.2.8p7) 26 Apr 2016; Dev (4.3.92) 26 Apr 2016
+   Date Resolved: Stable (4.2.8p7) 26 Apr 2016; Dev (4.3.92) 26 Apr 2016
    References: Sec 3012 / CVE-2016-1549
-   -Affects: All ntp-4 releases up to, but not including 4.2.8p7, and 4.3.0 up to, but not including 4.3.92
-   CVSSv2: 3.5 - (AV:N/AC:M/Au:S/C:N/I:P/A:N)
-   CVSS3v: 5.3 - CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:H/A:N
+   Affects: All ntp-4 releases up to, but not including 4.2.8p7, and
+   	4.3.0 up to, but not including 4.3.92
+   CVSSv2: LOW 3.5 - (AV:N/AC:M/Au:S/C:N/I:P/A:N)
+   CVSS3v: MED 5.3 - CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:H/A:N
    Summary: ntpd can be vulnerable to Sybil attacks. If one is not using
    	the feature introduced in ntp-4.2.8p6 allowing an optional 4th
 	field in the ntp.keys file to specify which IPs can serve time,
@@ -182,21 +279,11 @@ Other fixes:
 * [Bug 2879] Improve NTP security against timing attacks. perlinger at ntp.org
   - integrated patches by Loganaden Velvidron <logan at ntp.org>
     with some modifications & unit tests
-* [Bug 2952] Symmetric active/passive mode is broken.  HStenn.
 * [Bug 2960] async name resolution fixes for chroot() environments.
   Reinhard Max.
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
 * [Bug 2999] out-of-bounds access in 'is_safe_filename()'. perlinger at ntp.org
-* [Bug 3007] Validate crypto-NAKs.  Danny Mayer.
-* [Bug 3009] Crafted addpeer with hmode > 7 causes OOB error. perlinger at ntp.org
-   - added more stringent checks on packet content
-* [Bug 3010] remote configuration trustedkey/requestkey values
-  are not properly validated. perlinger at ntp.org
-  - sidekick: Ignore keys that have an unsupported MAC algorithm
-    but are otherwise well-formed
-* [Bug 3011] Duplicate IPs on unconfig directives will cause an assertion botch
-  - graciously accept the same IP multiple times. perlinger at ntp.org
 * [Bug 3013] Fix for ssl_init.c SHA1 test. perlinger at ntp.org
   - Patch provided by Ch. Weisgerber
 * [Bug 3015] ntpq: config-from-file: "request contains an unprintable character"

#### ChangeSet ####
2016-04-24 09:17:06+00:00, stenn at psp-deb1.ntp.org
  [Bug 3036] autokey trips an INSIST in authistrustedip()

==== ntpd/ntp_proto.c ====
2016-04-24 09:16:18+00:00, stenn at psp-deb1.ntp.org +0 -1
  [Bug 3036] autokey trips an INSIST in authistrustedip()

--- 1.385/ntpd/ntp_proto.c	2016-04-21 19:29:09 -04:00
+++ 1.386/ntpd/ntp_proto.c	2016-04-24 05:16:18 -04:00
@@ -1782,7 +1782,6 @@ receive(
 	    case MODE_BROADCAST:	/* broadcast mode */
 	    case MODE_ACTIVE:		/* symmetric active mode */
 	    case MODE_PASSIVE:		/* symmetric passive mode */
-		DEBUG_INSIST((is_authentic == AUTH_OK) && !skeyid);
 		if (   is_authentic == AUTH_OK
 		    && skeyid
 		    && skeyid <= NTP_MAXKEY

#### ChangeSet ####
2016-04-21 23:42:43+00:00, stenn at psp-deb1.ntp.org
  Update 3007

==== NEWS ====
2016-04-21 23:42:26+00:00, stenn at psp-deb1.ntp.org +1 -1
  Update 3007

--- 1.167/NEWS	2016-04-21 05:29:26 -04:00
+++ 1.168/NEWS	2016-04-21 19:42:26 -04:00
@@ -188,7 +188,7 @@ Other fixes:
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
 * [Bug 2999] out-of-bounds access in 'is_safe_filename()'. perlinger at ntp.org
-* [Bug 3007] Validate crypto-NAKs
+* [Bug 3007] Validate crypto-NAKs.  Danny Mayer.
 * [Bug 3009] Crafted addpeer with hmode > 7 causes OOB error. perlinger at ntp.org
    - added more stringent checks on packet content
 * [Bug 3010] remote configuration trustedkey/requestkey values

#### ChangeSet ####
2016-04-21 23:29:30+00:00, stenn at psp-deb1.ntp.org
  [Bug 3007] Fix bug in crypto-NAK check

==== ChangeLog ====
2016-04-21 23:29:09+00:00, stenn at psp-deb1.ntp.org +1 -1
  [Bug 3007] Fix bug in crypto-NAK check

--- 1.1817/ChangeLog	2016-04-21 05:24:31 -04:00
+++ 1.1818/ChangeLog	2016-04-21 19:29:09 -04:00
@@ -21,7 +21,7 @@ 
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
 * [Bug 2999] out-of-bounds access in 'is_safe_filename()'. perlinger at ntp.org
-* [Bug 3007] Validate crypto-NAKs
+* [Bug 3007] Validate crypto-NAKs.  Danny Mayer.
 * [Bug 3009] Crafted addpeer with hmode > 7 causes OOB error. perlinger at ntp.org
    - added more stringent checks on packet content
 * [Bug 3010] remote configuration trustedkey/requestkey values

==== ntpd/ntp_proto.c ====
2016-04-21 23:29:09+00:00, stenn at psp-deb1.ntp.org +3 -1
  [Bug 3007] Fix bug in crypto-NAK check

--- 1.384/ntpd/ntp_proto.c	2016-04-21 05:27:39 -04:00
+++ 1.385/ntpd/ntp_proto.c	2016-04-21 19:29:09 -04:00
@@ -852,7 +852,9 @@ receive(
 	 */
 	if (crypto_nak_test == INVALIDNAK) {
 		report_event(PEVNT_AUTH, peer, "Invalid_NAK");
-		peer->badNAK++;
+		if (0 != peer) {
+			peer->badNAK++;
+		}
 		msyslog(LOG_ERR, "Invalid-NAK error at %ld %s<-%s", 
 			current_time, stoa(dstadr_sin), stoa(&rbufp->recv_srcadr));
 		return;

#### ChangeSet ####
2016-04-21 09:29:31+00:00, stenn at psp-deb1.ntp.org
  [Bug 3036] autokey trips an INSIST in authistrustedip()

==== NEWS ====
2016-04-21 09:29:26+00:00, stenn at psp-deb1.ntp.org +1 -0
  [Bug 3036] autokey trips an INSIST in authistrustedip()

--- 1.166/NEWS	2016-04-18 01:37:24 -04:00
+++ 1.167/NEWS	2016-04-21 05:29:26 -04:00
@@ -216,6 +216,7 @@ Other fixes:
   - Check the initial delay calculation and reject/unpeer the broadcast
     server if the delay exceeds 50ms. Retry again after the next
     broadcast packet.
+* [Bug 3036] autokey trips an INSIST in authistrustedip().  Harlan Stenn.
 * Document ntp.key's optional IP list in authenetic.html.  Harlan Stenn.
 * Update html/xleave.html documentation.  Harlan Stenn.
 * Update ntp.conf documentation.  Harlan Stenn.

#### ChangeSet ####
2016-04-21 09:24:12+00:00, stenn at psp-deb1.ntp.org
  tweak some ntp_proto.c timestamp log messages

==== ntpd/ntp_proto.c ====
2016-04-21 09:24:04+00:00, stenn at psp-deb1.ntp.org +4 -3
  tweak some ntp_proto.c timestamp log messages

--- 1.382/ntpd/ntp_proto.c	2016-04-13 21:59:38 -04:00
+++ 1.383/ntpd/ntp_proto.c	2016-04-21 05:24:04 -04:00
@@ -1580,7 +1580,7 @@ receive(
 		if (peer->flip == 0 && !L_ISEQU(&p_org, &peer->aorg)) {
 			peer->bogusorg++;
 			msyslog(LOG_INFO,
-				"receive: KoD origin timestamp %#010x.%08x from %s does not match %#010x.%08x - ignoring.",
+				"receive: flip 0 KoD origin timestamp %#010x.%08x from %s does not match %#010x.%08x - ignoring.",
 				p_org.l_ui, p_org.l_uf,
 				ntoa(&peer->srcadr),
 				peer->aorg.l_ui, peer->aorg.l_uf);
@@ -1588,7 +1588,7 @@ receive(
 		} else if (peer->flip == 1 && !L_ISEQU(&p_org, &peer->borg)) {
 			peer->bogusorg++;
 			msyslog(LOG_INFO,
-				"receive: KoD origin timestamp %#010x.%08x from %s does not match interleave %#010x.%08x - ignoring.",
+				"receive: flip 1 KoD origin timestamp %#010x.%08x from %s does not match interleave %#010x.%08x - ignoring.",
 				p_org.l_ui, p_org.l_uf,
 				ntoa(&peer->srcadr),
 				peer->borg.l_ui, peer->borg.l_uf);
@@ -1628,8 +1628,9 @@ receive(
 			peer->bogusorg++;
 			peer->flash |= TEST2;	/* bogus */
 			msyslog(LOG_INFO,
-				"receive: Unexpected origin timestamp %#010x.%08x from %s@%s xmt %#010x.%08x",
+				"receive: Unexpected origin timestamp %#010x.%08x does not match aorg %#010x.%08x from %s@%s xmt %#010x.%08x",
 				ntohl(pkt->org.l_ui), ntohl(pkt->org.l_uf),
+				peer->aorg.l_ui, peer->aorg.l_uf,
 				hm_str, ntoa(&peer->srcadr),
 				ntohl(pkt->xmt.l_ui), ntohl(pkt->xmt.l_uf));
 			if (  !L_ISZERO(&peer->dst)

#### ChangeSet ####
2016-04-21 09:11:51+00:00, stenn at psp-deb1.ntp.org
  [Bug 3036] autokey trips an INSIST in authistrustedip()

==== ChangeLog ====
2016-04-21 09:11:42+00:00, stenn at psp-deb1.ntp.org +1 -0
  [Bug 3036] autokey trips an INSIST in authistrustedip()

--- 1.1794.1.14/ChangeLog	2016-04-12 03:44:18 -04:00
+++ 1.1794.1.15/ChangeLog	2016-04-21 05:11:42 -04:00
@@ -27,6 +27,7 @@ 
   - Check the initial delay calculation and reject/unpeer the broadcast
     server if the delay exceeds 50ms. Retry again after the next
     broadcast packet.
+* [Bug 3036] autokey trips an INSIST in authistrustedip().  Harlan Stenn.
 * Document ntp.key's optional IP list in authenetic.html.  Harlan Stenn.
 * Fix some Credit: attributions in the NEWS file.  Harlan Stenn.
 * Fix typo in html/monopt.html.  Harlan Stenn.

==== ntpd/ntp_proto.c ====
2016-04-21 09:11:42+00:00, stenn at psp-deb1.ntp.org +6 -1
  [Bug 3036] autokey trips an INSIST in authistrustedip()

--- 1.373.2.6/ntpd/ntp_proto.c	2016-04-12 03:43:00 -04:00
+++ 1.373.2.7/ntpd/ntp_proto.c	2016-04-21 05:11:42 -04:00
@@ -1606,17 +1606,22 @@ receive(
 	/*
 	 * If:
 	 *	- this is a *cast (uni-, broad-, or m-) server packet
-	 *	- and it's authenticated
+	 *	- and it's symmetric-key authenticated
 	 * then see if the sender's IP is trusted for this keyid.
 	 * If it is, great - nothing special to do here.
 	 * Otherwise, we should report and bail.
+	 *
+	 * Autokey-authenticated packets are accepted.
 	 */
 
 	switch (hismode) {
 	    case MODE_SERVER:		/* server mode */
 	    case MODE_BROADCAST:	/* broadcast mode */
 	    case MODE_ACTIVE:		/* symmetric active mode */
+		DEBUG_INSIST((is_authentic == AUTH_OK) && !skeyid);
 		if (   is_authentic == AUTH_OK
+		    && skeyid
+		    && skeyid <= NTP_MAXKEY
 		    && !authistrustedip(skeyid, &peer->srcadr)) {
 			report_event(PEVNT_AUTH, peer, "authIP");
 			peer->badauth++;

#### ChangeSet ####
2016-04-19 05:29:57+00:00, stenn at psp-deb1.ntp.org
  Windows cleanup for Bug 2978 mitigation

==== ports/winnt/include/config.h ====
2016-04-19 05:29:53+00:00, stenn at psp-deb1.ntp.org +6 -0
  Windows cleanup for Bug 2978 mitigation

--- 1.113/ports/winnt/include/config.h	2015-11-13 16:54:34 -05:00
+++ 1.114/ports/winnt/include/config.h	2016-04-19 01:29:53 -04:00
@@ -546,6 +546,12 @@ typedef unsigned long uintptr_t;
 #undef STRINGIZE
 
 #define  SIOCGIFFLAGS SIO_GET_INTERFACE_LIST /* used in ntp_io.c */
+
+/* Bug 2978 mitigation -- unless defined elsewhere, do it here*/
+#ifndef DYNAMIC_INTERLEAVE
+# define DYNAMIC_INTERLEAVE 0
+#endif
+
 /*
  * Below this line are includes which must happen after the bulk of
  * config.h is processed.  If you need to add another #include to this

#### ChangeSet ####
2016-04-18 05:38:06+00:00, stenn at psp-deb1.ntp.org
  4.2.8p7 update: [Bug 2831] Segmentation Fault in DNS lookup during startup

==== NEWS ====
2016-04-18 05:37:24+00:00, stenn at psp-deb1.ntp.org +2 -0
  4.2.8p7 update: [Bug 2831] Segmentation Fault in DNS lookup during startup

--- 1.165/NEWS	2016-04-16 03:59:08 -04:00
+++ 1.166/NEWS	2016-04-18 01:37:24 -04:00
@@ -176,6 +176,8 @@ Other fixes:
 
 Other fixes:
 
+* [Bug 2831]  Segmentation Fault in DNS lookup during startup. perlinger at ntp.org
+  - fixed yet another race condition in the threaded resolver code.
 * [Bug 2858] bool support.  Use stdbool.h when available.  HStenn.
 * [Bug 2879] Improve NTP security against timing attacks. perlinger at ntp.org
   - integrated patches by Loganaden Velvidron <logan at ntp.org>

#### ChangeSet ####
2016-04-18 06:07:25+02:00, perlinger at ntp.org
  [Bug 2831]  Segmentation Fault in DNS lookup during startup.
   - fixed yet another race condition in the threaded resolver code.

==== ChangeLog ====
2016-04-18 06:07:25+02:00, perlinger at ntp.org +2 -0
  [Bug 2831]  Segmentation Fault in DNS lookup during startup.
   - fixed yet another race condition in the threaded resolver code.

--- 1.1794.1.2/ChangeLog	2016-01-24 05:14:42 -05:00
+++ 1.1794.15.1/ChangeLog	2016-04-18 00:07:25 -04:00
@@ -1,5 +1,7 @@ 
 ---
 
+* [Bug 2831]  Segmentation Fault in DNS lookup during startup. perlinger at ntp.org
+  - fixed yet another race condition in the threaded resolver code.
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
 

==== include/ntp_worker.h ====
2016-04-18 06:07:25+02:00, perlinger at ntp.org +2 -0
  [Bug 2831]  Segmentation Fault in DNS lookup during startup.
   - fixed yet another race condition in the threaded resolver code: global locker prototype

--- 1.6/include/ntp_worker.h	2016-01-20 22:48:36 -05:00
+++ 1.7/include/ntp_worker.h	2016-04-18 00:07:25 -04:00
@@ -171,6 +171,8 @@ extern	void	kill_asyncio	(int);
 extern	void	kill_asyncio	(int);
 #endif
 
+extern void worker_global_lock(int inOrOut);
+
 # ifdef WORK_PIPE
 typedef	void	(*addremove_io_fd_func)(int, int, int);
 extern	addremove_io_fd_func		addremove_io_fd;

==== libntp/ntp_intres.c ====
2016-04-18 06:07:25+02:00, perlinger at ntp.org +20 -28
  [Bug 2831]  Segmentation Fault in DNS lookup during startup.
   - fixed yet another race condition in the threaded resolver code:
      lock global context table during access
      remove dangerous wrapper

--- 1.99/libntp/ntp_intres.c	2015-07-16 03:36:53 -04:00
+++ 1.100/libntp/ntp_intres.c	2016-04-18 00:07:25 -04:00
@@ -201,8 +201,6 @@ static	void		alloc_dnsworker_context(u_i
 /* === forward declarations === */
 static	u_int		reserve_dnschild_ctx(void);
 static	u_int		get_dnschild_ctx(void);
-static	void		alloc_dnsworker_context(u_int);
-/* static	void		free_dnsworker_context(u_int); */
 static	dnsworker_ctx *	get_worker_context(blocking_child *, u_int);
 static	void		scheduled_sleep(time_t, time_t,
 					dnsworker_ctx *);
@@ -949,47 +947,41 @@ static void
 }
 
 
-static void
-alloc_dnsworker_context(
-	u_int idx
-	)
-{
-	const size_t worker_context_sz = sizeof(*dnsworker_contexts[0]);
-
-	REQUIRE(NULL == dnsworker_contexts[idx]);
-	dnsworker_contexts[idx] = emalloc_zero(worker_context_sz);
-}
-
-
 static dnsworker_ctx *
 get_worker_context(
 	blocking_child *	c,
 	u_int			idx
 	)
 {
-	static size_t	ps = sizeof(dnsworker_contexts[0]);
-	u_int	min_new_alloc;
-	u_int	new_alloc;
-	size_t	octets;
-	size_t	new_octets;
-
+	u_int		min_new_alloc;
+	u_int		new_alloc;
+	size_t		octets;
+	size_t		new_octets;
+	dnsworker_ctx *	retv;
+
+	worker_global_lock(TRUE);
+	
 	if (dnsworker_contexts_alloc <= idx) {
 		min_new_alloc = 1 + idx;
 		/* round new_alloc up to nearest multiple of 4 */
 		new_alloc = (min_new_alloc + 4) & ~(4 - 1);
-		new_octets = new_alloc * ps;
-		octets = dnsworker_contexts_alloc * ps;
+		new_octets = new_alloc * sizeof(dnsworker_ctx*);
+		octets = dnsworker_contexts_alloc * sizeof(dnsworker_ctx*);
 		dnsworker_contexts = erealloc_zero(dnsworker_contexts,
 						   new_octets, octets);
 		dnsworker_contexts_alloc = new_alloc;
+		retv = emalloc_zero(sizeof(dnsworker_ctx));
+		dnsworker_contexts[idx] = retv;
+	} else if (NULL == (retv = dnsworker_contexts[idx])) {
+		retv = emalloc_zero(sizeof(dnsworker_ctx));
+		dnsworker_contexts[idx] = retv;
 	}
-
-	if (NULL == dnsworker_contexts[idx])
-		alloc_dnsworker_context(idx);
-	ZERO(*dnsworker_contexts[idx]);
-	dnsworker_contexts[idx]->c = c;
-
-	return dnsworker_contexts[idx];
+	
+	worker_global_lock(FALSE);
+	
+	ZERO(*retv);
+	retv->c = c;
+	return retv;
 }
 
 

==== libntp/work_fork.c ====
2016-04-18 06:07:25+02:00, perlinger at ntp.org +5 -0
  [Bug 2831]  Segmentation Fault in DNS lookup during startup.
   - fixed yet another race condition in the threaded resolver code: global locker dummy

--- 1.14/libntp/work_fork.c	2015-06-27 01:57:45 -04:00
+++ 1.14.1.1/libntp/work_fork.c	2016-04-18 00:07:25 -04:00
@@ -540,6 +540,11 @@ fork_blocking_child(
 }
 
 
+void worker_global_lock(int inOrOut)
+{
+	(void)inOrOut;
+}
+
 #else	/* !WORK_FORK follows */
 char work_fork_nonempty_compilation_unit;
 #endif

==== libntp/work_thread.c ====
2016-04-18 06:07:25+02:00, perlinger at ntp.org +23 -0
  [Bug 2831]  Segmentation Fault in DNS lookup during startup.
   - fixed yet another race condition in the threaded resolver code: create&handle global lock

--- 1.20/libntp/work_thread.c	2016-01-20 04:14:38 -05:00
+++ 1.21/libntp/work_thread.c	2016-04-18 00:07:25 -04:00
@@ -88,7 +88,27 @@ static	void	cleanup_after_child(blocking
 static	int	queue_req_pointer(blocking_child *, blocking_pipe_header *);
 static	void	cleanup_after_child(blocking_child *);
 
+static sema_type worker_mmutex;
+static sem_ref   worker_memlock;
 
+/* --------------------------------------------------------------------
+ * locking the global worker state table (and other global stuff)
+ */
+void
+worker_global_lock(
+	int inOrOut)
+{
+	if (worker_memlock) {
+		if (inOrOut)
+			wait_for_sem(worker_memlock, NULL);
+		else
+			tickle_sem(worker_memlock);
+	}
+}
+
+/* --------------------------------------------------------------------
+ * implementation isolation wrapper
+ */
 void
 exit_worker(
 	int	exitcode
@@ -724,6 +744,9 @@ prepare_child_sems(
 	blocking_child *c
 	)
 {
+	if (NULL == worker_memlock)
+		worker_memlock = create_sema(&worker_mmutex, 1, 1);
+	
 	c->accesslock           = create_sema(&c->sem_table[0], 1, 1);
 	c->workitems_pending    = create_sema(&c->sem_table[1], 0, 0);
 	c->wake_scheduled_sleep = create_sema(&c->sem_table[2], 0, 1);

#### ChangeSet ####
2016-04-16 07:59:23+00:00, stenn at psp-deb1.ntp.org
  type

==== NEWS ====
2016-04-16 07:59:08+00:00, stenn at psp-deb1.ntp.org +1 -1
  type

--- 1.164/NEWS	2016-04-14 05:03:09 -04:00
+++ 1.165/NEWS	2016-04-16 03:59:08 -04:00
@@ -40,7 +40,7 @@ following 9 low- and medium-severity vul
 * Clients that receive a KoD should validate the origin timestamp field.
    References: Sec 2901 / CVE-2015-7704, CVE-2015-7705
    Affects: All ntp-4 releases up to, but not including 4.2.8p7,
-   Summary: Improvements to the fixes incorporated in t 4.2.8p4 and 4.3.77.
+   Summary: Improvements to the fixes incorporated into 4.2.8p4 and 4.3.77.
 
 * peer associations were broken by the fix for NtpBug2899
    Date Resolved: Stable (4.2.8p7) 26 Apr 2016; Dev (4.3.92) 26 Apr 2016

#### ChangeSet ####
2016-04-14 09:03:11+00:00, stenn at psp-deb1.ntp.org
  Update the NEWS file for 4.2.8p7

==== NEWS ====
2016-04-14 09:03:09+00:00, stenn at psp-deb1.ntp.org +7 -0
  Update the NEWS file for 4.2.8p7

--- 1.163/NEWS	2016-04-13 21:46:45 -04:00
+++ 1.164/NEWS	2016-04-14 05:03:09 -04:00
@@ -8,6 +8,13 @@ In addition to bug fixes and enhancement
 When building NTP from source, there is a new configure option
 available, --enable-dynamic-interleave.  More information on this below.
 
+Also note that ntp-4.2.8p7 logs more "unexpected events" than previous
+versions of ntp.  These events have almost certainly happened in the
+past, it's just that they were silently counted and not logged.  With
+the increasing awareness around security, we feel it's better to clearly
+log these events to help detect abusive behavior.  This increased
+logging can also help detect other problems, too.
+
 In addition to bug fixes and enhancements, this release fixes the
 following 9 low- and medium-severity vulnerabilities:
 

#### ChangeSet ####
2016-04-14 01:59:45+00:00, stenn at psp-deb1.ntp.org
  [Sec 2978] Interleave can be partially triggered

==== ChangeLog ====
2016-04-14 01:59:38+00:00, stenn at psp-deb1.ntp.org +1 -0
  [Sec 2978] Interleave can be partially triggered

--- 1.1814/ChangeLog	2016-04-12 05:01:02 -04:00
+++ 1.1815/ChangeLog	2016-04-13 21:59:38 -04:00
@@ -4,6 +4,7 @@ 
 * [Sec 2936] Skeleton Key: Any system knowing the trusted key can serve
   time. Include passive servers in this check. HStenn.
 * [Sec 2945] Additional KoD packet checks.  HStenn.
+* [Sec 2978] Interleave can be partially triggered.  HStenn.
 * [Sec 3008] Always check the return value of ctl_getitem().
   - initial work by HStenn
   - Additional cleanup of ctl_getitem by perlinger at ntp.org

==== configure.ac ====
2016-04-14 01:59:38+00:00, stenn at psp-deb1.ntp.org +22 -0
  [Sec 2978] Interleave can be partially triggered

--- 1.604/configure.ac	2016-02-29 18:00:47 -05:00
+++ 1.605/configure.ac	2016-04-13 21:59:38 -04:00
@@ -4342,6 +4342,28 @@ NTP_UNITYBUILD
 esac
 AC_MSG_RESULT([$ntp_ok])
 
+###
+
+AC_MSG_CHECKING([if we want dynamic interleave support])
+AC_ARG_ENABLE(
+    [dynamic-interleave],
+    [AS_HELP_STRING(
+	[--enable-dynamic-interleave],
+	[- dynamic interleave support]
+    )],
+    [ntp_ok=$enableval],
+    [ntp_ok=no]
+)
+ntp_dynamic_interleave=0
+case "$ntp_ok" in
+ yes)
+    ntp_dynamic_interleave=1
+    ;;
+esac
+AC_DEFINE_UNQUOTED([DYNAMIC_INTERLEAVE], [$ntp_dynamic_interleave],
+    [support dynamic interleave?])
+AC_MSG_RESULT([$ntp_ok])
+
 NTP_UNITYBUILD
 
 dnl  gtest is needed for our tests subdirs. It would be nice if we could

==== ntpd/ntp_proto.c ====
2016-04-14 01:59:38+00:00, stenn at psp-deb1.ntp.org +11 -3
  [Sec 2978] Interleave can be partially triggered

--- 1.381/ntpd/ntp_proto.c	2016-04-12 04:18:50 -04:00
+++ 1.382/ntpd/ntp_proto.c	2016-04-13 21:59:38 -04:00
@@ -25,7 +25,7 @@ 
 #include <unistd.h>
 #endif
 
-/*[Bug 3031] define automatic broadcastdelay cutoff preset */
+/* [Bug 3031] define automatic broadcastdelay cutoff preset */
 #ifndef BDELAY_DEFAULT
 # define BDELAY_DEFAULT (-0.050)
 #endif
@@ -177,6 +177,8 @@ int kiss_code_check(u_char hisleap, u_ch
 int unpeer_crypto_nak_early	= 1;	/* crypto_NAK (TEST5) */
 int unpeer_digest_early		= 1;	/* bad digest (TEST5) */
 
+int dynamic_interleave = DYNAMIC_INTERLEAVE;	/* Bug 2978 mitigation */
+
 int kiss_code_check(u_char hisleap, u_char hisstratum, u_char hismode, u_int32 refid);
 enum nak_error_codes valid_NAK(struct peer *peer, struct recvbuf *rbufp, u_char hismode);
 static	double	root_distance	(struct peer *);
@@ -1633,8 +1635,14 @@ receive(
 			if (  !L_ISZERO(&peer->dst)
 			    && L_ISEQU(&p_org, &peer->dst)) {
 				/* Might be the start of an interleave */
-				peer->flip = 1;
-				report_event(PEVNT_XLEAVE, peer, NULL);
+				if (dynamic_interleave) {
+					peer->flip = 1;
+					report_event(PEVNT_XLEAVE, peer, NULL);
+				} else {
+					msyslog(LOG_INFO,
+						"receive: Dynamic interleave from %s@%s denied",
+						hm_str, ntoa(&peer->srcadr));
+				}
 			}
 		} else {
 			L_CLR(&peer->aorg);

#### ChangeSet ####
2016-04-14 01:46:50+00:00, stenn at psp-deb1.ntp.org
  Update the NEWS file for 4.2.8p7

==== NEWS ====
2016-04-14 01:46:45+00:00, stenn at psp-deb1.ntp.org +168 -26
  Update the NEWS file for 4.2.8p7

--- 1.162/NEWS	2016-04-12 18:29:12 -04:00
+++ 1.163/NEWS	2016-04-13 21:46:45 -04:00
@@ -5,16 +5,19 @@ In addition to bug fixes and enhancement
 
 Severity: MEDIUM
 
+When building NTP from source, there is a new configure option
+available, --enable-dynamic-interleave.  More information on this below.
+
 In addition to bug fixes and enhancements, this release fixes the
-following X low- and Y medium-severity vulnerabilities:
+following 9 low- and medium-severity vulnerabilities:
 
 * Improve NTP security against buffer comparison timing attacks
-   Date Resolved: Stable (4.2.8p7) 26 Apr 2016; Dev (4.3.XX) 26 Apr 2016
+   Date Resolved: Stable (4.2.8p7) 26 Apr 2016; Dev (4.3.92) 26 Apr 2016
    References: Sec 2879 / CVE-2016-1550
    Affects: All ntp-4 releases up to, but not including 4.2.8p7, and
-	4.3.0 up to, but not including 4.3.XX
-   CVSS2: (AV:L/AC:H/Au:N/C:P/I:P/A:N) Base Score: 2.6 - LOW
-   CVSS3: (CVSS:3.0/AV:L/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N) Base Score: 4.0 - MEDIUM
+	4.3.0 up to, but not including 4.3.92
+   CVSSv2: 2.6 - (AV:L/AC:H/Au:N/C:P/I:P/A:N)
+   CVSSv3: 4.0 - CVSS:3.0/AV:L/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N
    Summary: Packet authentication tests have been performed using
 	memcmp() or possibly bcmp(), and it is potentially possible
 	for a local or perhaps LAN-based attacker to send a packet with
@@ -27,30 +30,142 @@ XXX: HMS: the zero origin stuff is reall
    Credit: This weakness was discovered independently by Loganaden
    	Velvindron, and Matthew Van Gundy and Stephen Gray of Cisco ASIG.
 
-XXX: HMS: the zero origin stuff is really not 2901.  But check to be sure.
 * Clients that receive a KoD should validate the origin timestamp field.
-    Date Resolved: Stable (4.2.8p4) 21 Oct 2015
-    References: Sec 2901 / CVE-2015-7704 / CVE-2015-7705
-    Affects: All ntp-4 releases up to, but not including 4.2.8p4, and 4.3.0 up to, but not including 4.3.77
-    CVSS: (AV:N/AC:M/Au:N/C:N/I:N/A:P) Base Score: 4.3-5.0 at worst
-    Summary: An ntpd client that honors Kiss-of-Death responses will honor KoD messages that have been forged by an attacker, causing it to delay or stop querying its servers for time updates. Also, an attacker can forge packets that claim to be from the target and send them to servers often enough that a server that implements KoD rate limiting will send the target machine a KoD response to attempt to reduce the rate of incoming packets, or it may also trigger a firewall block at the server for packets from the target machine. For either of these attacks to succeed, the attacker must know what servers the target is communicating with. An attacker can be anywhere on the Internet and can frequently learn the identity of the target's time source by sending the target a time query.
-    Mitigation:
+   References: Sec 2901 / CVE-2015-7704, CVE-2015-7705
+   Affects: All ntp-4 releases up to, but not including 4.2.8p7,
+   Summary: Improvements to the fixes incorporated in t 4.2.8p4 and 4.3.77.
+
+* peer associations were broken by the fix for NtpBug2899
+   Date Resolved: Stable (4.2.8p7) 26 Apr 2016; Dev (4.3.92) 26 Apr 2016
+   References: Sec 2952 / CVE-2015-7704
+   Affects: All ntp-4 releases up to, but not including 4.2.8p7, and
+   	4.3.0 up to, but not including 4.3.92
+   CVSSv2: 4.3 - (AV:N/AC:M/Au:N/C:N/I:N/A:P)
+   Summary: The fix for NtpBug2952 in ntp-4.2.8p5 to address broken peer
+   	associations did not address all of the issues.
+   Mitigation:
         Implement BCP-38.
-        Upgrade to 4.2.8p4, or later, from the NTP Project Download Page or the NTP Public Services Project Download Page
-        If you can't upgrade, restrict who can query ntpd to learn who its servers are, and what IPs are allowed to ask your system for the time. This mitigation is heavy-handed.
+        Upgrade to 4.2.8p7, or later, from the NTP Project Download Page
+	    or the NTP Public Services Project Download Page
+        If you can't upgrade, use "server" associations instead of
+	    "peer" associations.
         Monitor your ntpd instances. 
-    Note: 4.2.8p4 protects against the first attack. For the second attack, all we can do is warn when it is happening, which we do in 4.2.8p4.
-    Credit: This weakness was discovered by Aanchal Malhotra, Issac E. Cohen, and Sharon Goldberg of Boston University. 
-
-***
-* [Sec 2901] KoD packets must have non-zero transmit timestamps.  HStenn.
-* [Sec 2936] Skeleton Key: Any system knowing the trusted key can serve
-  time. Include passive servers in this check. HStenn.
-* [Sec 2945] Additional KoD packet checks.  HStenn.
-* [Sec 3008] Always check the return value of ctl_getitem().
-  - initial work by HStenn
-  - Additional cleanup of ctl_getitem by perlinger at ntp.org
-* [Sec 3020] Refclock impersonation.  HStenn.
+   Credit: This problem was discovered by Michael Tatarinov.
+
+* Skeleton key: passive server with trusted key can serve time.
+   References: Sec 2936 / CVE-2015-7974
+   Affects: All ntp-4 releases up to, but not including 4.2.8p7,
+   Summary: Improvements to the fixes incorporated in t 4.2.8p6 and 4.3.90.
+
+* Zero origin timestamp bypass: Additional KoD checks.
+   References: Sec 2945 / CVE-2015-8138
+   Affects: All ntp-4 releases up to, but not including 4.2.8p7,
+   Summary: Improvements to the fixes incorporated in t 4.2.8p6 and 4.3.92.
+
+* ctl_getitem() return value not always checked
+   Date Resolved: Stable (4.2.8p7) 26 Apr 2016; Dev (4.3.92) 26 Apr 2016
+   References: Sec 3008 / CVE-2016-2519
+   Affects: All ntp-4 releases up to, but not including 4.2.8p7, and
+	4.3.0 up to, but not including 4.3.92
+   CVSSv2: 4.9 - (AV:N/AC:H/Au:S/C:N/I:N/A:C)
+   CVSSv3: 4.2 - CVSS:3.0/AV:N/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:H
+   Summary: ntpq and ntpdc can be used to store and retrieve information
+   	in ntpd. It is possible to store a data value that is larger
+	than the size of the buffer that the ctl_getitem() function of
+	ntpd uses to report the return value. If the length of the
+	requested data value returned by ctl_getitem() is too large,
+	the value NULL is returned instead. There are 2 cases where the
+	return value from ctl_getitem() was not directly checked to make
+	sure it's not NULL, but there are subsequent INSIST() checks
+	that make sure the return value is not NULL. There are no data
+	values ordinarily stored in ntpd that would exceed this buffer
+	length. But if one has permission to store values and one stores
+	a value that is "too large", then ntpd will abort if an attempt
+	is made to read that oversized value.
+    Mitigation:
+        Implement BCP-38.
+        Upgrade to 4.2.8p7, or later, from the NTP Project Download Page
+	    or the NTP Public Services Project Download Page
+        Properly monitor your ntpd instances.
+    Credit: This weakness was discovered by Yihan Lian of the Cloud
+    	Security Team, Qihoo 360. 
+
+* Refclock impersonation vulnerability
+   Date Resolved: Stable (4.2.8p7) 26 Apr 2016; Dev (4.3.92) 26 Apr 2016
+   References: Sec 3020 / CVE-2016-1551
+   Affects: On a very limited number of OSes, all NTP releases up to but
+	not including 4.2.8p7, and 4.3.0 up to but not including 4.3.92.
+	By "very limited number of OSes" we mean no general-purpose OSes
+	have yet been identified that have this vulnerability.
+   CVSSv2: 2.6 - (AV:N/AC:H/Au:N/C:N/I:P/A:N)
+   CVSSv3: 3.7 - CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N
+   Summary: While most OSes implement martian packet filtering in their
+   	network stack, at least regarding 127.0.0.0/8, some will allow
+	packets claiming to be from 127.0.0.0/8 that arrive over a
+	physical network. On these OSes, if ntpd is configured to use a
+	reference clock an attacker can inject packets over the network
+	that look like they are coming from that reference clock.
+   Mitigation:
+        Implement martian packet filtering and BCP-38.
+        Configure ntpd to use an adequate number of time sources.
+        Upgrade to 4.2.8p7, or later, from the NTP Project Download Page
+	    or the NTP Public Services Project Download Page
+        If you are unable to upgrade and if you are running an OS that
+	    has this vulnerability, implement martian packet filters and
+	    lobby your OS vendor to fix this problem, or run your
+	    refclocks on computers that use OSes that are not vulnerable
+	    to these attacks and have your vulnerable machines get their
+	    time from protected resources.
+        Properly monitor your ntpd instances.
+   Credit: This weakness was discovered by Matt Street and others of
+   	Cisco ASIG. 
+
+Two other vulnerabilities have been reported, and the mitigations
+for these are as follows:
+
+* Interleave-pivot
+   Date Resolved: Stable (4.2.8p7) 26 Apr 2016; Dev (4.3.92) 26 Apr 2016
+   References: Sec 2978 / CVE-2016-1548
+   Affects: All ntp-4 releases.
+   CVSSv2: 6.4 - (AV:N/AC:L/Au:N/C:N/I:P/A:P)
+   CVSSv3: 7.2 - CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:L/A:L
+   Summary: It is possible to change the time of an ntpd client or deny
+   	service to an ntpd client by forcing it to change from basic
+	client/server mode to interleaved symmetric mode. An attacker
+	can spoof a packet from a legitimate ntpd server with an origin
+	timestamp that matches the peer->dst timestamp recorded for that
+	server. After making this switch, the client will reject all
+	future legitimate server responses. It is possible to force the
+	victim client to move time after the mode has been changed.
+	ntpq gives no indication that the mode has been switched.
+   Mitigation:
+        Implement BCP-38.
+        Upgrade to 4.2.8p7, or later, from the NTP Project Download Page
+	    or the NTP Public Services Project Download Page.  These
+	    versions will not dynamically "flip" into interleave mode
+	    unless configured to do so.
+        Properly monitor your ntpd instances.
+   Credit: This weakness was discovered by Miroslav Lichvar of RedHat
+   	and separately by Jonathan Gardner of Cisco ASIG.
+
+* Sybil vulnerability: ephemeral association attack
+   -Date Resolved: Stable (4.2.8p7) 26 Apr 2016; Dev (4.3.92) 26 Apr 2016
+   References: Sec 3012 / CVE-2016-1549
+   -Affects: All ntp-4 releases up to, but not including 4.2.8p7, and 4.3.0 up to, but not including 4.3.92
+   CVSSv2: 3.5 - (AV:N/AC:M/Au:S/C:N/I:P/A:N)
+   CVSS3v: 5.3 - CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:H/A:N
+   Summary: ntpd can be vulnerable to Sybil attacks. If one is not using
+   	the feature introduced in ntp-4.2.8p6 allowing an optional 4th
+	field in the ntp.keys file to specify which IPs can serve time,
+	a malicious authenticated peer can create arbitrarily-many
+	ephemeral associations in order to win the clock selection of
+	ntpd and modify a victim's clock.
+   Mitigation:
+        Implement BCP-38.
+        Use the 4th field in the ntp.keys file to specify which IPs
+	    can be time servers.
+        Properly monitor your ntpd instances.
+   Credit: This weakness was discovered by Matthew Van Gundy of Cisco ASIG. 
 
 Other fixes:
 
@@ -100,6 +215,33 @@ Other fixes:
 * Add README.pullrequests.  Harlan Stenn.
 * Cleanup to include/ntp.h.  Harlan Stenn.
 
+New option to 'configure':
+
+While looking in to the issues around Bug 2978, the "interleave pivot"
+issue, it became clear that there are some intricate and unresolved
+issues with interleave operations.  We also realized that the interleave
+protocol was never added to the NTPv4 Standard, and it should have been.
+
+Interleave mode was first released in July of 2008, and can be engaged
+in two ways.  Any 'peer' and 'broadcast' lines in the ntp.conf file may
+contain the 'xleave' option, which will expressly enable interlave mode
+for that association.  Additionally, if a time packet arrives and is
+found inconsistent with normal protocol behavior but has certain
+characteristics that are compatible with interleave mode, NTP will
+dynamically switch to interleave mode.  With sufficient knowledge, an
+attacker can send a crafted forged packet to an NTP instance that
+triggers only one side to enter interleaved mode.
+
+To prevent this attack until we can thoroughly document, describe,
+fix, and test the dynamic interleave mode, we've added a new
+'configure' option to the build process:
+
+ --enable-dynamic-interleave
+
+This option controls whether or not NTP will, if conditions are right,
+engage dynamic interleave mode.  Dynamic interleave mode is disabled by
+default in ntp-4.2.8p7.
+
 ---
 NTP 4.2.8p6 (Harlan Stenn <stenn at ntp.org>, 2016/01/20) 
 

#### ChangeSet ####
2016-04-12 22:29:18+00:00, stenn at psp-deb1.ntp.org
  4.2.8p7 prep

==== NEWS ====
2016-04-12 22:29:12+00:00, stenn at psp-deb1.ntp.org +105 -5
  4.2.8p7 prep

--- 1.161/NEWS	2016-02-13 04:15:40 -05:00
+++ 1.162/NEWS	2016-04-12 18:29:12 -04:00
@@ -1,13 +1,114 @@ 
 ---
+NTP 4.2.8p7 (Harlan Stenn <stenn at ntp.org>, 2016/04/26) 
 
-NTP 4.2.8p6
+Focus: Security, Bug fixes, enhancements.
+
+Severity: MEDIUM
+
+In addition to bug fixes and enhancements, this release fixes the
+following X low- and Y medium-severity vulnerabilities:
+
+* Improve NTP security against buffer comparison timing attacks
+   Date Resolved: Stable (4.2.8p7) 26 Apr 2016; Dev (4.3.XX) 26 Apr 2016
+   References: Sec 2879 / CVE-2016-1550
+   Affects: All ntp-4 releases up to, but not including 4.2.8p7, and
+	4.3.0 up to, but not including 4.3.XX
+   CVSS2: (AV:L/AC:H/Au:N/C:P/I:P/A:N) Base Score: 2.6 - LOW
+   CVSS3: (CVSS:3.0/AV:L/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N) Base Score: 4.0 - MEDIUM
+   Summary: Packet authentication tests have been performed using
+	memcmp() or possibly bcmp(), and it is potentially possible
+	for a local or perhaps LAN-based attacker to send a packet with
+	an authentication payload and indirectly observe how much of
+	the digest has matched.
+   Mitigation:
+	Upgrade to 4.2.8p7, or later, from the NTP Project Download Page
+	    or the NTP Public Services Project Download Page.
+	Properly monitor your ntpd instances.
+   Credit: This weakness was discovered independently by Loganaden
+   	Velvindron, and Matthew Van Gundy and Stephen Gray of Cisco ASIG.
+
+XXX: HMS: the zero origin stuff is really not 2901.  But check to be sure.
+* Clients that receive a KoD should validate the origin timestamp field.
+    Date Resolved: Stable (4.2.8p4) 21 Oct 2015
+    References: Sec 2901 / CVE-2015-7704 / CVE-2015-7705
+    Affects: All ntp-4 releases up to, but not including 4.2.8p4, and 4.3.0 up to, but not including 4.3.77
+    CVSS: (AV:N/AC:M/Au:N/C:N/I:N/A:P) Base Score: 4.3-5.0 at worst
+    Summary: An ntpd client that honors Kiss-of-Death responses will honor KoD messages that have been forged by an attacker, causing it to delay or stop querying its servers for time updates. Also, an attacker can forge packets that claim to be from the target and send them to servers often enough that a server that implements KoD rate limiting will send the target machine a KoD response to attempt to reduce the rate of incoming packets, or it may also trigger a firewall block at the server for packets from the target machine. For either of these attacks to succeed, the attacker must know what servers the target is communicating with. An attacker can be anywhere on the Internet and can frequently learn the identity of the target's time source by sending the target a time query.
+    Mitigation:
+        Implement BCP-38.
+        Upgrade to 4.2.8p4, or later, from the NTP Project Download Page or the NTP Public Services Project Download Page
+        If you can't upgrade, restrict who can query ntpd to learn who its servers are, and what IPs are allowed to ask your system for the time. This mitigation is heavy-handed.
+        Monitor your ntpd instances. 
+    Note: 4.2.8p4 protects against the first attack. For the second attack, all we can do is warn when it is happening, which we do in 4.2.8p4.
+    Credit: This weakness was discovered by Aanchal Malhotra, Issac E. Cohen, and Sharon Goldberg of Boston University. 
+
+***
+* [Sec 2901] KoD packets must have non-zero transmit timestamps.  HStenn.
+* [Sec 2936] Skeleton Key: Any system knowing the trusted key can serve
+  time. Include passive servers in this check. HStenn.
+* [Sec 2945] Additional KoD packet checks.  HStenn.
+* [Sec 3008] Always check the return value of ctl_getitem().
+  - initial work by HStenn
+  - Additional cleanup of ctl_getitem by perlinger at ntp.org
+* [Sec 3020] Refclock impersonation.  HStenn.
+
+Other fixes:
+
+* [Bug 2858] bool support.  Use stdbool.h when available.  HStenn.
+* [Bug 2879] Improve NTP security against timing attacks. perlinger at ntp.org
+  - integrated patches by Loganaden Velvidron <logan at ntp.org>
+    with some modifications & unit tests
+* [Bug 2952] Symmetric active/passive mode is broken.  HStenn.
+* [Bug 2960] async name resolution fixes for chroot() environments.
+  Reinhard Max.
+* [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
+* [Bug 2995] Fixes to compile on Windows
+* [Bug 2999] out-of-bounds access in 'is_safe_filename()'. perlinger at ntp.org
+* [Bug 3007] Validate crypto-NAKs
+* [Bug 3009] Crafted addpeer with hmode > 7 causes OOB error. perlinger at ntp.org
+   - added more stringent checks on packet content
+* [Bug 3010] remote configuration trustedkey/requestkey values
+  are not properly validated. perlinger at ntp.org
+  - sidekick: Ignore keys that have an unsupported MAC algorithm
+    but are otherwise well-formed
+* [Bug 3011] Duplicate IPs on unconfig directives will cause an assertion botch
+  - graciously accept the same IP multiple times. perlinger at ntp.org
+* [Bug 3013] Fix for ssl_init.c SHA1 test. perlinger at ntp.org
+  - Patch provided by Ch. Weisgerber
+* [Bug 3015] ntpq: config-from-file: "request contains an unprintable character"
+  - A change related to [Bug 2853] forbids trailing white space in
+    remote config commands. perlinger at ntp.org
+* [Bug 3019] NTPD stops processing packets after ERROR_HOST_UNREACHABLE
+  - report and patch from Aleksandr Kostikov.
+  - Overhaul of Windows IO completion port handling. perlinger at ntp.org
+* [Bug 3022] authkeys.c should be refactored. perlinger at ntp.org
+  - fixed memory leak in access list (auth[read]keys.c)
+  - refactored handling of key access lists (auth[read]keys.c)
+  - reduced number of error branches (authreadkeys.c)
+* [Bug 3023] ntpdate cannot correct dates in the future. perlinger at ntp.org
+* [Bug 3030] ntpq needs a general way to specify refid output format.  HStenn.
+* [Bug 3031] ntp broadcastclient unable to synchronize to an server
+             when the time of server changed. perlinger at ntp.org
+  - Check the initial delay calculation and reject/unpeer the broadcast
+    server if the delay exceeds 50ms. Retry again after the next
+    broadcast packet.
+* Document ntp.key's optional IP list in authenetic.html.  Harlan Stenn.
+* Update html/xleave.html documentation.  Harlan Stenn.
+* Update ntp.conf documentation.  Harlan Stenn.
+* Fix some Credit: attributions in the NEWS file.  Harlan Stenn.
+* Fix typo in html/monopt.html.  Harlan Stenn.
+* Add README.pullrequests.  Harlan Stenn.
+* Cleanup to include/ntp.h.  Harlan Stenn.
+
+---
+NTP 4.2.8p6 (Harlan Stenn <stenn at ntp.org>, 2016/01/20) 
 
 Focus: Security, Bug fixes, enhancements.
 
 Severity: MEDIUM
 
 In addition to bug fixes and enhancements, this release fixes the
-following X low- and Y medium-severity vulnerabilities:
+following 1 low- and 8 medium-severity vulnerabilities:
 
 * Potential Infinite Loop in 'ntpq'
    Date Resolved: Stable (4.2.8p6) 19 Jan 2016; Dev (4.3.90) 19 Jan 2016
@@ -253,9 +354,8 @@ Other fixes:
 * Make leapsec_query debug messages less verbose.  Harlan Stenn.
 
 ---
+NTP 4.2.8p5 (Harlan Stenn <stenn at ntp.org>, 2016/01/07) 
 
-NTP 4.2.8p5
-
 Focus: Security, Bug fixes, enhancements.
 
 Severity: MEDIUM
@@ -354,7 +454,7 @@ NTP 4.2.8p4
 * Quiet a warning from clang.  Harlan Stenn.
 
 ---
-NTP 4.2.8p4
+NTP 4.2.8p4 (Harlan Stenn <stenn at ntp.org>, 2015/10/21) 
 
 Focus: Security, Bug fixes, enhancements.
 

#### ChangeSet ####
2016-04-12 09:01:09+00:00, stenn at psp-deb1.ntp.org
  Credit Aleksandr Kostikov on bug 3019

==== ChangeLog ====
2016-04-12 09:01:02+00:00, stenn at psp-deb1.ntp.org +1 -0
  Credit Aleksandr Kostikov on bug 3019

--- 1.1813/ChangeLog	2016-04-12 04:18:49 -04:00
+++ 1.1814/ChangeLog	2016-04-12 05:01:02 -04:00
@@ -33,6 +33,7 @@ 
   - A change related to [Bug 2853] forbids trailing white space in
     remote config commands. perlinger at ntp.org
 * [Bug 3019] NTPD stops processing packets after ERROR_HOST_UNREACHABLE
+  - report and patch from Aleksandr Kostikov.
   - Overhaul of Windows IO completion port handling. perlinger at ntp.org
 * [Bug 3022] authkeys.c should be refactored. perlinger at ntp.org
   - fixed memory leak in access list (auth[read]keys.c)

#### ChangeSet ####
2016-04-12 07:43:08+00:00, stenn at psp-deb1.ntp.org
  comment tweak

==== ntpd/ntp_proto.c ====
2016-04-12 07:43:00+00:00, stenn at psp-deb1.ntp.org +1 -1
  comment tweak

--- 1.373.2.5/ntpd/ntp_proto.c	2016-04-01 13:18:24 -04:00
+++ 1.373.2.6/ntpd/ntp_proto.c	2016-04-12 03:43:00 -04:00
@@ -1353,7 +1353,7 @@ receive(
 				++bail;
 			}
 
-			/* not monotonic? There's a trickser out there! */
+			/* Alert if time from the server is non-monotonic */
 			tdiff = p_xmt;
 			L_SUB(&tdiff, &peer->bxmt);
 			if (tdiff.l_i < 0) {

#### ChangeSet ####
2016-04-11 20:26:29-07:00, harlan at max.pfcs.com
  [Bug 2952] Symmetric active/passive mode is broken

==== ChangeLog ====
2016-04-11 20:26:11-07:00, harlan at max.pfcs.com +1 -0
  [Bug 2952] Symmetric active/passive mode is broken

--- 1.1811/ChangeLog	2016-04-11 22:56:02 -04:00
+++ 1.1812/ChangeLog	2016-04-11 23:26:11 -04:00
@@ -12,6 +12,7 @@ 
 * [Bug 2879] Improve NTP security against timing attacks. perlinger at ntp.org
   - integrated patches by Loganaden Velvidron <logan at ntp.org>
     with some modifications & unit tests
+* [Bug 2952] Symmetric active/passive mode is broken.  HStenn.
 * [Bug 2960] async name resolution fixes for chroot() environments.
   Reinhard Max.
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org

==== ntpd/ntp_proto.c ====
2016-04-11 20:26:17-07:00, harlan at max.pfcs.com +21 -12
  [Bug 2952] Symmetric active/passive mode is broken

--- 1.379/ntpd/ntp_proto.c	2016-02-21 22:39:18 -05:00
+++ 1.380/ntpd/ntp_proto.c	2016-04-11 23:26:17 -04:00
@@ -172,7 +172,8 @@ static int kiss_code_check(u_char hislea
 int unpeer_crypto_nak_early	= 1;	/* crypto_NAK (TEST5) */
 int unpeer_digest_early		= 1;	/* bad digest (TEST5) */
 
-static int kiss_code_check(u_char hisleap, u_char hisstratum, u_char hismode, u_int32 refid);
+int kiss_code_check(u_char hisleap, u_char hisstratum, u_char hismode, u_int32 refid);
+enum nak_error_codes valid_NAK(struct peer *peer, struct recvbuf *rbufp, u_char hismode);
 static	double	root_distance	(struct peer *);
 static	void	clock_combine	(peer_select *, int, int);
 static	void	peer_xmit	(struct peer *);
@@ -1592,9 +1593,9 @@ receive(
 	 * If there is no origin timestamp, it's either an initial packet
 	 * or we've already received a response to our query.  Of course,
 	 * should 'aorg' be all-zero because this really was the original
-	 * transmit timestamp, we'll drop the reply.  There is a window of
-	 * one nanosecond once every 136 years' time where this is possible.
-	 * We currently ignore this situation.
+	 * transmit timestamp, we'll ignore this reply.  There is a window
+	 * of one nanosecond once every 136 years' time where this is
+	 * possible.  We currently ignore this situation.
 	 *
 	 * Otherwise, check for bogus packet in basic mode.
 	 * If it is bogus, switch to interleaved mode and resynchronize,
@@ -1605,14 +1606,23 @@ receive(
 	 * be from us, attempting to cause our server to KoD us.
 	 */
 	} else if (peer->flip == 0) {
-		if (    L_ISZERO(&peer->aorg)
-		    || !L_ISEQU(&p_org, &peer->aorg)) {
+		INSIST(0 != hisstratum);
+		if (0) {
+		} else if (L_ISZERO(&p_org)) {
+			msyslog(LOG_INFO,
+				"receive: Got 0 origin timestamp from %s@%s xmt %#010x.%08x",
+				hm_str, ntoa(&peer->srcadr),
+				ntohl(pkt->xmt.l_ui), ntohl(pkt->xmt.l_uf));
+			L_CLR(&peer->aorg);
+		} else if (!L_ISEQU(&p_org, &peer->aorg)) {
+			/* are there cases here where we should bail? */
+			/* Should we set TEST2 if we decide to try xleave? */
 			peer->bogusorg++;
 			peer->flash |= TEST2;	/* bogus */
 			msyslog(LOG_INFO,
-				"receive: Unexpected origin timestamp %#010x.%08x from %s xmt %#010x.%08x",
+				"receive: Unexpected origin timestamp %#010x.%08x from %s@%s xmt %#010x.%08x",
 				ntohl(pkt->org.l_ui), ntohl(pkt->org.l_uf),
-				ntoa(&peer->srcadr),
+				hm_str, ntoa(&peer->srcadr),
 				ntohl(pkt->xmt.l_ui), ntohl(pkt->xmt.l_uf));
 			if (  !L_ISZERO(&peer->dst)
 			    && L_ISEQU(&p_org, &peer->dst)) {
@@ -1620,10 +1630,9 @@ receive(
 				peer->flip = 1;
 				report_event(PEVNT_XLEAVE, peer, NULL);
 			}
-			/* HMS: Do we want to return here if it's xleave? */
-			return; /* Bogus or possible interleave packet */
-		}
-		L_CLR(&peer->aorg);
+		} else {
+			L_CLR(&peer->aorg);
+		}
 
 	/*
 	 * Check for valid nonzero timestamp fields.

#### ChangeSet ####
2016-04-11 19:56:06-07:00, harlan at max.pfcs.com
  Cleanup to include/ntp.h

==== ChangeLog ====
2016-04-11 19:56:02-07:00, harlan at max.pfcs.com +1 -0
  Cleanup to include/ntp.h

--- 1.1810/ChangeLog	2016-03-30 06:35:59 -04:00
+++ 1.1811/ChangeLog	2016-04-11 22:56:02 -04:00
@@ -43,6 +43,7 @@ 
 * Fix some Credit: attributions in the NEWS file.  Harlan Stenn.
 * Fix typo in html/monopt.html.  Harlan Stenn.
 * Add README.pullrequests.  Harlan Stenn.
+* Cleanup to include/ntp.h.  Harlan Stenn.
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

==== include/ntp.h ====
2016-04-11 19:55:04-07:00, harlan at max.pfcs.com +7 -0
  cleanup

--- 1.217/include/ntp.h	2016-02-04 23:20:12 -05:00
+++ 1.218/include/ntp.h	2016-04-11 22:55:04 -04:00
@@ -241,6 +241,13 @@ struct interface {
 #define TEST13		0x1000	/* peer unreacable */
 #define	PEER_TEST_MASK	(TEST10 | TEST11 | TEST12 | TEST13)
 
+/*
+ * Unused flags
+ */
+#define TEST14		0x2000
+#define TEST15		0x4000
+#define TEST16		0x8000
+
 /*
  * The peer structure. Holds state information relating to the guys
  * we are peering with. Most of this stuff is from section 3.2 of the

#### ChangeSet ####
2016-04-01 19:18:25+02:00, jnperlin at nemesis.localnet
  [Bug 3031] ntp broadcastclient unable to synchronize to an server when the time of server changed
   - adjust pull cycle of broadcast client to trensmission of brodcast server

==== libntp/ntp_worker.c ====
2016-04-01 19:18:24+02:00, jnperlin at nemesis.localnet +1 -1
  [Bug 3031] ntp broadcastclient unable to synchronize to an server when the time of server changed
   - side kick: fix annoying signed/unsigned clash

--- 1.7/libntp/ntp_worker.c	2015-12-09 12:23:31 -05:00
+++ 1.7.1.1/libntp/ntp_worker.c	2016-04-01 13:18:24 -04:00
@@ -267,7 +267,7 @@ harvest_blocking_responses(void)
 void
 harvest_blocking_responses(void)
 {
-	int		idx;
+	size_t		idx;
 	blocking_child*	cp;
 	u_int		scseen, scdone;
 

==== ntpd/ntp_proto.c ====
2016-04-01 19:18:24+02:00, jnperlin at nemesis.localnet +1 -0
  [Bug 3031] ntp broadcastclient unable to synchronize to an server when the time of server changed
   - adjust pull cycle of broadcast client to trensmission of brodcast server

--- 1.373.2.4/ntpd/ntp_proto.c	2016-03-30 17:55:33 -04:00
+++ 1.373.2.5/ntpd/ntp_proto.c	2016-04-01 13:18:24 -04:00
@@ -2008,6 +2008,7 @@ process_packet(
 				return;
 			}
 		}
+		peer->nextdate = current_time + (1u << peer->ppoll) - 2u;
 		p_del = peer->delay;
 		p_offset += p_del / 2;
 

#### ChangeSet ####
2016-03-30 23:55:33+02:00, jnperlin at nemesis.localnet
  [Bug 3031] modify deadband

==== ntpd/ntp_proto.c ====
2016-03-30 23:55:33+02:00, jnperlin at nemesis.localnet +13 -12
  [Bug 3031] broadcast issues
   - modify deadband for first round after volley

--- 1.373.2.3/ntpd/ntp_proto.c	2016-03-30 16:15:02 -04:00
+++ 1.373.2.4/ntpd/ntp_proto.c	2016-03-30 17:55:33 -04:00
@@ -1308,9 +1308,9 @@ receive(
 #endif /* AUTOKEY */
 
 		if (MODE_BROADCAST == hismode) {
-			u_char poll;
-			int bail = 0;
-			l_fp tdiff;
+			int	bail = 0;
+			l_fp	tdiff;
+			u_long	deadband;
 
 			DPRINTF(2, ("receive: PROCPKT/BROADCAST: prev pkt %ld seconds ago, ppoll: %d, %d secs\n",
 				    (current_time - peer->timelastrec),
@@ -1332,27 +1332,28 @@ receive(
 					peer->ppoll, pkt->ppoll);
 			}
 
-			poll = min(peer->maxpoll,
-				   max(peer->minpoll, pkt->ppoll));
-
 			/* This is error-worthy */
-			if (pkt->ppoll != poll) {
+			if (pkt->ppoll < peer->minpoll ||
+			    pkt->ppoll > peer->maxpoll  ) {
 				msyslog(LOG_INFO, "receive: broadcast poll of %ud from %s is out-of-range (%d to %d)!",
 					pkt->ppoll, stoa(&rbufp->recv_srcadr),
 					peer->minpoll, peer->maxpoll);
 				++bail;
 			}
 
-			if (  (current_time - peer->timelastrec)
-			    < (1u << pkt->ppoll) - 1) {
-				msyslog(LOG_INFO, "receive: broadcast packet from %s arrived after %ld, not %d seconds!",
+			/* too early? worth an error, too! */
+			deadband = (1u << pkt->ppoll);
+			if (FLAG_BC_VOL & peer->flags)
+				deadband -= 3;	/* allow greater fuzz after volley */
+			if ((current_time - peer->timelastrec) < deadband) {
+				msyslog(LOG_INFO, "receive: broadcast packet from %s arrived after %lu, not %lu seconds!",
 					stoa(&rbufp->recv_srcadr),
 					(current_time - peer->timelastrec),
-					(1 << pkt->ppoll)
-					);
+					deadband);
 				++bail;
 			}
 
+			/* not monotonic? There's a trickser out there! */
 			tdiff = p_xmt;
 			L_SUB(&tdiff, &peer->bxmt);
 			if (tdiff.l_i < 0) {

#### ChangeSet ####
2016-03-30 17:28:04+00:00, perlinger at psp-deb1.ntp.org
  [Bug 3031] ntp broadcastclient unable to synchronize to an server when the time of server changed.
   - Check the initial delay calculation and reject/unpeer the broadcast server if the delay exceeds
     the cutoff limit. (default 50ms)
     Retry again after the next broadcast packet.

==== ChangeLog ====
2016-03-30 17:28:03+00:00, perlinger at psp-deb1.ntp.org +5 -0
  [Bug 3031] ntp broadcastclient unable to synchronize to an server when the time of server changed.

--- 1.1794.1.2/ChangeLog	2016-01-24 05:14:42 -05:00
+++ 1.1794.14.1/ChangeLog	2016-03-30 13:28:03 -04:00
@@ -2,6 +2,11 @@ 
 
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
+* [Bug 3031] ntp broadcastclient unable to synchronize to an server
+             when the time of server changed. perlinger at ntp.org
+  - Check the initial delay calculation and reject/unpeer the broadcast
+    server if the delay exceeds 50ms. Retry again after the next
+    broadcast packet.
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

==== ntpd/ntp_io.c ====
2016-03-30 17:28:03+00:00, perlinger at psp-deb1.ntp.org +28 -10
  [Bug 3031] ntp broadcastclient unable to synchronize to an server when the time of server changed.
   - improve/fix handling of opening broadcast sockets (-> EADDRNOTAVAIL)

--- 1.414/ntpd/ntp_io.c	2016-01-24 05:13:18 -05:00
+++ 1.414.3.1/ntpd/ntp_io.c	2016-03-30 13:28:03 -04:00
@@ -1013,8 +1013,8 @@ remove_interface(
 			stoa(&ep->bcast), ep->ifnum, ep->name);
 		close_and_delete_fd_from_list(ep->bfd);
 		ep->bfd = INVALID_SOCKET;
-		ep->flags &= ~INT_BCASTOPEN;
 	}
+	ep->flags &= ~INT_BCASTOPEN;
 
 	ninterfaces--;
 	mon_clearinterface(ep);
@@ -2565,7 +2565,7 @@ io_setbclient(void)
 			continue;
 
 		/* Only IPv4 addresses are valid for broadcast */
-		REQUIRE(IS_IPV4(&interf->sin));
+		REQUIRE(IS_IPV4(&interf->bcast));
 
 		/* Do we already have the broadcast address open? */
 		if (interf->flags & INT_BCASTOPEN) {
@@ -2593,13 +2593,31 @@ io_setbclient(void)
 			msyslog(LOG_INFO,
 				"Listen for broadcasts to %s on interface #%d %s",
 				stoa(&interf->bcast), interf->ifnum, interf->name);
-		} else {
-			/* silently ignore EADDRINUSE as we probably opened
-			   the socket already for an address in the same network */
-			if (errno != EADDRINUSE)
-				msyslog(LOG_INFO,
-					"failed to listen for broadcasts to %s on interface #%d %s",
-					stoa(&interf->bcast), interf->ifnum, interf->name);
+		} else switch (errno) {
+			/* Silently ignore EADDRINUSE as we probably
+			 * opened the socket already for an address in
+			 * the same network */
+		case EADDRINUSE:
+			/* Some systems cannot bind a socket to a broadcast
+			 * address, as that is not a valid host address. */
+		case EADDRNOTAVAIL:
+#		    ifdef SYS_WINNT	/*TODO: use for other systems, too? */
+			/* avoid recurrence here -- if we already have a
+			 * regular socket, it's quite useless to try this
+			 * again.
+			 */
+			if (interf->fd != INVALID_SOCKET) {
+				interf->flags |= INT_BCASTOPEN;
+				nif++;
+			}
+#		    endif
+			break;
+
+		default:
+			msyslog(LOG_INFO,
+				"failed to listen for broadcasts to %s on interface #%d %s",
+				stoa(&interf->bcast), interf->ifnum, interf->name);
+			break;
 		}
 	}
 	set_reuseaddr(0);
@@ -2639,8 +2657,8 @@ io_unsetbclient(void)
 				stoa(&ep->bcast), ep->ifnum, ep->name);
 			close_and_delete_fd_from_list(ep->bfd);
 			ep->bfd = INVALID_SOCKET;
-			ep->flags &= ~INT_BCASTOPEN;
 		}
+		ep->flags &= ~INT_BCASTOPEN;
 	}
 	broadcast_client_enabled = ISC_FALSE;
 }

==== ntpd/ntp_proto.c ====
2016-03-30 17:28:04+00:00, perlinger at psp-deb1.ntp.org +23 -4
  [Bug 3031] ntp broadcastclient unable to synchronize to an server when the time of server changed.
   - Check the initial delay calculation and reject/unpeer the broadcast server if the delay exceeds 50ms.
     Retry again after the next broadcast packet.
   - the absolute value of negative broadcastdelays is cutoff limit for peer removal.

--- 1.373/ntpd/ntp_proto.c	2016-01-18 06:54:51 -05:00
+++ 1.373.3.1/ntpd/ntp_proto.c	2016-03-30 13:28:04 -04:00
@@ -25,6 +25,11 @@ 
 #include <unistd.h>
 #endif
 
+/*[Bug 3031] define automatic broadcastdelay cutoff preset */
+#ifndef BDELAY_DEFAULT
+# define BDELAY_DEFAULT (-0.050)
+#endif
+
 /*
  * This macro defines the authentication state. If x is 1 authentication
  * is required; othewise it is optional.
@@ -1144,7 +1149,7 @@ receive(
 		/*
 		 * Determine whether to execute the initial volley.
 		 */
-		if (sys_bdelay != 0) {
+		if (sys_bdelay > 0.0) {
 #ifdef AUTOKEY
 			/*
 			 * If a two-way exchange is not possible,
@@ -1339,7 +1344,7 @@ receive(
 			}
 
 			if (  (current_time - peer->timelastrec)
-			    < (1 << pkt->ppoll)) {
+			    < (1u << pkt->ppoll) - 1) {
 				msyslog(LOG_INFO, "receive: broadcast packet from %s arrived after %ld, not %d seconds!",
 					stoa(&rbufp->recv_srcadr),
 					(current_time - peer->timelastrec),
@@ -1958,6 +1963,9 @@ process_packet(
 			peer->aorg = p_xmt;
 			peer->borg = peer->dst;
 			if (t34 < 0 || t34 > 1.) {
+				/* drop all if in the initial volley */
+				if (FLAG_BC_VOL & peer->flags)
+					goto bcc_init_volley_fail;
 				snprintf(statstr, sizeof(statstr),
 				    "offset %.6f delay %.6f", t21, t34);
 				report_event(PEVNT_XERR, peer, statstr);
@@ -1983,10 +1991,21 @@ process_packet(
 		 * between the unicast timestamp and the broadcast
 		 * timestamp. This works for both basic and interleaved
 		 * modes.
+		 * [Bug 3031] Don't keep this peer when the delay 
+		 * calculation gives reason to suspect clock steps.
+		 * This is assumed for delays > 50ms.
 		 */
 		if (FLAG_BC_VOL & peer->flags) {
 			peer->flags &= ~FLAG_BC_VOL;
 			peer->delay = fabs(peer->offset - p_offset) * 2;
+			DPRINTF(2, ("broadcast volley: initial delay=%.6f\n",
+				peer->delay));
+			if (peer->delay > fabs(sys_bdelay)) {
+		bcc_init_volley_fail:
+				DPRINTF(2, ("%s", "broadcast volley: initial delay exceeds limit\n"));
+				unpeer(peer);
+				return;
+			}
 		}
 		p_del = peer->delay;
 		p_offset += p_del / 2;
@@ -4333,7 +4352,7 @@ init_proto(void)
 	sys_survivors = 0;
 	sys_manycastserver = 0;
 	sys_bclient = 0;
-	sys_bdelay = 0;
+	sys_bdelay = BDELAY_DEFAULT;	/*[Bug 3031] delay cutoff */
 	sys_authenticate = 1;
 	sys_stattime = current_time;
 	orphwait = current_time + sys_orphwait;
@@ -4426,7 +4445,7 @@ proto_config(
 		break;
 
 	case PROTO_BROADDELAY:	/* default broadcast delay (bdelay) */
-		sys_bdelay = dvalue;
+		sys_bdelay = (dvalue ? dvalue : BDELAY_DEFAULT);
 		break;
 
 	case PROTO_CEILING:	/* stratum ceiling (ceiling) */

#### ChangeSet ####
2016-03-30 19:23:06+02:00, jnperlin at nemesis.localnet
  [Bug 3031]

==== ntpd/ntp_io.c ====
2016-03-30 19:23:05+02:00, jnperlin at nemesis.localnet +28 -10
  [Bug 3031]
   - improve/fix handling of opening broadcast sockets (-> EADDRNOTAVAIL)

--- 1.414/ntpd/ntp_io.c	2016-01-24 05:13:18 -05:00
+++ 1.414.2.1/ntpd/ntp_io.c	2016-03-30 13:23:05 -04:00
@@ -1013,8 +1013,8 @@ remove_interface(
 			stoa(&ep->bcast), ep->ifnum, ep->name);
 		close_and_delete_fd_from_list(ep->bfd);
 		ep->bfd = INVALID_SOCKET;
-		ep->flags &= ~INT_BCASTOPEN;
 	}
+	ep->flags &= ~INT_BCASTOPEN;
 
 	ninterfaces--;
 	mon_clearinterface(ep);
@@ -2565,7 +2565,7 @@ io_setbclient(void)
 			continue;
 
 		/* Only IPv4 addresses are valid for broadcast */
-		REQUIRE(IS_IPV4(&interf->sin));
+		REQUIRE(IS_IPV4(&interf->bcast));
 
 		/* Do we already have the broadcast address open? */
 		if (interf->flags & INT_BCASTOPEN) {
@@ -2593,13 +2593,31 @@ io_setbclient(void)
 			msyslog(LOG_INFO,
 				"Listen for broadcasts to %s on interface #%d %s",
 				stoa(&interf->bcast), interf->ifnum, interf->name);
-		} else {
-			/* silently ignore EADDRINUSE as we probably opened
-			   the socket already for an address in the same network */
-			if (errno != EADDRINUSE)
-				msyslog(LOG_INFO,
-					"failed to listen for broadcasts to %s on interface #%d %s",
-					stoa(&interf->bcast), interf->ifnum, interf->name);
+		} else switch (errno) {
+			/* Silently ignore EADDRINUSE as we probably
+			 * opened the socket already for an address in
+			 * the same network */
+		case EADDRINUSE:
+			/* Some systems cannot bind a socket to a broadcast
+			 * address, as that is not a valid host address. */
+		case EADDRNOTAVAIL:
+#		    ifdef SYS_WINNT	/*TODO: use for other systems, too? */
+			/* avoid recurrence here -- if we already have a
+			 * regular socket, it's quite useless to try this
+			 * again.
+			 */
+			if (interf->fd != INVALID_SOCKET) {
+				interf->flags |= INT_BCASTOPEN;
+				nif++;
+			}
+#		    endif
+			break;
+
+		default:
+			msyslog(LOG_INFO,
+				"failed to listen for broadcasts to %s on interface #%d %s",
+				stoa(&interf->bcast), interf->ifnum, interf->name);
+			break;
 		}
 	}
 	set_reuseaddr(0);
@@ -2639,8 +2657,8 @@ io_unsetbclient(void)
 				stoa(&ep->bcast), ep->ifnum, ep->name);
 			close_and_delete_fd_from_list(ep->bfd);
 			ep->bfd = INVALID_SOCKET;
-			ep->flags &= ~INT_BCASTOPEN;
 		}
+		ep->flags &= ~INT_BCASTOPEN;
 	}
 	broadcast_client_enabled = ISC_FALSE;
 }

==== ntpd/ntp_proto.c ====
2016-03-30 19:23:05+02:00, jnperlin at nemesis.localnet +14 -6
  [Bug 3031]
   - the absolute value of negative broadcastdelays is cutoff limit for peer removal

--- 1.373.2.1/ntpd/ntp_proto.c	2016-03-29 12:22:02 -04:00
+++ 1.373.2.2/ntpd/ntp_proto.c	2016-03-30 13:23:05 -04:00
@@ -25,6 +25,11 @@ 
 #include <unistd.h>
 #endif
 
+/*[Bug 3031] define automatic broadcastdelay cutoff preset */
+#ifndef BDELAY_DEFAULT
+# define BDELAY_DEFAULT (-0.050)
+#endif
+
 /*
  * This macro defines the authentication state. If x is 1 authentication
  * is required; othewise it is optional.
@@ -1144,7 +1149,7 @@ receive(
 		/*
 		 * Determine whether to execute the initial volley.
 		 */
-		if (sys_bdelay != 0) {
+		if (sys_bdelay > 0.0) {
 #ifdef AUTOKEY
 			/*
 			 * If a two-way exchange is not possible,
@@ -1339,7 +1344,7 @@ receive(
 			}
 
 			if (  (current_time - peer->timelastrec)
-			    < (1 << pkt->ppoll)) {
+			    < (1u << pkt->ppoll) - 1) {
 				msyslog(LOG_INFO, "receive: broadcast packet from %s arrived after %ld, not %d seconds!",
 					stoa(&rbufp->recv_srcadr),
 					(current_time - peer->timelastrec),
@@ -1993,8 +1998,11 @@ process_packet(
 		if (FLAG_BC_VOL & peer->flags) {
 			peer->flags &= ~FLAG_BC_VOL;
 			peer->delay = fabs(peer->offset - p_offset) * 2;
-			if (peer->delay > 0.05) {
-	bcc_init_volley_fail:
+			DPRINTF(2, ("broadcast volley: initial delay=%.6f\n",
+				peer->delay));
+			if (peer->delay > fabs(sys_bdelay)) {
+		bcc_init_volley_fail:
+				DPRINTF(2, ("%s", "broadcast volley: initial delay exceeds limit\n"));
 				unpeer(peer);
 				return;
 			}
@@ -4344,7 +4352,7 @@ init_proto(void)
 	sys_survivors = 0;
 	sys_manycastserver = 0;
 	sys_bclient = 0;
-	sys_bdelay = 0;
+	sys_bdelay = BDELAY_DEFAULT;	/*[Bug 3031] delay cutoff */
 	sys_authenticate = 1;
 	sys_stattime = current_time;
 	orphwait = current_time + sys_orphwait;
@@ -4437,7 +4445,7 @@ proto_config(
 		break;
 
 	case PROTO_BROADDELAY:	/* default broadcast delay (bdelay) */
-		sys_bdelay = dvalue;
+		sys_bdelay = (dvalue ? dvalue : BDELAY_DEFAULT);
 		break;
 
 	case PROTO_CEILING:	/* stratum ceiling (ceiling) */

#### ChangeSet ####
2016-03-30 10:29:07+00:00, stenn at psp-deb1.ntp.org
  [Bug 2960] async name resolution fixes for chroot() environments.  Reinhard Max

==== ChangeLog ====
2016-03-30 10:28:14+00:00, stenn at psp-deb1.ntp.org +2 -0
  [Bug 2960] async name resolution fixes for chroot() environments.  Reinhard Max

--- 1.1794.1.11/ChangeLog	2016-03-23 01:28:04 -04:00
+++ 1.1794.1.12/ChangeLog	2016-03-30 06:28:14 -04:00
@@ -1,5 +1,7 @@ 
 ---
 
+* [Bug 2960] async name resolution fixes for chroot() environments.
+  Reinhard Max.
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
 * [Bug 2999] out-of-bounds access in 'is_safe_filename()'. perlinger at ntp.org

==== libntp/work_fork.c ====
2016-03-30 10:28:18+00:00, stenn at psp-deb1.ntp.org +1 -1
  [Bug 2960] async name resolution fixes for chroot() environments.  Reinhard Max

--- 1.14/libntp/work_fork.c	2015-06-27 01:57:45 -04:00
+++ 1.15/libntp/work_fork.c	2016-03-30 06:28:18 -04:00
@@ -451,7 +451,7 @@ fork_blocking_child(
 		}
 	}
 
-#ifdef HAVE_DROPROOT
+#if defined(HAVE_DROPROOT) && !defined(NEED_EARLY_FORK)
 	/* defer the fork until after root is dropped */
 	if (droproot && !root_dropped)
 		return;

==== ntpd/ntp_timer.c ====
2016-03-30 10:28:36+00:00, stenn at psp-deb1.ntp.org +6 -0
  [Bug 2960] async name resolution fixes for chroot() environments.  Reinhard Max

--- 1.95/ntpd/ntp_timer.c	2016-01-14 06:44:16 -05:00
+++ 1.96/ntpd/ntp_timer.c	2016-03-30 06:28:36 -04:00
@@ -276,6 +276,12 @@ intres_timeout_req(
 	u_int	seconds		/* 0 cancels */
 	)
 {
+#if defined(HAVE_DROPROOT) && defined(NEED_EARLY_FORK)
+	if (droproot) {
+		worker_idle_timer = 0;
+		return;
+	}
+#endif
 	if (0 == seconds) {
 		worker_idle_timer = 0;
 		return;

==== ntpd/ntpd.c ====
2016-03-30 10:28:36+00:00, stenn at psp-deb1.ntp.org +15 -0
  [Bug 2960] async name resolution fixes for chroot() environments.  Reinhard Max

--- 1.170/ntpd/ntpd.c	2016-01-14 06:21:11 -05:00
+++ 1.171/ntpd/ntpd.c	2016-03-30 06:28:36 -04:00
@@ -332,6 +332,16 @@ my_pthread_warmup(void)
 
 #endif /*defined(NEED_PTHREAD_WARMUP)*/
 
+#ifdef NEED_EARLY_FORK
+static void
+dummy_callback(void) { return; }
+
+static void
+fork_nonchroot_worker(void) {
+	getaddrinfo_sometime("localhost", "ntp", NULL, INITIAL_DNS_RETRY,
+			     (gai_sometime_callback)&dummy_callback, NULL);
+}
+#endif /* NEED_EARLY_FORK */
 
 void
 parse_cmdline_opts(
@@ -931,6 +941,11 @@ ntpdmain(
 
 # ifdef HAVE_DROPROOT
 	if (droproot) {
+
+#ifdef NEED_EARLY_FORK
+		fork_nonchroot_worker();
+#endif
+
 		/* Drop super-user privileges and chroot now if the OS supports this */
 
 #  ifdef HAVE_LINUX_CAPABILITIES

==== sntp/m4/ntp_libntp.m4 ====
2016-03-30 10:28:47+00:00, stenn at psp-deb1.ntp.org +1 -0
  [Bug 2960] async name resolution fixes for chroot() environments.  Reinhard Max

--- 1.32/sntp/m4/ntp_libntp.m4	2015-09-26 09:17:12 -04:00
+++ 1.33/sntp/m4/ntp_libntp.m4	2016-03-30 06:28:47 -04:00
@@ -163,6 +163,7 @@ esac
 	# include <sys/socket.h>
 	#endif
     ])
+    AC_DEFINE([NEED_EARLY_FORK], [1], [having to fork the DNS worker early when doing chroot?])
 esac
 
 AC_CHECK_HEADERS([arpa/nameser.h sys/param.h sys/time.h sys/timers.h])

#### ChangeSet ####
2016-03-29 18:22:03+02:00, perlinger at ntp.org
  [Bug 3031] ntp broadcastclient unable to synchronize to an server when the time of server changed.
   - Check the initial delay calculation and reject/unpeer the broadcast server if the delay exceeds 50ms.
     Retry again after the next broadcast packet.

==== ChangeLog ====
2016-03-29 18:22:02+02:00, perlinger at ntp.org +5 -0
  [Bug 3031] ntp broadcastclient unable to synchronize to an server when the time of server changed.

--- 1.1794.1.2/ChangeLog	2016-01-24 05:14:42 -05:00
+++ 1.1794.13.1/ChangeLog	2016-03-29 12:22:02 -04:00
@@ -2,6 +2,11 @@ 
 
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
+* [Bug 3031] ntp broadcastclient unable to synchronize to an server
+             when the time of server changed. perlinger at ntp.org
+  - Check the initial delay calculation and reject/unpeer the broadcast
+    server if the delay exceeds 50ms. Retry again after the next
+    broadcast packet.
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

==== ntpd/ntp_proto.c ====
2016-03-29 18:22:02+02:00, perlinger at ntp.org +11 -0
  [Bug 3031] ntp broadcastclient unable to synchronize to an server when the time of server changed.
   - Check the initial delay calculation and reject/unpeer the broadcast server if the delay exceeds 50ms.
     Retry again after the next broadcast packet.

--- 1.373/ntpd/ntp_proto.c	2016-01-18 06:54:51 -05:00
+++ 1.373.2.1/ntpd/ntp_proto.c	2016-03-29 12:22:02 -04:00
@@ -1958,6 +1958,9 @@ process_packet(
 			peer->aorg = p_xmt;
 			peer->borg = peer->dst;
 			if (t34 < 0 || t34 > 1.) {
+				/* drop all if in the initial volley */
+				if (FLAG_BC_VOL & peer->flags)
+					goto bcc_init_volley_fail;
 				snprintf(statstr, sizeof(statstr),
 				    "offset %.6f delay %.6f", t21, t34);
 				report_event(PEVNT_XERR, peer, statstr);
@@ -1983,10 +1986,18 @@ process_packet(
 		 * between the unicast timestamp and the broadcast
 		 * timestamp. This works for both basic and interleaved
 		 * modes.
+		 * [Bug 3031] Don't keep this peer when the delay 
+		 * calculation gives reason to suspect clock steps.
+		 * This is assumed for delays > 50ms.
 		 */
 		if (FLAG_BC_VOL & peer->flags) {
 			peer->flags &= ~FLAG_BC_VOL;
 			peer->delay = fabs(peer->offset - p_offset) * 2;
+			if (peer->delay > 0.05) {
+	bcc_init_volley_fail:
+				unpeer(peer);
+				return;
+			}
 		}
 		p_del = peer->delay;
 		p_offset += p_del / 2;

#### ChangeSet ####
2016-03-27 23:59:51+02:00, jnperlin at nemesis.localnet
  [Bug 3019] NTPD stops processing packets after ERROR_HOST_UNREACHABLE
   - complete refurbishment of overlapped IO engine
   - cleanup

==== ChangeLog ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +2 -0
  [Bug 3019] NTPD stops processing packets after ERROR_HOST_UNREACHABLE
    - work around windows network issues, improve overlapped IO. perlinger at ntp.org

--- 1.1794.1.2/ChangeLog	2016-01-24 05:14:42 -05:00
+++ 1.1794.12.1/ChangeLog	2016-03-27 17:59:49 -04:00
@@ -2,6 +2,8 @@ 
 
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
+* [Bug 3019] NTPD stops processing packets after ERROR_HOST_UNREACHABLE
+  - Overhaul of Windows IO completion port handling. perlinger at ntp.org
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

==== include/ntp.h ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +1 -0
  [Bug 3019] NTPD stops processing packets ERROR_HOST_UNREACHABLE
   - add IOCPL registration handle to interface

--- 1.216/include/ntp.h	2016-01-17 00:12:11 -05:00
+++ 1.216.1.1/include/ntp.h	2016-03-27 17:59:49 -04:00
@@ -175,6 +175,7 @@ struct interface {
 struct interface {
 	endpt *		elink;		/* endpt list link */
 	endpt *		mclink;		/* per-AF_* multicast list */
+	void *		ioreg_ctx;	/* IO registration context */
 	SOCKET		fd;		/* socket descriptor */
 	SOCKET		bfd;		/* for receiving broadcasts */
 	u_int32		ifnum;		/* endpt instance count */

==== include/ntp_refclock.h ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +2 -1
  [Bug 3019] NTPD stops processing packets ERROR_HOST_UNREACHABLE
   - add IOCPL registration handle to RIO structure

--- 1.37/include/ntp_refclock.h	2015-11-13 16:54:33 -05:00
+++ 1.38/include/ntp_refclock.h	2016-03-27 17:59:49 -04:00
@@ -105,7 +105,8 @@ struct refclockio {
 	int	active;		/* nonzero when in use */
 
 #ifdef HAVE_IO_COMPLETION_PORT
-	void *	device_context;	/* device-related data for i/o subsystem */
+	void *	ioreg_ctx;	/* IO registration context */
+	void *	device_ctx;	/* device-related data for i/o subsystem */
 #endif
 };
 

==== include/recvbuff.h ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +2 -2
  [Bug 3019] NTPD stops processing packets ERROR_HOST_UNREACHABLE
   - fix SOCKET vs. FD clash
   - 'get_free_recv_buffer_alloc()': extended comment

--- 1.25/include/recvbuff.h	2011-05-16 01:18:55 -04:00
+++ 1.26/include/recvbuff.h	2016-03-27 17:59:49 -04:00
@@ -91,7 +91,7 @@ extern	struct recvbuf *get_free_recv_buf
 
 /* signal safe - no malloc */
 extern	struct recvbuf *get_free_recv_buffer(void);
-/* signal unsafe - may malloc */
+/* signal unsafe - may malloc, never returs NULL */
 extern	struct recvbuf *get_free_recv_buffer_alloc(void);
 
 /*   Add a buffer to the full list
@@ -113,7 +113,7 @@ extern	void purge_recv_buffers_for_fd(SO
  * purge_recv_buffers_for_fd() - purges any previously-received input
  *				 from a given file descriptor.
  */
-extern	void purge_recv_buffers_for_fd(SOCKET);
+extern	void purge_recv_buffers_for_fd(int);
 
 /*
  * Checks to see if there are buffers to process

==== libntp/ntp_worker.c ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +1 -1
  [Bug 3019] NTPD stops processing packets after ERROR_HOST_UNREACHABLE
    - fix signed/unsigned clash

--- 1.7/libntp/ntp_worker.c	2015-12-09 12:23:31 -05:00
+++ 1.8/libntp/ntp_worker.c	2016-03-27 17:59:49 -04:00
@@ -267,7 +267,7 @@ harvest_blocking_responses(void)
 void
 harvest_blocking_responses(void)
 {
-	int		idx;
+	size_t		idx;
 	blocking_child*	cp;
 	u_int		scseen, scdone;
 

==== libntp/recvbuff.c ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +15 -13
  [Bug 3019] NTPD stops processing packets after ERROR_HOST_UNREACHABLE
   - API cleanup: accept and silently ignore NULL pointer in 'freerecvbuf()'
   - fix SOCKET vs. FD clash

--- 1.40/libntp/recvbuff.c	2015-07-16 03:36:53 -04:00
+++ 1.41/libntp/recvbuff.c	2016-03-27 17:59:49 -04:00
@@ -156,18 +156,15 @@ freerecvbuf(recvbuf_t *rb)
 void
 freerecvbuf(recvbuf_t *rb)
 {
-	if (rb == NULL) {
-		msyslog(LOG_ERR, "freerecvbuff received NULL buffer");
-		return;
+	if (rb) {
+		LOCK();
+		rb->used--;
+		if (rb->used != 0)
+			msyslog(LOG_ERR, "******** freerecvbuff non-zero usage: %d *******", rb->used);
+		LINK_SLIST(free_recv_list, rb, link);
+		free_recvbufs++;
+		UNLOCK();
 	}
-
-	LOCK();
-	rb->used--;
-	if (rb->used != 0)
-		msyslog(LOG_ERR, "******** freerecvbuff non-zero usage: %d *******", rb->used);
-	LINK_SLIST(free_recv_list, rb, link);
-	free_recvbufs++;
-	UNLOCK();
 }
 
 	
@@ -264,7 +261,7 @@ purge_recv_buffers_for_fd(
  */
 void
 purge_recv_buffers_for_fd(
-	SOCKET	fd
+	int	fd
 	)
 {
 	recvbuf_t *rbufp;
@@ -277,7 +274,12 @@ purge_recv_buffers_for_fd(
 	     rbufp != NULL;
 	     rbufp = next) {
 		next = rbufp->link;
-		if (rbufp->fd == fd) {
+#	    ifdef HAVE_IO_COMPLETION_PORT
+		if (rbufp->dstadr == NULL && rbufp->fd == fd)
+#	    else
+		if (rbufp->fd == fd)
+#	    endif
+		{
 			UNLINK_MID_FIFO(punlinked, full_recv_fifo,
 					rbufp, link, recvbuf_t);
 			INSIST(punlinked == rbufp);

==== ntpd/ntp_io.c ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +42 -12
  [Bug 3019] NTPD stops processing packets after hitting ERROR_HOST_UNREACHABLE
   - first invalidate FDs in shared structure, then close handles
   - defer free() via cooling pond when doing overlapped IO 
  ---
  [Bug 3019] NTPD stops processing packets after hitting ERROR_HOST_UNREACHABLE
   - proper wiring to IO completion ports
  ---
  [Bug 3019] NTPD stops processing packets after hitting ERROR_HOST_UNREACHABLE
   - first invalidate FDs in shared structure, then close handles
   - defer free() via cooling pond when doing overlapped IO 
   - proper wiring to IO completion ports
  ---
  [Bug 3019] NTPD stops processing packets after hitting ERROR_HOST_UNREACHABLE
   - wired the needed unregistration functions for overlapped IO

--- 1.414/ntpd/ntp_io.c	2016-01-24 05:13:18 -05:00
+++ 1.414.1.1/ntpd/ntp_io.c	2016-03-27 17:59:49 -04:00
@@ -774,6 +774,12 @@ new_interface(
 	iface->ifnum = sys_ifnum++;
 	iface->starttime = current_time;
 
+#   ifdef HAVE_IO_COMPLETION_PORT
+	if (!io_completion_port_add_interface(iface)) {
+		msyslog(LOG_EMERG, "cannot register interface with IO engine -- will exit now");
+		exit(1);
+	}
+#   endif
 	return iface;
 }
 
@@ -781,11 +787,14 @@ static inline void
 /*
  * return interface storage into free memory pool
  */
-static inline void
+static void
 delete_interface(
 	endpt *ep
 	)
 {
+#    ifdef HAVE_IO_COMPLETION_PORT
+	io_completion_port_remove_interface(ep);
+#    endif
 	free(ep);
 }
 
@@ -1003,6 +1012,9 @@ remove_interface(
 			ep->sent,
 			ep->notsent,
 			current_time - ep->starttime);
+#	    ifdef HAVE_IO_COMPLETION_PORT
+		io_completion_port_remove_socket(ep->fd, ep);
+#	    endif
 		close_and_delete_fd_from_list(ep->fd);
 		ep->fd = INVALID_SOCKET;
 	}
@@ -1011,10 +1023,16 @@ remove_interface(
 		msyslog(LOG_INFO,
 			"stop listening for broadcasts to %s on interface #%d %s",
 			stoa(&ep->bcast), ep->ifnum, ep->name);
+#	    ifdef HAVE_IO_COMPLETION_PORT
+		io_completion_port_remove_socket(ep->bfd, ep);
+#	    endif
 		close_and_delete_fd_from_list(ep->bfd);
 		ep->bfd = INVALID_SOCKET;
 		ep->flags &= ~INT_BCASTOPEN;
 	}
+#   ifdef HAVE_IO_COMPLETION_PORT
+	io_completion_port_remove_interface(ep);
+#   endif
 
 	ninterfaces--;
 	mon_clearinterface(ep);
@@ -2637,6 +2655,9 @@ io_unsetbclient(void)
 			msyslog(LOG_INFO,
 				"stop listening for broadcasts to %s on interface #%d %s",
 				stoa(&ep->bcast), ep->ifnum, ep->name);
+#		    ifdef HAVE_IO_COMPLETION_PORT
+			io_completion_port_remove_socket(ep->bfd, ep);
+#		    endif
 			close_and_delete_fd_from_list(ep->bfd);
 			ep->bfd = INVALID_SOCKET;
 			ep->flags &= ~INT_BCASTOPEN;
@@ -3016,11 +3037,11 @@ open_socket(
 		    fcntl(fd, F_GETFL, 0)));
 #endif /* SYS_WINNT || VMS */
 
-#if defined (HAVE_IO_COMPLETION_PORT)
+#if defined(HAVE_IO_COMPLETION_PORT)
 /*
  * Add the socket to the completion port
  */
-	if (io_completion_port_add_socket(fd, interf)) {
+	if (!io_completion_port_add_socket(fd, interf, bcast)) {
 		msyslog(LOG_ERR, "unable to set up io completion port - EXITING");
 		exit(1);
 	}
@@ -3029,10 +3050,6 @@ open_socket(
 }
 
 
-#ifdef SYS_WINNT
-#define sendto(fd, buf, len, flags, dest, destsz)	\
-	io_completion_port_sendto(fd, buf, len, (sockaddr_u *)(dest))
-#endif
 
 /* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */
 /*
@@ -3120,6 +3137,9 @@ sendpkt(
 
 #ifdef SIM
 		cc = simulate_server(dest, src, pkt);
+#elif defined(HAVE_IO_COMPLETION_PORT)
+		cc = io_completion_port_sendto(src, src->fd, pkt,
+			(size_t)len, (sockaddr_u *)&dest->sa);
 #else
 		cc = sendto(src->fd, (char *)pkt, (u_int)len, 0,
 			    &dest->sa, SOCKLEN(dest));
@@ -4276,7 +4296,7 @@ io_addclock(
 		return 0;
 	}
 # elif defined(HAVE_IO_COMPLETION_PORT)
-	if (io_completion_port_add_clock_io(rio)) {
+	if (!io_completion_port_add_clock_io(rio)) {
 		UNBLOCKIO();
 		return 0;
 	}
@@ -4315,13 +4335,23 @@ io_closeclock(
 	rio->active = FALSE;
 	UNLINK_SLIST(unlinked, refio, rio, next, struct refclockio);
 	if (NULL != unlinked) {
-		purge_recv_buffers_for_fd(rio->fd);
-		/*
-		 * Close the descriptor.
-		 */
+		/* Close the descriptor. The order of operations is
+		 * important here in case of async / overlapped IO:
+		 * only after we have removed the clock from the
+		 * IO completion port we can be sure no further
+		 * input is queued. So...
+		 *  - we first disable feeding to the queu by removing
+		 *    the clock from the IO engine
+		 *  - close the file (which brings down any IO on it)
+		 *  - clear the buffer from results for this fd
+		 */
+#	    ifdef HAVE_IO_COMPLETION_PORT
+		io_completion_port_remove_clock_io(rio);
+#	    endif
 		close_and_delete_fd_from_list(rio->fd);
+		purge_recv_buffers_for_fd(rio->fd);
+		rio->fd = -1;
 	}
-	rio->fd = -1;
 
 	UNBLOCKIO();
 }

==== ports/winnt/include/ntp_iocompletionport.h ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +17 -10
  Bug 3019 - NTPD stops processing packets after ERROR_HOST_UNREACHABLE
   - extend API to provide essential information
   - added missing unregistration functions to API

--- 1.21/ports/winnt/include/ntp_iocompletionport.h	2015-11-13 16:54:34 -05:00
+++ 1.22/ports/winnt/include/ntp_iocompletionport.h	2016-03-27 17:59:49 -04:00
@@ -1,27 +1,34 @@ 
-#if !defined __ntp_iocompletionport_h
-# define __ntp_iocompletionport_h
+#ifndef NTP_IOCPMPLETIONPORT_H
+#define NTP_IOCPMPLETIONPORT_H
 
 #include "ntp_fp.h"
 #include "ntp.h"
 #include "clockstuff.h"
 #include "ntp_worker.h"
 
-# if defined(HAVE_IO_COMPLETION_PORT)
+#if defined(HAVE_IO_COMPLETION_PORT)
+
+struct refclockio;	/* in ntp_refclock.h but inclusion here triggers problems */
+struct interface;	/* likewise */
+
 
 extern	void	init_io_completion_port(void);
 extern	void	uninit_io_completion_port(void);
 
-extern	int	io_completion_port_add_socket(SOCKET fd, struct interface *);
-
-struct refclockio; /* in ntp_refclock.h but inclusion here triggers problems */
-extern	int	io_completion_port_add_clock_io(struct refclockio *rio);
+extern	BOOL	io_completion_port_add_interface(struct interface*);
+extern	void	io_completion_port_remove_interface(struct interface*);
+
+extern	BOOL	io_completion_port_add_socket(SOCKET fd, struct interface *, BOOL bcast);
+extern	void	io_completion_port_remove_socket(SOCKET fd, struct interface*);
+
+extern	int	io_completion_port_sendto(struct interface*, SOCKET, void *, size_t, sockaddr_u *);
+
+extern	BOOL	io_completion_port_add_clock_io(struct refclockio *rio);
 extern	void	io_completion_port_remove_clock_io(struct refclockio *rio);
-extern	int	io_completion_port_sendto(SOCKET, void *, size_t, sockaddr_u *);
 
 extern	int	GetReceivedBuffers(void);
 
 extern	HANDLE	WaitableExitEventHandle;
 
-# endif
-
-#endif
+#endif /*!defined(HAVE_IO_COMPLETION_PORT)*/
+#endif /*!defined(NTP_IOCPMPLETIONPORT_H)*/

==== ports/winnt/include/ntp_iocplmem.h ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +24 -0
  [Bug 3019] NTPD stops processing packets after hitting ERROR_HOST_UNREACHABLE
   - refactored IOCPL heap into separate file

--- /dev/null	2016-04-26 19:53:05 -04:00
+++ 1.1/ports/winnt/include/ntp_iocplmem.h	2016-03-27 17:59:49 -04:00
@@ -0,0 +1,24 @@ 
+/*
+ * ntp_iocplmem.h - separate memory pool for IOCPL related objects
+ *
+ * Written by Juergen Perlinger (perlinger at ntp.org) for the NTP project.
+ * The contents of 'html/copyright.html' apply.
+ *
+ * --------------------------------------------------------------------
+ * Notes on the implementation:
+ *
+ * Implements a thin layer over Windows Memory pools
+ */
+#ifndef NTP_IOCPLMEM_H
+#define NTP_IOCPLMEM_H
+
+#include <stdlib.h>
+
+extern void IOCPLPoolInit(size_t initSize);
+extern void IOCPLPoolDone(void);
+
+extern void* __fastcall	IOCPLPoolAlloc(size_t size, const char*	desc);
+extern void* __fastcall	IOCPLPoolMemDup(const void* psrc, size_t size, const char* desc);
+extern void  __fastcall	IOCPLPoolFree(void* ptr, const char* desc);
+
+#endif /*!defined(NTP_IOCPLMEM_H)*/

==== ports/winnt/include/ntp_iocplmem.h ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +0 -0

==== ports/winnt/include/ntp_iocpltypes.h ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +160 -0
  [Bug 3019] NTPD stops processing packets after ERROR_HOST_UNREACHABLE
   - refactored helper objects (locks, PPS/device context, IO context,...) into separate file

--- /dev/null	2016-04-26 19:53:05 -04:00
+++ 1.1/ports/winnt/include/ntp_iocpltypes.h	2016-03-27 17:59:49 -04:00
@@ -0,0 +1,160 @@ 
+/*
+ * ntp_iocpltypes.h - data structures for overlapped IO
+ *
+ * Written by Juergen Perlinger (perlinger at ntp.org) for the NTP project.
+ * The contents of 'html/copyright.html' apply.
+ *
+ * --------------------------------------------------------------------
+ */
+#ifndef NTP_IOCPLTYPES_H
+#define NTP_IOCPLTYPES_H
+
+#include <stdlib.h>
+#include <Windows.h>
+#include "ntp.h"
+
+/* ---------------------------------------------------------------------
+ * forward declarations to avoid deep header nesting
+ */
+typedef struct IoCtx		IoCtx_t;
+typedef struct refclockio	RIO_t;
+typedef struct interface	endpt;
+typedef struct recvbuf		recvbuf_t;
+
+/* ---------------------------------------------------------------------
+ * shared lock to avoid concurrent deletes on IO related stuff like
+ * RIO or ENDPOINT blocks.
+ *
+ * Basically we wwould need a multiple-reader/single-writer lock,
+ * but for now we do full mutual exclusion.
+ */
+typedef struct SharedLock SharedLock_t;
+typedef const struct SharedLock CSharedLock_t;
+struct SharedLock {
+	CRITICAL_SECTION	mutex[1];
+	volatile u_long		refc_count;
+	union {
+		RIO_t *		 rio;	/*  RIO back-link (for offload)	*/
+		endpt *		 ept;	/*  inetrface backlink		*/
+		ULONG_PTR	 key;	/*  as key for IOCPL queue	*/
+		void *		 any;
+	}			rsrc;	/* registered source		*/
+	HANDLE			handles[2]; /* 0->COM/SOCK 1->BCASTSOCK	*/
+	int			riofd;	/* FD for comports		*/
+};
+
+typedef BOOL(__fastcall * LockPredicateT)(CSharedLock_t*);
+
+extern SharedLock_t* __fastcall	slCreate(void * rsrc);
+extern SharedLock_t* __fastcall	slAttach(SharedLock_t*);
+extern SharedLock_t* __fastcall	slDetach(SharedLock_t*);
+extern SharedLock_t* __fastcall	slAttachShared(SharedLock_t*);
+extern SharedLock_t* __fastcall	slDetachShared(SharedLock_t*);
+extern SharedLock_t* __fastcall	slAttachExclusive(SharedLock_t*);
+extern SharedLock_t* __fastcall	slDetachExclusive(SharedLock_t*);
+
+extern BOOL __fastcall	slRefClockOK(CSharedLock_t*);
+extern BOOL __fastcall	slEndPointOK(CSharedLock_t*);
+
+extern BOOL	slQueueLocked(SharedLock_t*, LockPredicateT, recvbuf_t*);
+
+
+/* ---------------------------------------------------------------------
+ * storage type for PPS data (DCD change counts & times)
+ * ---------------------------------------------------------------------
+ */
+typedef struct PpsData PPSData_t;
+struct PpsData {
+	u_long	cc_assert;
+	u_long	cc_clear;
+	l_fp	ts_assert;
+	l_fp	ts_clear;
+};
+
+typedef volatile struct PpsDataEx PPSDataEx_t;
+struct PpsDataEx {
+	u_long		cov_count;
+	PPSData_t	data;
+};
+
+/* ---------------------------------------------------------------------
+ * device context; uses reference counting to avoid nasty surprises.
+ * Currently this stores only the PPS time stamps, but it could be
+ * easily extended.
+ * ---------------------------------------------------------------------
+ */
+#define PPS_QUEUE_LEN	8u		  /* must be power of two! */
+#define PPS_QUEUE_MSK	(PPS_QUEUE_LEN-1) /* mask for easy MOD ops */
+
+typedef struct DeviceContext DevCtx_t;
+struct DeviceContext {
+	volatile u_long	ref_count;
+	volatile u_long	cov_count;
+	PPSData_t	pps_data;
+	PPSDataEx_t	pps_buff[PPS_QUEUE_LEN];
+};
+
+extern DevCtx_t* __fastcall DevCtxAlloc(void);
+extern DevCtx_t* __fastcall DevCtxAttach(DevCtx_t*);
+extern DevCtx_t* __fastcall DevCtxDetach(DevCtx_t*);
+
+/* ---------------------------------------------------------------------
+ * I/O context structure
+ *
+ * This is an extended overlapped structure. Some fields are only used
+ * for serial I/O, others are used for all operations. The serial I/O is
+ * more interesting since the same context object is used for waiting,
+ * actual I/O and possibly offload processing in a worker thread until
+ * a complete operation cycle is done.
+ *
+ * In this case the I/O context is used to gather all the bits that are
+ * finally needed for the processing of the buffer.
+ * ---------------------------------------------------------------------
+ */
+
+typedef void(*IoCompleteFunc)(ULONG_PTR, IoCtx_t *);
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable : 201)		/* nonstd extension nameless union */
+#endif
+struct IoCtx {
+	OVERLAPPED		ol;		/* 'kernel' part of the context	*/
+	union {
+		recvbuf_t *	recv_buf;	/* incoming -> buffer structure	*/
+		void *		trans_buf;	/* outgoing -> char array	*/
+		PPSData_t *	pps_buf;	/* for reading PPS seq/stamps	*/
+		HANDLE		ppswake;	/* pps wakeup for attach	*/
+	};
+	union {
+		HANDLE		 hnd;		/*  IO handle (the real McCoy)	*/
+		SOCKET		 sfd;		/*  socket descriptor		*/
+	}			io;		/* the IO resource used		*/
+	IoCompleteFunc		onIoDone;	/* HL callback to execute	*/
+	SharedLock_t *		slock;
+	DevCtx_t *		devCtx;
+	DWORD			errCode;	/* error code of last I/O	*/
+	DWORD			byteCount;	/* byte count     "             */
+	u_int			flRawMem : 1;	/* buffer is raw memory -> free */
+	struct {
+		l_fp		DCDSTime;	/* PPS-hack: time of DCD ON	*/
+		l_fp		FlagTime;	/* time stamp of flag/event char*/
+		l_fp		RecvTime;	/* time stamp of callback	*/
+		DWORD		com_events;	/* buffer for COM events	*/
+		u_int		flTsDCDS : 1;	/* DCDSTime valid?		*/
+		u_int		flTsFlag : 1;	/* FlagTime valid?		*/
+	} aux;
+};
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+typedef BOOL (__fastcall *IoCtxStarterT)(IoCtx_t*, recvbuf_t*);
+
+extern IoCtx_t* __fastcall IoCtxAlloc(SharedLock_t*, DevCtx_t*);
+extern void	__fastcall IoCtxFree(IoCtx_t*);
+extern void	__fastcall IoCtxRelease(IoCtx_t*);
+
+extern BOOL	IoCtxStartLocked(IoCtx_t*, IoCtxStarterT, recvbuf_t*);
+
+#endif /*!defined(NTP_IOCPLTYPES_H)*/

==== ports/winnt/include/ntp_iocpltypes.h ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +0 -0

==== ports/winnt/ntpd/ntp_iocompletionport.c ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +875 -791
  [Bug 3019] NTPD stops processing packets after ERROR_HOST_UNREACHABLE
   - make sure ALL operations are overlapped for sockets
   - use APC queue for deferred error processing
   - take extra care to deal with interfaces/clocks being removed while overlapped IO in flight
   - minor WINAPI cleanups (VS2008 vs VS2013)
   - extend API to provide essential information
   - better context checking
   - implemented the missing unregistration functions
   - implemented shared locking between clocks/interfaces and IO operations
   - made sure minimal locking is engaged
   - fixed / locked / avoided access to global / shared values from IO thread
   - made sure interfaces and clocks cannot be deleted wile accessed from worker thread
   - made sure feeding the receive queue stops with deregistration
  In other words, a complete refurbishment.
   - further refactoring, better handling of received packets

--- 1.72/ports/winnt/ntpd/ntp_iocompletionport.c	2015-11-13 16:54:34 -05:00
+++ 1.73/ports/winnt/ntpd/ntp_iocompletionport.c	2016-03-27 17:59:49 -04:00
@@ -16,20 +16,20 @@ Some notes on the implementation:
     makes using more than one thread useless, as they would compete for
     the same core and create contention.
 
-+ Some IO operations need a possibly lengthy postprocessing. Emulating
++ Some IO operations need a possibly lengthy post-processing. Emulating
   the UN*X line discipline is currently the only but prominent example.
   To avoid the processing in the time-critical IOCPL thread, longer
   processing is offloaded the worker thread pool.
 
 + A fact that seems not as well-known as it should be is that all
-  ressources passed to an overlapped IO operation must be considered
+  resources passed to an overlapped IO operation must be considered
   owned by the OS until the result has been fetched/dequeued. This
   includes all overlapped structures and buffers involved, so cleaning
   up on shutdown must be carefully constructed. (This includes closing
   all the IO handles and waiting for the results to be dequeued.
   'CancleIo()' cannot be used since it's broken beyond repair.)
 
-  If this is not possible, then all ressources should be dropped into
+  If this is not possible, then all resources should be dropped into
   oblivion -- otherwise "bad things (tm)" are bound to happen.
 
   Using a private heap that is silently dropped but not deleted is a
@@ -59,124 +59,35 @@ Juergen Perlinger (perlinger at ntp.org) Fe
 #include <stdio.h>
 #include <process.h>
 #include <syslog.h>
-#include <limits.h>
 
 #include "ntpd.h"
-#include "ntp_machine.h"
+#include "ntp_request.h"
+
 #include "ntp_iocompletionport.h"
-#include "ntp_request.h"
-#include "ntp_assert.h"
-#include "ntp_io.h"
-#include "ntp_lists.h"
+#include "ntp_iocplmem.h"
+#include "ntp_iocpltypes.h"
 
 
 #define CONTAINEROF(p, type, member) \
 	((type *)((char *)(p) - offsetof(type, member)))
 
-#ifdef _MSC_VER
-# pragma warning(push)
-# pragma warning(disable: 201)		/* nonstd extension nameless union */
-#endif
-
-/*
- * ---------------------------------------------------------------------
- * storage type for PPS data (DCD change counts & times)
- * ---------------------------------------------------------------------
- */
-struct PpsData {
-	u_long	cc_assert;
-	u_long	cc_clear;
-	l_fp	ts_assert;
-	l_fp	ts_clear;
-};
-typedef struct PpsData PPSData_t;
-
-struct PpsDataEx {
-	u_long		cov_count;
-	PPSData_t	data;
-};
-typedef volatile struct PpsDataEx PPSDataEx_t;
-
-/*
- * ---------------------------------------------------------------------
- * device context; uses reference counting to avoid nasty surprises.
- * Currently this stores only the PPS time stamps, but it could be
- * easily extended.
- * ---------------------------------------------------------------------
- */
-#define PPS_QUEUE_LEN	8u		  /* must be power of two! */
-#define PPS_QUEUE_MSK	(PPS_QUEUE_LEN-1) /* mask for easy MOD ops */
-
-struct DeviceContext {
-	volatile long	ref_count;
-	volatile u_long	cov_count;
-	PPSData_t	pps_data;
-	PPSDataEx_t	pps_buff[PPS_QUEUE_LEN];
-};
-
-typedef struct DeviceContext DevCtx_t;
-
-/*
- * ---------------------------------------------------------------------
- * I/O context structure
- *
- * This is an extended overlapped structure. Some fields are only used
- * for serial I/O, others are used for all operations. The serial I/O is
- * more interesting since the same context object is used for waiting,
- * actual I/O and possibly offload processing in a worker thread until
- * a complete operation cycle is done.
- *
- * In this case the I/O context is used to gather all the bits that are
- * finally needed for the processing of the buffer.
- * ---------------------------------------------------------------------
- */
-//struct IoCtx;
-typedef struct IoCtx      IoCtx_t;
-typedef struct refclockio RIO_t;
-
-typedef void (*IoCompleteFunc)(ULONG_PTR, IoCtx_t *);
-
-struct IoCtx {
-	OVERLAPPED		ol;		/* 'kernel' part of the context	*/
-	union {
-		recvbuf_t *	recv_buf;	/* incoming -> buffer structure	*/
-		void *		trans_buf;	/* outgoing -> char array	*/
-		PPSData_t *	pps_buf;	/* for reading PPS seq/stamps	*/
-		HANDLE		ppswake;	/* pps wakeup for attach	*/
-	};
-	IoCompleteFunc		onIoDone;	/* HL callback to execute	*/
-	RIO_t *			rio;		/* RIO backlink (for offload)	*/
-	DevCtx_t *		devCtx;
-	l_fp			DCDSTime;	/* PPS-hack: time of DCD ON	*/
-	l_fp			FlagTime;	/* timestamp of flag/event char */
-	l_fp			RecvTime;	/* timestamp of callback        */
-	DWORD			errCode;	/* error code of last I/O	*/
-	DWORD			byteCount;	/* byte count     "             */
-	DWORD			com_events;	/* buffer for COM events	*/
-	unsigned int		flRawMem : 1;	/* buffer is raw memory -> free */
-	unsigned int		flTsDCDS : 1;	/* DCDSTime valid?		*/
-	unsigned int		flTsFlag : 1;	/* FlagTime valid?		*/
-};
-
-#ifdef _MSC_VER
-# pragma warning(pop)
-#endif
 
 /*
  * local function definitions
  */
-static		void ntpd_addremove_semaphore(HANDLE, int);
-static inline	void set_serial_recv_time    (recvbuf_t *, IoCtx_t *);
+static	void ntpd_addremove_semaphore(HANDLE, int);
+static	void set_serial_recv_time    (recvbuf_t *, IoCtx_t *);
 
 /* Initiate/Request async IO operations */
-static	BOOL QueueSerialWait   (RIO_t *, recvbuf_t *, IoCtx_t *);
-static	BOOL QueueSerialRead   (RIO_t *, recvbuf_t *, IoCtx_t *);
-static	BOOL QueueRawSerialRead(RIO_t *, recvbuf_t *, IoCtx_t *);
-static  BOOL QueueSocketRecv   (SOCKET , recvbuf_t *, IoCtx_t *);
+static	BOOL __fastcall QueueSerialWait   (IoCtx_t *, recvbuf_t *);
+static	BOOL __fastcall QueueSerialRead(IoCtx_t *, recvbuf_t *);
+static	BOOL __fastcall QueueRawSerialRead(IoCtx_t *, recvbuf_t *);
+static  BOOL __fastcall QueueSocketRecv(IoCtx_t *, recvbuf_t *);
 
 
 /* High-level IO callback functions */
 static	void OnSocketRecv           (ULONG_PTR, IoCtx_t *);
+static	void OnSocketSend           (ULONG_PTR, IoCtx_t *);
 static	void OnSerialWaitComplete   (ULONG_PTR, IoCtx_t *);
 static	void OnSerialReadComplete   (ULONG_PTR, IoCtx_t *);
 static	void OnRawSerialReadComplete(ULONG_PTR, IoCtx_t *);
@@ -192,198 +103,29 @@ static void free_io_completion_port_mem(
 #endif
 
 
-	HANDLE WaitableExitEventHandle;
-	HANDLE WaitableIoEventHandle;
-static	HANDLE hIoCompletionPort;
+	HANDLE	WaitableExitEventHandle;
+	HANDLE	WaitableIoEventHandle;
+static	HANDLE	hndIOCPLPort;
+static	HANDLE	hMainThread;
 
 DWORD	ActiveWaitHandles;
 HANDLE	WaitHandles[16];
 
-/*
- * -------------------------------------------------------------------
- * We make a pool of our own for IO context objects -- the are owned by
- * the system until a completion result is pulled from the queue, and
- * they seriously go into the way of memory tracking until we can safely
- * cancel an IO request.
- * -------------------------------------------------------------------
- */
-static	HANDLE hHeapHandle;
-
-/*
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- * Create a new heap for IO context objects
- */
-static void
-IoCtxPoolInit(
-	size_t	initObjs
-	)
-{
-	hHeapHandle = HeapCreate(0, initObjs * sizeof(IoCtx_t), 0);
-	if (hHeapHandle == NULL) {
-		msyslog(LOG_ERR, "Can't initialize Heap: %m");
-		exit(1);
-	}
-}
-
-/*
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- *
- * Delete the IO context heap
- *
- * Since we do not know what callbacks are pending, we just drop the
- * pool into oblivion. New allocs and frees will fail from this moment,
- * but we simply don't care. At least the normal heap dump stats will
- * show no leaks from IO context blocks. On the downside, we have to
- * track them ourselves if something goes wrong.
- */
-static void
-IoCtxPoolDone(void)
-{
-	hHeapHandle = NULL;
-}
-
-/*
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- * Alloc & Free on local heap
- *
- * When the heap handle is NULL, these both will fail; Alloc with a NULL
- * return and Free silently.
- */
-static void * __fastcall
-LocalPoolAlloc(
-	size_t		size,
-	const char *	desc
-)
-{
-	void *	ptr;
-
-	/* Windows heaps can't grok zero byte allocation.
-	 * We just get one byte.
-	 */
-	if (size == 0)
-		size = 1;
-	if (hHeapHandle != NULL)
-		ptr = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, size);
-	else
-		ptr = NULL;
-	DPRINTF(3, ("Allocate '%s', heap=%p, ptr=%p\n",
-			desc,  hHeapHandle, ptr));
-
-	return ptr;
-}
-
-static void __fastcall
-LocalPoolFree(
-	void *		ptr,
-	const char *	desc
-	)
-{
-	DPRINTF(3, ("Free '%s', heap=%p, ptr=%p\n",
-			desc, hHeapHandle, ptr));
-	if (ptr != NULL && hHeapHandle != NULL)
-		HeapFree(hHeapHandle, 0, ptr);
-}
-
-/*
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- * Alloc & Free of Device context
- *
- * When the heap handle is NULL, these both will fail; Alloc with a NULL
- * return and Free silently.
- */
-static DevCtx_t * __fastcall
-DevCtxAlloc(void)
-{
-	DevCtx_t *	devCtx;
-	u_long		slot;
-
-	/* allocate struct and tag all slots as invalid */
-	devCtx = (DevCtx_t *)LocalPoolAlloc(sizeof(DevCtx_t), "DEV ctx");
-	if (devCtx != NULL)
-	{
-		/* The initial COV values make sure there is no busy
-		 * loop on unused/empty slots.
-		 */
-		devCtx->cov_count = 0;
-		for (slot = 0; slot < PPS_QUEUE_LEN; slot++)
-			devCtx->pps_buff[slot].cov_count = ~slot;
-	}
-	return devCtx;
-}
-
-static void __fastcall
-DevCtxFree(
-	DevCtx_t *	devCtx
-	)
-{
-	/* this would be the place to get rid of managed ressources. */
-	LocalPoolFree(devCtx, "DEV ctx");
-}
-
-static DevCtx_t * __fastcall
-DevCtxAttach(
-	DevCtx_t *	devCtx
-	)
-{
-	if (devCtx != NULL)
-		InterlockedIncrement(&devCtx->ref_count);
-	return devCtx;
-}
-
-static void __fastcall
-DevCtxDetach(
-	DevCtx_t *	devCtx
-	)
-{
-	if (devCtx && !InterlockedDecrement(&devCtx->ref_count))
-		DevCtxFree(devCtx);
-}
 
 /*
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- * Alloc & Free of I/O context
- *
- * When the heap handle is NULL, these both will fail; Alloc with a NULL
- * return and Free silently.
- */
-static IoCtx_t * __fastcall
-IoCtxAlloc(
-	DevCtx_t *	devCtx
-	)
-{
-	IoCtx_t *	ioCtx;
-
-	ioCtx = (IoCtx_t *)LocalPoolAlloc(sizeof(IoCtx_t), "IO ctx");
-	if (ioCtx != NULL)
-		ioCtx->devCtx = DevCtxAttach(devCtx);
-	return ioCtx;
-}
+ * -------------------------------------------------------------------
+ * Windows 2000 bluescreens with bugcheck 0x76 PROCESS_HAS_LOCKED_PAGES
+ * at ntpd process termination when using more than one pending
+ * receive per socket.  A runtime version test during startup will
+ * allow using more on newer versions of Windows.
+ *
+ * perlinger at ntp.org: Considering the quirks fixed in the overlapped
+ * IO handling in recent years, it could even be that this is no longer
+ * an issue. Testing this might be tricky -- who runs a Win2k system
+ * in the year 2016?
+ */
+static size_t	s_SockRecvSched = 1;	/* possibly adjusted later */
 
-static void __fastcall
-IoCtxFree(
-	IoCtx_t *	ctx
-	)
-{
-	if (ctx)
-		DevCtxDetach(ctx->devCtx);
-	LocalPoolFree(ctx, "IO ctx");
-}
-
-static void __fastcall
-IoCtxReset(
-	IoCtx_t *	ctx
-	)
-{
-	RIO_t *		rio;
-	DevCtx_t *	dev;
-	if (ctx) {
-		rio = ctx->rio;
-		dev = ctx->devCtx;
-		ZERO(*ctx);
-		ctx->rio    = rio;
-		ctx->devCtx = dev;
-	}
-}
 
 /*
  * -------------------------------------------------------------------
@@ -408,7 +150,9 @@ iocompletionthread(void *NotUsed)
  * dangerous weapon -- it's like SIGKILL.
  */
 static unsigned WINAPI
-iocompletionthread(void *NotUsed)
+iocompletionthread(
+	void *NotUsed
+	)
 {
 	DWORD		err;
 	DWORD		octets;
@@ -418,19 +162,17 @@ iocompletionthread(void *NotUsed)
 
 	UNUSED_ARG(NotUsed);
 
-	/*
-	 * Socket and refclock receive call gettimeofday() so the I/O
+	/* Socket and refclock receive call gettimeofday() so the I/O
 	 * thread needs to be on the same processor as the main and
 	 * timing threads to ensure consistent QueryPerformanceCounter()
 	 * results.
 	 *
 	 * This gets seriously into the way of efficient thread pooling
-	 * on multicore systems.
+	 * on multi-core systems.
 	 */
 	lock_thread_to_processor(GetCurrentThread());
 
-	/*
-	 * Set the thread priority high enough so I/O will preempt
+	/* Set the thread priority high enough so I/O will pre-empt
 	 * normal recv packet processing, but not higher than the timer
 	 * sync thread.
 	 */
@@ -440,7 +182,7 @@ iocompletionthread(void *NotUsed)
 
 	for(;;) {
 		if (GetQueuedCompletionStatus(
-					hIoCompletionPort, 
+					hndIOCPLPort, 
 					&octets, 
 					&key, 
 					&pol, 
@@ -449,12 +191,12 @@ iocompletionthread(void *NotUsed)
 		} else {
 			err = GetLastError();
 		}
-		if (NULL == pol) {
+		if (pol == NULL) {
 			DPRINTF(2, ("Overlapped IO Thread Exiting\n"));
 			break; /* fail */
 		}
 		lpo = CONTAINEROF(pol, IoCtx_t, ol);
-		get_systime(&lpo->RecvTime);
+		get_systime(&lpo->aux.RecvTime);
 		lpo->byteCount = octets;
 		lpo->errCode = err;
 		handler_calls++;
@@ -471,12 +213,21 @@ init_io_completion_port(void)
 void
 init_io_completion_port(void)
 {
-#ifdef DEBUG
+	OSVERSIONINFO vi;
+
+#   ifdef DEBUG
 	atexit(&free_io_completion_port_mem);
-#endif
+#   endif
+
+	memset(&vi, 0, sizeof(vi));
+	vi.dwOSVersionInfoSize = sizeof(vi);
+
+	/* For windows 7 and above, schedule more than one receive */
+	if (GetVersionEx(&vi) && vi.dwMajorVersion >= 6)
+		s_SockRecvSched = 4;
 
 	/* Create the context pool first. */
-	IoCtxPoolInit(20);
+	IOCPLPoolInit(20);
 
 	/* Create the event used to signal an IO event */
 	WaitableIoEventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
@@ -492,9 +243,9 @@ init_io_completion_port(void)
 	}
 
 	/* Create the IO completion port */
-	hIoCompletionPort = CreateIoCompletionPort(
+	hndIOCPLPort = CreateIoCompletionPort(
 		INVALID_HANDLE_VALUE, NULL, 0, 0);
-	if (hIoCompletionPort == NULL) {
+	if (hndIOCPLPort == NULL) {
 		msyslog(LOG_ERR, "Can't create I/O completion port: %m");
 		exit(1);
 	}
@@ -505,17 +256,19 @@ init_io_completion_port(void)
 	WaitHandles[2] = WaitableTimerHandle;
 	ActiveWaitHandles = 3;
 
-	/*
-	 * Supply ntp_worker.c with function to add or remove a
+	/* Supply ntp_worker.c with function to add or remove a
 	 * semaphore to the ntpd I/O loop which is signalled by a worker
 	 * when a response is ready.  The callback is invoked in the
 	 * parent.
 	 */
 	addremove_io_semaphore = &ntpd_addremove_semaphore;
 
-	/*
-	 * Have one thread servicing I/O. See rationale in front matter.
- 	 */
+	/* Create a true handle for the main thread (APC processing) */
+	DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
+		GetCurrentProcess(), &hMainThread,
+		0, FALSE, DUPLICATE_SAME_ACCESS);
+
+	/* Have one thread servicing I/O. See rationale in front matter. */
 	hIoCompletionThread = (HANDLE)_beginthreadex(
 		NULL, 
 		0, 
@@ -535,35 +288,40 @@ uninit_io_completion_port(
 	void
 	)
 {
-        DWORD rc;
+	DWORD	rc;
 
 	/* do noting if completion port already gone. */
-	if (NULL == hIoCompletionPort)
+	if (hndIOCPLPort == NULL)
 		return;
 
-	/*
-	 * Service thread seems running. Terminate him with grace
+	/* Service thread seems running. Terminate him with grace
 	 * first and force later...
 	 */
-        if (tidCompletionThread != GetCurrentThreadId()) {
-	        PostQueuedCompletionStatus(hIoCompletionPort, 0, 0, 0);
-                rc = WaitForSingleObject(hIoCompletionThread, 5000);
-                if (rc == WAIT_TIMEOUT) {
-		        /* Thread lost. Kill off with TerminateThread. */
-		        msyslog(LOG_ERR,
-                                "IO completion thread refuses to terminate");
-		        TerminateThread(hIoCompletionThread, ~0UL);
-                }
+	if (tidCompletionThread != GetCurrentThreadId()) {
+		PostQueuedCompletionStatus(hndIOCPLPort, 0, 0, 0);
+		rc = WaitForSingleObject(hIoCompletionThread, 5000);
+		if (rc == WAIT_TIMEOUT) {
+			/* Thread lost. Kill off with TerminateThread. */
+			msyslog(LOG_ERR,
+				"IO completion thread refuses to terminate");
+			TerminateThread(hIoCompletionThread, ~0UL);
+		}
+	}
+
+	/* close the additional main thread handle */
+	if (hMainThread) {
+		CloseHandle(hMainThread);
+		hMainThread = NULL;
 	}
 
-         /* stop using the memory pool */
-	IoCtxPoolDone();
+	/* stop using the memory pool */
+	IOCPLPoolDone();
 
 	/* now reap all handles... */
 	CloseHandle(hIoCompletionThread);
 	hIoCompletionThread = NULL;
-	CloseHandle(hIoCompletionPort);
-	hIoCompletionPort = NULL;
+	CloseHandle(hndIOCPLPort);
+	hndIOCPLPort = NULL;
 }
 
 
@@ -594,8 +352,7 @@ ntpd_addremove_semaphore(
 			break;
 
 	if (remove) {
-		/*
-		 * If found, eventually swap with last entry to keep
+		/* If found, eventually swap with last entry to keep
 		 * the table dense.
 		 */
 		if (hi < ActiveWaitHandles) {
@@ -606,8 +363,7 @@ ntpd_addremove_semaphore(
 			WaitHandles[ActiveWaitHandles] = NULL;
 		}
 	} else {
-		/*
-		 * Make sure the entry is not found and there is enough
+		/* Make sure the entry is not found and there is enough
 		 * room, then append to the table array.
 		 */
 		if (hi >= ActiveWaitHandles) {
@@ -621,12 +377,9 @@ free_io_completion_port_mem(
 
 #ifdef DEBUG
 static void
-free_io_completion_port_mem(
-	void
-	)
-{
-	/*
-	 * At the moment, do absolutely nothing. Returning memory here
+free_io_completion_port_mem(void)
+{
+	/* At the moment, do absolutely nothing. Returning memory here
 	 * requires NO PENDING OVERLAPPED OPERATIONS AT ALL at this
 	 * point in time, and as long we cannot be reasonable sure about
 	 * that the simple advice is:
@@ -636,16 +389,68 @@ free_io_completion_port_mem(
 }
 #endif	/* DEBUG */
 
-
 /*
  * -------------------------------------------------------------------
- * Serial IO stuff
+ * APC callback for scheduling interface scans.
+ *
+ * We get an error when trying to send if the network interface is
+ * gone or has lost link. Rescan interfaces to catch on sooner, but no
+ * more often than once per minute.  Once ntpd is able to detect
+ * changes without polling this should be unnecessary.
+ */
+static void WINAPI
+apcOnUnexpectedNetworkError(
+	ULONG_PTR arg
+	)
+{
+	static u_long time_next_ifscan_after_error;
+
+	UNUSED_ARG(arg);
+
+	if (time_next_ifscan_after_error < current_time) {
+		time_next_ifscan_after_error = current_time + 60;
+		timer_interfacetimeout(current_time);
+	}
+	DPRINTF(4, ("UnexpectedNetworkError: interface may be down\n"));
+}
+
+/* -------------------------------------------------------------------
+ *
+ * Prelude to madness -- common error checking code
  *
- * Prelude -- common error checking code
  * -------------------------------------------------------------------
  */
 extern char * NTstrerror(int err, BOOL *bfreebuf);
 
+static void
+LogIoError(
+	const char *	msg,
+	HANDLE		hnd,
+	DWORD		err
+	)
+{
+	static const char * const rmsg =
+		"LogIoError (unknown source)";
+
+	/* -*- format & print the error message -*-
+	 * We have to resort to the low level error formatting functions
+	 * here, since the error code can come from an overlapped result.
+	 * Relying the value to be the same as the 'GetLastError()'
+	 * result at this point of execution is shaky at best, and using
+	 * 'SetLastError()' to force it seems too nasty.
+	 */
+	BOOL   dynbuf = FALSE;
+	char * msgbuf = NTstrerror(err, &dynbuf);
+	msyslog(LOG_ERR, "%s: hnd=%p, err=%u, '%s'",
+		(msg ? msg : rmsg), hnd, err, msgbuf);
+	if (dynbuf)
+		LocalFree(msgbuf);
+}
+
+/* -------------------------------------------------------------------
+ * synchronous IO request result check (network & serial)
+ * -------------------------------------------------------------------
+ */
 static BOOL
 IoResultCheck(
 	DWORD		err,
@@ -653,153 +458,252 @@ IoResultCheck(
 	const char *	msg
 	)
 {
-	char * msgbuf;
-	BOOL   dynbuf;
-
-	/* If the clock is not / no longer active, assume
-	 * 'ERROR_OPERATION_ABORTED' and do the necessary cleanup.
-	 */
-	if (ctx->rio && !ctx->rio->active)
-		err = ERROR_OPERATION_ABORTED;
-	
-	switch (err)
-	{
+	switch (err) {
 		/* The first ones are no real errors. */
 	case ERROR_SUCCESS:	/* all is good */
 	case ERROR_IO_PENDING:	/* callback pending */
-		return TRUE;
-
-		/* the next ones go silently -- only cleanup is done */
-	case ERROR_INVALID_PARAMETER:	/* handle already closed */
-	case ERROR_OPERATION_ABORTED:	/* handle closed while wait */
 		break;
 
+		/* this defers the error processing to the main thread
+		 * and continues silently.
+		 */
+	case ERROR_UNEXP_NET_ERR:
+		if (hMainThread) {
+			QueueUserAPC(apcOnUnexpectedNetworkError,
+				hMainThread, ctx->io.sfd);
+		}
+		IoCtxRelease(ctx);
+		return FALSE;
 
 	default:
-		/*
-		 * We have to resort to the low level error formatting
-		 * functions here, since the error code can be an
-		 * overlapped result. Relying the value to be the same
-		 * as the 'GetLastError()' result at this point of
-		 * execution is shaky at best, and using SetLastError()
-		 * to force it seems too nasty.
-		 */
-		msgbuf = NTstrerror(err, &dynbuf);
-		msyslog(LOG_ERR, "%s: err=%u, '%s'", msg, err, msgbuf);
-		if (dynbuf)
-			LocalFree(msgbuf);
+		LogIoError(msg, ctx->io.hnd, err);
+		/* the next ones go silently -- only clean-up is done */
+	case ERROR_INVALID_PARAMETER:	/* handle already closed (clock)*/
+	case WSAENOTSOCK	    :	/* handle already closed (socket)*/
+		IoCtxRelease(ctx);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/* -------------------------------------------------------------------
+ * IO callback context check -- serial (non-network) data streams
+ *
+ * Attention: deletes the IO context when the clock is dead!
+ * -------------------------------------------------------------------
+ */
+static RIO_t*
+getRioFromIoCtx(
+	IoCtx_t *	ctx,
+	ULONG_PTR	key,
+	const char *	msg
+	)
+{
+	/* Make sure the key matches the context info in the shared
+	 * lock, the check for errors. If the error indicates the
+	 * operation was cancelled, let the operation fail silently.
+	 */
+	RIO_t *		rio = NULL;
+	SharedLock_t *	slock = slAttachShared(ctx->slock);
+	if (NULL != slock) {
+		rio = slock->rsrc.rio;
+		if (key != slock->rsrc.key)
+			rio = NULL;
+		else if (ctx->io.hnd != slock->handles[0])
+			rio = NULL;
+		slDetachShared(slock);
+	}
+	if (rio != NULL) switch (ctx->errCode) {
+		/* When we got cancelled, don't spill messages */
+	case ERROR_INVALID_PARAMETER:	/* handle already closed (clock) */
+	case ERROR_OPERATION_ABORTED:	/* handle closed while wait      */
+	case WSAENOTSOCK:	/* handle already closed (sock?) */
+		ctx->errCode = ERROR_SUCCESS;
+		rio = NULL;
+	case ERROR_SUCCESS:		/* all is good */
+		break;
+	default:
+		/* log error, but return -- caller has to handle this! */
+		LogIoError(msg, ctx->io.hnd, ctx->errCode);
 		break;
 	}
+	if (rio == NULL)
+		IoCtxRelease(ctx);
+	return rio;
+}
 
-	/* If we end here, we have to mop up the buffer and context */
-	if (ctx->flRawMem) {
-		if (ctx->trans_buf)
-			free(ctx->trans_buf);
-	} else {
-		if (ctx->recv_buf)
-			freerecvbuf(ctx->recv_buf);
-	}
-	IoCtxFree(ctx);
-	return FALSE;
+/* -------------------------------------------------------------------
+ * IO callback context check -- network sockets
+ *
+ * Attention: deletes the IO context when the endpoint is dead!
+ * -------------------------------------------------------------------
+ */
+static endpt*
+getEndptFromIoCtx(
+	IoCtx_t *	ctx,
+	ULONG_PTR	key,
+	const char *	msg
+	)
+{
+	/* Make sure the key matches the context info in the shared
+	 * lock, the check for errors. If the error indicates the
+	 * operation was cancelled, let the operation fail silently.
+	 *
+	 * !Note! Since we use the lowest bit of the key to distinguish
+	 * between regular and broadcast socket, we must make sure the
+	 * LSB is not used in the reverse-link check. Hence we shift
+	 * it out in both the input key and the registered source.
+	 */
+	endpt *		ep    = NULL;
+	SharedLock_t *	slock = slAttachShared(ctx->slock);
+	if (slock != NULL) {
+		ep = slock->rsrc.ept;
+		if ((key >> 1) != (slock->rsrc.key >> 1))
+			ep = NULL;
+		else if (ctx->io.hnd != slock->handles[key & 1])
+			ep = NULL;
+		slDetachShared(slock);
+	}
+	if (ep != NULL) switch (ctx->errCode) {
+	case ERROR_UNEXP_NET_ERR:
+		if (hMainThread)
+			QueueUserAPC(apcOnUnexpectedNetworkError,
+				hMainThread, ctx->io.sfd);
+	case ERROR_INVALID_PARAMETER:	/* handle already closed (clock?)*/
+	case ERROR_OPERATION_ABORTED:	/* handle closed while wait      */
+	case WSAENOTSOCK            :	/* handle already closed (sock)  */
+		ctx->errCode = ERROR_SUCCESS;
+		ep = NULL;
+	case ERROR_SUCCESS:		/* all is good */
+		break;
+	default:
+		/* log error, but return -- caller has to handle this! */
+		LogIoError(msg, ctx->io.hnd, ctx->errCode);
+		ep = NULL;
+		break;
+	}
+	if (NULL == ep)
+		IoCtxRelease(ctx);
+	return ep;
 }
-
 /*
  * -------------------------------------------------------------------
  * Serial IO stuff
  *
  * Part 1 -- COMM event handling
+ *
+ * This is the initial step for serial line input: wait for COM event.
+ * We always check for DCD changes (for user-mode PPS time stamps) and
+ * either a flag char (line feed, for line mode emulation) or any
+ * input character (raw mode). In the callback we decide if we just
+ * have to go on with waiting, or if there is data we must read.
+ * Depending on the mode, we either queue a raw read or a 'regular'
+ * read request.
+ *
+ * !Note! Currently on single IO context circles through the WAIT,
+ * READ and PROCESS stages. For better performance, it might make
+ * sense to have on cycle for the wait, spinning off new read requests
+ * when there is data. There are actually two problems that must be
+ * solved:
+ *  - We would need a queue on post-processing.
+ *  - We have to take care of the order of read results. While the
+ *    IOCPL queue guarantees delivery in the order of enque, the
+ *    order of enque is not guaranteed once multiple reads are in
+ *    flight.
+ *
+ * So, for the time being, we have one request cycling...
  * -------------------------------------------------------------------
  */
 
-static BOOL
+static BOOL __fastcall
 QueueSerialWait(
-	RIO_t *		rio,
-	recvbuf_t *	buff,
-	IoCtx_t *	lpo
+	IoCtx_t *	lpo,
+	recvbuf_t *	buff
 	)
 {
-	BOOL   rc;
-
+	static const char * const msg =
+		"QueueSerialWait: cannot wait for COM event";
+
+	BOOL	rc;
+
+	memset(&lpo->aux, 0, sizeof(lpo->aux));
 	lpo->onIoDone = OnSerialWaitComplete;
 	lpo->recv_buf = buff;
 	lpo->flRawMem = 0;
-	lpo->rio      = rio;
-	buff->fd      = rio->fd;
-
-	rc = WaitCommEvent((HANDLE)_get_osfhandle(rio->fd),
-			   &lpo->com_events, &lpo->ol);
-	if (!rc)
-		return IoResultCheck(GetLastError(), lpo,
-				     "Can't wait on Refclock");
-	return TRUE;
+
+	buff->fd = lpo->slock->riofd;
+	/* keep receive position for continuation of partial lines! */
+	rc  = WaitCommEvent(lpo->io.hnd, &lpo->aux.com_events, &lpo->ol);
+	return rc || IoResultCheck(GetLastError(), lpo, msg);
 }
 
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 static void 
 OnSerialWaitComplete(
-	ULONG_PTR	key,       
+	ULONG_PTR	key,
 	IoCtx_t *	lpo
 	)
 {
-	RIO_t *		rio;
+	static const char * const msg =
+		"OnSerialWaitComplete: wait for COM event failed";
+
 	DevCtx_t *	dev;
-	recvbuf_t * 	buff;
 	PPSDataEx_t *	ppsbuf;
 	DWORD 		modem_status;
 	u_long		covc;
 
-	/* check and bail out if operation failed */
-	if (!IoResultCheck(lpo->errCode, lpo,
-		"WaitCommEvent failed"))
+	/* Make sure this RIO is not closed. */
+	if (NULL == getRioFromIoCtx(lpo, key, msg))
 		return;
 
-	/* get & validate context and buffer. */
-	rio  = (RIO_t *)key;
-	buff = lpo->recv_buf;
-	dev  = lpo->devCtx;
-
-	INSIST(rio == lpo->rio);
+	/* start next IO and leave if we hit an error */
+	if (lpo->errCode != ERROR_SUCCESS) {
+		IoCtxStartLocked(lpo, QueueSerialWait, lpo->recv_buf);
+		return;
+	}
 
 #ifdef DEBUG
-	if (~(EV_RXFLAG | EV_RLSD | EV_RXCHAR) & lpo->com_events) {
+	if (~(EV_RXFLAG | EV_RLSD | EV_RXCHAR) & lpo->aux.com_events) {
 		msyslog(LOG_ERR, "WaitCommEvent returned unexpected mask %x",
-			lpo->com_events);
+			lpo->aux.com_events);
 		exit(-1);
 	}
 #endif
-	/*
-	 * Take note of changes on DCD; 'user mode PPS hack'.
-	 * perlinger at ntp.org suggested a way of solving several problems with
-	 * this code that makes a lot of sense: move to a putative
+	/* Take note of changes on DCD; 'user mode PPS hack'.
+	 * perlinger at ntp.org suggested a way of solving several problems
+	 * with this code that makes a lot of sense: move to a putative
 	 * dcdpps-ppsapi-provider.dll.
-	 */
-	if (EV_RLSD & lpo->com_events) {
+	 *
+	 * perlinger at ntp.org: It came out as loopback-ppsapi-provider
+	 * (because it loops back into NTPD), but I had to maintain the
+	 * old hack for backward compatibility.
+	 */
+	if (EV_RLSD & lpo->aux.com_events) {
 		modem_status = 0;
-		GetCommModemStatus((HANDLE)_get_osfhandle(rio->fd),
-				   &modem_status);
-
-		if (dev != NULL) {
+		GetCommModemStatus(lpo->io.hnd, &modem_status);
+		if (NULL != (dev = lpo->devCtx)) {
 			/* PPS-context available -- use it! */
 			if (MS_RLSD_ON & modem_status) {
 				dev->pps_data.cc_assert++;
-				dev->pps_data.ts_assert = lpo->RecvTime;
-				DPRINTF(2, ("upps-real: fd %d DCD PPS Rise at %s\n", rio->fd,
-					ulfptoa(&lpo->RecvTime, 6)));
+				dev->pps_data.ts_assert = lpo->aux.RecvTime;
+				DPRINTF(2, ("upps-real: fd %d DCD PPS Rise at %s\n",
+					lpo->slock->rsrc.rio->fd,
+					ulfptoa(&lpo->aux.RecvTime, 6)));
 			} else {
 				dev->pps_data.cc_clear++;
-				dev->pps_data.ts_clear = lpo->RecvTime;
-				DPRINTF(2, ("upps-real: fd %d DCD PPS Fall at %s\n", rio->fd,
-					ulfptoa(&lpo->RecvTime, 6)));
-			}
-			/*
-			** Update PPS buffer, writing from low to high, with index
-			** update as last action. We use interlocked ops and a
-			** volatile data destination to avoid reordering on compiler
-			** and CPU level. The interlocked instruction act as full
-			** barriers -- we need only release semantics, but we don't
-			** have them before VS2010.
-			*/
+				dev->pps_data.ts_clear = lpo->aux.RecvTime;
+				DPRINTF(2, ("upps-real: fd %d DCD PPS Fall at %s\n",
+					lpo->slock->rsrc.rio->fd,
+					ulfptoa(&lpo->aux.RecvTime, 6)));
+			}
+			/* Update PPS buffer, writing from low to high, with index
+			 * update as last action. We use interlocked ops and a
+			 * volatile data destination to avoid reordering on compiler
+			 * and CPU level. The interlocked instruction act as full
+			 * barriers -- we need only release semantics, but we don't
+			 * have them before VS2010.
+			 */
 			covc   = dev->cov_count + 1u;
 			ppsbuf = dev->pps_buff + (covc & PPS_QUEUE_MSK);
 			InterlockedExchange((PLONG)&ppsbuf->cov_count, covc);
@@ -807,36 +711,73 @@ OnSerialWaitComplete(
 			InterlockedExchange((PLONG)&dev->cov_count, covc);
 		}
 		/* perlinger at ntp.org, 2012-11-19
-		It can be argued that once you have the PPS API active, you can
-		disable the old pps hack. This would give a behaviour that's much
-		more like the behaviour under a UN*Xish OS. On the other hand, it
-		will give a nasty surprise for people which have until now happily
-		taken the pps hack for granted, and after the first complaint, I have
-		decided to keep the old implementation unconditionally. So here it is:
-
-		/* backward compat: 'usermode-pps-hack' */
+		 * It can be argued that once you have the PPS API active, you can
+		 * disable the old pps hack. This would give a behaviour that's much
+		 * more like the behaviour under a UN*Xish OS. On the other hand, it
+		 * will give a nasty surprise for people which have until now happily
+		 * taken the pps hack for granted, and after the first complaint, I have
+		 * decided to keep the old implementation unconditionally. So here it is:
+		 *
+		 * backward compat: 'usermode-pps-hack'
+		 */
 		if (MS_RLSD_ON & modem_status) {
-			lpo->DCDSTime = lpo->RecvTime;
-			lpo->flTsDCDS = 1;
-			DPRINTF(2, ("upps-hack: fd %d DCD PPS Rise at %s\n", rio->fd,
-				ulfptoa(&lpo->RecvTime, 6)));
+			lpo->aux.DCDSTime = lpo->aux.RecvTime;
+			lpo->aux.flTsDCDS = 1;
+			DPRINTF(2, ("upps-hack: fd %d DCD PPS Rise at %s\n",
+				lpo->slock->rsrc.rio->fd,
+				ulfptoa(&lpo->aux.RecvTime, 6)));
 		}
 	}
 
 	/* If IO ready, read data. Go back waiting else. */
-	if (EV_RXFLAG & lpo->com_events) {		/* line discipline */
-		lpo->FlagTime = lpo->RecvTime;
-		lpo->flTsFlag = 1;
-		QueueSerialRead(rio, buff, lpo);
-	} else if (EV_RXCHAR & lpo->com_events) {	/* raw discipline */
-		lpo->FlagTime = lpo->RecvTime;
-		lpo->flTsFlag = 1;
-		QueueRawSerialRead(rio, buff, lpo);
+	if (EV_RXFLAG & lpo->aux.com_events) {		/* line discipline */
+		lpo->aux.FlagTime = lpo->aux.RecvTime;
+		lpo->aux.flTsFlag = 1;
+		IoCtxStartLocked(lpo, QueueSerialRead, lpo->recv_buf);
+	} else if (EV_RXCHAR & lpo->aux.com_events) {	/* raw discipline */
+		lpo->aux.FlagTime = lpo->aux.RecvTime;
+		lpo->aux.flTsFlag = 1;
+		IoCtxStartLocked(lpo, QueueRawSerialRead, lpo->recv_buf);
 	} else {					/* idle... */
-		QueueSerialWait(rio, buff, lpo);
+		IoCtxStartLocked(lpo, QueueSerialWait, lpo->recv_buf);
 	}
 }
 
+/*
+ * -------------------------------------------------------------------
+ * Serial IO stuff
+ *
+ * common for both modes
+ * -------------------------------------------------------------------
+ */
+static BOOL __fastcall
+QueueSerialReadCommon(
+	IoCtx_t *	lpo,
+	recvbuf_t *	buff
+	)
+{
+	static const char * const msg =
+		"QueueSerialRead: cannot schedule device read";
+
+	BOOL	rc;
+
+	/* 'lpo->onIoDone' must be set already! */
+	lpo->recv_buf = buff;
+	lpo->flRawMem = 0;
+
+	/* 'buff->recv_length' must be set already! */
+	buff->fd        = lpo->slock->riofd;
+	buff->dstadr    = NULL;
+	buff->receiver  = process_refclock_packet;
+	buff->recv_peer = lpo->slock->rsrc.rio->srcclock;
+
+	rc = ReadFile(lpo->io.hnd,
+		(char*)buff->recv_buffer + buff->recv_length,
+		sizeof(buff->recv_buffer) - buff->recv_length,
+		NULL, &lpo->ol);
+	return rc || IoResultCheck(GetLastError(), lpo, msg);
+}
+
 /*
  * -------------------------------------------------------------------
  * Serial IO stuff
@@ -848,37 +789,21 @@ OnSerialWaitComplete(
  * -------------------------------------------------------------------
  */
 
-/*
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  * Start & Queue a serial read for line discipline emulation.
  */
-static BOOL
+static BOOL __fastcall
 QueueSerialRead(
-	RIO_t *		rio,
-	recvbuf_t *	buff,
-	IoCtx_t *	lpo
+	IoCtx_t *	lpo,
+	recvbuf_t *	buff
 	)
 {
-	BOOL   rc;
-
 	lpo->onIoDone = &OnSerialReadComplete;
-	lpo->recv_buf = buff;
-	lpo->flRawMem = 0;
-	lpo->rio      = rio;
-	buff->fd      = rio->fd;
-
-	rc = ReadFile((HANDLE)_get_osfhandle(rio->fd),
-		      (char*)buff->recv_buffer  + buff->recv_length,
-		      sizeof(buff->recv_buffer) - buff->recv_length,
-		      NULL, &lpo->ol);
-	if (!rc)
-		return IoResultCheck(GetLastError(), lpo,
-				     "Can't read from Refclock");
-	return TRUE;
+	/* keep 'buff->recv_length' for line continuation! */
+	return QueueSerialReadCommon(lpo, buff);
 }
 
-/*
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  * IO completion thread callback. Takes a time stamp and offloads the
  * real work to the worker pool ASAP.
  */
@@ -888,27 +813,31 @@ OnSerialReadComplete(
 	IoCtx_t *	lpo
 	)
 {
-	RIO_t *		rio;
-	recvbuf_t *	buff;
-
-	/* check and bail out if operation failed */
-	if (!IoResultCheck(lpo->errCode, lpo,
-			   "Read from Refclock failed"))
+	static const char * const msg =
+		"OnSerialReadComplete: read from device failed";
+
+	/* Make sure this RIO is not closed. */
+	if (NULL == getRioFromIoCtx(lpo, key, msg))
 		return;
 
-	/* get & validate context and buffer. */
-	rio  = lpo->rio;
-	buff = lpo->recv_buf;
-	INSIST((ULONG_PTR)rio == key);
-
-	/* Offload to worker pool */
-	if (!QueueUserWorkItem(&OnSerialReadWorker, lpo, WT_EXECUTEDEFAULT)) {
-		msyslog(LOG_ERR,
-			"Can't offload to worker thread, will skip data: %m");
-		IoCtxReset(lpo);
-		buff->recv_length = 0;
-		QueueSerialWait(rio, buff, lpo);
-	}
+	/* start next IO and leave if we hit an error */
+	if (lpo->errCode != ERROR_SUCCESS)
+		goto wait_again;
+
+	/* Offload to worker pool, if there is data */
+	if (lpo->byteCount == 0)
+		goto wait_again;
+
+	if (QueueUserWorkItem(&OnSerialReadWorker, lpo, WT_EXECUTEDEFAULT))
+		return;	/* successful regular exit! */
+
+	/* croak as we're throwing away data */
+	msyslog(LOG_ERR,
+		"Can't offload to worker thread, will skip data: %m");
+
+wait_again:
+	/* make sure the read is issued again */
+	IoCtxStartLocked(lpo, QueueSerialWait, lpo->recv_buf);
 }
 
 
@@ -921,38 +850,64 @@ OnSerialReadComplete(
  * discipline. Since this involves allocation of additional buffers and
  * string parsing/copying, it is offloaded to the worker thread pool so
  * the IO completion thread can resume faster.
+ *
+ * !!ATTENTION!!
+ * This function runs on an arbitrary worker thread, and not under the
+ * protection of the shared lock! Accessing the RIO structure must set
+ * the lock explicitely!
  */
 static DWORD WINAPI
-OnSerialReadWorker(void * ctx)
+OnSerialReadWorker(
+void * ctx
+)
 {
 	IoCtx_t *	lpo;
+	SharedLock_t *	slock;
 	recvbuf_t *	buff, *obuf;
-	RIO_t *		rio;
 	char		*sptr, *send, *dptr;
 	BOOL		eol;
 	char		ch;
+	BOOL		active;
+	u_long		rcvcnt;
+	RIO_t *		rio;
 
 	/* Get context back */
 	lpo  = (IoCtx_t*)ctx;
 	buff = lpo->recv_buf;
-	rio  = lpo->rio;
-	/*
-	 * ignore 0 bytes read due to closure on fd.
+
+	/* query the lock structure under mutual exclusion */
+	active = FALSE;
+	rcvcnt = 0;
+	if (NULL != (slock = slAttachShared(lpo->slock))) {
+		if (NULL != (rio = slock->rsrc.rio)) {
+			active = TRUE;
+			rcvcnt = InterlockedIncrement(&rio->recvcount) - 1;
+		}
+		slDetachShared(slock);
+	}
+
+	/* bail out if we're disconnected now */
+	if (!active) {
+		IoCtxRelease(ctx);
+		return 0;
+	}
+
+	/* Ignore zero-byte reads due to closure on fd.
 	 * Eat the first line of input as it's possibly partial.
 	 */
-	if (lpo->byteCount && rio->recvcount++) {
+	if (lpo->byteCount && rcvcnt) {
 		/* account for additional input */
 		buff->recv_length += (int)lpo->byteCount;
 
 		/*
-		 * Now mimic the Unix line discipline. 
+		 * Now mimic the Unix line discipline.
 		 */
 		sptr = (char *)buff->recv_buffer;
 		send = sptr + buff->recv_length;
 		obuf = NULL;
 		dptr = NULL;
 
-		/* hack #1: eat away leading CR/LF if here is any */
+		/* hack #1: eat away leading CR/LF if there is any */
 		while (sptr != send) {
 			ch = *sptr;
 			if (ch != '\n' && ch != '\r')
@@ -960,51 +915,47 @@ OnSerialReadWorker(void * ctx)
 			sptr++;
 		}
 
-		while (sptr != send)
-		{
+		while (sptr != send) {
 			/* get new buffer to store line */
 			obuf = get_free_recv_buffer_alloc();
-			obuf->fd          = rio->fd;
-			obuf->receiver    = &process_refclock_packet;
-			obuf->dstadr      = NULL;
-			obuf->recv_peer   = rio->srcclock;
+			obuf->fd        = buff->fd;
+			obuf->receiver  = buff->receiver;
+			obuf->dstadr    = NULL;
+			obuf->recv_peer = buff->recv_peer;
 			set_serial_recv_time(obuf, lpo);
 
-			/*
-			 * Copy data to new buffer, convert CR to LF on
+			/* Copy data to new buffer, convert CR to LF on
 			 * the fly.  Stop after either.
 			 */
 			dptr = (char *)obuf->recv_buffer;
-			eol  = FALSE;
+			eol = FALSE;
 			while (sptr != send && !eol) {
-				ch  = *sptr++;
-				if ('\r' == ch) {
+				ch = *sptr++;
+				if ('\r' == ch)
 					ch = '\n';
-				}
 				*dptr++ = ch;
 				eol = ('\n' == ch);
 			}
 			obuf->recv_length =
-			    (int)(dptr - (char *)obuf->recv_buffer);
-
-			/*
-			 * If NL found, push this buffer and prepare to
-			 * get a new one.
+				(int)(dptr - (char *)obuf->recv_buffer);
+
+			/* If NL found, push this buffer and prepare to
+			 * get a new one. Be prepared for concurrent
+			 * removal of the clock...
 			 */
 			if (eol) {
-				add_full_recv_buffer(obuf);
-				SetEvent(WaitableIoEventHandle);
-				obuf = NULL;
+				slQueueLocked(lpo->slock, slRefClockOK, obuf);
+				obuf = NULL; /* consumed in any case */
 			}
 		}
 
-		/*
-		 * If we still have an output buffer, continue to fill
-		 * it again.
+		/* If we still have an output buffer, prepare it to be
+		 * used for added input from the ComPort. Otherwise
+		 * use the current input buffer again.
 		 */
 		if (obuf) {
 			obuf->recv_length =
-			    (int)(dptr - (char *)obuf->recv_buffer);
+				(int)(dptr - (char *)obuf->recv_buffer);
 			freerecvbuf(buff);
 			buff = obuf;
 		} else {
@@ -1015,8 +966,8 @@ OnSerialReadWorker(void * ctx)
 		buff->recv_length = 0;
 	}
 
-	IoCtxReset(lpo);
-	QueueSerialWait(rio, buff, lpo);
+	/* start next round -- must hold the lock during that! */
+	IoCtxStartLocked(lpo, QueueSerialWait, buff);
 	return 0;
 }
 
@@ -1032,89 +983,67 @@ static BOOL
  * -------------------------------------------------------------------
  */
 
-static BOOL
+static BOOL __fastcall
 QueueRawSerialRead(
-	RIO_t *		rio,
-	recvbuf_t *	buff,
-	IoCtx_t *	lpo
+	IoCtx_t *	lpo,
+	recvbuf_t *	buff
 	)
 {
-	BOOL   rc;
-
-	lpo->onIoDone = OnRawSerialReadComplete;
-	lpo->recv_buf = buff;
-	lpo->flRawMem = 0;
-	lpo->rio      = rio;
-	buff->fd      = rio->fd;
-
-	rc = ReadFile((HANDLE)_get_osfhandle(rio->fd),
-		      buff->recv_buffer,
-		      sizeof(buff->recv_buffer),
-		      NULL, &lpo->ol);
-	if (!rc)
-		return IoResultCheck(GetLastError(), lpo,
-				     "Can't read raw from Refclock");
-	return TRUE;
+	lpo->onIoDone     = OnRawSerialReadComplete;
+	buff->recv_length = 0;
+	return QueueSerialReadCommon(lpo, buff);
 }
 
-
-static void 
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * IO completion thread callback. Takes a time stamp and offloads the
+ * real work to the worker pool ASAP.
+ */
+static void
 OnRawSerialReadComplete(
 	ULONG_PTR	key,
 	IoCtx_t *	lpo
 	)
 {
-	RIO_t *		rio;
-	recvbuf_t *	buff;
-
-	/* check and bail out if operation failed */
-	if (!IoResultCheck(lpo->errCode, lpo,
-			   "Raw read from Refclock failed"))
+	static const char * const msg =
+		"OnRawSerialReadComplete: read from device failed";
+
+	recvbuf_t *	buff = lpo->recv_buf;
+	RIO_t *		rio  = getRioFromIoCtx(lpo, key, msg);
+	/* Make sure this RIO is not closed. */
+	if (rio == NULL)
 		return;
 
-	/* get & validate context and buffer. */
-	rio  = lpo->rio;
-	buff = lpo->recv_buf;
-	INSIST((ULONG_PTR)rio == key);
-
-	/* ignore 0 bytes read. */
-	if (lpo->byteCount > 0) {
+	/* start next IO and leave if we hit an error */
+	if (lpo->errCode == ERROR_SUCCESS && lpo->byteCount > 0) {
 		buff->recv_length = (int)lpo->byteCount;
-		buff->dstadr      = NULL;
-		buff->receiver    = process_refclock_packet;
-		buff->recv_peer   = rio->srcclock;
 		set_serial_recv_time(buff, lpo);
-		add_full_recv_buffer(buff);
-		SetEvent(WaitableIoEventHandle);
+		slQueueLocked(lpo->slock, slRefClockOK, buff);
 		buff = get_free_recv_buffer_alloc();
 	}
-
-	buff->recv_length = 0;
-	QueueSerialWait(rio, buff, lpo);
+	IoCtxStartLocked(lpo, QueueSerialWait, buff);
 }
 
 
-static inline void
+static void
 set_serial_recv_time(
 	recvbuf_t *	obuf,
 	IoCtx_t *	lpo
 	)
 {
-	/*
-	 * Time stamp assignment is interesting.  If we
+	/* Time stamp assignment is interesting.  If we
 	 * have a DCD stamp, we use it, otherwise we use
 	 * the FLAG char event time, and if that is also
 	 * not / no longer available we use the arrival
 	 * time.
 	 */
-	if (lpo->flTsDCDS)
-		obuf->recv_time = lpo->DCDSTime;
-	else if (lpo->flTsFlag)
-		obuf->recv_time = lpo->FlagTime;
+	if (lpo->aux.flTsDCDS)
+		obuf->recv_time = lpo->aux.DCDSTime;
+	else if (lpo->aux.flTsFlag)
+		obuf->recv_time = lpo->aux.FlagTime;
 	else
-		obuf->recv_time = lpo->RecvTime;
-
-	lpo->flTsDCDS = lpo->flTsFlag = 0; /* use only once... */
+		obuf->recv_time = lpo->aux.RecvTime;
+
+	lpo->aux.flTsDCDS = lpo->aux.flTsFlag = 0; /* use only once! */
 }
 
 
@@ -1138,30 +1067,41 @@ async_write(
 	unsigned int	count
 	)
 {
-	IoCtx_t *	lpo;
+	static const char * const msg =
+		"async_write: cannot schedule device write";
+	static const char * const dmsg =
+		"overlapped IO data buffer";
+
+	IoCtx_t *	lpo  = NULL;
+	void *		buff = NULL;
+	HANDLE		hnd  = NULL;
 	BOOL		rc;
 
-	lpo  = IoCtxAlloc(NULL);
-	if (lpo == NULL) {
-		DPRINTF(1, ("async_write: out of memory\n"));
-		errno = ENOMEM;
-		return -1;
-	}
-
+	hnd = (HANDLE)_get_osfhandle(fd);
+	if (hnd == INVALID_HANDLE_VALUE)
+		goto fail;
+	if (NULL == (buff = IOCPLPoolMemDup(data, count, dmsg)))
+		goto fail;
+	if (NULL == (lpo = IoCtxAlloc(NULL, NULL)))
+		goto fail;
+
+	lpo->io.hnd    = hnd;
 	lpo->onIoDone  = OnSerialWriteComplete;
-	lpo->trans_buf = emalloc(count);
+	lpo->trans_buf = buff;
 	lpo->flRawMem  = 1;
-	memcpy(lpo->trans_buf, data, count);
-
-	rc = WriteFile((HANDLE)_get_osfhandle(fd),
-		       lpo->trans_buf, count,
+
+	rc = WriteFile(lpo->io.hnd, lpo->trans_buf, count,
 		       NULL, &lpo->ol);
-	if (!rc && !IoResultCheck(GetLastError(), lpo,
-				  "Can't write to Refclock")) {
-		errno = EBADF;
-		return -1;
-	}
-	return count;
+	if (rc || IoResultCheck(GetLastError(), lpo, msg))
+		return count;	/* normal/success return */
+
+	errno = EBADF;
+	return -1;
+
+fail:
+	IoCtxFree(lpo);
+	IOCPLPoolFree(buff, dmsg);
+	return -1;
 }
 
 static void
@@ -1170,12 +1110,15 @@ OnSerialWriteComplete(
 	IoCtx_t *	lpo
 	)
 {
-	/* set RIO and force silent cleanup if no error */
-	lpo->rio = (RIO_t *)key;
-	if (ERROR_SUCCESS == lpo->errCode)
-		lpo->errCode = ERROR_OPERATION_ABORTED;
-	IoResultCheck(lpo->errCode, lpo,
-		      "Write to Refclock failed");
+	/* This is really trivial: Let 'getRioFromIoCtx()' do all the
+	 * error processing, and it returns with a valid RIO, just
+	 * drop the complete context.
+	 */
+	static const char * const msg =
+		"OnSerialWriteComplete: serial output failed";
+
+	if (NULL != getRioFromIoCtx(lpo, key, msg))
+		IoCtxRelease(lpo);
 }
 
 
@@ -1202,7 +1145,7 @@ OnPpsDummyRead(
 	RIO_t *	rio;
 
 	rio = (RIO_t *)key;
-	lpo->devCtx = DevCtxAttach(rio->device_context);
+	lpo->devCtx = DevCtxAttach(rio->device_ctx);
 	SetEvent(lpo->ppswake);
 }
 
@@ -1224,7 +1167,7 @@ ntp_pps_attach_device(
 	ZERO(myIoCtx);
 	dev   = NULL;
 	myEvt = CreateEvent(NULL, FALSE, FALSE, NULL);
-	if (NULL == myEvt)
+	if (myEvt == NULL)
 		goto done;
 
 	myIoCtx.ppswake   = myEvt;
@@ -1271,22 +1214,21 @@ ntp_pps_read(
 		SetLastError(ERROR_INVALID_PARAMETER);
 		return FALSE;
 	}
-	/*
-	** Reading from shared memory in a lock-free fashion can be
-	** a bit tricky, since we have to read the components in the
-	** opposite direction from the write, and the compiler must
-	** not reorder the read sequence.
-	** We use interlocked ops and a volatile data source to avoid
-	** reordering on compiler and CPU level. The interlocked
-	** instruction act as full barriers -- we need only aquire
-	** semantics, but we don't have them before VS2010.
-	*/
+	/* Reading from shared memory in a lock-free fashion can be
+	 * a bit tricky, since we have to read the components in the
+	 * opposite direction from the write, and the compiler must
+	 * not reorder the read sequence.
+	 * We use interlocked ops and a volatile data source to avoid
+	 * reordering on compiler and CPU level. The interlocked
+	 * instruction act as full barriers -- we need only acquire
+	 * semantics, but we don't have them before VS2010.
+	 */
 	repc = 3;
 	do {
-		InterlockedExchange((PLONG)&covc, dev->cov_count);
+		covc = InterlockedExchangeAdd((PLONG)&dev->cov_count, 0);
 		ppsbuf = dev->pps_buff + (covc & PPS_QUEUE_MSK);
 		*data = ppsbuf->data;
-		InterlockedExchange((PLONG)&guard, ppsbuf->cov_count);
+		guard = InterlockedExchangeAdd((PLONG)&ppsbuf->cov_count, 0);
 		guard ^= covc;
 	} while (guard && ~guard && --repc);
 
@@ -1297,217 +1239,368 @@ ntp_pps_read(
 	return TRUE;
 }
 
-/*
- * Add a reference clock data structures I/O handles to
- * the I/O completion port. Return 1 if any error.
+/* --------------------------------------------------------------------
+ * register and unregister refclock IOs with the IO engine
+ * --------------------------------------------------------------------
+ */
+
+/* Add a reference clock data structures I/O handles to
+ * the I/O completion port. Return FALSE if any error,
+ * TRUE on success
  */  
-int
+BOOL
 io_completion_port_add_clock_io(
 	RIO_t *rio
 	)
 {
+	static const char * const msgh =
+		"io_completion_port_add_clock_io";
+
 	IoCtx_t *	lpo;
-	DevCtx_t *	dev;
-	recvbuf_t *	buff;
 	HANDLE		h;
+	SharedLock_t *	slock = NULL;
+
+	/* preset to clear state for error cleanup:*/
+	rio->ioreg_ctx  = NULL;
+	rio->device_ctx = NULL;
 
 	h = (HANDLE)_get_osfhandle(rio->fd);
-	if (NULL == CreateIoCompletionPort(
-			h, 
-			hIoCompletionPort, 
-			(ULONG_PTR)rio,
-			0)) {
-		msyslog(LOG_ERR, "Can't add COM port to i/o completion port: %m");
-		return 1;
+	if (h == INVALID_HANDLE_VALUE) {
+		msyslog(LOG_ERR, "%s: COM port FD not valid",
+			msgh);
+		goto fail;
 	}
 
-	dev = DevCtxAlloc();
-	if (NULL == dev) {
-		msyslog(LOG_ERR, "Can't allocate device context for i/o completion port: %m");
-		return 1;
-	}
-	rio->device_context = DevCtxAttach(dev);
-	lpo = IoCtxAlloc(dev);
-	if (NULL == lpo) {
-		msyslog(LOG_ERR, "Can't allocate heap for completion port: %m");
-		return 1;
-	}
-	buff = get_free_recv_buffer_alloc();
-	buff->recv_length = 0;
-	QueueSerialWait(rio, buff, lpo);
+	;
+	if ( ! (rio->ioreg_ctx = slock = slCreate(rio))) {
+		msyslog(LOG_ERR, "%s: Failed to create shared lock",
+			msgh);
+		goto fail;
+	}
+	slock->handles[0] = h;
+	slock->riofd      = rio->fd;
+	slock->rsrc.rio   = rio;
+
+	if ( ! (rio->device_ctx = DevCtxAlloc())) {
+		msyslog(LOG_ERR, "%s: Failed to allocate device context",
+			msgh);
+		goto fail;
+	}
+
+	if ( ! (lpo = IoCtxAlloc(slock, rio->device_ctx))) {
+		msyslog(LOG_ERR, "%: Failed to allocate IO context",
+			msgh);
+		goto fail;
+	}
 
-	return 0;
+	if ( ! CreateIoCompletionPort(h, hndIOCPLPort, (ULONG_PTR)rio, 0)) {
+		msyslog(LOG_ERR, "%s: Can't add COM port to i/o completion port: %m",
+			msgh);
+		goto fail;
+	}
+	lpo->io.hnd = h;
+	return QueueSerialWait(lpo, get_free_recv_buffer_alloc());
+
+fail:
+	rio->ioreg_ctx  = slDetach(rio->ioreg_ctx);
+	rio->device_ctx = DevCtxDetach(rio->device_ctx);
+	return FALSE;
 }
 
+/* ----------------------------------------------------------------- */
 void
 io_completion_port_remove_clock_io(
 	RIO_t *rio
 	)
 {
-	if (rio)
-		DevCtxDetach((DevCtx_t *)rio->device_context);
+	SharedLock_t *	slock = NULL;
+	if (rio && NULL != (slock = slAttachExclusive(rio->ioreg_ctx))) {
+		slDetach(slock);
+
+		slock->handles[0] = INVALID_HANDLE_VALUE;
+		slock->handles[1] = INVALID_HANDLE_VALUE;
+		slock->rsrc.rio   = NULL;
+		slock->riofd      = -1;
+
+		rio->device_ctx = DevCtxDetach(rio->device_ctx);
+		rio->ioreg_ctx  = slDetachExclusive(slock);
+	}
 }
 
 /*
- * Queue a receiver on a socket. Returns 0 if no buffer can be queued 
- *
- *  Note: As per the winsock documentation, we use WSARecvFrom. Using
- *	  ReadFile() is less efficient.
- */
-static BOOL 
+ * -------------------------------------------------------------------
+ * Socket IO stuff
+ * -------------------------------------------------------------------
+ */
+
+/* Queue a receiver on a socket. Returns 0 if no buffer can be queued 
+ *
+ *  Note: As per the WINSOCK documentation, we use WSARecvFrom. Using
+ *	  ReadFile() is less efficient. Also, WSARecvFrom delivers
+ *	  the remote network address. With ReadFile, getting this
+ *	  becomes a chore.
+ */
+static BOOL __fastcall
 QueueSocketRecv(
-	SOCKET		s,
-	recvbuf_t *	buff,
-	IoCtx_t *	lpo
+	IoCtx_t *	lpo,
+	recvbuf_t *	buff
 	)
 {
-	WSABUF wsabuf;
-	DWORD  Flags;
-	int    rc;
+	static const char * const msg =
+		"QueueSocketRecv: cannot schedule socket receive";
+
+	WSABUF	wsabuf;
+	DWORD	Flags;
+	int	rc;
 
 	lpo->onIoDone = OnSocketRecv;
 	lpo->recv_buf = buff;
 	lpo->flRawMem = 0;
-	lpo->rio      = NULL;
-
-	Flags = 0;
-	buff->fd = s;
+	
+	buff->fd              = lpo->io.sfd;
 	buff->recv_srcadr_len = sizeof(buff->recv_srcadr);
+	buff->receiver        = receive;
+	buff->dstadr          = lpo->slock->rsrc.ept;
+
 	wsabuf.buf = (char *)buff->recv_buffer;
 	wsabuf.len = sizeof(buff->recv_buffer);
 
-	rc = WSARecvFrom(buff->fd, &wsabuf, 1, NULL, &Flags, 
+	Flags = 0;	/* in/out parameter, must be valid! */
+	rc = WSARecvFrom(lpo->io.sfd, &wsabuf, 1, NULL, &Flags,
 			 &buff->recv_srcadr.sa, &buff->recv_srcadr_len, 
 			 &lpo->ol, NULL);
-	if (SOCKET_ERROR == rc) 
-		return IoResultCheck(GetLastError(), lpo,
-				     "Can't read from Socket");
-	return TRUE;
+	return !rc || IoResultCheck((DWORD)WSAGetLastError(), lpo, msg);
 }
 
-
-static void 
+/* ----------------------------------------------------------------- */
+static void
 OnSocketRecv(
 	ULONG_PTR	key,
 	IoCtx_t *	lpo
 	)
 {
-	recvbuf_t * buff;
-	recvbuf_t * newbuff;
-	struct interface * inter = (struct interface *)key;
-	
-	REQUIRE(NULL != lpo);
-	REQUIRE(NULL != lpo->recv_buf);
-
-	/* check and bail out if operation failed */
-	if (!IoResultCheck(lpo->errCode, lpo,
-			   "Read from Socket failed"))
+	static const char * const msg =
+		"OnSocketRecv: receive from socket failed";
+
+	recvbuf_t *	buff    = NULL;
+	SharedLock_t *	slock   = NULL;
+
+	/* Make sure this endpoint is not closed. */
+	endpt *	ep = getEndptFromIoCtx(lpo, key, msg);
+	if (ep == NULL)
 		return;
 
-	/*
-	 * Convert the overlapped pointer back to a recvbuf pointer.
-	 * Fetch items that are lost when the context is queued again.
-	 */
-	buff = lpo->recv_buf;
-	buff->recv_time   = lpo->RecvTime;
-	buff->recv_length = (int)lpo->byteCount;
-
-	/*
-	 * Get a new recv buffer for the replacement socket receive
-	 */
-	newbuff = get_free_recv_buffer_alloc();
-	if (NULL != newbuff) {
-		QueueSocketRecv(inter->fd, newbuff, lpo);
-	} else {
-		IoCtxFree(lpo);
-		msyslog(LOG_ERR, "Can't add I/O request to socket");
-	}
-	DPRINTF(4, ("%sfd %d %s recv packet mode is %d\n", 
-		    (MODE_BROADCAST == get_packet_mode(buff))
+	/* We want to start a new read before we process the buffer.
+	 * Since we must not use the context object once it is in
+	 * another IO, we go through some pains to read everything
+	 * before going out for another read request.
+	 * We also need an extra hold to the SLOCK structure.
+	 */
+	slock = slAttach(lpo->slock);
+	if (lpo->errCode == ERROR_SUCCESS && lpo->byteCount > 0) {
+		/* keep input buffer, create new one for IO */
+		buff              = lpo->recv_buf;
+		lpo->recv_buf     = get_free_recv_buffer_alloc();
+
+		buff->recv_time   = lpo->aux.RecvTime;
+		buff->recv_length = (int)lpo->byteCount;
+
+	} /* Note: else we use the current buffer again */
+	IoCtxStartLocked(lpo, QueueSocketRecv, lpo->recv_buf);
+	/* below this, any usage of 'lpo' is invalid! */
+
+	/* If we have a buffer, do some bookkeeping and other chores,
+	 * then feed it to the input queue. And we can be sure we have
+	 * a packet here, so we can update the stats.
+	 */
+	if (buff != NULL) {
+		INSIST(buff->recv_srcadr_len <= sizeof(buff->recv_srcadr));
+		DPRINTF(4, ("%sfd %d %s recv packet mode is %d\n",
+			(MODE_BROADCAST == get_packet_mode(buff))
 			? " **** Broadcast "
 			: "",
-		    (int)buff->fd, stoa(&buff->recv_srcadr),
-		    get_packet_mode(buff)));
-
-	/*
-	 * If we keep it add some info to the structure
-	 */
-	if (buff->recv_length && !inter->ignore_packets) {
-		INSIST(buff->recv_srcadr_len <= sizeof(buff->recv_srcadr));
-		buff->receiver = &receive; 
-		buff->dstadr   = inter;
-		packets_received++;
-		handler_pkts++;
-		inter->received++;
-		add_full_recv_buffer(buff);
-
-		DPRINTF(2, ("Received %d bytes fd %d in buffer %p from %s\n", 
-			    buff->recv_length, (int)buff->fd, buff,
-			    stoa(&buff->recv_srcadr)));
+			(int)buff->fd, stoa(&buff->recv_srcadr),
+			get_packet_mode(buff)));
+
+		if (slAttachShared(slock)) {
+			BOOL epOK = slEndPointOK(slock);
+			if (epOK)
+				InterlockedIncrement(&slock->rsrc.ept->received);
+			slDetachShared(slock);
+			if (epOK) {
+				InterlockedIncrement(&packets_received);
+				InterlockedIncrement(&handler_pkts);
+			}
+		}
 
-		/*
-		 * Now signal we have something to process
-		 */
-		SetEvent(WaitableIoEventHandle);
-	} else
-		freerecvbuf(buff);
+		DPRINTF(2, ("Received %d bytes fd %d in buffer %p from %s\n",
+			buff->recv_length, (int)buff->fd, buff,
+			stoa(&buff->recv_srcadr)));
+		slQueueLocked(slock, slEndPointOK, buff);
+	}
+	slDetach(slock);
 }
 
+/* ----------------------------------------------------------------- */
+static void
+OnSocketSend(
+	ULONG_PTR	key,
+	IoCtx_t *	lpo
+	)
+{
+	/* this is somewhat easier: */
+	static const char * const msg =
+		"OnSocketRecv: send to socket failed";
+
+	SharedLock_t *	slock = NULL;
+	endpt *		ep    = getEndptFromIoCtx(lpo, key, msg);
+	/* Make sure this endpoint is not closed. */
+	if (ep == NULL)
+		return;
 
-/*
- * Add a socket handle to the I/O completion port, and send 
- * NTP_RECVS_PER_SOCKET recv requests to the kernel.
+	if (lpo->errCode != ERROR_SUCCESS)
+		slock = slAttachShared(lpo->slock);
+	if (slock) {
+		BOOL epOK = slEndPointOK(slock);
+		if (epOK) {
+			InterlockedIncrement(&slock->rsrc.ept->notsent);
+			InterlockedDecrement(&slock->rsrc.ept->sent);
+		}
+		slDetachShared(slock);
+		if (epOK) {
+			InterlockedIncrement(&packets_notsent);
+			InterlockedDecrement(&packets_sent);
+		}
+	}
+	IoCtxRelease(lpo);
+}
+
+/* --------------------------------------------------------------------
+ * register and de-register interface endpoints with the IO engine
+ * --------------------------------------------------------------------
+ */
+BOOL
+io_completion_port_add_interface(
+	endpt *	ep
+	)
+{
+	/* Registering an endpoint is simple: allocate a shared lock for
+	 * the enpoint and return if the allocation was successful.
+	 */
+	ep->ioreg_ctx = slCreate(ep);
+	return ep->ioreg_ctx != NULL;
+}
+/* ----------------------------------------------------------------- */
+void
+io_completion_port_remove_interface(
+	endpt *	ep
+	)
+{
+	/* Removing an endpoint is simple, too: Lock the shared lock
+	 * for write access, then invalidate the handles and the
+	 * endpoint pointer. Do an additional detach and leave the
+	 * write lock.
+	 */
+	SharedLock_t *	slock = slAttachExclusive(ep->ioreg_ctx);
+	if (slock != NULL) {
+		slDetach(slock);
+
+		slock->handles[0] = INVALID_HANDLE_VALUE;
+		slock->handles[1] = INVALID_HANDLE_VALUE;
+		slock->rsrc.ept   = NULL;
+
+		ep->ioreg_ctx = slDetachExclusive(slock);
+	}
+}
+
+/* --------------------------------------------------------------------
+ * register and de-register sockets for an endpoint
+ * --------------------------------------------------------------------
  */
-int
+
+/* Add a socket handle to the I/O completion port, and send 
+ * NTP_RECVS_PER_SOCKET receive requests to the kernel.
+ */
+BOOL
 io_completion_port_add_socket(
-	SOCKET			fd,
-	struct interface *	inter
+	SOCKET	sfd,
+	endpt *	ep,
+	BOOL	bcast
 	)
 {
+	/* Assume the endpoint is already registered. Set the socket
+	 * handle into the proper slot, and then start up the IO engine.
+	 */
+	static const char * const msg =
+		"Can't add socket to i/o completion port";
+
 	IoCtx_t *	lpo;
-	recvbuf_t *	buff;
-	int		n;
-
-	if (fd != INVALID_SOCKET) {
-		if (NULL == CreateIoCompletionPort((HANDLE)fd, 
-		    hIoCompletionPort, (ULONG_PTR)inter, 0)) {
-			msyslog(LOG_ERR,
-				"Can't add socket to i/o completion port: %m");
-			return 1;
-		}
+	size_t		n;
+	ULONG_PTR	key;
+	SharedLock_t *	slock = NULL;
+
+	key = ((ULONG_PTR)ep & ~(ULONG_PTR)1u) + !!bcast;
+
+	if (NULL == (slock = slAttachExclusive(ep->ioreg_ctx))) {
+		msyslog(LOG_CRIT, "io_completion_port_add_socket: endpt = %p not registered, exiting",
+			ep);
+		exit(1);
+	} else {
+		endpt *	rep = slock->rsrc.ept;
+		slock->handles[!!bcast] = (HANDLE)sfd;
+		slDetachExclusive(slock);
+		INSIST(rep == ep);
 	}
 
-	/*
-	 * Windows 2000 bluescreens with bugcheck 0x76
-	 * PROCESS_HAS_LOCKED_PAGES at ntpd process
-	 * termination when using more than one pending
-	 * receive per socket.  A runtime version test
-	 * would allow using more on newer versions
-	 * of Windows.
-	 */
-
-#define WINDOWS_RECVS_PER_SOCKET 1
-
-	for (n = 0; n < WINDOWS_RECVS_PER_SOCKET; n++) {
-
-		buff = get_free_recv_buffer_alloc();
-		lpo = IoCtxAlloc(NULL);
-		if (lpo == NULL)
-		{
-			msyslog(LOG_ERR
-				, "Can't allocate IO completion context: %m");
-			return 1;
-		}
-
-		QueueSocketRecv(fd, buff, lpo);
+	if (NULL == CreateIoCompletionPort((HANDLE)sfd,
+		hndIOCPLPort, key, 0))
+	{
+		msyslog(LOG_ERR, "%s: %m", msg);
+		goto fail;
+	}
+	for (n = s_SockRecvSched; n > 0; --n) {
+		if (NULL == (lpo = IoCtxAlloc(ep->ioreg_ctx, NULL))) {
+			msyslog(LOG_ERR, "%s: no read buffer: %m", msg);
+			goto fail;
+		}
+		lpo->io.sfd = sfd;
+		if (!QueueSocketRecv(lpo, get_free_recv_buffer_alloc()))
+			goto fail;
+	}
+	return TRUE;
 
+fail:
+	ep->ioreg_ctx = slDetach(ep->ioreg_ctx);
+	return FALSE;
+}
+/* ----------------------------------------------------------------- */
+void
+io_completion_port_remove_socket(
+	SOCKET	fd,
+	endpt *	ep
+	)
+{
+	/* Lock the shared lock for write, then search the given
+	 * socket handle and replace it with an invalid handle value.
+	 */
+	SharedLock_t *	lp = slAttachExclusive(ep->ioreg_ctx);
+	HANDLE		sh = (HANDLE)fd;
+	if (lp != NULL) {
+		if (lp->handles[0] == sh)
+			lp->handles[0] = INVALID_HANDLE_VALUE;
+		else if (lp->handles[1] == sh)
+			lp->handles[1] = INVALID_HANDLE_VALUE;
+		slDetachExclusive(lp);
 	}
-	return 0;
 }
 
 
-/*
- * io_completion_port_sendto() -- sendto() replacement for Windows
+/* --------------------------------------------------------------------
+ * I/O API functions for endpoints / interfaces
+ * --------------------------------------------------------------------
+ */
+
+/* io_completion_port_sendto() -- sendto() replacement for Windows
  *
  * Returns len after successful send.
  * Returns -1 for any error, with the error code available via
@@ -1515,73 +1608,65 @@ io_completion_port_sendto(
  */
 int
 io_completion_port_sendto(
-	SOCKET		fd,
+	endpt *		ep,
+	SOCKET		sfd,
 	void  *		pkt,
 	size_t		len,
 	sockaddr_u *	dest
 	)
 {
-	static u_long time_next_ifscan_after_error;
-	WSABUF wsabuf;
-	DWORD octets_sent;
-	DWORD Result;
-	int errval;
-	int AddrLen;
+	static const char * const msg =
+		"sendto: cannot schedule socket send";
+	static const char * const dmsg =
+		"overlapped IO data buffer";
+
+	IoCtx_t *	lpo  = NULL;
+	void *		dbuf = NULL;
+	WSABUF		wsabuf;
+	int		rc;
 
 	if (len > INT_MAX)
 		len = INT_MAX;
-	wsabuf.buf = (void *)pkt;
-	wsabuf.len = (DWORD)len;
-	AddrLen = SOCKLEN(dest);
-	octets_sent = 0;
-
-	Result = WSASendTo(fd, &wsabuf, 1, &octets_sent, 0,
-			   &dest->sa, AddrLen, NULL, NULL);
-	errval = GetLastError();
-	if (SOCKET_ERROR == Result) {
-		if (ERROR_UNEXP_NET_ERR == errval) {
-			/*
-			 * We get this error when trying to send if the
-			 * network interface is gone or has lost link.
-			 * Rescan interfaces to catch on sooner, but no
-			 * more often than once per minute.  Once ntpd
-			 * is able to detect changes without polling
-			 * this should be unneccessary
-			 */
-			if (time_next_ifscan_after_error < current_time) {
-				time_next_ifscan_after_error = current_time + 60;
-				timer_interfacetimeout(current_time);
-			}
-			DPRINTF(4, ("sendto unexpected network error, interface may be down\n"));
-		} else {
-			msyslog(LOG_ERR, "WSASendTo(%s) error %m",
-				stoa(dest));
-		}
-		SetLastError(errval);
-		return -1;
-	}
 
-	if ((DWORD)len != octets_sent) {
-		msyslog(LOG_ERR, "WSASendTo(%s) sent %u of %d octets",
-			stoa(dest), octets_sent, len);
-		SetLastError(ERROR_BAD_LENGTH);
-		return -1;
-	}
+	if (NULL == (dbuf = IOCPLPoolMemDup(pkt, len, dmsg)))
+		goto fail;
+	/* We register the IO operation against the shared lock here.
+	 * This is not strictly necessary, since the callback does not
+	 * access the endpoint structure in any way...
+	 */
+	if (NULL == (lpo = IoCtxAlloc(ep->ioreg_ctx, NULL)))
+		goto fail;
+
+	lpo->onIoDone  = OnSocketSend;
+	lpo->trans_buf = dbuf;
+	lpo->flRawMem  = 1;
+	lpo->io.sfd    = sfd;
+
+	wsabuf.buf = (void*)lpo->trans_buf;
+	wsabuf.len = (DWORD)len;
 
-	DPRINTF(4, ("sendto %s %d octets\n", stoa(dest), len));
-
-	return (int)len;
+	rc  = WSASendTo(sfd, &wsabuf, 1, NULL, 0,
+			&dest->sa, SOCKLEN(dest),
+			&lpo->ol, NULL);
+	if (!rc || IoResultCheck((DWORD)WSAGetLastError(), lpo, msg))
+		return (int)len;	/* normal/success return */
+
+	errno = EBADF;
+	return -1;
+
+fail:
+	IoCtxFree(lpo);
+	IOCPLPoolFree(dbuf, dmsg);
+	return -1;
 }
 
-
-
-/*
+/* --------------------------------------------------------------------
  * GetReceivedBuffers
  * Note that this is in effect the main loop for processing requests
  * both send and receive. This should be reimplemented
  */
 int
-GetReceivedBuffers()
+GetReceivedBuffers(void)
 {
 	DWORD	index;
 	HANDLE	ready;
@@ -1589,9 +1674,9 @@ GetReceivedBuffers()
 
 	have_packet = FALSE;
 	while (!have_packet) {
-		index = WaitForMultipleObjects(ActiveWaitHandles,
-					       WaitHandles, FALSE,
-					       INFINITE);
+		index = WaitForMultipleObjectsEx(
+			ActiveWaitHandles, WaitHandles,
+			FALSE, INFINITE, TRUE);
 		switch (index) {
 
 		case WAIT_OBJECT_0 + 0: /* Io event */
@@ -1638,4 +1723,3 @@ GetReceivedBuffers()
 #else /*defined(HAVE_IO_COMPLETION_PORT) */
   static int NonEmptyCompilationUnit;
 #endif  /*!defined(HAVE_IO_COMPLETION_PORT) */
-

==== ports/winnt/ntpd/ntp_iocplmem.c ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +123 -0
  [Bug 3019] NTPD stops processing packets after ERROR_HOST_UNREACHABLE
   - refactored IOCPL heap into separate file

--- /dev/null	2016-04-26 19:53:05 -04:00
+++ 1.1/ports/winnt/ntpd/ntp_iocplmem.c	2016-03-27 17:59:49 -04:00
@@ -0,0 +1,123 @@ 
+/*
+ * ntp_iocplmem.c - separate memory pool for IOCPL related objects
+ *
+ * Written by Juergen Perlinger (perlinger at ntp.org) for the NTP project.
+ * The contents of 'html/copyright.html' apply.
+ *
+ * --------------------------------------------------------------------
+ * Notes on the implementation:
+ *
+ * Implements a thin layer over Windows Memory pools
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include <syslog.h>
+
+#include "ntpd.h"
+#include "ntp_iocplmem.h"
+
+/* -------------------------------------------------------------------
+ * We make a pool of our own for IO context objects -- the are owned by
+ * the system until a completion result is pulled from the queue, and
+ * they seriously go into the way of memory tracking until we can safely
+ * cancel an IO request.
+ * -------------------------------------------------------------------
+ */
+static	HANDLE	hHeapHandle;
+
+/* -------------------------------------------------------------------
+ * Create a new heap for IO context objects
+ */
+ void
+IOCPLPoolInit(
+	size_t	initSize
+	)
+{
+	hHeapHandle = HeapCreate(0, initSize, 0);
+	if (hHeapHandle == NULL) {
+		msyslog(LOG_ERR, "Can't initialize Heap: %m");
+		exit(1);
+	}
+}
+
+/* -------------------------------------------------------------------
+ * Delete the IO context heap
+ *
+ * Since we do not know what callbacks are pending, we just drop the
+ * pool into oblivion. New allocs and frees will fail from this moment,
+ * but we simply don't care. At least the normal heap dump stats will
+ * show no leaks from IO context blocks. On the downside, we have to
+ * track them ourselves if something goes wrong.
+ */
+void
+IOCPLPoolDone(void)
+{
+	hHeapHandle = NULL;
+}
+
+/* -------------------------------------------------------------------
+ * Alloc & Free on local heap
+ *
+ * When the heap handle is NULL, these both will fail; Alloc with a NULL
+ * return and Free silently.
+ */
+void * __fastcall
+IOCPLPoolAlloc(
+	size_t		size,
+	const char *	desc
+	)
+{
+	void *	ptr = NULL;
+
+	if (hHeapHandle != NULL)
+		ptr = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, max(size, 1));
+	if (ptr == NULL)
+		errno = ENOMEM;
+	DPRINTF(6, ("IOCPLPoolAlloc: '%s', heap=%p, ptr=%p\n",
+		desc, hHeapHandle, ptr));
+	return ptr;
+}
+/* ----------------------------------------------------------------- */
+void __fastcall
+IOCPLPoolFree(
+	void *		ptr,
+	const char *	desc
+	)
+{
+	DPRINTF(6, ("IOCPLPoolFree: '%s', heap=%p, ptr=%p\n",
+		desc, hHeapHandle, ptr));
+	if (ptr != NULL && hHeapHandle != NULL)
+		HeapFree(hHeapHandle, 0, ptr);
+}
+
+/* -------------------------------------------------------------------
+ * Allocate a memory buffer and copy the data from a source buffer
+ * into the new allocated memory slice.
+ */
+void * __fastcall
+IOCPLPoolMemDup(
+const void *	psrc,
+size_t		size,
+const char *	desc
+)
+{
+	void *	ptr = NULL;
+
+	if (hHeapHandle != NULL) {
+		ptr = HeapAlloc(hHeapHandle, 0, max(size, 1));
+		if (ptr != NULL)
+			memcpy(ptr, psrc, size);
+	}
+	if (ptr == NULL)
+		errno = ENOMEM;
+
+	DPRINTF(6, ("IOCPLPoolMemDup: '%s', heap=%p, ptr=%p\n",
+		desc, hHeapHandle, ptr));
+	return ptr;
+
+}
+/* -*- that's all folks -*- */

==== ports/winnt/ntpd/ntp_iocplmem.c ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +0 -0

==== ports/winnt/ntpd/ntp_iocpltypes.c ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +366 -0
  [Bug 3019] NTPD stops processing packets after ERROR_HOST_UNREACHABLE
   - refactored helper objects (locks, PPS/device context, IO context,...) into separate file

--- /dev/null	2016-04-26 19:53:05 -04:00
+++ 1.1/ports/winnt/ntpd/ntp_iocpltypes.c	2016-03-27 17:59:49 -04:00
@@ -0,0 +1,366 @@ 
+/*
+ * ntp_iocpltypes.c - data structures for overlapped IO
+ *
+ * Written by Juergen Perlinger (perlinger at ntp.org) for the NTP project.
+ * The contents of 'html/copyright.html' apply.
+ *
+ * --------------------------------------------------------------------
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+
+#include "ntpd.h"
+#include "ntp_iocplmem.h"
+#include "ntp_iocpltypes.h"
+
+/*
+* ====================================================================
+* Shared lock manipulation
+* ====================================================================
+*/
+
+/* --------------------------------------------------------------------
+ * Create new shared lock node. The shared lock is returned with a
+ * refcount of 1, so the caller owns this immediately. The internal
+ * lock is NOT aquired, and all IO handles or FDs are set to an
+ * invalid value.
+ */
+SharedLock_t*  __fastcall
+slCreate(
+	void *	src
+	)
+{
+	SharedLock_t* retv;
+
+	retv = IOCPLPoolAlloc(sizeof(SharedLock_t), "Lock");
+	if (retv != NULL) {
+		InitializeCriticalSection(retv->mutex);
+		retv->refc_count = 1;
+		retv->rsrc.any   = src;
+		retv->handles[0] = INVALID_HANDLE_VALUE;
+		retv->handles[1] = INVALID_HANDLE_VALUE;
+		retv->riofd	 = -1;
+	}
+	return retv;
+}
+
+/* --------------------------------------------------------------------
+ * Attach to a lock. This just increments the use count, but does not
+ * aquire the internal lock. Return a pointer to the lock.
+ */
+SharedLock_t*  __fastcall
+slAttach(
+	SharedLock_t *	lp
+	)
+{
+	if (lp != NULL)
+		InterlockedIncrement(&lp->refc_count);
+	return lp;
+
+}
+
+/* --------------------------------------------------------------------
+ * Detach from a shared lock. If the use count drops to zero, the lock
+ * is destroyed and released.
+ * Alwys return NULL.
+ *
+ * THE CALLER MUST NOT OWN THE INTERNAL LOCK WHEN DOING THIS!
+ */
+SharedLock_t*  __fastcall
+slDetach(
+	SharedLock_t *	lp
+	)
+{
+	if (lp != NULL && !InterlockedDecrement(&lp->refc_count)) {
+		DeleteCriticalSection(lp->mutex);
+		memset(lp, 0xFF, sizeof(SharedLock_t));
+		IOCPLPoolFree(lp, "Lock");
+	}
+	return NULL;
+}
+
+/* --------------------------------------------------------------------
+ * Attach and aquire the lock for READ access. (This might block)
+ */
+SharedLock_t*  __fastcall
+slAttachShared(
+	SharedLock_t *	lp
+	)
+{
+	if (NULL != (lp = slAttach(lp)))
+		EnterCriticalSection(lp->mutex);
+	return lp;
+}
+
+/* --------------------------------------------------------------------
+ * Release the READ lock and detach from shared lock.
+ * Alwys returns NULL.
+ *
+ * THE CALLER MUST OWN THE READ LOCK WHEN DOING THIS.
+ */
+SharedLock_t*  __fastcall
+slDetachShared(
+	SharedLock_t *	lp
+	)
+{
+	if (lp != NULL)
+		LeaveCriticalSection(lp->mutex);
+	return slDetach(lp);
+}
+
+/* --------------------------------------------------------------------
+ * Attach and aquire the lock for WRITE access. (This might block)
+ */
+SharedLock_t*  __fastcall
+slAttachExclusive(
+	SharedLock_t *	lp
+)
+{
+	if (NULL != (lp = slAttach(lp)))
+		EnterCriticalSection(lp->mutex);
+	return lp;
+}
+
+/* --------------------------------------------------------------------
+ * Release the WRITE lock and detach from shared lock.
+ * Alwys returns NULL.
+ *
+ * THE CALLER MUST OWN THE WRITE LOCK WHEN DOING THIS.
+ */
+SharedLock_t*  __fastcall
+slDetachExclusive(
+	SharedLock_t *	lp
+	)
+{
+	if (lp != NULL)
+		LeaveCriticalSection(lp->mutex);
+	return slDetach(lp);
+}
+
+/* --------------------------------------------------------------------
+ * Predicate function: Is there an attached RIO, and is the RIO in
+ * active state?
+ */
+BOOL __fastcall
+slRefClockOK(
+	const SharedLock_t *	lp
+	)
+{
+	return	lp->rsrc.rio && lp->rsrc.rio->active;
+}
+
+/* --------------------------------------------------------------------
+ * Predicate function: Is there an attached interface, and is the
+ * interface accepting packets?
+ */
+BOOL __fastcall
+slEndPointOK(
+const SharedLock_t *	lp
+)
+{
+	return	lp->rsrc.ept &&	!lp->rsrc.ept->ignore_packets;
+}
+
+/* --------------------------------------------------------------------
+ * Enqueue a receive buffer under lock guard, but only if the shared
+ * lock is still active and a given predicate function holds.
+ *
+ * Returns TRUE if buffer was queued, FALSE in all other cases.
+ *
+ * !!NOTE!! The buffer is consumed by this call IN ANY CASE,
+ * independent of the function result!
+ */
+BOOL
+slQueueLocked(
+	SharedLock_t *	lp,
+	LockPredicateT	pred,
+	recvbuf_t *	buf
+	)
+{
+	BOOL	done = FALSE;
+	if (slAttachShared(lp)) {
+		done = (*pred)(lp);
+		if (done)
+			add_full_recv_buffer(buf);
+		slDetachShared(lp);
+	}
+	if (done)
+		SetEvent(WaitableIoEventHandle);
+	else
+		freerecvbuf(buf);
+	return done;
+}
+
+
+/* ====================================================================
+ * Alloc & Free of Device context
+ * ====================================================================
+ */
+
+/* !NOTE! The returned context is already owned by the caller! */
+DevCtx_t * __fastcall
+DevCtxAlloc(void)
+{
+	DevCtx_t *	devCtx;
+	u_long		slot;
+
+	/* allocate struct and tag all slots as invalid */
+	devCtx = (DevCtx_t *)IOCPLPoolAlloc(sizeof(DevCtx_t), "DEV ctx");
+	if (devCtx != NULL) {
+		/* The initial COV values make sure there is no busy
+		* loop on unused/empty slots.
+		*/
+		devCtx->cov_count = 1;	/* already owned! */
+		for (slot = 0; slot < PPS_QUEUE_LEN; slot++)
+			devCtx->pps_buff[slot].cov_count = ~slot;
+	}
+	return devCtx;
+}
+
+DevCtx_t * __fastcall
+DevCtxAttach(
+	DevCtx_t *	devCtx
+	)
+{
+	if (devCtx != NULL)
+		InterlockedIncrement(&devCtx->ref_count);
+	return devCtx;
+}
+
+DevCtx_t * __fastcall
+DevCtxDetach(
+	DevCtx_t *	devCtx
+	)
+{
+	if (devCtx && !InterlockedDecrement(&devCtx->ref_count))
+		IOCPLPoolFree(devCtx, "DEV ctx");
+	return NULL;
+}
+
+/* ====================================================================
+ * Alloc & Free of I/O context
+ * ====================================================================
+ */
+
+/* --------------------------------------------------------------------
+ * Allocate a new IO transfer context node and attach it to the lock
+ * and device context given. (Either or both may be NULL.)
+ * Returns new node, or NULL on error.
+ */
+IoCtx_t * __fastcall
+IoCtxAlloc(
+	SharedLock_t *	lock,
+	DevCtx_t *	devCtx
+	)
+{
+	IoCtx_t *	ctx;
+
+	ctx = (IoCtx_t *)IOCPLPoolAlloc(sizeof(IoCtx_t), "IO ctx");
+	if (ctx != NULL) {
+		ctx->slock = slAttach(lock);
+		ctx->devCtx = DevCtxAttach(devCtx);
+	}
+	return ctx;
+}
+
+/* --------------------------------------------------------------------
+ * Free an IO transfer context node after detaching it from lock and
+ * device context.
+ *
+ * This does *NOT* free any attache data buffers! Use 'IoCtxRelease()'
+ * for dropping the node and attached buffers.
+ */
+void __fastcall
+IoCtxFree(
+	IoCtx_t *	ctx
+	)
+{
+	if (ctx) {
+		ctx->slock  = slDetach(ctx->slock);
+		ctx->devCtx = DevCtxDetach(ctx->devCtx);
+		IOCPLPoolFree(ctx, "IO ctx");
+	}
+}
+
+/* --------------------------------------------------------------------
+ * Free an IO transfer context node after detaching it from lock and
+ * device context.
+ *
+ * Also disposes of any attached data buffers -- the buffer pointers
+ * should either be a valid reference or NULL.
+ */
+void __fastcall
+IoCtxRelease(
+	IoCtx_t * 	ctx
+	)
+{
+	static const char *const dmsg =
+		"overlapped IO data buffer";
+
+	if (ctx) {
+		if (ctx->flRawMem)
+			IOCPLPoolFree(ctx->trans_buf, dmsg);
+		else
+			freerecvbuf(ctx->recv_buf);
+		IoCtxFree(ctx);
+	}
+}
+
+/* --------------------------------------------------------------------
+ * Check if any source is attached to shared lock associated with
+ * this context node.
+ *
+ * UNGUARDED -- ONLY CALL UNDER LOCK.
+ */
+BOOL __fastcall
+IoCtxAlive(
+	IoCtx_t *	ctx
+	)
+{
+	return ctx			&&
+		ctx->slock		&&
+		ctx->slock->rsrc.any;
+}
+
+/* --------------------------------------------------------------------
+ * Start an IO operation on a given context object with a specified
+ * function and buffer.
+ * This locks the shared lock on the context, checks for the lock
+ * being active, and only then runs the starter function.
+ *
+ * Returns TRUE if the starter was executed successfully, FALSE in
+ * all other cases.
+ *
+ * !!NOTE!! The context object and the buffer are consumed by this
+ * call IN ANY CASE, independent of the function result!
+ */
+BOOL
+IoCtxStartLocked(
+	IoCtx_t *	lpo,
+	IoCtxStarterT	func,
+	recvbuf_t *	buf
+	)
+{
+	BOOL		done = FALSE;
+	SharedLock_t *	slock = slAttachShared(lpo->slock);
+	if (slock != NULL) {
+		if ((lpo->io.hnd == slock->handles[0]) ||
+		    (lpo->io.hnd == slock->handles[1])  )
+		{
+			done = (func)(lpo, buf);
+			lpo = NULL; /* consumed by 'func' */
+		}
+		slDetachShared(slock);
+	}
+	if (lpo != NULL) {
+		freerecvbuf(buf);
+		IoCtxFree(lpo);
+	}
+	return done;
+}
+
+/* -*- that's all folks -*- */

==== ports/winnt/ntpd/ntp_iocpltypes.c ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +0 -0

==== ports/winnt/ntpd/ntservice.c ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +13 -3
  [Bug 3019] NTPD stops processing packets after ERROR_HOST_UNREACHABLE
   - log request from SCM in INFO level

--- 1.29/ports/winnt/ntpd/ntservice.c	2012-10-09 23:07:44 -04:00
+++ 1.30/ports/winnt/ntpd/ntservice.c	2016-03-27 17:59:49 -04:00
@@ -229,6 +229,11 @@ ServiceControl(
 	DWORD dwCtrlCode
 	) 
 {
+	static const char * const msg_tab[2] = {
+		"explicit stop",
+		"system shutdown"
+	};
+
 	switch (dwCtrlCode) {
 
 	case SERVICE_CONTROL_SHUTDOWN:
@@ -237,19 +242,24 @@ ServiceControl(
 
 	case SERVICE_CONTROL_STOP:
 		if (WaitableExitEventHandle != NULL) {
-			SetEvent(WaitableExitEventHandle);
+			msyslog(LOG_INFO, "SCM requests stop (%s)",
+				msg_tab[!!computer_shutting_down]);
 			UpdateSCM(SERVICE_STOP_PENDING);
+			SetEvent(WaitableExitEventHandle);
 			Sleep(100);  //##++
+			break;
 		}
-		return;
+		msyslog(LOG_ERR, "SCM requests stop (%s), but have no exit event!",
+			msg_tab[!!computer_shutting_down]);
+		/* FALLTHROUGH */
 
 	case SERVICE_CONTROL_PAUSE:
 	case SERVICE_CONTROL_CONTINUE:
 	case SERVICE_CONTROL_INTERROGATE:
 	default:
+		UpdateSCM(SERVICE_RUNNING);
 		break;
 	}
-	UpdateSCM(SERVICE_RUNNING);
 }
 
 /*

==== ports/winnt/vs2005/ntpd.vcproj ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +8 -18
  [Bug 3019] NTPD stops processing packets after ERROR_HOST_UNREACHABLE
   - added ntp_iocpl{mem,types}.c to sources.

--- 1.20/ports/winnt/vs2005/ntpd.vcproj	2015-07-01 02:40:43 -04:00
+++ 1.21/ports/winnt/vs2005/ntpd.vcproj	2016-03-27 17:59:49 -04:00
@@ -365,26 +365,16 @@ 
 			<File
 				RelativePath="..\ntpd\ntp_iocompletionport.c"
 				>
-				<FileConfiguration
-					Name="Release|Win32"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""
-					/>
-				</FileConfiguration>
 			</File>
 			<File
+				RelativePath="..\ntpd\ntp_iocplmem.c"
+				>
+			</File>
+			<File
+				RelativePath="..\ntpd\ntp_iocpltypes.c"
+				>
+			</File>
+			<File
 				RelativePath="..\..\..\ntpd\ntp_leapsec.c"
 				>
 			</File>

==== ports/winnt/vs2008/ntpd/ntpd.vcproj ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +16 -0
  [Bug 3019] NTPD stops processing packets after ERROR_HOST_UNREACHABLE
   - added ntp_iocpl{mem,types}.c to sources.

--- 1.50/ports/winnt/vs2008/ntpd/ntpd.vcproj	2015-11-13 16:54:34 -05:00
+++ 1.51/ports/winnt/vs2008/ntpd/ntpd.vcproj	2016-03-27 17:59:49 -04:00
@@ -340,6 +340,14 @@ 
 				>
 			</File>
 			<File
+				RelativePath="..\..\ntpd\ntp_iocplmem.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\ntpd\ntp_iocpltypes.c"
+				>
+			</File>
+			<File
 				RelativePath="..\..\..\..\ntpd\ntp_leapsec.c"
 				>
 			</File>
@@ -549,6 +557,14 @@ 
 				>
 			</File>
 			<File
+				RelativePath="..\..\include\ntp_iocplmem.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\include\ntp_iocpltypes.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\..\..\ntpd\ntp_keyword.h"
 				>
 			</File>

==== ports/winnt/vs2013/debug-x64.props ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +1 -0
  [Bug 3019] NTPD stops processing packets after ERROR_HOST_UNREACHABLE
   - sidekick: property sheet name

--- 1.1/ports/winnt/vs2013/debug-x64.props	2015-04-12 13:49:31 -04:00
+++ 1.2/ports/winnt/vs2013/debug-x64.props	2016-03-27 17:59:49 -04:00
@@ -5,6 +5,7 @@ 
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup>
     <_ProjectFileVersion>12.0.30501.0</_ProjectFileVersion>
+    <_PropertySheetDisplayName>debug-x64</_PropertySheetDisplayName>
   </PropertyGroup>
   <ItemDefinitionGroup>
     <ClCompile>

==== ports/winnt/vs2013/libntp/libntp.vcxproj.filters ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +3 -0
  [Bug 3019] NTPD stops processing packets after ERROR_HOST_UNREACHABLE
   - auto update

--- 1.7/ports/winnt/vs2013/libntp/libntp.vcxproj.filters	2015-11-13 16:54:34 -05:00
+++ 1.7.1.1/ports/winnt/vs2013/libntp/libntp.vcxproj.filters	2016-03-27 17:59:49 -04:00
@@ -323,6 +323,9 @@ 
     <ClCompile Include="..\..\..\..\libntp\ymd2yd.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\..\libntp\is_ip_address.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\..\..\sntp\libopts\ag-char-map.h">

==== ports/winnt/vs2013/ntpd/ntpd.vcxproj ====
2016-03-27 23:59:50+02:00, jnperlin at nemesis.localnet +4 -0
  [Bug 3019] NTPD stops processing packets after ERROR_HOST_UNREACHABLE
   - added ntp_iocpl{mem,types}.c to sources.

--- 1.8/ports/winnt/vs2013/ntpd/ntpd.vcxproj	2015-11-13 16:54:34 -05:00
+++ 1.9/ports/winnt/vs2013/ntpd/ntpd.vcxproj	2016-03-27 17:59:50 -04:00
@@ -330,8 +330,12 @@ 
     <ClCompile Include="..\..\..\..\ntpd\refclock_wwv.c" />
     <ClCompile Include="..\..\..\..\ntpd\refclock_wwvb.c" />
     <ClCompile Include="..\..\..\..\ntpd\refclock_zyfer.c" />
+    <ClInclude Include="..\..\include\ntp_iocplmem.h" />
+    <ClInclude Include="..\..\include\ntp_iocpltypes.h" />
     <ClCompile Include="..\..\ntpd\hopf_PCI_io.c" />
     <ClCompile Include="..\..\ntpd\ntp_iocompletionport.c" />
+    <ClCompile Include="..\..\ntpd\ntp_iocplmem.c" />
+    <ClCompile Include="..\..\ntpd\ntp_iocpltypes.c" />
     <ClCompile Include="..\..\ntpd\ntservice.c" />
     <ClCompile Include="..\..\ntpd\nt_clockstuff.c" />
     <ClCompile Include="version.c" />

==== ports/winnt/vs2013/ntpd/ntpd.vcxproj.filters ====
2016-03-27 23:59:50+02:00, jnperlin at nemesis.localnet +12 -0
  [Bug 3019] NTPD stops processing packets after hitting ERROR_HOST_UNREACHABLE
   - auto update

--- 1.5/ports/winnt/vs2013/ntpd/ntpd.vcxproj.filters	2015-07-01 02:40:43 -04:00
+++ 1.6/ports/winnt/vs2013/ntpd/ntpd.vcxproj.filters	2016-03-27 17:59:50 -04:00
@@ -291,6 +291,12 @@ 
     <ClCompile Include="..\..\..\..\ntpd\rc_cmdlength.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\ntpd\ntp_iocplmem.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\ntpd\ntp_iocpltypes.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\..\..\include\ascii.h">
@@ -521,6 +527,12 @@ 
     <ClInclude Include="..\..\..\..\lib\isc\win32\include\isc\int.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\include\ntp_iocplmem.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\ntp_iocpltypes.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="..\..\libntp\messages.rc">

==== ports/winnt/vs2013/release-x64.props ====
2016-03-27 23:59:49+02:00, jnperlin at nemesis.localnet +1 -0
  [Bug 3019] NTPD stops processing packets after ERROR_HOST_UNREACHABLE
   - sidekick: property sheet name

--- 1.1/ports/winnt/vs2013/release-x64.props	2015-04-12 13:49:31 -04:00
+++ 1.2/ports/winnt/vs2013/release-x64.props	2016-03-27 17:59:49 -04:00
@@ -5,6 +5,7 @@ 
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup>
     <_ProjectFileVersion>12.0.30501.0</_ProjectFileVersion>
+    <_PropertySheetDisplayName>release-x64</_PropertySheetDisplayName>
   </PropertyGroup>
   <ItemDefinitionGroup>
     <ClCompile>

#### ChangeSet ####
2016-03-19 09:09:07+00:00, stenn at psp-deb1.ntp.org
  [Bug 3030] ntpq needs a general way to specify refid output format.  HStenn.

==== tests/ntpq/Makefile.am ====
2016-03-19 09:09:03+00:00, stenn at psp-deb1.ntp.org +1 -0
  [Bug 3030] ntpq needs a general way to specify refid output format.  HStenn.

--- 1.8/tests/ntpq/Makefile.am	2015-09-17 07:11:56 -04:00
+++ 1.9/tests/ntpq/Makefile.am	2016-03-19 05:09:03 -04:00
@@ -34,6 +34,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/sntp/unit
 AM_CPPFLAGS += $(CPPFLAGS_NTP)
 AM_CPPFLAGS += -DUNITY_INCLUDE_CONFIG_H
 AM_CPPFLAGS += -I$(top_srcdir)/sntp/unity
+AM_CPPFLAGS += $(LIBOPTS_CFLAGS)
 
 AM_LDFLAGS = $(LDFLAGS_NTP)
 

#### ChangeSet ####
2016-03-16 09:22:31+00:00, stenn at psp-deb1.ntp.org
  Add README.pullrequests.  Harlan Stenn

==== ChangeLog ====
2016-03-16 09:22:19+00:00, stenn at psp-deb1.ntp.org +1 -0
  Add README.pullrequests.  Harlan Stenn

--- 1.1794.1.8/ChangeLog	2016-03-14 06:20:38 -04:00
+++ 1.1794.1.9/ChangeLog	2016-03-16 05:22:19 -04:00
@@ -16,6 +16,7 @@ 
 * Document ntp.key's optional IP list in authenetic.html.  Harlan Stenn.
 * Fix some Credit: attributions in the NEWS file.  Harlan Stenn.
 * Fix typo in html/monopt.html.  Harlan Stenn.
+* Add README.pullrequests.  Harlan Stenn.
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

==== Makefile.am ====
2016-03-16 09:22:19+00:00, stenn at psp-deb1.ntp.org +1 -0
  Add README.pullrequests.  Harlan Stenn

--- 1.134/Makefile.am	2015-10-01 03:26:14 -04:00
+++ 1.135/Makefile.am	2016-03-16 05:22:19 -04:00
@@ -36,6 +36,7 @@ EXTRA_DIST =			\
 	README.hackers		\
 	README.leapsmear	\
 	README.patches		\
+	README.pullrequests	\
 	README.refclocks	\
 	README.versions		\
 	TODO			\

==== README.pullrequests ====
2016-03-16 09:22:03+00:00, stenn at psp-deb1.ntp.org +90 -0
  BitKeeper file /home/stenn/ntp-stable/README.pullrequests

--- /dev/null	2016-04-26 19:53:05 -04:00
+++ 1.1/README.pullrequests	2016-03-16 05:22:03 -04:00
@@ -0,0 +1,90 @@ 
+See README.hackers for notes on coding styles.
+
+The NTP project's github repository is at https://github.com/ntp-project/ntp.
+
+There are two branches, master and stable.
+
+The stable branch is the current supported production code branch, the
+ntp-stable code (even 2nd number).
+
+The master branch is for new development, also known as ntp-dev (which
+has an odd 2nd number).
+
+If you have some work you'd like to add, then if there is any interest
+in seeing that work in the current production release then base your work
+on the stable branch, and pull your work into a master copy to allow for
+publishing your changes in the ntp-dev or master branch.
+
+If there is no expectation that your work will be included in the
+current stable release (the ntp-stable code) then it's better to do your
+work on a copy of the master branch.
+
+Make sure that any changes you make to stable pull cleanly into master.
+
+It's possible that after pulling your changes from stable to master that
+some additional cleanup will be required in master.  Please do this.
+
+If you follow this method, then if you submit a pull request for either
+master or for master+stable, it will be easy for us to evaluate and
+incorporate your work.
+
+Please also note that your submissions will be able to be evaluated and
+handled sooner if the repo that contains your pull requests also includes
+test cases.
+
+The general workflow is as follows:
+
+1) If you haven't, create a fork of ntp-project/ntp with your github account.
+   i) Log on to github.com with your github account.
+       - If you don't have one, create one first. (read: https://help.github.com/articles/signing-up-for-a-new-github-account)
+       - Make sure you also have a SSH key associated with your github account.
+         (read: https://help.github.com/articles/generating-ssh-keys/)
+   ii) Go to https://github.com/ntp-project/ntp
+   iii) On the top right corner, right below the header bar, there is
+        a button labeled "Fork".  Click on it.  This will fork the current
+	ntp master to your own account. Once done, it will go to your account's
+	version of the ntp repository. (Your fork of ntp source)
+   iv) Clone a local version of your fork. 
+        - git clone git at github.com:<your_username>/ntp
+
+2) Look through the bugs listed in the bug tracker: http://bugs.ntp.org/
+
+3) Once you've found a bug to work on:
+
+   i) Create a branch off your own master branch of your local fork.
+      (the <branchname> can be any valid short string that will tell you
+       what you're working on)
+      - git checkout -b <branchname>
+        
+   ii) Start working on the bug.
+   iii) When you create changes in the source, it would help you to 
+        keep track of your changes by committing to your local repo.
+	(This way, every small change is tracked and when you've
+	 made a mistake, you can always go back.)
+	 - git commit -a -m "description of change"
+   iv) Once you are satisfied, you can push to your github account's
+       repository.
+         - git push origin <branchname>
+    v) (go to step iii).
+
+4) Once you feel you've fixed the bug (and tested it), you need to 
+   create a pull request on your branch on github.  (Read up on
+   pull requests @ https://help.github.com/articles/using-pull-requests)
+
+    i) Create your pullrequest by following the instructions @
+       https://help.github.com/articles/creating-a-pull-request/
+
+5) Your pull request will be reviewed by committers and when it
+   passes review, it will be merged by the reviewer/allowed committer.
+
+6) You have fixed a bug.  Goto step #2.
+
+If these patches are for a bugzilla issue, mark the issue as Resolved/READY
+with a comment of "Please pick up the patches from XXX" where XXX is
+something like:
+
+ hostname:~user/path	if it's a machine the reviewers have access to, or
+ github-pull-request-URI
+
+---
+

==== README.pullrequests ====
2016-03-16 09:22:03+00:00, stenn at psp-deb1.ntp.org +0 -0

#### ChangeSet ####
2016-03-16 08:46:16+00:00, stenn at psp-deb1.ntp.org
  [Bug 3030] ntpq needs a general way to specify refid output format.  HStenn.

==== ChangeLog ====
2016-03-16 08:45:48+00:00, stenn at psp-deb1.ntp.org +1 -0
  [Bug 3030] ntpq needs a general way to specify refid output format.  HStenn.

--- 1.1794.1.2/ChangeLog	2016-01-24 05:14:42 -05:00
+++ 1.1794.11.1/ChangeLog	2016-03-16 04:45:48 -04:00
@@ -2,6 +2,7 @@ 
 
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
+* [Bug 3030] ntpq needs a general way to specify refid output format.  HStenn.
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

==== ntpq/invoke-ntpq.texi ====
2016-03-16 08:45:52+00:00, stenn at psp-deb1.ntp.org +28 -1
  [Bug 3030] ntpq needs a general way to specify refid output format.  HStenn.

--- 1.508/ntpq/invoke-ntpq.texi	2016-01-20 04:20:07 -05:00
+++ 1.509/ntpq/invoke-ntpq.texi	2016-03-16 04:45:52 -04:00
@@ -6,7 +6,7 @@ 
 #
 # EDIT THIS FILE WITH CAUTION  (invoke-ntpq.texi)
 #
-# It has been AutoGen-ed  January 20, 2016 at 04:19:10 AM by AutoGen 5.18.5
+# It has been AutoGen-ed  March 16, 2016 at 05:10:35 AM by AutoGen 5.18.5
 # From the definitions    ntpq-opts.def
 # and the template file   agtexi-cmd.tpl
 @end ignore
@@ -826,6 +826,7 @@ This software is released under the NTP 
 * ntpq numeric::                numeric option (-n)
 * ntpq old-rv::                 old-rv option
 * ntpq peers::                  peers option (-p)
+* ntpq refid::                  refid option (-r)
 * ntpq wide::                   wide option (-w)
 * ntpq config::                 presetting/configuring ntpq
 * ntpq exit status::            exit status
@@ -868,6 +869,7 @@ Usage:  ntpq [ -<flag> [<val>] | --<name
       no  old-rv         Always output status line with readvar
    -p no  peers          Print a list of the peers
                                 - prohibits the option 'interactive'
+   -r KWd refid          Set default display type for S2+ refids
    -w no  wide           Display the full 'remote' value
       opt version        output version information and exit
    -? no  help           display extended usage information and exit
@@ -885,6 +887,10 @@ Please send bug reports to:  <http://bug
  - reading file ./.ntprc
  - examining environment variables named NTPQ_*
 
+The valid "refid" option keywords are:
+  hash ipv4
+  or an integer from 0 through 1
+
 Please send bug reports to:  <http://bugs.ntp.org, bugs@@ntp.org>
 @end example
 @exampleindent 4
@@ -992,6 +998,27 @@ of their state. This is equivalent to th
 
 Print a list of the peers known to the server as well as a summary
 of their state. This is equivalent to the 'peers' interactive command.
+ at node ntpq refid
+ at subsection refid option (-r)
+ at cindex ntpq-refid
+
+This is the ``set default display type for s2+ refids'' option.
+This option takes a keyword argument.
+
+ at noindent
+This option has some usage constraints.  It:
+ at itemize @bullet
+ at item
+This option takes a keyword as its argument.
+The argument sets an enumeration value that can be tested by comparing the option value macro (OPT_VALUE_REFID).
+The available keywords are:
+ at example
+    hash ipv4
+ at end example
+
+or their numeric equivalent. at end itemize
+
+Set the default display format for S2+ refids.
 @node ntpq wide
 @subsection wide option (-w)
 @cindex ntpq-wide

==== ntpq/ntpq-opts.c ====
2016-03-16 08:45:52+00:00, stenn at psp-deb1.ntp.org +108 -50
  [Bug 3030] ntpq needs a general way to specify refid output format.  HStenn.

--- 1.525/ntpq/ntpq-opts.c	2016-01-20 04:20:07 -05:00
+++ 1.526/ntpq/ntpq-opts.c	2016-03-16 04:45:52 -04:00
@@ -1,7 +1,7 @@ 
 /*
  *  EDIT THIS FILE WITH CAUTION  (ntpq-opts.c)
  *
- *  It has been AutoGen-ed  January 20, 2016 at 04:18:42 AM by AutoGen 5.18.5
+ *  It has been AutoGen-ed  March 16, 2016 at 05:10:15 AM by AutoGen 5.18.5
  *  From the definitions    ntpq-opts.def
  *  and the template file   options
  *
@@ -68,7 +68,7 @@ static char const ntpq_opt_strs[1925] =
 /**
  *  static const strings for ntpq options
  */
-static char const ntpq_opt_strs[1925] =
+static char const ntpq_opt_strs[1982] =
 /*     0 */ "ntpq 4.2.8p6\n"
             "Copyright (C) 1992-2016 The University of Delaware and Network Time Foundation, all rights reserved.\n"
             "This is free software. It is licensed for use, modification and\n"
@@ -113,29 +113,33 @@ static char const ntpq_opt_strs[1925] =
 /*  1404 */ "Print a list of the peers\0"
 /*  1430 */ "PEERS\0"
 /*  1436 */ "peers\0"
-/*  1442 */ "Display the full 'remote' value\0"
-/*  1474 */ "WIDE\0"
-/*  1479 */ "wide\0"
-/*  1484 */ "display extended usage information and exit\0"
-/*  1528 */ "help\0"
-/*  1533 */ "extended usage information passed thru pager\0"
-/*  1578 */ "more-help\0"
-/*  1588 */ "output version information and exit\0"
-/*  1624 */ "version\0"
-/*  1632 */ "save the option state to a config file\0"
-/*  1671 */ "save-opts\0"
-/*  1681 */ "load options from a config file\0"
-/*  1713 */ "LOAD_OPTS\0"
-/*  1723 */ "no-load-opts\0"
-/*  1736 */ "no\0"
-/*  1739 */ "NTPQ\0"
-/*  1744 */ "ntpq - standard NTP query program - Ver. 4.2.8p6\n"
+/*  1442 */ "Set default display type for S2+ refids\0"
+/*  1482 */ "REFID\0"
+/*  1488 */ "refid\0"
+/*  1494 */ "Display the full 'remote' value\0"
+/*  1526 */ "WIDE\0"
+/*  1531 */ "wide\0"
+/*  1536 */ "display extended usage information and exit\0"
+/*  1580 */ "help\0"
+/*  1585 */ "extended usage information passed thru pager\0"
+/*  1630 */ "more-help\0"
+/*  1640 */ "output version information and exit\0"
+/*  1676 */ "version\0"
+/*  1684 */ "save the option state to a config file\0"
+/*  1723 */ "save-opts\0"
+/*  1733 */ "load options from a config file\0"
+/*  1765 */ "LOAD_OPTS\0"
+/*  1775 */ "no-load-opts\0"
+/*  1788 */ "no\0"
+/*  1791 */ "NTPQ\0"
+/*  1796 */ "ntpq - standard NTP query program - Ver. 4.2.8p6\n"
             "Usage:  %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]... [ host ...]\n\0"
-/*  1863 */ "$HOME\0"
-/*  1869 */ ".\0"
-/*  1871 */ ".ntprc\0"
-/*  1878 */ "http://bugs.ntp.org, bugs at ntp.org\0"
-/*  1912 */ "ntpq 4.2.8p6";
+/*  1915 */ "$HOME\0"
+/*  1921 */ ".\0"
+/*  1923 */ ".ntprc\0"
+/*  1930 */ "http://bugs.ntp.org, bugs at ntp.org\0"
+/*  1964 */ "ntpq 4.2.8p6\0"
+/*  1977 */ "hash";
 
 /**
  *  ipv4 option description with
@@ -264,26 +268,41 @@ static int const aPeersCantList[] = {
 /** Compiled in flag settings for the peers option */
 #define PEERS_FLAGS     (OPTST_DISABLED)
 
+/**
+ *  refid option description:
+ */
+/** Descriptive text for the refid option */
+#define REFID_DESC      (ntpq_opt_strs+1442)
+/** Upper-cased name for the refid option */
+#define REFID_NAME      (ntpq_opt_strs+1482)
+/** Name string for the refid option */
+#define REFID_name      (ntpq_opt_strs+1488)
+/** The compiled in default value for the refid option argument */
+#define REFID_DFT_ARG   ((char const*)REFID_IPV4)
+/** Compiled in flag settings for the refid option */
+#define REFID_FLAGS     (OPTST_DISABLED \
+        | OPTST_SET_ARGTYPE(OPARG_TYPE_ENUMERATION))
+
 /**
  *  wide option description:
  */
 /** Descriptive text for the wide option */
-#define WIDE_DESC      (ntpq_opt_strs+1442)
+#define WIDE_DESC      (ntpq_opt_strs+1494)
 /** Upper-cased name for the wide option */
-#define WIDE_NAME      (ntpq_opt_strs+1474)
+#define WIDE_NAME      (ntpq_opt_strs+1526)
 /** Name string for the wide option */
-#define WIDE_name      (ntpq_opt_strs+1479)
+#define WIDE_name      (ntpq_opt_strs+1531)
 /** Compiled in flag settings for the wide option */
 #define WIDE_FLAGS     (OPTST_DISABLED)
 
 /*
  *  Help/More_Help/Version option descriptions:
  */
-#define HELP_DESC       (ntpq_opt_strs+1484)
-#define HELP_name       (ntpq_opt_strs+1528)
+#define HELP_DESC       (ntpq_opt_strs+1536)
+#define HELP_name       (ntpq_opt_strs+1580)
 #ifdef HAVE_WORKING_FORK
-#define MORE_HELP_DESC  (ntpq_opt_strs+1533)
-#define MORE_HELP_name  (ntpq_opt_strs+1578)
+#define MORE_HELP_DESC  (ntpq_opt_strs+1585)
+#define MORE_HELP_name  (ntpq_opt_strs+1630)
 #define MORE_HELP_FLAGS (OPTST_IMM | OPTST_NO_INIT)
 #else
 #define MORE_HELP_DESC  HELP_DESC
@@ -296,14 +315,14 @@ static int const aPeersCantList[] = {
 #  define VER_FLAGS     (OPTST_SET_ARGTYPE(OPARG_TYPE_STRING) | \
                          OPTST_ARG_OPTIONAL | OPTST_IMM | OPTST_NO_INIT)
 #endif
-#define VER_DESC        (ntpq_opt_strs+1588)
-#define VER_name        (ntpq_opt_strs+1624)
-#define SAVE_OPTS_DESC  (ntpq_opt_strs+1632)
-#define SAVE_OPTS_name  (ntpq_opt_strs+1671)
-#define LOAD_OPTS_DESC     (ntpq_opt_strs+1681)
-#define LOAD_OPTS_NAME     (ntpq_opt_strs+1713)
-#define NO_LOAD_OPTS_name  (ntpq_opt_strs+1723)
-#define LOAD_OPTS_pfx      (ntpq_opt_strs+1736)
+#define VER_DESC        (ntpq_opt_strs+1640)
+#define VER_name        (ntpq_opt_strs+1676)
+#define SAVE_OPTS_DESC  (ntpq_opt_strs+1684)
+#define SAVE_OPTS_name  (ntpq_opt_strs+1723)
+#define LOAD_OPTS_DESC     (ntpq_opt_strs+1733)
+#define LOAD_OPTS_NAME     (ntpq_opt_strs+1765)
+#define NO_LOAD_OPTS_name  (ntpq_opt_strs+1775)
+#define LOAD_OPTS_pfx      (ntpq_opt_strs+1788)
 #define LOAD_OPTS_name     (NO_LOAD_OPTS_name + 3)
 /**
  *  Declare option callback procedures
@@ -314,7 +333,7 @@ static tOptProc
     optionResetOpt,          optionStackArg,          optionTimeDate,
     optionTimeVal,           optionUnstackArg,        optionVendorOption;
 static tOptProc
-    doOptDebug_Level, doUsageOpt;
+    doOptDebug_Level, doOptRefid, doUsageOpt;
 #define VER_PROC        ntpOptionPrintVersion
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -432,8 +451,20 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PEERS_DESC, PEERS_NAME, PEERS_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 9, VALUE_OPT_WIDE,
-     /* equiv idx, value */ 9, VALUE_OPT_WIDE,
+  {  /* entry idx, value */ 9, VALUE_OPT_REFID,
+     /* equiv idx, value */ 9, VALUE_OPT_REFID,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ REFID_FLAGS, 0,
+     /* last opt argumnt */ { REFID_DFT_ARG },
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ doOptRefid,
+     /* desc, NAME, name */ REFID_DESC, REFID_NAME, REFID_name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 10, VALUE_OPT_WIDE,
+     /* equiv idx, value */ 10, VALUE_OPT_WIDE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ WIDE_FLAGS, 0,
@@ -512,24 +543,24 @@ static tOptDesc optDesc[OPTION_CT] = {
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 /** Reference to the upper cased version of ntpq. */
-#define zPROGNAME       (ntpq_opt_strs+1739)
+#define zPROGNAME       (ntpq_opt_strs+1791)
 /** Reference to the title line for ntpq usage. */
-#define zUsageTitle     (ntpq_opt_strs+1744)
+#define zUsageTitle     (ntpq_opt_strs+1796)
 /** ntpq configuration file name. */
-#define zRcName         (ntpq_opt_strs+1871)
+#define zRcName         (ntpq_opt_strs+1923)
 /** Directories to search for ntpq config files. */
 static char const * const apzHomeList[3] = {
-    ntpq_opt_strs+1863,
-    ntpq_opt_strs+1869,
+    ntpq_opt_strs+1915,
+    ntpq_opt_strs+1921,
     NULL };
 /** The ntpq program bug email address. */
-#define zBugsAddr       (ntpq_opt_strs+1878)
+#define zBugsAddr       (ntpq_opt_strs+1930)
 /** Clarification/explanation of what ntpq does. */
 #define zExplain        (NULL)
 /** Extra detail explaining what ntpq does. */
 #define zDetail         (NULL)
 /** The full version string for ntpq. */
-#define zFullVersion    (ntpq_opt_strs+1912)
+#define zFullVersion    (ntpq_opt_strs+1964)
 /* extracted from optcode.tlib near line 364 */
 
 #if defined(ENABLE_NLS)
@@ -588,6 +619,30 @@ OPT_VALUE_SET_DEBUG_LEVEL++;
     (void)pOptDesc;
     (void)pOptions;
 }
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/**
+ * Code to handle the refid option.
+ * Set the default display format for S2+ refids.
+ * @param[in] pOptions the ntpq options data structure
+ * @param[in,out] pOptDesc the option descriptor for this option.
+ */
+static void
+doOptRefid(tOptions* pOptions, tOptDesc* pOptDesc)
+{
+
+/* extracted from optmain.tlib near line 945 */
+    static char const * const names[2] = {
+        ntpq_opt_strs+1977, ntpq_opt_strs+1044 };
+
+    if (pOptions <= OPTPROC_EMIT_LIMIT) {
+        (void) optionEnumerationVal(pOptions, pOptDesc, names, 2);
+        return; /* protect AutoOpts client code from internal callbacks */
+    }
+
+    pOptDesc->optArg.argEnum =
+        optionEnumerationVal(pOptions, pOptDesc, names, 2);
+}
 /* extracted from optmain.tlib near line 1250 */
 
 /**
@@ -651,7 +706,7 @@ tOptions ntpqOptions = {
       NO_EQUIVALENT, /* '-#' option index */
       NO_EQUIVALENT /* index of default opt */
     },
-    15 /* full option count */, 10 /* user option count */,
+    16 /* full option count */, 11 /* user option count */,
     ntpq_full_usage, ntpq_short_usage,
     NULL, NULL,
     PKGDATADIR, ntpq_packager_info
@@ -833,6 +888,9 @@ implied warranty.\n"));
   /* referenced via ntpqOptions.pOptDesc->pzText */
   puts(_("Print a list of the peers"));
 
+  /* referenced via ntpqOptions.pOptDesc->pzText */
+  puts(_("Set default display type for S2+ refids"));
+
   /* referenced via ntpqOptions.pOptDesc->pzText */
   puts(_("Display the full 'remote' value"));
 

==== ntpq/ntpq-opts.def ====
2016-03-16 08:45:52+00:00, stenn at psp-deb1.ntp.org +12 -0
  [Bug 3030] ntpq needs a general way to specify refid output format.  HStenn.

--- 1.26/ntpq/ntpq-opts.def	2015-06-10 06:52:44 -04:00
+++ 1.27/ntpq/ntpq-opts.def	2016-03-16 04:45:52 -04:00
@@ -99,6 +99,18 @@ flag = {
 	_EndOfDoc_;
 };
 
+flag = {
+    name      = refid;
+    value     = r;
+    descrip   = "Set default display type for S2+ refids";
+    arg-type  = keyword;
+    keyword   = hash, ipv4;
+    arg-default = ipv4;
+    doc = <<-  _EndOfDoc_
+	Set the default display format for S2+ refids.
+	_EndOfDoc_;
+};
+
 flag = {
     name      = wide;
     value     = w;

==== ntpq/ntpq-opts.h ====
2016-03-16 08:45:52+00:00, stenn at psp-deb1.ntp.org +21 -8
  [Bug 3030] ntpq needs a general way to specify refid output format.  HStenn.

--- 1.523/ntpq/ntpq-opts.h	2016-01-20 04:20:07 -05:00
+++ 1.524/ntpq/ntpq-opts.h	2016-03-16 04:45:52 -04:00
@@ -1,7 +1,7 @@ 
 /*
  *  EDIT THIS FILE WITH CAUTION  (ntpq-opts.h)
  *
- *  It has been AutoGen-ed  January 20, 2016 at 04:18:42 AM by AutoGen 5.18.5
+ *  It has been AutoGen-ed  March 16, 2016 at 05:10:15 AM by AutoGen 5.18.5
  *  From the definitions    ntpq-opts.def
  *  and the template file   options
  *
@@ -73,15 +73,16 @@ typedef enum {
     INDEX_OPT_NUMERIC          =  6,
     INDEX_OPT_OLD_RV           =  7,
     INDEX_OPT_PEERS            =  8,
-    INDEX_OPT_WIDE             =  9,
-    INDEX_OPT_VERSION          = 10,
-    INDEX_OPT_HELP             = 11,
-    INDEX_OPT_MORE_HELP        = 12,
-    INDEX_OPT_SAVE_OPTS        = 13,
-    INDEX_OPT_LOAD_OPTS        = 14
+    INDEX_OPT_REFID            =  9,
+    INDEX_OPT_WIDE             = 10,
+    INDEX_OPT_VERSION          = 11,
+    INDEX_OPT_HELP             = 12,
+    INDEX_OPT_MORE_HELP        = 13,
+    INDEX_OPT_SAVE_OPTS        = 14,
+    INDEX_OPT_LOAD_OPTS        = 15
 } teOptIndex;
 /** count of all options for ntpq */
-#define OPTION_CT    15
+#define OPTION_CT    16
 /** ntpq version */
 #define NTPQ_VERSION       "4.2.8p6"
 /** Full ntpq version text */
@@ -174,6 +175,10 @@ typedef enum {
 #  warning undefining PEERS due to option name conflict
 #  undef   PEERS
 # endif
+# ifdef    REFID
+#  warning undefining REFID due to option name conflict
+#  undef   REFID
+# endif
 # ifdef    WIDE
 #  warning undefining WIDE due to option name conflict
 #  undef   WIDE
@@ -188,6 +193,7 @@ typedef enum {
 # undef NUMERIC
 # undef OLD_RV
 # undef PEERS
+# undef REFID
 # undef WIDE
 #endif  /*  NO_OPTION_NAME_WARNINGS */
 
@@ -206,6 +212,13 @@ typedef enum {
 #define VALUE_OPT_NUMERIC        'n'
 #define VALUE_OPT_OLD_RV         0x1001
 #define VALUE_OPT_PEERS          'p'
+#define VALUE_OPT_REFID          'r'
+
+typedef enum {
+    REFID_HASH, REFID_IPV4
+} te_Refid;
+#define OPT_REFID_VAL2STR(_v)    optionKeywordName(&DESC(REFID), (_v))
+#define OPT_VALUE_REFID          (DESC(REFID).optArg.argEnum)
 #define VALUE_OPT_WIDE           'w'
 /** option flag (value) for help-value option */
 #define VALUE_OPT_HELP          '?'

==== ntpq/ntpq-subs.c ====
2016-03-16 08:45:52+00:00, stenn at psp-deb1.ntp.org +17 -10
  [Bug 3030] ntpq needs a general way to specify refid output format.  HStenn.

--- 1.116/ntpq/ntpq-subs.c	2016-01-14 06:44:32 -05:00
+++ 1.116.1.1/ntpq/ntpq-subs.c	2016-03-16 04:45:52 -04:00
@@ -1679,7 +1679,8 @@ doprintpeers(
 		} else if (!strcmp("hmode", name)) {
 			decodeint(value, &hmode);
 		} else if (!strcmp("refid", name)) {
-			if (pvl == peervarlist) {
+			if (   (pvl == peervarlist)
+			    && (drefid == REFID_IPV4)) {
 				have_da_rid = TRUE;
 				drlen = strlen(value);
 				if (0 == drlen) {
@@ -1700,7 +1701,9 @@ doprintpeers(
 				} else {
 					have_da_rid = FALSE;
 				}
-			} else if (pvl == apeervarlist) {
+			} else if (   (pvl == apeervarlist)
+				   || (pvl == peervarlist)) {
+				/* no need to check drefid == REFID_HASH */
 				have_da_rid = TRUE;
 				drlen = strlen(value);
 				if (0 == drlen) {
@@ -2030,15 +2033,19 @@ peers(
 	FILE *fp
 	)
 {
-	int af = 0;
-
-	if (pcmd->nargs == 1) {
-		if (pcmd->argval->ival == 6)
-			af = AF_INET6;
-		else
-			af = AF_INET;
+	if (drefid == REFID_HASH) {
+		apeers(pcmd, fp);
+	} else {
+		int af = 0;
+
+		if (pcmd->nargs == 1) {
+			if (pcmd->argval->ival == 6)
+				af = AF_INET6;
+			else
+				af = AF_INET;
+		}
+		dopeers(0, fp, af);
 	}
-	dopeers(0, fp, af);
 }
 
 

==== ntpq/ntpq.1ntpqman ====
2016-03-16 08:45:52+00:00, stenn at psp-deb1.ntp.org +24 -3
  [Bug 3030] ntpq needs a general way to specify refid output format.  HStenn.

--- 1.336/ntpq/ntpq.1ntpqman	2016-01-20 04:20:07 -05:00
+++ 1.337/ntpq/ntpq.1ntpqman	2016-03-16 04:45:52 -04:00
@@ -10,11 +10,11 @@ 
 .ds B-Font B
 .ds I-Font I
 .ds R-Font R
-.TH ntpq 1ntpqman "20 Jan 2016" "4.2.8p6" "User Commands"
+.TH ntpq 1ntpqman "16 Mar 2016" "4.2.8p6" "User Commands"
 .\"
-.\" EDIT THIS FILE WITH CAUTION (/tmp/.ag-Z7aWRV/ag-_7aOQV)
+.\" EDIT THIS FILE WITH CAUTION (in-mem file)
 .\"
-.\" It has been AutoGen-ed January 20, 2016 at 04:19:06 AM by AutoGen 5.18.5
+.\" It has been AutoGen-ed March 16, 2016 at 05:10:36 AM by AutoGen 5.18.5
 .\" From the definitions ntpq-opts.def
 .\" and the template file agman-cmd.tpl
 .SH NAME
@@ -1347,6 +1347,27 @@ of their state. This is equivalent to th
 Print a list of the peers known to the server as well as a summary
 of their state. This is equivalent to the 'peers' interactive command.
 .TP
+.NOP \f\*[B-Font]\-r\f[] \f\*[I-Font]keyword\f[], \f\*[B-Font]\-\-refid\f[]=\f\*[I-Font]keyword\f[]
+Set default display type for S2+ refids.
+This option takes a keyword as its argument.  The argument sets an enumeration value that can
+be tested by comparing them against the option value macro.
+The available keywords are:
+.in +4
+.nf
+.na
+hash ipv4
+.fi
+or their numeric equivalent.
+.in -4
+.sp
+The default
+\f\*[I-Font]keyword\f[]
+for this option is:
+.ti +4
+ ipv4
+.sp
+Set the default display format for S2+ refids.
+.TP
 .NOP \f\*[B-Font]\-w\f[], \f\*[B-Font]\-\-wide\f[]
 Display the full 'remote' value.
 .sp

==== ntpq/ntpq.1ntpqmdoc ====
2016-03-16 08:45:52+00:00, stenn at psp-deb1.ntp.org +22 -2
  [Bug 3030] ntpq needs a general way to specify refid output format.  HStenn.

--- 1.336/ntpq/ntpq.1ntpqmdoc	2016-01-20 04:20:08 -05:00
+++ 1.337/ntpq/ntpq.1ntpqmdoc	2016-03-16 04:45:52 -04:00
@@ -1,9 +1,9 @@ 
-.Dd January 20 2016
+.Dd March 16 2016
 .Dt NTPQ 1ntpqmdoc User Commands
 .Os
 .\"  EDIT THIS FILE WITH CAUTION  (ntpq-opts.mdoc)
 .\"
-.\"  It has been AutoGen-ed  January 20, 2016 at 04:19:12 AM by AutoGen 5.18.5
+.\"  It has been AutoGen-ed  March 16, 2016 at 05:10:32 AM by AutoGen 5.18.5
 .\"  From the definitions    ntpq-opts.def
 .\"  and the template file   agmdoc-cmd.tpl
 .Sh NAME
@@ -898,6 +898,26 @@ of their state. This is equivalent to th
 .sp
 Print a list of the peers known to the server as well as a summary
 of their state. This is equivalent to the 'peers' interactive command.
+.It  Fl r Ar keyword , Fl \-refid Ns = Ns Ar keyword 
+Set default display type for S2+ refids.
+This option takes a keyword as its argument.  The argument sets an enumeration value that can
+be tested by comparing them against the option value macro.
+The available keywords are:
+.in +4
+.nf
+.na
+hash ipv4
+.fi
+or their numeric equivalent.
+.in -4
+.sp
+The default
+.Ar keyword
+for this option is:
+.ti +4
+ ipv4
+.sp
+Set the default display format for S2+ refids.
 .It  Fl w , Fl \-wide 
 Display the full 'remote' value.
 .sp

==== ntpq/ntpq.c ====
2016-03-16 08:45:53+00:00, stenn at psp-deb1.ntp.org +53 -2
  [Bug 3030] ntpq needs a general way to specify refid output format.  HStenn.

--- 1.168/ntpq/ntpq.c	2016-01-14 06:44:27 -05:00
+++ 1.169/ntpq/ntpq.c	2016-03-16 04:45:53 -04:00
@@ -38,7 +38,6 @@ 
 #include <ssl_applink.c>
 
 #include "ntp_libopts.h"
-#include "ntpq-opts.h"
 #include "safecast.h"
 
 #ifdef SYS_VXWORKS		/* vxWorks needs mode flag -casey*/
@@ -67,6 +66,11 @@ int	old_rv = 1;
  */
 int	old_rv = 1;
 
+/*
+ * How should we display the refid?
+ * REFID_HASH, REFID_IPV4
+ */
+te_Refid drefid = -1;
 
 /*
  * for get_systime()
@@ -198,6 +202,7 @@ static	void	version		(struct parse *, FI
 static	void	hostnames	(struct parse *, FILE *);
 static	void	setdebug	(struct parse *, FILE *);
 static	void	quit		(struct parse *, FILE *);
+static	void	showdrefid	(struct parse *, FILE *);
 static	void	version		(struct parse *, FILE *);
 static	void	raw		(struct parse *, FILE *);
 static	void	cooked		(struct parse *, FILE *);
@@ -269,6 +274,9 @@ struct xcmd builtins[] = {
 	{ "keyid",	keyid,		{ OPT|NTP_UINT, NO, NO, NO },
 	  { "key#", "", "", "" },
 	  "set keyid to use for authenticated requests" },
+	{ "drefid",	showdrefid,	{ OPT|NTP_STR, NO, NO, NO },
+	  { "hash|ipv4", "", "", "" },
+	  "display refid's as IPv4 or hash" },
 	{ "version",	version,	{ NO, NO, NO, NO },
 	  { "", "", "", "" },
 	  "print version number" },
@@ -532,6 +540,8 @@ ntpqmain(
 
 	old_rv = HAVE_OPT(OLD_RV);
 
+	drefid = OPT_VALUE_REFID;
+
 	if (0 == argc) {
 		ADDHOST(DEFHOST);
 	} else {
@@ -1327,7 +1337,7 @@ show_error_msg(
 	if (numhosts > 1)
 		fprintf(stderr, "server=%s ", currenthost);
 
-	switch(m6resp) {
+	switch (m6resp) {
 
 	case CERR_BADFMT:
 		fprintf(stderr,
@@ -2440,6 +2450,47 @@ ntp_poll(
 }
 
 
+/*
+ * showdrefid2str - return a string explanation of the value of drefid
+ */
+static char *
+showdrefid2str(void)
+{
+	switch (drefid) {
+	    case REFID_HASH:
+	    	return "hash";
+	    case REFID_IPV4:
+	    	return "ipv4";
+	    default:
+	    	return "Unknown";
+	}
+}
+
+
+/*
+ * drefid - display/change "display hash" 
+ */
+static void
+showdrefid(
+	struct parse *pcmd,
+	FILE *fp
+	)
+{
+	if (pcmd->nargs == 0) {
+		(void) fprintf(fp, "drefid value is %s\n", showdrefid2str());
+		return;
+	} else if (STREQ(pcmd->argval[0].string, "hash")) {
+		drefid = REFID_HASH;
+	} else if (STREQ(pcmd->argval[0].string, "ipv4")) {
+		drefid = REFID_IPV4;
+	} else {
+		(void) fprintf(fp, "What?\n");
+		return;
+	}
+	(void) fprintf(fp, "drefid value set to %s\n", showdrefid2str());
+}
+
+
 /*
  * keyid - get a keyid to use for authenticating requests
  */

==== ntpq/ntpq.h ====
2016-03-16 08:45:53+00:00, stenn at psp-deb1.ntp.org +3 -0
  [Bug 3030] ntpq needs a general way to specify refid output format.  HStenn.

--- 1.31/ntpq/ntpq.h	2015-11-28 13:09:53 -05:00
+++ 1.32/ntpq/ntpq.h	2016-03-16 04:45:53 -04:00
@@ -13,6 +13,8 @@ 
 #include "ntp_control.h"
 #include "lib_strbuf.h"
 
+#include "ntpq-opts.h"
+
 /*
  * Maximum number of arguments
  */
@@ -126,6 +128,7 @@ extern u_int	assoc_cache_slots;/* count 
 
 extern int	interactive;	/* are we prompting? */
 extern int	old_rv;		/* use old rv behavior? --old-rv */
+extern te_Refid	drefid;		/* How should we display a refid? */
 extern u_int	assoc_cache_slots;/* count of allocated array entries */
 extern u_int	numassoc;	/* number of cached associations */
 extern u_int	numhosts;

==== ntpq/ntpq.man.in ====
2016-03-16 08:45:53+00:00, stenn at psp-deb1.ntp.org +24 -3
  [Bug 3030] ntpq needs a general way to specify refid output format.  HStenn.

--- 1.336/ntpq/ntpq.man.in	2016-01-20 04:20:08 -05:00
+++ 1.337/ntpq/ntpq.man.in	2016-03-16 04:45:53 -04:00
@@ -10,11 +10,11 @@ 
 .ds B-Font B
 .ds I-Font I
 .ds R-Font R
-.TH ntpq @NTPQ_MS@ "20 Jan 2016" "4.2.8p6" "User Commands"
+.TH ntpq @NTPQ_MS@ "16 Mar 2016" "4.2.8p6" "User Commands"
 .\"
-.\" EDIT THIS FILE WITH CAUTION (/tmp/.ag-Z7aWRV/ag-_7aOQV)
+.\" EDIT THIS FILE WITH CAUTION (in-mem file)
 .\"
-.\" It has been AutoGen-ed January 20, 2016 at 04:19:06 AM by AutoGen 5.18.5
+.\" It has been AutoGen-ed March 16, 2016 at 05:10:36 AM by AutoGen 5.18.5
 .\" From the definitions ntpq-opts.def
 .\" and the template file agman-cmd.tpl
 .SH NAME
@@ -1347,6 +1347,27 @@ of their state. This is equivalent to th
 Print a list of the peers known to the server as well as a summary
 of their state. This is equivalent to the 'peers' interactive command.
 .TP
+.NOP \f\*[B-Font]\-r\f[] \f\*[I-Font]keyword\f[], \f\*[B-Font]\-\-refid\f[]=\f\*[I-Font]keyword\f[]
+Set default display type for S2+ refids.
+This option takes a keyword as its argument.  The argument sets an enumeration value that can
+be tested by comparing them against the option value macro.
+The available keywords are:
+.in +4
+.nf
+.na
+hash ipv4
+.fi
+or their numeric equivalent.
+.in -4
+.sp
+The default
+\f\*[I-Font]keyword\f[]
+for this option is:
+.ti +4
+ ipv4
+.sp
+Set the default display format for S2+ refids.
+.TP
 .NOP \f\*[B-Font]\-w\f[], \f\*[B-Font]\-\-wide\f[]
 Display the full 'remote' value.
 .sp

==== ntpq/ntpq.mdoc.in ====
2016-03-16 08:45:53+00:00, stenn at psp-deb1.ntp.org +22 -2
  [Bug 3030] ntpq needs a general way to specify refid output format.  HStenn.

--- 1.336/ntpq/ntpq.mdoc.in	2016-01-20 04:20:08 -05:00
+++ 1.337/ntpq/ntpq.mdoc.in	2016-03-16 04:45:53 -04:00
@@ -1,9 +1,9 @@ 
-.Dd January 20 2016
+.Dd March 16 2016
 .Dt NTPQ @NTPQ_MS@ User Commands
 .Os
 .\"  EDIT THIS FILE WITH CAUTION  (ntpq-opts.mdoc)
 .\"
-.\"  It has been AutoGen-ed  January 20, 2016 at 04:19:12 AM by AutoGen 5.18.5
+.\"  It has been AutoGen-ed  March 16, 2016 at 05:10:32 AM by AutoGen 5.18.5
 .\"  From the definitions    ntpq-opts.def
 .\"  and the template file   agmdoc-cmd.tpl
 .Sh NAME
@@ -898,6 +898,26 @@ of their state. This is equivalent to th
 .sp
 Print a list of the peers known to the server as well as a summary
 of their state. This is equivalent to the 'peers' interactive command.
+.It  Fl r Ar keyword , Fl \-refid Ns = Ns Ar keyword 
+Set default display type for S2+ refids.
+This option takes a keyword as its argument.  The argument sets an enumeration value that can
+be tested by comparing them against the option value macro.
+The available keywords are:
+.in +4
+.nf
+.na
+hash ipv4
+.fi
+or their numeric equivalent.
+.in -4
+.sp
+The default
+.Ar keyword
+for this option is:
+.ti +4
+ ipv4
+.sp
+Set the default display format for S2+ refids.
 .It  Fl w , Fl \-wide 
 Display the full 'remote' value.
 .sp

#### ChangeSet ####
2016-03-01 08:30:22+01:00, perlinger at ntp.org
  [Bug 3023] ntpdate cannot correct dates in the future.

==== ChangeLog ====
2016-03-01 08:30:21+01:00, perlinger at ntp.org +1 -0
  [Bug 3023] ntpdate cannot correct dates in the future.

--- 1.1794.1.2/ChangeLog	2016-01-24 05:14:42 -05:00
+++ 1.1794.10.1/ChangeLog	2016-03-01 02:30:21 -05:00
@@ -2,6 +2,7 @@ 
 
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
+* [Bug 3023] ntpdate cannot correct dates in the future. perlinger at ntp.org
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

==== ntpdate/ntpdate.c ====
2016-03-01 08:30:21+01:00, perlinger at ntp.org +9 -5
  [Bug 3023] ntpdate cannot correct dates in the future.

--- 1.97/ntpdate/ntpdate.c	2015-11-13 16:54:34 -05:00
+++ 1.98/ntpdate/ntpdate.c	2016-03-01 02:30:21 -05:00
@@ -1247,7 +1247,6 @@ clock_adjust(void)
 clock_adjust(void)
 {
 	register struct server *sp, *server;
-	s_fp absoffset;
 	int dostep;
 
 	for (sp = sys_servers; sp != NULL; sp = sp->next_server)
@@ -1270,10 +1269,15 @@ clock_adjust(void)
 	} else if (never_step) {
 		dostep = 0;
 	} else {
-		absoffset = server->soffset;
-		if (absoffset < 0)
-			absoffset = -absoffset;
-		dostep = (absoffset >= NTPDATE_THRESHOLD || absoffset < 0);
+		/* [Bug 3023] get absolute difference, avoiding signed
+		 * integer overflow like hell.
+		 */
+		u_fp absoffset;
+		if (server->soffset < 0)
+			absoffset = 1u + (u_fp)(-(server->soffset + 1));
+		else
+			absoffset = (u_fp)server->soffset;
+		dostep = (absoffset >= NTPDATE_THRESHOLD);
 	}
 
 	if (dostep) {

#### ChangeSet ####
2016-03-01 05:46:29+00:00, stenn at psp-deb1.ntp.org
  cleanup

==== ChangeLog ====
2016-03-01 05:46:25+00:00, stenn at psp-deb1.ntp.org +0 -1
  cleanup

--- 1.1804/ChangeLog	2016-02-29 18:00:47 -05:00
+++ 1.1805/ChangeLog	2016-03-01 00:46:25 -05:00
@@ -25,7 +25,6 @@ 
 * [Bug 3015] ntpq: config-from-file: "request contains an unprintable character"
   - A change related to [Bug 2853] forbids trailing white space in
     remote config commands. perlinger at ntp.org
->>>>>>>
 * Document ntp.key's optional IP list in authenetic.html.  Harlan Stenn.
 * Update html/xleave.html documentation.  Harlan Stenn.
 * Update ntp.conf documentation.  Harlan Stenn.

#### ChangeSet ####
2016-02-29 23:01:01+00:00, stenn at psp-deb1.ntp.org
  [Sec 3020] Refclock impersonation.  HStenn.

==== ChangeLog ====
2016-02-29 23:00:47+00:00, stenn at psp-deb1.ntp.org +1 -0
  [Sec 3020] Refclock impersonation.  HStenn.

--- 1.1803/ChangeLog	2016-02-22 01:37:34 -05:00
+++ 1.1804/ChangeLog	2016-02-29 18:00:47 -05:00
@@ -7,6 +7,7 @@ 
 * [Sec 3008] Always check the return value of ctl_getitem().
   - initial work by HStenn
   - Additional cleanup of ctl_getitem by perlinger at ntp.org
+* [Sec 3020] Refclock impersonation.  HStenn.
 * [Bug 2858] bool support.  Use stdbool.h when available.  HStenn.
 * [Bug 2879] Improve NTP security against timing attacks. perlinger at ntp.org
   - integrated patches by Loganaden Velvidron <logan at ntp.org>

==== configure.ac ====
2016-02-29 23:00:47+00:00, stenn at psp-deb1.ntp.org +18 -0
  [Sec 3020] Refclock impersonation.  HStenn.

--- 1.603/configure.ac	2016-01-21 03:45:29 -05:00
+++ 1.604/configure.ac	2016-02-29 18:00:47 -05:00
@@ -4160,6 +4160,24 @@ AC_MSG_CHECKING([if we should use the IR
 esac
 
 
+AC_MSG_CHECKING([if we want the explicit 127.0.0.0/8 martian filter])
+AC_ARG_ENABLE(
+    [bug3020-fix],
+    [AS_HELP_STRING(
+	[--enable-bug3020-fix],
+	[+ Provide the explicit 127.0.0.0/8 martian filter]
+    )],
+    [ans=$enableval],
+    [ans=yes]
+)
+AC_MSG_RESULT([$ans])
+case "$ans" in
+ yes)
+    AC_DEFINE([ENABLE_BUG3020_FIX], [1],
+	[Provide the explicit 127.0.0.0/8 martian filter?])
+esac
+
+
 AC_MSG_CHECKING([if we should use the IRIG sawtooth filter])
 
 case "$host" in

==== ntpd/ntp_io.c ====
2016-02-29 23:00:51+00:00, stenn at psp-deb1.ntp.org +12 -0
  [Sec 3020] Refclock impersonation.  HStenn.

--- 1.414/ntpd/ntp_io.c	2016-01-24 05:13:18 -05:00
+++ 1.415/ntpd/ntp_io.c	2016-02-29 18:00:51 -05:00
@@ -3447,6 +3447,18 @@ read_network_packet(
 	DPRINTF(3, ("read_network_packet: fd=%d length %d from %s\n",
 		    fd, buflen, stoa(&rb->recv_srcadr)));
 
+#ifdef ENABLE_BUG3020_FIX
+	if (ISREFCLOCKADR(&rb->recv_srcadr)) {
+		msyslog(LOG_ERR, "recvfrom(%s) fd=%d: refclock srcadr on a network interface!",
+			stoa(&rb->recv_srcadr), fd);
+		DPRINTF(1, ("read_network_packet: fd=%d dropped (refclock srcadr))\n",
+			    fd));
+		packets_dropped++;
+		freerecvbuf(rb);
+		return (buflen);
+	}
+#endif
+
 	/*
 	** Bug 2672: Some OSes (MacOSX and Linux) don't block spoofed ::1
 	*/

#### ChangeSet ####
2016-02-29 20:03:59+01:00, jnperlin at hydra.localnet
  [Bug 3022] authkeys.c should be refactored

==== ChangeLog ====
2016-02-29 20:03:59+01:00, jnperlin at hydra.localnet +4 -0
  [Bug 3022] authkeys.c should be refactored

--- 1.1794.1.2/ChangeLog	2016-01-24 05:14:42 -05:00
+++ 1.1794.9.1/ChangeLog	2016-02-29 14:03:59 -05:00
@@ -2,6 +2,10 @@ 
 
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
+* [Bug 3022] authkeys.c should be refactored. perlinger at ntp.org
+  - fixed memory leak in access list (auth[read]keys.c)
+  - refactored handling of key access lists (auth[read]keys.c)
+  - reduced number of error branches (authreadkeys.c)
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

==== include/ntp_keyacc.h ====
2016-02-29 20:03:59+01:00, jnperlin at hydra.localnet +6 -0
  [Bug 3022] authkeys.c should be refactored
   - refactoring of key access handling

--- 1.1/include/ntp_keyacc.h	2016-01-18 04:45:13 -05:00
+++ 1.2/include/ntp_keyacc.h	2016-02-29 14:03:59 -05:00
@@ -10,4 +10,10 @@ struct keyaccess {
 	sockaddr_u	addr;
 };
 
+extern KeyAccT* keyacc_new_push(KeyAccT *head, const sockaddr_u *addr);
+extern KeyAccT* keyacc_pop_free(KeyAccT *head);
+extern KeyAccT* keyacc_all_free(KeyAccT *head);
+extern int      keyacc_contains(const KeyAccT *head, const sockaddr_u *addr,
+				int res_on_empty_list);
+
 #endif	/* NTP_KEYACC_H */

==== libntp/authkeys.c ====
2016-02-29 20:03:59+01:00, jnperlin at hydra.localnet +146 -85
  [Bug 3022] authkeys.c should be refactored
   - refactoring of key access handling
   - fixed memory leak in access list

--- 1.33/libntp/authkeys.c	2016-01-23 22:02:24 -05:00
+++ 1.34/libntp/authkeys.c	2016-02-29 14:03:59 -05:00
@@ -54,7 +54,7 @@ static void		freesymkey(symkey *, keyid_
 static void		auth_resize_hashtable(void);
 static void		allocsymkey(keyid_t,	u_short,
 				    u_short, u_long, size_t, u_char *, KeyAccT *);
-static void		freesymkey(symkey *, keyid_t);
+static void		freesymkey(symkey *);
 #ifdef DEBUG
 static void		free_auth_mem(void);
 #endif
@@ -75,10 +75,10 @@ u_long authnumkeys;			/* number of activ
 
 u_long authkeynotfound;		/* keys not found */
 u_long authkeylookups;		/* calls to lookup keys */
-u_long authnumkeys;			/* number of active keys */
+u_long authnumkeys;		/* number of active keys */
 u_long authkeyexpired;		/* key lifetime expirations */
 u_long authkeyuncached;		/* cache misses */
-u_long authnokey;			/* calls to encrypt with no key */
+u_long authnokey;		/* calls to encrypt with no key */
 u_long authencryptions;		/* calls to encrypt */
 u_long authdecryptions;		/* calls to decrypt */
 
@@ -93,14 +93,87 @@ int authnumfreekeys;
 
 /*
  * The key cache. We cache the last key we looked at here.
+ * Note: this should hold the last *trusted* key. Also the
+ * cache is only loaded when the digest type / MAC algorithm
+ * is valid.
  */
 keyid_t	cache_keyid;		/* key identifier */
 u_char *cache_secret;		/* secret */
 size_t	cache_secretsize;	/* secret length */
-int	cache_type;				/* OpenSSL digest NID */
+int	cache_type;		/* OpenSSL digest NID */
 u_short cache_flags;		/* flags that wave */
 KeyAccT *cache_keyacclist;	/* key access list */
 
+/* --------------------------------------------------------------------
+ * manage key access lists
+ * --------------------------------------------------------------------
+ */
+/* allocate and populate new access node and pushes it on the list.
+ * Returns the new head.
+ */
+KeyAccT*
+keyacc_new_push(
+	KeyAccT          * head,
+	const sockaddr_u * addr
+	)
+{
+	KeyAccT *	node = emalloc(sizeof(KeyAccT));
+	
+	memcpy(&node->addr, addr, sizeof(sockaddr_u));
+	node->next = head;
+	return node;
+}
+
+/* ----------------------------------------------------------------- */
+/* pop and deallocate the first node of a list of access nodes, if
+ * the list is not empty. Returns the tail of the list.
+ */
+KeyAccT*
+keyacc_pop_free(
+	KeyAccT *head
+	)
+{
+	KeyAccT *	next = NULL;
+	if (head) {
+		next = head->next;
+		free(head);
+	}
+	return next;
+}
+
+/* ----------------------------------------------------------------- */
+/* deallocate the list; returns an empty list. */
+KeyAccT*
+keyacc_all_free(
+	KeyAccT * head
+	)
+{
+	while (head)
+		head = keyacc_pop_free(head);
+	return head;
+}
+
+/* ----------------------------------------------------------------- */
+/* scan a list to see if it contains a given address. Return the
+ * default result value in case of an empty list.
+ */
+int /*BOOL*/
+keyacc_contains(
+	const KeyAccT    *head,
+	const sockaddr_u *addr,
+	int               defv)
+{
+	if (head) {
+		do {
+			if (SOCK_EQ(&head->addr, addr))
+				return TRUE;
+		} while (NULL != (head = head->next));
+		return FALSE;
+	} else {
+		return !!defv;
+	}
+}
+
 
 /*
  * init_auth - initialize internal data
@@ -139,7 +212,7 @@ free_auth_mem(void)
 	symkey_alloc *	next_alloc;
 
 	while (NULL != (sk = HEAD_DLIST(key_listhead, llink))) {
-		freesymkey(sk, sk->keyid);
+		freesymkey(sk);
 	}
 	free(key_hash);
 	key_hash = NULL;
@@ -243,6 +316,21 @@ auth_log2(size_t x)
 	return (u_short)r;
 }
 
+static void
+authcache_flush_id(
+	keyid_t id
+	)
+{
+	if (cache_keyid == id) {
+		cache_keyid = 0;
+		cache_type = 0;
+		cache_flags = 0;
+		cache_secret = NULL;
+		cache_secretsize = 0;
+		cache_keyacclist = NULL;
+	}
+}
+
 
 /*
  * auth_resize_hashtable
@@ -326,13 +414,19 @@ freesymkey(
  */
 static void
 freesymkey(
-	symkey *	sk,
-	keyid_t		id
+	symkey *	sk
 	)
 {
-symkey **	bucket = &key_hash[KEYHASH(id)];
-symkey *	unlinked;
+	symkey **	bucket;
+	symkey *	unlinked;
+
+	if (NULL == sk)
+		return;
 
+	authcache_flush_id(sk->keyid);
+	keyacc_all_free(sk->keyacclist);
+	
+	bucket = &key_hash[KEYHASH(sk->keyid)];
 	if (sk->secret != NULL) {
 		memset(sk->secret, '\0', sk->secretsize);
 		free(sk->secret);
@@ -358,35 +452,26 @@ auth_findkey(
 {
 	symkey *	sk;
 
-	for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) {
-		if (id == sk->keyid) {
+	for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink)
+		if (id == sk->keyid)
 			return sk;
-		}
-	}
-
 	return NULL;
 }
 
 
 /*
- * auth_havekey - return TRUE if the key id is zero or known
+ * auth_havekey - return TRUE if the key id is zero or known. The
+ * key needs not to be trusted.
  */
 int
 auth_havekey(
 	keyid_t		id
 	)
 {
-	symkey *	sk;
-
-	if (0 == id || cache_keyid == id) {
-		return TRUE;
-	}
-
-	sk = auth_findkey(id);
-	if (sk != NULL && id == sk->keyid) {
-		return TRUE;
-	}
-	return FALSE;
+	return
+	    (0           == id) ||
+	    (cache_keyid == id) ||
+	    (NULL        != auth_findkey(id));
 }
 
 
@@ -402,33 +487,25 @@ authhavekey(
 	symkey *	sk;
 
 	authkeylookups++;
-	if (0 == id || cache_keyid == id) {
-		return TRUE;
-	}
+	if (0 == id || cache_keyid == id)
+		return !!(KEY_TRUSTED & cache_flags);
 
 	/*
-	 * Seach the bin for the key. If found and the key type
-	 * is zero, somebody marked it trusted without specifying
-	 * a key or key type. In this case consider the key missing.
+	 * Search the bin for the key. If not found, or found but the key
+	 * type is zero, somebody marked it trusted without specifying a
+	 * key or key type. In this case consider the key missing.
 	 */
 	authkeyuncached++;
 	sk = auth_findkey(id);
-	if (sk != NULL && id == sk->keyid) {
-		if (sk->type == 0) {
-			authkeynotfound++;
-			return FALSE;
-		}
+	if ((sk == NULL) || (sk->type == 0)) {
+		authkeynotfound++;
+		return FALSE;
 	}
 
 	/*
-	 * If the key is not found, or if it is found but not trusted,
-	 * the key is not considered found.
-	 */
-	if (NULL == sk) {
-		authkeynotfound++;
-		return FALSE;
-	}
-	if (!(KEY_TRUSTED & sk->flags)) {
+	 * If the key is not trusted, the key is not considered found.
+	 */
+	if ( ! (KEY_TRUSTED & sk->flags)) {
 		authnokey++;
 		return FALSE;
 	}
@@ -474,27 +551,22 @@ authtrust(
 	 * not to be trusted.
 	 */	
 	if (sk != NULL) {
-		if (cache_keyid == id) {
-			cache_flags = 0;
-			cache_keyid = 0;
-			cache_keyacclist = NULL;
-		}
-
 		/*
-		 * Key exists. If it is to be trusted, say so and
-		 * update its lifetime. 
+		 * Key exists. If it is to be trusted, say so and update
+		 * its lifetime. If no longer trusted, return it to the
+		 * free list. Flush the cache first to be sure there are
+		 * no discrepancies.
 		 */
+		authcache_flush_id(id);
 		if (trust > 0) {
 			sk->flags |= KEY_TRUSTED;
 			if (trust > 1)
 				sk->lifetime = current_time + trust;
 			else
 				sk->lifetime = 0;
-			return;
+		} else {
+			freesymkey(sk);
 		}
-
-		/* No longer trusted, return it to the free list. */
-		freesymkey(sk, id);
 		return;
 	}
 
@@ -544,33 +616,21 @@ authistrusted(
 	)
 {
 	symkey *	sk;
-	KeyAccT *	kal;
-	KeyAccT *	k;
 
+	/* That specific key was already used to authenticate the
+	 * packet. Therefore, the key *must* exist...  There's a chance
+	 * that is not trusted, though.
+	 */
 	if (keyno == cache_keyid) {
-		kal = cache_keyacclist;
+		return (KEY_TRUSTED & cache_flags) &&
+		    keyacc_contains(cache_keyacclist, sau, TRUE);
 	} else {
 		authkeyuncached++;
-
 		sk = auth_findkey(keyno);
-		if (NULL == sk || !(KEY_TRUSTED & sk->flags)) {
-			INSIST(!"authistrustedip: keyid not found/trusted!");
-			return FALSE;
-		}
-		kal = sk->keyacclist;
-	}
-
-	if (NULL == kal) {
-		return TRUE;
-	}
-
-	for (k = kal; k; k = k->next) {
-		if (SOCK_EQ(&k->addr, sau)) {
-			return TRUE;
-		}
+		INSIST(NULL != sk);
+		return (KEY_TRUSTED & sk->flags) &&
+		    keyacc_contains(sk->keyacclist, sau, TRUE);
 	}
-
-	return FALSE;
 }
 
 /* Note: There are two locations below where 'strncpy()' is used. While
@@ -612,7 +672,11 @@ MD5auth_setkey(
 		sk->secret = emalloc(secretsize + 1);
 		sk->type = (u_short)keytype;
 		sk->secretsize = secretsize;
-		sk->keyacclist = ka;
+		/* make sure access lists don't leak here! */
+		if (ka != sk->keyacclist) {
+			keyacc_all_free(sk->keyacclist);
+			sk->keyacclist = ka;
+		}
 #ifndef DISABLE_BUG1243_FIX
 		memcpy(sk->secret, key, secretsize);
 #else
@@ -620,11 +684,7 @@ MD5auth_setkey(
 		strncpy((char *)sk->secret, (const char *)key,
 			secretsize);
 #endif
-		if (cache_keyid == keyno) {
-			cache_flags = 0;
-			cache_keyid = 0;
-			cache_keyacclist = NULL;
-		}
+		authcache_flush_id(keyno);
 		return;
 	}
 
@@ -680,10 +740,11 @@ auth_delkeys(void)
 				free(sk->secret);
 				sk->secret = NULL; /* TALOS-CAN-0054 */
 			}
+			sk->keyacclist = keyacc_all_free(sk->keyacclist);
 			sk->secretsize = 0;
 			sk->lifetime = 0;
 		} else {
-			freesymkey(sk, sk->keyid);
+			freesymkey(sk);
 		}
 	ITER_DLIST_END()
 }
@@ -699,7 +760,7 @@ auth_agekeys(void)
 
 	ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
 		if (sk->lifetime > 0 && current_time > sk->lifetime) {
-			freesymkey(sk, sk->keyid);
+			freesymkey(sk);
 			authkeyexpired++;
 		}
 	ITER_DLIST_END()

==== libntp/authreadkeys.c ====
2016-02-29 20:03:59+01:00, jnperlin at hydra.localnet +52 -44
  [Bug 3022] authkeys.c should be refactored
   - refactoring of key access handling
   - reduced number of error branches

--- 1.25/libntp/authreadkeys.c	2016-01-18 06:54:42 -05:00
+++ 1.25.1.1/libntp/authreadkeys.c	2016-02-29 14:03:59 -05:00
@@ -101,13 +101,26 @@ log_maybe(
 	...)
 {
 	va_list ap;
-	if (++(*pnerr) <= nerr_loglimit) {
+	if ((NULL == pnerr) || (++(*pnerr) <= nerr_loglimit)) {
 		va_start(ap, fmt);
 		mvsyslog(LOG_ERR, fmt, ap);
 		va_end(ap);
 	}
 }
 
+static void
+free_keydata(
+	KeyDataT *node
+	)
+{
+	if (node) {
+		keyacc_all_free(node->keyacclist);
+		/* purge secrets from memory before free()ing it */
+		memset(node, 0, sizeof(*node) + node->seclen);
+		free(node);
+	}
+}
+
 /*
  * authreadkeys - (re)read keys from a file.
  */
@@ -156,7 +169,7 @@ authreadkeys(
 		 * First is key number.  See if it is okay.
 		 */
 		keyno = atoi(token);
-		if (keyno == 0) {
+		if (keyno < 1) {
 			log_maybe(&nerr,
 				  "authreadkeys: cannot change key %s",
 				  token);
@@ -180,6 +193,14 @@ authreadkeys(
 				  keyno);
 			continue;
 		}
+
+		/* We want to silently ignore keys where we do not
+		 * support the requested digest type. OTOH, we want to
+		 * make sure the file is well-formed.  That means we
+		 * have to process the line completely and have to
+		 * finally throw away the result... This is a bit more
+		 * work, but it also results in better error detection.
+		 */ 
 #ifdef OPENSSL
 		/*
 		 * The key type is the NID used by the message digest 
@@ -189,30 +210,28 @@ authreadkeys(
 		 */
 		keytype = keytype_from_text(token, NULL);
 		if (keytype == 0) {
-			log_maybe(&nerr,
+			log_maybe(NULL,
 				  "authreadkeys: invalid type for key %d",
 				  keyno);
-			continue;
-		}
-		if (EVP_get_digestbynid(keytype) == NULL) {
-			log_maybe(&nerr,
+		} else if (EVP_get_digestbynid(keytype) == NULL) {
+			log_maybe(NULL,
 				  "authreadkeys: no algorithm for key %d",
 				  keyno);
-			continue;
+			keytype = 0;
 		}
 #else	/* !OPENSSL follows */
-
 		/*
 		 * The key type is unused, but is required to be 'M' or
 		 * 'm' for compatibility.
 		 */
 		if (!(*token == 'M' || *token == 'm')) {
-			log_maybe(&nerr,
+			log_maybe(NULL,
 				  "authreadkeys: invalid type for key %d",
 				  keyno);
-			continue;
+			keytype = 0;
+		} else {
+			keytype = KEY_TYPE_MD5;
 		}
-		keytype = KEY_TYPE_MD5;
 #endif	/* !OPENSSL */
 
 		/*
@@ -269,26 +288,22 @@ DPRINTF(0, ("authreadkeys: full access l
 		}
 
 		token = nexttok(&line);
-DPRINTF(0, ("authreadkeys: full access list <%s>\n", (token) ? token : "NULL"));
+		DPRINTF(0, ("authreadkeys: full access list <%s>\n", (token) ? token : "NULL"));
 		if (token != NULL) {	/* A comma-separated IP access list */
 			char *tp = token;
 
 			while (tp) {
 				char *i;
-				KeyAccT ka;
+				sockaddr_u addr;
 
 				i = strchr(tp, (int)',');
 				if (i)
 					*i = '\0';
-DPRINTF(0, ("authreadkeys: access list:  <%s>\n", tp));
-
-				if (is_ip_address(tp, AF_UNSPEC, &ka.addr)) {
-					KeyAccT *kap;
-
-					kap = emalloc(sizeof(KeyAccT));
-					memcpy(kap, &ka, sizeof ka);
-					kap->next = next->keyacclist;
-					next->keyacclist = kap;
+				DPRINTF(0, ("authreadkeys: access list:  <%s>\n", tp));
+
+				if (is_ip_address(tp, AF_UNSPEC, &addr)) {
+					next->keyacclist = keyacc_new_push(
+						next->keyacclist, &addr);
 				} else {
 					log_maybe(&nerr,
 						  "authreadkeys: invalid IP address <%s> for key %d",
@@ -303,21 +318,25 @@ DPRINTF(0, ("authreadkeys: access list: 
 			}
 		}
 
+		/* check if this has to be weeded out... */
+		if (0 == keytype) {
+			free_keydata(next);
+			next = NULL;
+			continue;
+		}
+		
 		INSIST(NULL != next);
 		next->next = list;
 		list = next;
 	}
 	fclose(fp);
-	if (nerr > nerr_maxlimit) {
-		msyslog(LOG_ERR,
-			"authreadkeys: rejecting file '%s' after %u errors (emergency break)",
-			file, nerr);
-		goto onerror;
-	}
 	if (nerr > 0) {
+		const char * why = "";
+		if (nerr > nerr_maxlimit)
+			why = " (emergency break)";
 		msyslog(LOG_ERR,
-			"authreadkeys: rejecting file '%s' after %u error(s)",
-			file, nerr);
+			"authreadkeys: rejecting file '%s' after %u error(s)%s",
+			file, nerr, why);
 		goto onerror;
 	}
 
@@ -328,9 +347,8 @@ DPRINTF(0, ("authreadkeys: access list: 
 		list = next->next;
 		MD5auth_setkey(next->keyid, next->keytype,
 			       next->secbuf, next->seclen, next->keyacclist);
-		/* purge secrets from memory before free()ing it */
-		memset(next, 0, sizeof(*next) + next->seclen);
-		free(next);
+		next->keyacclist = NULL; /* consumed by MD5auth_setkey */
+		free_keydata(next);
 	}
 	return (1);
 
@@ -338,17 +356,7 @@ DPRINTF(0, ("authreadkeys: access list: 
 	/* Mop up temporary storage before bailing out. */
 	while (NULL != (next = list)) {
 		list = next->next;
-
-		while (next->keyacclist) {
-			KeyAccT *kap = next->keyacclist;
-
-			next->keyacclist = kap->next;
-			free(kap);
-		}
-
-		/* purge secrets from memory before free()ing it */
-		memset(next, 0, sizeof(*next) + next->seclen);
-		free(next);
+		free_keydata(next);
 	}
 	return (0);
 }

#### ChangeSet ####
2016-02-22 05:33:56+00:00, stenn at psp-deb1.ntp.org
  [Sec 3008] Always check the return value of ctl_getitem().  HStenn.

==== ChangeLog ====
2016-02-22 05:33:46+00:00, stenn at psp-deb1.ntp.org +1 -0
  [Sec 3008] Always check the return value of ctl_getitem().  HStenn.

--- 1.1801/ChangeLog	2016-02-06 02:43:23 -05:00
+++ 1.1801.2.1/ChangeLog	2016-02-22 00:33:46 -05:00
@@ -4,6 +4,7 @@ 
 * [Sec 2936] Skeleton Key: Any system knowing the trusted key can serve
   time. Include passive servers in this check. HStenn.
 * [Sec 2945] Additional KoD packet checks.  HStenn.
+* [Sec 3008] Always check the return value of ctl_getitem().  HStenn.
 * [Bug 2858] bool support.  Use stdbool.h when available.  HStenn.
 * [Bug 2879] Improve NTP security against timing attacks. perlinger at ntp.org
   - integrated patches by Loganaden Velvidron <logan at ntp.org>

==== ntpd/ntp_control.c ====
2016-02-22 05:33:41+00:00, stenn at psp-deb1.ntp.org +11 -2
  [Sec 3008] Always check the return value of ctl_getitem().  HStenn.

--- 1.206/ntpd/ntp_control.c	2016-01-13 00:55:43 -05:00
+++ 1.206.2.1/ntpd/ntp_control.c	2016-02-22 00:33:41 -05:00
@@ -3334,7 +3334,11 @@ read_sysvars(void)
 			gotvar = 1;
 		} else {
 			v = ctl_getitem(ext_sys_var, &valuep);
-			INSIST(v != NULL);
+			if (NULL == v) {
+				ctl_error(CERR_BADVALUE);
+				free(wants);
+				return;
+			}
 			if (EOV & v->flags) {
 				ctl_error(CERR_UNKNOWNVAR);
 				free(wants);
@@ -4575,7 +4579,12 @@ read_clockstatus(
 			gotvar = TRUE;
 		} else {
 			v = ctl_getitem(kv, &valuep);
-			INSIST(NULL != v);
+			if (NULL == v) {
+				ctl_error(CERR_BADVALUE);
+				free(wants);
+				free_varlist(cs.kv_list);
+				return;
+			}
 			if (EOV & v->flags) {
 				ctl_error(CERR_UNKNOWNVAR);
 				free(wants);

#### ChangeSet ####
2016-02-22 05:12:39+00:00, stenn at psp-deb1.ntp.org
  Update ntp.conf documentation.  Harlan Stenn.

==== ntpd/ntp.conf.def ====
2016-02-22 05:12:33+00:00, stenn at psp-deb1.ntp.org +38 -16
  Update ntp.conf documentation.  Harlan Stenn.

--- 1.22/ntpd/ntp.conf.def	2016-02-06 02:43:27 -05:00
+++ 1.23/ntpd/ntp.conf.def	2016-02-22 00:12:33 -05:00
@@ -113,8 +113,14 @@ In a few cases, including the reslist bi
 If the Basic Socket Interface Extensions for IPv6 (RFC-2553)
 is detected, support for the IPv6 address family is generated
 in addition to the default support of the IPv4 address family.
-In a few cases, including the reslist billboard generated
-by ntpdc, IPv6 addresses are automatically generated.
+In a few cases, including the
+.Cm reslist
+billboard generated
+by
+.Xr ntpq 1ntpqmdoc
+or
+.Xr ntpdc 1ntpdcmdoc ,
+IPv6 addresses are automatically generated.
 IPv6 addresses can be identified by the presence of colons
 .Dq \&:
 in the address field.
@@ -149,6 +155,7 @@ equivalent classes for that address fami
 .Op Cm prefer
 .Op Cm minpoll Ar minpoll
 .Op Cm maxpoll Ar maxpoll
+.Op Cm true
 .Xc
 .It Xo Ic peer Ar address
 .Op Cm key Ar key \&| Cm autokey
@@ -156,6 +163,8 @@ equivalent classes for that address fami
 .Op Cm prefer
 .Op Cm minpoll Ar minpoll
 .Op Cm maxpoll Ar maxpoll
+.Op Cm true
+.Op Cm xleave
 .Xc
 .It Xo Ic broadcast Ar address
 .Op Cm key Ar key \&| Cm autokey
@@ -163,6 +172,7 @@ equivalent classes for that address fami
 .Op Cm prefer
 .Op Cm minpoll Ar minpoll
 .Op Cm ttl Ar ttl
+.Op Cm xleave
 .Xc
 .It Xo Ic manycastclient Ar address
 .Op Cm key Ar key \&| Cm autokey
@@ -340,6 +350,7 @@ Marks the server as a truechimer.
 Says the association can be preempted.
 .It Cm true
 Marks the server as a truechimer.
+Use this option only for testing.
 .It Cm prefer
 Marks the server as preferred.
 All other things being equal,
@@ -352,6 +363,11 @@ for further information.
 provided in
 .Pa /usr/share/doc/ntp )
 for further information.
+.It Cm true
+Forces the association to always survive the selection and clustering algorithms.
+This option should almost certainly
+.Em only
+be used while testing an association.
 .It Cm ttl Ar ttl
 This option is used only with broadcast server and manycast
 client modes.
@@ -521,7 +537,7 @@ program running in
 commands and also by remote
 configuration commands sent by a
 .Xr ntpdc 1ntpdcmdoc
-program running in
+program running on
 another machine.
 If this flag is enabled, which is the default
 case, new broadcast client and symmetric passive associations and
@@ -711,7 +727,7 @@ includes the source and destinatino IP a
 all of which are bound together by the protocol specifically
 to deflect masquerade attacks.
 For this reason Autokey
-includes the source and destinatino IP addresses in message digest
+includes the source and destination IP addresses in message digest
 computations and so the same addresses must be available
 at both the server and client.
 For this reason operation
@@ -909,8 +925,8 @@ Specifies the location of the optional I
 .Pa ntpkey_key_ Ns Ar hostname
 in the keys directory.
 .It Cm iffpar Ar file
-Specifies the location of the optional IFF parameters file.This
-overrides the link
+Specifies the location of the optional IFF parameters file.
+This overrides the link
 .Pa ntpkey_iff_ Ns Ar hostname
 in the keys directory.
 .It Cm leap Ar file
@@ -920,8 +936,7 @@ This
 in the keys directory.
 .It Cm mvpar Ar file
 Specifies the location of the optional MV parameters file.
-This
-overrides the link
+This overrides the link
 .Pa ntpkey_mv_ Ns Ar hostname
 in the keys directory.
 .It Cm pw Ar password
@@ -1062,7 +1077,7 @@ directory of this distribution.
 Statistic files are managed using file generation sets
 and scripts in the
 .Pa ./scripts
-directory of this distribution.
+directory of the source code distribution.
 Using
 these facilities and
 .Ux
@@ -1396,7 +1411,9 @@ and the pid of the ntpd server process.
 the number of links of this file is one, it is renamed appending a
 dot, the letter
 .Cm C ,
-and the pid of the ntpd server process.
+and the pid of the
+.Xr ntpd 1ntpdmdoc
+server process.
 When the
 number of links is greater than one, the file is unlinked.
 This
@@ -1451,9 +1468,9 @@ an indefinate period.
 Some violations cause denied service
 only for the offending packet, others cause denied service
 for a timed period and others cause the denied service for
-an indefinate period.
+an indefinite period.
 When a client or network is denied access
-for an indefinate period, the only way at present to remove
+for an indefinite period, the only way at present to remove
 the restrictions is by restarting the server.
 .Ss The Kiss-of-Death Packet
 Ordinarily, packets denied service are simply dropped with no
@@ -1634,7 +1651,9 @@ The trap service is a subsystem of the n
 .It Cm notrap
 Decline to provide mode 6 control message trap service to matching
 hosts.
-The trap service is a subsystem of the ntpdq control message
+The trap service is a subsystem of the
+.Xr ntpq 1ntpqmdoc
+control message
 protocol which is intended for use by remote event logging programs.
 .It Cm notrust
 Deny service unless the packet is cryptographically authenticated.
@@ -2415,7 +2434,8 @@ a 6-bit code.  The default value is 46, 
 otherwise, should be avoided.
 .It Ic dscp Ar value
 This option specifies the Differentiated Services Control Point (DSCP) value,
-a 6-bit code.  The default value is 46, signifying Expedited Forwarding.
+a 6-bit code.
+The default value is 46, signifying Expedited Forwarding.
 .It Xo Ic enable
 .Oo
 .Cm auth | Cm bclient |
@@ -2654,7 +2674,8 @@ messages of the respective message class
 message class may also be followed by the
 .Cm all
 keyword to enable/disable all
-messages of the respective message class.Thus, a minimal log configuration
+messages of the respective message class.
+Thus, a minimal log configuration
 could look like this:
 .Bd -literal
 logconfig =syncstatus +sysevents
@@ -2832,7 +2853,8 @@ Specifies the maximum number of file des
 function.
 Defaults to 50 4k pages (200 4k pages in OpenBSD).
 .It Cm filenum Ar Nfiledescriptors
-Specifies the maximum number of file descriptors ntpd may have open at once. Defaults to the system default.
+Specifies the maximum number of file descriptors ntpd may have open at once.
+Defaults to the system default.
 .El
 .It Xo Ic trap Ar host_address
 .Op Cm port Ar port_number

#### ChangeSet ####
2016-02-22 03:39:39+00:00, stenn at psp-deb1.ntp.org
  Bug 3007 cleanup

==== ntpd/ntp_proto.c ====
2016-02-22 03:39:18+00:00, stenn at psp-deb1.ntp.org +4 -1
  Bug 3007 cleanup

--- 1.378/ntpd/ntp_proto.c	2016-02-21 21:09:33 -05:00
+++ 1.379/ntpd/ntp_proto.c	2016-02-21 22:39:18 -05:00
@@ -258,10 +258,11 @@ kiss_code_check(
 	}
 }
 
+
 /* 
  * Check that NAK is valid
  */
-BOOL
+enum nak_error_codes
 valid_NAK(
 	  struct peer *peer,
 	  struct recvbuf *rbufp,
@@ -319,6 +320,7 @@ valid_NAK(
 	}
 }
 
+
 /*
  * transmit - transmit procedure called by poll timeout
  */
@@ -4163,6 +4165,7 @@ group_test(
 }
 #endif /* AUTOKEY */
 
+
 #ifdef WORKER
 void
 pool_name_resolved(

#### ChangeSet ####
2016-02-21 15:09:37+01:00, perlinger at ntp.org
  [Bug 3009] Crafted addpeer with hmode > 7 causes OOB error

==== ChangeLog ====
2016-02-21 15:09:36+01:00, perlinger at ntp.org +2 -0
  [Bug 3009] Crafted addpeer with hmode > 7 causes OOB error

--- 1.1794.1.2/ChangeLog	2016-01-24 05:14:42 -05:00
+++ 1.1794.8.1/ChangeLog	2016-02-21 09:09:36 -05:00
@@ -2,6 +2,8 @@ 
 
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
+* [Bug 3009] Crafted addpeer with hmode > 7 causes OOB error. perlinger at ntp.org
+   - added more stringent checks on packet content
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

==== ntpd/ntp_request.c ====
2016-02-21 15:09:36+01:00, perlinger at ntp.org +29 -2
  [Bug 3009] Crafted addpeer with hmode > 7 causes OOB error
   - added more stringent checks on packet content:
     hmode <= 6 (7 is already out of range for a peer mode!)

--- 1.117/ntpd/ntp_request.c	2016-01-14 05:24:57 -05:00
+++ 1.117.2.1/ntpd/ntp_request.c	2016-02-21 09:09:36 -05:00
@@ -1342,11 +1342,38 @@ do_conf(
 		peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
 #endif
 
-		/* XXX W2DO? minpoll/maxpoll arguments ??? */
+		/* check mode value: 0 <= hmode <= 6
+		 *
+		 * There's no good global define for that limit, and
+		 * using a magic define is as good (or bad, actually) as
+		 * a magic number. So we use the highest possible peer
+		 * mode, and that is MODE_BCLIENT.
+		 *
+		 * [Bug 3009] claims that a problem occurs for hmode > 7,
+		 * but the code in ntp_peer.c indicates trouble for any
+		 * hmode > 6 ( --> MODE_BCLIENT).
+		 */
+		if (temp_cp.hmode > MODE_BCLIENT) {
+			req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
+			return;
+		}
+		
+		/* Any more checks on the values? Unchecked at this
+		 * point:
+		 *   - version
+		 *   - ttl
+		 *   - keyid
+		 *
+		 *   - minpoll/maxpoll, but they are treated properly
+		 *     for all cases internally. Checking not necessary.
+		 */
+		
+		/* finally create the peer */
 		if (peer_config(&peeraddr, NULL, NULL,
 		    temp_cp.hmode, temp_cp.version, temp_cp.minpoll, 
 		    temp_cp.maxpoll, fl, temp_cp.ttl, temp_cp.keyid,
-		    NULL) == 0) {
+		    NULL) == 0)
+		{
 			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
 			return;
 		}

#### ChangeSet ####
2016-02-21 09:39:25+01:00, perlinger at ntp.org
  Bug 3010] remote configuration trustedkey/requestkey values are not properly validated
   - sidekick: Ignore keys that have an unsupported MAC algorithm but are otherwise well-formed

==== ChangeLog ====
2016-02-21 09:39:25+01:00, perlinger at ntp.org +2 -0
  Bug 3010] remote configuration trustedkey/requestkey values are not properly validated
   - sidekick: Ignore keys that have an unsupported MAC algorithm but are otherwise well-formed

--- 1.1794.7.1/ChangeLog	2016-02-19 16:42:25 -05:00
+++ 1.1794.7.2/ChangeLog	2016-02-21 03:39:25 -05:00
@@ -4,6 +4,8 @@ 
 * [Bug 2995] Fixes to compile on Windows
 * [Bug 3010] remote configuration trustedkey/requestkey values
   are not properly validated. perlinger at ntp.org
+  - sidekick: Ignore keys that have an unsupported MAC algorithm
+    but are otherwise well-formed
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

==== libntp/authreadkeys.c ====
2016-02-21 09:39:25+01:00, perlinger at ntp.org +48 -26
  [Bug 3010] remote configuration trustedkey/requestkey values are not properly validated
   - sidekick: Ignore keys that have an unsupported MAC algorithm but are otherwise well-formed

--- 1.25/libntp/authreadkeys.c	2016-01-18 06:54:42 -05:00
+++ 1.26/libntp/authreadkeys.c	2016-02-21 03:39:25 -05:00
@@ -101,13 +101,33 @@ log_maybe(
 	...)
 {
 	va_list ap;
-	if (++(*pnerr) <= nerr_loglimit) {
+	if ((NULL == pnerr) || (++(*pnerr) <= nerr_loglimit)) {
 		va_start(ap, fmt);
 		mvsyslog(LOG_ERR, fmt, ap);
 		va_end(ap);
 	}
 }
 
+static void
+free_keydata(
+	KeyDataT *node
+	)
+{
+	KeyAccT *kap;
+	
+	if (node) {
+		while (node->keyacclist) {
+			kap = node->keyacclist;
+			node->keyacclist = kap->next;
+			free(kap);
+		}
+
+		/* purge secrets from memory before free()ing it */
+		memset(node, 0, sizeof(*node) + node->seclen);
+		free(node);
+	}
+}
+
 /*
  * authreadkeys - (re)read keys from a file.
  */
@@ -156,7 +176,7 @@ authreadkeys(
 		 * First is key number.  See if it is okay.
 		 */
 		keyno = atoi(token);
-		if (keyno == 0) {
+		if (keyno < 1) {
 			log_maybe(&nerr,
 				  "authreadkeys: cannot change key %s",
 				  token);
@@ -180,6 +200,14 @@ authreadkeys(
 				  keyno);
 			continue;
 		}
+
+		/* We want to silently ignore keys where we do not
+		 * support the requested digest type. OTOH, we want to
+		 * make sure the file is well-formed.  That means we
+		 * have to process the line completely and have to
+		 * finally throw away the result... This is a bit more
+		 * work, but it also results in better error detection.
+		 */ 
 #ifdef OPENSSL
 		/*
 		 * The key type is the NID used by the message digest 
@@ -189,30 +217,28 @@ authreadkeys(
 		 */
 		keytype = keytype_from_text(token, NULL);
 		if (keytype == 0) {
-			log_maybe(&nerr,
+			log_maybe(NULL,
 				  "authreadkeys: invalid type for key %d",
 				  keyno);
-			continue;
-		}
-		if (EVP_get_digestbynid(keytype) == NULL) {
-			log_maybe(&nerr,
+		} else if (EVP_get_digestbynid(keytype) == NULL) {
+			log_maybe(NULL,
 				  "authreadkeys: no algorithm for key %d",
 				  keyno);
-			continue;
+			keytype = 0;
 		}
 #else	/* !OPENSSL follows */
-
 		/*
 		 * The key type is unused, but is required to be 'M' or
 		 * 'm' for compatibility.
 		 */
 		if (!(*token == 'M' || *token == 'm')) {
-			log_maybe(&nerr,
+			log_maybe(NULL,
 				  "authreadkeys: invalid type for key %d",
 				  keyno);
-			continue;
+			keytype = 0;
+		} else {
+			keytype = KEY_TYPE_MD5;
 		}
-		keytype = KEY_TYPE_MD5;
 #endif	/* !OPENSSL */
 
 		/*
@@ -303,6 +329,13 @@ DPRINTF(0, ("authreadkeys: access list: 
 			}
 		}
 
+		/* check if this has to be weeded out... */
+		if (0 == keytype) {
+			free_keydata(next);
+			next = NULL;
+			continue;
+		}
+		
 		INSIST(NULL != next);
 		next->next = list;
 		list = next;
@@ -328,9 +361,8 @@ DPRINTF(0, ("authreadkeys: access list: 
 		list = next->next;
 		MD5auth_setkey(next->keyid, next->keytype,
 			       next->secbuf, next->seclen, next->keyacclist);
-		/* purge secrets from memory before free()ing it */
-		memset(next, 0, sizeof(*next) + next->seclen);
-		free(next);
+		next->keyacclist = NULL; /* consumed by MD5auth_setkey */
+		free_keydata(next);
 	}
 	return (1);
 
@@ -338,17 +370,7 @@ DPRINTF(0, ("authreadkeys: access list: 
 	/* Mop up temporary storage before bailing out. */
 	while (NULL != (next = list)) {
 		list = next->next;
-
-		while (next->keyacclist) {
-			KeyAccT *kap = next->keyacclist;
-
-			next->keyacclist = kap->next;
-			free(kap);
-		}
-
-		/* purge secrets from memory before free()ing it */
-		memset(next, 0, sizeof(*next) + next->seclen);
-		free(next);
+		free_keydata(next);
 	}
 	return (0);
 }

#### ChangeSet ####
2016-02-19 22:42:25+01:00, perlinger at ntp.org
  [Bug 3010] remote configuration trustedkey/requestkey values are not properly validated

==== ChangeLog ====
2016-02-19 22:42:25+01:00, perlinger at ntp.org +2 -0
  [Bug 3010] remote configuration trustedkey/requestkey values are not properly validated

--- 1.1794.1.2/ChangeLog	2016-01-24 05:14:42 -05:00
+++ 1.1794.7.1/ChangeLog	2016-02-19 16:42:25 -05:00
@@ -2,6 +2,8 @@ 
 
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
+* [Bug 3010] remote configuration trustedkey/requestkey values
+  are not properly validated. perlinger at ntp.org
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

==== ntpd/ntp_request.c ====
2016-02-19 22:42:25+01:00, perlinger at ntp.org +41 -25
  [Bug 3010] remote configuration trustedkey/requestkey values are not properly validated
   - make sure the new keyids are valid static key IDs and present in the key table

--- 1.117/ntpd/ntp_request.c	2016-01-14 05:24:57 -05:00
+++ 1.117.1.1/ntpd/ntp_request.c	2016-02-19 16:42:25 -05:00
@@ -2297,34 +2297,62 @@ do_setclr_trap(
 	return;
 }
 
-
-
 /*
- * set_request_keyid - set the keyid used to authenticate requests
+ * Validate a request packet for a new request or control key:
+ *  - only one item allowed
+ *  - key must be valid (that is, known, and not in the autokey range)
  */
 static void
-set_request_keyid(
-	sockaddr_u *srcadr,
-	endpt *inter,
+set_keyid_checked(
+	keyid_t        *into,
+	const char     *what,
+	sockaddr_u     *srcadr,
+	endpt          *inter,
 	struct req_pkt *inpkt
 	)
 {
 	keyid_t *pkeyid;
-
-	/*
-	 * Restrict ourselves to one item only.
-	 */
+	keyid_t  tmpkey;
+
+	/* restrict ourselves to one item only */
 	if (INFO_NITEMS(inpkt->err_nitems) > 1) {
-		msyslog(LOG_ERR, "set_request_keyid: err_nitems > 1");
+		msyslog(LOG_ERR, "set_keyid_checked[%s]: err_nitems > 1",
+			what);
 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
 		return;
 	}
 
+	/* plug the new key from the packet */
 	pkeyid = (keyid_t *)&inpkt->u;
-	info_auth_keyid = ntohl(*pkeyid);
+	tmpkey = ntohl(*pkeyid);
+
+	/* validate the new key id, claim data error on failure */
+	if (tmpkey < 1 || tmpkey > NTP_MAXKEY || !auth_havekey(tmpkey)) {
+		msyslog(LOG_ERR, "set_keyid_checked[%s]: invalid key id: %ld",
+			what, (long)tmpkey);
+		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
+		return;
+	}
+
+	/* if we arrive here, the key is good -- use it */
+	*into = tmpkey;
 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
 }
 
+/*
+ * set_request_keyid - set the keyid used to authenticate requests
+ */
+static void
+set_request_keyid(
+	sockaddr_u *srcadr,
+	endpt *inter,
+	struct req_pkt *inpkt
+	)
+{
+	set_keyid_checked(&info_auth_keyid, "request",
+			  srcadr, inter, inpkt);
+}
+
 
 
 /*
@@ -2337,20 +2365,8 @@ set_control_keyid(
 	struct req_pkt *inpkt
 	)
 {
-	keyid_t *pkeyid;
-
-	/*
-	 * Restrict ourselves to one item only.
-	 */
-	if (INFO_NITEMS(inpkt->err_nitems) > 1) {
-		msyslog(LOG_ERR, "set_control_keyid: err_nitems > 1");
-		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
-		return;
-	}
-
-	pkeyid = (keyid_t *)&inpkt->u;
-	ctl_auth_keyid = ntohl(*pkeyid);
-	req_ack(srcadr, inter, inpkt, INFO_OKAY);
+	set_keyid_checked(&ctl_auth_keyid, "control",
+			  srcadr, inter, inpkt);
 }
 
 

#### ChangeSet ####
2016-02-19 19:47:31+01:00, perlinger at ntp.org
  [Bug 3013] Fix for ssl_init.c SHA1 test

==== ChangeLog ====
2016-02-19 19:47:31+01:00, perlinger at ntp.org +2 -0
  [Bug 3013] Fix for ssl_init.c SHA1 test

--- 1.1794.1.2/ChangeLog	2016-01-24 05:14:42 -05:00
+++ 1.1794.6.1/ChangeLog	2016-02-19 13:47:31 -05:00
@@ -2,6 +2,8 @@ 
 
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
+* [Bug 3013] Fix for ssl_init.c SHA1 test. perlinger at ntp.org
+  - Patch provided by Ch. Weisgerber
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

==== tests/libntp/ssl_init.c ====
2016-02-19 19:47:31+01:00, perlinger at ntp.org +2 -2
  [Bug 3013] Fix for ssl_init.c SHA1 test
   - Require SHA1 explicitely, to avoid confusion with (deprecated) SHA0.
     Patch provided by Ch. Weisgerber

--- 1.8/tests/libntp/ssl_init.c	2015-07-25 10:54:18 -04:00
+++ 1.9/tests/libntp/ssl_init.c	2016-02-19 13:47:31 -05:00
@@ -43,7 +43,7 @@ test_SHA1KeyTypeWithDigestLength(void) {
 	size_t digestLength;
 	size_t expected = TEST_SHA1_DIGEST_LENGTH;
 
-	TEST_ASSERT_EQUAL(NID_sha, keytype_from_text("SHA", &digestLength));
+	TEST_ASSERT_EQUAL(NID_sha1, keytype_from_text("SHA1", &digestLength));
 	TEST_ASSERT_EQUAL(expected, digestLength);
 	/* OPENSSL */
 #else 
@@ -62,7 +62,7 @@ test_SHA1KeyName(void) {
 void
 test_SHA1KeyName(void) {
 #ifdef OPENSSL
-	TEST_ASSERT_EQUAL_STRING("SHA", keytype_name(NID_sha));
+	TEST_ASSERT_EQUAL_STRING("SHA1", keytype_name(NID_sha1));
 #else
 	TEST_IGNORE_MESSAGE("Skipping because OPENSSL isn't defined");
 #endif	/* OPENSSL */

#### ChangeSet ####
2016-02-17 18:36:10+01:00, perlinger at ntp.org
  [Bug 3015] ntpq: config-from-file: "request contains an unprintable character"

==== ChangeLog ====
2016-02-17 18:36:10+01:00, perlinger at ntp.org +3 -0
  [Bug 3015] ntpq: config-from-file: "request contains an unprintable character"

--- 1.1794.1.2/ChangeLog	2016-01-24 05:14:42 -05:00
+++ 1.1794.5.1/ChangeLog	2016-02-17 12:36:10 -05:00
@@ -2,6 +2,9 @@ 
 
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
+* [Bug 3015] ntpq: config-from-file: "request contains an unprintable character"
+  - A change related [Bug 2853] forbids trailing white space in
+    remote config command. perlinger at ntp.org
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

==== ntpq/ntpq-subs.c ====
2016-02-17 18:36:10+01:00, perlinger at ntp.org +35 -16
  [Bug 3015] ntpq: config-from-file: "request contains an unprintable character"
   - remove trailing whitespace in remote config command
   - remove comments, too.

--- 1.116/ntpq/ntpq-subs.c	2016-01-14 06:44:32 -05:00
+++ 1.117/ntpq/ntpq-subs.c	2016-02-17 12:36:10 -05:00
@@ -2244,6 +2244,10 @@ config (
  *    Longer lines will lead to unpredictable results.
  * 3. Since this function is sending a line at a time, we can't update
  *    the control key through the configuration file (YUCK!!)
+ *
+ * Pearly: There are a few places where 'size_t' is cast to 'int' based
+ * on the assumption that 'int' can hold the size of the involved
+ * buffers without overflow.
  */
 static void 
 config_from_file (
@@ -2254,6 +2258,7 @@ config_from_file (
 	u_short rstatus;
 	size_t rsize;
 	const char *rdata;
+	char * cp;
 	int res;
 	FILE *config_fd;
 	char config_cmd[MAXLINE];
@@ -2278,33 +2283,47 @@ config_from_file (
 	printf("Sending configuration file, one line at a time.\n");
 	i = 0;
 	while (fgets(config_cmd, MAXLINE, config_fd) != NULL) {
-		config_len = strlen(config_cmd);
-		/* ensure even the last line has newline, if possible */
-		if (config_len > 0 && 
-		    config_len + 2 < sizeof(config_cmd) &&
-		    '\n' != config_cmd[config_len - 1])
-			config_cmd[config_len++] = '\n';
+		/* Eliminate comments first. */
+		cp = strchr(config_cmd, '#');
+		config_len = (NULL != cp)
+		    ? (size_t)(cp - config_cmd)
+		    : strlen(config_cmd);
+		
+		/* [Bug 3015] make sure there's no trailing whitespace;
+		 * the fix for [Bug 2853] on the server side forbids
+		 * those. And don't transmit empty lines, as this would
+		 * just be waste.
+		 */
+		while (config_len != 0 &&
+		       (u_char)config_cmd[config_len-1] <= ' ')
+			--config_len;
+		config_cmd[config_len] = '\0';
+
 		++i;
+		if (0 == config_len)
+			continue;
+
 		retry_limit = 2;
 		do 
 			res = doquery(CTL_OP_CONFIGURE, 0, 1,
-				      strlen(config_cmd), config_cmd,
+				      config_len, config_cmd,
 				      &rstatus, &rsize, &rdata);
 		while (res != 0 && retry_limit--);
 		if (res != 0) {
-			printf("Line No: %d query failed: %s", i,
-			       config_cmd);
-			printf("Subsequent lines not sent.\n");
+			printf("Line No: %d query failed: %.*s\n"
+			       "Subsequent lines not sent.\n",
+			       i, (int)config_len, config_cmd);
 			fclose(config_fd);
 			return;
 		}
 
-		if (rsize > 0 && '\n' == rdata[rsize - 1])
-			rsize--;
-		if (rsize > 0 && '\r' == rdata[rsize - 1])
-			rsize--;
-		printf("Line No: %d %.*s: %s", i, (int)rsize, rdata, /* cast is wobbly */
-		       config_cmd);
+		/* Right-strip the result code string, then output the
+		 * last line executed, with result code. */
+		while (rsize != 0 && (u_char)rdata[rsize - 1] <= ' ')
+			--rsize;
+		printf("Line No: %d %.*s: %.*s\n", i,
+		       (int)rsize, rdata,
+		       (int)config_len, config_cmd);
 	}
 	printf("Done sending file\n");
 	fclose(config_fd);

#### ChangeSet ####
2016-02-17 09:30:05+01:00, jnperlin at hydra.localnet
  [Bug 3008] ctl_getitem() return value not always checked

==== ChangeLog ====
2016-02-17 09:30:05+01:00, jnperlin at hydra.localnet +3 -0
  [Bug 3008] ctl_getitem() return value not always checked

--- 1.1801/ChangeLog	2016-02-06 02:43:23 -05:00
+++ 1.1802/ChangeLog	2016-02-17 03:30:05 -05:00
@@ -10,6 +10,9 @@ 
     with some modifications & unit tests
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
+* [Bug 3008] ctl_getitem() return value not always checked.
+  - initial work by HSten
+  - cleanup of ctl_getitem by perlinger at ntp.org
 * Document ntp.key's optional IP list in authenetic.html.  Harlan Stenn.
 * Update html/xleave.html documentation.  Harlan Stenn.
 * Update ntp.conf documentation.  Harlan Stenn.

==== ntpd/ntp_control.c ====
2016-02-17 09:30:05+01:00, jnperlin at hydra.localnet +101 -58
  [Bug 3008] ctl_getitem() return value not always checked
   - also some cleanup of ctl_getitem

--- 1.206/ntpd/ntp_control.c	2016-01-13 00:55:43 -05:00
+++ 1.206.1.1/ntpd/ntp_control.c	2016-02-17 03:30:05 -05:00
@@ -3081,83 +3081,117 @@ ctl_getitem(
 	char **data
 	)
 {
+	/* [Bug 3008] First check the packet data sanity, then search
+	 * the key. This improves the consistency of result values: If
+	 * the result is NULL once, it will never be EOV again for this
+	 * packet; If it's EOV, it will never be NULL again until the
+	 * variable is found and processed in a given 'var_list'. (That
+	 * is, a result is returned that is neither NULL nor EOV).
+	 */ 
 	static const struct ctl_var eol = { 0, EOV, NULL };
 	static char buf[128];
 	static u_long quiet_until;
 	const struct ctl_var *v;
-	const char *pch;
 	char *cp;
 	char *tp;
 
 	/*
-	 * Delete leading commas and white space
+	 * Part One: Validate the packet state
 	 */
+
+	/* Delete leading commas and white space */
 	while (reqpt < reqend && (*reqpt == ',' ||
 				  isspace((unsigned char)*reqpt)))
 		reqpt++;
 	if (reqpt >= reqend)
 		return NULL;
 
+	/* Scan the string in the packet until we hit comma or
+	 * EoB. Register position of first '=' on the fly. */
+	for (tp = NULL, cp = reqpt; cp != reqend; ++cp) {
+		if (*cp == '=' && tp == NULL)
+			tp = cp;
+		if (*cp == ',')
+			break;
+	}
+
+	/* Process payload, if any. */
+	*data = NULL;
+	if (NULL != tp) {
+		/* eventually strip white space from argument. */
+		const char *plhead = tp + 1; /* skip the '=' */
+		const char *pltail = cp;
+		size_t      plsize;
+
+		while (plhead != pltail && isspace((u_char)plhead[0]))
+			++plhead;
+		while (plhead != pltail && isspace((u_char)pltail[-1]))
+			--pltail;
+		
+		/* check payload size, terminate packet on overflow */
+		plsize = (size_t)(pltail - plhead);
+		if (plsize >= sizeof(buf))
+			goto badpacket;
+
+		/* copy data, NUL terminate, and set result data ptr */
+		memcpy(buf, plhead, plsize);
+		buf[plsize] = '\0';
+		*data = buf;
+	} else {
+		/* no payload, current end --> current name termination */
+		tp = cp;
+	}
+
+	/* Part Two
+	 *
+	 * Now we're sure that the packet data itself is sane. Scan the
+	 * list now. Make sure a NULL list is properly treated by
+	 * returning a synthetic End-Of-Values record. We must not
+	 * return NULL pointers after this point, or the behaviour would
+	 * become inconsistent if called several times with different
+	 * variable lists after an EoV was returned.  (Such a behavior
+	 * actually caused Bug 3008.)
+	 */
+	
 	if (NULL == var_list)
 		return &eol;
 
-	/*
-	 * Look for a first character match on the tag.  If we find
-	 * one, see if it is a full match.
-	 */
-	cp = reqpt;
-	for (v = var_list; !(EOV & v->flags); v++) {
-		if (!(PADDING & v->flags) && *cp == *(v->text)) {
-			pch = v->text;
-			while ('\0' != *pch && '=' != *pch && cp < reqend
-			       && *cp == *pch) {
-				cp++;
-				pch++;
-			}
-			if ('\0' == *pch || '=' == *pch) {
-				while (cp < reqend && isspace((u_char)*cp))
-					cp++;
-				if (cp == reqend || ',' == *cp) {
-					buf[0] = '\0';
-					*data = buf;
-					if (cp < reqend)
-						cp++;
-					reqpt = cp;
-					return v;
-				}
-				if ('=' == *cp) {
-					cp++;
-					tp = buf;
-					while (cp < reqend && isspace((u_char)*cp))
-						cp++;
-					while (cp < reqend && *cp != ',') {
-						*tp++ = *cp++;
-						if ((size_t)(tp - buf) >= sizeof(buf)) {
-							ctl_error(CERR_BADFMT);
-							numctlbadpkts++;
-							NLOG(NLOG_SYSEVENT)
-								if (quiet_until <= current_time) {
-									quiet_until = current_time + 300;
-									msyslog(LOG_WARNING,
-"Possible 'ntpdx' exploit from %s#%u (possibly spoofed)", stoa(rmt_addr), SRCPORT(rmt_addr));
-								}
-							return NULL;
-						}
-					}
-					if (cp < reqend)
-						cp++;
-					*tp-- = '\0';
-					while (tp >= buf && isspace((u_char)*tp))
-						*tp-- = '\0';
-					reqpt = cp;
-					*data = buf;
-					return v;
-				}
-			}
-			cp = reqpt;
+	for (v = var_list; !(EOV & v->flags); ++v)
+		if (!(PADDING & v->flags)) {
+			/* check if the var name matches the buffer */
+			const char *sp1 = reqpt;
+			const char *sp2 = v->text;
+			
+			while ((sp1 != tp) && *sp2 && (*sp1 == *sp2)) {
+				++sp1;
+				++sp2;
+			}
+			if (sp1 == tp && !*sp2)
+				break;
 		}
-	}
+
+	/* See if we have found a valid entry or not. If found, advance
+	 * the request pointer for the next round; if not, clear the
+	 * data pointer so we have no dangling garbage here.
+	 */
+	if (EOV & v->flags)
+		*data = NULL;
+	else
+		reqpt = cp + (cp != reqend);
 	return v;
+
+  badpacket:
+	/*TODO? somehow indicate this packet was bad, apart from syslog? */
+	numctlbadpkts++;
+	NLOG(NLOG_SYSEVENT)
+	    if (quiet_until <= current_time) {
+		    quiet_until = current_time + 300;
+		    msyslog(LOG_WARNING,
+			    "Possible 'ntpdx' exploit from %s#%u (possibly spoofed)",
+			    stoa(rmt_addr), SRCPORT(rmt_addr));
+	    }
+	reqpt = reqend; /* never again for this packet! */
+	return NULL;
 }
 
 
@@ -3334,7 +3368,11 @@ read_sysvars(void)
 			gotvar = 1;
 		} else {
 			v = ctl_getitem(ext_sys_var, &valuep);
-			INSIST(v != NULL);
+			if (NULL == v) {
+				ctl_error(CERR_BADVALUE);
+				free(wants);
+				return;
+			}
 			if (EOV & v->flags) {
 				ctl_error(CERR_UNKNOWNVAR);
 				free(wants);
@@ -4575,7 +4613,12 @@ read_clockstatus(
 			gotvar = TRUE;
 		} else {
 			v = ctl_getitem(kv, &valuep);
-			INSIST(NULL != v);
+			if (NULL == v) {
+				ctl_error(CERR_BADVALUE);
+				free(wants);
+				free_varlist(cs.kv_list);
+				return;
+			}
 			if (EOV & v->flags) {
 				ctl_error(CERR_UNKNOWNVAR);
 				free(wants);

#### ChangeSet ####
2016-02-14 10:15:57+00:00, stenn at psp-deb1.ntp.org
  Fix typo in html/monopt.html.  Harlan Stenn.

==== ChangeLog ====
2016-02-14 10:14:07+00:00, stenn at psp-deb1.ntp.org +1 -0
  Fix typo in html/monopt.html.  Harlan Stenn.

--- 1.1794.3.2/ChangeLog	2016-02-13 04:15:40 -05:00
+++ 1.1794.3.3/ChangeLog	2016-02-14 05:14:07 -05:00
@@ -4,6 +4,7 @@ 
 * [Bug 2995] Fixes to compile on Windows
 * Document ntp.key's optional IP list in authenetic.html.  Harlan Stenn.
 * Fix some Credit: attributions in the NEWS file.  Harlan Stenn.
+* Fix typo in html/monopt.html.  Harlan Stenn.
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

==== html/monopt.html ====
2016-02-14 10:14:12+00:00, stenn at psp-deb1.ntp.org +2 -2
  Fix typo in html/monopt.html.  Harlan Stenn.

--- 1.38/html/monopt.html	2014-07-18 04:36:26 -04:00
+++ 1.39/html/monopt.html	2016-02-14 05:14:12 -05:00
@@ -11,7 +11,7 @@ 
 <img src="pic/pogo8.gif" alt="gif" align="left"><a href="http://www.eecis.udel.edu/~mills/pictures.html"></a> from <i>Pogo</i>, Walt Kelly</a>
 <p>Pig was hired to watch the logs.</p>
 <p>Last update:
-  <!-- #BeginDate format:En2m -->31-Jan-2014  06:54<!-- #EndDate -->
+  <!-- #BeginDate format:En2m -->14-Feb-2016  09:38<!-- #EndDate -->
     UTC</p>
 <br clear="left">
 <h4>Related Links</h4>
@@ -295,7 +295,7 @@ 
   <dd>The status field is encoded in hex format as described in Appendix B of
     the NTP specification RFC 1305.</dd>
   <dt><tt>protostats</tt></dt>
-  <dd>Record significant peer, system and [rptpcp; events. Each significant event
+  <dd>Record significant peer, system and protocol events. Each significant event
     appends one line to the <tt>protostats</tt> file set:</dd>
   <dd><tt>49213 525.624 128.4.1.1 963a 8a <i>message</i></tt></dd>
   <dd>

#### ChangeSet ####
2016-02-13 09:15:45+00:00, stenn at psp-deb1.ntp.org
  Fix some Credit: attributions in the NEWS file.  Harlan Stenn.

==== ChangeLog ====
2016-02-13 09:15:40+00:00, stenn at psp-deb1.ntp.org +1 -0
  Fix some Credit: attributions in the NEWS file.  Harlan Stenn.

--- 1.1794.3.1/ChangeLog	2016-02-05 04:20:02 -05:00
+++ 1.1794.3.2/ChangeLog	2016-02-13 04:15:40 -05:00
@@ -3,6 +3,7 @@ 
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
 * Document ntp.key's optional IP list in authenetic.html.  Harlan Stenn.
+* Fix some Credit: attributions in the NEWS file.  Harlan Stenn.
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

==== NEWS ====
2016-02-13 09:15:40+00:00, stenn at psp-deb1.ntp.org +3 -2
  Fix some Credit: attributions in the NEWS file.  Harlan Stenn.

--- 1.160/NEWS	2016-01-19 19:34:07 -05:00
+++ 1.161/NEWS	2016-02-13 04:15:40 -05:00
@@ -53,7 +53,8 @@ following X low- and Y medium-severity v
 	Upgrade to 4.2.8p6, or later, from the NTP Project Download Page
 	    or the NTP Public Services Project Download Page.
 	Monitor your 'ntpd= instances.
-   Credit: This weakness was discovered by Jonathan Gardner of Cisco ASIG.
+   Credit: This weakness was discovered by Matthey Van Gundy and
+	Jonathan Gardner of Cisco ASIG.
 
 * Stack exhaustion in recursive traversal of restriction list
    Date Resolved: Stable (4.2.8p6) 19 Jan 2016
@@ -689,7 +690,7 @@ Credit: This weakness was discovered by 
 		Apply the patch to the bottom of the "authentic" check
 			block around line 1136 of ntp_proto.c. 
 	Monitor your ntpd instances. 
-  Credit: This weakness was discovered by Stephen Gray <stepgray at cisco.com>. 
+  Credit: This weakness was discovered by Matthew Van Gundy of Cisco ASIG. 
 
 Backward-Incompatible changes:
 * [Bug 2817] Default on Linux is now "rlimit memlock -1".

#### ChangeSet ####
2016-02-10 20:11:21+01:00, perlinger at ntp.org
  [Bug 3011] Duplicate IPs on unconfig directives will cause an assertion botch

==== ChangeLog ====
2016-02-10 20:11:21+01:00, perlinger at ntp.org +2 -0
  [Bug 3011] Duplicate IPs on unconfig directives will cause an assertion botch

--- 1.1794.1.2/ChangeLog	2016-01-24 05:14:42 -05:00
+++ 1.1794.4.1/ChangeLog	2016-02-10 14:11:21 -05:00
@@ -2,6 +2,8 @@ 
 
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
+* [Bug 3011] Duplicate IPs on unconfig directives will cause an assertion botch
+  - graciously accept the same IP multiple times. perlinger at ntp.org
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

==== ntpd/ntp_request.c ====
2016-02-10 20:11:21+01:00, perlinger at ntp.org +48 -78
  [Bug 3011] Duplicate IPs on unconfig directives will cause an assertion botch
   - reworked 'do_unconf()' to survive the effect of having peers named multiple times

--- 1.117/ntpd/ntp_request.c	2016-01-14 05:24:57 -05:00
+++ 1.118/ntpd/ntp_request.c	2016-02-10 14:11:21 -05:00
@@ -1373,103 +1373,73 @@ do_unconf(
 	struct conf_unpeer	temp_cp;
 	struct peer *		p;
 	sockaddr_u		peeraddr;
-	int			bad;
-	int			found;
+	int			loops;
 
 	/*
 	 * This is a bit unstructured, but I like to be careful.
 	 * We check to see that every peer exists and is actually
 	 * configured.  If so, we remove them.  If not, we return
 	 * an error.
+	 *
+	 * [Bug 3011] Even if we checked all peers given in the request
+	 * in a dry run, there's still a chance that the caller played
+	 * unfair and gave the same peer multiple times. So we still
+	 * have to be prepared for nasty surprises in the second run ;)
 	 */
-	items = INFO_NITEMS(inpkt->err_nitems);
+
+	/* basic consistency checks */
 	item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize);
-	datap = inpkt->u.data;
 	if (item_sz > sizeof(temp_cp)) {
 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
 		return;
 	}
 
-	bad = FALSE;
-	while (items-- > 0 && !bad) {
-		ZERO(temp_cp);
-		memcpy(&temp_cp, datap, item_sz);
-		ZERO_SOCK(&peeraddr);
-		if (client_v6_capable && temp_cp.v6_flag) {
-			AF(&peeraddr) = AF_INET6;
-			SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6;
-		} else {
-			AF(&peeraddr) = AF_INET;
-			NSRCADR(&peeraddr) = temp_cp.peeraddr;
-		}
-		SET_PORT(&peeraddr, NTP_PORT);
-#ifdef ISC_PLATFORM_HAVESALEN
-		peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
-#endif
-		found = FALSE;
-		p = NULL;
-
-		DPRINTF(1, ("searching for %s\n", stoa(&peeraddr)));
-
-		while (!found) {
-			p = findexistingpeer(&peeraddr, NULL, p, -1, 0);
-			if (NULL == p)
-				break;
-			if (FLAG_CONFIG & p->flags)
-				found = TRUE;
-		}
-		if (!found)
-			bad = TRUE;
-
-		datap += item_sz;
-	}
-
-	if (bad) {
-		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
-		return;
-	}
-
-	/*
-	 * Now do it in earnest.
-	 */
-
-	items = INFO_NITEMS(inpkt->err_nitems);
-	datap = inpkt->u.data;
-
-	while (items-- > 0) {
-		ZERO(temp_cp);
-		memcpy(&temp_cp, datap, item_sz);
-		ZERO(peeraddr);
-		if (client_v6_capable && temp_cp.v6_flag) {
-			AF(&peeraddr) = AF_INET6;
-			SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6;
-		} else {
-			AF(&peeraddr) = AF_INET;
-			NSRCADR(&peeraddr) = temp_cp.peeraddr;
-		}
-		SET_PORT(&peeraddr, NTP_PORT);
-#ifdef ISC_PLATFORM_HAVESALEN
-		peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
-#endif
-		found = FALSE;
-		p = NULL;
-
-		while (!found) {
-			p = findexistingpeer(&peeraddr, NULL, p, -1, 0);
-			if (NULL == p)
-				break;
-			if (FLAG_CONFIG & p->flags)
-				found = TRUE;
-		}
-		INSIST(found);
-		INSIST(NULL != p);
-
-		peer_clear(p, "GONE");
-		unpeer(p);
-
-		datap += item_sz;
+	/* now do two runs: first a dry run, then a busy one */
+	for (loops = 0; loops != 2; ++loops) {
+		items = INFO_NITEMS(inpkt->err_nitems);
+		datap = inpkt->u.data;
+		while (items-- > 0) {
+			/* copy from request to local */
+			ZERO(temp_cp);
+			memcpy(&temp_cp, datap, item_sz);
+			/* get address structure */
+			ZERO_SOCK(&peeraddr);
+			if (client_v6_capable && temp_cp.v6_flag) {
+				AF(&peeraddr) = AF_INET6;
+				SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6;
+			} else {
+				AF(&peeraddr) = AF_INET;
+				NSRCADR(&peeraddr) = temp_cp.peeraddr;
+			}
+			SET_PORT(&peeraddr, NTP_PORT);
+#ifdef ISC_PLATFORM_HAVESALEN
+			peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
+#endif
+			DPRINTF(1, ("searching for %s\n",
+				    stoa(&peeraddr)));
+
+			/* search for matching configred(!) peer */
+			p = NULL;
+			do {
+				p = findexistingpeer(
+					&peeraddr, NULL, p, -1, 0);
+			} while (p && !(FLAG_CONFIG & p->flags));
+			
+			if (!loops && !p) {
+				/* Item not found in dry run -- bail! */
+				req_ack(srcadr, inter, inpkt,
+					INFO_ERR_NODATA);
+				return;
+			} else if (loops && p) {
+				/* Item found in busy run -- remove! */
+				peer_clear(p, "GONE");
+				unpeer(p);
+			}
+			datap += item_sz;
+		}
 	}
 
+	/* report success */
 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
 }
 

#### ChangeSet ####
2016-02-09 00:46:57+00:00, mayer at psp-deb1.ntp.org
  Allow Active and Passive peer for crypto-NAK and added reporting

==== ntpd/ntp_proto.c ====
2016-02-09 00:46:39+00:00, mayer at psp-deb1.ntp.org +6 -2
  Allow Active and Passive peer for crypto-NAK and added reporting

--- 1.373.1.1/ntpd/ntp_proto.c	2016-02-04 23:19:12 -05:00
+++ 1.373.1.2/ntpd/ntp_proto.c	2016-02-08 19:46:39 -05:00
@@ -292,7 +292,10 @@ valid_NAK(
 	 * Only server responses can contain NAK's
 	 */
 
-	if (hismode != MODE_SERVER) {
+	if (hismode != MODE_SERVER &&
+	    hismode != MODE_ACTIVE &&
+	    hismode != MODE_PASSIVE
+	    ) {
 		return (INVALIDNAK);
 	}
 
@@ -838,8 +841,9 @@ receive(
 	 * Drop any invalid crypto-NAKs
 	 */
 	if (crypto_nak_test == INVALIDNAK) {
+		report_event(PEVNT_AUTH, peer, "Invalid_NAK");
 		peer->badNAK++;
-		msyslog(LOG_ERR, "crypto-NAK error at %ld %s<-%s", 
+		msyslog(LOG_ERR, "Invalid-NAK error at %ld %s<-%s", 
 			current_time, stoa(dstadr_sin), stoa(&rbufp->recv_srcadr));
 		return;
 	}

#### ChangeSet ####
2016-02-07 07:35:03+00:00, stenn at psp-deb1.ntp.org
  Update ntp.conf documentation.  Harlan Stenn.

==== ChangeLog ====
2016-02-06 07:43:23+00:00, stenn at psp-deb1.ntp.org +1 -0
  Update ntp.conf documentation.  Harlan Stenn.

--- 1.1800/ChangeLog	2016-02-06 02:39:39 -05:00
+++ 1.1801/ChangeLog	2016-02-06 02:43:23 -05:00
@@ -12,6 +12,7 @@ 
 * [Bug 2995] Fixes to compile on Windows
 * Document ntp.key's optional IP list in authenetic.html.  Harlan Stenn.
 * Update html/xleave.html documentation.  Harlan Stenn.
+* Update ntp.conf documentation.  Harlan Stenn.
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

==== ntpd/invoke-ntp.conf.texi ====
2016-02-06 07:43:26+00:00, stenn at psp-deb1.ntp.org +37 -10
  Update ntp.conf documentation.  Harlan Stenn.

--- 1.196/ntpd/invoke-ntp.conf.texi	2016-01-20 04:20:06 -05:00
+++ 1.197/ntpd/invoke-ntp.conf.texi	2016-02-06 02:43:26 -05:00
@@ -6,7 +6,7 @@ 
 #
 # EDIT THIS FILE WITH CAUTION  (invoke-ntp.conf.texi)
 #
-# It has been AutoGen-ed  January 20, 2016 at 04:17:59 AM by AutoGen 5.18.5
+# It has been AutoGen-ed  February  6, 2016 at 07:23:05 AM by AutoGen 5.18.5
 # From the definitions    ntp.conf.def
 # and the template file   agtexi-file.tpl
 @end ignore
@@ -249,7 +249,9 @@ can be changed with the calldelay comman
 instead of the usual one.
 The packet spacing is normally 2 s;
 however, the spacing between the first and second packets
-can be changed with the calldelay command to allow
+can be changed with the
+ at code{calldelay}
+command to allow
 additional time for a modem or ISDN call to complete.
 This is designed to improve timekeeping quality
 with the
@@ -260,7 +262,9 @@ changed with the calldelay command to al
 instead of the usual one.
 The packet spacing is normally 2 s;
 however, the spacing between the first two packets can be
-changed with the calldelay command to allow
+changed with the
+ at code{calldelay}
+command to allow
 additional time for a modem or ISDN call to complete.
 This is designed to speed the initial synchronization
 acquisition with the
@@ -293,6 +297,10 @@ The server is discarded by the selection
 @item @code{noselect}
 Marks the server as unused, except for display purposes.
 The server is discarded by the selection algroithm.
+ at item @code{preempt}
+Says the association can be preempted.
+ at item @code{true}
+Marks the server as a truechimer.
 @item @code{prefer}
 Marks the server as preferred.
 All other things being equal,
@@ -323,6 +331,12 @@ default.
 packets.
 Versions 1-4 are the choices, with version 4 the
 default.
+ at item @code{xleave}
+Valid in
+ at code{peer}
+and
+ at code{broadcast}
+modes only, this flag enables interleave mode.
 @end table
 @subsubsection Auxiliary Commands
 @table @asis
@@ -1363,7 +1377,9 @@ included in the restrict list created by
 by a determined cracker.
 
 Clients can be denied service because they are explicitly
-included in the restrict list created by the restrict command
+included in the restrict list created by the
+ at code{restrict}
+command
 or implicitly as the result of cryptographic or rate limit
 violations.
 Cryptographic violations include certificate
@@ -1429,7 +1445,9 @@ The monitor subcommand specifies the pro
 and a kiss-o'-death packet returned if enabled.
 The default
 minimum average and minimum are 5 and 2, respectively.
-The monitor subcommand specifies the probability of discard
+The
+ at code{monitor}
+subcommand specifies the probability of discard
 for packets that overflow the rate-control window.
 @item @code{restrict} @code{address} @code{[@code{mask} @kbd{mask}]} @code{[@kbd{flag} @kbd{...}]}
 The
@@ -1485,7 +1503,9 @@ in the discard command.
 last one, the packet is dropped.
 @item @code{limited}
 Deny service if the packet spacing violates the lower limits specified
-in the discard command.
+in the
+ at code{discard}
+command.
 A history of clients is kept using the
 monitoring capability of
 @code{ntpd(1ntpdmdoc)}.
@@ -1613,8 +1633,11 @@ using the manycastclient command, which 
 as well and is highly recommended, especially for broadcast modes.
 
 A persistent manycast client association is configured
-using the manycastclient command, which is similar to the
-server command but with a multicast (IPv4 class
+using the
+ at code{manycastclient}
+command, which is similar to the
+ at code{server}
+command but with a multicast (IPv4 class
 @code{D}
 or IPv6 prefix
 @code{FF})
@@ -1684,7 +1707,9 @@ set at the minimum hops specified by the
 @code{maxpolll}
 value specified in this command.
 Initially, the TTL is
-set at the minimum hops specified by the ttl command.
+set at the minimum hops specified by the
+ at code{ttl}
+command.
 At each retransmission the TTL is increased until reaching
 the maximum hops specified by this command or a sufficient
 number client associations have been found.
@@ -2526,7 +2551,9 @@ This is the same operation as the -l com
 be used instead of the default system
 @code{syslog(3)}
 facility.
-This is the same operation as the -l command line option.
+This is the same operation as the
+ at code{-l}
+command line option.
 @item @code{setvar} @kbd{variable} @code{[@code{default}]}
 This command adds an additional system variable.
 These

==== ntpd/ntp.conf.5man ====
2016-02-06 07:43:26+00:00, stenn at psp-deb1.ntp.org +42 -12
  Update ntp.conf documentation.  Harlan Stenn.

--- 1.230/ntpd/ntp.conf.5man	2016-01-20 04:20:06 -05:00
+++ 1.231/ntpd/ntp.conf.5man	2016-02-06 02:43:26 -05:00
@@ -10,11 +10,11 @@ 
 .ds B-Font B
 .ds I-Font I
 .ds R-Font R
-.TH ntp.conf 5man "20 Jan 2016" "4.2.8p6" "File Formats"
+.TH ntp.conf 5man "06 Feb 2016" "4.2.8p6" "File Formats"
 .\"
-.\" EDIT THIS FILE WITH CAUTION (/tmp/.ag-gsaOxR/ag-XsaGwR)
+.\" EDIT THIS FILE WITH CAUTION (in-mem file)
 .\"
-.\" It has been AutoGen-ed January 20, 2016 at 04:17:45 AM by AutoGen 5.18.5
+.\" It has been AutoGen-ed February 6, 2016 at 07:23:07 AM by AutoGen 5.18.5
 .\" From the definitions ntp.conf.def
 .\" and the template file agman-cmd.tpl
 .SH NAME
@@ -289,7 +289,9 @@ can be changed with the calldelay comman
 instead of the usual one.
 The packet spacing is normally 2 s;
 however, the spacing between the first and second packets
-can be changed with the calldelay command to allow
+can be changed with the
+\f\*[B-Font]calldelay\f[]
+command to allow
 additional time for a modem or ISDN call to complete.
 This is designed to improve timekeeping quality
 with the
@@ -301,7 +303,9 @@ changed with the calldelay command to al
 instead of the usual one.
 The packet spacing is normally 2 s;
 however, the spacing between the first two packets can be
-changed with the calldelay command to allow
+changed with the
+\f\*[B-Font]calldelay\f[]
+command to allow
 additional time for a modem or ISDN call to complete.
 This is designed to speed the initial synchronization
 acquisition with the
@@ -339,6 +343,12 @@ The server is discarded by the selection
 Marks the server as unused, except for display purposes.
 The server is discarded by the selection algroithm.
 .TP 7
+.NOP \f\*[B-Font]preempt\f[]
+Says the association can be preempted.
+.TP 7
+.NOP \f\*[B-Font]true\f[]
+Marks the server as a truechimer.
+.TP 7
 .NOP \f\*[B-Font]prefer\f[]
 Marks the server as preferred.
 All other things being equal,
@@ -371,6 +381,13 @@ default.
 packets.
 Versions 1-4 are the choices, with version 4 the
 default.
+.TP 7
+.NOP \f\*[B-Font]xleave\f[]
+Valid in
+\f\*[B-Font]peer\f[]
+and
+\f\*[B-Font]broadcast\f[]
+modes only, this flag enables interleave mode.
 .PP
 .SS Auxiliary Commands
 .TP 7
@@ -1559,7 +1576,9 @@ included in the restrict list created by
 .ne 2
 
 Clients can be denied service because they are explicitly
-included in the restrict list created by the restrict command
+included in the restrict list created by the
+\f\*[B-Font]restrict\f[]
+command
 or implicitly as the result of cryptographic or rate limit
 violations.
 Cryptographic violations include certificate
@@ -1627,7 +1646,9 @@ The monitor subcommand specifies the pro
 and a kiss-o'-death packet returned if enabled.
 The default
 minimum average and minimum are 5 and 2, respectively.
-The monitor subcommand specifies the probability of discard
+The
+\f\*[B-Font]monitor\f[]
+subcommand specifies the probability of discard
 for packets that overflow the rate-control window.
 .TP 7
 .NOP \f\*[B-Font]restrict\f[] \f\*[B-Font]address\f[] [\f\*[B-Font]mask\f[] \f\*[I-Font]mask\f[]] [\f\*[I-Font]flag\f[] \f\*[I-Font]...\f[]]
@@ -1687,7 +1708,9 @@ in the discard command.
 .TP 7
 .NOP \f\*[B-Font]limited\f[]
 Deny service if the packet spacing violates the lower limits specified
-in the discard command.
+in the
+\f\*[B-Font]discard\f[]
+command.
 A history of clients is kept using the
 monitoring capability of
 \fCntpd\f[]\fR(1ntpdmdoc)\f[].
@@ -1832,8 +1855,11 @@ using the manycastclient command, which 
 .ne 2
 
 A persistent manycast client association is configured
-using the manycastclient command, which is similar to the
-server command but with a multicast (IPv4 class
+using the
+\f\*[B-Font]manycastclient\f[]
+command, which is similar to the
+\f\*[B-Font]server\f[]
+command but with a multicast (IPv4 class
 \f\*[B-Font]D\f[]
 or IPv6 prefix
 \f\*[B-Font]FF\f[])
@@ -1909,7 +1935,9 @@ set at the minimum hops specified by the
 \f\*[B-Font]maxpolll\f[]
 value specified in this command.
 Initially, the TTL is
-set at the minimum hops specified by the ttl command.
+set at the minimum hops specified by the
+\f\*[B-Font]ttl\f[]
+command.
 At each retransmission the TTL is increased until reaching
 the maximum hops specified by this command or a sufficient
 number client associations have been found.
@@ -2833,7 +2861,9 @@ This is the same operation as the \-l co
 be used instead of the default system
 \fCsyslog\f[]\fR(3)\f[]
 facility.
-This is the same operation as the \-l command line option.
+This is the same operation as the
+\f\*[B-Font]\-l\f[]
+command line option.
 .TP 7
 .NOP \f\*[B-Font]setvar\f[] \f\*[I-Font]variable\f[] [\f\*[B-Font]default\f[]]
 This command adds an additional system variable.

==== ntpd/ntp.conf.5mdoc ====
2016-02-06 07:43:26+00:00, stenn at psp-deb1.ntp.org +38 -11
  Update ntp.conf documentation.  Harlan Stenn.

--- 1.230/ntpd/ntp.conf.5mdoc	2016-01-20 04:20:06 -05:00
+++ 1.231/ntpd/ntp.conf.5mdoc	2016-02-06 02:43:26 -05:00
@@ -1,9 +1,9 @@ 
-.Dd January 20 2016
+.Dd February 6 2016
 .Dt NTP_CONF 5mdoc File Formats
 .Os
 .\"  EDIT THIS FILE WITH CAUTION  (ntp.mdoc)
 .\"
-.\"  It has been AutoGen-ed  January 20, 2016 at 04:18:07 AM by AutoGen 5.18.5
+.\"  It has been AutoGen-ed  February  6, 2016 at 07:23:02 AM by AutoGen 5.18.5
 .\"  From the definitions    ntp.conf.def
 .\"  and the template file   agmdoc-cmd.tpl
 .Sh NAME
@@ -286,7 +286,9 @@ can be changed with the calldelay comman
 instead of the usual one.
 The packet spacing is normally 2 s;
 however, the spacing between the first and second packets
-can be changed with the calldelay command to allow
+can be changed with the
+.Ic calldelay
+command to allow
 additional time for a modem or ISDN call to complete.
 This is designed to improve timekeeping quality
 with the
@@ -297,7 +299,9 @@ changed with the calldelay command to al
 instead of the usual one.
 The packet spacing is normally 2 s;
 however, the spacing between the first two packets can be
-changed with the calldelay command to allow
+changed with the
+.Ic calldelay
+command to allow
 additional time for a modem or ISDN call to complete.
 This is designed to speed the initial synchronization
 acquisition with the
@@ -330,6 +334,10 @@ The server is discarded by the selection
 .It Cm noselect
 Marks the server as unused, except for display purposes.
 The server is discarded by the selection algroithm.
+.It Cm preempt
+Says the association can be preempted.
+.It Cm true
+Marks the server as a truechimer.
 .It Cm prefer
 Marks the server as preferred.
 All other things being equal,
@@ -360,6 +368,12 @@ default.
 packets.
 Versions 1\-4 are the choices, with version 4 the
 default.
+.It Cm xleave
+Valid in
+.Cm peer
+and
+.Cm broadcast
+modes only, this flag enables interleave mode.
 .El
 .Ss Auxiliary Commands
 .Bl -tag -width indent
@@ -1423,7 +1437,9 @@ included in the restrict list created by
 by a determined cracker.
 .Pp
 Clients can be denied service because they are explicitly
-included in the restrict list created by the restrict command
+included in the restrict list created by the
+.Ic restrict
+command
 or implicitly as the result of cryptographic or rate limit
 violations.
 Cryptographic violations include certificate
@@ -1493,7 +1509,9 @@ The monitor subcommand specifies the pro
 and a kiss\-o'\-death packet returned if enabled.
 The default
 minimum average and minimum are 5 and 2, respectively.
-The monitor subcommand specifies the probability of discard
+The
+.Ic monitor
+subcommand specifies the probability of discard
 for packets that overflow the rate\-control window.
 .It Xo Ic restrict address
 .Op Cm mask Ar mask
@@ -1552,7 +1570,9 @@ in the discard command.
 last one, the packet is dropped.
 .It Cm limited
 Deny service if the packet spacing violates the lower limits specified
-in the discard command.
+in the
+.Ic discard
+command.
 A history of clients is kept using the
 monitoring capability of
 .Xr ntpd 1ntpdmdoc .
@@ -1679,8 +1699,11 @@ using the manycastclient command, which 
 as well and is highly recommended, especially for broadcast modes.
 .Pp
 A persistent manycast client association is configured
-using the manycastclient command, which is similar to the
-server command but with a multicast (IPv4 class
+using the
+.Ic manycastclient
+command, which is similar to the
+.Ic server
+command but with a multicast (IPv4 class
 .Cm D
 or IPv6 prefix
 .Cm FF )
@@ -1750,7 +1773,9 @@ set at the minimum hops specified by the
 .Cm maxpolll
 value specified in this command.
 Initially, the TTL is
-set at the minimum hops specified by the ttl command.
+set at the minimum hops specified by the
+.Ic ttl
+command.
 At each retransmission the TTL is increased until reaching
 the maximum hops specified by this command or a sufficient
 number client associations have been found.
@@ -2651,7 +2676,9 @@ This is the same operation as the \-l co
 be used instead of the default system
 .Xr syslog 3
 facility.
-This is the same operation as the \-l command line option.
+This is the same operation as the
+.Fl l
+command line option.
 .It Ic setvar Ar variable Op Cm default
 This command adds an additional system variable.
 These

==== ntpd/ntp.conf.def ====
2016-02-06 07:43:27+00:00, stenn at psp-deb1.ntp.org +36 -9
  Update ntp.conf documentation.  Harlan Stenn.

--- 1.21/ntpd/ntp.conf.def	2016-01-17 00:06:56 -05:00
+++ 1.22/ntpd/ntp.conf.def	2016-02-06 02:43:27 -05:00
@@ -288,7 +288,9 @@ can be changed with the calldelay comman
 instead of the usual one.
 The packet spacing is normally 2 s;
 however, the spacing between the first and second packets
-can be changed with the calldelay command to allow
+can be changed with the
+.Ic calldelay
+command to allow
 additional time for a modem or ISDN call to complete.
 This is designed to improve timekeeping quality
 with the
@@ -299,7 +301,9 @@ changed with the calldelay command to al
 instead of the usual one.
 The packet spacing is normally 2 s;
 however, the spacing between the first two packets can be
-changed with the calldelay command to allow
+changed with the
+.Ic calldelay
+command to allow
 additional time for a modem or ISDN call to complete.
 This is designed to speed the initial synchronization
 acquisition with the
@@ -332,6 +336,10 @@ The server is discarded by the selection
 .It Cm noselect
 Marks the server as unused, except for display purposes.
 The server is discarded by the selection algroithm.
+.It Cm preempt
+Says the association can be preempted.
+.It Cm true
+Marks the server as a truechimer.
 .It Cm prefer
 Marks the server as preferred.
 All other things being equal,
@@ -362,6 +370,12 @@ default.
 packets.
 Versions 1-4 are the choices, with version 4 the
 default.
+.It Cm xleave
+Valid in
+.Cm peer
+and
+.Cm broadcast
+modes only, this flag enables interleave mode.
 .El
 .Ss Auxiliary Commands
 .Bl -tag -width indent
@@ -1425,7 +1439,9 @@ included in the restrict list created by
 by a determined cracker.
 .Pp
 Clients can be denied service because they are explicitly
-included in the restrict list created by the restrict command
+included in the restrict list created by the
+.Ic restrict
+command
 or implicitly as the result of cryptographic or rate limit
 violations.
 Cryptographic violations include certificate
@@ -1495,7 +1511,9 @@ The monitor subcommand specifies the pro
 and a kiss-o'-death packet returned if enabled.
 The default
 minimum average and minimum are 5 and 2, respectively.
-The monitor subcommand specifies the probability of discard
+The
+.Ic monitor
+subcommand specifies the probability of discard
 for packets that overflow the rate-control window.
 .It Xo Ic restrict address
 .Op Cm mask Ar mask
@@ -1554,7 +1572,9 @@ in the discard command.
 last one, the packet is dropped.
 .It Cm limited
 Deny service if the packet spacing violates the lower limits specified
-in the discard command.
+in the
+.Ic discard
+command.
 A history of clients is kept using the
 monitoring capability of
 .Xr ntpd 1ntpdmdoc .
@@ -1681,8 +1701,11 @@ using the manycastclient command, which 
 as well and is highly recommended, especially for broadcast modes.
 .Pp
 A persistent manycast client association is configured
-using the manycastclient command, which is similar to the
-server command but with a multicast (IPv4 class
+using the
+.Ic manycastclient
+command, which is similar to the
+.Ic server
+command but with a multicast (IPv4 class
 .Cm D
 or IPv6 prefix
 .Cm FF )
@@ -1752,7 +1775,9 @@ set at the minimum hops specified by the
 .Cm maxpolll
 value specified in this command.
 Initially, the TTL is
-set at the minimum hops specified by the ttl command.
+set at the minimum hops specified by the
+.Ic ttl
+command.
 At each retransmission the TTL is increased until reaching
 the maximum hops specified by this command or a sufficient
 number client associations have been found.
@@ -2653,7 +2678,9 @@ This is the same operation as the -l com
 be used instead of the default system
 .Xr syslog 3
 facility.
-This is the same operation as the -l command line option.
+This is the same operation as the
+.Fl l
+command line option.
 .It Ic setvar Ar variable Op Cm default
 This command adds an additional system variable.
 These

==== ntpd/ntp.conf.man.in ====
2016-02-06 07:43:27+00:00, stenn at psp-deb1.ntp.org +42 -12
  Update ntp.conf documentation.  Harlan Stenn.

--- 1.230/ntpd/ntp.conf.man.in	2016-01-20 04:20:06 -05:00
+++ 1.231/ntpd/ntp.conf.man.in	2016-02-06 02:43:27 -05:00
@@ -10,11 +10,11 @@ 
 .ds B-Font B
 .ds I-Font I
 .ds R-Font R
-.TH ntp.conf 5 "20 Jan 2016" "4.2.8p6" "File Formats"
+.TH ntp.conf 5 "06 Feb 2016" "4.2.8p6" "File Formats"
 .\"
-.\" EDIT THIS FILE WITH CAUTION (/tmp/.ag-gsaOxR/ag-XsaGwR)
+.\" EDIT THIS FILE WITH CAUTION (in-mem file)
 .\"
-.\" It has been AutoGen-ed January 20, 2016 at 04:17:45 AM by AutoGen 5.18.5
+.\" It has been AutoGen-ed February 6, 2016 at 07:23:07 AM by AutoGen 5.18.5
 .\" From the definitions ntp.conf.def
 .\" and the template file agman-cmd.tpl
 .SH NAME
@@ -289,7 +289,9 @@ can be changed with the calldelay comman
 instead of the usual one.
 The packet spacing is normally 2 s;
 however, the spacing between the first and second packets
-can be changed with the calldelay command to allow
+can be changed with the
+\f\*[B-Font]calldelay\f[]
+command to allow
 additional time for a modem or ISDN call to complete.
 This is designed to improve timekeeping quality
 with the
@@ -301,7 +303,9 @@ changed with the calldelay command to al
 instead of the usual one.
 The packet spacing is normally 2 s;
 however, the spacing between the first two packets can be
-changed with the calldelay command to allow
+changed with the
+\f\*[B-Font]calldelay\f[]
+command to allow
 additional time for a modem or ISDN call to complete.
 This is designed to speed the initial synchronization
 acquisition with the
@@ -339,6 +343,12 @@ The server is discarded by the selection
 Marks the server as unused, except for display purposes.
 The server is discarded by the selection algroithm.
 .TP 7
+.NOP \f\*[B-Font]preempt\f[]
+Says the association can be preempted.
+.TP 7
+.NOP \f\*[B-Font]true\f[]
+Marks the server as a truechimer.
+.TP 7
 .NOP \f\*[B-Font]prefer\f[]
 Marks the server as preferred.
 All other things being equal,
@@ -371,6 +381,13 @@ default.
 packets.
 Versions 1-4 are the choices, with version 4 the
 default.
+.TP 7
+.NOP \f\*[B-Font]xleave\f[]
+Valid in
+\f\*[B-Font]peer\f[]
+and
+\f\*[B-Font]broadcast\f[]
+modes only, this flag enables interleave mode.
 .PP
 .SS Auxiliary Commands
 .TP 7
@@ -1559,7 +1576,9 @@ included in the restrict list created by
 .ne 2
 
 Clients can be denied service because they are explicitly
-included in the restrict list created by the restrict command
+included in the restrict list created by the
+\f\*[B-Font]restrict\f[]
+command
 or implicitly as the result of cryptographic or rate limit
 violations.
 Cryptographic violations include certificate
@@ -1627,7 +1646,9 @@ The monitor subcommand specifies the pro
 and a kiss-o'-death packet returned if enabled.
 The default
 minimum average and minimum are 5 and 2, respectively.
-The monitor subcommand specifies the probability of discard
+The
+\f\*[B-Font]monitor\f[]
+subcommand specifies the probability of discard
 for packets that overflow the rate-control window.
 .TP 7
 .NOP \f\*[B-Font]restrict\f[] \f\*[B-Font]address\f[] [\f\*[B-Font]mask\f[] \f\*[I-Font]mask\f[]] [\f\*[I-Font]flag\f[] \f\*[I-Font]...\f[]]
@@ -1687,7 +1708,9 @@ in the discard command.
 .TP 7
 .NOP \f\*[B-Font]limited\f[]
 Deny service if the packet spacing violates the lower limits specified
-in the discard command.
+in the
+\f\*[B-Font]discard\f[]
+command.
 A history of clients is kept using the
 monitoring capability of
 \fCntpd\f[]\fR(@NTPD_MS@)\f[].
@@ -1832,8 +1855,11 @@ using the manycastclient command, which 
 .ne 2
 
 A persistent manycast client association is configured
-using the manycastclient command, which is similar to the
-server command but with a multicast (IPv4 class
+using the
+\f\*[B-Font]manycastclient\f[]
+command, which is similar to the
+\f\*[B-Font]server\f[]
+command but with a multicast (IPv4 class
 \f\*[B-Font]D\f[]
 or IPv6 prefix
 \f\*[B-Font]FF\f[])
@@ -1909,7 +1935,9 @@ set at the minimum hops specified by the
 \f\*[B-Font]maxpolll\f[]
 value specified in this command.
 Initially, the TTL is
-set at the minimum hops specified by the ttl command.
+set at the minimum hops specified by the
+\f\*[B-Font]ttl\f[]
+command.
 At each retransmission the TTL is increased until reaching
 the maximum hops specified by this command or a sufficient
 number client associations have been found.
@@ -2833,7 +2861,9 @@ This is the same operation as the \-l co
 be used instead of the default system
 \fCsyslog\f[]\fR(3)\f[]
 facility.
-This is the same operation as the \-l command line option.
+This is the same operation as the
+\f\*[B-Font]\-l\f[]
+command line option.
 .TP 7
 .NOP \f\*[B-Font]setvar\f[] \f\*[I-Font]variable\f[] [\f\*[B-Font]default\f[]]
 This command adds an additional system variable.

==== ntpd/ntp.conf.mdoc.in ====
2016-02-06 07:43:27+00:00, stenn at psp-deb1.ntp.org +38 -11
  Update ntp.conf documentation.  Harlan Stenn.

--- 1.230/ntpd/ntp.conf.mdoc.in	2016-01-20 04:20:06 -05:00
+++ 1.231/ntpd/ntp.conf.mdoc.in	2016-02-06 02:43:27 -05:00
@@ -1,9 +1,9 @@ 
-.Dd January 20 2016
+.Dd February 6 2016
 .Dt NTP_CONF 5 File Formats
 .Os
 .\"  EDIT THIS FILE WITH CAUTION  (ntp.mdoc)
 .\"
-.\"  It has been AutoGen-ed  January 20, 2016 at 04:18:07 AM by AutoGen 5.18.5
+.\"  It has been AutoGen-ed  February  6, 2016 at 07:23:02 AM by AutoGen 5.18.5
 .\"  From the definitions    ntp.conf.def
 .\"  and the template file   agmdoc-cmd.tpl
 .Sh NAME
@@ -286,7 +286,9 @@ can be changed with the calldelay comman
 instead of the usual one.
 The packet spacing is normally 2 s;
 however, the spacing between the first and second packets
-can be changed with the calldelay command to allow
+can be changed with the
+.Ic calldelay
+command to allow
 additional time for a modem or ISDN call to complete.
 This is designed to improve timekeeping quality
 with the
@@ -297,7 +299,9 @@ changed with the calldelay command to al
 instead of the usual one.
 The packet spacing is normally 2 s;
 however, the spacing between the first two packets can be
-changed with the calldelay command to allow
+changed with the
+.Ic calldelay
+command to allow
 additional time for a modem or ISDN call to complete.
 This is designed to speed the initial synchronization
 acquisition with the
@@ -330,6 +334,10 @@ The server is discarded by the selection
 .It Cm noselect
 Marks the server as unused, except for display purposes.
 The server is discarded by the selection algroithm.
+.It Cm preempt
+Says the association can be preempted.
+.It Cm true
+Marks the server as a truechimer.
 .It Cm prefer
 Marks the server as preferred.
 All other things being equal,
@@ -360,6 +368,12 @@ default.
 packets.
 Versions 1\-4 are the choices, with version 4 the
 default.
+.It Cm xleave
+Valid in
+.Cm peer
+and
+.Cm broadcast
+modes only, this flag enables interleave mode.
 .El
 .Ss Auxiliary Commands
 .Bl -tag -width indent
@@ -1423,7 +1437,9 @@ included in the restrict list created by
 by a determined cracker.
 .Pp
 Clients can be denied service because they are explicitly
-included in the restrict list created by the restrict command
+included in the restrict list created by the
+.Ic restrict
+command
 or implicitly as the result of cryptographic or rate limit
 violations.
 Cryptographic violations include certificate
@@ -1493,7 +1509,9 @@ The monitor subcommand specifies the pro
 and a kiss\-o'\-death packet returned if enabled.
 The default
 minimum average and minimum are 5 and 2, respectively.
-The monitor subcommand specifies the probability of discard
+The
+.Ic monitor
+subcommand specifies the probability of discard
 for packets that overflow the rate\-control window.
 .It Xo Ic restrict address
 .Op Cm mask Ar mask
@@ -1552,7 +1570,9 @@ in the discard command.
 last one, the packet is dropped.
 .It Cm limited
 Deny service if the packet spacing violates the lower limits specified
-in the discard command.
+in the
+.Ic discard
+command.
 A history of clients is kept using the
 monitoring capability of
 .Xr ntpd @NTPD_MS@ .
@@ -1679,8 +1699,11 @@ using the manycastclient command, which 
 as well and is highly recommended, especially for broadcast modes.
 .Pp
 A persistent manycast client association is configured
-using the manycastclient command, which is similar to the
-server command but with a multicast (IPv4 class
+using the
+.Ic manycastclient
+command, which is similar to the
+.Ic server
+command but with a multicast (IPv4 class
 .Cm D
 or IPv6 prefix
 .Cm FF )
@@ -1750,7 +1773,9 @@ set at the minimum hops specified by the
 .Cm maxpolll
 value specified in this command.
 Initially, the TTL is
-set at the minimum hops specified by the ttl command.
+set at the minimum hops specified by the
+.Ic ttl
+command.
 At each retransmission the TTL is increased until reaching
 the maximum hops specified by this command or a sufficient
 number client associations have been found.
@@ -2651,7 +2676,9 @@ This is the same operation as the \-l co
 be used instead of the default system
 .Xr syslog 3
 facility.
-This is the same operation as the \-l command line option.
+This is the same operation as the
+.Fl l
+command line option.
 .It Ic setvar Ar variable Op Cm default
 This command adds an additional system variable.
 These

#### ChangeSet ####
2016-02-06 07:39:44+00:00, stenn at psp-deb1.ntp.org
  Update html/xleave.html documentation.  Harlan Stenn.

==== ChangeLog ====
2016-02-06 07:39:39+00:00, stenn at psp-deb1.ntp.org +1 -0
  Update html/xleave.html documentation.  Harlan Stenn.

--- 1.1799/ChangeLog	2016-02-05 04:23:08 -05:00
+++ 1.1800/ChangeLog	2016-02-06 02:39:39 -05:00
@@ -11,6 +11,7 @@ 
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
 * Document ntp.key's optional IP list in authenetic.html.  Harlan Stenn.
+* Update html/xleave.html documentation.  Harlan Stenn.
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

==== html/xleave.html ====
2016-02-06 07:39:33+00:00, stenn at psp-deb1.ntp.org +6 -6
  Update html/xleave.html documentation.  Harlan Stenn.

--- 1.10/html/xleave.html	2014-07-18 04:36:27 -04:00
+++ 1.11/html/xleave.html	2016-02-06 02:39:33 -05:00
@@ -11,17 +11,17 @@ 
 <img src="pic/pogo4.gif" alt="gif" align="left"><a href="http://www.eecis.udel.edu/%7emills/pictures.html">from <i>Pogo</i>, Walt Kelly</a>
 <p>You need a little magic.</p>
 <p>Last update:
-  <!-- #BeginDate format:En2m -->10-Mar-2014  05:25<!-- #EndDate -->
+  <!-- #BeginDate format:En2m -->6-Feb-2016  07:17<!-- #EndDate -->
     UTC</p>
 <br clear="left">
 <hr>
-<p>In the protocol described in the NTP specification and reference implementation up to now, the transmit timestamp, which is captured before the message digest is computed and the packet  queued for output,  is properly called as a <em>softstamp</em> The receive timestamp, which is captured after the input driver interrupt routine and before  the packet is queued for input,  is properly called  a <em>drivestamp</em>.  For enhanced accuracy it is desirable to capture the transmit timestamp  as close to the wire as possible; for example, after the output driver interrupt routine.</p>
-<p> In other words, we would like to replace the transmit softstamp with a drivestamp, but the problem is the transmit drivestamp is available only after the packet has been sent. A solution for this problem is the two-step or interleaved protocol described on this page and included in the the current reference implementation. In interleaved modes the transmit drivestamp for one packet is actually carried in the immediately following packet. The trick, however, is to implement the interleaved protocol without changing the NTP packet header format, without compromising backwards compatibility and without compromising the error recovery properties.</p>
-<p> The reference implementation captures a softstamp before the message digest routine and a drivestamp after the output interrupt routine. In this design the latter timestamp can be considered most accurate, as it avoids the various queuing and transmission latencies. The difference between the two timestamps, which is  called the interleaved or output delay, varies from 16 μs for a dual-core Pentium  running FreeBSD 6.1 to 1100 μs for a Sun Blade 1500 running Solaris 10.</p>
+<p>In the protocol described in the NTP specification and reference implementation up to now, the transmit timestamp, which is captured before the message digest is computed and the packet queued for output, is properly called as a <em>softstamp</em>.  The receive timestamp, which is captured after the input driver interrupt routine and before the packet is queued for input, is properly called a <em>drivestamp</em>.  For enhanced accuracy it is desirable to capture the transmit timestamp as close to the wire as possible; for example, after the output driver interrupt routine.</p>
+<p> In other words, we would like to replace the transmit softstamp with a drivestamp, but the problem is the transmit drivestamp is available only after the packet has been sent.  A solution for this problem is the two-step or interleaved protocol described on this page and included in the the current reference implementation.  In interleaved modes the transmit drivestamp for one packet is actually carried in the immediately following packet.  The trick, however, is to implement the interleaved protocol without changing the NTP packet header format, without compromising backwards compatibility and without compromising the error recovery properties.</p>
+<p> The reference implementation captures a softstamp before the message digest routine and a drivestamp after the output interrupt routine.  In this design the latter timestamp can be considered most accurate, as it avoids the various queuing and transmission latencies.  The difference between the two timestamps, which is called the interleaved or output delay, varies from 16 μs (microseconds) for a dual-core Pentium running FreeBSD 6.1 to 1100 μs (microseconds) for a Sun Blade 1500 running Solaris 10.</p>
 <p>Interleaved mode can be used only in NTP symmetric and broadcast modes.
   It is activated by the <tt>xleave</tt> option with the <tt>peer</tt> or <tt>broadcast</tt> configuration
-commands. A broadcast server configured for interleaved mode is transparent to ordinary broadcast clients, so both ordinary  and interleaved broadcast clients can use the same packets. An interleaved symmetric active peer automatically switches to ordinary symmetric mode if the other peer is not capable of operation in  interleaved mode. </p>
-<p>As demonstrated in the white paper <a href="http://www.eecis.udel.edu/~mills/onwire.html">Analysis and Simulation of the NTP On-Wire Protocols</a>, the interleaved modes have the same resistance to  lost packets, duplicate packets, packets crossed in flight and protocol restarts as the ordinary modes. An application of the interleaved symmetric mode in space missions is presented in the white paper <a href="http://www.eecis.udel.edu/~mills/proximity.html">Time Synchronization for Space Data Links</a>.</p>
+commands.  A broadcast server configured for interleaved mode is transparent to ordinary broadcast clients, so both ordinary and interleaved broadcast clients can use the same packets.  An interleaved symmetric active peer automatically switches to ordinary symmetric mode if the other peer is not capable of operation in interleaved mode.</p>
+<p>As demonstrated in the white paper <a href="http://www.eecis.udel.edu/~mills/onwire.html">Analysis and Simulation of the NTP On-Wire Protocols</a>, the interleaved modes have the same resistance to lost packets, duplicate packets, packets crossed in flight and protocol restarts as the ordinary modes.  An application of the interleaved symmetric mode in space missions is presented in the white paper <a href="http://www.eecis.udel.edu/~mills/proximity.html">Time Synchronization for Space Data Links</a>.</p>
 <hr>
 <div align="center"> <img src="pic/pogo1a.gif" alt="gif"> </div>
 <br>

#### ChangeSet ####
2016-02-05 10:50:33+00:00, stenn at psp-deb1.ntp.org
  cleanup

==== ChangeLog ====
2016-02-05 10:50:28+00:00, stenn at psp-deb1.ntp.org +1 -1
  cleanup

--- 1.1794.2.1/ChangeLog	2016-02-04 23:28:51 -05:00
+++ 1.1794.2.2/ChangeLog	2016-02-05 05:50:28 -05:00
@@ -1,8 +1,8 @@ 
-* [Bug 3007] Validate crypto-NAKs
 ---
 
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
+* [Bug 3007] Validate crypto-NAKs
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

#### ChangeSet ####
2016-02-05 09:21:00+00:00, stenn at psp-deb1.ntp.org
  Document ntp.key's optional IP list in authenetic.html.  Harlan Stenn.

==== ChangeLog ====
2016-02-05 09:20:02+00:00, stenn at psp-deb1.ntp.org +1 -0
  Document ntp.key's optional IP list in authenetic.html.  Harlan Stenn.

--- 1.1794.1.2/ChangeLog	2016-01-24 05:14:42 -05:00
+++ 1.1794.3.1/ChangeLog	2016-02-05 04:20:02 -05:00
@@ -2,6 +2,7 @@ 
 
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
+* Document ntp.key's optional IP list in authenetic.html.  Harlan Stenn.
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

==== html/authentic.html ====
2016-02-05 09:20:05+00:00, stenn at psp-deb1.ntp.org +16 -16
  Document ntp.key's optional IP list in authenetic.html.  Harlan Stenn.

--- 1.14/html/authentic.html	2014-07-17 02:12:29 -04:00
+++ 1.15/html/authentic.html	2016-02-05 04:20:05 -05:00
@@ -20,7 +20,7 @@ color: #FF0000;
 <img src="pic/alice44.gif" alt="gif" align="left"><a href="http://www.eecis.udel.edu/%7emills/pictures.html">from <i>Alice's Adventures in Wonderland</i>, Lewis Carroll</a>
 <p>Our resident cryptographer; now you see him, now you don't.</p>
 <p>Last update:
-  <!-- #BeginDate format:En2m -->1-Dec-2012  04:44<!-- #EndDate -->
+  <!-- #BeginDate format:En2m -->5-Feb-2016  09:13<!-- #EndDate -->
   UTC</p>
 <br clear="left">
 <h4>Related Links</h4>
@@ -35,28 +35,28 @@ color: #FF0000;
 </ul>
 <hr>
 <h4 id="auth">Introduction</h4>
-<p>This page describes the various cryptographic authentication provisions in NTPv4. Authentication support allows the NTP client to verify that servers are in fact known and trusted and not intruders intending accidentally or intentionally to masquerade as a legitimate server. A detailed discussion of the NTP multi-layer security model and vulnerability analysis is in the white paper <a href="http://www.eecis.udel.edu/~mills/security.html">NTP Security Analysis</a>.</p>
-<p> The NTPv3 specification (RFC-1305) defined an authentication scheme properly described as <em>symmetric key cryptography</em>. It used the Data Encryption Standard (DES) algorithm operating in cipher-block chaining (CBC) mode. Subsequently, this algorithm was replaced by the RSA Message Digest 5 (MD5) algorithm commonly called keyed-MD5. Either algorithm computes a message digest or one-way hash which can be used to verify the client has the same message digest as the server. The MD5 message digest algorithm is included in the distribution, so without further cryptographic support, the distribution can be freely exported.</p>
-<p>If the OpenSSL cryptographic library is installed prior to building the distribution, all message digest algorithms included in the library may be used, including SHA and SHA1.   However, if conformance to FIPS 140-2 is required, only a limited subset of these algorithms can be used. This library is available from <a href="http://www.openssl.org">http://www.openssl.org</a> and can be installed using the procedures outlined in the <a href="build.html">Building and Installing the Distribution</a> page. Once installed, the configure and  build process automatically detects the library and links the library routines
+<p>This page describes the various cryptographic authentication provisions in NTPv4.  Authentication support allows the NTP client to verify that servers are in fact known and trusted and not intruders intending accidentally or intentionally to masquerade as a legitimate server.  A detailed discussion of the NTP multi-layer security model and vulnerability analysis is in the white paper <a href="http://www.eecis.udel.edu/~mills/security.html">NTP Security Analysis</a>.</p>
+<p> The NTPv3 specification (RFC-1305) defined an authentication scheme properly described as <em>symmetric key cryptography</em>.  It used the Data Encryption Standard (DES) algorithm operating in cipher-block chaining (CBC) mode.  Subsequently, this algorithm was replaced by the RSA Message Digest 5 (MD5) algorithm commonly called keyed-MD5.  Either algorithm computes a message digest or one-way hash which can be used to verify the client has the same message digest as the server.  The MD5 message digest algorithm is included in the distribution, so without further cryptographic support, the distribution can be freely exported.</p>
+<p>If the OpenSSL cryptographic library is installed prior to building the distribution, all message digest algorithms included in the library may be used, including SHA and SHA1.  However, if conformance to FIPS 140-2 is required, only a limited subset of these algorithms can be used.  This library is available from <a href="http://www.openssl.org">http://www.openssl.org</a> and can be installed using the procedures outlined in the <a href="build.html">Building and Installing the Distribution</a> page.  Once installed, the configure and build process automatically detects the library and links the library routines
 required.</p>
-<p>In addition to  the symmetric key algorithms, this distribution includes support for the  Autokey public key algorithms and protocol specified in RFC-5906 "Network Time Protocol Version 4: Autokey Specification". This support is available only if the OpenSSL library has been installed and the <tt>--enable-autokey</tt> option   is used when the distribution is built.</p>
-<p> Public key cryptography is generally considered more secure than symmetric key cryptography, since the security is based on private and public values which are generated by each participant and where the private value is never revealed. Autokey uses X.509 public certificates, which can be produced by commercial services,  the OpenSSL application program, or the <a href="keygen.html"><tt>ntp-keygen</tt></a> utility program in the NTP software distribution.</p>
-<p>Note that according to US law, NTP binaries including OpenSSL library components, including the OpenSSL library itself, cannot be exported outside the US without license from the US Department of Commerce. Builders outside the US are advised to obtain the OpenSSL library directly from OpenSSL, which is outside the US, and build outside the US.</p>
-<p>Authentication is configured separately for each association using the <tt>key</tt> or <tt>autokey</tt> option of the <tt>server</tt> configuration command, as described in the <a href="confopt.html">Server Options</a> page. The <a href="keygen.html">ntp-keygen</a> page describes the files required for the various authentication schemes. Further details are in the briefings, papers and reports at the NTP project page linked from <a href="http://www.ntp.org">www.ntp.org</a>.</p>
-<p>By default, the client sends non-authenticated packets and the server responds with non-authenticated packets. If the client sends authenticated packets, the server  responds with  authenticated packets if correct, or a crypto-NAK packet if not.. In the case of unsolicited packets which might consume significant resources, such as broadcast or symmetric mode  packets, , authentication is required, unless overridden by a <tt>disable auth</tt> command.  In the current climate of targeted broadcast or "letterbomb" attacks, defeating this requirement would be decidedly dangerous. In any case, the <tt>notrust </tt>flag,  described on the <a href="authopt.html">Access Control Options</a> page, can be used to disable access to all but correctly authenticated clients..</p>
+<p>In addition to the symmetric key algorithms, this distribution includes support for the Autokey public key algorithms and protocol specified in RFC-5906 "Network Time Protocol Version 4: Autokey Specification".  This support is available only if the OpenSSL library has been installed and the <tt>--enable-autokey</tt> option is used when the distribution is built.</p>
+<p> Public key cryptography is generally considered more secure than symmetric key cryptography, since the security is based on private and public values which are generated by each participant and where the private value is never revealed.  Autokey uses X.509 public certificates, which can be produced by commercial services, the OpenSSL application program, or the <a href="keygen.html"><tt>ntp-keygen</tt></a> utility program in the NTP software distribution.</p>
+<p>Note that according to US law, NTP binaries including OpenSSL library components, including the OpenSSL library itself, cannot be exported outside the US without license from the US Department of Commerce.  Builders outside the US are advised to obtain the OpenSSL library directly from OpenSSL, which is outside the US, and build outside the US.</p>
+<p>Authentication is configured separately for each association using the <tt>key</tt> or <tt>autokey</tt> option of the <tt>server</tt> configuration command, as described in the <a href="confopt.html">Server Options</a> page.  The <a href="keygen.html">ntp-keygen</a> page describes the files required for the various authentication schemes.  Further details are in the briefings, papers and reports at the NTP project page linked from <a href="http://www.ntp.org">www.ntp.org</a>.</p>
+<p>By default, the client sends non-authenticated packets and the server responds with non-authenticated packets.  If the client sends authenticated packets, the server responds with authenticated packets if correct, or a crypto-NAK packet if not.  In the case of unsolicited packets which might consume significant resources, such as broadcast or symmetric mode packets, authentication is required, unless overridden by a <tt>disable auth</tt> command.  In the current climate of targeted broadcast or "letterbomb" attacks, defeating this requirement would be decidedly dangerous.  In any case, the <tt>notrust </tt>flag, described on the <a href="authopt.html">Access Control Options</a> page, can be used to disable access to all but correctly authenticated clients.</p>
 <h4 id="symm">Symmetric Key Cryptography</h4>
-<p>The original NTPv3 specification (RFC-1305), as well as the current NTPv4 specification (RFC-5905), allows any one of possibly 65,534 message digest keys (excluding zero), each distinguished by a 32-bit key ID, to authenticate an association. The servers and clients involved must agree on the  key ID, key type and key to authenticate NTP packets.</p>
-<p>The message digest is a cryptographic hash computed by an   algorithm such as MD5 or SHA. When authentication is specified,  a message authentication code (MAC)  is appended to the NTP packet header. The MAC consists of a 32-bit key identifier (key ID) followed by a 128- or 160-bit  message digest. The  algorithm computes the digest as the hash of a  128- or 160- bit  message digest key concatenated with the NTP packet header fields with the exception of the MAC. On transmit, the message digest is computed and inserted in the MAC. On receive, the message digest is computed and compared with the MAC. The packet is accepted only if the two MACs are identical. If a discrepancy is found by the client,   the client ignores the packet, but raises an alarm. If this happens at the server, the server returns a special message called a <em>crypto-NAK</em>. Since the crypto-NAK is protected by the loopback test, an intruder cannot disrupt the protocol by sending a bogus crypto-NAK.<
 /p>
-<p>Keys and related information are specified in a keys file, which must be distributed and stored using secure means beyond the scope of the NTP protocol itself. Besides the keys used for ordinary NTP associations, additional keys can be used as passwords for the <tt><a href="ntpq.html">ntpq</a></tt> and <tt><a href="ntpdc.html">ntpdc</a></tt> utility programs. Ordinarily, the <tt>ntp.keys</tt> file is generated by the <tt><a href="keygen.html">ntp-keygen</a></tt> program, but it can be constructed and edited using an ordinary text editor.</p>
-<p> Each line of the keys file consists of three fields: a key ID in the range  1 to 65,534, inclusive, a key type, and a  message digest key consisting of a printable ASCII string less than 40 characters, or a 40-character hex digit string. If the OpenSSL library is installed, the key type  can be any message digest algorithm supported by the  library.   If the OpenSSL library is not installed, the only permitted key type is MD5.</p>
+<p>The original NTPv3 specification (RFC-1305), as well as the current NTPv4 specification (RFC-5905), allows any one of possibly 65,534 message digest keys (excluding zero), each distinguished by a 32-bit key ID, to authenticate an association.  The servers and clients involved must agree on the key ID, key type and key to authenticate NTP packets.</p>
+<p>The message digest is a cryptographic hash computed by an algorithm such as MD5 or SHA.  When authentication is specified, a message authentication code (MAC) is appended to the NTP packet header.  The MAC consists of a 32-bit key identifier (key ID) followed by a 128- or 160-bit message digest.  The algorithm computes the digest as the hash of a 128- or 160- bit message digest key concatenated with the NTP packet header fields with the exception of the MAC.  On transmit, the message digest is computed and inserted in the MAC.  On receive, the message digest is computed and compared with the MAC.  The packet is accepted only if the two MACs are identical.  If a discrepancy is found by the client, the client ignores the packet, but raises an alarm.  If this happens at the server, the server returns a special message called a <em>crypto-NAK</em>.  Since the crypto-NAK is protected by the loopback test, an intruder cannot disrupt the protocol by sending a bogus crypto-NAK.</
 p>
+<p>Keys and related information are specified in a keys file, which must be distributed and stored using secure means beyond the scope of the NTP protocol itself.  Besides the keys used for ordinary NTP associations, additional keys can be used as passwords for the <tt><a href="ntpq.html">ntpq</a></tt> and <tt><a href="ntpdc.html">ntpdc</a></tt> utility programs.  Ordinarily, the <tt>ntp.keys</tt> file is generated by the <tt><a href="keygen.html">ntp-keygen</a></tt> program, but it can be constructed and edited using an ordinary text editor.</p>
+<p> Each line of the keys file consists of three or four fields: a key ID in the range 1 to 65,534, inclusive, a key type, a message digest key consisting of a printable ASCII string less than 40 characters or a 40-character hex digit string, and an optional comma-separated list of IPs that are allowed to serve time.  If the OpenSSL library is installed, the key type can be any message digest algorithm supported by the library.  If the OpenSSL library is not installed, the only permitted key type is MD5.</p>
 <div align="center">
   <p><img src="pic/sx5.gif" alt="gif"></p>
   <p>Figure 1. Typical Symmetric Key File</p>
 </div>
-<p>Figure 1 shows a typical keys file used by the reference implementation when the OpenSSL library is installed.   In this figure, for key IDs in he range 1-10, the  key is interpreted as a printable ASCII string. For key IDs in the range 11-20, the key is  a 40-character hex digit string.   The key  is truncated or zero-filled internally to either 128 or 160 bits, depending on the key type. The line can be edited later or new lines can be added to change any field.  The key can be  change  to a  password,  such as   <tt>2late4Me</tt> for key ID 10. Note that two or more keys files can be combined in any order as long as the key IDs are distinct.</p>
-<p>When <tt>ntpd</tt> is  started, it reads the keys file specified by the <tt>keys</tt> command and installs the keys in the key cache. However, individual keys must be activated with the <tt>trustedkey</tt> configuration command before use. This allows, for instance, the installation of possibly several batches of keys and then activating a key remotely using <tt>ntpq</tt> or <tt>ntpdc</tt>. The <tt>requestkey</tt> command selects the key ID used as the password for the <tt>ntpdc</tt> utility, while the <tt>controlkey</tt> command selects the key ID used as the password for the <tt>ntpq</tt> utility.</p>
+<p>Figure 1 shows a typical keys file used by the reference implementation when the OpenSSL library is installed.  In this figure, for key IDs in he range 1-10, the key is interpreted as a printable ASCII string.  For key IDs in the range 11-20, the key is a 40-character hex digit string.  The key is truncated or zero-filled internally to either 128 or 160 bits, depending on the key type.  The line can be edited later or new lines can be added to change any field.  The key can be change to a password, such as <tt>2late4Me</tt> for key ID 10.  Note that two or more keys files can be combined in any order as long as the key IDs are distinct.</p>
+<p>When <tt>ntpd</tt> is started, it reads the keys file specified by the <tt>keys</tt> command and installs the keys in the key cache.  However, individual keys must be activated with the <tt>trustedkey</tt> configuration command before use.  This allows, for instance, the installation of possibly several batches of keys and then activating a key remotely using <tt>ntpq</tt> or <tt>ntpdc</tt>.  The <tt>requestkey</tt> command selects the key ID used as the password for the <tt>ntpdc</tt> utility, while the <tt>controlkey</tt> command selects the key ID used as the password for the <tt>ntpq</tt> utility.</p>
 <h4 id="windows">Microsoft Windows Authentication</h4>
-<p>In addition to the above means, <tt>ntpd</tt> now supports Microsoft Windows MS-SNTP authentication using Active Directory services. This support was contributed by the Samba Team and is still in development. It is enabled using the <tt>mssntp</tt> flag of the <tt>restrict</tt> command described on the <a href="accopt.html#restrict">Access Control Options</a> page. <span class="style1">Note: Potential users should be aware that these services involve a TCP connection to another process that could potentially block, denying services to other users. Therefore, this flag should be used only for a dedicated server with no clients other than MS-SNTP.</span></p>
+<p>In addition to the above means, <tt>ntpd</tt> now supports Microsoft Windows MS-SNTP authentication using Active Directory services.  This support was contributed by the Samba Team and is still in development.  It is enabled using the <tt>mssntp</tt> flag of the <tt>restrict</tt> command described on the <a href="accopt.html#restrict">Access Control Options</a> page.  <span class="style1">Note: Potential users should be aware that these services involve a TCP connection to another process that could potentially block, denying services to other users.  Therefore, this flag should be used only for a dedicated server with no clients other than MS-SNTP.</span></p>
 <h4 id="pub">Public Key Cryptography</h4>
 <p>See the <a href="autokey.html">Autokey Public-Key Authentication</a> page.</p>
 <hr>

#### ChangeSet ####
2016-02-05 04:29:08+00:00, mayer at psp-deb1.ntp.org
  Validate crypto-NAK's

==== ChangeLog ====
2016-02-05 04:28:51+00:00, mayer at psp-deb1.ntp.org +1 -0
  Validate crypto-NAK's

--- 1.1794.1.2/ChangeLog	2016-01-24 05:14:42 -05:00
+++ 1.1794.2.1/ChangeLog	2016-02-04 23:28:51 -05:00
@@ -1,3 +1,4 @@ 
+* [Bug 3007] Validate crypto-NAKs
 ---
 
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org

==== include/ntp.h ====
2016-02-05 04:20:12+00:00, mayer at psp-deb1.ntp.org +2 -0
  Add badNAM to peer struct and specify min V4 len

--- 1.216/include/ntp.h	2016-01-17 00:12:11 -05:00
+++ 1.217/include/ntp.h	2016-02-04 23:20:12 -05:00
@@ -391,6 +391,7 @@ struct peer {
 	u_long	received;	/* packets received */
 	u_long	processed;	/* packets processed */
 	u_long	badauth;	/* bad authentication (TEST5) */
+	u_long	badNAK;		/* invalid crypto-NAK */
 	u_long	bogusorg;	/* bogus origin (TEST2, TEST3) */
 	u_long	oldpkt;		/* old duplicate (TEST1) */
 	u_long	seldisptoolarge; /* bad header (TEST6, TEST7) */
@@ -545,6 +546,7 @@ struct pkt {
 	l_fp	rec;		/* receive time stamp */
 	l_fp	xmt;		/* transmit time stamp */
 
+#define	MIN_V4_PKT_LEN	(12 * sizeof(u_int32)) /* min header length */
 #define	LEN_PKT_NOMAC	(12 * sizeof(u_int32)) /* min header length */
 #define MIN_MAC_LEN	(1 * sizeof(u_int32))	/* crypto_NAK */
 #define MAX_MD5_LEN	(5 * sizeof(u_int32))	/* MD5 */

==== ntpd/ntp_proto.c ====
2016-02-05 04:19:12+00:00, mayer at psp-deb1.ntp.org +78 -2
  Validate crypto-NAM's

--- 1.373/ntpd/ntp_proto.c	2016-01-18 06:54:51 -05:00
+++ 1.373.1.1/ntpd/ntp_proto.c	2016-02-04 23:19:12 -05:00
@@ -50,6 +50,12 @@ enum kiss_codes {
 	UNKNOWNKISS			/* Unknown Kiss Code */
 };
 
+enum nak_error_codes {
+	NONAK,				/* No NAK seen */
+	INVALIDNAK,			/* NAK cannot be used */
+	VALIDNAK			/* NAK is valid */
+};
+
 /*
  * traffic shaping parameters
  */
@@ -252,6 +258,63 @@ kiss_code_check(
 	}
 }
 
+/* 
+ * Check that NAK is valid
+ */
+BOOL
+valid_NAK(
+	  struct peer *peer,
+	  struct recvbuf *rbufp,
+	  u_char hismode
+	  )
+{
+	int base_packet_length = MIN_V4_PKT_LEN;
+	int remainder_size;
+	struct pkt *rpkt;
+	int keyid;
+
+	/*
+	 * Check to see if there is something beyond the basic packet
+	 */
+	if (rbufp->recv_length == base_packet_length) {
+		return NONAK;
+	}
+
+	remainder_size = rbufp->recv_length - base_packet_length;
+	/*
+	 * Is this a potential NAK?
+	 */
+	if (remainder_size != 4) {
+		return NONAK;
+	}
+
+	/*
+	 * Only server responses can contain NAK's
+	 */
+
+	if (hismode != MODE_SERVER) {
+		return (INVALIDNAK);
+	}
+
+	/* 
+	 * Make sure that the extra field in the packet is all zeros
+	 */
+	rpkt = &rbufp->recv_pkt;
+	keyid = ntohl(((u_int32 *)rpkt)[base_packet_length / 4]);
+	if (keyid != 0) {
+		return (INVALIDNAK);
+	}
+
+	/* 
+	 * Only valid if peer uses a key
+	 */
+	if (peer->keyid > 0 || peer->flags & FLAG_SKEY) {
+		return (VALIDNAK);
+	}
+	else {
+		return (INVALIDNAK);
+	}
+}
 
 /*
  * transmit - transmit procedure called by poll timeout
@@ -493,6 +556,7 @@ receive(
 	int	has_mac;		/* length of MAC field */
 	int	authlen;		/* offset of MAC field */
 	int	is_authentic = 0;	/* cryptosum ok */
+	int	crypto_nak_test;	/* result of crypto-NAK check */
 	int	retcode = AM_NOMATCH;	/* match code */
 	keyid_t	skeyid = 0;		/* key IDs */
 	u_int32	opcode = 0;		/* extension field opcode */
@@ -617,6 +681,7 @@ receive(
 	 * extension field is present, so we subtract the length of the
 	 * field and go around again.
 	 */
+
 	authlen = LEN_PKT_NOMAC;
 	has_mac = rbufp->recv_length - authlen;
 	while (has_mac > 0) {
@@ -767,6 +832,17 @@ receive(
 	 * is zero, acceptable outcomes of y are NONE and OK. If x is
 	 * one, the only acceptable outcome of y is OK.
 	 */
+	crypto_nak_test = valid_NAK(peer, rbufp, hismode);
+
+	/*
+	 * Drop any invalid crypto-NAKs
+	 */
+	if (crypto_nak_test == INVALIDNAK) {
+		peer->badNAK++;
+		msyslog(LOG_ERR, "crypto-NAK error at %ld %s<-%s", 
+			current_time, stoa(dstadr_sin), stoa(&rbufp->recv_srcadr));
+		return;
+	}
 
 	if (has_mac == 0) {
 		restrict_mask &= ~RES_MSSNTP;
@@ -777,7 +853,7 @@ receive(
 			    authlen,
 			    ntohl(pkt->org.l_ui), ntohl(pkt->org.l_uf),
 			    ntohl(pkt->xmt.l_ui), ntohl(pkt->xmt.l_uf)));
-	} else if (has_mac == 4) {
+	} else if (crypto_nak_test == VALIDNAK) {
 		restrict_mask &= ~RES_MSSNTP;
 		is_authentic = AUTH_CRYPTO; /* crypto-NAK */
 		DPRINTF(2, ("receive: at %ld %s<-%s mode %d/%s:%s keyid %08x len %d auth %d org %#010x.%08x xmt %#010x.%08x MAC4\n",
@@ -1507,7 +1583,7 @@ receive(
 	 * client packet. The server might have just changed keys. Clear
 	 * the association and restart the protocol.
 	 */
-	if (is_authentic == AUTH_CRYPTO) {
+	if (crypto_nak_test == VALIDNAK) {
 		report_event(PEVNT_AUTH, peer, "crypto_NAK");
 		peer->flash |= TEST5;		/* bad auth */
 		peer->badauth++;

#### ChangeSet ####
2016-01-28 08:08:42+01:00, jnperlin at hydra.localnet
  [Bug 2999] out-of-bounds access in 'is_safe_filename()'

==== ChangeLog ====
2016-01-28 08:08:42+01:00, jnperlin at hydra.localnet +1 -0
  [Bug 2999] out-of-bounds access in 'is_safe_filename()'

--- 1.1794.1.2/ChangeLog	2016-01-24 05:14:42 -05:00
+++ 1.1794.1.3/ChangeLog	2016-01-28 02:08:42 -05:00
@@ -2,6 +2,7 @@ 
 
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger at ntp.org
 * [Bug 2995] Fixes to compile on Windows
+* [Bug 2999] out-of-bounds access in 'is_safe_filename()'. perlinger at ntp.org
 
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>

==== ntpd/ntp_control.c ====
2016-01-28 08:08:42+01:00, jnperlin at hydra.localnet +3 -3
  [Bug 2999] out-of-bounds access in 'is_safe_filename()'
   - fixed array bound test
   - make function NULL-pointer safe

--- 1.206/ntpd/ntp_control.c	2016-01-13 00:55:43 -05:00
+++ 1.207/ntpd/ntp_control.c	2016-01-28 02:08:42 -05:00
@@ -911,18 +911,18 @@ is_safe_filename(const char * name)
 	};
 
 	u_int widx, bidx, mask;
-	if (!*name)
+	if ( ! (name && *name))
 		return FALSE;
 	
 	mask = 1u;
 	while (0 != (widx = (u_char)*name++)) {
 		bidx = (widx & 15) << 1;
 		widx = widx >> 4;
-		if (widx >= sizeof(chclass))
+		if (widx >= sizeof(chclass)/sizeof(chclass[0]))
 			return FALSE;
 		if (0 == ((chclass[widx] >> bidx) & mask))
 			return FALSE;
-		mask |= 2u;
+		mask = 2u;
 	}
 	return TRUE;
 }

#### ChangeSet ####
2016-01-26 08:47:08+00:00, stenn at psp-deb1.ntp.org
  cleanup

==== ntpd/ntp_proto.c ====
2016-01-26 08:47:02+00:00, stenn at psp-deb1.ntp.org +20 -18
  cleanup

--- 1.376/ntpd/ntp_proto.c	2016-01-23 07:54:31 -05:00
+++ 1.377/ntpd/ntp_proto.c	2016-01-26 03:47:02 -05:00
@@ -1401,6 +1401,7 @@ receive(
 		return;
 	}
 #endif	/* AUTOKEY */
+
 	peer->received++;
 	peer->flash &= ~PKT_TEST_MASK;
 	if (peer->flags & FLAG_XBOGUS) {
@@ -1418,8 +1419,8 @@ receive(
 	 */
 	if (L_ISZERO(&p_xmt)) {
 		peer->flash |= TEST3;			/* unsynch */
-		if (0 == hisstratum) {
-			peer->bogusorg++;	/* for TEST2 or TEST3 */
+		if (0 == hisstratum) {			/* KoD packet */
+			peer->bogusorg++;		/* for TEST2 or TEST3 */
 			msyslog(LOG_INFO,
 				"receive: Unexpected zero transmit timestamp in KoD from %s",
 				ntoa(&peer->srcadr));
@@ -1427,7 +1428,7 @@ receive(
 		}
 
 	/*
-	 * If the transmit timestamp duplicates a previous one, the
+	 * If the transmit timestamp duplicates our previous one, the
 	 * packet is a replay. This prevents the bad guys from replaying
 	 * the most recent packet, authenticated or not.
 	 */
@@ -1457,20 +1458,20 @@ receive(
 	 * KoD packets are a mixed-blessing.  Forged KoD packets
 	 * are DoS attacks.  There are rare situations where we might
 	 * get a valid KoD response, though.  Since KoD packets are
-	 * a special case that can easily complicate the checks we do
-	 * next, we handle the special KoD cases here.
+	 * a special case that complicate the checks we do next, we
+	 * handle the basic KoD checks here.
 	 *
 	 * Note that we expect the incoming KoD packet to have its
 	 * (nonzero) org, rec, and xmt timestamps set to the xmt timestamp
 	 * that we have previously sent out.  Watch interleave mode.
 	 */
 	} else if (0 == hisstratum) {
-		if (   L_ISZERO(&p_xmt)
-		    || L_ISZERO(&p_org)
+		DEBUG_INSIST(!L_ISZERO(&p_xmt));
+		if (   L_ISZERO(&p_org)		/* We checked p_xmt above */
 		    || L_ISZERO(&p_rec)) {
 			peer->bogusorg++;
 			msyslog(LOG_INFO,
-				"receive: KoD packet from %s has a zero xmt, org, or rec timestamp.  Ignoring.",
+				"receive: KoD packet from %s has a zero org or rec timestamp.  Ignoring.",
 				ntoa(&peer->srcadr));
 			return;
 		}
@@ -1488,7 +1489,7 @@ receive(
 		if (peer->flip == 0 && !L_ISEQU(&p_org, &peer->aorg)) {
 			peer->bogusorg++;
 			msyslog(LOG_INFO,
-				"receive: Unexpected KoD origin timestamp %#010x.%08x from %s does not match %#010x.%08x",
+				"receive: KoD origin timestamp %#010x.%08x from %s does not match %#010x.%08x - ignoring.",
 				p_org.l_ui, p_org.l_uf,
 				ntoa(&peer->srcadr),
 				peer->aorg.l_ui, peer->aorg.l_uf);
@@ -1496,7 +1497,7 @@ receive(
 		} else if (peer->flip == 1 && !L_ISEQU(&p_org, &peer->borg)) {
 			peer->bogusorg++;
 			msyslog(LOG_INFO,
-				"receive: Unexpected KoD origin timestamp %#010x.%08x from %s does not match interleave %#010x.%08x",
+				"receive: KoD origin timestamp %#010x.%08x from %s does not match interleave %#010x.%08x - ignoring.",
 				p_org.l_ui, p_org.l_uf,
 				ntoa(&peer->srcadr),
 				peer->borg.l_ui, peer->borg.l_uf);
@@ -1522,11 +1523,8 @@ receive(
 	 * be from us, attempting to cause our server to KoD us.
 	 */
 	} else if (peer->flip == 0) {
-		/* HMS: we can simplify this now that we do KoD checks above */
-		if (0 < hisstratum && L_ISZERO(&p_org)) {
-			L_CLR(&peer->aorg);
-		} else if (    L_ISZERO(&peer->aorg)
-			   || !L_ISEQU(&p_org, &peer->aorg)) {
+		if (    L_ISZERO(&peer->aorg)
+		    || !L_ISEQU(&p_org, &peer->aorg)) {
 			peer->bogusorg++;
 			peer->flash |= TEST2;	/* bogus */
 			msyslog(LOG_INFO,
@@ -1540,10 +1538,10 @@ receive(
 				peer->flip = 1;
 				report_event(PEVNT_XLEAVE, peer, NULL);
 			}
+			/* HMS: Do we want to return here if it's xleave? */
 			return; /* Bogus or possible interleave packet */
-		} else {
-			L_CLR(&peer->aorg);
 		}
+		L_CLR(&peer->aorg);
 
 	/*
 	 * Check for valid nonzero timestamp fields.
@@ -1682,7 +1680,6 @@ receive(
 		}
 	    	break;
 
-	    case MODE_UNSPEC:		/* unspecified (old version) */
 	    case MODE_CLIENT:		/* client mode */
 #if 0		/* At this point, MODE_CONTROL is overloaded by MODE_BCLIENT */
 	    case MODE_CONTROL:		/* control mode */
@@ -1690,7 +1687,12 @@ receive(
 	    case MODE_PRIVATE:		/* private mode */
 	    case MODE_BCLIENT:		/* broadcast client mode */
 	    	break;
+
+	    case MODE_UNSPEC:		/* unspecified (old version) */
 	    default:
+		msyslog(LOG_INFO,
+			"receive: Unexpected mode (%d) in packet from %s",
+			hismode, ntoa(&peer->srcadr));
 	    	break;
 	}
 

#### ChangeSet ####
2016-01-23 14:26:48+00:00, stenn at psp-deb1.ntp.org
  Reclassify KoD timestamp checks to 2945

==== ChangeLog ====
2016-01-23 14:25:48+00:00, stenn at psp-deb1.ntp.org +1 -1
  Reclassify KoD timestamp checks to 2945

--- 1.1793.1.5/ChangeLog	2016-01-23 07:54:35 -05:00
+++ 1.1793.1.6/ChangeLog	2016-01-23 09:25:48 -05:00
@@ -1,9 +1,9 @@ 
 ---
 
 * [Sec 2901] KoD packets must have non-zero transmit timestamps.  HStenn.
-* [Sec 2901] Additional KoD packet checks.  HStenn.
 * [Sec 2936] Skeleton Key: Any system knowing the trusted key can serve
   time. Include passive servers in this check. HStenn.
+* [Sec 2945] Additional KoD packet checks.  HStenn.
 * [Bug 2879] Improve NTP security against timing attacks. perlinger at ntp.org
   - integrated patches by Loganaden Velvidron <logan at ntp.org>
     with some modifications & unit tests

#### ChangeSet ####
2016-01-23 13:52:03+00:00, stenn at psp-deb1.ntp.org
  revert use of isc_tsmemcmp in sntp/crypto.c until it is in a more accessible place.  This is not a critical use of that function.

==== sntp/crypto.c ====
2016-01-23 13:51:58+00:00, stenn at psp-deb1.ntp.org +8 -3
  revert use of isc_tsmemcmp in sntp/crypto.c until it is in a more accessible place.  This is not a critical use of that function.

--- 1.20/sntp/crypto.c	2016-01-21 01:40:50 -05:00
+++ 1.21/sntp/crypto.c	2016-01-23 08:51:58 -05:00
@@ -57,11 +57,16 @@ auth_md5(
 	pkt_ptr = pkt_data;
 	hash_len = make_mac(pkt_ptr, pkt_size, sizeof(digest), cmp_key,
 			    digest);
-	if (!hash_len)
+	if (!hash_len) {
 		authentic = FALSE;
-	else
-		authentic = !isc_tsmemcmp(digest, pkt_data + pkt_size + 4,
+	} else {
+		/* isc_tsmemcmp will be better when its easy to link
+		 * with.  sntp is a 1-shot program, so snooping for
+		 * timing attacks is Harder.
+		 */
+		authentic = !memcmp(digest, pkt_data + pkt_size + 4,
 				    hash_len);
+	}
 	return authentic;
 }
 

#### ChangeSet ####
2016-01-23 12:54:39+00:00, stenn at psp-deb1.ntp.org
  [Sec 2901] Additional KoD packet checks.  HStenn.

==== ChangeLog ====
2016-01-23 12:54:35+00:00, stenn at psp-deb1.ntp.org +1 -0
  [Sec 2901] Additional KoD packet checks.  HStenn.

--- 1.1793.1.4/ChangeLog	2016-01-23 06:36:23 -05:00
+++ 1.1793.1.5/ChangeLog	2016-01-23 07:54:35 -05:00
@@ -1,6 +1,7 @@ 
 ---
 
 * [Sec 2901] KoD packets must have non-zero transmit timestamps.  HStenn.
+* [Sec 2901] Additional KoD packet checks.  HStenn.
 * [Sec 2936] Skeleton Key: Any system knowing the trusted key can serve
   time. Include passive servers in this check. HStenn.
 * [Bug 2879] Improve NTP security against timing attacks. perlinger at ntp.org

==== ntpd/ntp_proto.c ====
2016-01-23 12:54:31+00:00, stenn at psp-deb1.ntp.org +53 -0
  [Sec 2901] Additional KoD packet checks.  HStenn.

--- 1.375/ntpd/ntp_proto.c	2016-01-23 06:36:31 -05:00
+++ 1.376/ntpd/ntp_proto.c	2016-01-23 07:54:31 -05:00
@@ -1451,6 +1451,58 @@ receive(
 			return;
 		}
 
+	/*
+	 * Basic KoD validation checking:
+	 *
+	 * KoD packets are a mixed-blessing.  Forged KoD packets
+	 * are DoS attacks.  There are rare situations where we might
+	 * get a valid KoD response, though.  Since KoD packets are
+	 * a special case that can easily complicate the checks we do
+	 * next, we handle the special KoD cases here.
+	 *
+	 * Note that we expect the incoming KoD packet to have its
+	 * (nonzero) org, rec, and xmt timestamps set to the xmt timestamp
+	 * that we have previously sent out.  Watch interleave mode.
+	 */
+	} else if (0 == hisstratum) {
+		if (   L_ISZERO(&p_xmt)
+		    || L_ISZERO(&p_org)
+		    || L_ISZERO(&p_rec)) {
+			peer->bogusorg++;
+			msyslog(LOG_INFO,
+				"receive: KoD packet from %s has a zero xmt, org, or rec timestamp.  Ignoring.",
+				ntoa(&peer->srcadr));
+			return;
+		}
+
+		if (   !L_ISEQU(&p_xmt, &p_org)
+		    || !L_ISEQU(&p_xmt, &p_rec)) {
+			peer->bogusorg++;
+			msyslog(LOG_INFO,
+				"receive: KoD packet from %s has inconsistent xmt/org/rec timestamps.  Ignoring.",
+				ntoa(&peer->srcadr));
+			return;
+		}
+
+		/* Be conservative */
+		if (peer->flip == 0 && !L_ISEQU(&p_org, &peer->aorg)) {
+			peer->bogusorg++;
+			msyslog(LOG_INFO,
+				"receive: Unexpected KoD origin timestamp %#010x.%08x from %s does not match %#010x.%08x",
+				p_org.l_ui, p_org.l_uf,
+				ntoa(&peer->srcadr),
+				peer->aorg.l_ui, peer->aorg.l_uf);
+			return;
+		} else if (peer->flip == 1 && !L_ISEQU(&p_org, &peer->borg)) {
+			peer->bogusorg++;
+			msyslog(LOG_INFO,
+				"receive: Unexpected KoD origin timestamp %#010x.%08x from %s does not match interleave %#010x.%08x",
+				p_org.l_ui, p_org.l_uf,
+				ntoa(&peer->srcadr),
+				peer->borg.l_ui, peer->borg.l_uf);
+			return;
+		}
+	
 	/*
 	 * Basic mode checks:
 	 *
@@ -1470,6 +1522,7 @@ receive(
 	 * be from us, attempting to cause our server to KoD us.
 	 */
 	} else if (peer->flip == 0) {
+		/* HMS: we can simplify this now that we do KoD checks above */
 		if (0 < hisstratum && L_ISZERO(&p_org)) {
 			L_CLR(&peer->aorg);
 		} else if (    L_ISZERO(&peer->aorg)

#### ChangeSet ####
2016-01-23 11:36:37+00:00, stenn at psp-deb1.ntp.org
  [Sec 2901] KoD packets must have non-zero transmit timestamps.  HStenn.

==== ChangeLog ====
2016-01-23 11:36:23+00:00, stenn at psp-deb1.ntp.org +1 -0
  [Sec 2901] KoD packets must have non-zero transmit timestamps.  HStenn.

--- 1.1793.1.3/ChangeLog	2016-01-23 05:34:03 -05:00
+++ 1.1793.1.4/ChangeLog	2016-01-23 06:36:23 -05:00
@@ -1,5 +1,6 @@ 
 ---
 
+* [Sec 2901] KoD packets must have non-zero transmit timestamps.  HStenn.
 * [Sec 2936] Skeleton Key: Any system knowing the trusted key can serve
   time. Include passive servers in this check. HStenn.
 * [Bug 2879] Improve NTP security against timing attacks. perlinger at ntp.org

==== ntpd/ntp_proto.c ====
2016-01-23 11:36:31+00:00, stenn at psp-deb1.ntp.org +10 -0
  [Sec 2901] KoD packets must have non-zero transmit timestamps.  HStenn.

--- 1.374/ntpd/ntp_proto.c	2016-01-23 05:33:59 -05:00
+++ 1.375/ntpd/ntp_proto.c	2016-01-23 06:36:31 -05:00
@@ -1412,9 +1412,19 @@ receive(
 	 * Next comes a rigorous schedule of timestamp checking. If the
 	 * transmit timestamp is zero, the server has not initialized in
 	 * interleaved modes or is horribly broken.
+	 *
+	 * A KoD packet we pay attention to cannot have a 0 transmit
+	 * timestamp.
 	 */
 	if (L_ISZERO(&p_xmt)) {
 		peer->flash |= TEST3;			/* unsynch */
+		if (0 == hisstratum) {
+			peer->bogusorg++;	/* for TEST2 or TEST3 */
+			msyslog(LOG_INFO,
+				"receive: Unexpected zero transmit timestamp in KoD from %s",
+				ntoa(&peer->srcadr));
+			return;
+		}
 
 	/*
 	 * If the transmit timestamp duplicates a previous one, the

#### ChangeSet ####
2016-01-23 10:34:17+00:00, stenn at psp-deb1.ntp.org
  [Sec 2936] Skeleton Key: Any system knowing the trusted key can serve time. Include passive servers in this check. HStenn.

==== ChangeLog ====
2016-01-23 10:34:03+00:00, stenn at psp-deb1.ntp.org +2 -0
  [Sec 2936] Skeleton Key: Any system knowing the trusted key can serve time. Include passive servers in this check. HStenn.

--- 1.1793.1.2/ChangeLog	2016-01-21 02:35:44 -05:00
+++ 1.1793.1.3/ChangeLog	2016-01-23 05:34:03 -05:00
@@ -1,5 +1,7 @@ 
 ---
 
+* [Sec 2936] Skeleton Key: Any system knowing the trusted key can serve
+  time. Include passive servers in this check. HStenn.
 * [Bug 2879] Improve NTP security against timing attacks. perlinger at ntp.org
   - integrated patches by Loganaden Velvidron <logan at ntp.org>
     with some modifications & unit tests

==== ntpd/ntp_proto.c ====
2016-01-23 10:33:59+00:00, stenn at psp-deb1.ntp.org +1 -1
  [Sec 2936] Skeleton Key: Any system knowing the trusted key can serve time. Include passive servers in this check. HStenn.

--- 1.373/ntpd/ntp_proto.c	2016-01-18 06:54:51 -05:00
+++ 1.374/ntpd/ntp_proto.c	2016-01-23 05:33:59 -05:00
@@ -1610,6 +1610,7 @@ receive(
 	    case MODE_SERVER:		/* server mode */
 	    case MODE_BROADCAST:	/* broadcast mode */
 	    case MODE_ACTIVE:		/* symmetric active mode */
+	    case MODE_PASSIVE:		/* symmetric passive mode */
 		if (   is_authentic == AUTH_OK
 		    && !authistrustedip(skeyid, &peer->srcadr)) {
 			report_event(PEVNT_AUTH, peer, "authIP");
@@ -1619,7 +1620,6 @@ receive(
 	    	break;
 
 	    case MODE_UNSPEC:		/* unspecified (old version) */
-	    case MODE_PASSIVE:		/* symmetric passive mode */
 	    case MODE_CLIENT:		/* client mode */
 #if 0		/* At this point, MODE_CONTROL is overloaded by MODE_BCLIENT */
 	    case MODE_CONTROL:		/* control mode */

#### ChangeSet ####
2016-01-21 00:47:12-08:00, harlan at nb7-a.pfcs.com
  [Bug 2858] bool support.  Use stdbool.h when available.  HStenn.

==== ChangeLog ====
2016-01-21 00:45:28-08:00, harlan at nb7-a.pfcs.com +4 -0
  [Bug 2858] bool support.  Use stdbool.h when available.  HStenn.

--- 1.1793/ChangeLog	2016-01-20 04:20:05 -05:00
+++ 1.1793.2.1/ChangeLog	2016-01-21 03:45:28 -05:00
@@ -1,3 +1,7 @@ 
+---
+
+* [Bug 2858] bool support.  Use stdbool.h when available.  HStenn.
+
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>
 

==== configure.ac ====
2016-01-21 00:45:29-08:00, harlan at nb7-a.pfcs.com +3 -1
  [Bug 2858] bool support.  Use stdbool.h when available.  HStenn.

--- 1.602/configure.ac	2015-09-29 06:09:15 -04:00
+++ 1.603/configure.ac	2016-01-21 03:45:29 -05:00
@@ -302,7 +302,9 @@ AC_CHECK_HEADERS([sgtty.h stdatomic.h st
 AC_CHECK_HEADERS([fcntl.h fnmatch.h ieeefp.h inttypes.h kvm.h math.h])
 
 AC_CHECK_HEADERS([memory.h netdb.h poll.h])
-AC_CHECK_HEADERS([sgtty.h stdatomic.h stdlib.h string.h termio.h])
+AC_CHECK_HEADERS([sgtty.h stdatomic.h])
+AC_HEADER_STDBOOL
+AC_CHECK_HEADERS([stdlib.h string.h termio.h])
 AC_CHECK_HEADERS([termios.h timepps.h timex.h unistd.h])
 
 case "$host" in

==== include/ntp_types.h ====
2016-01-21 00:45:39-08:00, harlan at nb7-a.pfcs.com +7 -0
  [Bug 2858] bool support.  Use stdbool.h when available.  HStenn.

--- 1.36/include/ntp_types.h	2016-01-18 06:54:24 -05:00
+++ 1.37/include/ntp_types.h	2016-01-21 03:45:39 -05:00
@@ -35,6 +35,13 @@ 
 # define	FALSE	0
 #endif
 
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+typedef int bool;	/* Can't use enum TRUE/FALSE because of above */
+#endif
+
+
 /*
  * This is another naming conflict.
  * On NetBSD for MAC the macro "mac" is defined as 1

==== tests/libntp/lfpfunc.c ====
2016-01-21 00:46:31-08:00, harlan at nb7-a.pfcs.com +0 -3
  [Bug 2858] bool support.  Use stdbool.h when available.  HStenn.

--- 1.15/tests/libntp/lfpfunc.c	2015-11-20 02:27:04 -05:00
+++ 1.16/tests/libntp/lfpfunc.c	2016-01-21 03:46:31 -05:00
@@ -21,9 +21,6 @@ typedef int bool; // typedef enum { FALS
 }
 
 
-typedef int bool; // typedef enum { FALSE, TRUE } boolean; -> can't use this because TRUE and FALSE are already defined
-
-
 typedef struct  {
 	uint32_t h, l;
 } lfp_hl;

==== tests/libntp/run-lfpfunc.c ====
2016-01-21 00:46:34-08:00, harlan at nb7-a.pfcs.com +9 -9
  [Bug 2858] bool support.  Use stdbool.h when available.  HStenn.

--- 1.18/tests/libntp/run-lfpfunc.c	2015-11-20 02:27:04 -05:00
+++ 1.19/tests/libntp/run-lfpfunc.c	2016-01-21 03:46:34 -05:00
@@ -58,15 +58,15 @@ int main(int argc, char *argv[])
 {
   progname = argv[0];
   UnityBegin("lfpfunc.c");
-  RUN_TEST(test_AdditionLR, 51);
-  RUN_TEST(test_AdditionRL, 52);
-  RUN_TEST(test_SubtractionLR, 53);
-  RUN_TEST(test_SubtractionRL, 54);
-  RUN_TEST(test_Negation, 55);
-  RUN_TEST(test_Absolute, 56);
-  RUN_TEST(test_FDF_RoundTrip, 57);
-  RUN_TEST(test_SignedRelOps, 58);
-  RUN_TEST(test_UnsignedRelOps, 59);
+  RUN_TEST(test_AdditionLR, 48);
+  RUN_TEST(test_AdditionRL, 49);
+  RUN_TEST(test_SubtractionLR, 50);
+  RUN_TEST(test_SubtractionRL, 51);
+  RUN_TEST(test_Negation, 52);
+  RUN_TEST(test_Absolute, 53);
+  RUN_TEST(test_FDF_RoundTrip, 54);
+  RUN_TEST(test_SignedRelOps, 55);
+  RUN_TEST(test_UnsignedRelOps, 56);
 
   return (UnityEnd());
 }

==== tests/libntp/run-timevalops.c ====
2016-01-21 00:46:35-08:00, harlan at nb7-a.pfcs.com +28 -28
  [Bug 2858] bool support.  Use stdbool.h when available.  HStenn.

--- 1.13/tests/libntp/run-timevalops.c	2015-11-20 22:39:53 -05:00
+++ 1.14/tests/libntp/run-timevalops.c	2016-01-21 03:46:35 -05:00
@@ -77,34 +77,34 @@ int main(int argc, char *argv[])
 {
   progname = argv[0];
   UnityBegin("timevalops.c");
-  RUN_TEST(test_Helpers1, 39);
-  RUN_TEST(test_Normalise, 40);
-  RUN_TEST(test_SignNoFrac, 41);
-  RUN_TEST(test_SignWithFrac, 42);
-  RUN_TEST(test_CmpFracEQ, 43);
-  RUN_TEST(test_CmpFracGT, 44);
-  RUN_TEST(test_CmpFracLT, 45);
-  RUN_TEST(test_AddFullNorm, 46);
-  RUN_TEST(test_AddFullOflow1, 47);
-  RUN_TEST(test_AddUsecNorm, 48);
-  RUN_TEST(test_AddUsecOflow1, 49);
-  RUN_TEST(test_SubFullNorm, 50);
-  RUN_TEST(test_SubFullOflow, 51);
-  RUN_TEST(test_SubUsecNorm, 52);
-  RUN_TEST(test_SubUsecOflow, 53);
-  RUN_TEST(test_Neg, 54);
-  RUN_TEST(test_AbsNoFrac, 55);
-  RUN_TEST(test_AbsWithFrac, 56);
-  RUN_TEST(test_Helpers2, 57);
-  RUN_TEST(test_ToLFPbittest, 58);
-  RUN_TEST(test_ToLFPrelPos, 59);
-  RUN_TEST(test_ToLFPrelNeg, 60);
-  RUN_TEST(test_ToLFPabs, 61);
-  RUN_TEST(test_FromLFPbittest, 62);
-  RUN_TEST(test_FromLFPrelPos, 63);
-  RUN_TEST(test_FromLFPrelNeg, 64);
-  RUN_TEST(test_LFProundtrip, 65);
-  RUN_TEST(test_ToString, 66);
+  RUN_TEST(test_Helpers1, 37);
+  RUN_TEST(test_Normalise, 38);
+  RUN_TEST(test_SignNoFrac, 39);
+  RUN_TEST(test_SignWithFrac, 40);
+  RUN_TEST(test_CmpFracEQ, 41);
+  RUN_TEST(test_CmpFracGT, 42);
+  RUN_TEST(test_CmpFracLT, 43);
+  RUN_TEST(test_AddFullNorm, 44);
+  RUN_TEST(test_AddFullOflow1, 45);
+  RUN_TEST(test_AddUsecNorm, 46);
+  RUN_TEST(test_AddUsecOflow1, 47);
+  RUN_TEST(test_SubFullNorm, 48);
+  RUN_TEST(test_SubFullOflow, 49);
+  RUN_TEST(test_SubUsecNorm, 50);
+  RUN_TEST(test_SubUsecOflow, 51);
+  RUN_TEST(test_Neg, 52);
+  RUN_TEST(test_AbsNoFrac, 53);
+  RUN_TEST(test_AbsWithFrac, 54);
+  RUN_TEST(test_Helpers2, 55);
+  RUN_TEST(test_ToLFPbittest, 56);
+  RUN_TEST(test_ToLFPrelPos, 57);
+  RUN_TEST(test_ToLFPrelNeg, 58);
+  RUN_TEST(test_ToLFPabs, 59);
+  RUN_TEST(test_FromLFPbittest, 60);
+  RUN_TEST(test_FromLFPrelPos, 61);
+  RUN_TEST(test_FromLFPrelNeg, 62);
+  RUN_TEST(test_LFProundtrip, 63);
+  RUN_TEST(test_ToString, 64);
 
   return (UnityEnd());
 }

==== tests/libntp/timespecops.c ====
2016-01-21 00:46:36-08:00, harlan at nb7-a.pfcs.com +0 -2
  [Bug 2858] bool support.  Use stdbool.h when available.  HStenn.

--- 1.10/tests/libntp/timespecops.c	2015-11-20 22:39:53 -05:00
+++ 1.11/tests/libntp/timespecops.c	2016-01-21 03:46:36 -05:00
@@ -63,8 +63,6 @@ typedef int bool;
 void test_LFProundtrip(void);
 void test_ToString(void);
 
-typedef int bool;
-
 const bool	timespec_isValid(struct timespec V);
 struct timespec timespec_init(time_t hi, long lo);
 l_fp		l_fp_init(int32 i, u_int32 f);

==== tests/libntp/timevalops.c ====
2016-01-21 00:46:36-08:00, harlan at nb7-a.pfcs.com +0 -2
  [Bug 2858] bool support.  Use stdbool.h when available.  HStenn.

--- 1.13/tests/libntp/timevalops.c	2015-11-20 22:39:53 -05:00
+++ 1.14/tests/libntp/timevalops.c	2016-01-21 03:46:36 -05:00
@@ -27,8 +27,6 @@ typedef int bool;
 	u_int32	frac;
 } lfpfracdata ;
 
-typedef int bool;
-
 struct timeval timeval_init( time_t hi, long lo);
 const bool timeval_isValid(struct timeval V);
 l_fp l_fp_init(int32 i, u_int32 f);

#### ChangeSet ####
2016-01-21 07:35:48+00:00, stenn at psp-deb1.ntp.org
  merge cleanup

==== ChangeLog ====
2016-01-21 07:35:44+00:00, stenn at psp-deb1.ntp.org +7 -3
  merge cleanup

--- 1.1793.1.1/ChangeLog	2016-01-21 01:13:40 -05:00
+++ 1.1793.1.2/ChangeLog	2016-01-21 02:35:44 -05:00
@@ -1,3 +1,9 @@ 
+---
+
+* [Bug 2879] Improve NTP security against timing attacks. perlinger at ntp.org
+  - integrated patches by Loganaden Velvidron <logan at ntp.org>
+    with some modifications & unit tests
+
 ---
 (4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn at ntp.org>
 
@@ -53,9 +59,6 @@ 
 * CID 1341682: Nit in libntp/authreadkeys.c.  HStenn.
 * CID 1341684: Nit in tests/ntpd/t-ntp_signd.c.  HStenn.
 * [Bug 2829] Look at pipe_fds in ntpd.c  (did so. perlinger at ntp.org)
-* [Bug 2879] Improve NTP security against timing attacks. perlinger at ntp.org
-  - integrated patches by Loganaden Velvidron <loganaden at gmail.com>
-    with some modifications & unit tests
 * [Bug 2887] stratum -1 config results as showing value 99
   - fudge stratum should only accept values [0..16]. perlinger at ntp.org
 * [Bug 2932] Update leapsecond file info in miscopt.html.  CWoodbury, HStenn.
@@ -95,6 +98,7 @@ 
 * Update scripts/calc_tickadj/Makefile.am.  Harlan Stenn.
 
 ---
+(4.2.8p4) 2015/10/21 Released by Harlan Stenn <stenn at ntp.org>
 
 * [Sec 2899] CVE-2014-9297  perlinger at ntp.org
 * [Sec 2901] Drop invalid packet before checking KoD. Check for all KoD's.

#### ChangeSet ####
2015-12-12 10:24:19+00:00, perlinger at psp-deb1.ntp.org
  [Bug 2879] Improve NTP security against timing attacks.
   - use timing-safe memcmp() for digest tests

==== ChangeLog ====
2015-12-12 10:24:17+00:00, perlinger at psp-deb1.ntp.org +3 -0
  [Bug 2879] Improve NTP security against timing attacks.
   - use timing-safe memcmp() for digest test

--- 1.1786.1.1/ChangeLog	2015-12-06 06:19:58 -05:00
+++ 1.1786.5.1/ChangeLog	2015-12-12 05:24:17 -05:00
@@ -18,6 +18,9 @@ 
 * CID 1341682: Nit in libntp/authreadkeys.c.  HStenn.
 * CID 1341684: Nit in tests/ntpd/t-ntp_signd.c.  HStenn.
 * [Bug 2829] Look at pipe_fds in ntpd.c  (did so. perlinger at ntp.org)
+* [Bug 2879] Improve NTP security against timing attacks. perlinger at ntp.org
+  - integrated patches by Loganaden Velvidron <loganaden at gmail.com>
+    with some modifications & unit tests
 * [Bug 2887] stratum -1 config results as showing value 99
   - fudge stratum only accepts values [0..16]. perlinger at ntp.org
 * [Bug 2932] Update leapsecond file info in miscopt.html.  CWoodbury, HStenn.

==== lib/isc/hmacmd5.c ====
2015-12-12 10:24:17+00:00, perlinger at psp-deb1.ntp.org +1 -1
  [Bug 2879] Improve NTP security against timing attacks.
   - use timing-safe memcmp() for digest tests

--- 1.2/lib/isc/hmacmd5.c	2012-06-01 14:17:18 -04:00
+++ 1.3/lib/isc/hmacmd5.c	2015-12-12 05:24:17 -05:00
@@ -145,5 +145,5 @@ isc_hmacmd5_verify2(isc_hmacmd5_t *ctx, 
 
 	REQUIRE(len <= ISC_MD5_DIGESTLENGTH);
 	isc_hmacmd5_sign(ctx, newdigest);
-	return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+	return (ISC_TF(isc_tsmemcmp(digest, newdigest, len) == 0));
 }

==== lib/isc/hmacsha.c ====
2015-12-12 10:24:18+00:00, perlinger at psp-deb1.ntp.org +5 -5
  [Bug 2879] Improve NTP security against timing attacks.
   - use timing-safe memcmp() for digest tests

--- 1.2/lib/isc/hmacsha.c	2012-06-01 14:17:18 -04:00
+++ 1.3/lib/isc/hmacsha.c	2015-12-12 05:24:18 -05:00
@@ -538,7 +538,7 @@ isc_hmacsha1_verify(isc_hmacsha1_t *ctx,
 
 	REQUIRE(len <= ISC_SHA1_DIGESTLENGTH);
 	isc_hmacsha1_sign(ctx, newdigest, ISC_SHA1_DIGESTLENGTH);
-	return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+	return (ISC_TF(isc_tsmemcmp(digest, newdigest, len) == 0));
 }
 
 /*
@@ -551,7 +551,7 @@ isc_hmacsha224_verify(isc_hmacsha224_t *
 
 	REQUIRE(len <= ISC_SHA224_DIGESTLENGTH);
 	isc_hmacsha224_sign(ctx, newdigest, ISC_SHA224_DIGESTLENGTH);
-	return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+	return (ISC_TF(isc_tsmemcmp(digest, newdigest, len) == 0));
 }
 
 /*
@@ -564,7 +564,7 @@ isc_hmacsha256_verify(isc_hmacsha256_t *
 
 	REQUIRE(len <= ISC_SHA256_DIGESTLENGTH);
 	isc_hmacsha256_sign(ctx, newdigest, ISC_SHA256_DIGESTLENGTH);
-	return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+	return (ISC_TF(isc_tsmemcmp(digest, newdigest, len) == 0));
 }
 
 /*
@@ -577,7 +577,7 @@ isc_hmacsha384_verify(isc_hmacsha384_t *
 
 	REQUIRE(len <= ISC_SHA384_DIGESTLENGTH);
 	isc_hmacsha384_sign(ctx, newdigest, ISC_SHA384_DIGESTLENGTH);
-	return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+	return (ISC_TF(isc_tsmemcmp(digest, newdigest, len) == 0));
 }
 
 /*
@@ -590,5 +590,5 @@ isc_hmacsha512_verify(isc_hmacsha512_t *
 
 	REQUIRE(len <= ISC_SHA512_DIGESTLENGTH);
 	isc_hmacsha512_sign(ctx, newdigest, ISC_SHA512_DIGESTLENGTH);
-	return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+	return (ISC_TF(isc_tsmemcmp(digest, newdigest, len) == 0));
 }

==== lib/isc/include/isc/string.h ====
2015-12-12 10:24:18+00:00, perlinger at psp-deb1.ntp.org +18 -0
  [Bug 2879] Improve NTP security against timing attacks.
   - prototype for timing-safe 'isc_tsmemcmp()'

--- 1.4/lib/isc/include/isc/string.h	2009-09-24 11:50:40 -04:00
+++ 1.5/lib/isc/include/isc/string.h	2015-12-12 05:24:18 -05:00
@@ -199,6 +199,24 @@ char *
  *
  */
 
+int
+isc_tsmemcmp(const void *p1, const void *p2, size_t len);
+/*
+ * Lexicographic compare 'len' unsigned bytes from 'p1' and 'p2'
+ * like 'memcmp()'.
+ *
+ * This function is safe from timing attacks as it has a runtime that
+ * only depends on 'len' and has no early-out option.
+ *
+ * Use this to check MACs and other material that is security sensitive.
+ *
+ * Returns:
+ *  (let x be the byte offset of the first different byte)
+ *  -1 if (u_char)p1[x] < (u_char)p2[x]
+ *   1 if (u_char)p1[x] > (u_char)p2[x]
+ *   0 if byte series are equal
+ */
+
 char *
 isc_string_separate(char **stringp, const char *delim);
 

==== lib/isc/tsmemcmp.c ====
2015-12-12 10:24:18+00:00, perlinger at psp-deb1.ntp.org +55 -0
  [Bug 2879] Improve NTP security against timing attacks.
   - implement a timing safe (though less efficient) version of 'memcmp()'
     as 'isc_tsmemcmp()'

--- /dev/null	2016-04-26 19:53:05 -04:00
+++ 1.1/lib/isc/tsmemcmp.c	2015-12-12 05:24:18 -05:00
@@ -0,0 +1,55 @@ 
+/*
+ * Copyright (C) 2004-2007, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001, 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*! \file */
+
+#include <config.h>
+#include <limits.h>
+#include <isc/string.h>
+
+/* Making a portable memcmp that has no internal branches and loops always
+ * once for every byte without early-out shortcut has a few challenges.
+ *
+ * Inspired by 'timingsafe_memcmp()' from the BSD system and
+ * https://github.com/libressl-portable/openbsd/blob/master/src/lib/libc/string/timingsafe_memcmp.c
+ *
+ * Sadly, that one is not portable C: It makes assumptions on the representation
+ * of negative integers and assumes sign-preserving right-shift of negative
+ * signed values. This is a rewrite from scratch that should not suffer from
+ * such issues.
+ *
+ * 2015-12-12, J. Perlinger (perlinger-at-ntp-dot-org)
+ */
+int
+isc_tsmemcmp(const void *p1, const void *p2, size_t nb) {
+	const unsigned char *ucp1 = p1;
+	const unsigned char *ucp2 = p2;
+	unsigned int isLT = 0u;
+	unsigned int isGT = 0u;
+	volatile unsigned int mask = (1u << CHAR_BIT);
+
+	for (/*NOP*/; 0 != nb; --nb, ++ucp1, ++ucp2) {
+		isLT |= mask &
+		    ((unsigned int)*ucp1 - (unsigned int)*ucp2);
+		isGT |= mask &
+		    ((unsigned int)*ucp2 - (unsigned int)*ucp1);
+		mask &= ~(isLT | isGT);
+	}
+	return (int)(isGT >> CHAR_BIT) - (int)(isLT >> CHAR_BIT);
+}

==== lib/isc/tsmemcmp.c ====
2015-12-12 10:24:18+00:00, perlinger at psp-deb1.ntp.org +0 -0

==== libntp/Makefile.am ====
2015-12-12 10:24:18+00:00, perlinger at psp-deb1.ntp.org +1 -0
  [Bug 2879] Improve NTP security against timing attacks.
   - add new source file 'lib/isc/tsmemcmp.c'

--- 1.76/libntp/Makefile.am	2015-06-26 21:16:25 -04:00
+++ 1.77/libntp/Makefile.am	2015-12-12 05:24:18 -05:00
@@ -36,6 +36,7 @@ libisc_SRCS =								\
 	$(srcdir)/../lib/isc/unix/time.c				\
 	$(srcdir)/../lib/isc/sha1.c					\
 	$(srcdir)/../lib/isc/sockaddr.c					\
+	$(srcdir)/../lib/isc/tsmemcmp.c					\
 	$(NULL)
 
 if PTHREADS

==== libntp/a_md5encrypt.c ====
2015-12-12 10:24:18+00:00, perlinger at psp-deb1.ntp.org +2 -2
  [Bug 2879] Improve NTP security against timing attacks.
   - use timing-safe memcmp() for digest tests

--- 1.35/libntp/a_md5encrypt.c	2015-11-13 16:54:33 -05:00
+++ 1.36/libntp/a_md5encrypt.c	2015-12-12 05:24:18 -05:00
@@ -10,7 +10,7 @@ 
 #include "ntp_stdlib.h"
 #include "ntp.h"
 #include "ntp_md5.h"	/* provides OpenSSL digest API */
-
+#include "isc/string.h"
 /*
  * MD5authencrypt - generate message digest
  *
@@ -92,7 +92,7 @@ MD5authdecrypt(
 		    "MAC decrypt: MAC length error");
 		return (0);
 	}
-	return !memcmp(digest, (const char *)pkt + length + 4, len);
+	return !isc_tsmemcmp(digest, (const char *)pkt + length + 4, len);
 }
 
 /*

==== ports/winnt/vs2005/libntp.vcproj ====
2015-12-12 10:24:18+00:00, perlinger at psp-deb1.ntp.org +4 -0
  [Bug 2879] Improve NTP security against timing attacks.
   - add new source file 'lib/isc/tsmemcmp.c'

--- 1.24/ports/winnt/vs2005/libntp.vcproj	2015-03-30 13:10:12 -04:00
+++ 1.25/ports/winnt/vs2005/libntp.vcproj	2015-12-12 05:24:18 -05:00
@@ -533,6 +533,10 @@ 
 				>
 			</File>
 			<File
+				RelativePath="..\..\..\lib\isc\tsmemcmp.c"
+				>
+			</File>
+			<File
 				RelativePath="..\..\..\libntp\uglydate.c"
 				>
 			</File>

==== ports/winnt/vs2008/libntp/libntp.vcproj ====
2015-12-12 10:24:18+00:00, perlinger at psp-deb1.ntp.org +4 -0
  [Bug 2879] Improve NTP security against timing attacks.
   - add new source file 'lib/isc/tsmemcmp.c'

--- 1.54/ports/winnt/vs2008/libntp/libntp.vcproj	2015-04-19 06:38:29 -04:00
+++ 1.55/ports/winnt/vs2008/libntp/libntp.vcproj	2015-12-12 05:24:18 -05:00
@@ -648,6 +648,10 @@ 
 				>
 			</File>
 			<File
+				RelativePath="..\..\..\..\lib\isc\tsmemcmp.c"
+				>
+			</File>
+			<File
 				RelativePath="..\..\..\..\libntp\uglydate.c"
 				>
 			</File>

==== ports/winnt/vs2013/libntp/libntp.vcxproj ====
2015-12-12 10:24:18+00:00, perlinger at psp-deb1.ntp.org +3 -2
  [Bug 2879] Improve NTP security against timing attacks.
   - add new source file 'lib/isc/tsmemcmp.c'

--- 1.9/ports/winnt/vs2013/libntp/libntp.vcxproj	2015-11-13 16:54:34 -05:00
+++ 1.10/ports/winnt/vs2013/libntp/libntp.vcxproj	2015-12-12 05:24:18 -05:00
@@ -1,4 +1,4 @@ 
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup Label="ProjectConfigurations">
     <ProjectConfiguration Include="DebugXP|Win32">
@@ -295,6 +295,7 @@ 
     <ClCompile Include="..\..\..\..\lib\isc\sha1.c" />
     <ClCompile Include="..\..\..\..\lib\isc\sockaddr.c" />
     <ClCompile Include="..\..\..\..\lib\isc\task.c" />
+    <ClCompile Include="..\..\..\..\lib\isc\tsmemcmp.c" />
     <ClCompile Include="..\..\..\..\lib\isc\win32\condition.c" />
     <ClCompile Include="..\..\..\..\lib\isc\win32\interfaceiter.c" />
     <ClCompile Include="..\..\..\..\lib\isc\win32\net.c" />
@@ -426,4 +427,4 @@ 
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
\ No newline at end of file
+</Project>

==== ports/winnt/vs2013/libntp/libntp.vcxproj.filters ====
2015-12-12 10:24:18+00:00, perlinger at psp-deb1.ntp.org +5 -2
  [Bug 2879] Improve NTP security against timing attacks.
   - add new source file 'lib/isc/tsmemcmp.c'

--- 1.7/ports/winnt/vs2013/libntp/libntp.vcxproj.filters	2015-11-13 16:54:34 -05:00
+++ 1.8/ports/winnt/vs2013/libntp/libntp.vcxproj.filters	2015-12-12 05:24:18 -05:00
@@ -1,4 +1,4 @@ 
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
     <Filter Include="Source Files">
@@ -299,6 +299,9 @@ 
     <ClCompile Include="..\..\..\..\libntp\timevalops.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\..\libntp\tsmemcmp.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\..\..\..\libntp\uglydate.c">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -565,4 +568,4 @@ 
       <Filter>Resource Files</Filter>
     </CustomBuild>
   </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>

==== sntp/crypto.c ====
2015-12-12 10:24:18+00:00, perlinger at psp-deb1.ntp.org +2 -1
  [Bug 2879] Improve NTP security against timing attacks.
   - use timing-safe memcmp() for digest tests

--- 1.18/sntp/crypto.c	2014-12-29 01:09:11 -05:00
+++ 1.19/sntp/crypto.c	2015-12-12 05:24:18 -05:00
@@ -1,6 +1,7 @@ 
 #include <config.h>
 #include "crypto.h"
 #include <ctype.h>
+#include "isc/string.h"
 
 struct key *key_ptr;
 size_t key_cnt = 0;
@@ -58,7 +59,7 @@ auth_md5(
 	if (!hash_len)
 		authentic = FALSE;
 	else
-		authentic = !memcmp(digest, pkt_data + pkt_size + 4,
+		authentic = !isc_tsmemcmp(digest, pkt_data + pkt_size + 4,
 				    hash_len);
 	return authentic;
 }

==== tests/libntp/Makefile.am ====
2015-12-12 10:24:18+00:00, perlinger at psp-deb1.ntp.org +12 -0
  [Bug 2879] Improve NTP security against timing attacks.
   - add unit test for timing-safe memcmp

--- 1.93/tests/libntp/Makefile.am	2015-09-16 07:09:35 -04:00
+++ 1.94/tests/libntp/Makefile.am	2015-12-12 05:24:18 -05:00
@@ -42,6 +42,7 @@ check_PROGRAMS =		\
 	test-strtolfp		\
 	test-timespecops	\
 	test-timevalops		\
+	test-tsafememcmp	\
 	test-tstotv		\
 	test-tvtots		\
 	test-uglydate		\
@@ -102,6 +103,7 @@ BUILT_SOURCES +=			\
 	$(srcdir)/run-strtolfp.c	\
 	$(srcdir)/run-timevalops.c	\
 	$(srcdir)/run-timespecops.c	\
+	$(srcdir)/run-tsafememcmp.c	\
 	$(srcdir)/run-tstotv.c		\
 	$(srcdir)/run-tvtots.c		\
 	$(srcdir)/run-uglydate.c	\
@@ -477,6 +479,16 @@ test_tstotv_SOURCES =		\
 
 ###
 
+test_tsafememcmp_SOURCES =	\
+	tsafememcmp.c		\
+	run-tsafememcmp.c	\
+	$(NULL)
+
+$(srcdir)/run-tsafememcmp.c: $(srcdir)/tsafememcmp.c $(std_unity_list)
+	$(run_unity) tsafememcmp.c run-tsafememcmp.c
+
+###
+
 test_tstotv_SOURCES =		\
 	tstotv.c		\
 	run-tstotv.c		\

==== tests/libntp/run-tsafememcmp.c ====
2015-12-12 10:24:18+00:00, perlinger at psp-deb1.ntp.org +64 -0
  [Bug 2879] Improve NTP security against timing attacks.
   - auto-generated test runner

--- /dev/null	2016-04-26 19:53:05 -04:00
+++ 1.1/tests/libntp/run-tsafememcmp.c	2015-12-12 05:24:18 -05:00
@@ -0,0 +1,64 @@ 
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+//=======Test Runner Used To Run Each Test Below=====
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+  Unity.CurrentTestName = #TestFunc; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  if (TEST_PROTECT()) \
+  { \
+      setUp(); \
+      TestFunc(); \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+  } \
+  UnityConcludeTest(); \
+}
+
+//=======Automagically Detected Files To Include=====
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "config.h"
+#include "ntp_stdlib.h"
+#include "isc/string.h"
+
+//=======External Functions This Runner Calls=====
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_Empty(void);
+extern void test_Equal(void);
+extern void test_FirstByte(void);
+extern void test_LastByte(void);
+extern void test_MiddleByte(void);
+extern void test_MiddleByteUpLo(void);
+
+
+//=======Test Reset Option=====
+void resetTest(void);
+void resetTest(void)
+{
+  tearDown();
+  setUp();
+}
+
+char const *progname;
+
+
+//=======MAIN=====
+int main(int argc, char *argv[])
+{
+  progname = argv[0];
+  UnityBegin("tsafememcmp.c");
+  RUN_TEST(test_Empty, 10);
+  RUN_TEST(test_Equal, 11);
+  RUN_TEST(test_FirstByte, 12);
+  RUN_TEST(test_LastByte, 13);
+  RUN_TEST(test_MiddleByte, 14);
+  RUN_TEST(test_MiddleByteUpLo, 15);
+
+  return (UnityEnd());
+}

==== tests/libntp/run-tsafememcmp.c ====
2015-12-12 10:24:18+00:00, perlinger at psp-deb1.ntp.org +0 -0

==== tests/libntp/tsafememcmp.c ====
2015-12-12 10:24:18+00:00, perlinger at psp-deb1.ntp.org +85 -0
  [Bug 2879] Improve NTP security against timing attacks.
   - unit tests for timing-safe memcmp

--- /dev/null	2016-04-26 19:53:05 -04:00
+++ 1.1/tests/libntp/tsafememcmp.c	2015-12-12 05:24:18 -05:00
@@ -0,0 +1,85 @@ 
+#include "config.h"
+
+#include "ntp_stdlib.h"
+#include "isc/string.h"
+
+#include "unity.h"
+
+/* Basisc test for timingsafe_memcmp() */
+
+void test_Empty(void);
+void test_Equal(void);
+void test_FirstByte(void);
+void test_LastByte(void);
+void test_MiddleByte(void);
+void test_MiddleByteUpLo(void);
+
+void test_Empty(void)
+{
+	static const char dummy[1];
+	TEST_ASSERT_EQUAL_INT(0, isc_tsmemcmp(NULL , NULL , 0));
+	TEST_ASSERT_EQUAL_INT(0, isc_tsmemcmp(dummy, dummy, 0));
+}
+
+void test_Equal(void)
+{
+	static const char dummy[2][4] = {
+		"blob", "blob"
+	};
+	TEST_ASSERT_EQUAL_INT(0, isc_tsmemcmp(dummy[0],
+					      dummy[1],
+					      sizeof(dummy[0])));
+}
+
+void test_FirstByte(void)
+{
+	static const char dummy[2][4] = {
+		"Blob", "Clob"
+	};
+	TEST_ASSERT_EQUAL_INT(-1, isc_tsmemcmp(dummy[0],
+					       dummy[1],
+					       sizeof(dummy[0])));
+	TEST_ASSERT_EQUAL_INT( 1, isc_tsmemcmp(dummy[1],
+					       dummy[0],
+					       sizeof(dummy[0])));
+}
+
+void test_LastByte(void)
+{
+	static const char dummy[2][4] = {
+		"Blob", "Bloc"
+	};
+	TEST_ASSERT_EQUAL_INT(-1, isc_tsmemcmp(dummy[0],
+					       dummy[1],
+					       sizeof(dummy[0])));
+	TEST_ASSERT_EQUAL_INT( 1, isc_tsmemcmp(dummy[1],
+					       dummy[0],
+					       sizeof(dummy[0])));
+}
+
+void test_MiddleByte(void)
+{
+	static const char dummy[2][4] = {
+		"Blob", "Blpb"
+	};
+	TEST_ASSERT_EQUAL_INT(-1, isc_tsmemcmp(dummy[0],
+					       dummy[1],
+					       sizeof(dummy[0])));
+	TEST_ASSERT_EQUAL_INT( 1, isc_tsmemcmp(dummy[1],
+					       dummy[0],
+					       sizeof(dummy[0])));
+}
+
+void test_MiddleByteUpLo(void)
+{
+	static const char dummy[2][4] = {
+		"Blob", "Blpa"
+	};
+	TEST_ASSERT_EQUAL_INT(-1, isc_tsmemcmp(dummy[0],
+					       dummy[1],
+					       sizeof(dummy[0])));
+	TEST_ASSERT_EQUAL_INT( 1, isc_tsmemcmp(dummy[1],
+					       dummy[0],
+					       sizeof(dummy[0])));
+}
+

==== tests/libntp/tsafememcmp.c ====
2015-12-12 10:24:18+00:00, perlinger at psp-deb1.ntp.org +0 -0


More information about the bk-ntp-stable-send mailing list