RFC Errata


Errata Search

 
Source of RFC  
Summary Table Full Records

Found 33 records.

Status: Verified (14)

RFC 5905, "Network Time Protocol Version 4: Protocol and Algorithms Specification", June 2010

Note: This RFC has been updated by RFC 7822, RFC 8573, RFC 9109

Source of RFC: ntp (int)

Errata ID: 3007
Status: Verified
Type: Technical
Publication Format(s) : TEXT

Reported By: Danny Mayer
Date Reported: 2011-10-28
Verifier Name: Brian Haberman
Date Verified: 2012-04-27

Section 7.4 says:

b.  For kiss code RATE, the client MUST immediately reduce its
       polling interval to that server and continue to reduce it each
       time it receives a RATE kiss code.

It should say:

b.  For kiss code RATE, the client MUST immediately increase its
       polling interval to that server and continue to increase it each
       time it receives a RATE kiss code.

Notes:

The client needs to poll the server for new timestamps less often

Errata ID: 3627
Status: Verified
Type: Technical
Publication Format(s) : TEXT

Reported By: Tal Mizrahi
Date Reported: 2013-05-17
Verifier Name: Brian Haberman
Date Verified: 2014-05-16

Section 7.5 says:

In NTPv4, one or more extension fields can be inserted after the 
header and before the MAC, which is always present when an extension 
field is present.

It should say:

In NTPv4, one or more extension fields can be inserted after the 
header and before the MAC, if a MAC is present. If a MAC is not 
present, one or more extension fields can be inserted after the 
header, according to the following rules:
o If the packet includes a single extension field, the length of the 
  extension  field MUST be at least 7 words, i.e., at least 28 octets.
o If the packet includes more than one extension field, the length of 
  the last extension field MUST be at least 28 octets. The length of 
  the other extension fields in this case MUST be at least 16 octets 
  each.

Notes:

The usage of NTP extension fields without authentication is aligned with Section 10 of RFC 5906:

The extension field parser initializes a pointer to the first octet beyond the NTP packet header and calculates the number of octets remaining to the end of the packet If the remaining length is 20 (128-bit digest plus 4-octet key ID) or 22 (160-bit digest plus 4-octet key ID), the remaining data are the MAC and parsing is complete. If the remaining length is greater than 22, an extension field is present. If the remaining length is less than 8 or not a multiple of 4, a format error has occurred and the packet is discarded; otherwise, the parser increments the pointer by the extension field length and then uses the same rules as above to determine whether a MAC is present or another extension field.

Errata ID: 4504
Status: Verified
Type: Technical
Publication Format(s) : TEXT

Reported By: Miroslav Lichvar
Date Reported: 2015-10-15
Verifier Name: Erik Kline
Date Verified: 2022-07-27

Section 7.3 says:

   LI Leap Indicator (leap): 2-bit integer warning of an impending leap
   second to be inserted or deleted in the last minute of the current
   month with values defined in Figure 9.

           +-------+----------------------------------------+
           | Value | Meaning                                |
           +-------+----------------------------------------+
           | 0     | no warning                             |
           | 1     | last minute of the day has 61 seconds  |
           | 2     | last minute of the day has 59 seconds  |

It should say:

   LI Leap Indicator (leap): 2-bit integer warning of an impending leap
   second to be inserted or deleted in the last minute of the current
   day with values defined in Figure 9.

           +-------+----------------------------------------+
           | Value | Meaning                                |
           +-------+----------------------------------------+
           | 0     | no warning                             |
           | 1     | last minute of the day has 61 seconds  |
           | 2     | last minute of the day has 59 seconds  |

Notes:

There is an inconsistency (day vs month) between the LI description and the description of values in the Figure 9. Few paragraphs before that text there is: Except for a minor variation when using the IPv6 address family, these fields are backwards compatible with NTPv3.

If it was month instead of day it would not be compatible with RFC 1305 (NTPv3) and RFC 4330 (SNTPv4), which were obsoleted by RFC 5905.

Errata ID: 5600
Status: Verified
Type: Technical
Publication Format(s) : TEXT

Reported By: Takashi Nakamoto
Date Reported: 2019-01-15
Verifier Name: Erik Kline
Date Verified: 2022-08-29

Section 10. says:

   Let the first stage offset in the sorted list be theta_0; then, for
   the other stages in any order, the jitter is the RMS average

                          +-----                 -----+^1/2
                          |  n-1                      |
                          |  ---                      |
                  1       |  \                     2  |
      psi   =  -------- * |  /    (theta_0-theta_j)   |
                (n-1)     |  ---                      |
                          |  j=1                      |
                          +-----                 -----+

It should say:

   Let the first stage offset in the sorted list be theta_0; then, for
   the other stages in any order, the jitter is the RMS average

               +-----                             -----+^1/2
               |              n-1                      |
               |              ---                      |
               |    1         \                     2  |
      psi   =  | -------- *   /    (theta_0-theta_j)   |
               |  (n-1)       ---                      |
               |              j=1                      |
               +-----                             -----+

Notes:

The formula to calculate jitter "psi" in section "10. Clock Filter Algorithm" is incorrect, and also inconsistent with the formulate to calculate "psi_s" in section "11.2.2. Cluster Algorithm".

"psi" is defined as RMS average, so the term 1/(n-1) should be within [ ]^1/2 block.

Errata ID: 5601
Status: Verified
Type: Technical
Publication Format(s) : TEXT

Reported By: Takashi Nakamoto
Date Reported: 2019-01-15
Verifier Name: Erik Kline
Date Verified: 2022-09-26

