]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
Changes from Dave Mills: in/out-bound data rates, leapsecond cleanup, driftfile write...
authorHarlan Stenn <stenn@ntp.org>
Mon, 23 Jul 2007 05:34:01 +0000 (01:34 -0400)
committerHarlan Stenn <stenn@ntp.org>
Mon, 23 Jul 2007 05:34:01 +0000 (01:34 -0400)
bk: 46a43dc9042Z5FnO52ZjVUNUD_XIMw

21 files changed:
ChangeLog
html/confopt.html
html/drivers/driver6.html
html/index.html
html/miscopt.html
html/ntpd.html
html/ntpdc.html
html/scripts/links7.txt
include/ntp.h
include/ntp_control.h
include/ntp_crypto.h
include/ntpd.h
ntpd/ntp_config.c
ntpd/ntp_control.c
ntpd/ntp_crypto.c
ntpd/ntp_loopfilter.c
ntpd/ntp_peer.c
ntpd/ntp_proto.c
ntpd/ntp_timer.c
ntpd/ntp_util.c
ntpd/refclock_acts.c

index efc946982bd48c0eff4eabab0ff074599f0461dc..289e2054e238986a0e4a01b2bc37045e385221ba 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,5 @@
+* Changes from Dave Mills: in/out-bound data rates, leapsecond cleanup,
+  driftfile write cleanup, packet buffer length checks, documentation updates.
 * More assertion checks and malloc()->emalloc(), courtesy of Calysto.
 * [Bug 864] Place ntpd service in maintenance mode if using SMF on Solaris
 * [Bug 862] includefile nesting; preserve phonelist on reconfig.
index e2a04c47cd6693567d966323b3279d1bba39fae1..aeb522d101196bd53fe78b3ef27ffb079ab9efb2 100644 (file)
@@ -64,6 +64,8 @@
                        <dd>This option is used only with broadcast server and manycast client modes. It specifies the time-to-live <i><tt>ttl</tt></i> to use on broadcast server and multicast server and the maximum <i><tt>ttl</tt></i> for the expanding ring search with manycast client packets. Selection of the proper value, which defaults to 127, is something of a black art and should be coordinated with the network administrator.
                        <dt><tt>version <i>version</i></tt>
                        <dd>Specifies the version number to be used for outgoing NTP packets. Versions 1-4 are the choices, with version 4 the default. This option is valid only with the <tt>server,</tt> <tt>peer</tt> and <tt>broadcast</tt> commands.
+                       <dt><tt>dynamic</tt>
+                       <dd>Allows a server/peer to be configured even if it is not reachable at configuration time. It is assumed that at some point in the future the network environment changes so that this server/peer can be reached. This option is useful to configure servers/peers on mobile systems with intermittent network access (e.g. wlan clients).
                </dl>
                <h4 id="aux">Auxilliary Commands</h4>
                <dl>
index 811a13f81acba713351ea65782d247d2e3a156f2..eb12bdd39f99181b4a11f82adbb870d359ecfaac 100644 (file)
                <p>Cycle crossings relative to the corrected slice level determine the width of each pulse and its value - zero, one or position identifier (PI). The data encode ten characters (20 BCD digits) which determine the second, minute, hour and day of the year and with some IRIG&nbsp;generators the year and synchronization condition. The comb filter exponentially averages the corresponding samples of successive baud intervals in order to reliably identify the reference carrier cycle.</p>
                <p>A type-II phase-lock loop (PLL) performs additional integration and interpolation to accurately determine the zero crossing of that cycle, which determines the reference timestamp. A pulse-width discriminator demodulates the data pulses, which are then encoded as the BCD digits of the timecode. The timecode and reference timestamp are updated once each second with IRIG-B (ten seconds with IRIG-E) and local clock offset samples saved for later processing. At poll intervals of 64 s, the saved samples are processed by a median filter and used to update the system clock.</p>
                <h4>Monitor Data</h4>
-               
-               
-               The timecode format used for debugging and data recording includes data helpful in diagnosing problems with the IRIG signal and codec connections. With debugging enabled (<tt>-d</tt> on the <tt>ntpd</tt> command line), the driver produces one line for each timecode in the following format:
-               <p><tt>00 1 98 23 19:26:52 721 143 0.694 20 0.3 66.5 3094572411.00027</tt></p>
-               <p>The first field containes the error flags in hex, where the hex bits are interpreted as below. This is followed by the IRIG status indicator, year of century, day of year and time of day. Note that the time of day is for the previous minute, not the current time. The status indicator and year are not produced by some IRIG devices and appear as zeros. Following these fields are the carrier amplitude (0-6000), codec gain (0-255), modulation index (0-1), time constant (4-20), carrier phase error (0&plusmn;0.5) and carrier frequency error (PPM). The last field is the on-time timestamp in NTP format.</p>
+               The timecode format used for debugging and data recording includes data helpful in diagnosing problems with the IRIG signal and codec connections. The driver produces one line for each timecode in the following format:
+               <p><tt>00 00 98 23 19:26:52 2782 143 0.694 10 0.3 66.5 3094572411.00027</tt></p>
+               <p>If clockstats is enabled, the most recent line is written to the clockstats file every 64 s. If verbose recording is enabled (fudge flag 4) each line is written as generated.</p>
+               <p>The first field containes the error flags in hex, where the hex bits are interpreted as below. This is followed by the year of century, day of year and time of day. Note that the time of day is for the previous minute, not the current time. The status indicator and year are not produced by some IRIG devices and appear as zeros. Following these fields are the carrier amplitude (0-3000), codec gain (0-255), modulation index (0-1), time constant (4-10), carrier phase error (0&plusmn;0.5) and carrier frequency error (PPM). The last field is the on-time timestamp in NTP format.</p>
                <p>The error flags are defined as follows in hex:</p>
                <dl>
                        <dt><tt>x01</tt>
index 5c19313176e3056d807680ab95610361ce7d0352..d41a2f6e3d904d3ce0e6681018e2b567fe1be4ff 100644 (file)
@@ -13,7 +13,7 @@
                <h3>The Network Time Protocol (NTP) Distribution</h3>
                <img src="pic/barnstable.gif" alt="gif" align="left"><a href="http://www.eecis.udel.edu/%7emills/pictures.html"><i>P.T. Bridgeport Bear</i>; from <i>Pogo</i>, Walt Kelly</a>
                <p>Pleased to meet you.</p>
-               <p>Last update: <csobj format="ShortTime" h="25" locale="00000409" region="0" t="DateTime" w="61">18:39</csobj> UTC <csobj format="LongDate" h="25" locale="00000409" region="0" t="DateTime" w="246">Thursday, July 28, 2005</csobj></p>
+               <p>Last update: <csobj format="ShortTime" h="25" locale="00000409" region="0" t="DateTime" w="61">03:09</csobj> UTC <csobj format="LongDate" h="25" locale="00000409" region="0" t="DateTime" w="223">Friday, June 22, 2007</csobj></p>
                <br clear="left">
                <h4>Related Links</h4>
                <script type="text/javascript" language="javascript" src="scripts/links7.txt"></script>
@@ -58,7 +58,7 @@
                        <li class="inline"><a href="tickadj.html"><tt>tickadj</tt> - set time-related kernel variables</a>
                        <li class="inline"><a href="ntptime.html"><tt>ntptime</tt> - read kernel time variables</a>
                        <li class="inline"><a href="keygen.html"><tt>ntp-keygen</tt> - generate public and private keys</a>
-                       <li class="inline"><a href="ntpdsim.html"><tt>ntpdsim</tt> - Network Time Protocol (NTP) simulator</a>
+                       <li class="inline"><a href="ntpdsim_new.html"><tt>ntpdsim</tt> - Network Time Protocol (NTP) simulator</a>
                </ul>
                <h4 id="docs">Supporting Documentation</h4>
                <ul>
index 54041b1979d2585117a2582b13db225e42b622e5..bf48150761e6d506077df0a09737c69e53d68b0b 100644 (file)
@@ -12,7 +12,7 @@
                <h3>Miscellaneous Options</h3>
                <img src="pic/boom3.gif" alt="gif" align="left"><a href="http://www.eecis.udel.edu/~mills/pictures.html">from <i>Pogo</i>, Walt Kelly</a>
                <p>We have three, now looking for more.</p>
-               <p>Last update: <csobj format="ShortTime" h="25" locale="00000409" region="0" t="DateTime" w="61">18:50</csobj> UTC <csobj format="LongDate" h="25" locale="00000409" region="0" t="DateTime" w="271">Monday, January 09, 2006</csobj></p>
+               <p>Last update: <csobj format="ShortTime" h="25" locale="00000409" region="0" t="DateTime" w="61">16:01</csobj> UTC <csobj format="LongDate" h="25" locale="00000409" region="0" t="DateTime" w="268">Wednesday, July 18, 2007</csobj></p>
                <br clear="left">
                <h4>Related Links</h4>
                <script type="text/javascript" language="javascript" src="scripts/links7.txt"></script>
                        <dd>The broadcast and multicast modes require a special calibration to determine the network delay between the local and remote servers. Ordinarily, this is done automatically by the initial protocol exchanges between the client and server. In some cases, the calibration procedure may fail due to network or server access controls, for example. This command specifies the default delay to be used under these circumstances. Typically (for Ethernet), a number between 0.003 and 0.007 seconds is appropriate. The default when this command is not used is 0.004 seconds.
                        <dt><tt>calldelay <i>delay</i></tt>
                        <dd>This option controls the delay in seconds between the first and second packets sent in burst or iburst mode to allow additional time for a modem or ISDN call to complete.
-                       <dt><tt>driftfile <i>driftfile</i> [<i>
-               minutes </i> [<i> tolerance </i>] ]</tt>
+                       <dt><tt>driftfile <i>driftfile</i> { <i>tolerance</i> ]</tt>
                        <dd>This command specifies the complete path and name of the file used to record the frequency of the local clock oscillator. This is the same operation as the <tt>-f</tt> command linke option. If the file exists, it is read at startup in order to set the initial frequency and then updated once per hour with the current frequency computed by the daemon. If the file name is specified, but the file itself does not exist, the starts with an initial frequency of zero and creates the file when writing it for the first time. If this command is not given, the daemon will always start with an initial frequency of zero.
                                <p>The file format consists of a single line containing a single floating point number, which records the frequency offset measured in parts-per-million (PPM). The file is updated by first writing the current drift value into a temporary file and then renaming this file to replace the old version. This implies that <tt>ntpd</tt> must have write permission for the directory the drift file is located in, and that file system links, symbolic or otherwise, should be avoided.</p>
                        
-<p>The two optional values determine how often the file is written, and
-are particuarly useful when is it desirable to avoid spinning up the
-disk unnecessarily.  The parameter <tt>minutes</tt> is how often the file will be written.  If omitted or less
-than 1, the interval will be 60 minutes (one hour).  The parameter <tt>tolerance</tt> is the
-threshold to skip writing the new value.  If the new value is within
-<tt>tolerance</tt> percent of the last value written (compared out to 3
-decimal places), the write will be
-skipped. The default is 0.0, which means that the write will occur
-unless the current and previous values are the same.  A tolerance of
-.1 equates roughly to a difference in the 2nd decimal place.</p>
+<p>The parameter <tt>tolerance</tt> is the wander threshold to skip writing the new value. If the value of wander computed from recent frequency changes is greater than this threshold the file will be updated once per hour. If below the threshold, the file will not be written.</p>
 <dt><tt>enable [ auth | bclient | calibrate | kernel | monitor | ntp | pps | stats]</tt><br>
                                <tt>disable [ auth | bclient | calibrate | kernel | monitor | ntp | pps | stats ]</tt>
                        <dd>Provides a way to enable or disable various system options. Flags not mentioned are unaffected. Note that all of these flags can be controlled remotely using the <a href="ntpdc.html"><tt>ntpdc</tt></a> utility program.
index 3b70694a6efd72f4b6484fe20dff7773d377b43a..c27b6a364f318c88b62ec818768f0a51d6a141bc 100644 (file)
@@ -13,7 +13,7 @@
                <h3><tt>ntpd</tt> - Network Time Protocol (NTP) daemon</h3>
                <img src="pic/alice47.gif" alt="gif" align="left"><a href="http://www.eecis.udel.edu/~mills/pictures.html">from <i>Alice's Adventures in Wonderland</i>, Lewis Carroll</a>
                <p>The mushroom knows all the command line options.</p>
-               <p>Last update: <csobj format="ShortTime" h="25" locale="00000409" region="0" t="DateTime" w="61">18:44</csobj> UTC <csobj format="LongDate" h="25" locale="00000409" region="0" t="DateTime" w="246">Thursday, July 28, 2005</csobj></p>
+               <p>Last update: <csobj format="ShortTime" h="25" locale="00000409" region="0" t="DateTime" w="61">19:27</csobj> UTC <csobj format="LongDate" h="25" locale="00000409" region="0" t="DateTime" w="229">Sunday, July 01, 2007</csobj></p>
                <br clear="left">
                <h4>Related Links</h4>
                <script type="text/javascript" language="javascript" src="scripts/links7.txt"></script>
                        <li class="inline"><a href="#freq">Frequency Discipline</a><br>
                        <li class="inline"><a href="#modes">Operating Modes</a><br>
                        <li class="inline"><a href="#poll">Poll Interval Control</a><br>
-                       <li class="inline"><a href="#poll">Poll Interval Control</a><br>
-                       <li class="inline"><a href="#notes">Notes</a><br>
+                       <li class="inline"><a href="#leap">Leap Second Processing</a><br>
+                       <li class="inline"><a href="#notes">Additional Features</a><br>
+                       
+                       
+                       
+                       
                        <li class="inline"><a href="#cmd">Command Line Options</a><br>
                        <li class="inline"><a href="#cfg">The Configuration File</a><br>
                        <li class="inline"><a href="#opt">Configuration Options</a><br>
                <h4 id="synop">Synopsis</h4>
                <tt>ntpd [ -46aAbdDgLmnNqx ] [ -c <i>conffile</i> ] [ -f <i>driftfile</i> ] [ -i <i>jaildir</i> ] [ -k <i>keyfile</i> ] [ -l <i>logfile</i> ] [ -p <i>pidfile</i> ] [ -P <i>priority</i> ] [ -r <i>broadcastdelay</i> ] [ -s <i>statsdir</i> ] [ -t <i>key</i> ] [ -u <i>user</i>[:<i>group</i>] ] [ -U <i>interface_update_interval</i> ] [ -v <i>variable</i> ] [ -V <i>variable</i> ]</tt>
                <h4 id="descr">Description</h4>
-               <p>The <tt>ntpd</tt> program is an operating system daemon which sets and maintains the system time of day in synchronism with Internet standard time servers. It is a complete implementation of the Network Time Protocol (NTP) version 4, but also retains compatibility with version 3, as defined by RFC-1305, and version 1 and 2, as defined by RFC-1059 and RFC-1119, respectively. <tt>ntpd</tt> does most computations in 64-bit floating point arithmetic and does relatively clumsy 64-bit fixed point operations only when necessary to preserve the ultimate precision, about 232 picoseconds. While the ultimate precision is not achievable with ordinary workstations and networks of today, it may be required with future gigahertz CPU clocks and gigabit LANs.</p>
+               <p>The <tt>ntpd</tt> program is an operating system daemon which sets and maintains the system time of day in synchronism with Internet standard time servers. It is a complete implementation of the Network Time Protocol (NTP) version 4, but also retains compatibility with version 3, as defined by RFC-1305, and version 1 and 2, as defined by RFC-1059 and RFC-1119, respectively. <tt>ntpd</tt> does most computations in 64-bit floating-point arithmetic and does relatively clumsy 64-bit fixed-point operations only when necessary to preserve the ultimate precision, about 232 picoseconds. While the ultimate precision is not achievable with ordinary workstations and networks of today, it may be required with future gigahertz CPU clocks and gigabit LANs.</p>
                <h4 id="op">How NTP Operates</h4>