Section 11.2.3. says:

                  | s.rootdisp  <-- p.epsilon_r + p.epsilon + |
                  |                 p.psi + PHI * (s.t - p.t) |
                  |                 + |THETA|                 |
                  | s.refid     <-- p.refid                   |
                  | s.reftime   <-- p.reftime                 |
                  | s.t         <-- p.t                       |
                  +-------------------------------------------+

                    Figure 25: System Variables Update

   There is an important detail not shown.  The dispersion increment
   (p.epsilon + p.psi + PHI * (s.t - p.t) + |THETA|) is bounded from
   below by MINDISP.

It should say:

                  | s.rootdisp  <-- p.epsilon_r + p.epsilon + |
                  |                 p.psi + PHI * (t_s - p.t) |
                  |                 + |THETA|                 |
                  | s.refid     <-- p.refid                   |
                  | s.reftime   <-- p.reftime                 |
                  | s.t         <-- p.t                       |
                  +-------------------------------------------+

                    Figure 25: System Variables Update

   where t_s is the time when the system variables are updated.
   There is an important detail not shown.  The dispersion increment
   (p.epsilon + p.psi + PHI * (t_s - p.t) + |THETA|) is bounded from
   below by MINDISP.

Notes:

In the same section, it is said that "By rule, an update is discarded if its time of arrival p.t is not strictly later than the last update used s.t." This means that p.t > s.t when the system variable is updated. Hence, (s.t - p.t) is negative. It may lead to a negative dispersion, but, by definition, the dispersion cannot be negative. So, the original formula should be wrong.

Because the dispersion is defined as the value that grows at constant rate PHI, s.rootdisp should be

s.rootdisp <-- p.epsilon_r + p.epsilon + p.psi + PHI * (t_s - p.t) + |THETA|

where t_s is the time when the system variables are updated. The symbol t_s is arbitrary because it is not defined in other places.

---

[verifier notes]

From https://mailarchive.ietf.org/arch/msg/ntp/CHcBo-my1WdRg5PbhSU8aFlIS_k/ :

"""
... the reported section with is indeed erroneous, and s.t
should be replaced with c.t, defined in section 9.1/12. The attached
note seems inaccurate in the statement that a new name (t_s) is
needed, since c.t covers the required concept...
"""

Errata ID: 5978
Status: Verified
Type: Technical
Publication Format(s) : TEXT

Reported By: David Verbree
Date Reported: 2020-02-08
Verifier Name: Erik Kline
Date Verified: 2022-09-26

Section A.5.1.1. says:

    /*
        * Verify valid root distance.
        */
    if (r->rootdelay / 2 + r->rootdisp >= MAXDISP || p->reftime >
        r->xmt)
            return;                 /* invalid header values */

It should say:

    /*
        * Verify valid root distance.
        */
    if (p->rootdelay / 2 + p->rootdisp >= MAXDISP || p->reftime >
        r->xmt)
            return;                 /* invalid header values */

Notes:

The r->rootdelay and r->rootdisp are the received values not in double format and therefore, should not be compared against MAXDISP. Use the p->rootdelay and p->rootdisp instead which have already been converted to double via FP2D macro.

---

[verifier notes]

See also https://mailarchive.ietf.org/arch/msg/ntp/Cbg3sOhChyfenYoj7UG5wCymFMU/

Errata ID: 6207
Status: Verified
Type: Technical
Publication Format(s) : TEXT

Reported By: Tam Phan
Date Reported: 2020-06-08
Verifier Name: Erik Kline
Date Verified: 2022-09-26

Section A.5.5.1 says:

/*
         * Find the largest contiguous intersection of correctness
         * intervals.  Allow is the number of allowed falsetickers;
         * found is the number of midpoints.  Note that the edge values
         * are limited to the range +-(2 ^ 30) < +-2e9 by the timestamp
         * calculations.
         */
        low = 2e9; high = -2e9;
        for (allow = 0; 2 * allow < n; allow++) {

                /*
                 * Scan the chime list from lowest to highest to find
                 * the lower endpoint.
                 */
                found = 0;
                chime = 0;
                for (i = 0; i < n; i++) {
                        chime -= s.m[i].type;
                        if (chime >= n - found) {
                                low = s.m[i].edge;
                                break;
                        }
                        if (s.m[i].type == 0)
                                found++;
                }

                /*
                 * Scan the chime list from highest to lowest to find
                 * the upper endpoint.
                 */
                chime = 0;
                for (i = n - 1; i >= 0; i--) {
                        chime += s.m[i].type;
                        if (chime >= n - found) {
                                high = s.m[i].edge;
                                break;
                        }
                        if (s.m[i].type == 0)
                                found++;
                }




Mills, et al.                Standards Track                   [Page 91]
 
RFC 5905                   NTPv4 Specification                 June 2010


                /*
                 * If the number of midpoints is greater than the number
                 * of allowed falsetickers, the intersection contains at
                 * least one truechimer with no midpoint.  If so,
                 * increment the number of allowed falsetickers and go
                 * around again.  If not and the intersection is
                 * non-empty, declare success.
                 */
                if (found > allow)
                        continue;

                if (high > low)
                        break;
        }

It should say:

/*
         * Find the largest contiguous intersection of correctness
         * intervals.  Allow is the number of allowed falsetickers;
         * found is the number of midpoints.  Note that the edge values
         * are limited to the range +-(2 ^ 30) < +-2e9 by the timestamp
         * calculations.
         */
        low = 2e9; high = -2e9;
        for (allow = 0; 2 * allow < n; allow++) {

                /*
                 * Scan the chime list from lowest to highest to find
                 * the lower endpoint.
                 */
                found = 0;
                chime = 0;
                for (i = 0; i < n; i++) {
                        chime -= s.m[i].type;
                        if (chime >= n - allow) {
                                low = s.m[i].edge;
                                break;
                        }
                        if (s.m[i].type == 0)
                                found++;
                }

                /*
                 * Scan the chime list from highest to lowest to find
                 * the upper endpoint.
                 */
                chime = 0;
                for (i = n - 1; i >= 0; i--) {
                        chime += s.m[i].type;
                        if (chime >= n - allow) {
                                high = s.m[i].edge;
                                break;
                        }
                        if (s.m[i].type == 0)
                                found++;
                }




Mills, et al.                Standards Track                   [Page 91]
 
RFC 5905                   NTPv4 Specification                 June 2010


                /*
                 * If the number of midpoints is greater than the number
                 * of allowed falsetickers, the intersection contains at
                 * least one truechimer with no midpoint.  If so,
                 * increment the number of allowed falsetickers and go
                 * around again.  If not and the intersection is
                 * non-empty, declare success.
                 */
                if (found > allow)
                        continue;

                if (high > low)
                        break;
        }

Notes:

The algorithm described in section 11.2.3 is not properly written here; we compare c to n - f in the algorithm, but f != found; f corresponds to the "allowed" falsetickers. This algorithm implementation results in the lower and upper bounds unchanging throughout the described loop, but this change should fix the implementation.

---

[INT AD notes]

For analysis and further discussion see https://mailarchive.ietf.org/arch/msg/ntp/zJNoHvZ08SPX-3kwflMK7PIReFo/ especially the one or two addition issues identified.

Errata ID: 6550
Status: Verified
Type: Technical
Publication Format(s) : TEXT

Reported By: Perry Lorier
Date Reported: 2021-04-17
Verifier Name: Erik Kline
Date Verified: 2022-08-29

Section A.5.2 says:

        for (i = 0; i < NSTAGE; i++) {
                p->disp += f[i].disp / (2 ^ (i + 1));
                p->jitter += SQUARE(f[i].offset - f[0].offset);
        }

It should say:

        for (i = 0; i < NSTAGE; i++) {
                p->disp += f[i].disp / (1 << (i + 1));
                p->jitter += SQUARE(f[i].offset - f[0].offset);
        }

Notes:

^ is the xor operator in C, not the exponent operator. 2 xor (i+1) will be zero when i == 1, causing a division by zero error.

Errata ID: 4019
Status: Verified
Type: Editorial
Publication Format(s) : TEXT

Reported By: Teruaki Kitasuka
Date Reported: 2014-06-20
Verifier Name: Brian Haberman
Date Verified: 2014-06-20

Section 11.2.1 says:

   An
   example of this calculation is shown by the rootdist() routine in
   Appendix A.5.1.1.

It should say:

   An
   example of this calculation is shown by the root_dist() routine in
   Appendix A.5.5.2.

Notes:

No rootdist() routine is in Appendix. root_dist() appears in Appendix A.5.5.2.

Errata ID: 4121
Status: Verified
Type: Editorial
Publication Format(s) : TEXT

Reported By: Marina Gertsvolf
Date Reported: 2014-09-23
Verifier Name: Brian Haberman
Date Verified: 2014-10-21

Section 8 says:

In the exchange above, a packet is duplicate or
   replay if the transmit timestamp t3 in the packet matches the org
   state variable T3. 

It should say:

In the exchange above, a packet is duplicate or
   replay if the transmit timestamp t3 in the packet matches the org
   state variable. 

Notes:

The org state variable for peer A has not yet been assigned the value T3.

Errata ID: 4680
Status: Verified
Type: Editorial
Publication Format(s) : TEXT

Reported By: Riccardo Brama
Date Reported: 2016-04-29
Verifier Name: Erik Kline
Date Verified: 2022-07-27

Section 6, Fig 3 says:

       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                           Era Number                          |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                           Era Offset                          |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                               |
      |                           Fraction                            |
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                              NTP Date Format

It should say:

       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                           Era Number                          |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                           Era Offset                          |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                               |
      +                           Fraction                            +
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                              NTP Date Format

Notes:

This allows to better appreciate only two 32b rows really form the Fraction part, leading to an overall type length of 128b instead of 160b as it could otherwise be misunderstood in the original figure.

---

The "+" vs "|" on the Fraction line would seem to improve consistency with packet layouts in other documents.

Errata ID: 5104
Status: Verified
Type: Editorial
Publication Format(s) : TEXT

Reported By: Denis Ovsienko
Date Reported: 2017-08-30
Verifier Name: Erik Kline
Date Verified: 2022-07-27

Section 7.3, Fig 8 says:

      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                          Key Identifier                       |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                               |
      |                            dgst (128)                         |
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

It should say:

      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                          Key Identifier                       |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                               |
      |                       Message Digest (128)                    |
      |                                                               |
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Notes:

As the text before the figure explains, the last field is called "Message Digest", which is consistent with the rest of the document. In this document "dgst" and "mac" mean two protocol variables associated with this packet field.

---

Note: edited to clarify 4 32bit words, rather than 3 rows.

Errata ID: 5189
Status: Verified
Type: Editorial
Publication Format(s) : TEXT

Reported By: Marcel Telka
Date Reported: 2017-11-28
Verifier Name: Erik Kline
Date Verified: 2022-09-26

Section 6 says:

   | 31 Dec 1999 | 51,543     | 0   | 3,155,587,200 | Last day 20th    |
   |             |            |     |               | Century          |

It should say:

   | 31 Dec 2000 | 51,909     | 0   | 3,187,209,600 | Last day 20th    |
   |             |            |     |               | Century          |

Notes:

20th Century was from 1901 to 2000.

---

[verifier notes]

See also: https://mailarchive.ietf.org/arch/msg/ntp/Cbg3sOhChyfenYoj7UG5wCymFMU/