-               <p>The <tt>ntpd</tt> program operates by exchanging messages with one or more configured servers at designated poll intervals. When started, whether for the first or subsequent times, the program requires several exchanges from the majority of these servers so the signal processing and mitigation algorithms can accumulate and groom the data and set the clock. In order to protect the network from bursts, the initial poll interval for each server is delayed an interval randomized over a few seconds. At the default initial poll interval of 64s, several minutes can elapse before the clock is set. The initial delay to set the clock can be reduced using the <tt>iburst</tt> keyword with the <tt>server</tt> configuration command, as described on the <a href="confopt.html">Configuration Options</a> page.</p>
-               <p>Most operating systems and hardware of today incorporate a time-of-year (TOY) chip to maintain the time during periods when the power is off. When the machine is booted, the chip is used to initialize the operating system time. After the machine has synchronized to a NTP server, the operating system corrects the chip from time to time. In case there is no TOY chip or for some reason its time is more than 1000s from the server time, <tt>ntpd</tt> assumes something must be terribly wrong and the only reliable action is for the operator to intervene and set the clock by hand. This causes <tt>ntpd</tt> to exit with a panic message to the system log. The <tt>-g</tt> option overrides this check and the clock will be set to the server time regardless of the chip time. However, and to protect against broken hardware, such as when the CMOS battery fails or the clock counter becomes defective, once the clock has been set, an error greater than 1000s will cause <tt>ntpd</tt> to exit anyway.</p>
-               <p>Under ordinary conditions, <tt>ntpd</tt> adjusts the clock in small steps so that the timescale is effectively continuous and without discontinuities. Under conditions of extreme network congestion, the roundtrip delay jitter can exceed three seconds and the synchronization distance, which is equal to one-half the roundtrip delay plus error budget terms, can become very large. The <tt>ntpd</tt> algorithms discard sample offsets exceeding 128 ms, unless the interval during which no sample offset is less than 128 ms exceeds 900s. The first sample after that, no matter what the offset, steps the clock to the indicated time. In practice this reduces the false alarm rate where the clock is stepped in error to a vanishingly low incidence.</p>
-               <p>As the result of this behavior, once the clock has been set, it very rarely strays more than 128 ms, even under extreme cases of network path congestion and jitter. Sometimes, in particular when <tt>ntpd</tt> is first started, the error might exceed 128 ms. This may on occasion cause the clock to be set backwards if the local clock time is more than 128 s in the future relative to the server. In some applications, this behavior may be unacceptable. If the <tt>-x</tt> option is included on the command line, the clock will never be stepped and only slew corrections will be used.</p>
+               <p>The <tt>ntpd</tt> program operates by exchanging messages with one or more configured servers at designated poll intervals. When started, whether for the first or subsequent times, the program requires several exchanges from the majority of these servers so the signal processing and mitigation algorithms can accumulate and groom the data to set the clock. In order to protect the network from bunching, the initial poll interval for each server is delayed an interval randomized over a few seconds. At the default initial poll interval of 64 s, several minutes can elapse before the clock is set. The initial delay to set the clock can be reduced using the <tt>iburst</tt> keyword with the <tt>server</tt> configuration command, as described on the <a href="confopt.html">Server Options</a> page.</p>
+               <p>Most operating systems and hardware of today incorporate a time-of-year (TOY) chip to maintain the time during periods when the power is off. When the machine is booted, the chip is used to initialize the operating system time. After the machine has synchronized to a NTP server, the operating system corrects the chip from time to time. In case there is no TOY chip or for some reason its time is more than 1000 s, called the <i>panic threshold</i>, from the server time, <tt>ntpd</tt> assumes something must be terribly wrong and the only reliable action is for the operator to intervene and set the clock by hand. This causes <tt>ntpd</tt> to exit with a panic message to the system log. The <tt>-g</tt> option overrides this check and the clock will be set to the server time regardless of the chip time. However, and to protect against broken hardware, such as when the CMOS battery fails or the clock counter becomes defective, once the clock has been set, an error greater than 1000 s will cause <tt>ntpd</tt> to exit anyway.</p>
+               <p>Under ordinary conditions, <tt>ntpd</tt> adjusts the clock in small steps so that the timescale is effectively continuous and never runs backwards. Under conditions of extreme network congestion, the roundtrip delay jitter can exceed three seconds and the synchronization distance, which is equal to one-half the roundtrip delay plus error budget terms, can become very large. The <tt>ntpd</tt> algorithms discard offsets exceeding 128 ms, called the <i>step threshold</i>, unless the interval during which no sample offset is less than 128 ms exceeds 900 s, called the <i>stepout threshold</i>. The first sample after that, no matter what the offset, steps the clock to the indicated time. In practice this reduces the false alarm rate where the clock is stepped in error to a vanishingly low incidence.</p>
+               <p>As the result of this behavior, once the clock has been set, it very rarely strays more than 128 ms, even under extreme cases of network congestion and jitter. Sometimes, in particular when <tt>ntpd</tt> is first started, the error might exceed 128 ms. This may on occasion cause the clock to be set backwards if the local clock time is more than 128 s in the future relative to the server. In some applications, this behavior may be unacceptable. If the <tt>-x</tt> option is included on the command line, the clock will always be slewed unless the offset exceeds 600 s (10 minutes), in which case it will be stepped.</p>
                <p>The issues should be carefully explored before deciding to use the <tt>-x</tt> option. The maximum slew rate possible is limited to 500 parts-per-million (PPM) as a consequence of the correctness principles on which the NTP protocol and algorithm design are based. As a result, the local clock can take a long time to converge to an acceptable offset, about 2,000 s for each second the clock is outside the acceptable range. During this interval the local clock will not be consistent with any other network clock and the system cannot be used for distributed applications that require correctly synchronized network time.</p>
-               <p>In spite of the above precautions, sometimes when large frequency errors are present the resulting time offsets stray outside the 128-ms range and an eventual step or slew time correction is required. If following such a correction the frequency error is so large that the first sample is outside the acceptable range, <tt>ntpd</tt> enters the same state as when the <tt>ntp.drift</tt> file is not present. The intent of this behavior is to quickly correct the frequency and restore operation to the normal tracking mode. In the most extreme cases (<tt>time.ien.it</tt> comes to mind), there may be occasional step/slew corrections and subsequent frequency corrections. It helps in these cases to use the <tt>burst</tt> keyword when configuring the server.</p>
                <h4 id="freq">Frequency Discipline</h4>
-               <p>The <tt>ntpd</tt> behavior at startup depends on whether the frequency file, usually <tt>ntp.drift</tt>, exists. This file contains the latest estimate of clock frequency error. When the <tt>ntpd</tt> is started and the file does not exist, the <tt>ntpd</tt> enters a special mode designed to quickly adapt to the particular system clock oscillator time and frequency error. This takes approximately 15 minutes, after which the time and frequency are set to nominal values and the <tt>ntpd</tt> enters normal mode, where the time and frequency are continuously tracked relative to the server. After one hour the frequency file is created and the current frequency offset written to it. When the <tt>ntpd</tt> is started and the file does exist, the <tt>ntpd</tt> frequency is initialized from the file and enters normal mode immediately. After that the current frequency offset is written to the file at hourly intervals.</p>
+               <p>The <tt>ntpd</tt> behavior at startup depends on whether the frequency file, usually called <tt>ntp.drift</tt>, exists. This file contains the latest estimate of clock frequency offset. When <tt>ntpd</tt> is started and the file does not exist, <tt>ntpd</tt> enters a special mode designed to directly measure the particular clock frequency offset. This takes 15 minutes, after which the time and frequency are set to nominal values and <tt>ntpd</tt> enters normal mode, where the time and frequency are continuously adjusted.</p>
+               <p>After one hour the frequency file is created and the current frequency offset written to it. When <tt>ntpd</tt> is started and the file does exist, <tt>ntpd</tt> initializes the frequency from the file and then enters normal mode immediately. In either case the current frequency offset is written to the file at hourly intervals.</p>
                <h4 id="modes">Operating Modes</h4>
-               <p><tt>ntpd</tt> can operate in any of several modes, including symmetric active/passive, client/server broadcast/multicast and manycast, as described in the <a href="assoc.html">Association Management</a> page. It normally operates continuously while monitoring for small changes in frequency and trimming the clock for the ultimate precision. However, it can operate in a one-time mode where the time is set from an external server and frequency is set from a previously recorded frequency file. A broadcast/multicast or manycast client can discover remote servers, compute server-client propagation delay correction factors and configure itself automatically. This makes it possible to deploy a fleet of workstations without specifying configuration details specific to the local environment.</p>
-               <p>By default, <tt>ntpd</tt> runs in continuous mode where each of possibly several external servers is polled at intervals determined by an intricate state machine. The state machine measures the incidental roundtrip delay jitter and oscillator frequency wander and determines the best poll interval using a heuristic algorithm. Ordinarily, and in most operating environments, the state machine will start with 64s intervals and eventually increase in steps to 1024s. A small amount of random variation is introduced in order to avoid bunching at the servers. In addition, should a server become unreachable for some time, the poll interval is increased in steps to 1024s in order to reduce network overhead.</p>
-               <p>In some cases it may not be practical for <tt>ntpd</tt> to run continuously. A common workaround has been to run the <tt>ntpdate</tt> program from a <tt>cron</tt> job at designated times. However, this program does not have the crafted signal processing, error checking and mitigation algorithms of <tt>ntpd</tt>. The <tt>-q</tt> option is intended for this purpose. Setting this option will cause <tt>ntpd</tt> to exit just after setting the clock for the first time. The procedure for initially setting the clock is the same as in continuous mode; most applications will probably want to specify the <tt>iburst</tt> keyword with the <tt>server</tt> configuration command. With this keyword a volley of messages are exchanged to groom the data and the clock is set in about 10 s. If nothing is heard after a couple of minutes, the daemon times out and exits. After a suitable period of mourning, the <tt>ntpdate</tt> program may be retired.</p>
-               <p>When kernel support is available to discipline the clock frequency, which is the case for stock Solaris, Tru64, Linux and FreeBSD, a useful feature is available to discipline the clock frequency. First, <tt>ntpd</tt> is run in continuous mode with selected servers in order to measure and record the intrinsic clock frequency offset in the frequency file. It may take some hours for the frequency and offset to settle down. Then the <tt>ntpd</tt> is stopped and run in one-time mode as required. At each startup, the frequency is read from the file and initializes the kernel frequency.</p>
+               <p><tt>ntpd</tt> can operate in any of several modes, including symmetric active/passive, client/server broadcast/multicast and manycast, as described in the <a href="assoc.html">Association Management</a> page. It normally operates continuously while adjusting the system clock time and frequency with respect to external sources. In some cases it may not be practical to run <tt>ntpd</tt> continuously. A common workaround has been to run the <tt>ntpdate</tt> program from a <tt>cron</tt> job at designated times. However, this program does not have the crafted signal processing, error checking and mitigation algorithms of <tt>ntpd</tt>. If the <tt>-q</tt> option is specified on the command line, <tt>ntpd</tt> will operate as in continous mode, but exit just after setting the clock for the first time. Most applications will probably want to specify the <tt>iburst</tt> keyword with the <tt>server</tt> configuration command. With this keyword a volley of messages is exchanged to groom the data and set the clock in about 10 s. If nothing is heard after a couple of minutes, the daemon times out and exits.</p>
+               <p>A broadcast/multicast or manycast client can discover remote servers, compute server-client propagation delay correction factors and configure itself automatically. This makes it possible to deploy a fleet of workstations without specifying configuration details specific to the local environment. An alternative to broadcast/multicast is manycast mode, in which a client broadcasts a request and one or more servers in range offer service. Further details are on the <a href="manyopt.html">Automatic NTP Configuration Options</a> page.</p>
+               <p>By default, <tt>ntpd</tt> runs in continuous mode where each of possibly several external servers is polled at intervals determined by an intricate phase/frequncy-lock feedback loop. The feedback loop measures the incidental clock offset jitter and oscillator frequency wander and determines the best poll interval using a heuristic algorithm. Ordinarily, and in most operating environments, the feedback loop will start with 64 s poll intervals and eventually increase in steps to 1024 s. A small amount of random variation is introduced in order to avoid bunching. In addition, should a server become unreachable for some time, the poll interval is increased in steps to 1024 s in order to reduce network overhead.</p>
                <h4 id="poll">Poll Interval Control</h4>
-               <p>This version of NTP includes an intricate state machine to reduce the network load while maintaining a quality of synchronization consistent with the observed jitter and wander. There are a number of ways to tailor the operation in order enhance accuracy by reducing the interval or to reduce network overhead by increasing it. However, the user is advised to carefully consider the consequences of changing the poll adjustment range from the default minimum of 64 s to the default maximum of 1,024 s. The default minimum can be changed with the <tt>tinker minpoll</tt> command to a value not less than 16 s. This value is used for all configured associations, unless overridden by the <tt>minpoll</tt> option on the configuration command. Note that most device drivers will not operate properly if the poll interval is less than 64 s and that the broadcast server and manycast client associations will also use the default, unless overridden.</p>
-               <p>In some cases involving dial up or toll services, it may be useful to increase the minimum interval to a few tens of minutes and maximum interval to a day or so. Under normal operation conditions, once the clock discipline loop has stabilized the interval will be increased in steps from the minimum to the maximum. However, this assumes the intrinsic clock frequency error is small enough for the discipline loop correct it. The capture range of the loop is 500 PPM at an interval of 64s decreasing by a factor of two for each doubling of interval. At a minimum of 1,024 s, for example, the capture range is only 31 PPM. If the intrinsic error is greater than this, the drift file <tt>ntp.drift</tt> will have to be specially tailored to reduce the residual error below this limit. Once this is done, the drift file is automatically updated once per hour and is available to initialize the frequency on subsequent daemon restarts.</p>
+               <p>NTP uses an intricate clock discipline algorithm to automatically control the poll interval for maximum accuracy consistent with minimum network load. The default minimum interval is 64 s and the maximum 1024 s, which is suitable for most conditions. The default minimum and maximum intervals  can be changed using the <tt>tinker minpoll</tt> and <tt>tinker maxpoll </tt> commands, respectively. These values are used for all configured associations, unless overridden by the <tt>minpoll</tt> or <tt>minpoll</tt> options on the  <tt>server</tt>configuration command.</p>
+               <p>In some cases involving dial-up or ISDN toll services, it may be useful to set the minimum interval to 12 (4096 s) and maximum interval to 17 (36 h). Under normal operation conditions, once the clock discipline loop has stabilized the interval will be increased in steps from the minimum to the maximum. However, this assumes the residual clock frequency error is small enough for the discipline loop to capture and correct it. The capture range of the loop is 500 PPM with a 64-s interval decreasing by a factor of two for each interval doubling. At a 36-hr interval, for example, the capture range is only 0.24 PPM. If the frequency changes abruptly, due for instance a large change in temperature, one or more step adjustments may occur.is greater than this, the frequency file <tt>ntp.drift</tt></p>
                <h4 id="huff">The huff-n'-puff Filter</h4>
                <p>In scenarios where a considerable amount of data are to be downloaded or uploaded over telephone modems, timekeeping quality can be seriously degraded. This occurs because the differential delays on the two directions of transmission can be quite large. In many cases the apparent time errors are so large as to exceed the step threshold and a step correction can occur during and after the data transfer is in progress.</p>
                <p>The huff-n'-puff filter is designed to correct the apparent time offset in these cases. It depends on knowledge of the propagation delay when no other traffic is present. In common scenarios this occurs during other than work hours. The filter maintains a shift register that remembers the minimum delay over the most recent interval measured usually in hours. Under conditions of severe delay, the filter corrects the apparent offset using the sign of the offset and the difference between the apparent delay and minimum delay. The name of the filter reflects the negative (huff) and positive (puff) correction, which depends on the sign of the offset.</p>
-               <p>The filter is activated by the <tt>tinker</tt> command and <tt>huffpuff</tt> keyword, as described in the <a href="miscopt.html">Miscellaneous Options</a> page.</p>
-               <h4 id="notes">Notes</h4>
-               <p>If NetInfo support is built into <tt>ntpd</tt>, then <tt>ntpd</tt> will attempt to read its configuration from the NetInfo if the default ntp.conf file cannot be read and no file is specified by the <tt>-c</tt> option.</p>
+               <p>The filter is activated by the <tt>tinker huffpuff</tt> command, as described in the <a href="miscopt.html">Miscellaneous Options</a> page.</p>
+               <h4 id="leap">Leap Second Processing</h4>
+               <p>As provided by international agreement, an extra second is sometimes inserted in Coordinated Universal Time (UTC) at the end of a selected month, usually June or December. The National Institutes of Standards and Technology (NIST) provides an historic leapseconds file at time.nist.gov for retrieval via FTP. When this file, usually called ntp.leap, is installed, <tt>ntpd</tt> reads it at startup and initializes three leapsecond values, the offset of International Atomic Time (TAI) after the last leap in the file, the NTP&nbsp;seconds of that leap and the NTP&nbsp;seconds when the leapseconds file expires.</p>
+               <p>If a host does not have the leapsecond values, they can be obtained over the net using the Autokey security protocol. Ordinarily, the leapseconds file is installed on the primary servers and the values flow from them to dependent servers and eventually clients. When multiple servers are involved, the values with the latest expiration time are used.</p>
+               <p>If the latest leap is in the past, nothing further is done other than to install the TAI offset in the kernel where it can be retrieved by the <tt>ntp_gettimeofday()</tt> system call. If the leap is in the future less than 28 days, the leap warning bits are set to insert one second. If in the future less than 23 hours, the kernel is armed to insert one second at the end of the current day. If the kernel is enabled, the leap is done automatically at that time; otherwise, the clock is stepped back one second at that time.</p>
+               <p>Dependent servers and clients tally the leap warning bits of surviving servers and reference clocks. When a majority of the survivors show warning, a leap is programmed at the end of the current month. During the month and day of insertion, they operate as above. In this way the leap is propagated at all dependent servers and clients.</p>
+               <h4 id="notes">Additional Features</h4>
+               <p>If <tt>ntpd</tt>, is configured with NetInfo support, it will attempt to read its configuration from the NetInfo service if the default <tt></tt>ntp.conf</tt> file cannot be read and no file is specified by the <tt>-c</tt> option.</p>
                <p>In contexts where a host name is expected, a <tt>-4</tt> qualifier preceding the host name forces DNS resolution to the IPv4 namespace, while a <tt>-6</tt> qualifier forces DNS resolution to the IPv6 namespace.</p>
                <p>Various internal <tt>ntpd</tt> variables can be displayed and configuration options altered while the <tt>ntpd</tt> is running using the <tt><a href="ntpq.html">ntpq</a></tt> and <tt><a href="ntpdc.html">ntpdc</a></tt> utility programs.</p>
                <p>When <tt>ntpd</tt> starts it looks at the value of <tt>umask</tt>, and if zero <tt>ntpd</tt> will set the <tt>umask</tt> to <tt>022</tt>.</p>
                <h4 id="cfg">The Configuration File</h4>
                <p>Ordinarily, <tt>ntpd</tt> reads the <tt>ntp.conf</tt> configuration file at startup time in order to determine the synchronization sources and operating modes. It is also possible to specify a working, although limited, configuration entirely on the command line, obviating the need for a configuration file. This may be particularly useful when the local host is to be configured as a broadcast/multicast client, with all peers being determined by listening to broadcasts at run time.</p>
                <p>Usually, the configuration file is installed in the <tt>/etc</tt> directory, but could be installed elsewhere (see the <tt>-c <i>conffile</i></tt> command line option). The file format is similar to other Unix configuration files - comments begin with a <tt>#</tt> character and extend to the end of the line; blank lines are ignored.</p>
-               <p>Configuration commands consist of an initial keyword followed by a list of arguments, some of which may be optional, separated by whitespace. Commands may not be continued over multiple lines. Arguments may be host names, host addresses written in numeric, dotted-quad form, integers, floating point numbers (when specifying times in seconds) and text strings. Optional arguments are delimited by <tt>[ ]</tt> in the following descriptions, while alternatives are separated by <tt>|</tt>. The notation <tt>[ ... ]</tt> means an optional, indefinite repetition of the last item before the <tt>[ ... ]</tt>.</p>
+               <p>Configuration commands consist of an initial keyword followed by a list of arguments, some of which may be optional, separated by whitespace. Commands may not be continued over multiple lines. Arguments may be host names, host addresses written in numeric, dotted-quad form, integers, floating point numbers (when specifying times in seconds) and text strings. Optional arguments are delimited by <tt>[ ]</tt> in the following option pages, while alternatives are separated by <tt>|</tt>. The notation <tt>[ ... ]</tt> means an optional, indefinite repetition of the last item before the <tt>[ ... ]</tt>.</p>
                <h4 id="opt">Configuration Options</h4>
                <p><a href="confopt.html">Server Options</a><br>
                        <a href="authopt.html">Authentication Options</a><br>