Errata ID: 7555
Status: Verified
Type: Editorial
Publication Format(s) : TEXT

Reported By: Sylvain Etienne
Date Reported: 2023-06-28
Verifier Name: RFC Editor
Date Verified: 2023-06-28

Section 4 says:

Under the auspices of the
   Metre Convention of 1865, in 1975 the CGPM [CGPM] strongly endorsed
   the use of UTC as the basis for civil time.

It should say:

Under the auspices of the
   Metre Convention of 1875, in 1975 the CGPM [CGPM] strongly endorsed
   the use of UTC as the basis for civil time.

Notes:

The Metre convention was signed on 20 May 1875 as stated on https://www.bipm.org/en/metre-convention.

Status: Held for Document Update (16)

RFC 5905, "Network Time Protocol Version 4: Protocol and Algorithms Specification", June 2010

Note: This RFC has been updated by RFC 7822, RFC 8573, RFC 9109

Source of RFC: ntp (int)

Errata ID: 3125
Status: Held for Document Update
Type: Technical
Publication Format(s) : TEXT

Reported By: Richard Walters
Date Reported: 2012-02-16
Held for Document Update by: Brian Haberman

Section A.5.1.1 says:

        /*
         * Calculate offset, delay and dispersion, then pass to the
         * clock filter.  Note carefully the implied processing.  The
         * first-order difference is done directly in 64-bit arithmetic,
         * then the result is converted to floating double.  All further
         * processing is in floating-double arithmetic with rounding
         * done by the hardware.  This is necessary in order to avoid
         * overflow and preserve precision.
         *
         * The delay calculation is a special case.  In cases where the
         * server and client clocks are running at different rates and
         * with very fast networks, the delay can appear negative.  In
         * order to avoid violating the Principle of Least Astonishment,
         * the delay is clamped not less than the system precision.
         */
        if (p->pmode == M_BCST) {
                offset = LFP2D(r->xmt - r->dst);
                delay = BDELAY;
                disp = LOG2D(r->precision) + LOG2D(s.precision) + PHI *
                    2 * BDELAY;
        } else {
                offset = (LFP2D(r->rec - r->org) + LFP2D(r->dst -
                    r->xmt)) / 2;
                delay = max(LFP2D(r->dst - r->org) - LFP2D(r->rec -
                    r->xmt), LOG2D(s.precision));
                disp = LOG2D(r->precision) + LOG2D(s.precision) + PHI *
                    LFP2D(r->dst - r->org);
        }
        clock_filter(p, offset, delay, disp);

It should say:

        /*
         * Calculate offset, delay and dispersion, then pass to the
         * clock filter.  Note carefully the implied processing.  The
         * first-order difference is done directly in 64-bit arithmetic,
         * then the result is converted to floating double.  All further
         * processing is in floating-double arithmetic with rounding
         * done by the hardware.  This is necessary in order to avoid
         * overflow and preserve precision.
         *
         * The delay calculation is a special case.  In cases where the
         * server and client clocks are running at different rates and
         * with very fast networks, the delay can appear negative.  In
         * order to avoid violating the Principle of Least Astonishment,
         * the delay is clamped not less than the system precision.
         */
        if (p->pmode == M_BCST) {
                offset = LFP2D(r->xmt - r->dst);
                delay = BDELAY;
                disp = LOG2D(r->precision) + LOG2D(s.precision) + PHI *
                    2 * BDELAY;
        } else {
                offset = (LFP2D(r->rec - r->org) + LFP2D(r->xmt -
                    r->dst)) / 2;
                delay = max(LFP2D(r->dst - r->org) - LFP2D(r->xmt -
                    r->rec), LOG2D(s.precision));
                disp = LOG2D(r->precision) + LOG2D(s.precision) + PHI *
                    LFP2D(r->dst - r->org);
        }
        clock_filter(p, offset, delay, disp);

Notes:

Calculations of 'offset' and 'delay' have terms that are incorrectly swapped. In the calculation of 'offset', term 'r->dst' should be 'r->xmt', and term 'r->xmt' should be 'r->dst'. In the calculation of 'delay', term 'r->rec' should be 'r->xmt', and term 'r->xmt' should be 'r->rec'.

See the text from section 8:

"In the figure, the first packet transmitted by A contains only the
origin timestamp t1, which is then copied to T1. B receives the
packet at t2 and copies t1 to T1 and the receive timestamp t2 to T2.
At this time or some time later at t3, B sends a packet to A
containing t1 and t2 and the transmit timestamp t3. All three
timestamps are copied to the corresponding state variables. A
receives the packet at t4 containing the three timestamps t1, t2, and
t3 and the destination timestamp t4. These four timestamps are used
to compute the offset and delay of B relative to A, as described
below.

...

"The four most recent timestamps, T1 through T4, are used to compute
the offset of B relative to A

theta = T(B) - T(A) = 1/2 * [(T2-T1) + (T3-T4)]

and the round-trip delay

delta = T(ABA) = (T4-T1) - (T3-T2)."

Noting that, from the perspective of A at time t4:

T1 = t1 = origin timestamp (r->org)
T2 = t2 = receive timestamp (r->rec)
T3 = t3 = transmit timestamp (r->xmt)
T4 = t4 = destination timestamp (r->dst)

An alternative correction would be to change the '+' to a '-' in the calculation of 'offset', and change the '-' to a '+' in the calculation of 'delay'. However, this would deviate from the operators used in the formulas from section 8.

Errata ID: 2476
Status: Held for Document Update
Type: Technical
Publication Format(s) : TEXT

Reported By: Joerg Weilbier
Date Reported: 2010-08-19
Held for Document Update by: Brian Haberman

Section 7.3. says:

For instance, a value of -18 
corresponds to a precision of about one microsecond.

It should say:

For instance, a value of -20 
corresponds to a precision of about one microsecond.

Notes:

2**-20 = 0.954 usec
2**-18 = 3.815 usec

Errata ID: 3404
Status: Held for Document Update
Type: Technical
Publication Format(s) : TEXT

Reported By: Philippe Verdy
Date Reported: 2012-11-08
Held for Document Update by: Brian Haberman

Section A.1.1. says:

#define SQUARE(x)       (x * x)

It should say:

#define SQUARE(x)       ((x) * (x))

Notes:

This macro is used in the example code to square differences:

//- in clock_filter() {...} (page 85) :

p->jitter += SQUARE(f[i].offset - f[0].offset);

//- in clock_select() { ... } (page 92) :

dtemp += SQUARE(p->offset - q->offset);

//- in clock_combine() { ... } (page 96) :

w += SQUARE(p->offset - s.v[0].p->offset) / x;

//- in local_clock() { ... } (page 99) :

dtemp = SQUARE(max(fabs(offset - c.last),
LOG2D(s.precision)));


These expressions are using differences of double values: the .offset member in a Filter stage structure (f), and the .jitter member in an Association structure (p), or in a Local clock structure (c), or in a System structure (s).

All these occurences of macro substitions of SQUARE() will be wrong if the C macro does not surrounds its parameter expression by adding parentheses around them !

This is a very classic error made by beginners in C programming using "utility" macros with side effects... At least newer programmers avoid these kind of macros and prefer defining inline functions

Errata ID: 3127
Status: Held for Document Update
Type: Technical
Publication Format(s) : TEXT

Reported By: Richard Walters
Date Reported: 2012-02-17
Held for Document Update by: Brian Haberman

Section A.5.5.1 says:

                /*
                 * Scan the chime list from lowest to highest to find
                 * the lower endpoint.
                 */
                found = 0;
                chime = 0;
                for (i = 0; i < n; i++) {
                        chime -= s.m[i].type;
                        if (chime >= n - found) {
                                low = s.m[i].edge;
                                break;
                        }
                        if (s.m[i].type == 0)
                                found++;
                }

                /*
                 * Scan the chime list from highest to lowest to find
                 * the upper endpoint.
                 */
                chime = 0;
                for (i = n - 1; i >= 0; i--) {
                        chime += s.m[i].type;
                        if (chime >= n - found) {
                                high = s.m[i].edge;
                                break;
                        }
                        if (s.m[i].type == 0)
                                found++;
                }

It should say:

                /*
                 * Scan the chime list from lowest to highest to find
                 * the lower endpoint.
                 */
                found = 0;
                chime = 0;
                for (i = 0; i < n; i++) {
                        chime -= s.m[i].type;
                        if (chime >= n - allow) {
                                low = s.m[i].edge;
                                break;
                        }
                        if (s.m[i].type == 0)
                                found++;
                }

                /*
                 * Scan the chime list from highest to lowest to find
                 * the upper endpoint.
                 */
                chime = 0;
                for (i = n - 1; i >= 0; i--) {
                        chime += s.m[i].type;
                        if (chime >= n - allow) {
                                high = s.m[i].edge;
                                break;
                        }
                        if (s.m[i].type == 0)
                                found++;
                }

Notes:

In both scans (lowest to highest, and highest to lowest)

chime >= n - found

needs to be:

chime >= n - allow

Errata ID: 3608
Status: Held for Document Update
Type: Technical
Publication Format(s) : TEXT

Reported By: Cristian Rodríguez
Date Reported: 2013-04-29
Held for Document Update by: Brian Haberman

Section A.2. says:

/*
         * Read command line options and initialize system variables.
         * The reference implementation measures the precision specific
         * to each machine by measuring the clock increments to read the
         * system clock.
         */
        memset(&s, sizeof(s), 0);

.....
/*
         * Initialize local clock variables
         */
        memset(&c, sizeof(c), 0);

It should say:

/*
         * Read command line options and initialize system variables.
         * The reference implementation measures the precision specific
         * to each machine by measuring the clock increments to read the
         * system clock.
         */
        memset(&s, 0. sizeof(s));
...

/*
         * Initialize local clock variables
         */
        memset(&c, 0, sizeof(c));

Notes:

Paramters 2 and 3 of the memset functions are inverted everywhere in the example code, not just in section A2

Errata ID: 4366
Status: Held for Document Update
Type: Technical
Publication Format(s) : TEXT

Reported By: Vyacheslav
Date Reported: 2015-05-13
Held for Document Update by: Brian Haberman
Date Held: 2015-09-14

Section 11.2.1 says:

5.  Is d = f and l < u?  If yes, then follow step 5A; else, follow
   step 5B.

It should say:

5.  Is d <= f and l < u?  If yes, then follow step 5A; else, follow
   step 5B.

Notes:

Original text doesn't correspond to sample implementation at A.5.5.1. And, I suppose, described algorithm may throw out reasonable set of measures.

Errata ID: 5604
Status: Held for Document Update
Type: Technical
Publication Format(s) : TEXT

Reported By: Takashi Nakamoto
Date Reported: 2019-01-15
Held for Document Update by: Erik Kline
Date Held: 2022-09-26

Section 11.2.3. says:

                  | s.rootdisp  <-- p.epsilon_r + p.epsilon + |
                  |                 p.psi + PHI * (s.t - p.t) |
                  |                 + |THETA|                 |

It should say:

                  | s.rootdisp  <-- p.epsilon_r + p.epsilon   |
                  |                 + 5 * p.psi +             |
                  |                 + PHI * (s.t - p.t)       |
                  |                 + |THETA|                 |

Notes:

In addition to the correction proposed in Errata ID 5601, I think that the formula to calculate the dispersion should be revised. The term "p.psi" should be multiplied by not one, but a larger value.

This is because the dispersion is defined as the statistics that represent the maximum error, so when it is calculated, it should take into account the maximum errors in the offset estimation. However, the jitter p.psi is defined as the RMS average of the offset values theta_j relative to theta_0, so the term "p.psi" does not represent the maximum error caused by the distribution of the offset values.

If we assume that the offset value follows the uniform distribution, the error bound is represented as sqrt(3) * p.psi. So, at least, the term "p.psi" should be multiplied by sqrt(3). There is arbitrarity in choice of the distribution type, so depending on the distribution type the factor may change. For example, if the normal distribution is assumed, 5 * p.psi gives us 99.99994% confidence. Assuming that the system variable is updated every 16 seconds, the actual offset may be outside the range [theta_0 - 5 * p.psi, theta_0 + 5 * p.psi] approximately once a year. It should be sufficient for usual Internet applications, though someone may think that the factor "5" may not be sufficient depending on the application.

---

[INT AD notes]

See also https://mailarchive.ietf.org/arch/msg/ntp/Cbg3sOhChyfenYoj7UG5wCymFMU/ :

"""
...That makes some sense to me, but I'd say it really depends on the model of the clock and that's arbitrary...
"""

Errata ID: 6280
Status: Held for Document Update
Type: Technical
Publication Format(s) : TEXT

Reported By: Jingguo Yao
Date Reported: 2020-09-05
Held for Document Update by: Erik Kline
Date Held: 2022-09-26

Section A.5.5.1. says:

There is the following comment:

* First, construct the chime list of tuples (p, type, edge) as
* shown below, then sort the list by edge from lowest to
* highest.


It should say:

There should be some statements to do the sorting since the comment mentions it. But there are no statements related to sorting in the following code. 

And I checked the NTP reference implementation. There is code to do the sorting at https://github.com/ntp-project/ntp/blob/71a962710bfe066f76da9679cf4cfdeffe34e95e/ntpd/ntp_proto.c#L2837

Notes:

From https://mailarchive.ietf.org/arch/msg/ntp/zJNoHvZ08SPX-3kwflMK7PIReFo/ :

"""
... correctly identifies the problem, but it doesn't provide the new
text. I'd suggest to add "sort(s.m, n);" right after the first while
loop in A.5.5.1.
"""

Errata ID: 2514
Status: Held for Document Update
Type: Editorial
Publication Format(s) : TEXT

Reported By: Jerzy Miernik
Date Reported: 2010-09-08
Held for Document Update by: Brian Haberman

Section A.5.1 says:

if (0) { ...

It should say:

if (unicast ...) { ...

Notes:

expression under if is needed, even using pseudo-code

Errata ID: 2826
Status: Held for Document Update
Type: Editorial
Publication Format(s) : TEXT

Reported By: Christian Aistleitner
Date Reported: 2011-06-10
Held for Document Update by: Brian Haberman

Section 6 says:

[...]
and a 64-bit fraction field resolving .05 attosecond (i.e., 0.5e-18).

It should say:

[...]
and a 64-bit fraction field resolving .05 attosecond (i.e., 0.05e-18).

Notes:

"atto" is the prefix for 1e-18.

Errata ID: 3126
Status: Held for Document Update
Type: Editorial
Publication Format(s) : TEXT

Reported By: Richard Walters
Date Reported: 2012-02-16
Held for Document Update by: Brian Haberman

Section 3 says:

          +-------------------+-------------------+------------------+
          |  Association Mode | Assoc. Mode Value | Packet Mode Value|
          +-------------------+-------------------+------------------+
          | Symmetric Active  |         1         | 1 or 2           |
          | Symmetric Passive |         2         | 1                |
          | Client            |         3         | 4                |
          | Server            |         4         | 3                |
          | Broadcast Server  |         5         | 5                |
          | Broadcast Client  |         6         | N/A              |
          +-------------------+-------------------+------------------+

                  Figure 1: Association and Packet Modes

   In the client/server variant, a persistent client sends packet mode 4
   packets to a server, which returns packet mode 3 packets.

It should say:

          +-------------------+-------------------+------------------+
          |  Association Mode | Assoc. Mode Value | Packet Mode Value|
          +-------------------+-------------------+------------------+
          | Symmetric Active  |         1         | 1 or 2           |
          | Symmetric Passive |         2         | 1                |
          | Client            |         3         | 4                |
          | Server            |         4         | 3                |
          | Broadcast Server  |         5         | N/A              |
          | Broadcast Client  |         6         | 5                |
          +-------------------+-------------------+------------------+

                  Figure 1: Association and Packet Modes

   In the client/server variant, a persistent client sends packet mode 3
   packets to a server, which returns packet mode 4 packets.

Notes:

The majority of the rows in Figure 1 are correct if the 'Packet Mode Value' refers to the mode of packets which are expected to be received by an NTP speaker which has mobilized an association with the corresponding 'Association Mode'. Assuming this is the case, the last two rows are incorrect:

* A peer with a mobilized 'Broadcast Server' mode association is not expected to receive any packets at all for this association -- a broadcast server does not receive anything back (see 'Broadcast' mode row in Section 9.2, Figure 20, where each column in that row is 'DSCRD'.) Therefore, the value of 'Packet Mode Value' for 'Broadcast Server' should be 'N/A', not '5'.

* A peer with a mobilized 'Broadcast Client' mode association is expected to receive packets with a 'Packet Mode Value' of 5 for this association (see 'Bcast Client' mode row in Section 9.2, Figure 20, where each column in that row is 'DSCRD' except for the '5' column, which is 'PROC'.) Therefore, the value of 'Packet Mode Value' for 'Broadcast Client' should be '5', not 'N/A'.

It might help the clarity of Figure 1 if the row labeled 'Packet Mode Value' were to be changed to 'Receive Packet Mode Value(s)'.

The text immediately following Figure 1 also has the packet mode values swapped. As made clear throughout the RFC (for example, see Section 9.2 where is says, "FXMIT. This indicates a client (mode 3) packet matching no association (mode 0). If the destination address is not a broadcast address, the server constructs a server (mode 4) packet and returns it to the client without retaining state."), clients send servers packet mode 3 packets, not packet mode 4 packets; it is servers which send clients packet mode 4 packets, not packet mode 3 packets.

Just to make it perfectly clear, here are the modes of packets sent:

* Time t0: client mobilizes 'Client' mode association for server (via configuration, or due to reception of manycast server packet)
* Time t1: client transmits mode 3 packet to server (e.g. via poll(p) => peer_xmit(p) when c.t >= p->nextdate)
* Time t2: server receives mode 3 packet from client (dispatch: FXMIT; no association found or mobilized)
* Time t3: server transmits mode 4 packet to client
* Time t4: client receives mode 4 packet from server (matches previously mobilized association -- dispatch: PROC)

Errata ID: 3132
Status: Held for Document Update
Type: Editorial
Publication Format(s) : TEXT

Reported By: Richard Walters
Date Reported: 2012-02-21
Held for Document Update by: Brian Haberman

Section 11.2.1 says:

   First, those servers that are unusable according to the rules of the
   protocol are detected and discarded as shown by the accept() routine
   in Appendix A.5.5.3.

It should say:

   First, those servers that are unusable according to the rules of the
   protocol are detected and discarded as shown by the fit() routine
   in Appendix A.5.2.

Notes:

The fit() and accept() routines are identical. Since accept() is not called from, nor mentioned anywhere else, whereas fit() is called from two places and listed in the function prototypes, just drop accept() and use fit() instead in section 11.2.1.

Errata ID: 4025
Status: Held for Document Update
Type: Editorial
Publication Format(s) : TEXT

Reported By: Julien Cretin
Date Reported: 2014-06-25
Held for Document Update by: Brian Haberman
Date Held: 2014-06-25

Section 6 says:

-678,491

It should say:

-678,941

Notes:

In Figure 4, the MJD of 1 Jan 0 has a typo.

There are 365 (not 815) days from 1 Jan -1 to 1 Jan 0, and 366 (not -84) from 1 Jan 0 to 1 Jan 1. I took NTP Timestamp Era Offset as a reference for the number of days in these years.

Errata ID: 4263
Status: Held for Document Update
Type: Editorial
Publication Format(s) : TEXT

Reported By: Priyesh Patel
Date Reported: 2015-02-05
Held for Document Update by: Brian Haberman
Date Held: 2015-02-06

Section 7.3, Fig 8 says:

       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |LI | VN  |Mode |    Stratum     |     Poll      |  Precision   |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

It should say:

       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |LI | VN  |Mode |    Stratum    |     Poll      |  Precision    |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Notes:

The field boundaries are not aligned with the bit boundaries in "Figure 8: Packet Header Format".

Errata ID: 6423
Status: Held for Document Update
Type: Editorial
Publication Format(s) : TEXT

Reported By: Stijn van Drongelen
Date Reported: 2021-02-07
Held for Document Update by: Erik Kline
Date Held: 2022-07-27

Section 6 says:

| 1 Jan 1972  | 41,317     | 0   | 2,272,060,800 | First day UTC    |

It should say:

| 1 Jan 1972  | 41,317     | 0   | 2,272,060,800 | First day "modern" UTC |

Notes:

The initial definition of UTC was introduced in 1963 with CCIR Recommendation 374. The time standard specified that seconds had a varying duration. In 1970, CCIR Recommendation 460 introduced the current definition of UTC, using leap seconds, which was implemented on the first second of 1972. Consult D. McCarthy's "Note on Coordinated Universal Time" (numbered CCTF/09-32 by the Consultative Committee for Time and Frequency of the BIPM) for more information.

---

There may perhaps be more precise terminology than "modern", but this point should be addressed by a document that updates or replaces this one.

Errata ID: 6524
Status: Held for Document Update
Type: Editorial
Publication Format(s) : TEXT

Reported By: Kenneth Duffill
Date Reported: 2021-04-09
Held for Document Update by: Erik Kline
Date Held: 2022-09-26

Section 6 says:

202,939,144

It should say:

202,934,144

Notes:

In Figure 4 The Era Offset of 1 Jan 1 has a typo.

The value of 202,939,144 for the Era Offset of 1 Jan 1 should be 202,934,144 because 1 Jan 0 has an Era Offset of 171,311,744 and there are 366 days in year 0, therefore the Era Offset for 1 Jan 1 should be 86400 * 366 (= 31,622,400) greater than that for 1 JAN 0.

---

[INT AD notes]

From https://mailarchive.ietf.org/arch/msg/ntp/Cbg3sOhChyfenYoj7UG5wCymFMU/ :

"""
... might be correct too, but I find that table confusing with those
dates when the modern definition of the second and UTC didn't exist
yet...
"""

Status: Rejected (3)

RFC 5905, "Network Time Protocol Version 4: Protocol and Algorithms Specification", June 2010

Note: This RFC has been updated by RFC 7822, RFC 8573, RFC 9109

Source of RFC: ntp (int)

Errata ID: 3613
Status: Rejected
Type: Technical
Publication Format(s) : TEXT

Reported By: Tony O'Brien
Date Reported: 2013-05-06
Rejected by: Brian Haberman
Date Rejected: 2013-05-06

Section 8 says:


Notes:

In the paragraph explaining the sanity checks on received packets, it states: "In the exchange above, a packet is duplicate or replay if the transmit timestamp t3 in the packet matches the org state variable T3." But in the pseudo-code in A.5.1 it states
/*
* If the transmit timestamp duplicates a previous one, the
* packet is a replay.
*/
if (r->xmt == p->xmt)
i.e. comparing the transmit timestamp p->xmt with the xmt state variable T1. Which is correct?

Similarly for the check for a bogus packet, Section 8 states: "A packet is bogus if the origin timestamp t1 in the packet does not match the xmt state variable T1. But the pseudo-code says:
/*
* If this is a broadcast mode packet, skip further checking.
* If the origin timestamp is zero, the sender has not yet heard
* from us. Otherwise, if the origin timestamp does not match
* the transmit timestamp, the packet is bogus.
*/
synch = TRUE;
if (r->mode != M_BCST) {
if (r->org == 0)
synch = FALSE; /* unsynchronized */

else if (r->org != p->xmt)
synch = FALSE; /* bogus packet */
}
i.e. it is comparing the transmit timestamp t3 in the packet with the org state variable T3.

Which is correct? Looking at Figure 15 my guess would be Section 8 is correct but I have seen code that more closely follows the pseudo-code.
--VERIFIER NOTES--
The Introduction of the document clearly states that the pseudo-code in the appendix is non-normative. Therefore the text in the main body of the specification describes the conformant behavior:

"The contents of Appendix A are non-normative examples designed to illustrate the protocol's operation and are not a requirement for a conforming implementation."

Errata ID: 4505
Status: Rejected
Type: Technical
Publication Format(s) : TEXT

Reported By: Miroslav Lichvar
Date Reported: 2015-10-15
Rejected by: Brian Haberman
Date Rejected: 2015-12-14

Section A.5.1 says:

        /*
         * Update the origin and destination timestamps.  If
         * unsynchronized or bogus, abandon ship.
         */
        p->org = r->xmt;
        p->rec = r->dst;
        if (!synch)
                return;                 /* unsynch */

        /*
         * The timestamps are valid and the receive packet matches the
         * last one sent.  If the packet is a crypto-NAK, the server
         * might have just changed keys.  We demobilize the association
         * and wait for better times.
         */
        if (auth == A_CRYPTO) {
                clear(p, X_CRYPTO);
                return;                 /* crypto-NAK */
        }

        /*
         * If the association is authenticated, the key ID is nonzero
         * and received packets must be authenticated.  This is designed
         * to avoid a bait-and-switch attack, which was possible in past
         * versions.
         */
        if (!AUTH(p->keyid || (p->flags & P_NOTRUST), auth))
                return;                 /* bad auth */

It should say:

        /*
         * If the packet is a valid crypto-NAK, the server might have
         * just changed keys.  We demobilize the association and wait
         * for better times.
         */
        if (synch && auth == A_CRYPTO) {
                clear(p, X_CRYPTO);
                return;                 /* crypto-NAK */
        }

        /*
         * If the association is authenticated, the key ID is nonzero
         * and received packets must be authenticated.  This is designed
         * to avoid a bait-and-switch attack, which was possible in past
         * versions.
         */
        if (!AUTH(p->keyid || (p->flags & P_NOTRUST), auth))
                return;                 /* bad auth */

        /*
         * Update the origin and destination timestamps.  If
         * unsynchronized or bogus, abandon ship.
         */
        p->org = r->xmt;
        p->rec = r->dst;
        if (!synch)
                return;                 /* unsynch */

Notes:

The state variables must be updated after the authentication is checked in order to prevent DoS attacks on authenticated symmetric associations (CVE-2015-1799).
--VERIFIER NOTES--
The appendix is not the normative description of the protocol behavior. A change such as this needs consensus within the working group. To do that, a draft should be submitted with the proposed changes.

Errata ID: 5020
Status: Rejected
Type: Technical
Publication Format(s) : TEXT

Reported By: Ferenc Wágner
Date Reported: 2017-05-15
Rejected by: Erik Kline
Date Rejected: 2022-08-29

Section 8 says:

theta = T(B) - T(A) = 1/2 * [(T2-T1) + (T3-T4)]

It should say:

theta = T(B) - T(A) = 1/2 * [(T2-T1) + (T4-T3)]

Notes:

The corresponding code line in A.5.1.1. agrees with this correction:

offset = (LFP2D(r->rec - r->org) + LFP2D(r->dst - r->xmt)) / 2;

taking Figure 7 into account:

| org | T1 | origin timestamp |
| rec | T2 | receive timestamp |
| xmt | T3 | transmit timestamp |
| dst | T4 | destination timestamp |
--VERIFIER NOTES--
As noted this thread:

https://mailarchive.ietf.org/arch/msg/ntp/AR7k0IP2PMgXdq2bknx6Eiz4upE/

'''
Theta is "the offset of B relative to A". The proposed revision is

1/2 * [(T2-T1) + (T4-T3)]

Example: Let's assume that B and A are exactly synced to UTC and that the
network delay is 50msec in each direction.

T2-T1 is the NTP mode 3 request delay (including network delay).

This gives 50 msec
T4-T3 is the NTP mode 4 response delay (including network delay).

This gives 50 msec.

The proposed revision gives 100msec/2 = RTT/2, not the expected offset of
zero.

The RFC5905 formula seems correct.

theta = T(B) - T(A) = 1/2 * [(T2-T1) + (T3-T4)]

but might have been clearer had it been written:

theta = T(B) - T(A) = 1/2 * [(T2-T1) - (T4-T3)]
'''

Report New Errata



Advanced Search