index 92fde1de78058bc1091d784d01c7e9b77352c558..02bc13aec451325e9fd914c8a07f5f33426dd9fe 100644 (file)
                <dt><tt>addpeer <i>peer_address</i> [
                <i>keyid</i> ] [ <i>version</i> ] [
                <tt>minpoll# | prefer | iburst  | burst | minpoll
-               <i>N</i> | <tt>maxpoll</tt> <i>N</i> [...] ]</tt>
+               <i>N</i> | <tt>maxpoll</tt> <i>N</i> [ <i>dynamic</i> ] [...] ]</tt>
                <dt><tt>addpeer <i>peer_address</i> [
                <tt>prefer | iburst | burst | minpoll
                <i>N</i> | <tt>maxpoll</tt> <i>N</i> | <tt>keyid</tt>
                        ntpd.  See the <a href="confopt.html">Server Options</a> page for further information.
                        Each flag (or its absence) replaces the
                        previous setting. The <tt>prefer</tt> keyword indicates a preferred peer (and thus will be used primarily for clock synchronisation if possible). The preferred peer also determines the validity of the PPS signal - if the preferred peer is suitable for synchronisation so is the PPS signal.
+                       The <tt>dynamic</tt> keyword allows association configuration even when no suitable network interface is found at configuration time. The dynamic interface update mechanism may complete the configuration when new interfaces appear (e.g. WLAN/PPP interfaces) at a later time and thus render the association operable.
                        <dt><tt>addserver <i>peer_address</i> [
                <i>keyid</i> ] [ <i>version</i> ] [
                <tt>minpoll# | prefer | iburst  | burst | minpoll
                <dt><tt>addserver <i>peer_address</i> [
                <tt>prefer | iburst | burst | minpoll
                <i>N</i> | <tt>maxpoll</tt> <i>N</i> | <tt>keyid</tt>
-                       <i>N</i> | <tt>version</tt> <i>N</i> [...] ]</tt>
+                       <i>N</i> | <tt>version</tt> <i>N</i> [...] [ <i>dynamic</i> ] ]</tt>
                        <dd>Identical to the addpeer command, except that the operating mode is client.
                        <dt><tt>broadcast <i>peer_address</i> [
                        <i>keyid</i> ] [ <i>version</i> ] [ <i>prefer</i> ]</tt>
index 0d33473cc31e5cbde6a7a1abfefb0eccc2f0f888..eb0f97f85cbda1a157258b31bcb521d036fe3eb7 100644 (file)
@@ -1,6 +1,9 @@
 document.write("<ul>\\r
-<li class='inline'><a href='confopt.html'>Server Options</a><br>\\r
+<li class='inline'><a href='accopt.html'>Access Control Options</a><br>\
 <li class='inline'><a href='authopt.html'>Authentication Options</a><br>\\r
+<li class='inline'><a href='miscopt.html'>Miscellaneous Options</a><br>\
 <li class='inline'><a href='monopt.html'>Monitoring Options</a><br>\\r
+<li class='inline'><a href='clockopt.html'>Reference Clock Options</a><br>\
+<li class='inline'><a href='confopt.html'>Server Options</a><br>\
 <li class='inline'><a href='ntp_conf.html'>Configuration File Definition (Advanced)</a><br>\
 </ul>")
\ No newline at end of file
index c092c9bbd6f931c919cc04100944f28c77f48bbe..edd9bfbc5e57f06a15723bf30617e3a9298b4382 100644 (file)
@@ -348,6 +348,17 @@ struct peer {
        double  disp;           /* peer dispersion */
        double  estbdelay;      /* clock offset to broadcast server */
 
+       /*
+        * Variables used to correct for packet length and asymmetry.
+        */
+       double  t21;            /* outbound packet delay */
+       int     t21_bytes;      /* outbound packet length */
+       int     t21_last;       /* last outbound packet length */
+       double  r21;            /* outbound data rate */
+       double  t34;            /* inbound packet delay */
+       int     t34_bytes;      /* inbound packet length */
+       double  r34;            /* inbound data rate */
+
        /*
         * End of clear-to-zero area
         */
@@ -433,7 +444,7 @@ struct peer {
 #define FLAG_FIXPOLL   0x1000  /* stick at minpoll */
 #define FLAG_TRUE      0x2000  /* select truechimer */
 #define        FLAG_PREEMPT    0x4000  /* preemptable association */
-
+#define        FLAG_ASYM       0x8000  /* asymmetric delay compensation */
 /*
  * Definitions for the clear() routine.  We use memset() to clear
  * the parts of the peer structure which go to zero.  These are
index 50f84e9734962f7b0e1792e08aec806e4ccae2da..d8f6f7d94f8ff3e9e8cfce3dbd4b38ca296a0b95 100644 (file)
@@ -166,20 +166,20 @@ struct ntp_control {
 #define CS_VERSION     18
 #define        CS_STABIL       19
 #define CS_VARLIST     20
+#define CS_TAI          21
+#define CS_LEAPTAB      22
+#define CS_LEAPEND      23
 #ifdef OPENSSL
-#define CS_FLAGS       21
-#define CS_HOST                22
-#define CS_PUBLIC      23
-#define        CS_CERTIF       24
-#define        CS_REVTIME      25
-#define CS_LEAPTAB     26
-#define CS_TAI         27
+#define CS_FLAGS       24
+#define CS_HOST                25
+#define CS_PUBLIC      26
+#define        CS_CERTIF       27
 #define        CS_DIGEST       28
 #define CS_IDENT       29
-#define        CS_REVOKE       30
-#define        CS_MAXCODE      CS_REVOKE
+#define        CS_REVTIME      30
+#define        CS_MAXCODE      CS_REVTIME
 #else
-#define        CS_MAXCODE      CS_VARLIST
+#define        CS_MAXCODE      CS_LEAPEND
 #endif /* OPENSSL */
 
 /*
@@ -222,18 +222,20 @@ struct ntp_control {
 #define        CP_FLASH        35
 #define CP_TTL         36
 #define CP_VARLIST     37
+#define        CP_IN           38
+#define        CP_OUT          39
 #ifdef OPENSSL
-#define CP_FLAGS       38
-#define CP_HOST                39
-#define CP_VALID       40
-#define        CP_INITSEQ      41
-#define        CP_INITKEY      42
-#define        CP_INITTSP      43
-#define        CP_DIGEST       44
-#define CP_IDENT       45
+#define CP_FLAGS       40
+#define CP_HOST                41
+#define CP_VALID       42
+#define        CP_INITSEQ      43
+#define        CP_INITKEY      44
+#define        CP_INITTSP      45
+#define        CP_DIGEST       46
+#define CP_IDENT       47
 #define        CP_MAXCODE      CP_IDENT
 #else
-#define        CP_MAXCODE      CP_VARLIST
+#define        CP_MAXCODE      CP_OUT
 #endif /* OPENSSL */
 
 /*
index 2bdcb585ee403e469d441ac49d0ea0b6090614ff..6279effac25da391034e177f5f7fe260329e92b0 100644 (file)
@@ -49,7 +49,7 @@
 #define CRYPTO_CERT    CRYPTO_CMD(2) /* certificate */
 #define CRYPTO_COOK    CRYPTO_CMD(3) /* cookie value */
 #define CRYPTO_AUTO    CRYPTO_CMD(4) /* autokey values */
-#define CRYPTO_TAI     CRYPTO_CMD(5) /* leapseconds table */
+#define CRYPTO_TAI     CRYPTO_CMD(5) /* leapsecond values */
 #define        CRYPTO_SIGN     CRYPTO_CMD(6) /* certificate sign */
 #define CRYPTO_IFF     CRYPTO_CMD(7) /* IFF identity scheme */
 #define CRYPTO_GQ      CRYPTO_CMD(8) /* GQ identity scheme */
  * Miscellaneous crypto stuff
  */
 #define NTP_MAXSESSION 100     /* maximum session key list entries */
-#define NTP_AUTOMAX    13      /* log2 default max session key life */
-#define KEY_REVOKE     16      /* log2 default key revoke timeout */
+#define NTP_AUTOMAX    3600    /* default max session key lifetime */
+#define KEY_REVOKE     86400   /* default key revoke timeout */
 #define NTP_MAXEXTEN   1024    /* maximum extension field size */
 
 /*
index 1a76d92ba42fdccf4a45accb95f985902a40c1e4..68b90134fba41331bdfbcc3e553dd927ddc7d3c1 100644 (file)
@@ -122,6 +122,7 @@ extern      void    loop_config (int, double);
 extern void    huffpuff        (void);
 extern u_long  sys_clocktime;
 extern u_int   sys_tai;
+extern int     clock_stepcnt;
 
 /* ntp_monitor.c */
 extern void    init_mon        (void);
@@ -154,8 +155,11 @@ extern     struct  peer *findmanycastpeer  (struct recvbuf *);
 /* ntp_crypto.c */
 #ifdef OPENSSL
 extern int     crypto_recv     (struct peer *, struct recvbuf *);
-extern int     crypto_xmit     (struct pkt *, struct sockaddr_storage *, int, struct exten *, keyid_t);
-extern keyid_t session_key     (struct sockaddr_storage *, struct sockaddr_storage *, keyid_t, keyid_t, u_long);
+extern int     crypto_xmit     (struct pkt *, struct sockaddr_storage *,
+                                   int *, struct exten *, keyid_t);
+extern keyid_t session_key     (struct sockaddr_storage *,
+                                   struct sockaddr_storage *, keyid_t,
+                                   keyid_t, u_long);
 extern int     make_keylist    (struct peer *, struct interface *);
 extern void    key_expire      (struct peer *);
 extern void    crypto_update   (void);
@@ -177,11 +181,11 @@ extern struct value tai_leap;
 /* ntp_proto.c */
 extern void    transmit        (struct peer *);
 extern void    receive         (struct recvbuf *);
-extern  void    peer_crypto_clear (struct peer *peer);
 extern void    peer_clear      (struct peer *, char *);
-extern void    process_packet  (struct peer *, struct pkt *);
+extern void    process_packet  (struct peer *, struct pkt *, u_int);
 extern void    clock_select    (void);
 extern void    kod_proto       (void);
+extern int     leap_tai;
 extern u_long  leap_ins;
 extern u_long  leap_expire;
 extern u_long  leap_sec;
@@ -225,10 +229,10 @@ extern    void    timer           (void);
 extern void    timer_clr_stats (void);
 extern  void    timer_interfacetimeout (u_long);
 extern  volatile int interface_interval;
-
 #ifdef OPENSSL
 extern char    *sys_hostname;
-extern l_fp    sys_revoketime;
+extern u_long  sys_revoke;     /* keys revoke timeout */
+extern u_long  sys_automax;    /* session key timeout */
 #endif /* OPENSSL */
 
 /* ntp_util.c */
@@ -389,7 +393,6 @@ extern l_fp sys_reftime;            /* time we were last updated */
 extern struct peer *sys_peer;          /* our current peer */
 extern struct peer *sys_pps;           /* our current PPS peer */
 extern struct peer *sys_prefer;                /* our cherished peer */
-extern u_long  sys_automax;            /* maximum session key lifetime */
 
 /*
  * Nonspecified system state variables.
@@ -440,7 +443,6 @@ extern u_long       mon_age;                /* monitor preempt age */
 
 /* ntp_timer.c */
 extern volatile int alarm_flag;                /* alarm flag */
-extern u_char  sys_revoke;             /* keys revoke timeout (log2 s) */
 extern volatile u_long alarm_overflow;
 extern u_long  current_time;           /* current time (s) */
 extern u_long  timer_timereset;
index c7402b0ff4af4350388091373eb028827152b194..c5fbb8aa49d5af2c3e67e0f2aad80813921bf8e7 100644 (file)
@@ -1016,10 +1016,10 @@ config_auth(void)
                my_config.auth.trusted_key_list = NULL;
        }
     
-       /* Revoke Command */
 #ifdef OPENSSL
+       /* Revoke Command */
        if (my_config.auth.revoke) 
-               sys_revoke = (u_char) max(my_config.auth.revoke, KEY_REVOKE);
+               sys_revoke = my_config.auth.revoke;
 #endif /* OPENSSL */
 
 #if !defined(VMS) && !defined(SYS_VXWORKS)
@@ -1573,7 +1573,10 @@ config_vars(void)
                        }
                        break;
                    case T_DriftMinutes:
+
+#if 0  /* this code is bogus and should be replaced with wander threshold */
                        stats_write_period = 60 * curr_var->value.i;
+#endif
                        break;
                    case T_Leapfile:
                        stats_config(STATS_LEAP_FILE, curr_var->value.s);
@@ -1601,13 +1604,11 @@ config_vars(void)
                                        curr_var->value.s);
                        free(curr_var->value.s);
                        break;
-                   case T_Automax:
 #ifdef OPENSSL
-                       sys_automax = 1 << max(curr_var->value.i, 10);
-#else
-                       printf("Warning: Automax command ignored!\n");
-#endif
+                   case T_Automax:
+                       sys_automax = curr_var->value.i;
                        break;
+#endif
                }
                free_node(curr_var);
        }
index b7d857366ccd561e459a086c7129046df1d88a63..7b28b3164d4888b4418d15b434e3245ac168a967 100644 (file)
@@ -51,14 +51,13 @@ static      void    ctl_putuint     (const char *, u_long);
 static void    ctl_puthex      (const char *, u_long);
 static void    ctl_putint      (const char *, long);
 static void    ctl_putts       (const char *, l_fp *);
-static void    ctl_putadr      (const char *, u_int32, struct sockaddr_storage*);
+static void    ctl_putadr      (const char *, u_int32,
+                                   struct sockaddr_storage*);
 static void    ctl_putid       (const char *, char *);
 static void    ctl_putarray    (const char *, double *, int);
 static void    ctl_putsys      (int);
 static void    ctl_putpeer     (int, struct peer *);
-#ifdef OPENSSL
 static void    ctl_putfs       (const char *, tstamp_t);
-#endif
 #ifdef REFCLOCK
 static void    ctl_putclock    (int, struct refclockstat *, int);
 #endif /* REFCLOCK */
@@ -115,19 +114,19 @@ static struct ctl_var sys_var[] = {
        { CS_VERSION,   RO, "version" },        /* 18 */
        { CS_STABIL,    RO, "stability" },      /* 19 */
        { CS_VARLIST,   RO, "sys_var_list" },   /* 20 */
+       { CS_TAI,       RO, "tai" },            /* 21 */
+       { CS_LEAPTAB,   RO, "leapsec" },        /* 22 */
+       { CS_LEAPEND,   RO, "expire" },         /* 23 */
 #ifdef OPENSSL
-       { CS_FLAGS,     RO, "flags" },          /* 21 */
-       { CS_HOST,      RO, "hostname" },       /* 22 */
-       { CS_PUBLIC,    RO, "update" },         /* 23 */
-       { CS_CERTIF,    RO, "cert" },           /* 24 */
-       { CS_REVTIME,   RO, "expire" },         /* 25 */
-       { CS_LEAPTAB,   RO, "leapsec" },        /* 26 */
-       { CS_TAI,       RO, "tai" },            /* 27 */
+       { CS_FLAGS,     RO, "flags" },          /* 24 */
+       { CS_HOST,      RO, "hostname" },       /* 25 */
+       { CS_PUBLIC,    RO, "update" },         /* 26 */
+       { CS_CERTIF,    RO, "cert" },           /* 27 */
        { CS_DIGEST,    RO, "signature" },      /* 28 */
        { CS_IDENT,     RO, "ident" },          /* 29 */
-       { CS_REVOKE,    RO, "expire" },         /* 30 */
+       { CS_REVTIME,   RO, "until" },          /* 30 */
 #endif /* OPENSSL */
-       { 0,            EOV, "" }               /* 21/31 */
+       { 0,            EOV, "" }               /* 24/31 */
 };
 
 static struct ctl_var *ext_sys_var = (struct ctl_var *)0;
@@ -156,14 +155,15 @@ static    u_char def_sys_var[] = {
        CS_JITTER,
        CS_ERROR,
        CS_STABIL,
+       CS_TAI,
+       CS_LEAPTAB,
+       CS_LEAPEND,
 #ifdef OPENSSL
        CS_HOST,
        CS_DIGEST,
        CS_FLAGS,
        CS_PUBLIC,
        CS_IDENT,
-       CS_LEAPTAB,
-       CS_TAI,
        CS_CERTIF,
 #endif /* OPENSSL */
        0
@@ -212,17 +212,19 @@ static struct ctl_var peer_var[] = {
        { CP_FLASH,     RO, "flash" },          /* 35 */
        { CP_TTL,       RO, "ttl" },            /* 36 */
        { CP_VARLIST,   RO, "peer_var_list" },  /* 37 */
+       { CP_IN,        RO, "in" },             /* 38 */
+       { CP_OUT,       RO, "out" },            /* 39 */
 #ifdef OPENSSL
-       { CP_FLAGS,     RO, "flags" },          /* 38 */
-       { CP_HOST,      RO, "hostname" },       /* 39 */
-       { CP_VALID,     RO, "valid" },          /* 40 */
-       { CP_INITSEQ,   RO, "initsequence" },   /* 41 */
-       { CP_INITKEY,   RO, "initkey" },        /* 42 */
-       { CP_INITTSP,   RO, "timestamp" },      /* 43 */
-       { CP_DIGEST,    RO, "signature" },      /* 44 */
-       { CP_IDENT,     RO, "trust" },          /* 45 */
+       { CP_FLAGS,     RO, "flags" },          /* 40 */
+       { CP_HOST,      RO, "hostname" },       /* 41 */
+       { CP_VALID,     RO, "valid" },          /* 42 */
+       { CP_INITSEQ,   RO, "initsequence" },   /* 43 */
+       { CP_INITKEY,   RO, "initkey" },        /* 44 */
+       { CP_INITTSP,   RO, "timestamp" },      /* 45 */
+       { CP_DIGEST,    RO, "signature" },      /* 46 */
+       { CP_IDENT,     RO, "trust" },          /* 47 */
 #endif /* OPENSSL */
-       { 0,            EOV, "" }               /* 38/46 */
+       { 0,            EOV, "" }               /* 40/48 */
 };
 
 
@@ -234,6 +236,8 @@ static u_char def_peer_var[] = {
        CP_SRCPORT,
        CP_DSTADR,
        CP_DSTPORT,
+       CP_OUT,
+       CP_IN,
        CP_LEAP,
        CP_STRATUM,
        CP_PRECISION,
@@ -973,7 +977,7 @@ ctl_putdbl(
        (void)sprintf(cp, "%.3f", ts);
        while (*cp != '\0')
                cp++;
-       ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
+       ctl_putdata(buffer, (unsigned)(cp - buffer), 0);
 }
 
 /*
@@ -1004,7 +1008,6 @@ ctl_putuint(
 /*
  * ctl_putfs - write a decoded filestamp into the response
  */
-#ifdef OPENSSL
 static void
 ctl_putfs(
        const char *tag,
@@ -1034,11 +1037,11 @@ ctl_putfs(
                cp++;
        ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
 }
-#endif
 
 
 /*
- * ctl_puthex - write a tagged unsigned integer, in hex, into the response
+ * ctl_puthex - write a tagged unsigned integer, in hex, into the
+ * response
  */
 static void
 ctl_puthex(
@@ -1108,9 +1111,8 @@ ctl_putts(
                *cp++ = *cq++;
 
        *cp++ = '=';
-       (void) sprintf(cp, "0x%08lx.%08lx",
-                          ts->l_ui & 0xffffffffUL,
-                          ts->l_uf & 0xffffffffUL);
+       (void) sprintf(cp, "0x%08lx.%08lx", ts->l_ui & 0xffffffffUL,
+           ts->l_uf & 0xffffffffUL);
        while (*cp != '\0')
                cp++;
        ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
@@ -1263,7 +1265,7 @@ ctl_putsys(
                        ctl_putuint(sys_var[CS_PEERID].text, 0);
                else
                        ctl_putuint(sys_var[CS_PEERID].text,
-                               sys_peer->associd);
+                           sys_peer->associd);
                break;
 
        case CS_STATE:
@@ -1384,11 +1386,28 @@ ctl_putsys(
                }
                break;
 
+       case CS_TAI:
+               if (sys_tai > 0)
+                       ctl_putuint(sys_var[CS_TAI].text, sys_tai);
+               break;
+
+       case CS_LEAPTAB:
+               if (leap_sec > 0)
+                       ctl_putuint(sys_var[CS_LEAPTAB].text,
+                           leap_sec);
+               break;
+
+       case CS_LEAPEND:
+               if (leap_expire > 0)
+                       ctl_putfs(sys_var[CS_LEAPEND].text,
+                           leap_expire);
+               break;
+
 #ifdef OPENSSL
        case CS_FLAGS:
-               if (crypto_flags) {
-                       ctl_puthex(sys_var[CS_FLAGS].text, crypto_flags);
-               }
+               if (crypto_flags)
+                       ctl_puthex(sys_var[CS_FLAGS].text,
+                           crypto_flags);
                break;
 
        case CS_DIGEST:
@@ -1414,7 +1433,7 @@ ctl_putsys(
                            cp->issuer, cp->flags);
                        ctl_putstr(sys_var[CS_CERTIF].text, cbuf,
                            strlen(cbuf));
-                       ctl_putfs(sys_var[CS_REVOKE].text, cp->last);
+                       ctl_putfs(sys_var[CS_REVTIME].text, cp->last);
                }
                break;
 
@@ -1424,12 +1443,6 @@ ctl_putsys(
                            ntohl(hostval.tstamp));
                break;
 
-       case CS_REVTIME:
-               if (hostval.tstamp != 0)
-                       ctl_putfs(sys_var[CS_REVTIME].text,
-                           ntohl(hostval.tstamp));
-               break;
-
        case CS_IDENT:
                if (iffpar_pkey != NULL)
                        ctl_putstr(sys_var[CS_IDENT].text,
@@ -1442,15 +1455,6 @@ ctl_putsys(
                            mvpar_file, strlen(mvpar_file));
                break;
 
-       case CS_LEAPTAB:
-               ctl_putuint(sys_var[CS_LEAPTAB].text,
-                   leap_sec);
-               break;
-
-       case CS_TAI:
-               ctl_putuint(sys_var[CS_TAI].text, sys_tai);
-               break;
-
 #endif /* OPENSSL */
        }
 }
@@ -1514,6 +1518,18 @@ ctl_putpeer(
                    ntohs(((struct sockaddr_in*)&peer->dstadr->sin)->sin_port) : 0));
                break;
 
+       case CP_OUT:
+               if (peer->r21 > 0)
+                       ctl_putdbl(peer_var[CP_IN].text,
+                           peer->r21 / 1e3);
+               break;
+
+       case CP_IN:
+               if (peer->r34 >0)
+                       ctl_putdbl(peer_var[CP_OUT].text,
+                           peer->r34 / 1e3);
+               break;
+
        case CP_LEAP:
                ctl_putuint(peer_var[CP_LEAP].text, peer->leap);
                break;
index fc17c00dc7d93fe3f81397f1521dcf67c6c1c5ce..cc0ffa879ea0f892cdf92ee07ed89038a04d7c5f 100644 (file)
@@ -41,7 +41,7 @@
  * +-------+-------+
  * |   op  |  len  | <- extension pointer
  * +-------+-------+
- * |    assocID    |
+ * |    associd    |
  * +---------------+
  * |   timestamp   | <- value pointer
  * +---------------+
@@ -127,7 +127,6 @@ static char *rand_file = NULL;      /* random seed file */
 static char *host_file = NULL; /* host key file */
 static char *sign_file = NULL; /* sign key file */
 static char *cert_file = NULL; /* certificate file */
-static char *leap_file = NULL; /* leapseconds file */
 static tstamp_t if_fstamp = 0; /* IFF filestamp */
 static tstamp_t gq_fstamp = 0; /* GQ file stamp */
 static tstamp_t mv_fstamp = 0; /* MV filestamp */
@@ -149,7 +148,7 @@ static      int     crypto_bob3     (struct exten *, struct value *);
 static int     crypto_iff      (struct exten *, struct peer *);
 static int     crypto_gq       (struct exten *, struct peer *);
 static int     crypto_mv       (struct exten *, struct peer *);
-static u_int   crypto_send     (struct exten *, struct value *);
+static u_int   crypto_send     (struct exten *, struct value *, int *);
 static tstamp_t crypto_time    (void);
 static u_long  asn2ntp         (ASN1_TIME *);
 static struct cert_info *cert_parse (u_char *, u_int, tstamp_t);
@@ -160,7 +159,6 @@ static      void    cert_free       (struct cert_info *);
 static EVP_PKEY *crypto_key    (char *, tstamp_t *);
 static int     bighash         (BIGNUM *, BIGNUM *);
 static struct cert_info *crypto_cert (char *);
-static void    crypto_tai      (char *);
 
 #ifdef SYS_WINNT
 int
@@ -177,7 +175,7 @@ readlink(char * link, char * file, int len) {
  * session key is the MD5 hash of these values, while the next key ID is
  * the first four octets of the hash.
  *
- * Returns the next key ID
+ * Returns the next key ID or 0 if there is no destination address.
  */
 keyid_t
 session_key(
@@ -204,8 +202,10 @@ session_key(
        hdlen = 0;
        switch(srcadr->ss_family) {
        case AF_INET:
-               header[0] = ((struct sockaddr_in *)srcadr)->sin_addr.s_addr;
-               header[1] = ((struct sockaddr_in *)dstadr)->sin_addr.s_addr;
+               header[0] =
+                   ((struct sockaddr_in *)srcadr)->sin_addr.s_addr;
+               header[1] =
+                   ((struct sockaddr_in *)dstadr)->sin_addr.s_addr;
                header[2] = htonl(keyno);
                header[3] = htonl(private);
                hdlen = 4 * sizeof(u_int32);
@@ -247,6 +247,7 @@ session_key(
  * Returns
  * XEVNT_OK    success
  * XEVNT_PER   host certificate expired
+ * XEVNT_ERR   protocol error
  *
  * This routine constructs a pseudo-random sequence by repeatedly
  * hashing the session key starting from a given source address,
@@ -266,12 +267,12 @@ make_keylist(
        struct value *vp;       /* value pointer */
        keyid_t keyid = 0;      /* next key ID */
        keyid_t cookie;         /* private value */
-       u_long  lifetime;
+       long    lifetime;
        u_int   len, mpoll;
        int     i;
 
        if (!dstadr)
-               return XEVNT_OK;
+               return XEVNT_ERR;
        
        /*
         * Allocate the key list if necessary.
@@ -286,8 +287,10 @@ make_keylist(
         * NTP_MAXKEY.
         */
        while (1) {
-               keyid = (ntp_random() + NTP_MAXKEY + 1) & ((1 <<
-                   sizeof(keyid_t)) - 1);
+               keyid = ntp_random() & 0xffffffff;
+               if (keyid <= NTP_MAXKEY)
+                       continue;
+
                if (authhavekey(keyid))
                        continue;
                break;
@@ -310,10 +313,10 @@ make_keylist(
                peer->keylist[i] = keyid;
                peer->keynumber = i;
                keyid = session_key(&dstadr->sin, &peer->srcadr, keyid,
-                   cookie, lifetime);
+                   cookie, lifetime + mpoll);
                lifetime -= mpoll;
                if (auth_havekey(keyid) || keyid <= NTP_MAXKEY ||
-                   lifetime <= mpoll)
+                   lifetime < 0)
                        break;
        }
 
@@ -369,6 +372,11 @@ make_keylist(
  * valid length and is verified. There are a few cases where some values
  * are believed even if the signature fails, but only if the proventic
  * bit is not set.
+ *
+ * Returns
+ * XEVNT_OK    success
+ * XEVNT_LEN   bad field format or length
+ * XEVNT_ERR   protocol error
  */
 int
 crypto_recv(
@@ -413,12 +421,12 @@ crypto_recv(
                ep = (struct exten *)pkt;
                code = ntohl(ep->opcode) & 0xffff0000;
                len = ntohl(ep->opcode) & 0x0000ffff;
-               associd = (associd_t) ntohl(pkt[1]);
+               associd = (associd_t)ntohl(pkt[1]);
                rval = XEVNT_OK;
 #ifdef DEBUG
                if (debug)
                        printf(
-                           "crypto_recv: flags 0x%x ext offset %d len %u code 0x%x assocID %d\n",
+                           "crypto_recv: flags 0x%x ext offset %d len %u code 0x%x associd %d\n",
                            peer->crypto, authlen, len, code >> 16,
                            associd);
 #endif
@@ -437,7 +445,7 @@ crypto_recv(
                 * fake association ID over the fence, we better toss it
                 * out. Only the first one counts.
                 */
-               if (code & CRYPTO_RESP) {
+               if (!(code & CRYPTO_RESP)) {
                        if (peer->assoc == 0)
                                peer->assoc = associd;
                        else if (peer->assoc != associd)
@@ -863,7 +871,7 @@ crypto_recv(
                         * Decrypt the cookie, hunting all the time for
                         * errors.
                         */
-                       if (vallen == (u_int) EVP_PKEY_size(host_pkey)) {
+                       if (vallen == (u_int)EVP_PKEY_size(host_pkey)) {
                                RSA_private_decrypt(vallen,
                                    (u_char *)ep->pkt,
                                    (u_char *)&temp32,
@@ -1054,26 +1062,25 @@ crypto_recv(
                        peer->tai_leap.vallen = ep->vallen;
 
                        /*
-                        * Install the new table if there is no stored
-                        * table or the new table is more recent than
-                        * the stored table. Since a filestamp may have
-                        * changed, recompute the signatures.
+                        * If the packet leap values are more recent
+                        * that the stored ones, install the new leap
+                        * values and changed, recompute the signatures.
                         */
-                       if (ntohl(peer->tai_leap.fstamp) >
-                           ntohl(tai_leap.fstamp)) {
+                       if (ntohl(ep->pkt[2]) > leap_expire) {
+                               tai_leap.tstamp = ep->tstamp;
                                tai_leap.fstamp = ep->fstamp;
                                tai_leap.vallen = ep->vallen;
-                               if (tai_leap.ptr != NULL)
-                                       free(tai_leap.ptr);
-                               tai_leap.ptr = emalloc(vallen);
-                               memcpy(tai_leap.ptr, ep->pkt, vallen);
+                               leap_tai = ntohl(ep->pkt[0]);
+                               leap_ins = ntohl(ep->pkt[1]);
+                               leap_expire = ntohl(ep->pkt[2]);
                                crypto_update();
                        }
-                       crypto_flags |= CRYPTO_FLAG_TAI;
                        peer->crypto |= CRYPTO_FLAG_LEAP;
                        peer->flash &= ~TEST8;
-                       sprintf(statstr, "leap %u ts %u fs %u", vallen,
-                           ntohl(ep->tstamp), ntohl(ep->fstamp));
+                       sprintf(statstr,
+                           "leap tai %d add %u expire %u fs %u",
+                           ntohl(ep->pkt[0]), ntohl(ep->pkt[1]),
+                           ntohl(ep->pkt[2]), ntohl(ep->fstamp));
                        record_crypto_stats(&peer->srcadr, statstr);
 #ifdef DEBUG
                        if (debug)
@@ -1142,7 +1149,7 @@ crypto_recv(
                } else if (rval > XEVNT_OK && (code & CRYPTO_RESP)) {
                        rval = XEVNT_OK;
                }
-               authlen += len;
+               authlen += (len + 3) / 4 * 4;
        }
        return (rval);
 }
@@ -1156,13 +1163,20 @@ crypto_recv(
  * autokey information, in which case the caller has to provide the
  * association ID to match the association.
  *
- * Returns length of extension field.
+ * Side effect: update the packet offset.
+ *
+ * Returns
+ * XEVNT_OK    success
+ * XEVNT_LEN   bad field format or length
+ * XEVNT_CRT   bad or missing certificate
+ * XEVNT_ERR   protocol error
+ * XEVNT_SRV   server certificate expired
  */
 int
 crypto_xmit(
        struct pkt *xpkt,       /* transmit packet pointer */
        struct sockaddr_storage *srcadr_sin,    /* active runway */
-       int     start,          /* offset to extension field */
+       int     *start,         /* offset to extension field */
        struct exten *ep,       /* extension pointer */
        keyid_t cookie          /* session cookie */
        )
@@ -1187,11 +1201,11 @@ crypto_xmit(
         * and association ID. If this is a response and the host is not
         * synchronized, light the error bit and go home.
         */
-       pkt = (u_int32 *)xpkt + start / 4;
+       pkt = (u_int32 *)xpkt + *start / 4;
        fp = (struct exten *)pkt;
        opcode = ntohl(ep->opcode);
        associd = (associd_t) ntohl(ep->associd);
-       fp->associd = htonl(associd);
+       fp->associd = ep->associd;
        len = 8;
        rval = XEVNT_OK;
        tstamp = crypto_time();
@@ -1203,12 +1217,12 @@ crypto_xmit(
         * contains only the status word.
         */
        case CRYPTO_ASSOC | CRYPTO_RESP:
-               len += crypto_send(fp, &hostval);
+               rval = crypto_send(fp, &hostval, &len);
                fp->fstamp = htonl(crypto_flags);
                break;
 
        case CRYPTO_ASSOC:
-               len += crypto_send(fp, &hostval);
+               rval = crypto_send(fp, &hostval, &len);
                fp->fstamp = htonl(crypto_flags | ident_scheme);
                break;
 
@@ -1222,7 +1236,7 @@ crypto_xmit(
                vtemp.fstamp = ep->fstamp;
                vtemp.vallen = ep->vallen;
                vtemp.ptr = (u_char *)ep->pkt;
-               len += crypto_send(fp, &vtemp);
+               rval = crypto_send(fp, &vtemp, &len);
                break;
 
        /*
@@ -1291,7 +1305,7 @@ crypto_xmit(
                else if (tstamp < xp->first || tstamp > xp->last)
                        rval = XEVNT_SRV;
                else
-                       len += crypto_send(fp, &xp->cert);
+                       rval = crypto_send(fp, &xp->cert, &len);
                break;
 
        /*
@@ -1303,7 +1317,7 @@ crypto_xmit(
                        break;
                }
                if ((rval = crypto_alice(peer, &vtemp)) == XEVNT_OK) {
-                       len += crypto_send(fp, &vtemp);
+                       rval = crypto_send(fp, &vtemp, &len);
                        value_free(&vtemp);
                }
                break;
@@ -1313,7 +1327,7 @@ crypto_xmit(
         */
        case CRYPTO_IFF | CRYPTO_RESP:
                if ((rval = crypto_bob(ep, &vtemp)) == XEVNT_OK) {
-                       len += crypto_send(fp, &vtemp);
+                       rval = crypto_send(fp, &vtemp, &len);
                        value_free(&vtemp);
                }
                break;
@@ -1327,7 +1341,7 @@ crypto_xmit(
                        break;
                }
                if ((rval = crypto_alice2(peer, &vtemp)) == XEVNT_OK) {
-                       len += crypto_send(fp, &vtemp);
+                       rval = crypto_send(fp, &vtemp, &len);
                        value_free(&vtemp);
                }
                break;
@@ -1337,7 +1351,7 @@ crypto_xmit(
         */
        case CRYPTO_GQ | CRYPTO_RESP:
                if ((rval = crypto_bob2(ep, &vtemp)) == XEVNT_OK) {
-                       len += crypto_send(fp, &vtemp);
+                       rval = crypto_send(fp, &vtemp, &len);
                        value_free(&vtemp);
                }
                break;
@@ -1351,7 +1365,7 @@ crypto_xmit(
                        break;
                }
                if ((rval = crypto_alice3(peer, &vtemp)) == XEVNT_OK) {
-                       len += crypto_send(fp, &vtemp);
+                       rval = crypto_send(fp, &vtemp, &len);
                        value_free(&vtemp);
                }
                break;
@@ -1361,7 +1375,7 @@ crypto_xmit(
         */
        case CRYPTO_MV | CRYPTO_RESP:
                if ((rval = crypto_bob3(ep, &vtemp)) == XEVNT_OK) {
-                       len += crypto_send(fp, &vtemp);
+                       rval = crypto_send(fp, &vtemp, &len);
                        value_free(&vtemp);
                }
                break;
@@ -1376,7 +1390,7 @@ crypto_xmit(
         */
        case CRYPTO_SIGN | CRYPTO_RESP:
                if ((rval = cert_sign(ep, &vtemp)) == XEVNT_OK)
-                       len += crypto_send(fp, &vtemp);
+                       rval = crypto_send(fp, &vtemp, &len);
                value_free(&vtemp);
                break;
 
@@ -1385,7 +1399,7 @@ crypto_xmit(
         * key.
         */
        case CRYPTO_COOK:
-               len += crypto_send(fp, &pubkey);
+               rval = crypto_send(fp, &pubkey, &len);
                break;
 
        /*
@@ -1408,7 +1422,7 @@ crypto_xmit(
                }
                if ((rval = crypto_encrypt(ep, &vtemp, &tcookie)) ==
                    XEVNT_OK)
-                       len += crypto_send(fp, &vtemp);
+                       rval = crypto_send(fp, &vtemp, &len);
                value_free(&vtemp);
                break;
 
@@ -1425,7 +1439,7 @@ crypto_xmit(
                        break;
                }
                peer->flags &= ~FLAG_ASSOC;
-               len += crypto_send(fp, &peer->sndval);
+               rval = crypto_send(fp, &peer->sndval, &len);
                break;
 
        /*
@@ -1435,8 +1449,7 @@ crypto_xmit(
         */
        case CRYPTO_TAI:
        case CRYPTO_TAI | CRYPTO_RESP:
-               if (crypto_flags & CRYPTO_FLAG_TAI)
-                       len += crypto_send(fp, &tai_leap);
+               rval = crypto_send(fp, &tai_leap, &len);
                break;
 
        /*
@@ -1447,6 +1460,7 @@ crypto_xmit(
                if (opcode & CRYPTO_RESP)
                        rval = XEVNT_ERR;
        }
+       fp->opcode = htonl((opcode & 0xffff0000) | len);
 
        /*
         * In case of error, flame the log. If a request, toss the
@@ -1464,20 +1478,14 @@ crypto_xmit(
                if (!(opcode & CRYPTO_RESP))
                        return (0);
        }
-
-       /*
-        * Round up the field length to a multiple of 8 bytes and save
-        * the request code and length.
-        */
-       len = ((len + 7) / 8) * 8;
-       fp->opcode = htonl((opcode & 0xffff0000) | len);
 #ifdef DEBUG
        if (debug)
                printf(
-                   "crypto_xmit: flags 0x%x ext offset %d len %u code 0x%x assocID %d\n",
-                   crypto_flags, start, len, opcode >> 16, associd);
+                   "crypto_xmit: flags 0x%x ext offset %d len %u code 0x%x associd %d\n",
+                   crypto_flags, *start, len, opcode >> 16, associd);
 #endif
-       return (len);
+       *start += len;
+       return (rval);
 }
 
 
@@ -1702,6 +1710,12 @@ crypto_encrypt(
  *
  * This routine determines which identity scheme is in use and
  * constructs an extension field for that scheme.
+ *
+ * Returns
+ * CRYTPO_IFF  IFF scheme
+ * CRYPTO_GQ   GQ scheme
+ * CRYPTO_MV   MV scheme
+ * CRYPTO_NULL no available scheme
  */
 u_int
 crypto_ident(
@@ -1766,7 +1780,7 @@ crypto_ident(
         */
        msyslog(LOG_INFO,
            "crypto_ident: no compatible identity scheme found");
-       return (0);
+       return (CRYPTO_NULL);
 }
 
 
@@ -1803,13 +1817,10 @@ crypto_args(
        ep->opcode = htonl(opcode + len);
 
        /*
-        * If a response, send our ID; if a request, send the
-        * responder's ID.
+        * If a request, send our ID; if a response, send the
+        * requestor's ID.
         */
-       if (opcode & CRYPTO_RESP)
-               ep->associd = htonl(peer->associd);
-       else
-               ep->associd = htonl(peer->assoc);
+       ep->associd = htonl(peer->associd);
        ep->tstamp = htonl(tstamp);
        ep->fstamp = hostval.tstamp;
        ep->vallen = 0;
@@ -1826,43 +1837,71 @@ crypto_args(
 /*
  * crypto_send - construct extension field from value components
  *
- * Returns extension field length. Note: it is not polite to send a
- * nonempty signature with zero timestamp or a nonzero timestamp with
- * empty signature, but these rules are not enforced here.
+ * The value and signature fields are zero-padded to a word boundary.
+ * Note: it is not polite to send a nonempty signature with zero
+ * timestamp or a nonzero timestamp with an empty signature, but those
+ * rules are not enforced here.
+ *
+ * Returns
+ * XEVNT_OK    success
+ * XEVNT_LEN   bad field format or length
  */
 u_int
 crypto_send(
        struct exten *ep,       /* extension field pointer */
-       struct value *vp        /* value pointer */
+       struct value *vp,       /* value pointer */
+       int     *start          /* buffer offset */
        )
 {
-       u_int   len, temp32;
-       int     i;
+       u_int   len, vallen, siglen;
+       int     i, j;
 
        /*
-        * Copy data. If the data field is empty or zero length, encode
-        * an empty value with length zero.
+        * Calculate extension field length and check for buffer
+        * overflow. Leave room for the MAC.
+        */
+       len = 16;
+       vallen = ntohl(vp->vallen);
+       len += ((vallen + 3) / 4 + 1) * 4; 
+       siglen = ntohl(vp->siglen);
+       len += ((siglen + 3) / 4 + 1) * 4; 
+       if (*start + len > NTP_MAXEXTEN - LEN_PKT_NOMAC - MAX_MAC_LEN)
+               return (XEVNT_LEN);
+
+       /*
+        * Copy timestamps.
         */
        ep->tstamp = vp->tstamp;
        ep->fstamp = vp->fstamp;
        ep->vallen = vp->vallen;
-       len = 12;
-       temp32 = ntohl(vp->vallen);
-       if (temp32 > 0 && vp->ptr != NULL)
-               memcpy(ep->pkt, vp->ptr, temp32);
+
+       /*
+        * Copy value. If the data field is empty or zero length,
+        * encode an empty value with length zero.
+        */
+       i = 0;
+       if (vallen > 0 && vp->ptr != NULL) {
+               j = vallen / 4;
+               if (j * 4 < vallen)
+                       ep->pkt[i + j++] = 0;
+               memcpy(&ep->pkt[i], vp->ptr, vallen);
+               i += j;
+       }
 
        /*
         * Copy signature. If the signature field is empty or zero
         * length, encode an empty signature with length zero.
         */
-       i = (temp32 + 3) / 4;
-       len += i * 4 + 4;
        ep->pkt[i++] = vp->siglen;
-       temp32 = ntohl(vp->siglen);
-       if (temp32 > 0 && vp->sig != NULL)
-               memcpy(&ep->pkt[i], vp->sig, temp32);
-       len += temp32;
-       return (len);
+       if (siglen > 0 && vp->sig != NULL) {
+               j = vallen / 4;
+               if (j * 4 < siglen)
+                       ep->pkt[i + j++] = 0;
+               memcpy(&ep->pkt[i], vp->sig, siglen);
+               i += j;
+       }
+       *start += len;
+       return (XEVNT_OK);
 }
 
 
@@ -1876,7 +1915,7 @@ crypto_send(
  * hostval     host name (not signed)
  * pubkey      public key
  * cinfo       certificate info/value list
- * tai_leap    leapseconds file
+ * tai_leap    leap values
  *
  * Filestamps are proventicated data, so this routine is run only when
  * the host has been synchronized to a proventicated source. Thus, the
@@ -1892,6 +1931,7 @@ crypto_update(void)
        struct cert_info *cp, *cpn; /* certificate info/value */
        char    statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
        tstamp_t tstamp;        /* NTP timestamp */
+       u_int32 *ptr;
        u_int   len;
 
        if ((tstamp = crypto_time()) == 0)
@@ -1937,22 +1977,28 @@ crypto_update(void)
        }
 
        /*
-        * Sign leapseconds table and timestamps. The filestamp is
-        * derived from the leapsecond file extension from wherever the
-        * file was generated.
+        * Sign leapseconds values and timestamps. Note it is not an
+        * error to return null values.
         */
-       if (tai_leap.vallen != 0) {
-               tai_leap.tstamp = hostval.tstamp;
-               tai_leap.siglen = 0;
-               if (tai_leap.sig == NULL)
-                       tai_leap.sig = emalloc(sign_siglen);
-               EVP_SignInit(&ctx, sign_digest);
-               EVP_SignUpdate(&ctx, (u_char *)&tai_leap, 12);
-               EVP_SignUpdate(&ctx, tai_leap.ptr,
-                   ntohl(tai_leap.vallen));
-               if (EVP_SignFinal(&ctx, tai_leap.sig, &len, sign_pkey))
-                       tai_leap.siglen = htonl(len);
-       }
+       tai_leap.tstamp = hostval.tstamp;
+       tai_leap.fstamp = hostval.tstamp;
+       len = 3 * sizeof(u_int32);
+       if (tai_leap.ptr == NULL)
+               tai_leap.ptr = emalloc(len);
+       tai_leap.vallen = htonl(len);
+       ptr = (u_int32 *)tai_leap.ptr;
+       ptr[0] = htonl(leap_tai);
+       ptr[1] = htonl(leap_ins);
+       ptr[2] = htonl(leap_expire);
+       if (tai_leap.sig == NULL)
+               tai_leap.sig = emalloc(sign_siglen);
+       EVP_SignInit(&ctx, sign_digest);
+       EVP_SignUpdate(&ctx, (u_char *)&tai_leap, 12);
+       EVP_SignUpdate(&ctx, tai_leap.ptr, len);
+       if (EVP_SignFinal(&ctx, tai_leap.sig, &len, sign_pkey))
+               tai_leap.siglen = htonl(len);
+       if (leap_tai > 0)
+               crypto_flags |= CRYPTO_FLAG_TAI;
        sprintf(statstr, "update ts %u", ntohl(hostval.tstamp)); 
        record_crypto_stats(NULL, statstr);
 #ifdef DEBUG
@@ -2006,13 +2052,10 @@ asn2ntp (
        char    *v;             /* pointer to ASN1_TIME string */
        struct  tm tm;          /* used to convert to NTP time */
 
-       NTP_REQUIRE(asn1time != NULL);
-       NTP_REQUIRE(asn1time->data != NULL);
-
        /*
         * Extract time string YYMMDDHHMMSSZ from ASN1 time structure.
         * Note that the YY, MM, DD fields start with one, the HH, MM,
-        * SS fields start with zero and the Z character should be 'Z'
+        * SS fiels start with zero and the Z character should be 'Z'
         * for UTC. Also note that years less than 50 map to years
         * greater than 100. Dontcha love ASN.1? Better than MIL-188.
         */
@@ -2056,9 +2099,7 @@ bighash(
        EVP_DigestUpdate(&ctx, ptr, len);
        EVP_DigestFinal(&ctx, dgst, &len);
        BN_bin2bn(dgst, len, bk);
-
-       /* XXX MEMLEAK? free ptr? */
-
+       free(ptr);
        return (1);
 }
 
@@ -3098,8 +3139,6 @@ cert_parse(
        cnt = X509_get_ext_count(cert);
        for (i = 0; i < cnt; i++) {
                ext = X509_get_ext(cert, i);
-               NTP_INSIST(ext != NULL);
-               NTP_INSIST(ext->value != NULL);
                method = X509V3_EXT_get(ext);
                temp = OBJ_obj2nid(ext->object);
                switch (temp) {
@@ -3734,134 +3773,6 @@ crypto_cert(
 }
 
 
-/*
- * crypto_tai - load leapseconds table from file
- *
- * This routine loads the ERTS leapsecond file in NIST text format,
- * converts to a value structure and extracts a filestamp from the file
- * name. The data are used to establish the TAI offset from UTC, which
- * is provided to the kernel if supported. Later the data can be sent to
- * another machine on request.
- */
-static void
-crypto_tai(
-       char    *cp             /* file name */
-       )
-{
-       FILE    *str;           /* file handle */
-       char    buf[NTP_MAXSTRLEN];     /* file line buffer */
-       u_int32 leapsec[MAX_LEAP]; /* NTP time at leaps */
-       u_long  expire;         /* NTP time when file expires */
-       int     offset;         /* offset at leap (s) */
-       char    filename[MAXFILENAME]; /* name of leapseconds file */
-       char    linkname[MAXFILENAME]; /* file link (for filestamp) */
-       char    statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
-       tstamp_t fstamp;        /* filestamp */
-       u_int   len;
-       u_int32 *ptr;
-       char    *dp;
-       int     rval, i, j;
-
-       /*
-        * Open the file and discard comment lines. If the first
-        * character of the file name is not '/', prepend the keys
-        * directory string. If the file is not found, not to worry; it
-        * can be retrieved over the net. But, if it is found with
-        * errors, we crash and burn.
-        */
-       if (*cp == '/')
-               strcpy(filename, cp);
-       else
-               snprintf(filename, MAXFILENAME, "%s/%s", keysdir, cp);
-       if ((str = fopen(filename, "r")) == NULL)
-               return;
-
-       /*
-        * Extract filestamp if present.
-        */
-       rval = readlink(filename, linkname, MAXFILENAME - 1);
-       if (rval > 0) {
-               linkname[rval] = '\0';
-               dp = strrchr(linkname, '.');
-       } else {
-               dp = strrchr(filename, '.');
-       }
-       if (dp != NULL)
-               sscanf(++dp, "%u", &fstamp);
-       else
-               fstamp = 0;
-       tai_leap.fstamp = htonl(fstamp);
-
-       /*
-        * We are rather paranoid here, since an intruder might cause a
-        * coredump by infiltrating naughty values. Empty lines and
-        * comments are ignored. Other lines must begin with two
-        * integers followed by junk or comments. The first integer is
-        * the NTP seconds of leap insertion, the second is the offset
-        * of TAI relative to UTC after that insertion. The second word
-        * must equal the initial insertion of ten seconds on 1 January
-        * 1972 plus one second for each succeeding insertion.
-        */
-       i = TAI_1972;
-       expire = 0;
-       while (i < MAX_LEAP) {
-               dp = fgets(buf, NTP_MAXSTRLEN - 1, str);
-               if (dp == NULL)
-                       break;
-
-               if (strlen(buf) < 1)
-                       continue;
-
-               if (buf[0] == '#') {
-                       if (buf[1] == '@') {
-                               if (sscanf(&buf[2], "%lu", &expire) !=
-                                   1)
-                                       break;
-                       }
-               }
-               continue;
-
-               if (sscanf(buf, "%u %d", &leapsec[i], &offset) != 2)
-                       continue;
-
-               if (i != offset) 
-                       break;
-
-               i++;
-       }
-       fclose(str);
-       if (dp != NULL) {
-               msyslog(LOG_INFO,
-                   "crypto_tai: leapseconds file %s error %d", cp,
-                   rval);
-               exit (-1);
-       }
-
-       /*
-        * The extension field table entries consists of the NTP seconds
-        * of leap insertion in network byte order.
-        */
-       len = i * sizeof(u_int32);
-       tai_leap.vallen = htonl(len);
-       ptr = emalloc(len);
-       tai_leap.ptr = (u_char *)ptr;
-       for (j = 0; j < i; j++)
-               *ptr++ = htonl(leapsec[j]);
-       sys_tai = offset;
-       leap_ins = leapsec[--j];
-       leap_expire = expire;
-       crypto_flags |= CRYPTO_FLAG_TAI;
-       sprintf(statstr,
-            "%s fs %u leap %lu tai %d expire %lu len %u", cp,
-           fstamp, leap_ins, sys_tai, leap_expire, len);
-       record_crypto_stats(NULL, statstr);
-#ifdef DEBUG
-       if (debug)
-               printf("crypto_tai: %s\n", statstr);
-#endif
-}
-
-
 /*
  * crypto_setup - load keys, certificate and leapseconds table
  *
@@ -4068,7 +3979,7 @@ crypto_setup(void)
 
        /*
         * It the certificate is trusted, the subject must be the same
-        * as the issuer, in other words it must be self signed.
+        * as the issuer, in other words it must be self-signed.
         */
        if (cinfo->flags & CERT_TRUST && strcmp(cinfo->subject,
            cinfo->issuer) != 0) {
@@ -4084,15 +3995,6 @@ crypto_setup(void)
        if (cinfo->flags & CERT_PRIV)
                crypto_flags |= CRYPTO_FLAG_PRIV;
        crypto_flags |= cinfo->nid << 16;
-
-       /*
-        * Load optional leapseconds table from file "ntpkey_leap". If
-        * the file is missing or defective, the values can later be
-        * retrieved from a server.
-        */
-       if (leap_file == NULL)
-               leap_file = "ntpkey_leap";
-       crypto_tai(leap_file);
 #ifdef DEBUG
        if (debug)
                printf(
@@ -4188,14 +4090,6 @@ crypto_config(
                cert_file = emalloc(strlen(cp) + 1);
                strcpy(cert_file, cp);
                break;
-
-       /*
-        * Set leapseconds file name.
-        */
-       case CRYPTO_CONF_LEAP:
-               leap_file = emalloc(strlen(cp) + 1);
-               strcpy(leap_file, cp);
-               break;
        }
        crypto_flags |= CRYPTO_FLAG_ENAB;
 }
index 122234e4c49c4641a8e2b63fe2586b6638e6f814..267da6651272536273bc56360efc045507c2ead2 100644 (file)
@@ -159,6 +159,7 @@ int state;                  /* clock discipline state */
 u_char sys_poll = NTP_MINDPOLL; /* time constant/poll (log2 s) */
 int    tc_counter;             /* jiggle counter */
 double last_offset;            /* last offset (s) */
+int    clock_stepcnt;          /* step counter */
 
 /*
  * Huff-n'-puff filter variables
@@ -225,12 +226,6 @@ local_clock(
         * monitor and record the offsets anyway in order to determine
         * the open-loop response and then go home.
         */
-#ifdef DEBUG
-       if (debug)
-               printf(
-                   "local_clock: assocID %d offset %.9f freq %.3f state %d\n",
-                   peer->associd, fp_offset, drift_comp * 1e6, state);
-#endif
 #ifdef LOCKCLOCK
        return (0);
 
@@ -402,7 +397,8 @@ local_clock(
                        sys_poll = NTP_MINPOLL;
                        clock_jitter = LOGTOD(sys_precision);
                        rval = 2;
-                       if (state == S_NSET) {
+                       clock_stepcnt++;
+                       if (state == S_NSET || clock_stepcnt > 2) {
                                rstclock(S_FREQ, peer->epoch, 0);
                                return (rval);
                        }
@@ -783,8 +779,9 @@ rstclock(
 {
 #ifdef DEBUG
        if (debug)
-               printf("local_clock: time %lu offset %.6f freq %.3f state %d\n",
-                   update, offset, drift_comp * 1e6, trans);
+               printf("local_clock: at %lu offset %.6f freq %.3f state %d step %d\n",
+                   update, offset, drift_comp * 1e6, trans,
+                   clock_stepcnt);
 #endif
        state = trans;
        sys_clocktime = update;
index c7ded70ccef676461a756557726253800c5502f9..21473c36f24a353e93525bc7283464a04986212a 100644 (file)
@@ -302,8 +302,8 @@ clear_all(void)
        for (n = 0; n < NTP_HASH_SIZE; n++) {
                for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
                        next_peer = peer->next;
-                       if (!(peer->cast_flags & (MDF_ACAST | MDF_MCAST |
-                           MDF_BCAST))) {
+                       if (!(peer->cast_flags & (MDF_ACAST |
+                           MDF_MCAST | MDF_BCAST))) {
                                peer->hpoll = peer->minpoll;
                                peer_clear(peer, "STEP");
                        }
@@ -329,7 +329,8 @@ unpeer(
        char    statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
 
        if (peer_to_remove->flags & FLAG_SKEY) {
-               sprintf(statstr, "unpeer %d flash %x reach %03o flags %04x",
+               sprintf(statstr,
+                   "unpeer %d flash %x reach %03o flags %04x",
                    peer_to_remove->associd, peer_to_remove->flash,
                    peer_to_remove->reach, peer_to_remove->flags);
                record_crypto_stats(&peer_to_remove->srcadr, statstr);
@@ -345,9 +346,6 @@ unpeer(
                    peer_associations, peer_preempt);
 #endif
        set_peerdstadr(peer_to_remove, NULL);
-
-       /* XXXMEMLEAK? peer_clear->crypto allocation */
-
        hash = NTP_HASH_ADDR(&peer_to_remove->srcadr);
        peer_hash_count[hash]--;
        peer_demobilizations++;
@@ -362,19 +360,20 @@ unpeer(
                refclock_unpeer(peer_to_remove);
 #endif
        peer_to_remove->action = 0;     /* disable timeout actions */
-       if (peer_hash[hash] == peer_to_remove)
+       if (peer_hash[hash] == peer_to_remove) {
                peer_hash[hash] = peer_to_remove->next;
-       else {
+       else {
                register struct peer *peer;
 
                peer = peer_hash[hash];
                while (peer != 0 && peer->next != peer_to_remove)
-                   peer = peer->next;
+                       peer = peer->next;
                
                if (peer == 0) {
                        peer_hash_count[hash]++;
-                       msyslog(LOG_ERR, "peer struct for %s not in table!",
-                               stoa(&peer->srcadr));
+                       msyslog(LOG_ERR,
+                           "peer struct for %s not in table!",
+                           stoa(&peer->srcadr));
                } else {
                        peer->next = peer_to_remove->next;
                }
@@ -385,9 +384,9 @@ unpeer(
         */
        hash = peer_to_remove->associd & NTP_HASH_MASK;
        assoc_hash_count[hash]--;
-       if (assoc_hash[hash] == peer_to_remove)
+       if (assoc_hash[hash] == peer_to_remove) {
                assoc_hash[hash] = peer_to_remove->ass_next;
-       else {
+       else {
                register struct peer *peer;
 
                peer = assoc_hash[hash];
@@ -397,7 +396,7 @@ unpeer(
                if (peer == 0) {
                        assoc_hash_count[hash]++;
                        msyslog(LOG_ERR,
-                               "peer struct for %s not in association table!",
+                           "peer struct for %s not in association table!",
                                stoa(&peer->srcadr));
                } else {
                        peer->ass_next = peer_to_remove->ass_next;
@@ -442,9 +441,11 @@ peer_config(
                while (peer != 0) {
                        if (peer->dstadr == dstadr)
                                break;
+
                        if (dstadr == ANY_INTERFACE_CHOOSE(srcadr) &&
                            peer->dstadr == findinterface(srcadr))
-                            break;
+                               break;
+
                        peer = findexistingpeer(srcadr, peer, hmode);
                }
        }
@@ -502,7 +503,7 @@ peer_config(
                peer->minpoll = (u_char) minpoll;
                peer->maxpoll = (u_char) maxpoll;
                peer->flags = flags | FLAG_CONFIG |
-                       (peer->flags & FLAG_REFCLOCK);
+                   (peer->flags & FLAG_REFCLOCK);
                peer->cast_flags = cast_flags;
                peer->ttl = (u_char) ttl;
                peer->keyid = key;
@@ -535,29 +536,29 @@ set_peerdstadr(struct peer *peer, struct interface *interface)
                    (interface->flags & INT_MCASTIF) &&
                    peer->burst) {
                        /*
-                        * don't accept updates to a true multicast reception
-                        * interface while a BCLNT peer is running it's
-                        * unicast protocol
+                        * don't accept updates to a true multicast
+                        * reception interface while a BCLNT peer is
+                        * running it's unicast protocol
                         */
                        return;
                }
 
-               if (peer->dstadr != NULL)
-               {
+               if (peer->dstadr != NULL) {
                        peer->dstadr->peercnt--;
-                       ISC_LIST_UNLINK_TYPE(peer->dstadr->peers, peer, ilink, struct peer);
+                       ISC_LIST_UNLINK_TYPE(peer->dstadr->peers, peer,
+                           ilink, struct peer);
                }
 
                DPRINTF(4, ("set_peerdstadr(%s): change interface from %s to %s\n",
                            stoa(&peer->srcadr),
-                           (peer->dstadr != NULL) ? stoa(&peer->dstadr->sin) : "<null>",
-                           (interface != NULL) ? stoa(&interface->sin) : "<null>"));
-
+                           (peer->dstadr != NULL) ?
+                           stoa(&peer->dstadr->sin) : "<null>",
+                           (interface != NULL) ?
+                           stoa(&interface->sin) : "<null>"));
                peer->dstadr = interface;
-
-               if (peer->dstadr != NULL)
-               {
-                       ISC_LIST_APPEND(peer->dstadr->peers, peer, ilink);
+               if (peer->dstadr != NULL) {
+                       ISC_LIST_APPEND(peer->dstadr->peers, peer,
+                           ilink);
                        peer->dstadr->peercnt++;
                }
        }
@@ -571,53 +572,45 @@ peer_refresh_interface(struct peer *peer)
 {
        struct interface *niface, *piface;
 
-       niface = select_peerinterface(peer, &peer->srcadr, NULL, peer->cast_flags);
+       niface = select_peerinterface(peer, &peer->srcadr, NULL,
+           peer->cast_flags);
 
 #ifdef DEBUG
        if (debug > 3)
        {
                printf(
-                       "peer_refresh_interface: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %d key %08x: new interface: ",
-                       peer->dstadr == NULL ? "<null>" : stoa(&peer->dstadr->sin),
-                       stoa(&peer->srcadr),
-                       peer->hmode, peer->version, peer->minpoll,
-                       peer->maxpoll, peer->flags, peer->cast_flags,
-                       peer->ttl, peer->keyid);
-               if (niface != NULL) 
-               {
-                       printf("fd=%d, bfd=%d, name=%.16s, flags=0x%x, scope=%d, ",
-                              niface->fd,
-                              niface->bfd,
-                              niface->name,
-                              niface->flags,
-                              niface->scopeid);
+                   "peer_refresh_interface: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %d key %08x: new interface: ",
+                   peer->dstadr == NULL ? "<null>" :
+                   stoa(&peer->dstadr->sin), stoa(&peer->srcadr),
+                   peer->hmode, peer->version, peer->minpoll,
+                   peer->maxpoll, peer->flags, peer->cast_flags,
+                   peer->ttl, peer->keyid);
+               if (niface != NULL) {
+                       printf(
+                           "fd=%d, bfd=%d, name=%.16s, flags=0x%x, scope=%d, ",
+                           niface->fd,  niface->bfd, niface->name,
+                           niface->flags, niface->scopeid);
                        /* Leave these as three printf calls. */
-                       printf(", sin=%s",
-                              stoa((&niface->sin)));
+                       printf(", sin=%s", stoa((&niface->sin)));
                        if (niface->flags & INT_BROADCAST)
                                printf(", bcast=%s,",
-                                      stoa((&niface->bcast)));
-                       printf(", mask=%s\n",
-                              stoa((&niface->mask)));
-               }
-               else
-               {
+                                   stoa((&niface->bcast)));
+                       printf(", mask=%s\n", stoa((&niface->mask)));
+               } else {
                        printf("<NONE>\n");
                }
        }
 #endif
 
        piface = peer->dstadr;
-
        set_peerdstadr(peer, niface);
-
        if (peer->dstadr) {
                 /*
                  * clear crypto if we change the local address
                  */
-                if (peer->dstadr != piface && !(peer->cast_flags & MDF_BCLNT)) {
-                       peer_crypto_clear(peer);
-               }
+                if (peer->dstadr != piface && !(peer->cast_flags &
+                   MDF_BCLNT))
+                       peer_clear(peer, "XFAC");
 
                /*
                 * Broadcast needs the socket enabled for broadcast
@@ -627,10 +620,12 @@ peer_refresh_interface(struct peer *peer)
                }
 
                /*
-                * Multicast needs the socket interface enabled for multicast
+                * Multicast needs the socket interface enabled for
+                * multicast
                 */
                if (peer->cast_flags & MDF_MCAST) {
-                       enable_multicast_if(peer->dstadr, &peer->srcadr);
+                       enable_multicast_if(peer->dstadr,
+                           &peer->srcadr);
                }
        }
 }
@@ -682,20 +677,22 @@ select_peerinterface(struct peer *peer, struct sockaddr_storage *srcadr, struct
                        if (debug > 3) {
                                if (interface != NULL)
                                        printf("Found *-cast interface address %s, for address %s\n",
-                                              stoa(&(interface)->sin), stoa(srcadr));
+                                           stoa(&(interface)->sin), stoa(srcadr));
                                else
                                        printf("No *-cast local address found for address %s\n",
                                               stoa(srcadr));
                        }
 #endif
                        /*
-                        * If it was a multicast packet, findbcastinter() may not
-                        * find it, so try a little harder.
+                        * If it was a multicast packet,
+                        * findbcastinter() may not find it, so try a
+                        * little harder.
                         */
                        if (interface == ANY_INTERFACE_CHOOSE(srcadr))
                                interface = findinterface(srcadr);
                }
-               else if (dstadr != NULL && dstadr != ANY_INTERFACE_CHOOSE(srcadr))
+               else if (dstadr != NULL && dstadr !=
+                   ANY_INTERFACE_CHOOSE(srcadr))
                        interface = dstadr;
                else
                        interface = findinterface(srcadr);
@@ -760,7 +757,8 @@ newpeer(
 
        ISC_LINK_INIT(peer, ilink);  /* set up interface link chain */
 
-       set_peerdstadr(peer, select_peerinterface(peer, srcadr, dstadr, cast_flags));
+       set_peerdstadr(peer, select_peerinterface(peer, srcadr, dstadr,
+           cast_flags));
        
        peer->srcadr = *srcadr;
        peer->hmode = (u_char)hmode;
@@ -768,12 +766,12 @@ newpeer(
        peer->minpoll = (u_char)max(NTP_MINPOLL, minpoll);
        peer->maxpoll = (u_char)min(NTP_MAXPOLL, maxpoll);
        peer->flags = flags;
-
 #ifdef DEBUG
        if (debug > 2) {
                if (peer->dstadr)
                        printf("newpeer: using fd %d and our addr %s\n",
-                              peer->dstadr->fd, stoa(&peer->dstadr->sin));
+                              peer->dstadr->fd,
+                                   stoa(&peer->dstadr->sin));
                else
                        printf("newpeer: local interface currently not bound\n");
        }
@@ -916,7 +914,7 @@ peer_unconfig(
 }
 
 /*
- * peer_clr_stats - clear peer module stat counters
+ * peer_clr_stats - clear peer module statiistics counters
  */
 void
 peer_clr_stats(void)
@@ -929,7 +927,7 @@ peer_clr_stats(void)
 }
 
 /*
- * peer_reset - reset stat counters in a peer structure
+ * peer_reset - reset statistics counters
  */
 void
 peer_reset(
@@ -950,7 +948,7 @@ peer_reset(
 
 
 /*
- * peer_all_reset - reset all peer stat counters
+ * peer_all_reset - reset all peer statistics counters
  */
 void
 peer_all_reset(void)
@@ -980,7 +978,7 @@ expire_all(void)
         * peer list for all associations and flush only the key list
         * and cookie. If a manycast client association, flush
         * everything. Then, recompute and sign the agreement public
-        * value, if present.
+        * values, if present, and refresh the leap values.
         */
        if (!crypto_flags)
                return;
@@ -995,7 +993,8 @@ expire_all(void)
                            peer->hmode == MODE_PASSIVE) {
                                key_expire(peer);
                                peer->crypto &= ~(CRYPTO_FLAG_AUTO |
-                                   CRYPTO_FLAG_AGREE);
+                                   CRYPTO_FLAG_AGREE |
+                                   CRYPTO_FLAG_LEAP);
                        }
                                
                }
index 135563580477c9752bec73fa2e6144cb30486ab4..56254b287f4cb3bb87e291a77b6d0d1c1be8ebba 100644 (file)
@@ -17,7 +17,9 @@
 #include <stdio.h>
 #ifdef HAVE_LIBSCF_H
 #include <libscf.h>
-#endif
+#include <unistd.h>
+#endif /* HAVE_LIBSCF_H */
+
 
 #if defined(VMS) && defined(VMS_LOCALUNIT)     /*wjm*/
 #include "ntp_refclock.h"
@@ -51,9 +53,6 @@ struct        peer *sys_pps;          /* our PPS peer */
 struct peer *sys_prefer;       /* our cherished peer */
 int    sys_kod;                /* kod credit */
 int    sys_kod_rate = 2;       /* max kod packets per second */
-#ifdef OPENSSL
-u_long sys_automax;            /* maximum session key lifetime */
-#endif /* OPENSSL */
 
 /*
  * Nonspecified system state variables.
@@ -69,6 +68,7 @@ static        double sys_maxdist = MAXDISTANCE; /* selection threshold (s) */
 double sys_jitter;             /* system jitter (s) */
 static int sys_hopper;         /* anticlockhop counter */
 static int sys_maxhop = MAXHOP; /* anticlockhop counter threshold */
+int    leap_tai;               /* TAI at next next leap */
 u_long leap_ins;               /* seconds at next leap */
 u_long leap_expire;            /* seconds leapfile expires */
 u_long leap_sec;               /* leap countdown */
@@ -117,7 +117,7 @@ static      void    peer_xmit       (struct peer *);
 static void    fast_xmit       (struct recvbuf *, int, keyid_t,
                                    int);
 static void    clock_update    (void);
-static int     default_get_precision   (void);
+static int     default_get_precision (void);
 static int     peer_unfit      (struct peer *);
 
 
@@ -309,7 +309,7 @@ transmit(
                                peer_ntpdate--;
                                if (peer_ntpdate == 0) {
                                        msyslog(LOG_NOTICE,
-                                           "no reply; clock not set");
+                                           "proto: no reply; clock not set");
                                        exit (0);
                                }
                        }
@@ -547,20 +547,20 @@ receive(
                is_authentic = AUTH_NONE; /* not required */
 #ifdef DEBUG
                if (debug)
-                       printf("receive: at %ld %s<-%s mode %d code %d auth %d\n",
+                       printf("receive: at %ld %s<-%s mode %d len %d\n",
                            current_time, stoa(dstadr_sin),
-                           stoa(&rbufp->recv_srcadr), hismode, retcode,
-                           is_authentic);
+                           stoa(&rbufp->recv_srcadr), hismode,
+                           authlen);
 #endif
        } else if (has_mac == 4) {
                        is_authentic = AUTH_CRYPTO; /* crypto-NAK */
 #ifdef DEBUG
                if (debug)
                        printf(
-                           "receive: at %ld %s<-%s mode %d code %d keyid %08x len %d mac %d auth %d\n",
+                           "receive: at %ld %s<-%s mode %d keyid %08x len %d auth %d\n",
                            current_time, stoa(dstadr_sin),
-                           stoa(&rbufp->recv_srcadr), hismode, retcode,
-                           skeyid, authlen, has_mac, is_authentic);
+                           stoa(&rbufp->recv_srcadr), hismode, skeyid,
+                           authlen + has_mac, is_authentic);
 #endif
        } else {
 #ifdef OPENSSL
@@ -666,10 +666,10 @@ receive(
 #ifdef DEBUG
                if (debug)
                        printf(
-                           "receive: at %ld %s<-%s mode %d code %d keyid %08x len %d mac %d auth %d\n",
+                           "receive: at %ld %s<-%s mode %d keyid %08x len %d auth %d\n",
                            current_time, stoa(dstadr_sin),
-                           stoa(&rbufp->recv_srcadr), hismode, retcode,
-                           skeyid, authlen, has_mac, is_authentic);
+                           stoa(&rbufp->recv_srcadr), hismode, skeyid,
+                           authlen + has_mac, is_authentic);
 #endif
        }
 
@@ -952,7 +952,7 @@ receive(
        /*
         * Update the origin and destination timestamps. If
         * unsynchronized or bogus abandon ship. If the crypto machine
-        * breaks, light the crypto bit and plaint the log.
+        * breaks, demobilize the association and wait for calmer seas.
         */
        peer->org = p_xmt;
        peer->rec = rbufp->recv_time;
@@ -960,10 +960,8 @@ receive(
 #ifdef OPENSSL
                if (crypto_flags && (peer->flags & FLAG_SKEY)) {
                        rval = crypto_recv(peer, rbufp);
-                       if (rval != XEVNT_OK) {
+                       if (rval != XEVNT_OK)
                                peer_clear(peer, "CRYP");
-                               peer->flash |= TEST9; /* crypto error */
-                       }
                }
 #endif /* OPENSSL */
                return;                         /* unsynch */
@@ -1083,12 +1081,10 @@ receive(
         * the packet over the fence for processing, which may light up
         * more flashers.
         */
-       process_packet(peer, pkt);
+       process_packet(peer, pkt, rbufp->recv_length);
 
        /*
-        * Well, that was nice. If TEST4 is lit, either the crypto
-        * machine jammed or a kiss-o'-death packet flew in, either of
-        * which is fatal.
+        * Well, that was nice. If TEST4 is lit access was denied.
         */
        if (peer->flash & TEST4) {
                msyslog(LOG_INFO, "receive: fatal error %04x for %s",
@@ -1107,7 +1103,8 @@ receive(
 void
 process_packet(
        register struct peer *peer,
-       register struct pkt *pkt
+       register struct pkt *pkt,
+       u_int   len
        )
 {
        double  t34, t21;
@@ -1116,6 +1113,10 @@ process_packet(
        l_fp    ci;
        u_char  pmode, pleap, pstratum;
 
+       double  etemp, ftemp;   /* experimental */
+       int     itemp;
+       double  td;
+
        sys_processed++;
        peer->processed++;
        p_del = FPTOD(NTOHS_FP(pkt->rootdelay));
@@ -1138,14 +1139,16 @@ process_packet(
                if (memcmp(&pkt->refid, "DENY", 4) == 0) {
                        peer_clear(peer, "DENY");
                        peer->flash |= TEST4;   /* access denied */
+                       return;
                }
        }
 
        /*
         * Capture the header values.
         */
-       record_raw_stats(&peer->srcadr, peer->dstadr ? &peer->dstadr->sin : NULL, &p_org,
-           &p_rec, &p_xmt, &peer->rec);
+       record_raw_stats(&peer->srcadr, peer->dstadr ?
+           &peer->dstadr->sin : NULL, &p_org, &p_rec, &p_xmt,
+           &peer->rec);
        peer->leap = pleap;
        peer->stratum = min(pstratum, STRATUM_UNSPEC);
        peer->pmode = pmode;
@@ -1224,6 +1227,69 @@ process_packet(
        ci = peer->rec;                 /* t4 - t1 */
        L_SUB(&ci, &p_org);
 
+       /*
+        * This code calculates the outbound and inbound data rates by
+        * measuring the differences between timestamps at different
+        * packet lengths. This is helpful in cases of large asymmetric
+        * delays commonly experienced on deep space communication
+        * links.
+        */
+       if (peer->t21_last > 0 && peer->t34_bytes > 0) {
+               itemp = peer->t21_bytes - peer->t21_last;
+               if (itemp > 25) {
+                       etemp = t21 - peer->t21;
+                       if (fabs(etemp) > 1e-6) {
+                               ftemp = itemp / etemp;
+                               if (ftemp > 1000.)
+                                       peer->r21 = ftemp;
+                       }
+               }
+               itemp = len - peer->t34_bytes;
+               if (itemp > 25) {
+                       etemp = -t34 - peer->t34;
+                       if (fabs(etemp) > 1e-6) {
+                               ftemp = itemp / etemp;
+                               if (ftemp > 1000.)
+                                       peer->r34 = ftemp;
+                       }
+               }
+       }
+       peer->t21 = t21;
+       peer->t21_last = peer->t21_bytes;
+       peer->t34 = -t34;
+       peer->t34_bytes = len;
+       p_del = t21 - t34;
+#ifdef DEBUG
+       if (debug > 1)
+               printf("proto: t21 %.6lf %d t34 %.6lf %d\n", peer->t21,
+                   peer->t21_bytes, peer->t34, peer->t34_bytes);
+#endif
+
+       /*
+        * The following section compensates for different data rates on
+        * the outbound (d21) and inbound (t34) directions. To do this,
+        * it finds t such that r21 * t - r34 * (d - t) = 0, where d is
+        * the roundtrip delay. Then it calculates the correction as a
+        * fraction of d.
+        */
+       if (peer->r21 > 0 && peer->r34 > 0 && p_del > 0) {
+               if (pmode != MODE_BROADCAST)
+                       td = (peer->r34 / (peer->r21 + peer->r34) -
+                           .5) * p_del;
+               else
+                       td = 0;
+#if 0 /* temporarily disabled */
+               t21 -= td;
+               t34 -= td;
+#endif
+#ifdef DEBUG
+               if (debug > 1)
+                       printf("proto: del %.6lf r21 %.1lf r34 %.1lf %.6lf\n",
+                           p_del, peer->r21 / 1e3, peer->r34 / 1e3,
+                           td);
+#endif
+       } 
+
        /*
         * If running in a broadcast association, the clock offset is
         * (t1 - t0) corrected by the one-way delay, but we can't
@@ -1247,7 +1313,6 @@ process_packet(
                p_disp = 0;
        } else {
                p_offset = (t21 + t34) / 2.;
-               p_del = t21 - t34;
                LFPTOD(&ci, p_disp);
                p_disp = LOGTOD(sys_precision) +
                    LOGTOD(peer->precision) + clock_phi * p_disp;
@@ -1265,13 +1330,12 @@ process_packet(
 static void
 clock_update(void)
 {
-       u_char  oleap;
        u_char  ostratum;
        double  dtemp;
        l_fp    now;
 #ifdef HAVE_LIBSCF_H
-       char *fmri;
-#endif
+       char    *fmri;
+#endif /* HAVE_LIBSCF_H */
 
        /*
         * There must be a system peer at this point. If we just changed
@@ -1288,10 +1352,9 @@ clock_update(void)
 
 #ifdef DEBUG
        if (debug)
-               printf("clock_update: at %ld assoc %d \n", current_time,
-                   peer_associations);
+               printf("clock_update: at %lu associd %d leap %lu TAI %d\n",
+                   current_time, sys_peer->associd, leap_sec, sys_tai);
 #endif
-       oleap = sys_leap;
        ostratum = sys_stratum;
        switch (local_clock(sys_peer, sys_offset)) {
 
@@ -1301,18 +1364,22 @@ clock_update(void)
        case -1:
                report_event(EVNT_SYSFAULT, NULL);
 #ifdef HAVE_LIBSCF_H
-               /* enter the maintenance mode */
-               if ((fmri = getenv("SMF_FMRI")) != NULL) {
-                       if (smf_maintain_instance(fmri, 0) < 0) {
-                               printf("smf_maintain_instance:%s\n",
-                                   scf_strerror(scf_error()));
-                               exit(1);
-                       }
-                       /* sleep until SMF kills us */
-                       for (;;)
-                               pause();
-               }
-#endif
+               /*
+                * For Solaris enter the maintenance mode.
+                */
+               if ((fmri = getenv("SMF_FMRI")) != NULL) {
+                       if (smf_maintain_instance(fmri, 0) < 0) {
+                               printf("smf_maintain_instance: %s\n",
+                                   scf_strerror(scf_error()));
+                               exit(1);
+                       }
+                       /*
+                        * Sleep until SMF kills us.
+                        */
+                       for (;;)
+                               pause();
+               }
+#endif /* HAVE_LIBSCF_H */
                exit (-1);
                /* not reached */
 
@@ -1323,9 +1390,10 @@ clock_update(void)
                clear_all();
                sys_leap = LEAP_NOTINSYNC;
                sys_stratum = STRATUM_UNSPEC;
-               sys_peer = NULL;
                sys_rootdelay = 0;
                sys_rootdispersion = 0;
+               L_CLR(&sys_reftime);
+               sys_jitter = LOGTOD(sys_precision);
                memcpy(&sys_refid, "STEP", 4);
                report_event(EVNT_CLOCKRESET, NULL);
                break;
@@ -1342,19 +1410,19 @@ clock_update(void)
                sys_reftime = sys_peer->rec;
 
                /*
-                * If a leapseconds file is not present or expired and
-                * the number of upstream server leap bits is at least
-                * the sanity threshold, schedule a leap for the end of
-                * the current month.
+                * If a leapseconds file is not present and the number
+                * of survivor leap bits is greater than half the number
+                * of survivors, schedule a leap for the end of the
+                * current month.
                 */
                get_systime(&now);
-               if (now.l_ui > leap_expire) {
-                       if (leap_next >= sys_minsane) {
+               if (leap_ins == 0) {
+                       if (leap_next > sys_survivors / 2) {
                                if (!leap_sw) {
                                        leap_sw++;
                                        leap_sec = leap_month(now.l_ui);
                                        msyslog(LOG_NOTICE,
-                                           "leap second armed %lu s",
+                                           "proto: leap second armed %lu s",
                                            leap_sec);
                                }
                        } else {
@@ -1363,28 +1431,29 @@ clock_update(void)
                        }
 
                /*
-                * If a leapseconds file is present and not expired and
-                * a future leap is scheduled, decrement the TAI offset.
-                * If the kernel code is available and enabled, pass the
-                * TAI offset to the kernel. If less than 28 days remain
-                * to the leap, schedule a leap when the leapseconds
-                * counter expires.
+                * If a leapseconds file is present and a future leap is
+                * indicated, decrement the TAI offset. If the kernel
+                * code is available and enabled, pass the TAI offset to
+                * the kernel. If less than 28 days remain to the leap,
+                * schedule a leap when the leapseconds counter expires.
                 */
                } else if (leap_sec == 0) {
                        if (leap_ins > now.l_ui) {
                                if (leap_ins - now.l_ui < 28 * 86400) {
                                        leap_sec = leap_ins - now.l_ui;
                                        msyslog(LOG_NOTICE,
-                                           "leap second armed %lu s",
+                                           "proto: leap second armed %lu s",
                                            leap_sec);
                                }
-                               if (!leap_sw)
-                                       sys_tai--;
+                               sys_tai = leap_tai - 1;
+                       } else {
+                               sys_tai = leap_tai;
                        }
                        if (!leap_sw) {
                                leap_sw++;
                                msyslog(LOG_NOTICE,
-                                   "TAI offset %d s", sys_tai);
+                                   "proto: TAI offset %d s at %u",
+                                   sys_tai, now.l_ui);
 #ifdef KERNEL_PLL
                                if (pll_control && kern_enable)
                                        loop_config(LOOP_LEAP, 0);
@@ -1394,10 +1463,13 @@ clock_update(void)
 
                /*
                 * If this is the first time the clock is set,
-                * reset the leap bits.
+                * reset the leap bits. If crypto, the timer will goose
+                * the setup process.
                 */
-               if (sys_leap == LEAP_NOTINSYNC)
+               if (sys_leap == LEAP_NOTINSYNC) {
                        sys_leap = LEAP_NOWARNING;
+                       report_event(EVNT_SYNCCHG, NULL);
+               }
 
                /*
                 * In orphan mode the stratum defaults to the orphan
@@ -1427,13 +1499,6 @@ clock_update(void)
                        sys_rootdispersion = dtemp +
                            sys_peer->rootdispersion;
                }
-               if (oleap == LEAP_NOTINSYNC) {
-                       report_event(EVNT_SYNCCHG, NULL);
-#ifdef OPENSSL
-                       expire_all();
-                       crypto_update();
-#endif /* OPENSSL */
-               }
                break;
        /*
         * Popcorn spike or step threshold exceeded. Pretend it never
@@ -1553,14 +1618,30 @@ poll_update(
 #endif
 }
 
+
 /*
- * peer_crypto_clear - discard crypto information
+ * peer_clear - clear peer filter registers.  See Section 3.4.8 of the spec.
  */
 void
-peer_crypto_clear(
-                 struct peer *peer
-                 )
+peer_clear(
+       struct peer *peer,              /* peer structure */
+       char    *ident                  /* tally lights */
+       )
 {
+       int     i;
+#ifdef OPENSSL
+       char    statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
+#endif /* OPENSSL */
+
+       if (peer == sys_peer)
+               sys_peer = NULL;
+
+       /*
+        * Wipe the association clean and initialize the nonzero values.
+        */
+       memset(CLEAR_TO_ZERO(peer), 0, LEN_CLEAR_TO_ZERO);
+
+#ifdef OPENSSL
        /*
         * If cryptographic credentials have been acquired, toss them to
         * Valhalla. Note that autokeys are ephemeral, in that they are
@@ -1570,10 +1651,6 @@ peer_crypto_clear(
         * purged, too. This makes it much harder to sneak in some
         * unauthenticated data in the clock filter.
         */
-       DPRINTF(1, ("peer_crypto_clear: at %ld next %ld assoc ID %d\n",
-                   current_time, peer->nextdate, peer->associd));
-
-#ifdef OPENSSL
        peer->assoc = 0;
        peer->crypto = 0;
        if (peer->pkey != NULL)
@@ -1607,28 +1684,6 @@ peer_crypto_clear(
        key_expire(peer);
        value_free(&peer->encrypt);
 #endif /* OPENSSL */
-}
-
-/*
- * peer_clear - clear peer filter registers.  See Section 3.4.8 of the spec.
- */
-void
-peer_clear(
-       struct peer *peer,              /* peer structure */
-       char    *ident                  /* tally lights */
-       )
-{
-       int     i;
-
-       peer_crypto_clear(peer);
-       
-       if (peer == sys_peer)
-               sys_peer = NULL;
-
-       /*
-        * Wipe the association clean and initialize the nonzero values.
-        */
-       memset(CLEAR_TO_ZERO(peer), 0, LEN_CLEAR_TO_ZERO);
        peer->estbdelay = sys_bdelay;
        peer->ppoll = peer->maxpoll;
        peer->hpoll = peer->minpoll;
@@ -1664,9 +1719,14 @@ peer_clear(
        else
                peer->nextdate += (ntp_random() & ((1 << NTP_MINDPOLL) -
                    1));
-
-       DPRINTF(1, ("peer_clear: at %ld next %ld assoc ID %d refid %s\n",
-                   current_time, peer->nextdate, peer->associd, ident));
+#ifdef OPENSSL
+       sprintf(statstr, "clear %d ident %s", peer->associd,
+           ident);
+               record_crypto_stats(&peer->srcadr, statstr);
+#endif /* OPENSSL */
+       DPRINTF(1, ("peer_clear: at %ld next %ld associd %d refid %s\n",
+                   current_time, peer->nextdate, peer->associd,
+                   ident));
 }
 
 
@@ -1852,10 +1912,11 @@ clock_filter(
 /*
  * clock_select - find the pick-of-the-litter clock
  *
- * LOCKCLOCK: If the local clock is the prefer peer, it will always be
- * enabled, even if declared falseticker, (2) only the prefer peer can
- * be selected as the system peer, (3) if the external source is down,
- * the system leap bits are set to 11 and the stratum set to infinity.
+ * LOCKCLOCK: (1) If the local clock is the prefer peer, it will always
+ * be enabled, even if declared falseticker, (2) only the prefer peer
+ * can be selected as the system peer, (3) if the external source is
+ * down, the system leap bits are set to 11 and the stratum set to
+ * infinity.
  */
 void
 clock_select(void)
@@ -2520,15 +2581,16 @@ peer_xmit(
        if (!(peer->flags & FLAG_AUTHENABLE)) {
                get_systime(&peer->xmt);
                HTONL_FP(&peer->xmt, &xpkt.xmt);
+               peer->t21_bytes = sendlen;
                sendpkt(&peer->srcadr, peer->dstadr, sys_ttl[peer->ttl],
                    &xpkt, sendlen);
                peer->sent++;
 #ifdef DEBUG
                if (debug)
-                       printf("transmit: at %ld %s->%s mode %d\n",
+                       printf("transmit: at %ld %s->%s mode %d len %d\n",
                            current_time, peer->dstadr ?
                            stoa(&peer->dstadr->sin) : "-",
-                           stoa(&peer->srcadr), peer->hmode);
+                           stoa(&peer->srcadr), peer->hmode, sendlen);
 #endif
                return;
        }
@@ -2555,7 +2617,7 @@ peer_xmit(
                 * messages have the same code as the request, but have
                 * a response bit and possibly an error bit set. In this
                 * implementation, a message may contain no more than
-                * one command and no more than one response.
+                * one command and one or more responses.
                 *
                 * Cryptographic session keys include both a public and
                 * a private componet. Request and response messages
@@ -2581,10 +2643,10 @@ peer_xmit(
                         * identifier to verify authenticity.
                         *
                         * If for some reason a key is no longer in the
-                        * key cache, a birthday has happened and the
-                        * pseudo-random sequence is probably broken. In
-                        * that case, purge the keylist and regenerate
-                        * it.
+                        * key cache, a birthday has happened or the key
+                        * has expired, so the pseudo-random sequence is
+                        * broken. In that case, purge the keylist and
+                        * regenerate it.
                         */
                        if (peer->keynumber == 0)
                                make_keylist(peer, peer->dstadr);
@@ -2629,7 +2691,7 @@ peer_xmit(
                 */
                case MODE_ACTIVE:
                case MODE_PASSIVE:
-                       if (peer->flash & TEST9)
+                       if (peer->flash & (TEST4 | TEST9))
                                break;
                        /*
                         * Parameter and certificate.
@@ -2669,13 +2731,13 @@ peer_xmit(
                            peer->leap != LEAP_NOTINSYNC &&
                            !(peer->crypto & CRYPTO_FLAG_AGREE))
                                exten = crypto_args(peer, CRYPTO_COOK,
-                                                   NULL);
+                                   NULL);
                        else if (peer->flags & FLAG_ASSOC)
                                exten = crypto_args(peer, CRYPTO_AUTO |
-                                                   CRYPTO_RESP, NULL);
+                                   CRYPTO_RESP, NULL);
                        else if (!(peer->crypto & CRYPTO_FLAG_AUTO))
                                exten = crypto_args(peer, CRYPTO_AUTO,
-                                                   NULL);
+                                   NULL);
 
                        /*
                         * Postamble. We trade leapseconds only when the
@@ -2683,7 +2745,6 @@ peer_xmit(
                         */
                        else if (sys_leap != LEAP_NOTINSYNC &&
                            peer->leap != LEAP_NOTINSYNC &&
-                           peer->crypto & CRYPTO_FLAG_TAI &&
                            !(peer->crypto & CRYPTO_FLAG_LEAP))
                                exten = crypto_args(peer, CRYPTO_TAI,
                                    NULL);
@@ -2710,7 +2771,7 @@ peer_xmit(
                 * If the crypto bit is lit, don't send requests.
                 */
                case MODE_CLIENT:
-                       if (peer->flash & TEST9)
+                       if (peer->flash & (TEST4 | TEST9))
                                break;
                        /*
                         * Parameter and certificate.
@@ -2723,18 +2784,20 @@ peer_xmit(
                                    peer->issuer);
 
                        /*
-                        * Identity
+                        * Identity. Nothing special here.
                         */
                        else if (!(peer->crypto & CRYPTO_FLAG_VRFY))
                                exten = crypto_args(peer,
                                    crypto_ident(peer), NULL);
 
                        /*
-                        * Autokey
+                        * Cookie and autokey data. In broadcast client
+                        * mode we request the autokey values now to
+                        * avoid having to wait for the next key list.
                         */
                        else if (!(peer->crypto & CRYPTO_FLAG_AGREE))
                                exten = crypto_args(peer, CRYPTO_COOK,
-                                                   NULL);
+                                   NULL);
                        else if (!(peer->crypto & CRYPTO_FLAG_AUTO) &&
                            (peer->cast_flags & MDF_BCLNT))
                                exten = crypto_args(peer, CRYPTO_AUTO,
@@ -2745,11 +2808,10 @@ peer_xmit(
                         * since there is no chance of deadlock.
                         */
                        else if (sys_leap != LEAP_NOTINSYNC &&
-                                !(peer->crypto & CRYPTO_FLAG_SIGN))
+                               !(peer->crypto & CRYPTO_FLAG_SIGN))
                                exten = crypto_args(peer, CRYPTO_SIGN,
-                                                   sys_hostname);
+                                   sys_hostname);
                        else if (sys_leap != LEAP_NOTINSYNC &&
-                           peer->crypto & CRYPTO_FLAG_TAI &&
                            !(peer->crypto & CRYPTO_FLAG_LEAP))
                                exten = crypto_args(peer, CRYPTO_TAI,
                                    NULL);
@@ -2765,24 +2827,15 @@ peer_xmit(
                 */
                if (peer->cmmd != NULL) {
                        peer->cmmd->associd = htonl(peer->associd);
-                       sendlen += crypto_xmit(&xpkt, &peer->srcadr,
-                                              sendlen, peer->cmmd, 0);
+                       crypto_xmit(&xpkt, &peer->srcadr, &sendlen,
+                           peer->cmmd, 0);
                        free(peer->cmmd);
                        peer->cmmd = NULL;
                }
                if (exten != NULL) {
-                       int ltemp = 0;
-
-                       if (exten->opcode != 0) {
-                               ltemp = crypto_xmit(&xpkt,
-                                   &peer->srcadr, sendlen, exten, 0);
-                               if (ltemp == 0) {
-                                       peer->flash |= TEST9; /* crypto error */
-                                       free(exten);
-                                       return;
-                               }
-                       }
-                       sendlen += ltemp;
+                       if (exten->opcode != 0)
+                               crypto_xmit(&xpkt, &peer->srcadr,
+                                   &sendlen, exten, 0);
                        free(exten);
                }
 
@@ -2805,8 +2858,7 @@ peer_xmit(
        /*
         * Stash the transmit timestamp corrected for the encryption
         * delay. If autokey, give back the key, as we use keys only
-        * once. Check for errors such as missing keys, buffer overflow,
-        * etc.
+        * once. Check for errors such as missing keys, etc.
         */
        xkeyid = peer->keyid;
        get_systime(&peer->xmt);
@@ -2829,6 +2881,7 @@ peer_xmit(
                msyslog(LOG_ERR, "buffer overflow %u", sendlen);
                exit (-1);
        }
+       peer->t21_bytes = sendlen;
        sendpkt(&peer->srcadr, peer->dstadr, sys_ttl[peer->ttl], &xpkt,
            sendlen);
 
@@ -2848,20 +2901,19 @@ peer_xmit(
 #ifdef OPENSSL
 #ifdef DEBUG
        if (debug)
-               printf("transmit: at %ld %s->%s mode %d keyid %08x len %d mac %d index %d\n",
+               printf("transmit: at %ld %s->%s mode %d keyid %08x len %d index %d\n",
                    current_time, peer->dstadr ?
                    ntoa(&peer->dstadr->sin) : "-",
-                   ntoa(&peer->srcadr), peer->hmode, xkeyid, sendlen -
-                   authlen, authlen, peer->keynumber);
+                   ntoa(&peer->srcadr), peer->hmode, xkeyid, sendlen,
+                   peer->keynumber);
 #endif
-#else
+#else /* OPENSSL */
 #ifdef DEBUG
        if (debug)
-               printf("transmit: at %ld %s->%s mode %d keyid %08x len %d mac %d\n",
+               printf("transmit: at %ld %s->%s mode %d keyid %08x len %d\n",
                    current_time, peer->dstadr ?
                    ntoa(&peer->dstadr->sin) : "-",
-                   ntoa(&peer->srcadr), peer->hmode, xkeyid, sendlen -
-                   authlen, authlen);
+                   ntoa(&peer->srcadr), peer->hmode, xkeyid, sendlen);
 #endif
 #endif /* OPENSSL */
 }
@@ -2879,10 +2931,10 @@ fast_xmit(
        int     mask            /* restrict mask */
        )
 {
-       struct pkt xpkt;                /* transmit packet structure */
-       struct pkt *rpkt;               /* receive packet structure */
-       l_fp    xmt_ts;                 /* timestamp */
-       l_fp    xmt_tx;                 /* timestamp after authent */
+       struct pkt xpkt;        /* transmit packet structure */
+       struct pkt *rpkt;       /* receive packet structure */
+       l_fp    xmt_ts;         /* timestamp */
+       l_fp    xmt_tx;         /* timestamp after authent */
        int     sendlen, authlen;
 #ifdef OPENSSL
        u_int32 temp32;
@@ -2963,7 +3015,7 @@ fast_xmit(
 
        /*
         * This is an orphan parent. Show leap synchronized, orphan
-        * stratum, loopack reference ID and zero root delay.
+        * stratum, loopback reference ID and zero root delay.
         */
        } else {
                xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
@@ -2993,9 +3045,9 @@ fast_xmit(
                    sendlen);
 #ifdef DEBUG
                if (debug)
-                       printf("transmit: at %ld %s->%s mode %d\n",
+                       printf("transmit: at %ld %s->%s mode %d len %d\n",
                            current_time, stoa(&rbufp->dstadr->sin),
-                           stoa(&rbufp->recv_srcadr), xmode);
+                           stoa(&rbufp->recv_srcadr), xmode, sendlen);
 #endif
                return;
        }
@@ -3029,9 +3081,9 @@ fast_xmit(
                            &rbufp->recv_srcadr, xkeyid, 0, 2);
                        temp32 = CRYPTO_RESP;
                        rpkt->exten[0] |= htonl(temp32);
-                       sendlen += crypto_xmit(&xpkt,
-                           &rbufp->recv_srcadr, sendlen,
-                           (struct exten *)rpkt->exten, cookie);
+                       crypto_xmit(&xpkt, &rbufp->recv_srcadr,
+                           &sendlen, (struct exten *)rpkt->exten,
+                           cookie);
                } else {
                        session_key(&rbufp->dstadr->sin,
                            &rbufp->recv_srcadr, xkeyid, cookie, 2);
@@ -3048,10 +3100,6 @@ fast_xmit(
                authtrust(xkeyid, 0);
 #endif /* OPENSSL */
        get_systime(&xmt_tx);
-       if (sendlen > sizeof(xpkt)) {
-               msyslog(LOG_ERR, "buffer overflow %u", sendlen);
-               exit (-1);
-       }
        sendpkt(&rbufp->recv_srcadr, rbufp->dstadr, 0, &xpkt, sendlen);
 
        /*
@@ -3069,10 +3117,9 @@ fast_xmit(
 #ifdef DEBUG
        if (debug)
                printf(
-                   "transmit: at %ld %s->%s mode %d keyid %08x len %d mac %d\n",
+                   "transmit: at %ld %s->%s mode %d keyid %08x len %d\n",
                    current_time, ntoa(&rbufp->dstadr->sin),
-                   ntoa(&rbufp->recv_srcadr), xmode, xkeyid, sendlen -
-                   authlen, authlen);
+                   ntoa(&rbufp->recv_srcadr), xmode, xkeyid, sendlen);
 #endif
 }
 
@@ -3096,6 +3143,7 @@ key_expire(
        }
        value_free(&peer->sndval);
        peer->keynumber = 0;
+       peer->flags &= ~FLAG_ASSOC;
 #ifdef DEBUG
        if (debug)
                printf("key_expire: at %lu\n", current_time);
@@ -3245,22 +3293,23 @@ init_proto(void)
 
        /*
         * Fill in the sys_* stuff.  Default is don't listen to
-        * broadcasting, authenticate.
+        * broadcasting, require authentication.
         */
        sys_leap = LEAP_NOTINSYNC;
        sys_stratum = STRATUM_UNSPEC;
        sys_peer = NULL;
        sys_rootdelay = 0;
        sys_rootdispersion = 0;
+       L_CLR(&sys_reftime);
+       sys_jitter = 0;
+       sys_peer = NULL;
+
        memcpy(&sys_refid, "INIT", 4);
        sys_precision = (s_char)default_get_precision();
-       sys_jitter = LOGTOD(sys_precision);
        sys_orphandelay = (double)(ntp_random() & 0xffff) / 65536. *
            sys_maxdist;
-       L_CLR(&sys_reftime);
-       sys_peer = NULL;
-       sys_survivors = 0;
        get_systime(&dummy);
+       sys_survivors = 0;
        sys_manycastserver = 0;
        sys_bclient = 0;
        sys_bdelay = DEFBROADDELAY;
@@ -3274,9 +3323,6 @@ init_proto(void)
                sys_ttl[i] = (u_char)((i * 256) / MAX_TTL);
                sys_ttlmax = i;
        }
-#ifdef OPENSSL
-       sys_automax = 1 << NTP_AUTOMAX;
-#endif /* OPENSSL */
        pps_enable = 0;
        stats_control = 1;
 }
index 35b843d0b0846892a078f9f4efd00697ecbdcf72..7a51ea2cb673800fd4424a61cbfde2231037c1f4 100644 (file)
 volatile int interface_interval = 300;     /* update interface every 5 minutes as default */
          
 /*
- * Alarm flag. The mainline code imports this.
+ * Alarm flag. The mainline code imports this.
  */
 volatile int alarm_flag;
 
 /*
- * The counters
+ * The counters and timeouts
  */
-static u_long adjust_timer;            /* second timer */
-static u_long keys_timer;              /* minute timer */
-static u_long stats_timer;             /* stats timer */
-static u_long huffpuff_timer;          /* huff-n'-puff timer */
-static  u_long interface_timer;                /* interface update timer */
+static u_long adjust_timer;    /* second timer */
+static u_long stats_timer;     /* stats timer */
+static u_long huffpuff_timer;  /* huff-n'-puff timer */
+static  u_long interface_timer;        /* interface update timer */
 #ifdef OPENSSL
-static u_long revoke_timer;            /* keys revoke timer */
-u_char sys_revoke = KEY_REVOKE;        /* keys revoke timeout (log2 s) */
+static u_long revoke_timer;    /* keys revoke timer */
+u_long sys_revoke = KEY_REVOKE; /* keys revoke timeout */
+static u_long keys_timer;      /* session key timer */
+u_long sys_automax = NTP_AUTOMAX; /* session key timeout */
 #endif /* OPENSSL */
 
 /*
@@ -63,7 +64,8 @@ u_char        sys_revoke = KEY_REVOKE;        /* keys revoke timeout (log2 s) */
 volatile u_long alarm_overflow;
 
 #define MINUTE 60
-#define HOUR   (60 * 60)
+#define HOUR   (60 * MINUTE)
+#define        DAY     (24 * HOUR)
 
 u_long current_time;           /* seconds since startup */
 
@@ -256,7 +258,7 @@ get_timer_handle(void)
 #endif
 
 /*
- * timer - dispatch anyone who needs to be
+ * timer - event timer
  */
 void
 timer(void)
@@ -266,12 +268,15 @@ timer(void)
        char    statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
 #endif /* OPENSSL */
        u_int   n;
-
-       current_time += (1<<EVENT_TIMEOUT);
+       l_fp    now;
 
        /*
-        * Adjustment timeout first.
+        * The basic timerevent is one second. This is used to adjust
+        * the system clock in time and frequency, implement the
+        * kiss-o'-deatch function and implement the association
+        * polling function..
         */
+       current_time += (1<<EVENT_TIMEOUT);
        if (adjust_timer <= current_time) {
                adjust_timer += 1;
                adj_host_clock();
@@ -320,33 +325,26 @@ timer(void)
                sys_leap = LEAP_ADDSECOND;
                leap_sec--;
                if (leap_sec == 0) {
+                       get_systime(&now);
+                       msyslog(LOG_NOTICE, "timer: leap second at %u",
+                           now.l_ui);
                        sys_leap = LEAP_NOWARNING;
                        if (sys_tai > 0) {
                                sys_tai++;
-                               msyslog(LOG_NOTICE, "TAI offset %d s",
-                                   sys_tai);
 #ifdef KERNEL_PLL
                                if (!(pll_control && kern_enable))
                                        step_systime(-1.0);
 #else /* KERNEL_PLL */
                                step_systime(-1.0);
 #endif /* KERNEL_PLL */
+                               msyslog(LOG_NOTICE,
+                                   "timer: TAI offset %d s", sys_tai);
                        }
-                       msyslog(LOG_NOTICE, "leap second %+.6f s",
-                           -1.0);
                }
        }
 
        /*
-        * Garbage collect expired keys.
-        */
-       if (keys_timer <= current_time) {
-               keys_timer += MINUTE;
-               auth_agekeys();
-       }
-
-       /*
-        * Huff-n'-puff filter
+        * Update huff-n'-puff filter.
         */
        if (huffpuff_timer <= current_time) {
                huffpuff_timer += HUFFPUFF;
@@ -354,13 +352,26 @@ timer(void)
        }
 
 #ifdef OPENSSL
+
+       /*
+        * Garbage collect expired keys.
+        */
+       if (keys_timer <= current_time) {
+               keys_timer += sys_automax;
+               auth_agekeys();
+       }
+
        /*
-        * Garbage collect old keys and generate new private value
+        * Garbage collect key list and generate new private value. The
+        * timer runs only after initial synchronization and fires about
+        * once per day.
         */
-       if (revoke_timer <= current_time) {
-               revoke_timer += RANDPOLL(sys_revoke);
+       if (revoke_timer <= current_time && sys_leap !=
+           LEAP_NOTINSYNC) {
+               revoke_timer += sys_revoke;
                expire_all();
-               sprintf(statstr, "refresh ts %u", ntohl(hostval.tstamp));
+               sprintf(statstr, "refresh ts %u",
+                   ntohl(hostval.tstamp));
                record_crypto_stats(NULL, statstr);
 #ifdef DEBUG
                if (debug)
@@ -370,24 +381,24 @@ timer(void)
 #endif /* OPENSSL */
 
        /*
-        * interface update timer
+        * Interface update timer
         */
        if (interface_interval && interface_timer <= current_time) {
-               timer_interfacetimeout(current_time + interface_interval);
+               timer_interfacetimeout(current_time +
+                   interface_interval);
 #ifdef DEBUG
-         if (debug)
-           printf("timer: interface update\n");
+               if (debug > 1)
+                       printf("timer: interface update\n");
 #endif
-         interface_update(NULL, NULL);
+               interface_update(NULL, NULL);
        }
        
        /*
-        * Finally, periodically write stats.
+        * Finally, write stats once per hour.
         */
        if (stats_timer <= current_time) {
-            if (stats_timer != 0)
-                 write_stats();
-            stats_timer += stats_write_period;
+               stats_timer += HOUR;
+               write_stats();
        }
 }
 
index 40d52fe26b8c8549654e7dadb191e24ed89f5187..77dae40734bdca72baffeb57e5fb2e67d00c3e67 100644 (file)
@@ -58,7 +58,8 @@ static        char *key_file_name;            /* keys file name */
 char   *leapseconds_file_name;         /* leapseconds file name */
 char   *stats_drift_file;              /* frequency file name */
 static char *stats_temp_file;          /* temp frequency file name */
-int stats_write_period = 3600;         /* seconds between writes. */
+static double wander_resid;            /* wander threshold */
+double wander_threshold = 1e-7;        /* initial wander threshold */
 
 /*
  * Statistics file stuff
@@ -221,13 +222,31 @@ write_stats(void)
                    sys_poll);
 
        record_sys_stats();
+       clock_stepcnt = 0;
        ftemp = fabs(prev_drift_comp - drift_comp); 
        prev_drift_comp = drift_comp;
        if (ftemp > clock_phi)
                return;
 
        if (stats_drift_file != 0) {
-               if (state == 4) {
+
+               /*
+                * When the frequency file is written, initialize the
+                * wander threshold to a configured initial value.
+                * Thereafter reduce it by a factor of 0.85. When it
+                * drops below the frequency wander, write the frequency
+                * file. This adapts to the prevailing wander yet
+                * minimizes the file writes.
+                */
+               wander_resid *= 0.8;
+#ifdef DEBUG
+               if (debug)
+                       printf("write_stats: wander %.6lf thresh %.6lf, freq %.6lf\n",
+                           clock_stability * 1e6, wander_resid * 1e6,
+                           drift_comp * 1e6);
+#endif
+               if (state == 4 && clock_stability > wander_resid) {
+                       wander_resid = wander_threshold;
                        if ((fp = fopen(stats_temp_file, "w")) == NULL)
                            {
                                msyslog(LOG_ERR, "can't open %s: %m",
@@ -242,7 +261,8 @@ write_stats(void)
 #endif /* SYS_WINNT */
 
 #ifndef NO_RENAME
-                       (void) rename(stats_temp_file, stats_drift_file);
+                       (void) rename(stats_temp_file,
+                           stats_drift_file);
 #else
                        /* we have no rename NFS of ftp in use */
                        if ((fp = fopen(stats_drift_file, "w")) == NULL)
@@ -363,7 +383,7 @@ stats_config(
                        break;
                }
                if (fscanf(fp, "%lf", &old_drift) != 1) {
-                       msyslog(LOG_ERR, "Frequency format error in %s", 
+                       msyslog(LOG_ERR, "frequency format error in %s", 
                            stats_drift_file);
                        old_drift = 1e9;
                        fclose(fp);
@@ -755,7 +775,7 @@ leap_file(
        )
 {
        FILE    *str;           /* file handle */
-       char    buf[NTP_MAXSTRLEN];     /* file line buffer */
+       char    buf[NTP_MAXSTRLEN]; /* file line buffer */
        u_long  leapsec;        /* NTP time at leap */
        u_long  expire;         /* NTP time when file expires */
        int     offset;         /* TAI offset at leap (s) */
@@ -766,10 +786,10 @@ leap_file(
        NTP_REQUIRE(cp != NULL);
 
        /*
-        * Open the file and discard comment lines. If the first
-        * character of the file name is not '/', prepend the keys
-        * directory string. If the file is not found, ignore; if found
-        * with errors, report to the log and ignore.
+        * Open the leapseconds file. If the first character of the
+        * file name is not '/', prepend the keys directory string. If
+        * the file is not found, ignore; if found with errors, report
+        * to the log and ignore.
         */
        if (*cp == '/')
                strcpy(filename, cp);
@@ -785,7 +805,8 @@ leap_file(
         * seconds at the leap, the second is the TAI offset after the
         * leap. The second word must equal the initial insertion of ten
         * seconds on 1 January 1972 plus one second for each succeeding
-        * insertion.
+        * insertion. The line beginning with #@ contains the file
+        * expiration time in NTP seconds.
         */
        i = TAI_1972;
        expire = 0;
@@ -803,8 +824,8 @@ leap_file(
                                    1)
                                        break;
                        }
+                       continue;
                }
-               continue;
 
                if (sscanf(buf, "%lu %d", &leapsec, &offset) != 2)
                        continue;
@@ -815,14 +836,14 @@ leap_file(
        }
        fclose(str);
        if (dp != NULL) {
-               msyslog(LOG_INFO, "leapseconds %s error",  cp);
+               msyslog(LOG_INFO, "leap_file: %s error", cp);
        } else {
-               sys_tai = offset;
+               leap_tai = offset;
                leap_ins = leapsec;
                leap_expire = expire;
                msyslog(LOG_INFO,
-                   "TAI offset %d s at %lu file %s expire %lu",
-                   sys_tai, leap_ins, cp, leap_expire);
+                   "leap_file: %s TAI offset %d s insert %lu expire %lu",
+                   cp, leap_tai, leap_ins, leap_expire);
        }
 }
 
index 192f77760f3213097fdb6a803b13d37db4f9a9e5..957328a1ef2fd724c99485b28492a063a387e7bf 100644 (file)
@@ -368,7 +368,7 @@ acts_message(
        up = (struct actsunit *)pp->unitptr;
 #ifdef DEBUG
        ioctl(pp->io.fd, TIOCMGET, (char *)&modem);
-       sprintf(tbuf, "acts: %04x (%d %d) %lu %s", modem, up->state,
+       sprintf(tbuf, "acts: %04x (%d %d) %d %s", modem, up->state,
            up->timer, strlen(pp->a_lastcode), pp->a_lastcode);
        if (debug)
                printf("%s\n", tbuf);