NTP WG                                                   J. Burbank, Ed.
Internet-Draft                                             W. Kasch, Ed.
Obsoletes: RFC 4330, RFC 1305                                    JHU/APL
(if approved)                                             J. Martin, Ed.
Intended status: Standards Track                             Netzwert AG                                Daedelus
Expires: July 21, September 24, 2007                                     D. Mills
                                                             U. Del.
                                                        January 17, Delaware
                                                          March 23, 2007

 Network Time Protocol Version 4 Protocol And Algorithms Specification
                     draft-ietf-ntp-ntpv4-proto-04
                     draft-ietf-ntp-ntpv4-proto-05

Status of this Memo

   By submitting this Internet-Draft, each author represents that any
   applicable patent or other IPR claims of which he or she is aware
   have been or will be disclosed, and any of which he or she becomes
   aware will be disclosed, in accordance with Section 6 of BCP 79.

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF), its areas, and its working groups.  Note that
   other groups may also distribute working documents as Internet-
   Drafts.

   Internet-Drafts are draft documents valid for a maximum of six months
   and may be updated, replaced, or obsoleted by other documents at any
   time.  It is inappropriate to use Internet-Drafts as reference
   material or to cite them other than as "work in progress."

   The list of current Internet-Drafts can be accessed at
   http://www.ietf.org/ietf/1id-abstracts.txt.

   The list of Internet-Draft Shadow Directories can be accessed at
   http://www.ietf.org/shadow.html.

   This Internet-Draft will expire on July 21, September 24, 2007.

Copyright Notice

   Copyright (C) The IETF Trust (2007).

Abstract

   The Network Time Protocol (NTP) is widely used to synchronize
   computer clocks in the Internet.  This memorandum document describes NTP Version
   4
   of the NTP (NTPv4), introducing several changes from which is backwards compatible with NTP Version 3 of NTP (NTPv3)
   described in RFC 1305, including the introduction as well as previous versions of the protocol.

   It includes a modified protocol header to accomodate accommodate the Internet
   Protocol Version 6. 6 address family.  NTPv4 also includes optional extensions fundamental
   improvements in the mitigation and discipline algorithms which extend
   the potential accuracy to the NTPv3
   protocol,including tens of microseconds with modern
   workstations and fast LANs.  It includes a dynamic server discovery
   scheme, so that in many cases specific server configuration is not
   required.  It corrects certain errors in the NTPv3 design and
   implementation and includes an optional extension mechanism.

Table of Contents

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   4
     1.1.  Requirements Notation . . . . . . . . . . . . . . . . . .   5
   2.  Modes of Operation  . . . . . . . . . . . . . . . . . . . . .   5
   3.  Definitions  Protocol Modes  . . . . . . . . . . . . . . . . . . . . . . .   6
     3.1.  Simple Network Time Protocol (SNTP) . . . . . . . . . . .   7
     3.2.  Dynamic Server Discovery  . . . . . . . . . . . . . . . .   8
   4.  Definitions . . . . . . . . . . . . . . . . . . . . . . . . .   9
   5.  Implementation Model  . . . . . . . . . . . . . . . . . . . .  10
   5.  11
   6.  Data Types  . . . . . . . . . . . . . . . . . . . . . . . . .  13
   6.
   7.  Data Structures . . . . . . . . . . . . . . . . . . . . . . .  17
     6.1.
     7.1.  Structure Conventions . . . . . . . . . . . . . . . . . .  17
     6.2.
     7.2.  Global Parameters . . . . . . . . . . . . . . . . . . . .  17
     6.3.
     7.3.  Packet Header Variables . . . . . . . . . . . . . . . . .  19
       6.3.1.  18
     7.4.  The Kiss-o'-Death Packet  . . . . . . . . . . . . . .  25
       6.3.2. . .  24
     7.5.  NTP Extension Field Format  . . . . . . . . . . . . .  26
   7. . .  25
   8.  On Wire Protocol  . . . . . . . . . . . . . . . . . . . . . .  28
   8.  27
   9.  Peer Process  . . . . . . . . . . . . . . . . . . . . . . . .  32
     8.1.  31
     9.1.  Peer Process Variables  . . . . . . . . . . . . . . . . .  32
     8.2.  31
     9.2.  Peer Process Operations . . . . . . . . . . . . . . . . .  35
     8.3.  34
   10. Clock Filter Algorithm  . . . . . . . . . . . . . . . . .  42
   9. . .  38
   11. System Process  . . . . . . . . . . . . . . . . . . . . . . .  45
     9.1.  40
     11.1. System Process Variables  . . . . . . . . . . . . . . . .  45
     9.2.  40
     11.2. System Process Operations . . . . . . . . . . . . . . . .  47
       9.2.1.  42
       11.2.1.  Selection Algorithm  . . . . . . . . . . . . . . . . .  48
       9.2.2.  Clustering  44
       11.2.2.  Cluster Algorithm  . . . . . . . . . . . . . . . .  50
       9.2.3.  Combining .  45
       11.2.3.  Combine Algorithm  . . . . . . . . . . . . . . . . .  52
       9.2.4.  46
     11.3. Clock Discipline Algorithm  . . . . . . . . . . . . .  56
     9.3. . .  48
   12. Clock Adjust Process  . . . . . . . . . . . . . . . . . .  64
   10. . .  52
   13. Poll Process  . . . . . . . . . . . . . . . . . . . . . . . .  65
     10.1.  52
     13.1. Poll Process Variables and Parameters  . . . . . . . . . .  65
     10.2. . . . . . . .  52
     13.2. Poll Process Operations . . . . . . . . . . . . . . . . .  66
   11.  53
   14. Security Considerations . . . . . . . . . . . . . . . . . . .  67
   12.  55
   15. IANA Considerations . . . . . . . . . . . . . . . . . . . . .  67
   13.  56
   16. Acknowledgements  . . . . . . . . . . . . . . . . . . . . . .  68
   14.  56
   17. Informative References  . . . . . . . . . . . . . . . . . . .  68  56
   Appendix A.  Code Skeleton  . . . . . . . . . . . . . . . . . . .  68  57
     A.1.  Global Definitions  . . . . . . . . . . . . . . . . . . .  69  58
       A.1.1.   Definitions, Constants, Parameters . . . . . . . . .  69  58
       A.1.2.   Packet Data Structures . . . . . . . . . . . . . . .  72  61
       A.1.3.   Association Data Structures  . . . . . . . . . . . . .  73  62
       A.1.4.   System Data Structures . . . . . . . . . . . . . . .  76  64
       A.1.5.   Local Clock Data Structures  . . . . . . . . . . . . .  77  65
       A.1.6.   Function Prototypes  . . . . . . . . . . . . . . . . .  77  65
     A.2.  Main Program and Utility Routines . . . . . . . . . . . .  78  66
     A.3.  Kernel Input/Output Interface . . . . . . . . . . . . . .  82  69
     A.4.  Kernel System Clock Interface . . . . . . . . . . . . . .  82  69
     A.5.  Peer Process  . . . . . . . . . . . . . . . . . . . . . .  84  71
       A.5.1.   receive()  . . . . . . . . . . . . . . . . . . . . . .  85  72
       A.5.2.  packet()  . . . . . . . . . . . . . . . . . . . . . .  90
       A.5.3.   clock_filter() . . . . . . . . . . . . . . . . . . .  92
       A.5.4.  79
       A.5.3.   fast_xmit()  . . . . . . . . . . . . . . . . . . . . .  93
       A.5.5.  83
       A.5.4.   access() . . . . . . . . . . . . . . . . . . . . . .  95
     A.6.  85
       A.5.5.   System Process . . . . . . . . . . . . . . . . . . . . .  95
       A.6.1.  clock_select()  . . . . . . . . . . . . . . . . . . .  95
       A.6.2.  root_dist() . . . . . . . . . . . . . . . . . . . . .  99
       A.6.3.  accept()  . . . . . . . . . . . . . . . . . . . . . . 100
       A.6.4.  clock_update()  . . . . . . . . . . . . . . . . . . . 100
       A.6.5.  clock_combine() . . . . . . . . . . . . . . . . . . . 103
       A.6.6.  local_clock() . . . . . . . . . . . . . . . . . . . . 103
       A.6.7.  rstclock()  . . . . . . . . . . . . . . . . . . . . . 109
     A.7.  85
       A.5.6.   Clock Adjust Process . . . . . . . . . . . . . . . . . . 109
       A.7.1.  clock_adjust()  . . . . . . . . . . . . . . . . . . . 109
     A.8.  99
       A.5.7.   Poll Process . . . . . . . . . . . . . . . . . . . . . . 110
       A.8.1.  poll()  . . . . . . . . . . . . . . . . . . . . . . . 110
       A.8.2.  poll_update() . . . . . . . . . 100
   Authors' Addresses  . . . . . . . . . . . 112
       A.8.3.  peer_xmit() . . . . . . . . . . . . 107
   Intellectual Property and Copyright Statements  . . . . . . . . . 114
   Authors' Addresses  . . . . . . . . . . . . . . . . . . . . . . . 115
   Intellectual Property and Copyright Statements  . . . . . . . . . 116 108

1.  Introduction

   This document specifies defines the Network Time Protocol Version 4 (NTPv4),
   which is widely used to synchronize the system clocks among a set of
   distributed time servers and clients.  This document defines  It describes the core
   architecture, protocol, state machines, data structures and
   algorithms.  This document describes NTPv4, which  NTPv4 introduces new functionality to NTPv3 NTPv3, as
   described in [1], and functionality expanded from that of SNTPv4 as described
   in [2] (SNTPv4 is a subset of NTPv4).  This document obsoletes RFC 1305 [1],
   and RFC 4330. [2].  While certain minor changes have been made in some protocol
   header fields, these do not affect the interoperability between NTPv4
   and previous
   versions. versions of NTP and SNTP.

   The NTP subnet model includes a number of widely accessible primary
   time servers synchronized by wire or radio to national standards.
   The purpose of the NTP protocol is to convey timekeeping information
   from these primary servers to secondary time servers and clients via
   both private networks and the public Internet.  Crafted algorithms
   mitigate errors that may result from network disruptions, server
   failures and possible hostile action.  Servers and clients are
   configured such that values flow from the primary servers at the root
   via branching secondary servers toward clients.

   The NTPv4 design overcomes significant shortcomings in the NTPv3
   design, corrects certain bugs and incorporates new features.  In
   particular, expanded NTP timestamp definitions encourage the use of
   floating double data types throughout any the implementation.  The time
   resolution is better than one nanosecond and frequency resolution
   better than one nanosecond per second.  Additional improvements
   include a new clock discipline algorithm which is more responsive to
   system clock hardware frequency fluctuations.  Typical primary
   servers using modern machines are precise within a few tens of
   microseconds.  Typical secondary servers and clients on fast LANs are
   within a few hundred microseconds with poll intervals up to 1024
   seconds, which was the maximum with NTPv3.  With NTPv4, servers and
   clients are within a few tens of milliseconds with poll intervals up
   to 36 hours.

   The main body of this document describes only the core protocol and data
   structures necessary to interoperate between conforming
   implementations.  Additional  Appendix A contains additional detail is provided in the form
   of a skeleton program included as an appendix.  This program includes including data structures and code segments for
   the core algorithms and in addition the mitigation algorithms used to
   enhance reliability and accuracy.  While the skeleton and other
   descriptions in this document apply to a particular implementation,
   they are not intended as the only way the required functions can be
   implemented.  While the NTPv3 symmetric key authentication scheme
   described in this document carries over from NTPv3, the Autokey
   public key authentication scheme new to NTPv4 is described in [3].

   The NTP protocol includes the modes of operation described in
   Section 2 using the data types described in Section 5 6 and the data
   structures in Section 6. 7.  The implementation model described in
   Section 4 5 is based on a multiple-process, threaded architecture,
   although other architectures could be used as well.  The on-wire
   protocol described in Section 7 8 is based on a returnable-time design
   which depends only on measured clock offsets, but does not require
   reliable message delivery.  The synchronization subnet is a self-
   organizing, hierarchical, master-slave network with synchronization
   paths determined by a shortest-path spanning tree and defined metric.
   While multiple masters (primary servers) may exist, there is no
   requirement for an election protocol.

   The remaining sections of this

   This document define the data structures includes material from [4], which contains flow charts
   and algorithms suitable equations unsuitable for a fully featured NTPv4 implementation.
   Appendix A contains the code skeleton with definitions, structures RFC format.  There is much additional
   information in [5], including an extensive technical analysis and code segments that represent the basic structure
   performance assessment of the protocol and algorithms in this
   document.  The reference
   implementation. implementation itself is available at
   www.ntp.org.

   The remainder of this document contains numerous variables and
   mathematical expressions.  Those  Some variables take the form of Greek
   characters.  Those Greek characters
   characters, which are spelled out by their full
   name, with the "cap" prefix added to variables referring to the
   corresponding upper case Greek character. case-sensitive name.
   For example capdelta DELTA refers to the uppercase Greek character, where while
   delta refers to the lowercase Greek character.  Furthermore, subscripts are
   denoted with
   a '_' separating the variable name and the subscript.  For '_', for example
   'theta_i' theta_i refers to the variable lowercase Greek
   character theta with subscript i, or phonetically 'theta theta sub i.' i.

1.1.  Requirements Notation

   The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
   "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
   document are to be interpreted as described in RFC 2119 [4]. [6].

2.  Modes of Operation

   An NTP implementation operates as a primary server, secondary server
   or client.  A primary server is synchronized directly to a reference
   clock, such as a GPS receiver or telephone modem service.  A client
   is synchronized to one or more upstream servers, but does not provide
   synchronization to dependent clients.  A secondary server has one or
   more upstream servers and one or more downstream servers or clients.
   All servers and clients claiming full NTPv4 compliance must implement
   the entire suite of algorithms described in this document.  In order
   to maintain stability in large NTP subnets, secondary servers must be
   fully NTPv4 compliant.

   Primary servers and clients complying with a subset of NTP, called
   the Simple Network Time

3.  Protocol (SNTPv4) [2], do not need to
   implement all algorithms.  SNTP Modes

   There are three NTP protocol variants, symmetric, client/server and
   broadcast.  Each is intended for primary servers
   equipped associated with a single reference clock, as well an association mode as clients with a
   single upstream server shown in
   Figure 1.  Persistent associations are mobilized upon startup and no dependent clients.  The fully developed
   NTPv4 implementation is intended for secondary servers with multiple
   upstream servers and multiple downstream servers or clients.  Other
   than these considerations, NTP and SNTP servers and clients are
   completely interoperable and can be mixed
   never demobilized.  Ephemeral associations are mobilized upon arrival
   of a packet and matched in NTP subnets. are demobilized upon error or timeout.

               +-------------------+--------------+-------------+
               |  Association Mode | Assoc. Mode  | Packet Mode |
               +-------------------+--------------+-------------+
               | 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         |
               +-------------------+--------------+-------------+

                   Table

                  Figure 1: Association and Packet Modes

   There are three NTP protocol variants, symmetric, client/server and
   broadcast.  Each is associated with an association mode as shown in
   Table 1.

   In the client/server variant a persistent client association sends
   mode-3 (client)
   client (mode 3) packets to a server, which returns mode-4 (server) server (mode 4)
   packets.  Servers provide synchronization to one or more clients, but
   do not accept synchronization from them.  A server can also be a
   reference clock driver which obtains time directly from a standard
   source such as a GPS receiver or telephone modem service.  We say
   that clients pull synchronization from servers.

   In the symmetric variant a peer operates as both a server and client
   using either a symmetric-active symmetric active or symmetric-passive symmetric passive association.  A
   symmetric-active
   persistent symmetric active association sends mode-1 (symmetric-active) symmetric active (mode
   1) packets to a symmetric-active symmetric active peer association.  Alternatively, a symmetric- an
   ephemeral symmetric passive association can be mobilized upon arrival
   of a mode-1 packet. symmetric active packet matching no association.  That
   association sends mode-2 (symmetric-passive) symmetric passive (mode 2) packets and persists
   until error or timeout.  Peers both push and pull synchronization to
   and from each other.  For the purposes of this document, a peer
   operates like a client, so a reference to client implies peer as
   well.

   In the broadcast variant a persistent broadcast server association
   sends periodic mode-5 (broadcast) broadcast server (mode 5) packets which are can be
   received by multiple
   mode-6 (broadcast client) associations. clients.  Upon reception of a broadcast server
   packet matching no association, an ephemeral broadcast client (mode
   6) association is mobilized and persists until error or timeout.  It
   is useful to provide an initial volley where the client operating in
   client mode 3 exchanges several packets with the server in order to
   calibrate the propagation delay and to run the Autokey security
   protocol, after which the client reverts to mode 6. broadcast client mode.
   We say that broadcast servers push synchronization to willing
   consumers.

   Following conventions established by the telephone industry, the
   level of each server in the hierarchy is defined by a number called
   the stratum, with the primary servers assigned stratum one and the
   secondary servers at each level assigned one greater than the
   preceding level.  As the stratum increases from one, the accuracies
   achievable degrade somewhat depending on the particular network path
   and system clock stability.  It is useful to assume that mean errors,
   and thus a metric called the synchronization distance, increase
   approximately in proportion to the stratum and measured roundtrip round trip
   delay.  It is important to note that NTP stratum is only loosely
   modeled after the telecommunications stratum.  The NTP stratum numbers
   and telecommunications stratum numbers do not correlate with one
   another.  Telecommunications stratum numbers are rigorously stratum, which is defined by
   international standards that are not covered within this document. agreement.

   Drawing from the experience of the telephone telecommunications industry, which
   learned such lessons at considerable cost, the subnet topology should
   be organized to produce the lowest synchronization distances, but
   must never be allowed to form a loop.  In NTP the subnet topology is
   determined using a variant of the Bellman-Ford distributed routing
   algorithm, which computes the shortest-distance spanning tree rooted
   on the primary servers.  As a result of this design, the algorithm
   automatically reorganizes the subnet to produce the most accurate and
   reliable time, even when one or more primary or secondary servers or
   the network paths fail.

3.  Definitions

   A number of terms used throughout this document have

3.1.  Simple Network Time Protocol (SNTP)

   Primary servers and clients complying with a precise
   technical definition.  A timescale subset of NTP, called
   the Simple Network Time Protocol (SNTPv4) [2], do not need to
   implement the mitigation algorithms described in Section 9 and
   following sections.  SNTP is intended for primary servers equipped
   with a frame of single reference where time
   is expressed clock, as the value of well as for clients with a monotonic-increasing binary counter
   with an indefinite number of bits.  It counts in seconds single
   upstream server and fraction
   with the decimal point somewhere in the middle.  The Coordinated
   Universal Time (UTC) timescale represents mean solar time as
   disseminated by national standards laboratories. no dependent clients.  The system time fully developed NTPv4
   implementation is
   represented by the system clock maintained by the operating system
   kernel.  The goal of the intended for secondary servers with multiple
   upstream servers and multiple downstream servers or clients.  Other
   than these considerations, NTP algorithms is to minimize both the time
   difference and frequency difference between UTC SNTP servers and clients are
   completely interoperable and can be mixed and matched in NTP subnets.

   An SNTP primary server implementing the system on-wire protocol described in
   Section 8 has no upstream servers except a single reference clock.
   When these differences have been reduced below nominal tolerances,
   the system clock
   In principle, it is said to be synchronized to UTC.

   The date of indistinguishable from an event is the UTC time at which it takes place.  Dates
   are ephemeral values NTP primary server
   which always increase in step with reality and
   are designated with upper case T in this document.  It is convenient has the mitigation algorithms, presumably to define another timescale coincident with mitigate between
   multiple reference clocks.

   Upon receiving a client request, an SNTP primary server constructs
   and sends the running time reply packet as described in Figure 2 of the
   NTP program Section 9.2.
   Note that provides the synchronization function.  This is
   convenient dispersion field in order to determine intervals for the various repetitive
   functions like poll events.  Running time is usually designated packet header must be updated
   as described in Section 4.

                   +-----------------------------------+
                   | Packet Variable <--   Variable    |
                   +-----------------------------------+
                   | x.leap        <--     s.leap      |
                   | x.version     <--     r.version   |
                   | x.mode        <--     4           |
                   | x.stratum     <--     s.stratum   |
                   | x.poll        <--     r.poll      |
                   | x.precision   <--     s.precision |
                   | x.rootdelay   <--     s.rootdelay |
                   | x.rootdisp    <--     s.rootdisp  |
                   | x.refid       <--     s.refid     |
                   | x.reftime     <--     s.reftime   |
                   | x.org         <--     r.xmt       |
                   | x.rec         <--     r.dst       |
                   | x.xmt         <--     clock       |
                   | x.keyid       <--     r.keyid     |
                   | x.digest      <--     md5 digest  |
                   +-----------------------------------+

                     Figure 2: fast_xmit Packet Header

   A SNTP client implementing the on-wire protocol has a single server
   and no dependent clients.  It can operate with any subset of the NTP
   on-wire protocol, the simplest using only the transmit timestamp of
   the server packet and ignoring all other fields.  However, the
   additional complexity to implement the full on-wire protocol is
   minimal and is encouraged.

3.2.  Dynamic Server Discovery

   There are two special associations, manycast client and manycast
   server, which provide a dynamic server discovery function.  There are
   two types of manycast client associations, persistent and ephemeral.
   The persistent manycast client sends client (mode 3) packets to a
   designated IPv4 or IPv6 broadcast or multicast group address.
   Designated manycast servers in range of the time-to-live (TTL) field
   in the packet listen for packets with that address.  If suitable for
   synchronization, the server returns an ordinary server (mode 4)
   packet, but using its unicast address rather than its broadcast
   address.  Upon receipt an ephemeral client (mode 3) association is
   mobilized using the addresses and other data in the persistent
   manycast client association and server packet header.  The ephemeral
   client association persists until error or timeout.

   The manycast client continues to send packets until a specified
   minimum number of client associations have been mobilized.  If fewer
   than this number have been found, the client sends packets starting
   with a TTL of one and increasing by one for each subsequent packet
   until reaching a designated maximum.  Upon reaching the maximum,
   packets are not sent until after a designated timeout, after which
   the cycle repeats.  If at least the minimum number of associations
   have been found, the client sends one packet at each timeout.

   It is the intent that ephemeral associations compete with other
   associations and newly discovered associations.  As each crop of
   ephemeral associations are mobilized, the mitigation algorithms
   described in Section 10 and Section 11.2 sift the best candidates
   from the population and the remaining ephemeral associations time out
   and are demobilized.  In this way the population includes only the
   best and freshest candidates to discipline the system clock.  The
   reference implementation includes intricate means to do this, but
   these are beyond the scope of this document.

4.  Definitions

   A number of terms used throughout this document have a precise
   technical definition.  A timescale is a frame of reference where time
   is expressed as the value of a monotonic-increasing binary counter
   with an indefinite number of bits.  It counts in seconds and fraction
   with the decimal point somewhere in the middle.  The Coordinated
   Universal Time (UTC) timescale represents mean solar time as
   disseminated by national standards laboratories.  The system time is
   represented by the system clock maintained by the hardware and
   operating system.  The goal of the NTP algorithms is to minimize both
   the time difference and frequency difference between UTC and the
   system clock.  When these differences have been reduced below nominal
   tolerances, the system clock is said to be synchronized to UTC.

   The date of an event is the UTC time at which it takes place.  Dates
   are ephemeral values which always increase in step with reality and
   are designated with upper case T in this document.  It is convenient
   to define another timescale coincident with the running time of the
   NTP program that provides the synchronization function.  This is
   convenient in order to determine intervals for the various repetitive
   functions like poll events.  Running time is designated with lower
   case t.

   A timestamp T(t) represents either the UTC date or time offset from
   UTC at running time t.  Which meaning is intended should be clear
   from the context.  Let T(t) be the time offset, R(t) the frequency
   offset, D(t) the ageing rate (first derivative of R(t) with respect
   to t).  Then, if T(t_0) is the UTC time offset determined at t=t_0, t = t_0,
   the UTC time offset after some interval is: is

   T(t+t_0) = T(t_0) + R(t_0)(t+t_0)+(1/2)*D(t_0)(t+t_0)^2 R(t_0)(t+t_0) + 1/2 * D(t_0)(t+t_0)^2 + e,

   where e is a stochastic error term discussed later in this document.
   While the D(t) term is important when characterizing precision
   oscillators, it is ordinarily neglected for computer oscillators.  In
   this document all time values are in seconds (s) and all frequency
   values are in seconds-per-second (s/s).  It is sometimes convenient
   to express frequency offsets in parts-per-million (PPM), where 1 PPM
   is equal to 1*10^(-6) 10^(-6) seconds.

   It is important in computer timekeeping applications to assess the
   performance of the timekeeping function.  The NTP performance model
   includes four statistics which are updated each time a client makes a
   measurement with a server.  The offset theta (theta) represents the maximum-
   likelihood
   maximum-likelihood time offset of the server clock relative to the
   system clock.  The delay del (delta) represents the roundtrip round trip delay
   between the client and server.  The dispersion epsilon (epsilon) represents
   the maximum error inherent in the measurement.  It increases at a
   rate equal to the maximum disciplined system clock frequency
   tolerance phi, (PHI), typically 15 PPM.  The jitter psi, (psi) is defined as
   the root-mean-square (RMS) average of the most recent time offset
   differences, represents the nominal error in estimating theta. the offset.

   While the theta, del, delta, epsilon, and psi statistics represent
   measurements of the system clock relative to the each server clock
   separately, the NTP protocol includes mechanisms to combine the
   statistics of several servers to more accurately discipline and
   calibrate the system clock.  The system offset captheta (THETA) represents the
   maximum-likelihood offset estimate for the server population.  The
   system jitter, defined as vartheta, jitter (PSI) represents the nominal error in estimating captheta. the
   system offset.  The del delta and epsilon statistics are accumulated at
   each stratum level from the reference clocks clock to produce the root delay delta rootdelay
   (DELTA) and root dispersion capepsilon (EPSILON) statistics.  The
   synchronization distance gamma=capepsilon+delta/2 (LAMBDA) equal to EPSILON + DELTA / 2
   represents the maximum error due all causes.  The detailed
   formulations of these statistics are given later in this document. Section 11.2.  They are
   available to the dependent applications in order to assess the
   performance of the synchronization function.

    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 |     Strat     |     Poll      |     Prec      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         Root Delay                            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         Root Dispersion                       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                          Reference ID                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   +                       Reference Timestamp                     +
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   +                        Origin Timestamp                       +
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   +                        Receive Timestamp                      +
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   +                        Transmit Timestamp                     +
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   +                    Extension Field 1 (Optional)               +
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   +                    Extension Field 2 (Optional)               +
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   .                                                               .
   .                          Authentication                       .
   .                       (Optional) (160 bits)                   .
   .                                                               .
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                      Figure 1: NTPv4 Message Format

4.

5.  Implementation Model

   Figure 2 3 shows the architecture of a typical, multiple-thread
   implementation.  It includes two processes dedicated to each server,
   a peer process to receive messages from the server or reference clock
   and a poll process to transmit messages to the server or reference
   clock. .

   ..........................................................

   .....................................................................
   . Remote   ..   .   Peer/Poll   ..  .              System          .  Clock   .
   . Servers  ..  .   Processes   ..  .              Process         .Discipline.
   .          .          ..               ..              .
   .----------..-------------..--------------                              . Process  .
   .+--------+. +-----------+. +------------+               .          .
   .|        |->|           |..|           |. |            |               .          .
   .|Server 1|..|Peer/Poll 1|  |Peer/Poll 1|->|            |               .          .
   .|        |<-|           |..|           |. |               ............
   .----------..-------------..|            |               .   Clock          .
                                                            .Discipline.
   .+--------+. +-----------+. |            |               .          .
   .          .          ..       ^     ..|      . |               .. Process            |               .          .
   .          .          ..       |     ..|      . |            |               ..               .
   .----------..-------------..|          .
   .+--------+. +-----------+. |            |  |-----------|..  +-----------+.          .
   .|        |->|           |..|           |. | Selection  |->|            ..--------           |. +------+ .
   .|Server 2|..|Peer/Poll 2|  |Peer/Poll 2|->|    and     |  | Combining Combine   |->| Loop | .
   .|        |<-|           |..| Clustering           |. | Cluster    |  | Algorithm |..|Filter| |. |Filter| .
   .----------..-------------..|
   .+--------+. +-----------+. | Algorithms |->|           |.-----------           |. +------+ .
   .          .          ..       ^     ..|      . |  |-----------|.            |  +-----------+.    |     .
   .          .       |      .          .. |     ..|            |               .    |
   .----------..-------------..|     .
   .+--------+. +-----------+. |            |               .    |     .
   .|        |->|           |..|           |. |            |               .    |     .
   .|Server 3|..|Peer/Poll 3|  |Peer/Poll 3|->|            |               .    |     .
   .|        |<-|           |..|           |. |               .            |
   .----------..-------------..|------------|               .    |
   ....................^.....................................     |
                       |                                          |     .
   .+--------+. +-----------+. +------------+               .    |                                         \|/     .
   ....................^.........................................|......
                       |                                ...............                                    .    V     .
                       |                                    .   /-----\ +-----+  .
                       '----------------------------------<-|
                       +--------------------------------------| VFO |-<-. |  .   \-----/
                                                            . +-----+  .
                                                            .  Clock Adjust.   .
                                                            .  Adjust  .
                                                            .  Process .
                                                        ...............
                                                            ............

                       Figure 2: NTPv4 Algorithm Interactions 3: Implementatin Model

   These processes operate on a common data structure structure, called an
   association, which contains the statistics described above along with
   various other data described later. in Section 9.  A client sends an NTP packet packets to
   one or more servers and processes the replies as received.  The
   server interchanges addresses and ports, overwrites certain fields in
   the packet and returns it immediately (client/ server (client/server mode) or at some
   time later (symmetric modes).  As each NTP message is received, the
   offset theta between the peer clock and the system clock is computed
   along with the associated statistics del, epsilon, delta, epsilon and psi.

   The system process includes the selection, clustering cluster and combining combine
   algorithms which mitigate among the various servers and reference
   clocks to determine the most accurate and reliable candidates to
   synchronize the system clock.  The selection algorithm uses Byzantine
   principles to discard the falsetickers from the incident population,
   leaving only truechimers.  A 'truechimer' truechimer is a clock that maintains
   timekeeping accuracy to a previously published (and trusted)
   standard, while a 'falseticker' falseticker is a clock that does not maintain
   that level of timekeeping accuracy. shows misleading or
   inconsistent time.  The clustering cluster algorithm uses statistical principles
   to sift the most accurate truechimers leaving the survivors as
   result.  The combining combine algorithm develops the final clock offset as a
   statistical average of the survivors.

   The clock discipline process, which is actually part of the system
   process, includes engineered algorithms to control the time and
   frequency of the system clock, here represented as a variable
   frequency oscillator (VFO).  Timestamps struck from the VFO close the
   feedback loop which maintains the system clock time.  Associated with
   the clock discipline process is the clock adjust process, which runs
   once each second to inject a computed time offset and maintain
   constant frequency.  The RMS average of past time offset differences
   represents the nominal error or system jitter vartheta. clock jitter.  The RMS average
   of past frequency offset differences represents the oscillator
   frequency stability or frequency wander cappsi. wander.  These terms are given
   precise interpretation in Section 11.2.

   A client sends messages to each server with a poll interval of 2^tau
   seconds, as determined by the poll exponent tau.  In NTPv4 NTPv4, tau
   ranges from 4 (16 s) through 17 (36 h).  The value of tau is
   determined by the clock discipline algorithm to match the loop time
   constant
   T_c=2^tau.  A server responds with messages at an update interval of
   mu seconds.  For stateless servers, mu=T_c, since T_c = 2^tau.  In client/server mode the server responds
   immediately.  However,
   immediately; however, in symmetric modes each of two peers manages
   the time constant
   tau as a function of current system offset and system jitter, so may
   not agree with the same tau. value.  It is important that the dynamic
   behavior of the clock discipline algorithms algorithm be carefully controlled in
   order to maintain stability in the NTP subnet at large.  This
   requires that the peers agree on a common tau equal to the minimum
   poll exponent of both peers.  The NTP protocol includes provisions to
   properly negotiate this value.

   While not shown in the figure, the

   The implementation model includes some means to set and adjust the
   system clock.  The operating system is assumed to provide two
   functions, one to set the time directly, for example the Unix
   settimeofday() function, and another to adjust the time in small
   increments advancing or retarding the time by a designated amount,
   for example the Unix adjtime() function
   (parentheses function.  In this and following
   references, parentheses following a name indicate reference to a
   function rather than a simple variable). variable.  In the intended design the
   clock discipline process uses the adjtime() function if the
   adjustment is less than a designated threshold, and the
   settimeofday() function if above the threshold.  The manner in which
   this is done and the value of the threshold is as described later.

5. in
   Section 10.

6.  Data Types

   All NTP time values are represented in twos-complement format, with
   bits numbered in big-endian (as described in Appendix A of [5]) [7])
   fashion from zero starting at the left, or high-order, position.
   There are three NTP time formats, a 128-bit date format, a 64-bit
   timestamp format and a 32-bit short format, as shown in Figure 3. 4.
   The 128-bit date format is used where sufficient storage and word
   size are available.  It includes a 64-bit signed seconds field
   spanning 584 billion years and a 64-bit fraction field resolving .05
   attosecond (i.e. (i.e., 0.5e-18).  For convenience in mapping between
   formats, the seconds field is divided into a 32-bit era Era Number field
   and a 32-bit timestamp Era Offset field.  Eras cannot be produced by NTP
   directly, nor is there need to do so.  When necessary, they can be
   derived from external means, such as the filesystem or dedicated
   hardware.

       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
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |          Seconds              |           Fraction            |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                               NTP Short Format

       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
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                            Seconds                            |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                            Fraction                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                             NTP Timestamp Format

       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

                        Figure 3: 4: NTP Time Format Formats

   The 64-bit timestamp format is used in packet headers and other
   places with limited word size.  It includes a 32-bit unsigned seconds
   field spanning 136 years and a 32-bit fraction field resolving 232
   picoseconds.  The 32-bit short format is used in delay and dispersion
   header fields where the full resolution and range of the other
   formats are not justified.  It includes a 16-bit unsigned seconds
   field and a 16-bit fraction field.

   In the date format and timestamp formats the prime epoch, or base date of
   era 0, is 0 h 1 January 1900 UTC, when all bits are zero.  It should
   be noted that strictly speaking, UTC did not exist prior to 1 January
   1972, but it is convenient to assume it has existed for all eternity,
   even if all knowledge of historic leap seconds has been lost.  Dates
   are relative to the prime epoch; values greater than zero represent
   times after that date; values less than zero represent times before
   it.  Note that the Era Offset field of the date format and the
   Seconds field of the timestamp format have the same interpretation.

   Timestamps are unsigned values and operations on them produce a
   result in the same or adjacent eras.  Era 0 includes dates from the
   prime epoch to some time in 2036, when the timestamp field wraps
   around and the base date for era 1 is established.  In either format
   a value of zero is a special case representing unknown or
   unsynchronized time.  Table 2  Figure 5 shows a number of historic NTP dates
   together with their corresponding Modified Julian Day (MJD), NTP era
   and NTP timestamp.

   +-------------+------------+-----+---------------+------------------+
   | Year        | MJD        | NTP | NTP Timestamp | Epoch            |
   |             |            | Era | Era Offset    |                  |
   +-------------+------------+-----+---------------+------------------+
   | 1 Jan -4712 | -2,400,001 | -49 | 1,795,583,104 | 1st day Julian   |
   | 1 Jan -1    | -679,306   | -14 | 139,775,744   | 2 BCE            |
   | 1 Jan 0     | -678,491   | -14 | 171,311,744   | 1 BCE            |
   | 1 Jan 1     | -678,575   | -14 | 202,939,144   | 1 CE             |
   | 4 Oct 1582  | -100,851   | -3  | 2,873,647,488 | Last day Julian  |
   | 15 Oct 1582 | -100,840   | -3  | 2,874,597,888 | First day        |
   |             |            |     |               | Gregorian        |
   | 31 Dec 1899 | 15019      | -1  | 4,294,880,896 | Last day NTP Era |
   |             |            |     |               | -1               |
   | 1 Jan 1900  | 15020      | 0   | 0             | First day NTP    |
   |             |            |     |               | Era 0            |
   | 1 Jan 1970  | 40,587     | 0   | 2,208,988,800 | First day UNIX   |
   | 1 Jan 1972  | 41,317     | 0   | 2,272,060,800 | First day UTC    |
   | 31 Dec 1999 | 51,543     | 0   | 3,155,587,200 | Last day 20th    |
   |             |            |     |               | Century          |
   | 8 Feb 2036  | 64,731     | 1   | 63,104        | First day NTP    |
   |             |            |     |               | Era 1            |
   +-------------+------------+-----+---------------+------------------+

                  Table 2:

                 Figure 5: Interesting Historic NTP Dates

   Let p be the number of significant bits in the second fraction.  The
   clock resolution is defined 2^(-p), in seconds.  In order to minimize
   bias and help make timestamps unpredictable to an intruder, the non-
   significant bits should be set to an unbiased random bit string.  The
   clock precision is defined as the running time to read the system
   clock, in seconds.  Note that the precision defined in this way can
   be larger or smaller than the resolution.  The term rho, representing
   the precision used in this document, the protocol, is the larger of the two.

   The only arithmetic operation permitted with on dates and timestamps is twos-
   complement
   twos-complement subtraction, yielding a 127-bit or 63-bit signed
   result.  It is critical that the first-order differences between two
   dates preserve the full 128-bit precision and the first-order
   differences between two timestamps preserve the full 64-bit
   precision.  However, the differences are ordinarily small compared to
   the seconds span, so they can be converted to floating double format
   for further processing and without compromising the precision.

   It is important to note that twos-complement arithmetic does not know
   the difference between signed and unsigned values; only the
   conditional branch instructions. instructions do.  Thus, although the distinction
   is made between signed dates and unsigned timestamps, they are
   processed the same way.  A perceived hazard with 64-bit timestamp
   calculations spanning an era, such as possible in 2036, might result
   in incorrect values.  In point of fact, if the client is set within
   68 years of the server before the protocol is started, correct values
   are obtained even if the client and server are in adjacent eras.

   Some time values are represented in exponent format, including the
   precision, time constant and poll interval values. interval.  These are in 8-bit
   signed integer format in log2 (log to the base 2) seconds.  The only
   arithmetic operations permitted on them are increment and decrement.
   For the purpose of this document and to simplify the presentation, a
   reference to one of these state variables by name means the exponentiated
   value, e.g., the poll interval is 1024 s, while reference by name and
   exponent means the actual value, e.g., the poll exponent is 10.

   To convert system time in any format to NTP date and timestamp
   formats requires that the number of seconds s from the prime epoch to
   the system time be determined.  The era is  To determine the integer quotient era and
   the
   timestamp the integer remainder as in: given s,

   era = s / 2^(32) and timestamp = s - era*2^(32) era * 2^(32),

   which works for positive and negative dates.  To convert from NTP determine s given
   the era and timestamp to system time requires the calculation timestamp,

   s = era*2^(32) era * 2^(32) + timestamp

   to determine the number of seconds since the prime epoch. timestamp.

   Converting between NTP and system time can be a little messy, but
   beyond the scope of this document.  Note that the number of days in
   era 0 is one more than the number of days in most other eras and this
   won't happen again until the year 2400 in era 3.

   In the description of state variables to follow, explicit reference
   to integer type implies a 32-bit unsigned integer.  This simplifies
   bounds checks, since only the upper limit needs to be defined.
   Without explicit reference, the default type is 64-bit floating
   double.  Exceptions will be noted as necessary.

6.

7.  Data Structures

   The NTP protocol state machines described in following sections are
   defined using state variables and flow chart fragments. code fragments defined in
   Appendix A.  State variables are separated into classes according to
   their function in packet headers, peer and poll processes, the system
   process and the clock discipline process.  Packet variables represent
   the NTP header values in transmitted and received packets.  Peer and
   poll variables represent the contents of the association for each
   server separately.  System variables represent the state of the
   server as seen by its dependent clients.  Clock discipline variables
   represent the internal workings of the clock discipline algorithm.
   Additional constant parameters and variable classes are defined in Appendix A.

6.1.

7.1.  Structure Conventions

   In order to distinguish between different variables of the same name
   but used in different processes, the naming convention summarized in
   Table 3
   Figure 6 is employed. adopted.  A receive packet variable v is a member of the
   packet structure r with fully qualified name r.v.  In a similar
   manner x.v is a transmit packet variable, p.v is a peer variable, s.v
   is a system variable and c.v is a clock discipline variable.  There
   is a set of peer variables for each association; there is only one
   set of system and clock variables.  Most flow chart fragments begin
   with a statement label and end with a named go-to or exit.  A
   subroutine call includes a dummy () following the name and return at
   the end to the point following the call.

                   +------+---------------------------------+
                   | Name | Description                     |
                   +------+---------------------------------+
                   | r.   | receive packet header variable  |
                   | x.   | transmit packet header variable |
                   | p.   | peer/poll variable              |
                   | s.   | system variable                 |
                   | c.   | clock discipline variable       |
                   +------+---------------------------------+

                     Table 3: Name

                       Figure 6: Prefix Conventions

6.2.

7.2.  Global Parameters

   In addition to the variable classes a number of global parameters are
   defined in this document, including those shown with values in
   Table 4.
   Figure 7.

            +-----------+-------+----------------------------------+
            | Name      | Value | Description                      |
            +-----------+-------+----------------------------------+
            | PORT      | 123   | NTP port number                  |
            | VERSION   | 4     | version number                   |
            | TOLERANCE | 15e-6 | frequency tolerance PHI (s/s)    |
            | MINPOLL   | 4     | minimum poll exponent (16 s)     |
            | MAXPOLL   | 17    | maximum poll exponent (36 h)     |
            | MAXDISP   | 16    | maximum dispersion (s) (16 s)        |
            | MINDISP   | .005  | minimum dispersion increment (s) |
            | MAXDIST   | 1     | distance threshold (s) (1 s)         |
            | MAXSTRAT  | 16    | maximum stratum number           |
            +-----------+-------+----------------------------------+

                        Table 4:

                        Figure 7: Global Parameters

   While these are the only global parameters needed in this document, a
   larger collection is necessary in the skeleton and larger still for
   any implementation.  Appendix A.1.1 contains those used by the
   skeleton for the mitigation algorithms, clock discipline algorithm
   and related implementation-dependent functions.  Some of these
   parameter values are cast in stone, like the NTP port number assigned
   by the IANA and the version number assigned NTPv4 itself.  Others
   like the frequency
   tolerance, tolerance (also called PHI), involve an assumption
   about the worst case behavior of a
   system clock once synchronized and then allowed to drift when its
   sources have become unreachable.  The minimum and maximum parameters
   define the limits of state variables as described in later sections.

   While shown with fixed values in this document, some implementations
   may make them variables adjustable by configuration commands.  For
   instance, the reference implementation computes the value of
   PRECISION as log2 of the minimum time in several iterations to read
   the system clock.

6.3.  Packet Header Variables

            +-----------+------------+-----------------------+
            | Name      | Formula    | Description           |
            +-----------+------------+-----------------------+
            | leap      | leap       | leap indicator (LI)   |
            | version   | version    | version number (VN)   |
            | mode      | mode       | mode                  |
            | stratum   | stratum    | stratum               |
            | poll      | poll       | poll exponent         |
            | precision | rho        | precision exponent    |
            | rootdelay | delta      | root delay            |
            | rootdisp  | capepsilon | root dispersion       |
            | refid     | refid      | reference ID          |
            | reftime   | reftime    | of a system clock once synchronized and
   then allowed to drift when its sources have become unreachable.  The
   minimum and maximum parameters define the limits of state variables
   as described in later sections of this document.

   While shown with fixed values in this document, some implementations
   may make them variables adjustable by configuration commands.  For
   instance, the reference timestamp   |
            | org       | T1         | origin timestamp      |
            | rec       | T2         | receive timestamp     |
            | xmt       | T3         | transmit timestamp    |
            | dst       | T4         | destination timestamp |
            | keyid     | keyid      | key ID                |
            | digest    | digest     | message digest        |
            +-----------+------------+-----------------------+

                     Table 5: implementation computes the value of
   PRECISION as log2 of the minimum time in several iterations to read
   the system clock.

7.3.  Packet Header Variables

   The most important state variables from an external point of view are
   the packet header variables described in Figure 8 and below.  The NTP
   packet header consists of a an integral number of 32-bit (4 octet)
   words in network byte order.  The packet format consists of three
   components, the header itself, one or more optional extension fields
   and an optional message authentication code (MAC).  The header component is identical to the NTPv3 header
   and previous versions.  The optional extension fields are used by the
   Autokey public key cryptographic algorithms described in [3].  The
   optional MAC is used by both Autokey and the symmetric key
   cryptographic algorithms described in the main body of this report.

   The NTP packet header follows the UDP and IP headers and the physical
   header specific to the underlying transport network.  It consists of
   a number of 32-bit (4-octet) words, although some fields use multiple
   words and others are packed in smaller fields within a word.  The NTP
   packet header shown in Figure 4 has 12 words followed by optional
   extension fields and finally an optional message authentication code
   (MAC) consisting of (MAC).  The header
   component is identical to the key identifier NTPv3 header and message digest fields. previous versions.
   The optional extension fields described in this section are used by the Autokey security protocol [3], which is not public key
   cryptographic algorithms described here. in [3].  The optional MAC is used
   by both Autokey and the symmetric key authentication
   scheme described in Appendix A.  As is the convention in other
   Internet protocols, all fields are in network byte order, commonly
   called big-endian.

   A list of the packet header variables is shown in Table 5 and cryptographic algorithm
   described in detail below.  The packet header fields apply to both
   transmitted (x prefix) and received packets (r prefix).  The NTP
   header is shown in report.

               +-----------+------------+-----------------------+
               | Name      | Formula    | Description           |
               +-----------+------------+-----------------------+
               | leap      | leap       | leap indicator (LI)   |
               | version   | version    | version number (VN)   |
               | mode      | mode       | mode                  |
               | stratum   | stratum    | stratum               |
               | poll      | poll       | poll exponent         |
               | precision | rho        | precision exponent    |
               | rootdelay | delta_r    | root delay            |
               | rootdisp  | epsilon_r  | root dispersion       |
               | refid     | refid      | reference ID          |
               | reftime   | reftime    | reference timestamp   |
               | org       | T1         | origin timestamp      |
               | rec       | T2         | receive timestamp     |
               | xmt       | T3         | transmit timestamp    |
               | dst       | T4         | destination timestamp |
               | keyid     | keyid      | key ID                |
               | digest    | digest     | message digest        |
               +-----------+------------+-----------------------+

                     Figure 4 , where the size of some multiple-word
   fields is shown in bits if not the default 32 bits. 8: Packet Header Variables

   The NTP packet header
   extends from follows the beginning of UDP and IP headers and the packet physical
   header specific to the end of the Transmit
   Timestamp field.  When using the IPv4 address family these underlying transport network.  Some fields are
   backwards compatible with NTPv3.  When using the IPv6 address family
   on an NTPv4 server with a NTPv3 client, the Reference Identifier
   field appears to be a random value use
   multiple words and others are packed in smaller fields within a timing loop might not be
   detected. word.
   The NTP packet header shown in Figure 9 has 12 words followed by
   optional extension fields and finally an optional message
   authentication code (MAC) consists consisting of a 32-bit
   Key Identifier followed by a 128bit Message Digest.  The message
   digest, or cryptosum, is calculated as in [6] over all header the key identifier field and
   optional extension fields.
   message digest field.

       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 |     Strat    Stratum     |     Poll      |     Prec  Precision   |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                         Root Delay                            |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                         Root Dispersion                       |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                          Reference ID                         |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                               |
      +                     Reference Timestamp (64)                  +
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                               |
      +                      Origin Timestamp (64)                    +
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                               |
      +                      Receive Timestamp (64)                   +
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                               |
      +                      Transmit Timestamp (64)                  +
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                               |
      +                    Extension Field 1 (variable)               +
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                               |
      +                    Extension Field 2 (variable)               +
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                          Key Identifier                       |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                               |
      |                       Message Digest (128)                    |
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                      Figure 9: Packet Header Format

   The extension fields are used to add optional capabilities, for
   example, the Autokey security protocol [3].  The extension field
   format is presented in order that the packet can be parsed without
   knowledge of the extension field functions.  The MAC is used by both
   Autokey and the symmetric key authentication scheme described in
   Appendix A.

   A list of the packet header variables is shown in Figure 8 and
   described in detail below.  Except for a minor variation when using
   the IPv6 address family, these fields are backwards compatible with
   NTPv3.  The packet header fields apply to both transmitted packets (x
   prefix) and received packets (r prefix).  In Figure 9 the size of
   some multiple-word fields is shown in bits if not the default 32
   bits.  The header extends from the beginning of the packet to the end
   of the Transmit Timestamp                     +
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   +                    Extension Field 1 (Optional)               +
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   +                    Extension Field 2 (Optional)               +
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   .                                                               .
   .                          Authentication                       .
   .                       (Optional) (160 bits)                   .
   .                                                               .
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                      Figure 4: NTPv4 Message Format field.

   The fields and associated packet variables (in parentheses) are
   interpreted as follows:

   leap:

   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, coded as
   follows:
   month with values defined in Figure 10.

           +-------+-------------------------------------------------+
           | Value | Meaning                                         |
           +-------+-------------------------------------------------+
           | 0     | no warning                                      |
           | 1     | last minute of the day has 61 seconds           |
           | 2     | last minute of the day has 59 seconds           |
           | 3     | alarm condition (the clock is not synchronized) |
           +-------+-------------------------------------------------+

                          Table 6:

                         Figure 10: Leap Indicator

   version:

   VN Version Number (version): 3-bit integer representing the NTP
   version number, currently 4.

   mode:

   Mode (mode): 3-bit integer representing the mode, with values defined as
   follows:
   in Figure 11.

                      +-------+--------------------------+
                      | Value | Meaning                  |
                      +-------+--------------------------+
                      | 0     | reserved                 |
                      | 1     | symmetric active         |
                      | 2     | symmetric passive        |
                      | 3     | client                   |
                      | 4     | server                   |
                      | 5     | broadcast                |
                      | 6     | NTP control message      |
                      | 7     | reserved for private use |
                      +-------+--------------------------+

                               Table 7: Mode

   stratum:

                       Figure 11: Association Modes

   Stratum (stratum): 8-bit integer representing the stratum, with
   values defined
   as follows: in Figure 12.

        +--------+-----------------------------------------------------+
        | Value  | Meaning                                             |
        +--------+-----------------------------------------------------+
        | 0      | unspecified or invalid                              |
        | 1      | primary server (e.g., equipped with a GPS receiver) |
        | 2-15   | secondary server (via NTP)                          |
        | 16     | client-only                                         |
     | 17-255 16-255 | undefined                                           |
        +--------+-----------------------------------------------------+

                             Table 8:

                         Figure 12: Packet Stratum

   It is customary to map the stratum value 0 in received packets to
   MAXSTRAT (16) in the peer variable p.stratum and to map p.stratum
   values of MAXSTRAT or greater to 0 in transmitted packets.  This
   allows reference clocks, which normally appear at stratum 0, to be
   conveniently mitigated using the same algorithms used for external
   sources.

   poll:

   Poll: 8-bit signed integer representing the maximum interval between
   successive messages, in log2 seconds.  Suggested default limits for
   minimum and maximum poll intervals are 6 and 10, respectively.

   precision:

   Precision: 8-bit signed integer representing the precision of the
   system clock, in log2 seconds.  For instance a value of -18
   corresponds to a precision of about one microsecond.  The precision
   can be determined when the service first starts up as the minimum
   time of several iterations to read the system clock.

   rootdelay:

   Root Delay (rootdelay): Total roundtrip round trip delay to the reference
   clock, in NTP short format.

   rootdisp:

   Root Dispersion (rootdisp): Total dispersion to the reference clock,
   in NTP short format.

   refid:

   Reference ID (refid): 32-bit code identifying the particular server
   or reference clock.  The interpretation depends on the value in the
   stratum field.  For packet stratum 0 (unspecified or invalid) this is
   a four-
   character four-character ASCII string, called the kiss code, used for
   debugging and monitoring purposes.  For stratum 1 (reference clock)
   this is a four-
   octet, four-octet, left-justified, zero-padded ASCII string
   assigned to the reference clock.  While not specifically enumerated
   in this document, the following identifiers in Figure 13 have been used as
   ASCII identifiers:

     +------+----------------------------------------------------------+
     | ID   | Clock Source                                             |
     +------+----------------------------------------------------------+
     | GOES | Geosynchronous Orbit Environment Satellite               |
     | GPS  | Global Position System                                   |
     | GAL  | Galileo Positioning System                               |
     | PPS  | Generic pulse-per-second                                 |
     | IRIG | Inter-Range Instrumentation Group                        |
     | WWVB | LF Radio WWVB Ft. Collins, CO 60 kHz                     |
     | DCF  | LF Radio DCF77 Mainflingen, DE 77.5 kHz                  |
     | HBG  | LF Radio HBG Prangins, HB 75 kHz                         |
     | MSF  | LF Radio MSF Anthorn, UK 60 kHz (Rugby until April 2007) |
     | JJY  | LF Radio JJY Fukushima, JP 40 kHz, Saga, JP 60 kHz       |
     | LORC | MF Radio LORAN C 100 kHz                                 |
     | TDF  | MF Radio Allouis, FR 162 kHz                             |
     | CHU  | HF Radio CHU Ottawa, Ontario                             |
     | WWV  | HF Radio WWV Ft. Collins, CO                             |
     | WWVH | HF Radio WWVH Kauai, HI                                  |
     | NIST | NIST telephone modem                                     |
     | ACTS | NIST telephone modem                                     |
     | USNO | USNO telephone modem                                     |
     | PTB  | European telephone modem                                 |
     +------+----------------------------------------------------------+

                          Table 9:

                     Figure 13: Reference IDs Identifiers

   Above stratum 1 (secondary servers and clients) this is the reference
   identifier of the server. server and is intended to detect timing loops.  If
   using the IPv4 address family, the identifier is the four-octet IPv4
   address.  If using the IPv6 address family, it is the first four
   octets of the MD5 hash of the IPv6 address.

   reftime:  Note that, when using
   the IPv6 address family on an NTPv4 server with a NTPv3 client, the
   Reference Identifier field appears to be a random value and a timing
   loop might not be detected.

   Reference Timestamp: Time when the system clock was last set or
   corrected, in NTP timestamp format.

   org:

   Origin Timestamp (org): Time at the client when the request departed
   for the server, in NTP timestamp format.

   rec:

   Receive Timestamp (rec): Time at the server when the request arrived
   from the client, in NTP timestamp format.

   xmt:

   Transmit Timestamp (xmt): Time at the server when the response left
   for the client, in NTP timestamp format.

   dst:

   Destination Timestamp (dst): Time at the client when the reply
   arrived from the server, in NTP timestamp format.

   Note: This value Destination Timestamp field is not included as a header field;
   it is determined upon arrival of the packet and made available in the
   packet buffer data structure.

   The MAC consists of the Key Identifier followed by the Message
   Digest.  The message digest, or cryptosum, is not included calculated as in a [8]
   over all header
   field; it is determined upon arrival of the packet and made available
   in optional extension fields, but not the packet buffer data structure.

   keyid: MAC
   itself.

   Key Identifier (keyid): 32-bit unsigned integer used by the client
   and server to designate a secret 128-bit MD5 key.  Together, the keyid and digest
   fields collectively are called message authentication code (MAC).

   digest:

   Message Digest (digest): 128-bit bitstring computed by the keyed MD5
   message digest
   algorithm described computed over all the words in Appendix A.

6.3.1. the header and
   extension fields, but not the MAC itself.

7.4.  The Kiss-o'-Death Packet

   If the Stratum field is 0, which is an 'unspecified' Stratum field
   value, implies unspecified or invalid, the
   Reference Identifier field can be used to convey messages useful for
   status reporting and access control.  In NTPv4 and SNTPv4,
   packets of this kind  These are called Kiss-o'-Death
   (KoD) packets and the ASCII messages they convey are called kiss
   codes.  The KoD packets got their name because an early use was to
   tell clients to stop sending packets that violate server access
   controls.  The kiss codes can provide useful information for an
   intelligent client.  These client, either NTPv4 or SNTPv4.  Kiss codes are encoded
   in four-character ASCII strings left justified and zero filled.  The
   strings are designed for character displays and log files.  A list of
   the currently-defined kiss codes is given below: in Figure 14.  Other than
   displaying the kiss code, KoD packets have no protocol significance
   and are discarded after inspection.

   +------+------------------------------------------------------------+
   | Code |                           Meaning                          |
   +------+------------------------------------------------------------+
   | ACST | The association belongs to a unicast server                |
   | AUTH | Server authentication failed                               |
   | AUTO | Autokey sequence failed                                    |
   | BCST | The association belongs to a broadcast server              |
   | CRYP | Cryptographic authentication or identification failed      |
   | DENY | Access denied by remote server                             |
   | DROP | Lost peer in symmetric mode                                |
   | RSTR | Access denied due to local policy                          |
   | INIT | The association has not yet synchronized for the first     |
   |      | time                                                       |
   | MCST | The association belongs to a dynamically discovered server |
   | NKEY | No key found. Either the key was never installed or is     |
   |      | not trusted                                                |
   | RATE | Rate exceeded. The server has temporarily denied access    |
   |      | because the client exceeded the rate threshold             |
   | RMOT | Alteration of association from a remote host running       |
   |      | ntpdc.                                                     |
   | STEP | A step change in system time has occurred, but the         |
   |      | association has not yet resynchronized                     |
   +------+------------------------------------------------------------+

                Table 10: Currently-defined NTP

                           Figure 14: Kiss Codes

6.3.2.

7.5.  NTP Extension Field Format

   In NTPv4 one or more extension fields can be inserted after the
   header and before the MAC, which is always present when an extension
   fields are present.  The extension fields can occur in any order;
   however, in some cases there
   field is a preferred order which improves present.  Other than defining the
   protocol efficiency. field format, this
   document makes no use of the field contents.  An extension field
   contains a request or response message in the format shown in
   Figure 5. 15.

       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
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |          Field Type           |            Length             |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                          Association ID                       |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                           Timestamp                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                           Filestamp                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                          Value Length                         |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      .                                                               .
      .                            Value                              .
      .                                                               .
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                        Signature Length                       |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      .                                                               .
      .                          Signature                            .
      .                                                               .
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                       Padding (as needed)                     |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                     Figure 5: NTP 15: Extension Field Format

   All extension fields are zero-padded to a word (4 octets) boundary
   and the last is padded to a 64-bit (8 octet) boundary.  The Length Field
   Type field covers the entire extension field, including is specific to the
   Length defined function and Padding fields. is not elaborated
   here.  While the minimum field length containing required fields is 4
   words (16 octets), a maximum field length remains to be established.

   The RE, VN, and Code fields together form a Field Type field, a 16-
   bit integer which indicates the type of extension message contained
   within the extension field.

   The Length field is a 16-bit integer which indicates the length of
   the entire extension field in octets, including the Length and Padding fields. field.

   The 32-bit Association ID field is set by clients to the value
   previously received from the server or 0 otherwise.  The server sets
   the Association ID field when sending a response as a handle for
   subsequent exchanges.  If the association ID value in a request does
   not match the association ID of any association, the server returns
   the request with value
   previously received from the first two bits of server or 0 otherwise.  The server sets
   the Field Type Association ID field set to 1. when sending a response as a handle for
   subsequent exchanges.

   The Timestamp and Filestamp 32-bit fields carry the seconds field of
   an NTP timestamp.  The Timestamp field establishes the signature
   epoch of the data field in the message, extension field, while the filestamp
   establishes the generation epoch of the file that ultimately produced
   the data.

   The 32-bit Value Length field indicates the length of the Value field
   in octets.  The minimum length of the Value this field is 0, in which case the
   Value field itself is omitted.

   The 32-bit Value Signature Length field indicates the length of the Value
   Signature field in octets.  The minimum length of the Value this field is 0.

   Zero padding is applied, as necessary, to extend
   In which case the extension Signature field
   to a word (4-octet) boundary. itself is omitted.

   If multiple extension both the Value Length and Signature Length fields are
   present, 0, both of
   these words can be omitted, in which case the last extension field is zero-padded to a double-word (8
   octet) boundary. has
   length 4 words.

   The presence of the MAC and extension fields in the packet is
   determined from the length of the remaining area after the header to
   the end of the packet.  The parser initializes a pointer just after
   the header.  If the Length field is not a multiple of 4, a format
   error has occurred and the packet is discarded.  The following cases
   are possible based on the remaining length in words.
    0        The packet contains no MAC and is not authenticated.
    1        The packet is an error report or crypto-NAK.
    2, 3, 4  The packet is discarded with a format error.
    5        The remainder of the packet is the 160-bit MAC.
    >5       One or more extension fields are present.

   If an extension field is present, the parser examines the Length
   field.  If the length is less than 4 or not length is less than 4 or not a multiple of 4, a format
   error has occurred and the packet is discarded; otherwise, the parser
   increments the pointer by this value.  The parser now uses the same
   rules as above to determine whether a MAC is present and/or another
   extension field.  An additional implementation dependent test is
   necessary to ensure the pointer does not stray outside the buffer
   space occupied by the packet.

8.  On Wire Protocol

   The heart of the NTP on-wire protocol is the core mechanism which
   exchanges time values between servers, peers and clients.  It is
   inherently resistant to lost or duplicate packets.  Data integrity is
   provided by the IP and UDP checksums.  No flow control or
   retransmission facilities are provided or necessary.  The protocol
   uses timestamps, either extracted from packet headers or struck from
   the system clock upon the arrival or departure of a packet.
   Timestamps are precision data and should be restruck in case of link
   level retransmission and corrected for the time to compute a multiple MAC on
   transmit.

   NTP messages make use of 4, a format
   error has occurred two different communication modes, one-to-
   one and one-to-many, commonly referred to as unicast and broadcast.
   For the packet purposes of this document, the term broadcast is discarded; otherwise, interpreted
   to mean any available one-to-many mechanism.  For IPv4 this equates
   to either IPv4 broadcast or IPv4 multicast.  For IPv6 this equates to
   IPv6 multicast.  For this purpose, IANA has allocated the parser
   increments IPv4
   multicast address 224.0.1.1 and the pointer IPv6 multicast address ending
   :101, with prefix determined by this value. scoping rules.

   The parser now on-wire protocol uses the same
   rules four timestamps numbered T1 through T4 and
   three state variables org, rec and xmt, as above to determine whether a MAC is present and/or another
   extension field.  An additional implementation dependent test is
   necessary shown in Figure 17.  This
   figure shows the most general case where each of two peers, A and B,
   independently measure the offset and delay relative to ensure the pointer does not stray outside other.
   For purposes of illustration the buffer
   space occupied by individual timestamp values are
   shown in lower case with a number indicating the packet.

7.  On Wire Protocol order of
   transmission and reception.

              t2            t3           t6            t7
         +---------+   +---------+   +---------+   +---------+
     T1  |    0    |   |    t2    t1   |   |   t4   t3    |   |    t6    t5   |
         +---------+   +---------+   +---------+   +---------+
     T2  |    0    |   |    t1    t2   |   |   t3   t4    |   |    t5    t6   |  Packet
         +---------+   +---------+   +---------+   +---------+ Variables
     T3  |t2=clock  |   t1    |    t2   |t3=clock |   |t6=clock   |   t5    |    t6   |t7=clock |
         +---------+   +---------+   +---------+   +---------+
     T4  |t2=clock |   t1    |   |t3=clock |   |   t5    |   |t7=clock                 |t6=clock |
         +---------+                 +---------+   +---------+   +---------+
                                                                Peer B
         +---------+   +---------+   +---------+   +---------+
    org  |   t1    |   |    t1   |   | T3<>t1? |   |    t5   |
         +---------+   +---------+   +---------+   +---------+   State
    rec  |   t2    |   |    t2   |   |   t6    |   |    t6   | Variables
         +---------+   +---------+   +---------+   +---------+
    xmt  |    0    |   |    t3   |   | T1<>t3? |   |    t7   |
         +---------+   +---------+   +---------+   +---------+

                   t2      t3                 t6          t7
         ---------------------------------------------------------
                  /\         \                 /\            \
                  /           \                /              \
                 /             \              /                \
                /               \/           /                 \/
         ---------------------------------------------------------
              t1                t4         t5                  t8

             t1            t4            t5             t8
         +---------+   +---------+   +---------+   +---------+
     T1  |    0    |   |    t2   |   |   t4    |   |    t6   |
         +---------+   +---------+   +---------+   +---------+
     T2  |    0    |   |    t1   |   |   t3    |   |    t5   |  Packet
         +---------+   +---------+   +---------+   +---------+ Variables
     T3
     T2  |    0    |   |t4=clock   |    t2   |   |   t4    |   |t8=clock   |    t6   |  Packet
         +---------+   +---------+   +---------+   +---------+
     T4 Variables
     T3  |t1=clock |   |    t3   |   |t5=clock |   |    t7   |
         +---------+   +---------+   +---------+   +---------+
     T4                |t4=clock |                 |t8=clock |
                       +---------+                 +---------+
                                                                Peer A
         +---------+   +---------+   +---------+   +---------+
    org  |    0    |   |  T3<>0? |   |   t3    |   | T3<>t3? |
         +---------+   +---------+   +---------+   +---------+   State
    rec  |    0    |   |    t4   |   |   t4    |   |    t8   | Variables
         +---------+   +---------+   +---------+   +---------+
    xmt  |   t1    |   |  T1=t1? |   |   t5    |   | T1<>t5? |
         +---------+   +---------+   +---------+   +---------+

                        Figure 7: On-Wire Protocol
   The NTP on-wire protocol is the core mechanism to exchange time
   values between servers, peers and clients.  It is inherently
   resistant to lost or duplicate data packets.  Data integrity is
   provided by the IP and UDP checksums.  No flow-control or
   retransmission facilities are provided or necessary.  The protocol
   uses timestamps, either extracted from packet headers or struck from
   the system clock upon the arrival or departure of a packet.
   Timestamps are precision data and should be restruck in case of link
   level retransmission and corrected for the time to compute a MAC on
   transmit.

   NTP messages make use of two different communication modes, one to
   one and one to many, commonly referred to as unicast and broadcast.
   For the purposes of this document, the term broadcast is interpreted
   to mean any available one to many mechanism.  For IPv4 this equates
   to either IPv4 broadcast or IPv4 multicast.  For IPv6 this equates to
   IPv6 multicast.  For this purpose, IANA has allocated the IPv4
   multicast address 224.0.1.1 and the IPv6 multicast address ending
   :101, with prefix determined by scoping rules.

   The on-wire protocol uses four timestamps numbered T1 through T4 and
   three state variables org,
         +---------+   +---------+   +---------+   +---------+   State
    rec and xmt, as shown in  |    0    |   |    t4   |   |   t4    |   |    t8   | Variables
         +---------+   +---------+   +---------+   +---------+
    xmt  |   t1    |   |  T1=t1? |   |   t5    |   | T1<>t5? |
         +---------+   +---------+   +---------+   +---------+

                        Figure 7.  This
   figure shows the most general case where each of two peers, A and B,
   independently measure the offset and delay relative to the other.
   For purposes of illustration the individual timestamp values are
   shown in lower case with subscripts indicating the order of
   transmission and reception. 17: On-Wire Protocol
   In the figure the first packet transmitted by A containing contains only the
   transmit timestamp T3 with value t1.  B receives the packet at t2 and
   saves the origin timestamp T1 with value t1 in state variable org and
   the destination timestamp T4 with value t2 in state variable rec.  At
   this time or some time later B sends a packet to A containing the org
   and rec state variables in T1 and T2, respectively and in addition
   the transmit timestamp T3 with value t3, which is saved in the xmt
   state variable.  When this packet arrives at A the packet header
   variables T1, T2, T3 and destination timestamp T4 represent the four
   timestamps necessary to compute the offset and delay of B relative to
   A, as described later. below.

   Before the A state variables are updated, two sanity checks are
   performed in order to protect against duplicate or bogus packets.  A
   packet is a duplicate if the transmit timestamp T3 in the packet
   matches the xmt state variable.  A packet is bogus if the origin
   timestamp T1 in the packet does not match the org state variable.  In
   either of these cases the state variables are updated, but then the
   packet is discarded.

   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)+(T4-T3) 1/2 * [(T2-T1) + (T4-T3)]

   and the roundtrip round trip delay

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

   Note that the quantities within parentheses are computed from 64-bit
   unsigned timestamps and result in signed values with 63 significant
   bits plus sign.  These values can represent dates from 68 years in
   the past to 68 years in the future.  However, the offset and delay
   are computed as the sum sums and difference differences of these values, which contain
   62 significant bits and two sign bits, so can represent unambiguous
   values from 34 years in the past to 34 years in the future.  In other
   words, the time of the client must be set within 34 years of the
   server before the service is started.  This is a fundamental
   limitation with 64-bit integer arithmetic.

   In implementations where floating double arithmetic is available, the
   first-order differences can be converted to floating double and the
   second-order sums and differences computed in that arithmetic.  Since
   the second-order terms are typically very small relative to the
   timestamps themselves,
   timestamp magnitudes, there is no loss in significance, yet the
   unambiguous range is increased restored from 34 years to 68 years.

   In some scenarios where the initial frequency offset between of the client and
   server is
   relatively large and the actual propagation time small, it is
   possible that the delay computation becomes negative.  For instance,
   if the frequency difference is 100 PPM and the interval T4-T1 is 64
   s, the apparent delay is -6.4 ms.  Since negative values are
   misleading in subsequent computations, the value of del delta should be
   clamped not less than s.rho, where s.rho is the system precision defined.
   described in Section 11.1, expressed in seconds.

   The discussion above assumes the most general case where two
   symmetric peers independently measure the offsets and delays between
   them.  In the case of a stateless server, the protocol can be
   simplified.  A stateless server copies T3 and T4 from the client
   packet to T1 and T2 of the server packet and tacks on the transmit
   timestamp T3 before sending it to the client.  Additional details for
   filling in the remaining protocol fields are given in the next
   section a Section 9 and
   following sections and in Appendix A.

   A SNTP primary server implementing the on-wire protocol has no
   upstream servers except a single reference clock In principle, it is
   indistinguishable from an NTP primary server which has the mitigation
   algorithms, presumably appendix.

9.  Peer Process

   The process descriptions to mitigate between multiple reference clocks.

   Upon receiving a client request, follow include a SNTP primary server constructs and
   sends the reply packet as shown in Table 4 below.  Note that the
   dispersion field in the packet header must be calculated in the same
   way as in the NTP case.

   A SNTP client using listing of the on-wire protocol has a single server and no
   downstream clients.  It can operate with any subset important
   state variables followed by an overview of the NTP on-
   wire protocol, process operations
   implemented as routines.  Frequent reference is made to the simplest using only skeleton
   in the transmit timestamp of appendix.  The skeleton includes C-language fragments that
   describe the
   server packet functions in more detail.  It includes the parameters,
   variables and ignoring all other fields. declarations necessary for a conforming NTPv4
   implementation.  However, the many additional
   complexity to implement the full on-wire protocol is minimal variables and is
   encouraged.

8.  Peer Process routines may
   be necessary in a working implementation.

   The peer process is called upon arrival of a server or peer packet.
   It runs the on-wire protocol to determine the clock offset and roundtrip round
   trip delay and in addition computes statistics used by the system and
   poll processes.  Peer variables are instantiated in the association
   data structure when the structure is initialized and updated by
   arriving packets.  There is a peer process, poll process and
   association for each server.

   The discussion in this section covers only

9.1.  Peer Process Variables

   Figure 18, Figure 19, Figure 20 and Figure 21 summarize the variables common
   names, formula names and routines
   necessary for a conforming NTPv4 implementation.

8.1. short description of the peer variables.
   The common names and formula names are interchangeable; formula names
   are intended for equations where space is important.  Unless noted
   otherwise, all peer variables have assumed prefix p.

                 +---------+----------+-----------------------+
                 | Name    | Formula  | Description           |
                 +---------+----------+-----------------------+
                 | srcaddr | srcaddr  | source address        |
                 | srcport | srcport  | source port           |
                 | dstaddr | dstaddr  | destination address   |
                 | dstport | destport | destination port      |
                 | keyid   | keyid    | key identifier key ID |
                 +---------+----------+-----------------------+

              Figure 18: Peer Process Configuration Variables

                +-----------+------------+---------------------+
                | Name      | Formula    | Description         |
                +-----------+------------+---------------------+
                | leap      | leap       | leap indicator      |
                | version   | version    | version number      |
                | mode      | mode       | mode                |
                | stratum   | stratum    | stratum             |
                | ppoll     | ppoll      | peer poll exponent  |
                | rootdelay | delta_r    | root delay          |
                | rootdisp  | epsilon_r  | root dispersion     |
                | refid     | refid      | reference ID        |
                | reftime   | reftime    | reference timestamp |
                +-----------+------------+---------------------+

                 Figure 19: Peer Process Packet Variables

   Table 11, Table 12, Table 13, and Table 14 summarize the common
   names, formula names and a short description of each peer variable,
   all of which have prefix p.

              +---------+----------+-----------------------+

                     +------+---------+--------------------+
                     | Name | Formula | Description        |
              +---------+----------+-----------------------+
                     +------+---------+--------------------+
                     | srcaddr org  | srcaddr T1      | source address origin timestamp   |
                     | srcport rec  | srcport T2      | source port receive timestamp  |
                     | dstaddr xmt  | dstaddr T3      | destination address transmit timestamp |
                     | dstport t    | destport t       | destination port packet time        |
                     +------+---------+--------------------+

                Figure 20: Peer Process Timestamp Variables
                     +--------+---------+-----------------+
                     | keyid Name   | keyid Formula | key identifier key ID Description     |
              +---------+----------+-----------------------+

              Table 11:
                     +--------+---------+-----------------+
                     | offset | theta   | clock offset    |
                     | delay  | delta   | roundtrip delay |
                     | disp   | epsilon | dispersion      |
                     | jitter | psi     | jitter          |
                     | filter | filter  | clock filter    |
                     | tp     | t_p     | filter time     |
                     +--------+---------+-----------------+

               Figure 21: Peer Process Configuration Statistics Variables

   The following configuration variables are normally initialized when
   the association is mobilized, either from a configuration file or
   upon arrival of the first packet for an ephemeral unknown association.

   p.srcadr:

   srcaddr: IP address of the remote server or reference clock.  This
   becomes the destination IP address in packets sent from this
   association.

   p.srcport:

   srcport: UDP port number of the server or reference clock.  This
   becomes the destination port number in packets sent from this
   association.  When operating in symmetric modes (1 and 2) this field
   must contain the NTP port number PORT (123) assigned by the IANA.  In
   other modes it can contain any number consistent with local policy.

   p.dstadr:

   dstaddr: IP address of the client.  This becomes the source IP
   address in packets sent from this association.

   p.dstport:

   dstport: UDP port number of the client, ordinarily the NTP port
   number PORT (123) assigned by the IANA.  This becomes the source port
   number in packets sent from this association.

   p.keyid:

   keyid: Symmetric key ID for the 128-bit MD5 key used to generate and
   verify the MAC.  The client and server or peer can use different
   values, but they must map to the same key.

             +-----------+------------+---------------------+
             | Name      | Formula    | Description         |
             +-----------+------------+---------------------+
             | leap      | leap       | leap indicator      |
             | version   | version    | version number      |
             | mode      | mode       | mode                |
             | stratum   | stratum    | stratum             |
             | ppoll     | ppoll      | peer poll exponent  |
             | rootdelay | delta      | root delay          |
             | rootdisp  | capepsilon | root dispersion     |
             | refid     | refid      | reference ID        |
             | reftime   | reftime    | reference timestamp |
             +-----------+------------+---------------------+

                  Table 12: Peer Process Packet Variables

   The variables defined below in Figure 19 are updated from the packet header
   as each packet arrives.  They are interpreted in the same way as the as
   packet variables of the same names.  Note however, unlike the NTPv3
   design, the packet leap and stratum variables of are never reset unless the same names.

   ------------------
   |    receive     |
   ------------------
          \| /
   ------------------ no------------------
   |    format OK?  |-->| format error   |
   ------------------   ------------------
          \| /  yes
   ------------------ no------------------
   |    access OK?  |-->| access error   |
   ------------------   ------------------
          \| /  yes
   ------------------yes------------------
   |    mode = 3?   |-->| client_packet  |
   ------------------   ------------------
          \| /  no
   ------------------yes------------------
   |    auth OK?    |-->| auth error     |
   ------------------   ------------------
          \| /  yes
   ------------------
   |    match_assoc |
   ------------------

                       Figure 8: Receive Processing

   p.leap, p.version, p.mode, p.stratum, p.ppoll, p.rootdelay,
   p.rootdisp, p.refid, p.reftime
   association is reset, which happens only if the system time is
   stepped.  It is convenient for later processing to convert the NTP
   short format packet values p.rootdelay r.rootdelay and p.rootdisp r.rootdisp to floating
   doubles as peer variables.

                  +------+---------+--------------------+
                  | Name | Formula | Description        |
                  +------+---------+--------------------+
                  | t    | t       | epoch              |
                  | org  | T1      | origin timestamp   |
                  | rec  | T2      | receive timestamp  |
                  | xmt  | T3      | transmit timestamp |
                  +------+---------+--------------------+

                Table 13: Peer Process Timestamp Variables
                  +--------+---------+-----------------+
                  | Name   | Formula | Description     |
                  +--------+---------+-----------------+
                  | offset | theta   | clock offset    |
                  | delay  | del     | roundtrip delay |
                  | disp   | epsilon | dispersion      |
                  | jitter | psi     | jitter          |
                  +--------+---------+-----------------+

                Table 14: Peer Process Statistics Variables

   The p.org, p.rec, p.xmt variables represent defined in Figure 20 include the timestamps computed exchanged
   by the on-wire protocol described previously. in Section 8.  The p.offset, p.delay,
   p.disp, p.jitter variables represent the current time values and
   statistics produced by t variable is the clock filter algorithm. seconds
   counter c.t associated with these values.  The offset and
   delay are computed c.t variable is
   maintained by the on-wire protocol; the dispersion and jitter
   are calculated as clock adjust process described below.  Strictly speaking, in Section 12.  It
   counts the epoch p.t
   is not a timestamp; it records seconds since the system timer upon arrival of service was started.  The variables
   defined in Figure 21 include the
   latest packet selected statistics computed by the clock filter algorithm.

8.2.
   clock_filter() routine described in Section 10.  The tp variable is
   the seconds counter associated with these values.

9.2.  Peer Process Operations

   Figure 8

   The receive() routine in Appendix A.5.1 shows the peer process code
   flow upon the arrival of a packet.  The access() routine in
   Appendix A.5.4 implements access restrictions using an access control
   list (ACL).  There is no specific method required for access control,
   although it is recommended that implementations include such a match-and-
   mask scheme
   scheme, which is similar to many others now in widespread use.
   Format checks require correct field length and alignment, acceptable
   version number (1-4) and correct extension field syntax, if present.

   There is no specific requirement for authentication; however, if
   authentication is implemented, the symmetric key scheme described in
   Section 6
   Appendix A.2 must be included among the supported. supported schemes.  This scheme uses
   the MD5 keyed hash algorithm described in Appendix A.2.  For the most
   vulnerable applications the Autokey public key scheme described in
   [3] is recommended. [8].

   Next, the association table is searched for matching source address
   and source port using the find_assoc() routine in Appendix A.5.1.
   The
   Figure 22 is a dispatch table near where the beginning of that section is indexed by columns correspond to the
   packet mode and association mode (0 if no matching association) rows correspond to determine the dispatch code and thus the case target. association mode.  The
   significant cases are FXMT, NEWPS
   intersection of the association and NEWBC.
   ----------------- packet modes dispatches
   processing to one of the following steps.

           +------------------+---------------------------------------+
           | client_packet                  |
   -----------------
         \              Packet Mode              | /
   -----------------
           +------------------+-------+-------+-------+-------+-------+
           | copy header Association Mode |
   -----------------
         \   1   | /
   -----------------   2   | copy T1,T2   3   |
   -----------------
         \   4   | /
   -----------------   5   | T3 = clock
           +------------------+-------+-------+-------+-------+-------+
           |
   -----------------
         \ No Association 0 | /
   ----------------- yes -------------- NEWPS | copy header DSCRD | --> FXMIT | MD5 digest |-\
   -----------------     -------------- MANY  | NEWBC | no
           |
         \ Symm. Active   1 | / PROC  |
   ----------------- PROC  | DSCRD | NAK digest DSCRD | DSCRD |
   -----------------
           |
           |-----------------------------/
         \ Symm. Passive  2 | /
   ----------------- PROC  | fast_xmit() ERR   |
   -----------------
         \ DSCRD | /
   ----------------- DSCRD | xmt = T3 DSCRD |
   -----------------
         \
           | /
   ----------------- Client         3 | return DSCRD |
   -----------------

   Packet Variable <-- Variable
   x.leap <-- s.leap
   x.version <-- r.version
   x.mode <-- DSCRD | DSCRD | PROC  | DSCRD |
           | Server         4
   x.stratum <-- s.stratum
   x.poll <-- r.poll
   x.precision <-- s.precision
   x.rootdelay <-- s.rootdelay
   x.rootdisp <-- s.rootdisp
   x.refid <-- s.refid
   x.reftime <-- s.reftime
   x.org <-- r.xmt
   x.rec <-- r.dst
   x.xmt <-- clock
   x.keyid <-- r.keyid
   x.digest <-- md5 digest | DSCRD | DSCRD | DSCRD | DSCRD | DSCRD |
           | Broadcast      5 | DSCRD | DSCRD | DSCRD | DSCRD | DSCRD |
           | Bcast Client   6 | DSCRD | DSCRD | DSCRD | DSCRD | PROC  |
           +------------------+-------+-------+-------+-------+-------+

                      Figure 9: Client Packet Processing 22: Peer Dispatch Table

   DSCRD.  This is a nonfatal violation of protocol as the result of a
   programming error, long delayed packet or replayed packet.  The peer
   process discards the packet and exits.

   ERR.  This is a fatal violation of protocol as the result of a
   programming error, long delayed packet or replayed packet.  The peer
   process discards the packet, demobilizes the symmetric passive
   association and exits.

   FXMIT.  This is a client (mode 3) packet matching no association.
   The 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.  The server packet header is
   constructed as
   in Figure 9 and by the fast_xmit() routine in Appendix A.5.4. A.5.3.  The packet
   header is assembled from the receive packet and system variables as
   shown in Figure 23.  If the s.rootdelay and s.rootdisp system
   variables are stored in floating double, they must be converted to
   NTP short format first.

                   +-----------------------------------+
                   | Packet Variable -->   Variable    |
                   +-----------------------------------+
                   | r.leap        -->     p.leap      |
                   | r.mode        -->     p.mode      |
                   | r.stratum     -->     p.stratum   |
                   | r.poll        -->     p.ppoll     |
                   | r.rootdelay   -->     p.rootdelay |
                   | r.rootdisp    -->     p.rootdisp  |
                   | r.refid       -->     p.refid     |
                   | r.reftime     -->     p.reftime   |
                   | r.keyid       -->     p.keyid     |
                   +-----------------------------------+

                     Figure 23: Receive Packet Header

   Note that, if authentication fails, fails, the server returns a special
   message called a crypto-NAK.  This message includes the normal NTP
   header data shown in Figure 9, but with a MAC consisting of four
   octets of zeros.  The client MAY accept or reject the data in the
   message.  After these actions the peer process exits.

   If the destination address is a multicast address, the sender is
   operating in manycast client mode.  If the packet is valid and the
   server stratum is less than the client stratum, the server sends an
   ordinary server (mode 4) packet, but using its unicast destination
   address.  A crypto-NAK is not sent if authentication fails.  After
   these actions the peer process exits.

   MANY: This is a server returns (mode 4) packet matching no association.

   Ordinarily, this can happen only as the result of a special message called manycast server
   reply to a crypto-NAK.  This message MUST include the normal NTP header data
   shown in previously sent multicast client packet.  If the figure, but with a MAC consisting of four octets of
   zeros.  The packet is
   valid, an ordinary client MAY accept or reject (mode 3) association is mobilized and
   operation continues as if the data in association was mobilized by the message.
   configuration file.

   NEWBC.  This is a broadcast (mode 5) packet matching no association.
   The client mobilizes either a client (mode 3) or broadcast client
   (mode 6) association as shown in the mobilize() and clear() routines
   in Appendix A.2.  Then the packet() routine in Appendix A.5.1.1
   validates the packet and initializes the peer variables.

   If the implementation supports no additional security or calibration
   functions, the association mode is set to broadcast client (mode 6)
   and the peer process exits.  Implementations supporting public key
   authentication first perform the necessary steps to MAY run the Autokey or other protocol, equivalent security protocol.
   Implementations SHOULD set the association mode to 3 and run a short
   client/server exchange to determine the propagation delay,
   then delay.  Following
   the exchange the association mode is set to 6 and the peer process
   continues in listen-only (mode 6) to receive further packets. mode.  Note the distinction between a mode-6
   packet, which is reserved for the NTP monitor and control functions,
   and a mode-6 association.

   NEWPS.  This is a symmetric active (1) (mode 1) packet matching no
   association.  The client mobilizes a symmetric passive (mode 2)
   association as shown in the mobilize() and clear() routines in
   Appendix A.2.  Code flow continues to the match_assoc() fragment
   described below.  In other cases the packet matches an existing
   association and code flows to the match_assoc fragment in Figure 10.
   The packet timestamps are carefully checked to avoid invalid,
   duplicate or bogus packets, as shown in the figure.  Note that a
   crypto-NAK is considered valid only if it survives these tests.
   Next, the peer variables are copied from the packet header variables
   association as shown in Figure 11 and the packet() mobilize() routine and clear() routines
   in Appendix A.5.2.
   Implementations MUST include a number of data range checks as shown A.2.  Processing continues in Table 15 and discard the PROC section below.

   PROC.  The packet if the ranges are exceeded;
   however, the header fields MUST be copied even if errors occur, since
   they matches an existing association.  The packet
   timestamps are necessary in symmetric modes carefully checked to construct the subsequent
   poll message.

   ---------------
   | match assoc |
   ---------------
        \ | /
   --------------- yes ----------------
   | T3 = 0?     | --> | format error |
   ---------------     ----------------
        \ | / no
   --------------- yes ----------------
   | T3 = xmt?   | --> | avoid invalid, duplicate    |
   ---------------     ----------------
        \ | / no
   --------------- no  ---------------- yes
   | mode = 5?   | --> |T1 or T2 = 0? |--\
   ---------------     ----------------  |
          | yes             \ | / no     |
        \ | /<-----\  ----------------   |
          |         \-| T1 = xmt?    |   |
   ----------------   ----------------   |
   | auth = NAK?  |      no  \ | /<------/
   ----------------            |
   yes\|/     no\|/   ----------------
   --------- ------   |  org = T3    |
   |org=T3|  |auth|   |  rec = T4    |
   |rec=T4|  |err |   ----------------
   --------- ------         \ | /
     \|/              ----------------
   ---------          | return       |
   |packet |          ----------------
   ---------

                      Figure 10: Timestamp Processing
   ----------------
   | packet       |
   ----------------
        \ | /
   ----------------
   | copy header  |
   ----------------
        \ | /
   ---------------- bad ----------------
   | header?      | --> |header error  |
   ----------------     ----------------
        \ | /
   ----------------
   | reach |= 1   |
   ----------------
        \ | /
   ----------------
   | poll update  |
   ----------------
        \ | /
   ----------------------------------------
   | theta = 1/2*(T2-T1)+(T3-T4)          |
   | del = (T4-T1)-(T3-T2)                |
   | epsilon = rho_r+rho+capphi*((T4-T1)  |
   ----------------------------------------
        \ | /
   ----------------
   | clock filter |
   ----------------

   Peer Variables <-- Packet Variables
   p.leap <-- r.leap
   p.mode <-- r.mode
   p.stratum <-- r.stratum
   p.ppoll <-- r.ppoll
   p.rootdelay <-- r.rootdelay
   p.rootdisp <-- r.rootdisp
   p.refid <-- r.refid
   p.reftime <-- r.reftime bogus
   packets.  Additional checks are summarized in Figure 11: Packet Processing 24.  Note that
   all packets, including a crypto-NAK, are considered valid only if
   they survive these tests.

   +--------------------------+----------------------------------------+
   | Packet Type              | Description                            |
   +--------------------------+----------------------------------------+
   | 1 duplicate packet       | The packet is at best an old duplicate |
   |                          | or at worst a replay by a hacker.      |
   |                          | This can happen in symmetric modes if  |
   |                          | the poll intervals are uneven.         |
   | 2 bogus packet           |                                        |
   | 3 invalid                | One or more timestamp fields are       |
   |                          | invalid. This normally happens in      |
   |                          | symmetric modes when one peer sends    |
   |                          | the first packet to the other and      |
   |                          | before the other has received its      |
   |                          | first reply.                           |
   | 4 access denied          | The access controls have black         |
   | 5 authentication failure | The cryptographic message digest does  |
   |                          | not match the MAC.                     |
   | 6 unsynchronized         | The server is not synchronized to a    |
   |                          | valid source.                          |
   | 7 bad header data        | One or more header fields are invalid. |
   | 8 autokey error          | Public key cryptography has failed to  |
   |                          | authenticate the packet.               |
   | 9 crypto error           | Mismatched or missing cryptographic    |
   |                          | keys or certificates.                  |
   +--------------------------+----------------------------------------+

                       Table 15:

                      Figure 24: Packet Error Checks

   Processing continues in the packet() routine in Appendix A.5.1.1.  It
   copies the packet variables to the peer variables as shown in
   Figure 23 and the packet() routine in Appendix A.5.2">.  The
   receive() routine implements tests 1-5 in Figure 24; the packet()
   routine implements tests 6-7.  If errors are found the packet is
   discarded and the peer process exits.

   The on-wire protocol calculates the clock offset theta and round trip
   delay delta from the four most recent timestamps as described in
   Section 8.  While it is in principle possible to do all calculations
   except the first-order timestamp differences in fixed-point
   arithmetic, it is much easier to convert the first-order differences
   to floating doubles and do the remaining calculations in that
   arithmetic, and this will be assumed in the following description.

   Next, the 8-bit p.reach shift register in the poll process described later
   in Section 13 is used to determine whether the server is reachable or not and
   provide information useful to insure the server is reachable
   and the data are fresh.  The register is shifted left by one bit when
   a packet is sent and the rightmost bit is set to zero.  As valid
   packets arrive, the packet() routine sets the rightmost bit is set to one.
   If the register contains any nonzero bits, the server is considered
   reachable; otherwise, it is unreachable.  Since the peer poll
   interval might have changed since the last packet, the poll_update()
   routine in
   Appendix A.8.2 is called to re-determine the host poll interval.

   The on-wire protocol calculates the clock offset theta and roundtrip
   delay del from the four most recent timestamps as shown in Figure 7.
   While it is in principle possible to do all calculations except the
   first-order timestamp differences in fixed-point arithmetic, it is
   much easier to convert the first-order differences to floating
   doubles and do the remaining calculations in that arithmetic, and
   this will be assumed in Appendix A.5.7.2 is called to redetermine the following description. host poll
   interval.

   The dispersion statistic epsilon(t) represents the maximum error due
   to the frequency tolerance and time since the last measurement. packet was sent It
   is initialized

   epsilon(t_o)

   epsilon(t_0) = rho_r r.rho + rho +capphi(T4-T1) s.rho + PHI * (T4-T1)

   when the measurement is made at t _0. t_0 according to the seconds counter.
   Here rho_r r.rho is the peer packet precision described in the packet header r.precision Section 7.3 and rho s.rho
   is the system precision s.precision, described in Section 11.1, both expressed in
   seconds.  These terms are necessary to account for the uncertainty in
   reading the system clock in both the server and the client.

   The dispersion then grows at constant rate TOLERANCE (cappsi); PHI; in other words, at
   time t,
   epsilon(t)=epsilon(t_0)+cappsi(t-t_0). epsilon(t) = epsilon(t_0) + PHI * (t-t_0).  With the default
   value
   cappsi=15 PHI = 15 PPM, this amounts to about 1.3 s per day.  With this
   understanding, the argument t will be dropped and the dispersion
   represented simply as epsilon.  The remaining statistics are computed
   by the clock filter algorithm described in the next section.

8.3.

10.  Clock Filter Algorithm
   -----------------------
   |

   The clock filter        |
   -----------------------
            \ | /
   -----------------------
   | shift sample theta, |
   | del, epsilon, and t |
   | filter shift registr|
   -----------------------
            \ | /
   -----------------------
   | copy filter to a    |
   | temporary list. sort|
   | list by increasing  |
   | del.  Let theta_i   |
   | del_i, epsilon_i,   |
   | t_i be algorithm, part of the ith entry|
   | on peer process, is implemented
   in the sorted list. |
   -----------------------
            \ | /
   -----------------------   no
   |     t_0 > t?        |----\
   -----------------------    |
            \ | / yes         |
   -----------------------    |
   | theta = theta_0     |    |
   | del = del_0         |    |
   | epsilon             |    |
   | = sum(epsilon_i)    |    |
   |       ----------    |    |
   |        2^(i+1)      |    |
   | psi                 |    |
   | = sqrt(1/7* ...     |    |
   |    ... sum( ...     |    |
   | (theta_0-theta_i)^2 |    |
   | t = t_0             |    |
   -----------------------    |
            \ | /             |
   -----------------------    |
   | clock_select()      |    |
   -----------------------    |
            \ | /<------------/
   -----------------------
   | return              |
   -----------------------

                    Figure 12: Clock Filter Processing
   The clock filter algorithm clock_filter() routine in Appendix A.5.2.  It grooms the
   stream of on-wire data to select the samples most likely to represent the correct
   accurate time.  The algorithm produces the p.offset theta, p.delay del, p.dispersion
   epsilon, p.jitter psi, variables shown in
   Figure 21, including the offset (theta), delay (delta), dispersion
   (epsilon), jitter (psi) and time of arrival p.t t (t).  These data are used
   by the mitigation algorithms to determine the best and final offset
   used to discipline the system clock.  They are also used to determine
   the server health and whether it is suitable for synchronization.

   The
   core processing steps of this algorithm are shown in Figure 12 with
   more detail in the clock_filter() routine in Appendix A.5.3.

   The clock filter algorithm saves the most recent sample tuples
   (theta, del, delta, epsilon, t) in the filter structure, which functions
   as an 8-stage shift register register.  The tuples are saved in the order that
   packets arrive.  Here t is the system timer, packet time of arrival according to
   the seconds counter and should not be confused with the peer variable of the same name.
   tp.

   The following scheme is used to insure sufficient samples are in the register
   filter and that old stale data are discarded.  Initially, the tuples
   of all stages are set to the dummy tuple (0,MAXDISP, (0, MAXDISP, MAXDISP, 0).
   As valid packets arrive, the (theta,
   del, epsilon, t) tuples are shifted into the register filter causing
   old
   samples tuples to be discarded, so eventually only valid samples tuples remain.
   If the three low order bits of the reach register are zero,
   indicating three poll intervals have expired with no valid packets
   received, the poll process calls the clock filter algorithm with the a
   dummy tuple just as if the tuple had arrived from the network.  If
   this persists for eight poll intervals, the register returns to the
   initial condition.

   In the next step the shift register stages are copied to a temporary
   list and the list sorted by increasing del. delta.  Let j i index the stages
   starting with the lowest del. delta.  If the sample first tuple epoch t_0 is not
   later than the last valid sample epoch p.t, the routine exits without
   affecting the current peer variables.  Otherwise, let epsilon_j epsilon_i be
   the dispersion of the jth ith entry, then
                     i=n-1
                     ---     epsilon_i
      capepsilon =    \     ----------
                      /        (i+1)
                     ---     2
                     i=0

   is the peer dispersion p.disp.  Note the overload of epsilon, whether
   input to the clock filter or output, the meaning should be clear from
   context.

   The observer should note (a) if all stages contain the dummy tuple
   with dispersion MAXDISP, the computed dispersion is a little less
   than 16 s, (b) each time a valid tuple is shifted into the register,
   the dispersion drops by a little less than half, depending on the
   valid tuples dispersion, (c) after the fourth valid packet the
   dispersion is usually a little less than 1 s, which is the assumed
   value of the MAXDIST parameter used by the selection algorithm to
   determine whether the peer variables are acceptable or not.

   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                      |     |
                 |            +-----                 -----+     |
                 |                                              |
                 +-----                                    -----+

   where n is the number of valid tuples in the register. filter (n > 1).  In
   order to insure consistency and avoid divide exceptions in other
   computations, the psi is bounded from below by the system precision rho
   s.rho expressed in seconds.  While not in general considered a major
   factor in ranking server quality, jitter is a valuable indicator of
   fundamental timekeeping performance and network congestion state.  Of
   particular importance to the mitigation algorithms is the peer
   synchronization distance, which is computed from the root delay and
   root
   dispersion.  The root delay is

   del ' = delta_r + del

   and the root dispersion is

   epsilon '

   lambda = capepsilon_r + epsilon (delta / 2) + psi epsilon.

   Note that epsilon and therefore lambda increase at rate capphi. PHI.  The peer
   synchronization distance
   lambda is defined not a state variable, since lambda = (del ' / 2) + epsilon

   and is recalculated as necessary.  The lambda at each
   use.  It is a component of the root synchronization distance caplambda used by
   the mitigation algorithms as a metric to evaluate the quality of time
   available from each server.  Note that there

   It is no state important to note that, unlike NTPv3, NTPv4 associations do not
   show a timeout condition by setting the stratum peer variable for lambda, as it
   depends on to 16.
   In NTPv4 lambda increases with time, so eventually the time since
   synchronization distance exceeds the last update.

9. distance threshold MAXDIST, in
   which case the association is considered unfit for synchronization.

11.  System Process

   As each new sample (theta, delta, epsilon, jitter, t) is produced by
   the clock filter algorithm, the sample is processed all peer processes are scanned by the
   mitigation algorithms consisting of the selection, clustering, combining cluster, combine
   and clock discipline algorithms in the system process.  The selection
   algorithm scans all associations and casts off the falsetickers,
   which have demonstrably incorrect time, leaving the truechimers as
   result.  In a series of rounds the clustering cluster algorithm discards the
   association statistically furthest from the centroid until a
   specified minimum number of survivors remain.  The combining combine algorithm
   produces the best and final offset statistics on a weighted average basis and selects one of
   the associations as the system peer providing the best statistics for
   performance evaluation. basis.
   The final offset is passed to the clock discipline algorithm to steer
   the system clock to the correct time.

   The cluster algorithm selects one of the survivors as the system
   peer.  The associated statistics (theta, delta, epsilon, jitter, t) associated with the system
   peer
   are used to construct the system variables inherited by dependent
   servers and clients and made available to other applications running
   on the same machine.

   The discussion in following sections covers the basic variables and
   routines necessary for a conforming NTPv4 implementation.  Additional
   implementation details are in Appendix A.  An interface that might be
   considered in a formal specification is represented by the function
   prototypes in Appendix A.1.6.

9.1.

11.1.  System Process Variables

   The variables and parameters associated with the system process are
   summarized in Table 16, which gives

   Figure 27 summarizes the variable name, common names, formula name names and a short description.
   description of each system variable.  Unless noted otherwise, all
   variables have assumed prefix s.

             +-----------+------------+---------------------+

                +-----------+------------+------------------------+
                | Name      | Formula    | Description            |
             +-----------+------------+---------------------+
                +-----------+------------+------------------------+
                | t         | t          | epoch update time            |
                | p         | p          | system peer identifier |
                | leap      | leap       | leap indicator         |
                | stratum   | stratum    | stratum                |
                | precision | rho        | precision              |
                | p         | p          | system peer pointer |
             | offset    | captheta THETA      | combined offset        |
                | jitter    | varsigma PSI        | combined jitter        |
                | rootdelay | capdelta DELTA      | root delay             |
                | rootdisp  | capepsilon EPSILON    | root dispersion        |
                | refid     | refid      | reference ID           |
                | reftime   | reftime    | reference time         |
                | NMIN      | 3          | minimum survivors      |
                | CMIN      | 1          | minimum candidates     |
             +-----------+------------+---------------------+

             Table 16:
                +-----------+------------+------------------------+

                    Figure 27: System Process Variables and Parameters

   All

   Except for the t, p, offset and jitter variables except s.t and s.p the NMIN and
   CMIN constants, the variables have the same format and interpretation
   as the peer variables of the same name.  The remaining
   variables NMIN and CMIN parameters
   are defined below.

   s.t: Integer representing used by the value of selection and cluster algorithms described in the system timer
   next section.

   The t variable is the seconds counter at the last
   update.

   s.p: System update determined
   by the clock_update() routine in Appendix A.5.5.4.  The p variable is
   the system peer association pointer.

   s.precision: 8-bit signed integer representing identifier determined by the cluster() routine in
   Section 11.2.2.  The precision variable has the same format as the
   packet variable of the
   system same name.  The precision is defined as the
   larger of the resolution and time to read the clock, in log2 seconds.

   s.offset: Offset computed by units.
   For instance, the combining algorithm.

   s.jitter: Jitter computed by precision of a mains-frequency clock incrementing
   at 60 Hz is 16 ms, even when the cluster and combining algorithms. system clock hardware representation
   is to the nanosecond.

   The offset and jitter variables defined below are updated from determined by the system peer process
   as described later.  They are interpreted combine()
   routine in Section 11.2.3.  These values represent the same way as the as
   the peer variables of best and final
   offset and jitter used to discipline the same names.

   s.leap, s.stratum, s.rootdelay, s.rootdisp, s.refid, s.reftime system clock.  Initially,
   all variables are cleared to zero, then the s.leap leap is set to 3
   (unsynchronized) and s.stratum stratum is set to MAXSTRAT (16).  The
   remaining statistics are determined as described below.

9.2.  Remember that
   MAXSTRAT is mapped to zero in the transmitted packet.

11.2.  System Process Operations

   The

   Figure 28 summarizes the system process implements operations performed by the selection, clustering, combining
   and clock discipline algorithms.  The
   clock_select() routine in
   Figure 15 includes the routine.  The selection algorithm of described in
   Section 9.2.1 that 11.2.1 produces a majority clique of truechimers presumed correct
   candidates (truechimers) based on agreement principles.  The clustering cluster
   algorithm of described in Section 9.2.2 11.2.2 discards the
   outliers of the clique outlyers to produce
   the survivors used by the combining most accurate survivors.  The combine algorithm described in
   Section 9.2.3 , which in turn 11.2.3 provides the best and final offset for the clock
   discipline algorithm described in Section 9.2.4. Appendix A.5.5.6.  If the selection
   algorithm cannot produce a majority clique, or if the
   clustering algorithm it cannot produce
   at least CMIN survivors, the system process terminates with no further processing. exits without
   disciplining the system clock.  If successful, the clustering cluster algorithm
   selects the statistically best candidate as the system peer and its
   variables are inherited as the system variables.  The selection and clustering algorithms are described
   below separately, but combined in the code skeleton.

                            -------------------------

                          +-----------------+
                          | clock_select()  |
                            -------------------------
                                     \|/
   -----------------------------------|---------------
   |              ----------- ---------------------- |
   |          /---|
                          +-----------------+
   ................................|...........
   .                               V          .
   .      yes +---------+ +-----------------+ .
   .       +--| accept? | | scan candidates | .
   .       |  +---------+ |                 |   ----------- |                    | |
   |          | yes       no| |                    | | .
   .       V        no |     -----------  |                 | .
   .  +---------+      |  |                 | .
   .  | add peer|      |  |                 | |
   |     -----------      | .
   .  +----------      |  |                 | .
   .       |           V  |          \|/                 | .
   .       +---------->-->|                 | .
   .                      |                 |          \-------->----->| .
   . Selection Algorithm  +-----------------+ .
   .................................|..........
                                    V
                       no +-------------------+
            +-------------|     survivors?    |
            |             +-------------------+
            |                       | yes
            |                       V
            |             +-------------------+
            |  selection algorithm     ----------------------             | Cluster Algorithm |                                  \|/
            |
   ------------------------------------|--------------
                  no          -----------------------
               /--------------| survivors?             +-------------------+
            |                       |              -----------------------
            |                      \|/                       V
            V         yes
               |              -----------------------
               |              | clustering algorithm|
               |              -----------------------
               |                      \|/
               |              -----------------------
               |<---------yes-| +-------------------+
            |<------------|     n < CMIN?     |
              \|/             -----------------------
   -------------------------          \|/
            |             +-------------------+
            V                       |
     +-----------------+            V no
     |   s.p = NULL    |  -----------------------
   -------------------------  +-------------------+
     +-----------------+  |   s.p = vo.p      |
              \|/             -----------------------
   -------------------------          \|/
            |             +-------------------+
            V                       |
     +-----------------+            V
     | return (UNSYNC) |  -----------------------
   -------------------------  +-------------------+
     +-----------------+  |   return (SYNC)   |
                              -----------------------
                          +-------------------+

                     Figure 15: 28: clock_select() routine

9.2.1. Routine

11.2.1.  Selection Algorithm

   Note that the selection and cluster algorithms are described
   separately, but combined in the code skeleton.  The selection
   algorithm operates to find the an intersection interval containing a
   majority clique of truechimers using Byzantine agreement principles
   originally proposed by Marzullo [7], [9], but modified to improve
   accuracy.  An overview of the algorithm is
   listed given below and in the
   first half of the clock_select() routine in Appendix A.6.1. A.5.5.1.

   First, those servers which are unusable according to the rules of the
   protocol are detected and discarded by the accept() routine in Figure 16 and
   Appendix A.6.3. A.5.5.3.  Next, a set of tuples {p, (p, type, edge} edge) is generated
   for the remaining servers, where candidates.  Here, p is an the association pointer, type identifier
   and edge type identifies the upper (+1), middle (0) and lower (-1) endpoint
   endpoints of a correctness interval [theta-
   lambda,theta+lambda], centered on theta for that
   candidate.  This results in three tuples, lowpoint (p, -1, theta -
   lambda), midpoint (p, 0, theta) and highpoint (p, +1, theta +
   lambda), where lambda is the root distance. synchronization distance calculated
   on each use by the rootdist() routine in Appendix A.5.1.1.  The steps
   of the algorithm are:

   1.  For each of m associations, construct a correctness interval
       [(theta-rootdist()),(theta+rootdist())]. place three tuples as defined above
   on the candidate list.

   2.  Select  Sort the tuples on the list by the edge component.  Order the
   lowpoint, midpoint and highpoint of these intervals.
       Sort of these values in a list intervals from lowest to
   highest.  Set the number of falsetickers f=0. f = 0.

   3.  Set the number of midpoints d=0. d = 0.  Set c=0. c = 0.  Scan from lowest
   endpoint to highest.  Add one to c for every lowpoint, subtract one
   for every highpoint, add one to d for every midpoint.  If
       c>=m-f, c >= m - f,
   stop; set l=current lowpoint l = current lowpoint.

   4.  Set c=0. c = 0.  Scan from highest endpoint to lowest.  Add one to c
   for every highpoint, subtract one for every lowpoint, add one to d
   for every midpoint.  If c>=m-f, c >= m - f, stop; set u=current u = current highpoint.

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

       A.

   5A. Success: the intersection interval is [l, u].

       B.

   5B. Add one to f.  Is f < (m / 2)?  If yes, then go to step 3
           again.  If no, then go to step 6.

   6.  Failure; a majority clique could not be found.  Stop algorithm.

   The tuples are placed on a list and sorted by edge.  The list is
   processed from the lowest to the highest, then from highest to lowest
   as described in detail in [8].  The algorithm starts with the
   assumption that there are no falsetickers (f=0) and attempts to find
   a nonempty intersection interval containing the midpoints of all
   correct servers, i.e., truechimers.  If a nonempty interval cannot be
   found, it increases the number of assumed falsetickers by one and
   tries again.  If a nonempty interval is found and the number of
   falsetickers is less than the number of truechimers, a majority
   clique has been found and the midpoints (offsets) represent the
   survivors available for the clustering algorithm.  Otherwise, there
   are no suitable candidates to synchronize the system clock.

   --------------------
   | accept()         |
   --------------------
           \|/
   --------------------
   | leap = 11?       |
   | stratum >=       |--any yes---\ server not
   | MAXSTRAT?        |            | synchronized
   --------------------            |
           \|/ all no              |
   --------------------            |
   | reach = 0?       |---yes----->| server not
   --------------------            | reachable
           \|/ no                  |
   --------------------            |
   | root_dist() >=   |            |
   | MAXDIST?         |---yes----->| root distance
   --------------------            | exceeded
           \|/ no                  |
   --------------------            |
   | refid = addr?    |---yes----->| server/client
   --------------------            | sync loop
           \|/ no                  |
   --------------------            |
   | return (YES)     | -----------------------
   -------------------- | return (NO)         |
                        -----------------------

                        Figure 16: accept() routine

9.2.2.  Clustering Algorithm

   The members of the f < (m / 2)?  If yes, then go to step 3 again.
   If no, then go to step 6.

   6.  Failure; a majority clique could not be found.  There are placed on no
   suitable candidates to discipline the survivor list,
   and sorted first by stratum, then by root distance lambda. system clock.

   The
   sorted list is processed by the clustering algorithm below and the
   second half of the clock_select() algorithm is described in detail in Appendix A.6.1.

      1.  Let (theta, phi, Lambda) represent a candidate peer A.5.5.1.  Note that
   it starts with
      offset theta, jitter psi the assumption that there are no falsetickers (f = 0)
   and attempts to find a weight factor
      Lambda=stratum*MAXDIST+rootdist().

      2.  Sort nonempty intersection interval containing the candidates by increasing Lambda.  Let n
   midpoints of all correct servers, i.e., truechimers.  If a nonempty
   interval cannot be found, it increases the number of candidates assumed
   falsetickers by one and tries again.  If a nonempty interval is found
   and NMIN the minimum number of survivors.

      3.  For each candidate compute falsetickers is less than the selection jitter psi_S (RMS
      peer offset differences between this number of
   truechimers, a majority clique has been found and all other candidates).

      4.  Select psi_max as the candidate with maximum psi_S.

      5.  Select psi_min as midpoint of
   each truechimer (theta) represents the candidate with minimum psi_S.

      6.  Is psi_max < psi_min or n <= NMIN?  If yes, go to step 6y.  If
      no, go candidates available to step 6n.

      6y.  Done.  The remaining cluster survivors are correct.  The
      survivors are in the v. structure sorted by Lambda.

      6n.  Delete the outlyer candidate with psi_max; reduce n by one,
      and go back to step 3.

   It operates in
   cluster algorithm.

   If a series of rounds where each round discards majority clique is not found, or if the
   furthest statistical outlier until a specified minimum number of
   survivors NMIN (3) are left or until no further improvement truechimers is
   possible.  In each round let n be
   less than CMIN, there are insufficient candidates to discipline the
   system clock.  CMIN defines the minimum number of survivors and s index
   the survivor list.  Assume psi_p is servers consistent
   with the peer jitter of correctness requirements.  Suspicious operators would set
   CMIN to insure multiple redundant servers are available for the s
   survivor.  Compute
              +-----                                    -----+
              |                                        1/2   |
              |            +-----                 -----+     |
              |            |  n-1                      |     |
              |            |  ---                      |     |
              |    1       |  \                     2  |     |
   psi_s  =   | -------- * |  /    (theta_s-theta_j)   |     |
              |  (n-1)     |  ---                      |     |
              |            |  j=1                      |     |
              |            +-----                 -----+     |
              |                                              |
              +-----                                    -----+

   as
   algorithms to mitigate properly.  However, for historic reasons the selection jitter.  Then choose psi_max=max(psi) and
   psi_min=min(psi).  If psi_max<psi_min or n<NMIN, no further reduction
   in selection jitter
   default value for CMIN is possible, so the algorithm terminates and one.

11.2.2.  Cluster Algorithm

   The candidates of the
   remaining survivors majority clique are processed by the combining algorithm.
   Otherwise, placed on the algorithm case off survivor list
   in the psi_max survivor, reduces n by
   one form of tuples (p, theta_p, psi_p, lambda_p), where p is an
   association identifier, theta_p, psi_p, and makes another round.

9.2.3.  Combining Algorithm
   ---------------------
   | clock_combine()   |
   ---------------------
           \|/
   ---------------------
   | y = z = w = 0     |
   ---------------------
           \|/
   ---------------------
   | scan cluster      |   ------------------
   | survivors         |-->| x = rootdist() |
   |                   |   ------------------
   |                   |          \|/
   |                   |   ------------------
   |                   |<--| y+= 1/x        |
   |                   |   | z+=theta_i/x   |
   |                   |   | w+=(theta_i -  |
   |                   |   | theta_o)^2     |
   ---------------------   ------------------
           \|/ done
   -----------------------
   | captheta = z/y      |
   | vartheta = sqrt(w/y)|
   -----------------------
           \|/
   -----------------------
   | return              |
   -----------------------

   Variable/Process/Description
   captheta/system/combined clock offset
   vartheta_p/system/combined stratum_p the current
   offset, jitter
   theta_0/survivor list/first survivor offset
   theta_i/survivor list/ith and stratum of association p, respectively, and
   lambda_p is a merit factor equal to stratum_p * MAXDIST + lambda,
   where lambda is the root synchronization distance for association p.
   The list is processed by the cluster algorithm below and the second
   half of the clock_select() algorithm in Appendix A.5.5.1.

   1.  Let (p, theta_p, psi_p, lambda_p) represent a survivor offset
   x,y,z,w/ /temporaries

                    Figure 18: clock_combine() routine
                         --------------------
                         | clock_update()   |
                         --------------------
                                 \|/
                         --------------------
            /----no----->| p.t > s.t        |
            |            --------------------
            |                    \|/ yes
            |            --------------------
            |            | s.t = p.t        |
            |            --------------------
            |                    \|/
            |            --------------------
            |            | local_clock()    |
            |            --------------------
            |                    \|/
            |<--------------------+-----------------\
            | panic\|/            | adj        step\|/
            | -------------       |       -------------------
            | | panic exit|       |       | clear all assoc.|
            | -------------       |       -------------------
            |             -----------------        \|/
            |             |*update system | -----------------
            | candidate.

   2.  Sort the candidates by increasing lambda_p.  Let n be the number
   of candidates and NMIN the minimum required number of survivors.

   3.  For each candidate compute the selection jitter psi_s:
                                               1/2
                    +-----                 -----+
                    | variables  n-1                      |
                    | leap = 3  ---                      |
               1    |             -----------------  \                     2  | quamtum
     psi_s = ---- * |  /  (theta_s - theta_j)   |                    \|/        | MAXSTRAT      |
            |
              n-1   |         -----------------
            \---------------------+----------------/  ---                      |
                          ---------------
                    | return  j=1                      |
                          ---------------

   System Variables <-- System Peer Variables
   leap <-- leap
   stratum <-- stratum + 1
   refid <-- refid
   reftime <-- reftime
   capdelta <-- capdelta_r + del
   capepsilon <-- capepsilon_r+epsilon+cappsi*mu+psi+|captheta|
   * update system variables

                     Figure 19: clock_update() routine

   The remaining survivors are processed by the clock_combine() routine
   in Figure 18 and Appendix A.6.5 to produce
                    +-----                 -----+

   4.  Select psi_max as the best and final data
   for candidate with maximum psi_s.

   5.  Select psi_min as the clock discipline algorithm. candidate with minimum psi_p.

   6.  Is psi_max < psi_min or n <= NMIN?  If yes, follow step 6A;
   otherwise, follow step 6B.

   6A. Done.  The routine processes the peer
   offset theta and jitter psi to produce remaining candidates on the system offset captheta and
   system peer jitter vartheta_p, where each server statistic is
   weighted by survivor list are ranked
   in the reciprocal order of the root distance and the result
   normalized. preference.  The system peer jitter vartheta_p is a component of first entry on the list represents
   the system jitter described later.

   The system statistics peer; its variables are passed used later to update the clock_update() routine in
   Figure 19 and Appendix A.6.4.  If there is only one survivor, system
   variables.

   6B. Delete the
   offset passed outlyer candidate with psi_max; reduce n by one and go
   back to the clock discipline step 3.

   The algorithm is captheta=theta and
   the system peer jitter is vartheta=psi.  Otherwise, operates in a series of rounds where each round
   discards the statistical outlyer with maximum selection jitter vartheta_s psi_s.
   However, if psi_s is computed as in (8), where theta_0 represents the
   offset of less than the system minimum peer and j ranges over the survivors.
   Peer Variables         Client        System Variables
   ----------------                     -----------------
   | theta = 1/2* |-------------------->| captheta =    |
   | [(T2 - T1)+  |                     | (combine      |
   | (T3 - T4)]   |                     | (theta_j))    |
   ----------------                     -----------------
   | del = [(T4 - |--sum--------------->| capdelta=     |
   | T1) - (T3 -  |  /|\                | capdelta_r +  |
   | T2)]         |   |                 | del           |
   ----------------   |                 -----------------
   | epsilon =    |   |                 | capepsilon =  |
   |              |   |                 |capepsilon_r + |
   | rho_r + rho +|   |                 | epsilon +     |
   | captheta*(   |   |                 | vartheta +    |
   | T4 - T1)     |------------sum----->| absolutevalue(|
   ----------------   |        /|\      | theta)        |
   | psi =        |   |         |       -----------------
   | sqrt((1/n)-1)*|  |         |       | psi_s =       |
   | (sum(theta_0)|   |         |       | sqrt(1/(m-1)* |
   | -theta_i)^2))|---|---\     |       | sum(theta_0-  |
   ----------------   |   |     |       | theta_j)^2)   |
         /|\          |   |     |       -----------------
          |           |   |     |             \|/
          |           |   \------------------>sum
    server|           |         |              |
   ----------------   |         |             \|/
   |    rho_r     |   |         |              |
   ----------------   |         |       -----------------
   |  capdelta_r  |>--/         |       | vartheta =    |
   ----------------             |       | sqrt(         |
   | capepsilon_r |>------------/       | (vartheta_p)^2|
   ----------------                     | +             |
                                        | (vartheta_s)^2|
                                        -----------------

                  Figure 20: System Variables Processing jitter psi_p, no
   improvement is possible by discarding outlyers.  This and the minimum
   number of survivors represent the terminating conditions of the
   algorithm.  Upon termination, the final value of psi_max is saved as
   the system selection jitter PSI_s for use later.

11.2.3.  Combine Algorithm

   The remaining survivors are processed by the clock_combine() routine
   in Appendix A.5.5.5 to produce the best and final data for the clock
   discipline algorithm.  The clock_combine() routine processes peer
   offset and jitter statistics to produce the combined system offset
   THETA and system peer jitter PSI_p, where each server statistic is
   weighted by the reciprocal of the root synchronization distance and
   the result normalized.

   The combined THETA is passed to the clock_update() routine in
   Appendix A.5.5.4.  The first survivor candidate on the survivor list is selected
   nominated as the system peer with identifier p.  The system peer
   jitter PSI_p is a component of the system jitter PSI.  It is used
   along with the selection jitter PSI_s to produce the system jitter:

   PSI = [(PSI_s)^2 + (PSI_p)^2]

   Each time an update is received from the system peer, here represented by the statistics (theta, del, epsilon, psi).
   clock_update() routine in Appendix A.5.5.4 is called.  By rule, an
   update is discarded if its time of arrival p.t is not strictly later
   than the last update used s.t.  Let mu=p.t-s.t be the
   time since the last update or update interval.  If the update
   interval is less than or equal to zero, the update is discarded.
   Otherwise, the system variables are updated from the system peer
   variables as shown in Figure 19.  Note that s.stratum is set to
   p.stratum plus one.  The arrows labeled labels IGNOR, PANIC, ADJ and STEP
   refer to return codes from the local_clock() routine described in the
   next section.

   IGNORE means the update has been ignored as an outlier. outlyer.  PANIC means
   the offset is greater than the panic threshold PANICT (1000 s) and
   SHOULD cause the program to exit with a diagnostic message to the
   system log.  STEP means the offset is less than the panic threshold,
   but greater than the step threshold STEPT (125 ms).  Since this means
   all peer data have been invalidated, all associations SHOULD MUST be reset
   and the client begins as at initial start.

   ADJ means the offset is less than the step threshold and thus a valid update for the local_clock()
   routine described later.
   update.  In this case the system variables are updated from the peer
   variables as shown in Figure 19. 30.

                  +-------------------------------------------+
                  | System Variable <-- System Peer Variable  |        |
                  +-------------------------------------------+
                  | s.leap      <-- p.leap                    |
                  | s.stratum   <-- p.stratum + 1             |
                  | s.offset    <-- THETA                     |
                  | s.jitter    <-- PSI                       |
                  | s.rootdelay <-- p.delta_r + delta         |
                  | 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 30: System Variables Update

   There is one exception an important detail not shown.  The dispersion increment
   (p.epsilon + p.psi + PHI * (s.t - p.t) + |THETA|) is bounded from
   below by MINDISP.  In subnets with very fast processors and networks
   and very small dispersion and delay and dispersion this forces a monotone-definite
   increase in capepsilon, s.rootdisp (EPSILON), which avoids loops between peers
   operating at the same stratum.

   Figure 20 shows how the error budget grows from the packet variables,
   on-wire protocol and system peer process to produce the

   The system variables that are passed available to dependent applications and clients. application programs
   as nominal performance statistics.  The system jitter is defined

   vartheta = sqrt((vartheta_p)^2+(vartheta_s)^2)

   where vartheta_s offset THETA is the selection jitter
   clock offset relative to the system peer. available synchronization sources.  The
   system jitter PSI is passed to dependent applications programs as an estimate of the
   nominal error statistic. in determining this
   value, elsewhere called the expected error.  The root delay capdelta and root dispersion
   capepsilon statistics are relative to the primary server reference
   clock and thus inherited by each server along the path.  The system
   synchronization distance is defined

   caplambda = capdelta/2 + capepsilon

   which DELTA is passed to dependent application programs as
   the maximum
   error statistic.

9.2.4.  Clock Discipline Algorithm
                        ---------
             theta_r + |         \        +----------------+
         NTP --------->|  Phase   \  V_d  |                |  V_s
             theta_c - | Detector  ------>|  Clock Filter  |-----+
             +-------->|          /       |                |     |
             |         |         /        +----------------+     |
             |          ---------                                |
             |                                                   |
           -----                                                 |
          /     \                                                |
          | VFO |                                                |
          \     /                                                |
           -----    +-------------------------------------+      |
             ^      |            Loop Filter              |      |
             |      |                                     |      |
             |      | +---------+   x  +-------------+    |      |
             | V_c  | |         |<-----|             |    |      |
             +------|-|  Clock  |   y  | Phase/Freq  |<---|------+
                    | | Adjust  |<-----| Prediction  |    |
                    | |         |      |             |    |
                    | +---------+      +-------------+    |
                    |                                     |
                    +-------------------------------------+

                 Figure 21: total round trip delay relative to the primary server.  The root
   dispersion EPSILON is the dispersion accumulated over the network
   from the primary server.  Finally, the root synchronization distance
   is defined

   LAMBDA = EPSILON + DELTA / 2,

   which represents the maximum error due all causes and is designated
   the root synchronization distance.

11.3.  Clock Discipline Feedback Loop Algorithm

   The NTPv4 clock discipline algorithm, shortened to discipline in the
   following, functions as a combination of two philosophically quite
   different feedback control systems.  In a phase-locked loop (PLL)
   design, periodic phase updates at update intervals m mu seconds are
   used directly to minimize the time error and indirectly the frequency
   error.  In a frequency-locked loop (FLL) design, periodic frequency
   updates at intervals mu are used directly to minimize the frequency
   error and indirectly the time error.  As shown in [8], [5], a PLL usually
   works better when network jitter dominates, while a FLL works better
   when oscillator wander dominates.  This section contains an outline
   of how the NTPv4 design works.  An in-depth discussion of the design
   principles is provided in [8], [5], which also includes a performance
   analysis.

   The clock discipline and clock adjust processes interact with the
   other algorithms in NTPv4.  The output of the combining algorithm
   represents the best estimate of the system clock offset relative to
   the server ensemble.  The discipline adjusts the frequency of the VFO
   to minimize this offset.  Finally, the timestamps of each server are
   compared to the timestamps derived from the VFO in order to calculate
   the server offsets and close the feedback loop.

   The discipline is implemented as the feedback control system shown in
   Figure 21. 31.  The variable theta_r represents the combining combine algorithm
   offset (reference phase) and theta_c the VFO offset (control phase).
   Each update produces a signal V_d representing the instantaneous
   phase difference theta_r - theta_c.  The clock filter for each server
   functions as a tapped delay line, with the output taken at the tap
   selected by the clock filter algorithm.  The selection, clustering cluster and combining
   combine algorithms combine the data from multiple filters to produce
   the signal V_s.  The loop filter, with impulse response F(t),
   produces the signal V_c which controls the VFO frequency omega_c and
   thus its the integral of the phase theta_c=integral(omega_c,dt) theta_c which closes the loop.  The
   V_c signal is generated by the clock adjust process in Section 9.3.  The characteristic behavior of this model, which is
   determined by F(t) and the various gain factors given in
   Appendix A.6.6.

   The transient behavior of the PLL/FLL feedback loop is determined by
   the impulse response of the loop filter F(t). 12.
   The loop filter shown detailed equations that implement these functions are best
   presented in Figure 22 predicts a phase adjustment x as a function of Vs.  The
   PLL predicts a frequency adjustment yFLL as an integral of Vs*mu with
   repsect to t, while the FLL predicts an adjustment yPLL as a function routines of Vs /mu.  The two adjustments are combined to correct the frequency
   y as shown in Figure 22.  The x Appendix A.5.5.6 and y are then used by the
   clock_adjust() routine to control the Appendix A.5.6.1.

                theta_r + +---------\        +----------------+
            NTP --------->|  Phase   \  V_d  |                | V_s
                theta_c - | Detector  ------>|  Clock Filter  |----+
                +-------->|          /       |                |    |
                |         +---------/        +----------------+    |
                |                                                  |
              -----                                                |
             /     \                                               |
             | VFO frequency.  The detailed
   equations that implement these functions are best presented in the
   routines of Appendix A.6.6 and Appendix A.7.1. |                                               |
             \     /                                               |
              -----    .......................................     |
                ^      .            Loop Filter              .     |
                |      . +---------+   x <------(Phase Correction)<--.  +-------------+    .     |
                           y_FLL
                |
                            .-(FLL Predict)<-------+<--V_s V_c  . |         |<-----|             |    .     |
                           \|/
                +------.-|  Clock  |   y <--(Sum)  |
                            ^ Phase/Freq  |<---------+
                       . | Adjust  |<-----| Prediction  |    .
                       . |         |      |
                            '-(PLL Predict)<-------'
                           y_PLL             |    .
                       . +---------+      +-------------+    .
                       .......................................

                 Figure 22: 31: Clock Discipline Feedback Loop Filter

   Ordinarily, the pseudo-linear feedback loop described above operates
   to discipline the system clock.  However, there are cases where a
   nonlinear algorithm offers considerable improvement.  One case is
   when the discipline starts without knowledge of the intrinsic clock
   frequency.  The pseudo-linear loop takes several hours to develop an
   accurate measurement and during most of that time the poll interval
   cannot be increased.  The nonlinear loop described below does this in
   15 minutes.  Another case is when occasional bursts of large jitter
   are present due to congested network links.  The state machine
   described below resists error bursts lasting less than 15 minutes.

   The remainder of this section describes how the discipline works.
   Table 17

   Figure 32 contains a summary of the variables and parameters
   including the program variables (lower case) or parameters (upper case) name,
   formula name and short description.  Unless noted
   otherwisse, otherwise, all
   variables have assumed prefix c.  The variables c.t,
   c.tc, c.state, t, tc, state, hyster
   and c.count count are integers; the memainder remaining variables are floating doubles.
   The function of each will be explained in the algorithm descriptions
   below.

             +--------+------------+-------------------------+

                +--------+------------+--------------------------+
                | Name   | Formula    | Description              |
             +--------+------------+-------------------------+
                +--------+------------+--------------------------+
                | t      | timer      | seconds counter          |
                | offset | captheta theta      | combined offset          |
                | resid  | captheta_r theta_r    | residual offset          |
                | freq   | phi        | clock frequency          |
                | jitter | psi        | clock offset jitter      |
                | wander | cappsi omega      | clock frequency wander   |
                | tc     | tau        | time constant(log2)     |
             | state  | state      | state                   |
             | adj    | adj        | frequency adjustment    |
             | count  | count      | hysteresis counter      |
             | STEPT  | 125        | step threshold (.125 s) |
             | WATCH  | 900        | stepout thresh(s)       |
             | PANICT | 1000       | panic threshold(1000 s) |
             | LIMIT  | 30         | hysteresis limit        |
             | PGATE  | 4          | hysteresis gate         |
             | TC     | 16         | time constant scale     |
             | AVG    | 8          | averaging constant      |
             +--------+------------+-------------------------+

            Table 17: Clock Discipline Variables And Parameters
   =====================================================================
   | State |  captheta < STEP  | captheta > STEP   |    Comments       |
   ---------------------------------------------------------------------
   | NSET  | > FREQ; adjust    | > FREQ; step      | no frequency      |
   |       | time              | time              | file              |
   ---------------------------------------------------------------------
   | FSET  | > SYNC; adjust    | > SYNC; step      | frequency file    |
   |       | time              | time              |                   |
   ---------------------------------------------------------------------
   | SPIK  | > SYNC; adjust    | if (<900 s)>SPIK  | outlier detected  |
   | tau        | freq, adjust time constant (log2)     | else SYNC; step
                | state  | state      | state                    |
                | freq; step time adj    | adj        |
   --------------------------------------------------------------------- frequency adjustment     | FREQ
                | if (<900 s)> FREQ hyster | if (<900 s)>FREQ hyster     | initial frequency hysteresis counter       |
                | STEPT  | else >SYNC; step 125        | else >SYNC; step threshold (.125 s)  |
                | WATCH  | 900        | freq, adjust time stepout thresh(s)        | freq, adjust time
                | PANICT |
   --------------------------------------------------------------------- 1000       | SYNC panic threshold (1000 s) | >SYNC; adjust freq| if (<900 s)>SPIK
                | normal operation LIMIT  | 30         | hysteresis limit         | adjust time
                | else >SYNC; step PGATE  | 4          | hysteresis gate          |
                | TC     | 16         | freq; step time constant scale      |
                | AVG    | 8          | averaging constant       |
   ---------------------------------------------------------------------
                +--------+------------+--------------------------+

           Figure 23 32: Clock Discipline Variables and Parameters

   The discipline is implemented by the local_clock() routine, which is
   called from the clock_update() routine.  The local_clock() routine
   pseudo code in
   Appendix A.6.6 A.5.5.6 has two parts; the first implements the clock state
   machine
   shown in Figure 24 and second the algorithm that second determines the time constant and thus the poll interval in Figure 25.
   interval.

   The local_clock() routine exits immediately if the offset is greater
   than the panic threshold PANICT (1000 s).  The state transition
   function in Figure 24 is implemented by the rst() rstclock() function
   shown at in
   Appendix A.5.5.7.  Figure 33 shows the lower left of state transition function used
   bu this routine.  It has four columns showing respectively the figure.  The local_clock() routine
   exits immediately state
   name, predicate and action if the offset theta is greater less than the panic threshold.
                               ---
                              | A |
                               ---
                                ||
                                \/
                               --- yes ---
                              | B |-->| C |
                               ---     ---
                             no ||
                                \/
                               ---
                              | D |
                               ---
                                ||
                                \/
                       --- no  ---  yes    SYNC         SPIK FREQ
                      | E |<--| F |----------------------------------
                       ---     ---         ||             ||
           SYNC         ||                 \/             \/
           SPIKE  FSET  \/ FREQ    NSET   ---            ---
            -------------------------    | G |          | H |
           ||     ||        ||      ||    ---            ---
           ||     ||        \/      \/     ||      yes  ||  ||  no
           ||     ||       ---     ---     ||           ||  \/
           ||    ---      | H |   | I |    ||           ||  ---
           \/   | I |      ---     ---     ||           || | J |
          ---    ---   no || ||yes  ||     ||           ||  --- step
   threshold, the predicate and actions otherwise, and finally some
   comments.

      +-------+---------------------+-------------------+--------------+
      | K State |    ||      || ||     \/     ||           || ||  || yes
          ---     ||      \/ ||    ---     ||           || ||  \/
           ||     ||     --- || theta < STEP        | L theta > STEP      |    ||           || ||  ---
           ||     || Comments     | M |||    ---     ||           || ||
      +-------+---------------------+-------------------+--------------+
      | M NSET  |
           ||     ||     --- ||     ||     ||           || ||  ---
           ||     ||      || \/     \/     \/           \/ ||   ||
           ||     ||      ||  ------------>\/<-----------  \/   \/
           ||     ||      ||              ---               --->\/<-----
           ||     ||      || ->FREQ              | N ->FREQ            |                 ---
           ||     ||      ||              --- no frequency | O
      |
           ||     ||      ||                                   ---
           ||     ||      ||                                    ||
           ||     ||      ||                                    \/
           ||     ||      ||    ---                ---         ---
            ----->-------->----| P |----><--------| Q |<------| R       |
                                ---     ||         ---         ---
         ---                            \/                      || adjust time         | S step time         |                          ---                      \/
         --- file         | T
      +-------+---------------------+-------------------+--------------+
      |                    ---
          ||                           --- FSET  | U ->SYNC              |
          \/                                                   ---
         ---                                                    || ->SYNC            | V frequency    |                                                   \/
         ---                                                   ---
          ||
      | W       |
          \/                                                   ---
         --- adjust time         | X step time         |
         ---

   A: local_clock()
   B: |captheta|>PANICT?
   C: return(PANIC)
   D: freq=0
      rval=IGNOR
   E:
   F: |captheta|>STEPT?
   G: state=SPIK
   H: mu<WATCH
   I: captheta_g=captheta
   J: FREQ?
   K: Calculate new freq adjustment from captheta, tau, and mu using
   hybrid PLL and FLL
   L: rst(FREQ,0)
   M: freq=((captheta-captheta_B-captheta_R)/mu)
   N: return(rval)
   O: step_time(captheta)
      rval=STEP
   P: rval=ADJ
   Q: rst(SYNC,0)
   R: state=NSET?
   S: rst(new,off)
   T: tc
   U: rst(FREQ,0)
   V: state=new
      captheta_B=off-captheta_R
      captheta_R=off
   W: return(rval)
   X: return

                 Figure 24: local_clock() routine (1 of 2)

   ----- file         | A
      +-------+---------------------+-------------------+--------------+
      |
   -----
    \|/
   ----- SPIK  | B ->SYNC              |
   -----
    \|/
   ----- if < 900 s ->SPIK | C |-no-----\
   ----- outlyer      |
    \|/yes
      |
   -----      -----       | D adjust freq         | else ->SYNC       | E detected     |
   -----      -----
    \|/        \|/
   -----      -----
      | F |no\       | G |no\
   ----- adjust time         |   ----- step freq         |
    \|/yes|    \|/yes|              |
      |       |                     |
   ----- step time         |   -----              |
      +-------+---------------------+-------------------+--------------+
      | H FREQ  | if < 900 s ->FREQ   | if < 900 s ->FREQ | I initial      |
      |
   -----       |   ----- else ->SYNC         | else ->SYNC       | J frequency    |
      |       | K step freq           | step freq         |
   -----              |   -----
      |
   |y  no-><-no  y|       |
   ---- adjust time         |    ---- adjust time       |              | L|
      +-------+---------------------+-------------------+--------------+
      | SYNC  | M| ->SYNC              |
   -------><---------/
         \|/
        ----- if < 900 s ->SPIK | N normal       |
        -----
         \|/
        -----
      | O       |
        -----
         \|/
        ----- adjust freq         | P else ->SYNC       |
        -----

   A: tc
   B: state=SYNC
   C: |captheta_g| > PGATE?
   D: count -= 2*tau
   E: count += tau
   F: count <= -LIMIT?
   G: count >= LIMIT?
   H: count = 0
   I: count = 0
   J: tau>MINPOLL
   K: tau<MAXPOLL
   L: tau--
   M: tau++
   N: phi += operation    |
      |       | adjust time         | step freq
   O: cappsi = sqrt(expectationvalue(phi^2))
   P: return(rval)         |              |
      |       |                     | step time         |              |
      +-------+---------------------+-------------------+--------------+

                   Figure 25: local_clock() routine (2 of 2)

   The remaining portion of 33: State Transition Function

   In the local_clock() routine is shown in
   Figure 25.  The time constant tau table entries the next state is determined identified by comparing the
   clock jitter psi arrow ->
   with the magnitude of the current residual offset
   captheata_R. produced actions listed below.  Actions such as adjust time and
   adjust frequency are implemented by the clock adjust routine PLL/FLL feedback loop in the next
   section.  If the residual offset is greater than PGATE (4) times the
   local_clock() routine.  A step clock jitter, be hysteresis counter is reduced by two; otherwise, it action is increased implemented by one.  If the hysteresis counter increases to the
   upper limit LIMIT (30), setting
   the time constant clock directly, but this is increased by one; if it
   decreases to done only after the lower limit -LIMIT (-30), stepout threshold
   WATCH (900 s) when the time constant offset is
   decreased by one.  Normally, more than the time constant hovers near MAXPOLL,
   but quickly decreases it frequency surges due to a temperature spike,
   for example.

   The step threshold STEPT
   (.125 s).  This resists clock steps under conditions of extreme
   network congestion.

   The jitter statistic vartheta (psi) and the clock wander statistic
   cappsi (omega) statistics are implemented as computed using an
   exponential averages of RMS offset
   differences and RMS frequency differences, respectively.  Let x_i be
   a measurement at average with weight factor AVG.  The time i of either vartheta or cappsi,y_i = x_i -
   x_(i-1) constant
   exponent (tau) is determined by comparing psi with the first-order sample difference and y_i_HAT magnitude of
   the exponential
   average.  Then,

   y_(i+1)_HAT = sqrt((y_i_HAT)^2+[(y_i)^2-(y_i_HAT)^2)/AVG])

   where AVG (4) is current offset theta.  If the averaging parameter in Table 17, offset is the
   exponential average at time i + 1.  The greater than PGATE (4)
   times the clock jitter statistic jitter, the hysteresis counter hyster is
   used reduced by
   two; otherwise, it is increased by one.  If hyster increases to the poll-adjust algorithm above;
   upper limit LIMIT (30), tau is increased by one; if it decreases to
   the clock wander statistic
   issued only for performance monitoring.

9.3. lower limit -LIMIT (-30), tau is decreased by one.  Normally, tau
   hovers near MAXPOLL, but quickly decreases if a temperature spike
   causes a frequency surge.

12.  Clock Adjust Process
   -----
   | A |
   -----
    \|/
   -----
   | B |
   -----
    \|/
   -----
   | C |
   -----
    \|/
   -----
   | D |
   -----
    \|/
   -----
   | E |
   -----
    \|/
   -----
   | F |-----no----\
   -----           |
    \|/yes        \|/
   -----         -----
   | H |<--------| G |
   -----         -----

   A: clock_adjust()
   B: capepsilon += captheta
   C: tmp = captheta_r/TC(tau)
   D: captheta_R -= tmp
   E: adjust_time(phi + tmp)
   F: next < timer?
   G: poll()
   H: return

                     Figure 26: clock_adjust() Routine

   The actual clock adjustment is performed by the clock_adjust()
   routine shown in Figure 26 and Appendix A.7.1. Appendix A.5.6.1.  It runs at one-second
   intervals to add the frequency offset in Figure 25 correction and a fixed percentage of
   the residual offset captheta_R. theta_r.  The captheta_R theta_r is in effect the
   exponential decay of the captheta theta value produced by the loop filter at
   each update.  The TC parameter scales the time constant to match the
   poll interval for convenience.  Note that the dispersion capepsilon EPSILON
   increases by capphi PHI at each second.

   The clock adjust process includes a timer interrupt facility driving
   the system timer seconds counter c.t.  It begins at zero when the service starts
   and increments once each second.  At each interrupt the
   clock_adjust() routine is called to incorporate the clock discipline
   time and frequency adjustments, then the associations are scanned to
   determine if the system timer seconds counter equals or exceeds the p.next state
   variable defined in the next section.  If so, the poll process is
   called to send a packet and compute the next p.next value.

10.

13.  Poll Process

   Each association supports a poll process that runs at regular
   intervals to construct and send packets in symmetric, client and
   broadcast server associations.  It runs continuously, whether or not
   servers are reachable.  The discussion reachable in this section covers order to manage the
   variables and routines necessary for a conforming NTPv4
   implementation.  Further details clock filter and rationale for the engineering
   design are discussed in [8].

10.1. reach
   register.

13.1.  Poll Process Variables

   Figure 34 summarizes the common names, formula names and Parameters a short
   description of the poll process variables(lower case) and parameters
   (upper case).  Unless noted otherwise, all variables have assumed
   prefix p.

                   +---------+---------+--------------------+
                   | Name    | Formula | Description        |
                   +---------+---------+--------------------+
                   | hpoll   | hpoll   | host poll exponent |
                   | last    | last    | last poll time     |
                   | next    | next    | next poll time     |
                   | reach   | reach   | reach register     |
                   | unreach | unreach | unreach counter    |
                   | UNREACH | 24      | unreach limit      |
                   | BCOUNT  | 8       | burst count        |
                   | BURST   | flag    | burst enable       |
                   | IBURST  | flag    | iburst enable      |
                   +---------+---------+--------------------+

              Table 18:

                     Figure 34: Poll Process Variables And Parameters

   The poll process variables are allocated in the association data
   structure along with the peer process variables.  Table 18 shows the
   names, formula names and short definition for each one.  Following is a
   detailed description of the variables, all of which carry variables.  The parameters will be called
   out in the p
   prefix.

   p.hpoll: Signed following text.

   hpoll: signed integer representing the poll exponent, in log2
   seconds.

   p.last: Integer seconds

   last: integer representing the system timer value seconds counter when the most recent
   packet was sent.

   p.next: Integer sent

   next: integer representing the system timer value seconds counter when the next packet
   is to be sent.

   p.reach: sent

   reach: 8-bit integer shift register.  When a packet is sent, the register is shifted left one bit, with zero entering from shared by the right peer and overflow bits discarded.

   p.unreach: Integer poll
   processes

   unreach: integer representing the number of seconds the server has
   been unreachable.

10.2. unreachable

13.2.  Poll Process Operations

   As described previously, once each second the clock_adjust() routine
   MUST be
   in the clock adjust process is called.  This routine calls the poll()
   routine in Appendix A.8.1 A.5.7.1 for each association in turn.  If the
   time for the next poll message is greater than the system timer, seconds counter,
   the routine MUST
   return returns immediately.  A mode-5 (broadcast server) association MUST  Symmetric (modes 1, 2), client
   (mode 3) and broadcast server (mode 5) associations routinely send a packet, but a mode-6 (broadcast client)
   packets.  A broadcast client (mode 6) association MUST NOT
   send a packet, but MUST run runs the routine to
   update the p.reach reach and
   p.unreach variables. unreach variables, but does not send packets.
   The poll() routine calls the peer_xmit() routine in Appendix A.8.3 A.5.7.3
   to send a packet.  If in a burst (p.burst (burst > 0), nothing further is done
   except call the poll_update() routine to set the next poll interval.

   If not in a burst, the p.reach reach variable is shifted left by one bit,
   with zero replacing the rightmost bit.  If the server has not been
   heard for the last three poll intervals, the clock_filter() routine
   is called to increase the dispersion as described in Section 8.3.
   Appendix A.5.7.3.

   If the BURST flag is lit and the server is reachable and a valid
   source of synchronization is available, the client sends a burst of
   BCOUNT (8) packets at each poll interval.  The interval between
   packets in the burst is two seconds.  This is useful to accurately
   measure jitter with long poll intervals.  If the IBURST flag is lit
   and this is the first packet sent when the server becomes has been
   unreachable, the client sends a burst.  This is useful to quickly
   reduce the synchronization distance below the distance threshold and
   synchronize the clock.

   If the P_MANY flag is lit in the p.flags word of the association,
   this is a manycast client association.  Manycast client associations
   send client mode packets to designated multicast group addresses at
   MINPOLL intervals.  The figure also shows association starts out with a TTL of 1.  If
   by the mechanism which time of the next poll there are fewer than MINCLOCK servers
   have been mobilized, the ttl is increased by one.  If the ttl reaches
   the limit TTLMAX, without finding MINCLOCK servers, the poll interval
   increases until reaching BEACON, when it starts over from the
   beginning.

   The poll() routine includes a feature that backs off the poll
   interval if the server becomes unreachable.  If
   p.reach reach is nonzero, the
   server is reachable and p.unreach unreach is set to zero; otherwise, p.unreach unreach is
   incremented by one for each poll to the maximum UNREACH (24). UNREACH.  Thereafter
   for each poll p.hpoll hpoll is increased by one, which doubles the poll
   interval up to the maximum MAXPOLL determined by the poll_update()
   routine.  When the server again becomes reachable, p.unreach unreach is set to
   zero, p.hpoll hpoll is reset to tau the t.c system variable and operation resumes
   normally.

   When a

   A packet is sent from an association, some by the xmit_packet() routine in Appendix A.3.  Some
   header values are copied from the peer variables left by a previous
   packet and others from the system variables. includes a flow diagram and a table
   showing  Figure 35 shows which
   values are copied to each header field.  In those implementations
   using floating double data types for root delay and root dispersion,
   these must be converted to NTP short format.  All other fields are
   either copied intact from peer and system variables or struck as a
   timestamp from the system clock.

                   +-----------------------------------+
                   | Packet Variable <--   Variable    |
                   +-----------------------------------+
                   | x.leap        <--     s.leap      |
                   | x.version     <--     s.version   |
                   | x.mode        <--     s.mode      |
                   | x.stratum     <--     s.stratum   |
                   | x.poll        <--     s.poll      |
                   | x.precision   <--     s.precision |
                   | x.rootdelay   <--     s.rootdelay |
                   | x.rootdisp    <--     s.rootdisp  |
                   | x.refid       <--     s.refid     |
                   | x.reftime     <--     s.reftime   |
                   | x.org         <--     p.xmt       |
                   | x.rec         <--     p.dst       |
                   | x.xmt         <--     clock       |
                   | x.keyid       <--     p.keyid     |
                   | x.digest      <--     md5 digest  |
                   +-----------------------------------+

                   Figure 35: xmit_packet Packet Header

   The poll_update() routine shown in Appendix A.8.2 A.5.7.2 is called when a
   valid packet is received and immediately after a poll message is has
   been sent.  If in a burst, the poll interval is fixed at 2 s;
   otherwise, the host poll exponent hpoll is set to the minimum of p.poll
   ppoll from the last packet received and p.hpoll hpoll from the poll()
   routine, but not less than MINPOLL nor greater than MAXPOLL.  Thus
   the clock discipline can be oversampled, but not undersampled.  This
   is necessary to preserve subnet dynamic behavior and protect against
   protocol errors.
   Finally, the

   The poll exponent is converted to an interval which
   establishes when added to the
   last variable determines the next variable and thus the time at for the
   next poll p.next.

11. poll.  Finally, the last variable is set to the current seconds
   counter.

14.  Security Considerations

   NTPv4 provides an optional authentication field that utilizes the MD5
   algorithm.  MD5, as the case for SHA-1, is derived from MD4, which
   has long been known to be weak.  In 2004, techniques for efficiently
   finding collisions in MD5 were announced.  A summary of the weakness
   apropriateness of MD5 can be found in [9]. [10].

   In the case of NTP as specified herein, NTP broadcast clients are
   vulnerable to disruption by misbehaving or hostile SNTP or NTP
   broadcast servers elsewhere in the Internet.  Access controls and/or
   cryptographic authentication means should be provided for additional
   security in such cases.

12.

15.  IANA Considerations

   UDP/TCP Port 123 was previously assigned by IANA for this protocol.
   The IANA has assigned the IPv4 multicast group address 224.0.1.1 and
   the IPv6 multicast address ending :101 for NTP.  This document
   introduces NTP extension fields allowing for the development of
   future extensions to the protocol, where a particular extension is to
   be identified by the Field Type sub-field within the extension field.
   IANA is requested to establish and maintain a registry for Extension
   Field Types associated with this protocol, populating this registry
   with no initial entries.  As future needs arise, new Extension Field
   Types may be defined.  Following the policies outlined in [10], [11], new
   values are to be defined by IETF Consensus.

13.
   consensus.

16.  Acknowledgements

   This authors

   The editors would like to thank Karen O'Donoghue, Brian Haberman,
   Greg Dowd, Mark Elliot, and Harlan Stenn for technical reviews of
   this document.

14.

17.  Informative References

   [1]   Mills, D., "Network Time Protocol (Version 3) Specification,
         Implementation",
         Implementation and Analysis", RFC 1305, Current Status DRAFT
         STANDARD, March 1992.

   [2]   Mills, D., "Simple Network Time Protocol (SNTP) Version 4 for
         IPv4, IPv6 and OSI", RFC 4330, draft-mills-sntp-v4-01 (work in
         progress), Current Status INFORMATIONAL, January 2006.

   [3]   University of Delaware,   Mills, D.L., "The Autokey security architecture, protocol and
         algorithms. Electrical and Computer Engineering Technical
         Report 06-1-1", NDSS , January 2006.

   [4]   Mills, D.L., Electrical and Computer Engineering Technical
         Report 06-6-1, NDSS, June 2006., "Network Time Protocol Version
         4 Reference and Implementation Guide.", 2006.

   [5]   Mills, D.L., "Computer Network Time Synchronization - the
         Network Time Protocol. CRC Press, 304pp.", 2006.

   [6]   Bradner, S., "Key words for use in RFCs to Indicate Requirement
         Levels", BCP 14, RFC 2119, Current Status BEST CURRENT
         PRACTICE, March 1997.

   [5]

   [7]   Postel, J., "Internet Protocol", STD 5, RFC 791, Updated
         by RFC1349, Current Status STANDARD, September 1981.

   [6]

   [8]   Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321,
         Current Status INFORMATIONAL, April 1992.

   [7]

   [9]   Marzullo and S. Owicki, "Maintaining the time in a distributed
         system.", ACM Operating Systems Review 19 , July 1985.

   [8]   Mills, D. L., "Computer Network Time Synchronization - the
         Network Time Protocol. CRC Press, 304pp.", 2006.

   [9]

   [10]  Bellovin, S. and E. Rescorla, Proceedings of the 13th annual
         ISOC Network and Distributed System Security Symposium,
         "Deploying a new Hash Algorithm", February 2006.

   [10]

   [11]  Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA
         Considerations Section in RFCs", BCP 26, RFC 2434, Updated
         by RFC3692, Current Status BEST CURRENT PRACTICE, October 1998.

Appendix A.  Code Skeleton

   This appendix is intended to describe the protocol and algorithms of
   an implementation in a general way using what is called a code
   skeleton program.  This consists of a set of definitions, structures
   and code segments fragments which illustrate the protocol operations without
   the complexities of an actual implementation of the protocol.  This
   program is not an executable and is not designed to run in the
   ordinary sense.  It is designed to be compiled only in order to
   verify consistent variable and type usage.

   Most of the features of the reference implementation are included
   here, with the following exceptions: There are no provisions for
   reference clocks or public key (Autokey) cryptography.  There is no
   huff-n'-puff filter, anti-clockhop hysteresis or monitoring
   provisions.  Many of the values that can be tinkered in the reference
   implementation are assumed constants here.  There are only minimal
   provisions for the kiss-o'death packet and no responding code.

   The program is not intended to be fast or compact, just to
   demonstrate the algorithms with sufficient fidelity to understand how
   they work.  The code skeleton consists of eight segments, a header
   segment included by each of the other segments, plus a code segment
   for the main program, kernel I/O and system clock interfaces, and
   peer, system, clock_adjust and poll processes.  These are presented
   in order below along with definitions and variables specific to each
   process.

A.1.  Global Definitions

   Following are definitions and other data shared by all programs.
   These values are defined in a header file ntp4.h which is included in
   all files.

A.1.1.  Definitions, Constants, Parameters

#include <math.h> s/*               /* avoids complaints about sqrt() */
#include <sys/time.h>           /* for gettimeofday() and friends */
#include <stdlib.h>             /* for malloc() and friends */

/*
 * Data types
 *
 * This program assumes the int data type is 32 bits and bitsand the long data
 * type is 64 bits. The native data type used in most calculations is
 * floating double. The data types used in some packet header fields
 * require conversion to and from this representation. Some header
 * fields involve partitioning an octet, here represented represeted by individual
 * octets.
 *
 * The 64-bit NTP timestamp format used in timestamp calculations is
 * unsigned seconds and fraction with the decimal point to the left of
 * bit 32. The only operation permitted with these values is
 * subtraction, yielding a signed 31-bit difference. The 32-bit NTP
 * short format used in delay and dispersion calculations is seconds and
 * fraction with the decimal point to the left of bit 16. The only
 * operations permitted with these values are addition and
 * multiplication by a constant.
 *
 * The IPv4 address is 32 bits, while the IPv6 address is 128 bits. The
 * message digest field is 128 bits as constructed by the MD5 algorithm.
 * The precision and poll interval fields are signed log2 seconds.
 */
typedef unsigned long tstamp;   /* NTP timestamp format */
typedef unsigned int tdist;     /* NTP short format */
typedef unsigned long ipaddr;
 typedef unsinged int ipport;   /* IPv4 or IPv6 address */
typedef unsigned long digest;   /* md5 digest */
typedef signed char s_char;     /* precision and poll interval (log2) */

/*
 * Arithmetic Timestamp conversion macroni
 */
#define FRIC            65536.                  /* NTP timestamp format 2^16 as a double */
#define D2FP(r)         ((tdist)((r) * FRIC))   /* NTP short format */
 /* IPv4 or IPv6 address */
#define FP2D(r)         ((double)(r) / FRIC)

#define FRAC            4294967296.             /* IP port number 2^32 as a double */
#define D2LFP(a)        ((tstamp)((a) * FRAC))  /* md5 digest NTP timestamp */

#define LFP2D(a)        ((double)(a) / FRAC)
#define U2LFP(a)        ((a).tv_sec + JAN_1970 << 32 + (unsigned long) \
                            ((a).tv_usec / 1e6 * FRAC))

/* precision and poll interval (log2)
 * Arithmetic conversions
 */
#define LOG2D(a)        ((a) < 0 ? 1. / (1L << -(a)) : \
                            1L << (a))          /* poll, etc. */
#define LFP2D(a) ((double)(a) / 0x100000000L) /* NTP timestamp */

 #define D2LFP(a) ((tstamp)((a) * 0x100000000L))

 #define FP2D(a) (double)(a) / 0x10000L)  /* NTP short */
 #define D2FP(a) ((tdist)((a) * 0x10000L))
 #define SQUARE(x)       (x * x)
#define SQRT(x)         (sqrt(x))

/*
 * Global constants. Some of these might be converted to variables
 * which can be tinkered by configuration or computed on-fly. For
 * instance, the reference implementation computes PRECISION could be calculated on-fly and
 * provide provides performance tuning for the defines marked with % below.
 */
#define VERSION         4       /* version number */
#define PORT 123 /* NTP poert number */
 #define MINDISP         .01     /* % minimum dispersion (s) */
#define MAXDISP         16      /* % maximum dispersion (s) */
#define MAXDIST         1       /* % distance threshold (s) */
#define NOSYNC 3          0x3     /* leap unsync */
#define MAXSTRAT        16      /* maximum stratum (infinity metric) */
#define MINPOLL 4         6       /* % minimum poll interval (16 (64 s)*/
#define MAXPOLL         17      /* % maximum poll interval (36.4 h) */
#define MINCLOCK        3       /* minimum manycast survivors */
#define MAXCLOCK        10      /* maximum manycast candidates */
#define TTLMAX          8       /* max ttl manycast */
#define BEACON          15      /* max interval between beacons */

#define PHI             15e-6   /* % frequency tolerance (15 PPM) */
#define NSTAGE          8       /* clock register stages */
#define NMAX            50      /* % maximum number of peers */
#define NSANE           1       /* % minimum intersection survivors */
#define NMIN            3       /* % minimum cluster survivors */

/*
 * Global return values
 */
#define TRUE            1       /* boolean true */
#define FALSE           0       /* boolean false */
#define NULL            0       /* empty pointer */

/*
 * Local clock process return codes
 */
#define IGNORE          0       /* ignore */

#define SLEW            1       /* slew adjustment */
#define STEP            2       /* step adjustment */
#define PANIC           3       /* panic - no adjustment */

/*
 * System flags
 */
#define S_FLAGS         0       /* any system flags */
#define S_BCSTENAB      0x1     /* enable broadcast client */

/*
 * Peer flags
 */
#define P_FLAGS         0       /* any peer flags */
#define P_EPHEM         0x01    /* association is ephemeral */
#define P_BURST         0x02    /* burst enable */
#define P_IBURST        0x04    /* intial burst enable */
#define P_NOTRUST       0x08    /* authenticated access */
#define P_NOPEER        0x10    /* authenticated mobilization */
#define P_MANY          0x20    /* manycast client */

/*
 * Authentication codes
 */
#define A_NONE          0       /* no authentication */
#define A_OK            1       /* authentication OK */
#define A_ERROR         2       /* authentication error */
#define A_CRYPTO        3       /* crypto-NAK */

/*
 * Association state codes
 */
#define X_INIT          0       /* initialization */
#define X_STALE         1       /* timeout */
#define X_STEP          2       /* time step */
#define X_ERROR         3       /* authentication error */
#define X_CRYPTO        4       /* crypto-NAK received */
#define X_NKEY          5       /* untrusted key */

/*
 * Protocol mode definitionss
 */
#define M_RSVD          0       /* reserved */
#define M_SACT          1       /* symmetric active */
#define M_PASV          2       /* symmetric passive */
#define M_CLNT          3       /* client */
#define M_SERV          4       /* server */
#define M_BCST          5       /* broadcast server */

#define M_BCLN          6       /* broadcast client */

/*
 * Clock state definitions
 */
#define NSET            0       /* clock never set */
#define FSET            1       /* frequency set from file */
#define SPIK            2       /* spike detected */
#define FREQ            3       /* frequency mode */
#define SYNC            4       /* clock synchronized */

A.1.2.  Packet Data Structures

 /*
  * The receive and transmit packets may contain an optional message
  * authentication code (MAC) consisting of a key identifier (keyid) and
  * message digest (mac). NTPv4 supports optional extension fields which
  * are inserted after the the header and before the MAC, but these are
  * not described here.
  *
  * Receive packet
  *
  * Note the dst timestamp is not part of the packet itself. It is
  * captured upon arrival and returned in the receive buffer along with
  * the buffer length and data. Note that some of the char fields are
  * packed in the actual header, but the details are omited here. packed in the actual header, but the details are omited here.
  */
 struct r {
         ipaddr  srcaddr;        /* source (remote) address */
         ipaddr  dstaddr;        /* destination (local) address */
         char    version;        /* version number */
         char    leap;           /* leap indicator */
         char    mode;           /* mode */
         char    stratum;        /* stratum */
         char    poll;           /* poll interval */
         s_char  precision;      /* precision */
         tdist   rootdelay;      /* root delay */
         tdist   rootdisp;       /* root dispersion */
         char    refid;          /* reference ID */
         tstamp  reftime;        /* reference time */
         tstamp  org;            /* origin timestamp */
         tstamp  rec;            /* receive timestamp */
         tstamp  xmt;            /* transmit timestamp */
         int     keyid;          /* key ID */
         digest  mac;            /* message digest */
         tstamp  dst;            /* destination timestamp */
 } r;
 /*
  * Transmit packet
  */
 struct r x {
         ipaddr  srcaddr;  dstaddr;        /* source (remote) (local) address */
         ipaddr  dstaddr;  srcaddr;        /* destination (local) (remote) address */
         char    version;        /* version number */
         char    leap;           /* leap indicator */
         char    mode;           /* mode */
         char    stratum;        /* stratum */
         char    poll;           /* poll interval */
         s_char  precision;      /* precision */
         tdist   rootdelay;      /* root delay */
         tdist   rootdisp;       /* root dispersion */
         char    refid;          /* reference ID */
         tstamp  reftime;        /* reference time */
         tstamp  org;            /* origin timestamp */
         tstamp  rec;            /* receive timestamp */
         tstamp  xmt;            /* transmit timestamp */
         int     keyid;          /* key ID */
         digest  digest;  mac;            /* message digest */
 } x;

A.1.3.  Association Data Structures

   /*
    * Filter stage structure. Note the t member in this and other
    * structures refers to process time, not real time. Process time
    * increments by one second for every elapsed second of real time.
    */
   struct f {
           tstamp  dst;  t;              /* destination timestamp update time */
           double  offset;         /* clock ofset */
           double  delay;          /* roundtrip delay */
           double  disp;           /* dispersion */
   } r; f;

   /*
    * Transmit packet Association structure. This is shared between the peer process and
    * poll process.
    */
   struct x p {

           /*
            * Variables set by configuration
            */
           ipaddr  dstaddr;  srcaddr;        /* source (local) (remote) address */
           ipaddr  srcaddr;  dstaddr;        /* destination (remote) (local) address */
           char    version;        /* version number */
           char    hmode;          /* host mode */
           int     keyid;          /* key identifier */
           int     flags;          /* option flags */

           /*
            * Variables set by received packet
            */
           char    leap;           /* leap indicator */
           char  mode;    pmode;          /* peer mode */
           char    stratum;        /* stratum */
           char  poll;    ppoll;          /* peer poll interval */
  s_char  precision;  /* precision */
  tdist
           double  rootdelay;      /* root delay */
  tdist
           double  rootdisp;       /* root dispersion root dispersion */
           char    refid;          /* reference ID */
           tstamp  reftime;        /* reference time */
   #define begin_clear org         /* beginning of clear area */
           tstamp  org;            /* originate timestamp */
           tstamp  rec;            /* receive timestamp */
           tstamp  xmt;            /* transmit timestamp */

           /*
            * Computed data
            */
           double  t;              /* update time */
           struct f f[NSTAGE];     /* clock filter */
           double  offset;         /* peer offset */
           double  delay;          /* peer delay */
           double  disp;           /* peer dispersion */
           double  jitter;         /* RMS jitter */

           /*
            * Poll process variables
            */
           char  refid;    hpoll;          /* reference ID host poll interval */
  tstamp  reftime;
           int     burst;          /* reference time burst counter */
  tstamp  org;
           int     reach;          /* origin timestamp reach register */
  tstamp  rec;
           int     ttl;            /* receive timestamp ttl (manycast) */
  tstamp  xmt;
   #define end_clear unreach       /* transmit timestamp end of clear area */
           int keyid;     unreach;        /* key ID unreach counter */
  digest digest;
           int     outdate;        /* message digest last poll time */
           int     nextdate;       /* next poll time */
   } x;

A.1.3.  Association p;

A.1.4.  System Data Structures

   /*
    * Filter stage structure. Note the t member in this and other
   * structures refers to process time, not real time. Process time
   * increments Chime list. This is used by one second for every elapsed second of real time. the intersection algorithm.
    */
   struct f m {
   tstamp   t;                      /* update time m is for Marzullo */
   double   offset;
           struct p *p;            /* clock ofset peer structure pointer */
   double   delay;
           int     type;           /* roundtrip delay high +1, mid 0, low -1 */
           double   disp;  edge;           /* dispersion correctness interval edge */
   } f; m;

   /*
    * Association structure. Survivor list. This is shared between used by the peer process and
   * poll process. clustering algorithm.
    */
   struct p v {
           struct p *p;            /*
   * Variables set by configuration
   */
   ipaddr   srcaddr;   /* source (remote) address */
   ipport   srcport;   /* source port number *.
   ipaddr   dstaddr;   /* destination (local) address */
   ipport   dstport;   /* destination port number */
   char   version;   /* version number */
   char   mode;   /* mode peer structure pointer */
   int   keyid;
           double  metric;         /* key identifier sort metric */
   int   flags;
   } v;

   /* option flags
    * System structure
    */
   struct s {
           tstamp  t;              /*
   * Variables set by received packet update time */
           char    leap;           /* leap indicator */
           char   mode;    stratum;        /* mode stratum */
           char   stratum;    poll;           /* stratum poll interval */
           char   ppoll;    precision;      /* peer poll interval precision */
           double  rootdelay;      /* root delay */
           double  rootdisp;       /* root dispersion */
           char    refid;          /* reference ID */
           tstamp  reftime;        /* reference time */
   #define   begin_clear org
           struct m m[NMAX];       /* beginning of clear area chime list */
   tstamp   org;
           struct v v[NMAX];       /* originate timestamp survivor list */
   tstamp   rec;
           struct p *p;            /* receive timestamp association ID */
   tstamp   xmt;
           double  offset;         /* transmit timestamp combined offset */
           double  jitter;         /* combined jitter */
           int     flags;          /* option flags */
           int     n;              /* number of survivors */
   } s;

A.1.5.  Local Clock Data Structures

   /*
    * Computed data Local clock structure
    */
   double
   struct c {
           tstamp  t;              /* update time */
   struct f f[NSTAGE];
           int     state;          /* clock filter current state */
           double  offset;         /* peer current offset */
           double   delay;  last;           /* peer delay previous offset */
           int     count;          /* jiggle counter */
           double   disp;  freq;           /* peer dispersion frequency */
           double  jitter;         /* RMS jitter */
           double  wander;         /* RMS wander */
   } c;

A.1.6.  Function Prototypes

  /*
   * Poll Peer process variables
   */
   char   hpoll;
  void    receive(struct r *);    /* host poll interval receive packet */
   int   burst;
  void    packet(struct p *, struct r *); /* burst counter process packet */
   int   reach;
  void    clock_filter(struct p *, double, double, double); /* reach register filter */
   #define   end_clear unreach
  double  root_dist(struct p *);  /* end calculate root distance */
  int     fit(struct p *);        /* determine fitness of server */
  void    clear(struct p *, int); /* clear area association */
  int   unreach;     access(struct r *);     /* unreach counter determine access restrictions */

  /*
   * System process
   */
  int   last;     main();                 /* last poll time main program */
  void    clock_select();         /* find the best clocks */
  void    clock_update(struct p *); /* update the system clock */
  void    clock_combine();        /* combine the offsets */

  /*
   * Local clock process
   */
  int     local_clock(struct p *, double); /* clock discipline */
  void    rstclock(int, double, double); /* clock state transition */

  /*
   * Clock adjust process
   */
   int   next;
  void    clock_adjust();         /* next poll time one-second timer process */
   } p;

A.1.4.  System Data Structures
  /*
   * Chime list. This is used by the intersection algorithm. Poll process
   */
   struct m {
  void    poll(struct p *);               /* m is for Marzullo poll process */
   struct
  void    poll_update(struct p *p; *, int); /* peer structure pointer update the poll interval */
   int   type;
  void    peer_xmit(struct p *);  /* high +1, mid 0, low -1 transmit a packet */
   double   edge;
  void    fast_xmit(struct r *, int, int); /* correctness interval edge transmit a reply packet */
   } m;

  /*
   * Survivor list. This is used by the clustering algorithm. Utility routines
   */
  digest  md5(int);               /* generate a message digest */
   struct v {
  struct p *p; *mobilize(ipaddr, ipaddr, int, int, int, int); /* peer structure pointer mobilize */
   double   metric;
  struct p *find_assoc(struct r *); /* sort metric search the association table */
   } v;

  /*
   * System structure Kernel interface
   */
  struct s {
   tstamp   t; r *recv_packet();        /* update time wait for packet */
   char   leap;
  void    xmit_packet(struct x *); /* leap indicator send packet */
   char   stratum;
  void    step_time(double);      /* stratum step time */
   char   poll;
  void    adjust_time(double);    /* poll interval adjust (slew) time */
   char   precision;
  tstamp  get_time();             /* precision read time */
   double   rootdelay;

A.2.  Main Program and Utility Routines

/* root delay
 * Definitions
 */
   double   rootdisp;
#define PRECISION       -18     /* root dispersion precision (log2 s)  */
   char   refid;
#define IPADDR          0       /* reference ID any IP address */
   tstamp   reftime;
#define MODE            0       /* reference time any NTP mode */
   struct m m[NMAX];
#define KEYID           0       /* chime list any key identifier */
   struct v v[NMAX];

/* survivor list
 * main() - main program
 */
int
main()
{
        struct p *p;            /* association ID */
   double   offset;   /* combined offset peer structure pointer */
   double   jitter;
        struct r *r;            /* combined jitter receive packet pointer */
   int   flags;

        /* option flags
         * 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.

         */
   } s;

A.1.5.  Local Clock Data Structures
        memset(&s, sizeof(s), 0);
        s.leap = NOSYNC;
        s.stratum = MAXSTRAT;
        s.poll = MINPOLL;
        s.precision = PRECISION;
        s.p = NULL;

        /*
         * Local Initialize local clock structure variables
         */
   struct c
        memset(&c, sizeof(c), 0);
        if (/* frequency file */ 0) {
   tstamp   t;
                c.freq = /* update time freq */
   int   state; 0;
                rstclock(FSET, 0, 0);
        } else {
                rstclock(NSET, 0, 0);
        }
        c.jitter = LOG2D(s.precision);

        /* current state
         * Read the configuration file and mobilize persistent
         * associations with spcified addresses, version, mode, key ID
         * and flags.
         */
   double   offset;
        while (/* mobilize configurated associations */ 0) {
                p = mobilize(IPADDR, IPADDR, VERSION, MODE, KEYID,
                    P_FLAGS);
        }

        /* current offset
         * Start the system timer, which ticks once per second. Then
         * read packets as they arrive, strike receive timestamp and
         * call the receive() routine.
         */
   double   base;
        while (0) {
                r = recv_packet();
                r->dst = get_time();
                receive(r);
        }
}

/* base offset
 * mobilize() - mobilize and initialize an association
 */
   double   last;
struct p
*mobilize(
        ipaddr  srcaddr,        /* previous offset IP source address */
   int   count;
        ipaddr  dstaddr,        /* jiggle counter IP destination address */
   double   freq;
        int     version,        /* frequency version */
   double   jitter;
        int     mode,           /* RMS jitter host mode */
   double   wander;
        int     keyid,          /* RMS wander key identifier */
   } c;

A.1.6.  Function Prototypes
        int     flags           /*
   * Peer peer flags */
        )
{
        struct p *p;            /* peer process pointer */
   void   receive(struct r *);

        /* receive packet
         * Allocate and initialize association memory
         */
   void   fast_xmit(struct r *, int, int);
        p = malloc(sizeof(struct p));
        p->srcaddr = srcaddr;
        p->dstaddr = dstaddr;
        p->version = version;
        p->hmode = mode;
        p->keyid = keyid;
        p->hpoll = MINPOLL;
        clear(p, X_INIT);
        p->flags == flags;
        return (p);
}

/* transmit
 * find_assoc() - find a reply packet matching association
 */
struct p *find_assoc(struct r *);                        /* search the association table peer structure pointer or NULL */
   void   packet(struct p *,
*find_assoc(
        struct r *); *r             /* process receive packet pointer */
   void   clock_filter(struct
        )
{
        struct p *, double, double, double); *p;            /* filter dummy peer structure pointer */
   int   accept(struct p *);

        /* determine fitness of server
         * Search association table for matching source
         * address, source port and mode.
         */
   int   access(struct r *);
   /* determine access restrictions
        while (/* all associations */ 0) {
                if (r->srcaddr == p->srcaddr && r->mode == p->hmode)
                        return(p);
        }
        return (NULL);
}

/*
 * System process md5() - compute message digest
 */
   void   clock_select();

digest
md5(
        int     keyid           /* find the best clocks key identifier */
   void   clock_update(struct p *);
        )
{
        /* update
         * Compute a keyed cryptographic message digest. The key
         * identifier is associated with a key in the system clock */
   void   clock_combine();   /* combine local key cache.
         * The key is prepended to the offsets */
   double   root_dist(struct p *);   /* calculate root distance */

   /* packet header and extension fieds
         * Clock discipline process
   */
   int   local_clock(struct p *, double); /* clock discipline and the result hashed by the MD5 algorithm as described in
         * RFC-1321. Return a MAC consisting of the 32-bit key ID
         * concatenated with the 128-bit digest.
         */
   void   rstclock(int, double, double); /* clock state transition
        return (/* MD5 digest */ 0);
}

A.3.  Kernel Input/Output Interface

   /*
    * Clock adjust process Kernel interface to transmit and receive packets. Details are
    * deliberately vague and depend on the operating system.
    *
    * recv_packet - receive packet from network
    */
   void   clock_adjust();
   struct r                        /* one-second timer process receive packet pointer*/
   *recv_packet() {
           return (/* receive packet r */ 0);
   }

   /*
    * Poll process
   */
   void   poll(struct p *);   /* poll process xmit_packet - transmit packet to network
    */
   void   poll_update(struct p *, int);
   xmit_packet(
           struct x *x             /* update the poll interval transmit packet pointer */
   void   peer_xmit(struct p *);
           )
   {
           /* transmit a send packet x */
   }

A.4.  Kernel System Clock Interface

/*
 * Main program and System clock utility functions
 *
 * There are three time formats: native (Unix), NTP and floating double.
 * The get_time() routine returns the time in NTP long format. The Unix
 * routines expect arguments as a structure of two signed 32-bit words
 * in seconds and microseconds (timeval) or nanoseconds (timespec). The
 * step_time() and adjust_time() routines expect signed arguments in
 * floating double. The simplified code shown here is for illustration
 * only and has not been verified.
 */
   int   main();   /* main program */
   struct p *mobilize(ipaddr, ipaddr, int, int, int, int);
    /* mobilize */
   void   clear(struct p *, int);   /* clear association */
   digest   md5(int);
#define JAN_1970        2208988800UL /* generate a message digest 1970 - 1900 in seconds */

/*
 * Kernel I/O Interface get_time - read system time and convert to NTP format
 */
tstamp
get_time()
{
        struct r *recv_packet(); timeval unix_time;

        /* wait for
         * There are only two calls on this routine in the program. One
         * when a packet */
   void   xmit_packet(struct x *);   /* send arrives from the network and the other when a
         * packet */

   /* is placed on the send queue. Call the kernel time of
         * Kernel system clock interface day routine (such as gettimeofday()) and convert to NTP
         * format.
         */
   void   step_time(double);
        gettimeofday(&unix_time, NULL);
        return (U2LFP(unix_time));
}

/*
 * step_time() - step system time to given offset valuet
 */
void   adjust_time(double);
step_time(
        double  offset          /* adjust (slew) time clock offset */
        )
{
        struct timeval unix_time;
        tstamp   get_time();  ntp_time;

        /* read time */

A.2.  Main Program
         * Convert from double to native format (signed) and Utility Routines

   #include "ntp4.h"

   /* add to the
         * Definitions
   */
   #define PRECISION -18   /* precision (log2 s)    */
   #define IPADDR   0   /* any IP address */
   #define MODE   0   /* any NTP mode */
   #define KEYID   0   /* any key identifier current time. Note the addition is done in native format to
         * avoid overflow or loss of precision.
         */
        gettimeofday(&unix_time, NULL);
        ntp_time = D2LFP(offset) + U2LFP(unix_time);;
        unix_time.tv_sec = ntp_time >> 32;
        unix_time.tv_usec = (long)((ntp_time - unix_time.tv_sec <<
            32) / FRAC * 1e6);
        settimeofday(&unix_time, NULL);
}

/*
 * main() adjust_time() - main program slew system clock to given offset value
 */
   int
   main()
   {
   struct p *p;
void
adjust_time(
        double  offset          /* peer structure pointer clock offset */
        )
{
        struct r *r;   /* receive packet pointer */ timeval unix_time;
        tstamp  ntp_time;

        /*
         * Read command line options and initialize system variables.
   * Implementations MAY measure the precision specific
   * to each machine by measuring the clock increments Convert from double to native format (signed) and add to read the
         * system clock. current time.
         */
   memset(&s, sizeof(s), 0);
   s.leap = NOSYNC;
   s.stratum = MAXSTRAT;
   s.poll
        ntp_time = MINPOLL;
   s.precision D2LFP(offset);
        unix_time.tv_sec = PRECISION;
   s.p ntp_time >> 32;
        unix_time.tv_usec = NULL;

   /* (long)((ntp_time - unix_time.tv_sec <<
            32) / FRAC * Initialize local clock variables
   */
   memset(&c, sizeof(c), 0);
   if (/* frequency file */ 0) {
      c.freq = /* freq */ 0;
      rstclock(FSET, 0, 0);
    } else {
   rstclock(NSET, 0, 0); 1e6);
        adjtime(&unix_time, NULL);
}
   c.jitter = LOG2D(s.precision);

A.5.  Peer Process

  /*
   * Read A crypto-NAK packet includes the configuration file and mobilize persistent NTP header followed by a MAC
   * associations with spcified addresses, version, mode, consisting only of the key ID identifier with value zero. It tells the
   * and flags.
   */
   while (/* mobilize configurated associations */ 0) {
      p = mobilize(IPADDR, IPADDR, VERSION, MODE, KEYID,
      P_FLAGS);
   }

   /* receiver that a prior request could not be properly authenticated,
   * Start but the system timer, which ticks once per second. Then NTP header fields are correct.
   * read packets as they arrive, strike receive timestamp
   * A kiss-o'-death packet is an NTP header with leap 0x3 (NOSYNC) and
   * call stratum 16 (MAXSTRAT. It tells the receive() routine.

   */
   while (0) {
   r = recv_packet(); r->dst = get_time(); receive(r);
   }
   }

   /* receiver that something drastic
   * mobilize() - mobilize and initialize an association
   */
   struct p
   *mobilize(
   ipaddr   srcaddr,   /* IP source address */
   ipaddr   dstaddr,   /* IP destination address */
   int   version,   /* version */
   int   mode,   /* host mode has happened, as revealled by the kiss code in the refid field. The
   * NTP header fields may or may not be correct.
   */
   int   keyid,
  /* key identifier
   * Peer process parameters and constants
   */
   int   flags
  #define SGATE           3       /* peer flags spike gate (clock filter */
   )
   {
   struct p *p;
  #define BDELAY          .004    /* peer process pointer broadcast delay (s) */

  /*
   * Allocate and initialize association memory Dispatch codes
   */
   p = malloc(sizeof(struct p));
   p->srcaddr = srcaddr;
   p->srcport = PORT;
   p->dstaddr = dstaddr;
   p->dstport = PORT;
   p->version = version;
   p->mode = mode;
   p->keyid = keyid;
   p->hpoll = MINPOLL;
   clear(p, X_INIT);
   p->flags == flags;
   return (p);
   }
  #define ERR             -1      /*
   * clear() - reinitialize for persistent association, demobilize
   * for ephemeral association. error */
   void
   clear(
   struct p *p,
  #define DSCRD           0       /* peer structure pointer discard packet */
   int   kiss
  #define PROC            1       /* kiss code process packet */
   )
   {
   int i;
  #define BCST            2       /*
   * The first thing to do is return all resources to the bank.
   * Typical resources are not detailed here, but they include
   * dynamically allocated structures for keys, certificates, etc.
   * If an ephemeral association and not initialization, return
   * the association memory as well. broadcast packet */
  #define FXMIT           3       /* return resources client packet */
   if (s.p == p)
   s.p = NULL;
   if (kiss != X_INIT && (p->flags & P_EPHEM)) {
      free(p);
   return;
   }
  #define NEWPS           4       /*
   * Initialize the association fields for general reset. new symmetric passive client */
   memset(BEGIN_CLEAR(p), LEN_CLEAR, 0); p->leap = NOSYNC;
   p->stratum = MAXSTRAT;
   p->ppoll = MAXPOLL;
   p->hpoll = MINPOLL;
   p->disp = MAXDISP;
   p->jitter = LOG2D(s.precision); p->refid = kiss;
   for (i = 0; i < NSTAGE; i++)
      p->f[i].disp = MAXDISP;
  #define NEWBC           5       /*
   * Randomize the first poll just in case thousands of new broadcast client */

  /*
   * clients have just been stirred up after a long absence of the Dispatch matrix
   * broadcast server.              active  passv  client server bcast */
   p->last = p->t = c.t;
   p->next
  int table[7][5] = p->last + (random() & ((1 << MINPOLL) - 1));
   } {
  /*
   * md5() - compute message digest nopeer  */
   digest
   md5(
   int   keyid   { NEWPS, DSCRD, FXMIT, MANY, NEWBC },
  /* key identifier active  */   { PROC,  PROC,  DSCRD, DSCRD, DSCRD },
  /* passv   */
   )   { PROC,  ERR,   DSCRD, DSCRD, DSCRD },
  /* client  */   { DSCRD, DSCRD, DSCRD, PROC,  DSCRD },
  /* server  */   { DSCRD, DSCRD, DSCRD, DSCRD, DSCRD },
  /* bcast   */   { DSCRD, DSCRD, DSCRD, DSCRD, DSCRD },
  /* bclient */   { DSCRD, DSCRD, DSCRD, DSCRD, PROC}
  };

  /*
   * Compute a keyed cryptographic message digest. The key
   * identifier is associated with a key in the local key cache.
   * The key is prepended to the packet header and extension fieds Miscellaneous macroni
   * and the result hashed by the MD5 algorithm as described in
   * RFC-1321. Return a MAC consisting of This macro defines the 32-bit key ID authentication state. If x is 0,
   * concatenated with the 128-bit digest.
   */
   return (/* MD5 digest authentication is optional, othewise it is required.
   */ 0);
   }

A.3.  Kernel Input/Output Interface
  #define AUTH(x, y)      ((x) ? (y) == A_OK : (y) == A_OK || \
                              (y) == A_NONE)

  /*
   * Kernel interface to transmit and receive packets. Details These are
   * deliberately vague and depend on used by the operating system.
   * clear() routine
   */
  #define BEGIN_CLEAR(p)  ((char *)&((p)->begin_clear))
  #define END_CLEAR(p)    ((char *)&((p)->end_clear))
  #define LEN_CLEAR       (END_CLEAR((struct p *)0) - \
                              BEGIN_CLEAR((struct p *)0))

A.5.1.  receive()

/*
 * recv_packet receive() - receive packet from network and decode modes
 */
void
receive(
        struct r *r             /* receive packet pointer*/
   *recv_packet() pointer */
        )

{
   return (/* receive packet r
        struct p *p;            /* peer structure pointer
        int     auth;           /* authentication code */
        int     has_mac;        /* size of MAC */
        int     synch;          /* synchronized switch */
        int     auth;           /* authentication code */ 0);
   }

        /*
         * xmit_packet - transmit packet Check access control lists. The intent here is to network implement a
         * whitelist of those IP addresses specifically accepted and/or
         * a blacklist of those IP addresses specifically rejected.
         * There could be different lists for authenticated clients and
         * unauthenticated clients.
         */
   void
   xmit_packet(
   struct x *x
        if (!access(r))
                return;                 /* transmit packet pointer access denied */
   )
   {

        /* send
         * The version must not be in the future. Format checks include
         * packet x length, MAC length and extension field lengths, if
         * present.
         */
        if (r->version > VERSION /* or format error */)
                return;                 /* format error */
   }

A.4.  Kernel System Clock Interface

        /*
         * Authentication is conditioned by two switches which can be
         * specified on a per-client basis.
         *
         * P_NOPEER     do not mobilize an association unless
         *              authenticated
         * P_NOTRUST    do not allow access unless authenticated
         *              (implies P_NOPEER)
         *
         * There are three time formats: native (Unix), NTP and floating double. four outcomes:
         * The get_time() routine returns
         * A_NONE       the time in NTP long format. The Unix packet has no MAC
         * routines expect arguments as A_OK         the packet has a structure of two signed 32-bit words MAC and authentication
         * in seconds               succeeds
         * A_ERROR      the packet has a MAC and microseconds (timeval) or nanoseconds (timespec). authentication fails
         * A_CRYPTO     crypto-NAK. The MAC has four octets only.
         * step_time() and adjust_time() routines expect signed arguments in
         * floating double. Note: The simplified code shown here AUTH(x, y) macro is for illustration used to filter outcomes. If x
         * only is zero, acceptable outcomes of y are NONE and has OK. If x is
         * one, the only acceptable outcome of y is OK.
         */
        has_mac = /* length of MAC field */ 0;
        if (has_mac == 0) {
                auth = A_NONE;          /* not been verified. required */
 #define JAN_1970   2208988800UL
        } else if (has_mac == 4) {
                auth == A_CRYPTO;       /* 1970 - 1900 in seconds crypto-NAK */
        } else {
                if (r->mac != md5(r->keyid))
                        auth = A_ERROR; /* auth error */
                else
                        auth = A_OK;    /* auth OK */
        }

        /*
         * get_time - read system time Find association and convert dispatch code. If there is no
         * association to NTP format match, the value of p->hmode is assumed NULL.
         */
 tstamp
 get_time()
        p = find_assoc(r);
        switch(table[p->hmode][r->mode]) {
 struct timeval unix_time;

        /*
         * There are only two calls on this routine in the program. One
 * when a Client packet arrives from the network and the other when a no association. Send server reply without
         * packet is placed on the send queue. Call the kernel time of saving state.
         */
        case FXMIT:

                /*
                 * day routine (such as gettimeofday()) and convert to NTP If unicast destination address, send server packet.
                 * format. If authentication fails, send a crypto-NAK packet.
                /*
                if (/* not multicast dstaddr */0) {
                        if (AUTH(p->flags & P_NOTRUST, auth))
                                fast_xmit(r, M_SERV, auth);
                        else if (auth == A_ERROR)
                                fast_xmit(r, M_SERV, A_CRYPTO);
                        return;         /* M_SERV packet sent */
 gettimeofday(&unix_time, NULL);

 return ((unix_time.tv_sec + JAN_1970) * 0x100000000L +
    (unix_time.tv_usec * 0x100000000L) / 1000000);
                }

                /*
                 * step_time() - step system time to given offset valuet
 */
 void
 step_time(
 double   offset   /* clock offset This must be manycast. Do not repspond if we are not
                 * synchronized or if our stratum is above the
                 * manycaster.
                 */
 )
 {
 struct timeval unix_time;
 tstamp   ntp_time;
                if (s.leap == NOSYNC || s.stratum > r->stratum)
                        return;

                /*
                 * Convert from double to native format (signed) and add to Respond only if authentication is ok. Note that the
                 * current time. Note unicast addreess is used, not the addition multicast.
                 */
                if (AUTH(p->flags & P_NOTRUST, auth))
                        fast_xmit(r, M_SERV, auth);
                return;

        /*
         * New manycase client ephemeral association. It is done mobilized in native format to
         * avoid overflow or loss of precision.
 */
 ntp_time = D2LFP(offset); gettimeofday(&unix_time, NULL);
 unix_time.tv_sec += ntp_time / 0x100000000L;
 unix_time.tv_usec += ntp_time % 0x100000000L;
 unix_time.tv_sec += unix_time.tv_usec / 1000000;
 unix_time.tv_usec %= 1000000;
 settimeofday(&unix_time, NULL);
 }

 /* the same version as in the packet. If authentication fails,
         * adjust_time() - slew system clock to given offset value
 */
 void
 adjust_time(
 double   offset   /* clock offset */
 )
 {
 struct timeval unix_time;
 tstamp   ntp_time;

 /* ignore the packet. Verify the server packet by comparing the
         * Convert from double to native format (signed) and add to r->org timestamp in the packet with the p->xmt timestamp in
         * current time. the multicast client association. If they match, the server
         * packet is authentic. Details omitted.
         */
 ntp_time = D2LFP(offset);
 unix_time.tv_sec = ntp_time / 0x100000000L;
 unix_time.tv_usec
        case MANY:
                if (!AUTH(p->flags & (P_NOTRUST | P_NOPEER), auth))
                        return;         /* authentication error */

                p = ntp_time % 0x100000000L;
 unix_time.tv_sec += unix_time.tv_usec / 1000000;
 unix_time.tv_usec %= 1000000;
 adjtime(&unix_time, NULL);
 }

A.5.  Peer Process

   #include "ntp4.h" mobilize(r->srcaddr, r->dstaddr, r->version, M_CLNT,
                    r->keyid, P_EPHEM);
                break;

        /*
         * A crypto-NAK packet includes the NTP header followed by a MAC
   * consisting only of the key identifier with value zero. New symmetric passive ssociation. It tells is mobilized in the same
         * receiver that a prior request could not be properly authenticated,
   * but version as in the NTP header fields are correct. packet. If authentication fails, send a
         * crypto-NAK packet. If restrict no-moblize, send a symmetric
         * A kiss-o'-death active packet has an NTP header with leap 3 (NOSYNC) and instead.
         */
        case NEWPS:
                if (!AUTH(p->flags & P_NOTRUST, auth)) {
                        if (auth == A_ERROR)
                                fast_xmit(r, M_SACT, A_CRYPTO);
                        return;         /* crypto-NAK packet sent */
                }
                if (!AUTH(p->flags & P_NOPEER, auth)) {
                        fast_xmit(r, M_SACT, auth);
                        return;         /* M_SACT packet sent */
                }
                p = mobilize(r->srcaddr, r->dstaddr, r->version, M_PASV,
                    r->keyid, P_EPHEM);
                break;

        /*
         * stratum 0. New broadcast client association. It tells is mobilized in the receiver that something drastic same
         * has happened, version as revealled by in the kiss packet. If authentication fails, ignore the
         * packet. Note this code in does not support the refid field. The initial volley
         * NTP header fields may or may feature in the reference implementation.
         */
        case NEWBC:
                if (!AUTH(p->flags & (P_NOTRUST | P_NOPEER), auth))
                        return;         /* authentication error */
                if (!(s.flags & S_BCSTENAB))
                        return;         /* broadcast not be correct. enabled */

                p = mobilize(r->srcaddr, r->dstaddr, r->version, M_BCLN,
                    r->keyid, P_EPHEM);
                break;                  /* processing continues */

        /*
         * Definitions Process packet. Placeholdler only.
         */
   #define SGATE   3
        case PROC:
                break;                  /* spike gate (clock filter processing continues */

        /*
         * Invalid mode combination. We get here only in case of
         * ephemeral associations, so the correct action is simply to
         * toss it.
         */
   #define BDELAY   .004
        case ERR:
                clear(p, X_ERROR);
                return;                 /* broadcast delay (s) invalid mode combination */

        /*
         * Dispatch codes No match; just discard the packet.
         */
   #define ERR   -1
        case DSCRD:
                return;                 /* error orphan abandoned */
   #define DSCRD   0
        }

        /* discard packet
         * Next comes a rigorous schedule of timestamp checking. If the
         * transmit timestamp is zero, the server is horribly broken.
         */
   #define PROC   1
        if (r->xmt == 0)
                return;                 /* process packet invalid timestamp */
   #define BCST   2

        /* broadcast
         * If the transmit timestamp duplicates a previous one, the
         * packet is a replay.
         */
   #define FXMIT   3
        if (r->xmt == p->xmt)
                return;                 /* client duplicate packet */
   #define NEWPS   4   /* new symmetric passive client */
   #define NEWBC   5

        /* new
         * If this is a broadcast client */

   /* mode packet, skip further checking.
         * Dispatch matrix If the origin timestamp is zero, the sender has not yet heard
         *   active passv client server bcast from us. Otherwise, if the origin timestamp does not match
         * the transmit timestamp, the packet is bogus.

         */
   int table[7][5]
        synch = TRUE;
        if (r->mode != M_BCST) {
                if (r->org == 0)
                        synch = FALSE;  /* nopeer    */{ NEWPS, DSCRD, FXMIT, DSCRD, NEWBC },
   /* active    */{ PROC, PROC, DSCRD, DSCRD, DSCRD },
   /* passv    */{ PROC, ERR, DSCRD, DSCRD, DSCRD },
   /* client    */{ DSCRD, DSCRD, DSCRD, PROC, DSCRD },
   /* server    */{ DSCRD, DSCRD, DSCRD, DSCRD, DSCRD },
   /* bcast    */{ DSCRD, DSCRD, DSCRD, DSCRD, DSCRD }, unsynchronized */

                else if (r->org != p->xmt)
                        synch = FALSE;  /* bclient */{ DSCRD, DSCRD, DSCRD, DSCRD, PROC}
   }; bogus packet */
        }

        /*
         * Miscellaneous macroni
   *
   * This macro defines Update the authentication state. origin and destination timestamps. If x is 0,
         * authentication is optional, othewise it is required. unsynchronized or bogus, abandon ship.
         */
   #define AUTH(x, y)((x) ? (y) == A_OK : (y) == A_OK || \
      (y) == A_NONE)
        p->org = r->xmt;
        p->rec = r->dst;
        if (!synch)
                return;                 /*
   * These are used by the clear() routine unsynch */
   #define BEGIN_CLEAR(p)   ((char *)&((p)->begin_clear))
   #define END_CLEAR(p)   ((char *)&((p)->end_clear))
   #define LEN_CLEAR (END_CLEAR ((struct p *)0) - \
      BEGIN_CLEAR((struct p *)0))

A.5.1.  receive()

        /*
         * receive() - receive packet The timestamps are valid and decode modes
   */
   void
   receive(
   struct r *r   /* the receive packet pointer 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) {
   struct p *p;   /* peer structure pointer
   int   auth;   /* authentication code */
   int   has_mac;
                clear(p, X_CRYPTO);
                return;                 /* size of MAC crypto-NAK */
   int   synch;
        }

        /* synchronized switch
         * 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.
         */
   int   auth;
        if (!AUTH(p->keyid || (p->flags & P_NOTRUST), auth))
                return;                 /* authentication code bad auth */

        /*
         * Check access control lists. The intent here is Everything possible has been done to implement a validate the timestamps
         * whitelist of those IP addresses specifically accepted and/or and prevent bad guys from disrupting the protocol or
         * a blacklist of those IP addresses specifically rejected. injecting bogus data. Earn some revenue.
         */
        packet(p, r);
}

A.5.1.1.  packet()

/*
 * There could be different lists for authenticated clients packet() - process packet and compute offset, delay and
 * unauthenticated clients. dispersion.
 */
   if (!access(r))
   return;
void
packet(
        struct p *p,            /* access denied peer structure pointer */
        struct r *r             /*
   * The version must not be in the future. Format checks include
   * receive packet length, MAC length and extension field lengths, if
   * present. pointer */
   if (r->version > VERSION
        )
{
        double  offset;         /* or format error */)
   return; sample offsset */
        double  delay;          /* format error sample delay */
        double  disp;           /* sample dispersion */

        /*
         * Authentication is conditioned by two switches which can be
   * specified on a per-client basis.
   *
   * P_NOPEER   do not mobilize an association unless
   *   authenticated
   * P_NOTRUST   do not allow access unless authenticated
   *   (implies P_NOPEER)*
   * There are four outcomes:
   *
   * A_NONE By golly the packet has no MAC
   * A_OK is valid. Light up the packet has a MAC and authentication remaining header
         *   succeeds fields. Note that we map stratum 0 (unspecified) to MAXSTRAT
         * A_ERROR   the packet has a MAC to make stratum comparisons simpler and authentication fails
   * A_CRYPTO   crypto-NAK. the MAC has four octets only.
   *
   * Note: The AUTH(x, y) macro is used to filter outcomes. If x provide a natural
         * is zero, acceptable outcomes of y are NONE and OK. If x is interface for radio clock drivers that operate for
         * one, the only acceptable outcome of y is OK.  convenience at stratum 0.
         */
   has_mac
        p->leap = r->leap;
        if (r->stratum == 0)
                p->stratum = MAXSTRAT;
        else
                p->stratum = r->stratum;
        p->pmode = r->mode;
        p->ppoll = r->poll;
        p->rootdelay = /* length of MAC field */ 0; if (has_mac == 0) {
   auth FP2D(r->rootdelay);
        p->rootdisp = A_NONE; FP2D(r->rootdisp);
        p->refid = r->refid;
        p->reftime = r->reftime;

        /*
         * Verify the server is synchronized with valid stratum and
         * reference time not required later than the transmit time.
         */
   } else
        if (has_mac == 4) {
   auth (p->leap == A_CRYPTO; NOSYNC || p->stratum >= MAXSTRAT)
                return;                 /* crypto-NAK unsynchronized */
   } else {
   if (r->mac != md5(r->keyid))
   auth = A_ERROR;

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

        poll_update(p, p->hpoll);
        p->reach |= 1;

        /*
         * Find association Calculate offset, delay and dispatch code. If there dispersion, then pass to the
         * clock filter. Note carefully the implied processing. The
         * first-order difference is no done directly in 64-bit arithmetic,
         * association then the result is converted to match, floating double. All further
         * processing is in floating double arithmetic with rounding
         * done by the value of p->mode hardware. This is assumed NULL.
   */
   p = find_assoc(r);
   switch(table[p->mode][r->mode]) {

   /* necessary in order to avoid
         * Client packet. Send server reply (no association). If overflow and preseve precision.
         * authentication fails, send
         * The delay calculation is a crypto-NAK packet.
   */
   case FXMIT:
   if (AUTH(p->flags & P_NOTRUST, auth))
      fast_xmit(r, M_SERV, auth);
   else if (auth == A_ERROR)
      fast_xmit(r, M_SERV, A_CRYPTO);
   return;   /* M_SERV packet sent */

   /* special case. In cases where the
         * New symmetric passive server and client (ephemeral association). It is 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,
         * mobilized in the same version as in delay is clamped not less than the packet. If
   * authentication fails, send a crypto-NAK packet. If restrict
   * no-moblize, send a symmetric active packet instead. system precision.
         */
   case NEWPS:
   if (!AUTH(p->flags & P_NOTRUST, auth)) {
        if (auth (p->pmode == A_ERROR)
   fast_xmit(r, M_SACT, A_CRYPTO);
   return;   /* crypto-NAK packet sent */
   }
   if (!AUTH(p->flags & P_NOPEER, auth)) M_BCST) {
      fast_xmit(r, M_SACT, auth);
   return;   /* M_SACT packet sent */
                offset = LFP2D(r->xmt - r->dst);
                delay = BDELAY;
                disp = LOG2D(r->precision) + LOG2D(s.precision) + PHI *
                    2 * BDELAY;
        }
   p else {
                offset = mobilize(r->srcaddr, r->dstaddr, r->version, M_PASV,
      r->keyid, P_EPHEM);
   break;

   /* (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 * New broadcast client (ephemeral association). It is mobilized
                    LFP2D(r->dst - r->org);
        }
        clock_filter(p, offset, delay, disp);
}

A.5.2.  clock_filter()

/*
 * in clock_filter(p, offset, delay, dispersion) - select the same version as in best from the packet. If authentication
 * error, ignore the packet.
   */
   case NEWBC:
   if (!AUTH(p->flags & (P_NOTRUST | P_NOPEER), auth))
   return;   /* authentication error */

   if (!(s.flags & S_BCSTENAB))
   return;   /* broadcast not enabled latest eight delay/offset samples.
 */
void
clock_filter(
        struct p = mobilize(r->srcaddr, r->dstaddr, r->version, M_BCLN,
      r->keyid, P_EPHEM);
   break;   /* processing continues */

   /*
   * Process packet. Placeholdler only.
   */
   case PROC:
   break; *p,            /* processing continues peer structure pointer */
        double  offset,         /*
   * Invalid mode combination. We get here only in case of
   * ephemeral associations, so the correct action is simply to
   * toss it. clock offset */
   case ERR:
   clear(p, X_ERROR);
   return;
        double  delay,          /* invalid mode combination roundtrip delay */
        double  disp            /*
   * No match; just discard the packet. dispersion */
   case DSCRD:
   return;
        )
{
        struct f f[NSTAGE];     /* orphan abandoned sorted list */
   }
        double  dtemp;
        int     i;

        /*
         * Next comes a rigorous schedule The clock filter contents consist of timestamp checking. If eight tuples (offset,
         * delay, dispersion, time). Shift each tuple to the left,
         * transmit timestamp is zero, discarding the server leftmost one. As each tuple is horribly broken.
   */
   if (r->xmt == 0)
   return;   /* invalid timestamp */

   /* shifted,
         * If increase the transmit timestamp duplicates a previous one, dispersion since the last filter update. At the
         * packet is a replay.
   */
   if (r->xmt == p->xmt)
   return;   /* duplicate packet */

   /*
   * If this is same time, copy each tuple to a broadcast mode packet, skip further checking. temporary list. After this,
         * If the origin timestamp is zero, place the sender has not yet heard
   * from us. Otherwise, if (offset, delay, disp, time) in the origin timestamp does not match vacated
         * the transmit timestamp, the packet is bogus. rightmost tuple.
         */
   synch
        for (i = TRUE;
   if (r->mode != M_BCST) 1; i < NSTAGE; i++) {
      if (r->org == 0)
   synch
                p->f[i] = FALSE;/* unsynchronized */

   else if (r->org != p->xmt)
   synch p->f[i - 1];
                p->f[i].disp += PHI * (c.t - p->t);
                f[i] = FALSE;/* bogus packet */ p->f[i];
        }
        p->f[0].t = c.t;
        p->f[0].offset = offset;
        p->f[0].delay = delay;
        p->f[0].disp = disp;
        f[0] = p->f[0];

        /*
         * Update Sort the origin and destination timestamps. If temporary list of tuples by increasing f[].delay.
         * The first entry on the sorted list represents the best
         * unsynchronized or bogus, abandon ship. sample, but it might be old.
         */
   p->org
        dtemp = r->xmt;
   p->rec p->offset;
        p->offset = r->dst;
   if (!synch)
   return;   /* unsynch */ f[0].offset;
        p->delay = f[0].delay;
        for (i = 0; i < NSTAGE; i++) {
                p->disp += f[i].disp / (2 ^ (i + 1));
                p->jitter += SQUARE(f[i].offset - f[0].offset);
        }
        p->jitter = max(SQRT(p->jitter), LOG2D(s.precision));

        /*
         * The timestamps are valid Prime directive: use a sample only once and the receive packet matches the
   * last one sent. If the packet is never a crypto-NAK, the server sample
         * might have just changed keys. We demobilize older than the association latest one, but anything goes before first
         * and wait for better times. synchronized.
         */
        if (auth == A_CRYPTO) {
      clear(p, X_CRYPTO); (f[0].t - p->t <= 0 && s.leap != NOSYNC)
                return;

        /* crypto-NAK */
   }

   /*
         * If Popcorn spike suppressor. Compare the association is authenticated, difference between the key ID is nonzero
         * last and received packets must be authenticated. This is designed
   * current offsets to avoid a bait-and-switch attack, which was possible in past the current jitter. If greater
         * versions.
   */ than SGATE (3) and if (!AUTH(p->keyid || (p->flags & P_NOTRUST), auth))
   return;   /* bad auth */

   /* the interval since the last offset is
         * Everything possible has been done to validate less than twice the timestamps system poll interval, dump the spike.
         * Otherwise, and prevent bad guys from disrupting if not in a burst, shake out the protocol or
   * injecting bogus data. Earn some revenue. truechimers.
         */
   packet(p, r);
        if (fabs(p->offset - dtemp) > SGATE * p->jitter && (f[0].t -
            p->t) < 2 * s.poll)
                return;

        p->t = f[0].t;
        if (p->burst == 0)
                clock_select();
        return;
}

/*
 * find_assoc() root_dist() - find a matching association calculate root distance
 */
double
root_dist(
        struct p *p             /* peer structure pointer or NULL */
   *find_assoc(
   struct r *r   /* receive packet pointer */
        )
{
   struct p *p;   /* dummy peer structure pointer */
        /*
         * Search association table for matching source The root synchronization distance is the maximum error due to
         * address and  source port.
   */
   while (/* all associations causes of the local clock relative to the primary server.
         * It is defined as half the total delay plus total dispersion
         * plus peer jitter.
         */ 0) {
   if (r->srcaddr == p->srcaddr && r->port == p->port)
      return(p);
   }
        return (NULL); (max(MINDISP, p->rootdelay + p->delay) / 2 +
            p->rootdisp + p->disp + PHI * (c.t - p->t) + p->jitter);
}

A.5.2.  packet()

/*
 * packet() fit() - process packet and compute offset, delay and
   * dispersion. test if association p is acceptable for synchronization
 */
   void
   packet(
int
fit(
        struct p *p, *p             /* peer structure pointer */
   struct r *r   /* receive packet pointer */
        )
{
   double   offset;   /* sample offsset */
   double   delay;   /* sample delay */
   double   disp;   /* sample dispersion */
        /*
         * By golly the packet is valid. Light up the remaining header
   * fields. Note that we map stratum 0 (unspecified) to MAXSTRAT
   * to make stratum comparisons simpler and to provide a natural
   * interface for radio clock drivers that operate for
   * convenience at A stratum 0.
   */
   p->leap = r->leap; error occurs if (r->stratum == 0)
      p->stratum = MAXSTRAT; else
   p->stratum = r->stratum; p->mode = r->mode;
   p->ppoll = r->poll;
   p->rootdelay = FP2D(r->rootdelay); p->rootdisp = FP2D(r->rootdisp);
   p->refid = r->refid;
   p->reftime = r->reftime;

   /* (1) the server has never been
         * Verify synchronized, (2) the server is synchronized with valid stratum and
   * reference time not later than the transmit time. is invalid.
         */
        if (p->leap == NOSYNC || p->stratum >= MAXSTRAT)
   return;   /* unsynchronized */
                return (FALSE);

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

   poll_update(p, p->hpoll);
   p->reach |= 1;

   /*
   * Calculate offset, delay and dispersion, then pass to the
   * clock filter. Note carefully root distance exceeds the implied processing. The
   * first-order difference is done directly in 64-bit arithmetic,
         * then the result is converted distance threshold plus an increment equal to floating double. All further one poll
         * processing is in floating double arithmetic with rounding interval.
         */
        if (root_dist(p) > MAXDIST + PHI * done by LOG2D(s.poll))
                return (FALSE);

        /*
         * A loop error occurs if the hardware. This remote peer is necessary in order synchronized to avoid
   * overflow and preseve 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, local peer or the delay can appear negative. In
   * order remote peer is synchronized to avoid violating the Principle of Least Astonishment, current
         * the delay is clamped not less than the system precision.
   */
   if (p->mode == 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 peer. Note this is the behavior for IPv4; for IPv6 the
         *
      LFP2D(r->dst - r->org);
   }
   clock_filter(p, offset, delay, disp); MD5 hash is used instead.
         */
        if (p->refid == p->dstaddr || p->refid == s.refid)
                return (FALSE);

        /*
         * An unreachable error occurs if the server is unreachable.
         */
        if (p->reach == 0)
                return (FALSE);

        return (TRUE);
}

A.5.3.  clock_filter()

/*
 * clock_filter(p, offset, delay, dispersion) clear() - select the best from the reinitialize for persistent association, demobilize
 * latest eight delay/offset samples. for ephemeral association.
 */
void
 clock_filter(
clear(
        struct p *p,            /* peer structure pointer */
 double   offset,   /* clock offset */
 double   delay,   /* roundtrip delay */
 double   disp
        int     kiss            /* dispersion kiss code */
        )
{
 struct f f[NSTAGE];/* sorted list */
 double   dtemp;
        int i;

        /*
         * The clock filter contents consist of eight tuples (offset,
 * delay, dispersion, time). Shift each tuple first thing to do is return all resources to the left, bank.
         * discarding the leftmost one. As each tuple is shifted, Typical resources are not detailed here, but they include
         * increase the dispersion since the last filter update. At the dynamically allocated structures for keys, certificates, etc.
         * same time, copy each tuple to a temporary list. After this, If an ephemeral association and not initialization, return
         * place the (offset, delay, disp, time) in the vacated
 * rightmost tuple. association memory as well.
         */
 for (i = 1; i < NSTAGE; i++) {
    p->f[i] = p->f[i - 1];
 p->f[i].disp += PHI * (c.t - p->t); f[i] = p->f[i];
 }
 p->f[0].t = c.t;
 p->f[0].offset = offset;
 p->f[0].delay = delay;
 p->f[0].disp = disp;
 f[0]
        /* return resources */
        if (s.p == p)
                s.p = p->f[0]; NULL;
        if (kiss != X_INIT && (p->flags & P_EPHEM)) {
                free(p);
                return;
        }

        /*
         * Sort the temporary list of tuples by increasing f[].delay.
 * The first entry on the sorted list represents Initialize the best
 * sample, but it might be old. association fields for general reset.
         */
 dtemp
        memset(BEGIN_CLEAR(p), LEN_CLEAR, 0);
        p->leap = p->offset;
 p->offset NOSYNC;
        p->stratum = f[0].offset;
 p->delay MAXSTRAT;
        p->ppoll = f[0].delay; MAXPOLL;
        p->hpoll = MINPOLL;
        p->disp = MAXDISP;
        p->jitter = LOG2D(s.precision);
        p->refid = kiss;
        for (i = 0; i < NSTAGE; i++) {
    p->disp += f[i].disp / (2 ^ (i + 1));
    p->jitter += SQUARE(f[i].offset - f[0].offset);
  }
 p->jitter
                p->f[i].disp = max(SQRT(p->jitter), LOG2D(s.precision)); MAXDISP;

        /*
         * Prime directive: use a sample only once and never a sample
 * older than Randomize the latest one, but anything goes before first
 * synchronized.
 */
 if (f[0].t - p->t <= 0 && s.leap != NOSYNC)
    return;

 /*
 * Popcorn spike suppressor. Compare the difference between the
 * last and current offsets to the current jitter. If greater
 * than SGATE (3) and if the interval since the last offset is
 * less than twice the system poll interval, dump the spike.
 * Otherwise, and if not just in case thousands of broadcast
         * clients have just been stirred up after a burst, shake out long absence of the truechimers.
 */
 if (fabs(p->offset - dtemp) > SGATE * p->jitter && (f[0].t
    p->t) < 2
         * s.poll)
 return; broadcast server.
         */
        p->outdate = p->t = f[0].t;
 if (p->burst == 0)
    clock_select();
 return; c.t;
        p->nextdate = p->outdate + (random() & ((1 << MINPOLL) - 1));
}

A.5.4.

A.5.3.  fast_xmit()

/*
 * fast_xmit() - transmit a reply packet for receive packet r
 */
void
fast_xmit(
        struct r *r,            /* receive packet pointer */
        int     mode,           /* association mode */
        int     auth            /* authentication code */
        )
{
        struct x x;

        /*
         * Initialize header and transmit timestamp. Note that the
         * transmit version is copied from the receive version. This is
         * for backward compatibility.
         */
        x.version = r->version;
        x.srcaddr = r->dstaddr;
        x.dstaddr = r->srcaddr;
        x.leap = s.leap;
        x.mode = mode;
        if (s.stratum == MAXSTRAT)
                x.stratum = 0;
        else
                x.stratum = s.stratum;
        x.poll = r->poll;
        x.precision = s.precision;
        x.rootdelay = D2FP(s.rootdelay);
        x.rootdisp = D2FP(s.rootdisp);
        x.refid = s.refid;
        x.reftime = s.reftime;
        x.org = r->xmt;
        x.rec = r->dst;
        x.xmt = get_time();

        /*
         * If the authentication code is A.NONE, include only the
         * header; if A.CRYPTO, send a crypto-NAK; if A.OK, send a valid
         * MAC. Use the key ID in the received packet and the key in the
         * local key cache.
         */
        if (auth != A_NONE) {
                if (auth == A_CRYPTO) {
                        x.keyid = 0;
                } else {
                        x.keyid = r->keyid;
   x.digest
                        x.mac = md5(x.keyid);
                }
        }
        xmit_packet(&x);
}

A.5.5.

A.5.4.  access()

/*
 * access() - determine access restrictions
 */
int
access(
        struct r *r             /* receive packet pointer */
        )
{
        /*
         * The access control list is an ordered set of tuples
         * consisting of an address, mask and restrict word containing
         * defined bits. The list is searched for the first match on the
         * source address (r->srcaddr) and the associated restrict word
         * is returned.
         */
        return (/* access bits */ 0);
}

A.6.

A.5.5.  System Process

   #include "ntp4.h"

A.6.1.

A.5.5.1.  clock_select()

/*
 * clock_select() - find the best clocks
 */
void
clock_select() {
        struct p *p, *osys;     /* peer structure pointers */
        double  low, high;      /* correctness interval extents */
        int     allow, found, chime; /* used by intersecion algorithm */
        int     n, i, j;

        /*
         * We first cull the falsetickers from the server population,
         * leaving only the truechimers. The correctness interval for
         * association p is the interval from offset - root_dist() to
         * offset + root_dist(). The object of the game is to find a
         * majority clique; that is, an intersection of correctness
         * intervals numbering more than half the server population.
         *
         * First construct the chime list of tuples (p, type, edge) as
         * shown below, then sort the list by edge from lowest to
         * highest.
         */
        osys = s.p;
        s.p = NULL;
        n = 0;
        while (accept(p)) (fit(p)) {
                s.m[n].p = p;
                s.m[n].type = +1;
                s.m[n].edge = p->offset + root_dist(p);
                n++;
                s.m[n].p = p;
                s.m[n].type = 0;
                s.m[n].edge = p->offset;
                n++;
                s.m[n].p = p;
                s.m[n].type = -1;
                s.m[n].edge = p->offset - root_dist(p);
                n++;
        }

        /*
         * 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++;
                }

                /*
                 * 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
                 * nonempty, declare success.
                 */
                if (found > allow)
                        continue;

                if (high > low)
                        break;
        }

        /*
         * Clustering algorithm. Construct a list of survivors (p,
         * metric) from the chime list, where metric is dominated first
         * by stratum and then by root distance. All other things being
         * equal, this is the order of preference.
         */
   n
        s.n = 0;
        for (i = 0; i < n; i++) {
                if (s.m[i].edge < low || s.m[i].edge > high)
                        continue;

                p = s.m[i].p;
                s.v[n].p = p;
                s.v[n].metric = MAXDIST * p->stratum + root_dist(p);
   n++;
                s.n++;
        }

        /*
         * There must be at least NSANE survivors to satisfy the
         * correctness assertions. Ordinarily, the Byzantine criteria
         * require four, susrvivors, survivors, but for the demonstration here, one
         * is acceptable.
         */
        if (n == (s.n < NSANE)
                return;

        /*
         * For each association p in turn, calculate the selection
         * jitter p->sjitter as the square root of the sum of squares
         * (p->offset - q->offset) over all q associations. The idea is
         * to repeatedly discard the survivor with maximum selection
         * jitter until a termination condition is met.
         */
        while (1) {
                struct p *p, *q, *qmax;/* *qmax; /* peer structure pointers */
                double  max, min, dtemp;

                max = -2e9; min = 2e9;
                for (i = 0; i < n; s.n; i++) {
                        p = s.v[i].p;
                        if (p->jitter < min)
                                min = p->jitter;
                        dtemp = 0;
                        for (j = 0; j < n; j++) {
                                q = s.v[j].p;
                                dtemp += SQUARE(p->offset - q->offset);
                        }
                        dtemp = SQRT(dtemp);
                        if (dtemp > max) {
                                max = dtemp;
                                qmax = q;
                        }
                }

                /*
                 * If the maximum selection jitter is less than the
                 * minimum peer jitter, then tossing out more survivors
                 * will not lower the minimum peer jitter, so we might
                 * as well stop. To make sure a few survivors are left
                 * for the clustering algorithm to chew on, we also stop
                 * if the number of survivors is less than or equal to
                 * NMIN (3).
                 */
                if (max < min || n <= NMIN)
                        break;

                /*
                 * Delete survivor qmax from the list and go around
                 * again.
                 */
   n--;
                s.n--;
        }
        /*
         * Pick the best clock. If the old system peer is on the list
         * and at the same stratum as the first survivor on the list,
         * then don't do a clock hop. Otherwise, select the first
         * survivor on the list as the new system peer.
         */
        if (osys->stratum == s.v[0].p->stratum)
                s.p = osys;
        else
                s.p = s.v[0].p;
        clock_update(s.p);
}

A.6.2.

A.5.5.2.  root_dist()

/*
 * root_dist() - calculate root distance
 */
double
root_dist(
        struct p *p             /* peer structure pointer */
        )
{

        /*
         * The root synchronization distance is the maximum error due to
         * all causes of the local clock relative to the primary server.
         * It is defined as half the total delay plus total dispersion
         * plus peer jitter.
         */
        return (max(MINDISP, p->rootdelay + p->delay) / 2 +
            p->rootdisp + p->disp + PHI * (c.t - p->t) + p->jitter);
}

A.6.3.

A.5.5.3.  accept()

/*
 * accept() - test if association p is acceptable for synchronization
 */
int
accept(
        struct p *p             /* peer structure pointer */
        )
{
        /*
         * A stratum error occurs if (1) the server has never been
         * synchronized, (2) the server stratum is invalid.
         */
        if (p->leap == NOSYNC || p->stratum >= MAXSTRAT)
                return (FALSE);

        /*
         * A distance error occurs if the root distance exceeds the
         * distance threshold plus an increment equal to one poll
         * interval.
         */
        if (root_dist(p) > MAXDIST + PHI * LOG2D(s.poll))
                return (FALSE);

        /*
         * A loop error occurs if the remote peer is synchronized to the
         * local peer or the remote peer is synchronized to the current
         * system peer. Note this is the behavior for IPv4; for IPv6 the
         * MD5 hash is used instead.
         */
        if (p->refid == p->dstaddr || p->refid == s.refid)
                return (FALSE);

        /*
         * An unreachable error occurs if the server is unreachable.
         */
        if (p->reach == 0)
                return (FALSE);

        return (TRUE);
}

A.6.4.

A.5.5.4.  clock_update()

/*
 * clock_update() - update the system clock
 */

void
clock_update(
        struct p *p             /* peer structure pointer */
        )
{
        double dtemp;

        /*
         * If this is an old update, for instance as the result of a
         * system peer change, avoid it. We never use an old sample or
         * the same sample twice.
         *
        if (s.t >= p->t)
                return;

        /*
         * Combine the survivor offsets and update the system clock; the
         * local_clock() routine will tell us the good or bad news.
         */
        s.t = p->t;
        clock_combine();
        switch (local_clock(p, s.offset)) {

        /*
         * The offset is too large and probably bogus. Complain to the
         * system log and order the operator to set the clock manually
         * within PANIC range. An The reference implementation MAY include includes a
         * command line option to disable this check and to change the
         * panic threshold from the default 1000 s as required.
         */
        case PANIC:
                exit (0);

        /*
         * The offset is more than the step threshold (0.125 s by
         * default). After a step, all associations now have
         * inconsistent time valurs, so they are reset and started
         * fresh. The step threshold MAY can be changed in an the reference
         * implementation in order to lessen the chance the clock might
         * be stepped backwards. However, there may be serious
         * consequences. consequences, as noted in the white papers at the NTP project
         * site.
         */
        case STEP:
                while (/* all associations */ 0)
                        clear(p, X_STEP);
                s.stratum = MAXSTRAT;
                s.poll = MINPOLL;
                break;

        /*
         * The offset was less than the step threshold, which is the
         * normal case. Update the system variables from the peer
         * variables. The lower clamp on the dispersion increase is to
         * avoid timing loops and clockhopping when highly precise
         * sources are in play. The clamp MAY can be changed from the
         * suggested default of .01 s. s in the reference implementation.
         */
        case SLEW:
                s.leap = p->leap;
                s.stratum = p->stratum + 1;
                s.refid = p->refid;
                s.reftime = p->reftime;
                s.rootdelay = p->rootdelay + p->delay;
                dtemp = SQRT(SQUARE(p->jitter) + SQUARE(s.jitter));
                dtemp += max(p->disp + PHI * (c.t - p->t) +
                    fabs(p->offset), MINDISP);
                s.rootdisp = p->rootdisp + dtemp;
                break;

        /*
         * Some samples are discarded while, for instance, a direct
         * frequency measurement is being made.
         */
        case IGNORE:
                break;
        }
}

A.6.5.

A.5.5.5.  clock_combine()

/*
 * clock_combine() - combine offsets
 */
void
clock_combine()
{
        struct p *p;/* *p;            /* peer structure pointer */
        double x, y, z, w;
        int     i;

        /*
         * Combine the offsets of the clustering algorithm survivors
         * using a weighted average with weight determined by the root
         * distance. Compute the selection jitter as the weighted RMS
         * difference between the first survivor and the remaining
         * survivors. In some cases the inherent clock jitter can be
         * reduced by not using this algorithm, especially when frequent
         * clockhopping is involved. The reference implementation can be
         * configured to avoid this algorithm by designating a preferred
         * peer.
         */
        y = z = w = 0;
        for (i = 0; s.v[i].p != NULL; i++) {
                p = s.v[i].p;
                x = root_dist(p);
                y += 1 / x;
                z += p->offset / x;
                w += SQUARE(p->offset - s.v[0].p->offset) / x;
        }
        s.offset = z / y;
        s.jitter = SQRT(w / y);
}

A.6.6.

A.5.5.6.  local_clock()

   #include "ntp4.h"

/*
 * Constants Clock discipoine parameters and constants
 */
#define STEPT.128/* STEPT           .128    /* step threshold (s) */
#define WATCH900/* WATCH           900     /* stepout threshold (s) */
#define PANICT1000/* PANICT          1000    /* panic threshold (s) */
#define PLL65536/* PLL             65536   /* PLL loop gain */
#define FLLMAXPOLL FLL             MAXPOLL + 1/* 1 /* FLL loop gain */
#define AVG 4/*             4       /* parameter averaging constant */
#define ALLAN1500/* ALLAN           1500    /* compromise Allan intercept (s) */
#define LIMIT           30      /* poll-adjust threshold */

#define MAXFREQ         500e-6  /* maximum frequency tolerance (s/s) (500 PPM) */
#define PGATE           4       /* poll-adjust gate */

/*
 * local_clock() - discipline the local clock
 */
int                             /* return code */
local_clock(
        struct p *p,            /* peer structure pointer */
        double  offset          /* clock offset from combine() */
        )
{
        int     state;          /* clock discipline state */
        double  freq;           /* frequency */
        double  mu;             /* interval since last update */
        int     rval;
        double  etemp, dtemp;

        /*
         * If the offset is too large, give up and go home.
         */
        if (fabs(offset) > PANICT)
                return (PANIC);

        /*
         * Clock state machine transition function. This is where the
         * action is and defines how the system reacts to large time
         * and frequency errors. There are two main regimes: when the
         * offset exceeds the step threshold and when it does not.
         */
        rval = SLEW;
        mu = p->t - s.t;
        freq = 0;
        if (fabs(offset) > STEPT) {
                switch (c.state) {

                /*
                 * In S_SYNC state we ignore the first outlyer amd
                 * switch to S_SPIK state.
                 */
                case SYNC:
                        state = SPIK;
                        return (rval);

                /*
                 * In S_FREQ state we ignore outlyers and inlyers. At
                 * the first outlyer after the stepout threshold,
                 * compute the apparent frequency correction and step
                 * the time.
                 */
                case FREQ:
                        if (mu < WATCH)
                                return (IGNORE);

                        freq = (offset - c.base - c.offset) / mu;
                        /* fall through to S_SPIK */

                /*
                 * In S_SPIK state we ignore succeeding outlyers until
                 * either an inlyer is found or the stepout threshold is
                 * exceeded.
                 */
                case SPIK:
                        if (mu < WATCH)
                                return (IGNORE);

                        /* fall through to default */

                /*
                 * We get here by default in S_NSET and S_FSET states
                 * and from above in S_FREQ state. Step the time and
                 * clamp down the poll interval.
                 *
                 * In S_NSET state an initial frequency correction is
                 * not available, usually because the frequency file has
                 * not yet been written. Since the time is outside the
                 * capture range, the clock is stepped. The frequency
                 * will be set directly following the stepout interval.
                 *
                 * In S_FSET state the initial frequency has been set
                 * from the frequency file. Since the time is outside
                 * the capture range, the clock is stepped immediately,
                 * rather than after the stepout interval. Guys get
                 * nervous if it takes 17 minutes to set the clock for
                 * the first time.
                 *
                 * In S_SPIK state the stepout threshold has expired and
                 * the phase is still above the step threshold. Note
                 * that a single spike greater than the step threshold
                 * is always suppressed, even at the longer poll
                 * intervals.
                 */
                default:

                        /*
                         * This is the kernel set time function, usually
                         * implemented by the Unix settimeofday() system
                         * call.
                         */
                        step_time(offset);
                        c.count = 0;
                        s.poll = MINPOLL;
                        rval = STEP;
                        if (state == NSET) {
                                rstclock(FREQ, p->t, 0);
                                return (rval);
                        }
                        break;
                }
                rstclock(SYNC, p->t, 0);
        } else {

                /*
                 * Compute the clock jitter as the RMS of exponentially
                 * weighted offset differences. This is used by the
                 * poll-adjust code.
                 */
                etemp = SQUARE(c.jitter);
                dtemp = SQUARE(max(fabs(offset - c.last),
                    LOG2D(s.precision)));
                c.jitter = SQRT(etemp + (dtemp - etemp) / AVG);
                switch (c.state) {

                /*
                 * In S_NSET state this is the first update received and
                 * the frequency has not been initialized. The first
                 * thing to do is directly measure the oscillator
                 * frequency.
                 */
                case NSET:
   c.offset = offset;
                        rstclock(FREQ, p->t, offset);
                        return (IGNORE);

                /*
                 * In S_FSET state this is the first update and the
                 * frequency has been initialized. Adjust the phase, but
                 * don't adjust the frequency until the next update.
                 */
                case FSET:
   c.offset = offset;
                        rstclock(SYNC, p->t, offset);
                        break;

                /*
                 * In S_FREQ state ignore updates until the stepout
                 * threshold. After that, correct the phase and
                 * frequency and switch to S_SYNC state.
                 */
                case FREQ:
                        if (c.t - s.t < WATCH)
                                return (IGNORE);

                        freq = (offset - c.base - c.offset) / mu;
                        break;

                /*
                 * We get here by default in S_SYNC and S_SPIK states.
                 * Here we compute the frequency update due to PLL and
                 * FLL contributions.
                 */
                default:

                        /*
                         * The FLL and PLL frequency gain constants
                         * depend on the poll interval and Allan
                         * intercept. The FLL is not used below one-half
                         * the Allan intercept. Above that the loop gain
                         * increases in steps to 1 / AVG.
                         */
                        if (LOG2D(s.poll) > ALLAN / 2) {
                                etemp = FLL - s.poll;
                                if (etemp < AVG)
                                        etemp = AVG;
                                freq += (offset - c.offset) / (max(mu,
                                    ALLAN) * etemp);
                        }

                        /*
                         * For the PLL the integration interval
                         * (numerator) is the minimum of the update
                         * interval and poll interval. This allows
                         * oversampling, but not undersampling.
                         */
                        etemp = min(mu, LOG2D(s.poll));
                        dtemp = 4 * PLL * LOG2D(s.poll);
                        freq += offset * etemp / (dtemp * dtemp);
   break;
   }
                        rstclock(SYNC, p->t, offset);
                        break;
                }
        }

        /*
         * Calculate the new frequency and frequency stability (wander).

         * Compute the clock wander as the RMS of exponentially weighted
         * frequency differences. This is not used directly, but can,
         * along withthe jitter, be a highly useful monitoring and
         * debugging tool
         */
        freq += c.freq;
        c.freq = max(min(MAXFREQ, freq), -MAXFREQ);
        etemp = SQUARE(c.wander);
        dtemp = SQUARE(freq);
        c.wander = SQRT(etemp + (dtemp - etemp) / AVG);

        /*
         * Here we adjust the poll interval by comparing the current
         * offset with the clock jitter. If the offset is less than the
         * clock jitter times a constant, then the averaging interval is
         * increased, otherwise it is decreased. A bit of hysteresis
         * helps calm the dance. Works best using burst mode.
         */
        if (fabs(c.offset) < PGATE * c.jitter) {
                c.count += s.poll;
                if (c.count > LIMIT) {
                        c.count = LIMIT;
                        if (s.poll < MAXPOLL) {
                                c.count = 0;
                                s.poll++;
                        }
                }
        } else {
                c.count -= s.poll << 1;
                if (c.count < -LIMIT) {
                        c.count = -LIMIT;
                        if (s.poll > MINPOLL) {
                                c.count = 0;
                                s.poll--;
                        }
                }
        }
        return (rval);
}

A.6.7.

A.5.5.7.  rstclock()

/*
 * rstclock() - clock state machine
 */
void
rstclock(
        int     state,          /* new state */
        double  offset,         /* new offset */
        double  t               /* new update time */
        )
{
        /*
         * Enter new state and set state variables. Note we use the time
         * of the last clock filter sample, which must be earlier than
         * the current time.
         */
        c.state = state;
   c.base = offset - c.offset;
        c.last = c.offset = offset;
        s.t = t;
}

A.7.

A.5.6.  Clock Adjust Process

A.7.1.

A.5.6.1.  clock_adjust()

/*
 * clock_adjust() - runs at one-second intervals
 */
void
clock_adjust() {
        double  dtemp;

        /*
         * Update the process time c.t. Also increase the dispersion
         * since the last update. In contrast to NTPv3, NTPv4 does not
         * declare unsynchronized after one day, since the dispersion
         * threshold serves this function. When the dispersion exceeds
         * MAXDIST (1 s), the server is considered unaccept unfit for
         * synchroniztion.
         */
        c.t++;
        s.rootdisp += PHI;

        /*
         * Implement the phase and frequency adjustments. The gain
         * factor (denominator) is not allowed to increase beyond the
         * Allan intercept. It doesn't make sense to average phase noise
         * beyond this point and it helps to damp residual offset at the
         * longer poll intervals.
         */
        dtemp = c.offset / (PLL * min(LOG2D(s.poll), ALLAN));
        c.offset -= dtemp;

        /*
         * This is the kernel adjust time function, usually implemented
         * by the Unix adjtime() system call.
         */
        adjust_time(c.freq + dtemp);

        /*
         * Peer timer. Call the poll() routine when the poll timer
         * expires.
         */
        while (/* all associations */ 0) {
                struct p *p;/* *p;    /* dummy peer structure pointer */

                if (c.t >= p->next) p->nextdate)
                        poll(p);
        }

        /*
         * Once per hour write the clock frequency to a file
         */
        if (c.t % 3600 == 3599)
                /* write c.freq to file */ 0;
}

A.8.

A.5.7.  Poll Process

   #include "ntp4.h"

   /*
    * Constants Poll process parameters and constants
    */
   #define UNREACH         12      /* unreach counter threshold */
   #define BCOUNT          8       /* packets in a burst */
   #define BTIME           2       /* burst interval (s) */

A.8.1.

A.5.7.1.  poll()

/*
 * poll() - determine when to send a packet for association p->
 */
void
poll(
        struct p *p             /* peer structure pointer */
        )

{
        int     hpoll;
        int     oreach;

        /*
         * This routine is called when the current time c.t catches up
         * to the next poll time p->next. p->nextdate. The value p->last p->outdate is
         * the last time this routine was executed. The poll_update()
         * routine determines the next execution time p->next. p->nextdate.
         *
         * If broadcasting, just do it, but only if we are synchronized.
         */
        hpoll = p->hpoll;
        if (p->mode (p->hmode == M_BCST) {
     p->last
                p->outdate = c.t;
                if (s.p != NULL)
                        peer_xmit(p);
                poll_update(p, hpoll);
                return;
        }

        /*
         * If manycasting, start with ttl = 1. The ttl is increased by
         * one for each poll until MAXCLOCK servers have been found or
         * ttl reaches TTLMAX. If reaching MAXCLOCK, stop polling until
         * the number of servers falls below MINCLOCK, then start all
         * over.
         */
        if (p->hmode == M_CLNT && p->flags & P_MANY) {
                p->outdate = c.t;
                if (p->unreach > BEACON) {
                        p->unreach = 0;
                        p->ttl = 1;
                        peer_xmit(p);
                } else if (s.n < MINCLOCK) {
                        if (p->ttl < TTLMAX)
                                p->ttl++;
                        peer_xmit(p);
                }
                p->unreach++;
                poll_update(p, hpoll);
                return;
        }
        if (p->burst == 0) {

                /*
                 * We are not in a burst. Shift the reachability
                 * register to the left. Hopefully, some time before the
                 * next poll a packet will arrive and set the rightmost
                 * bit.
                 */
   p->last = c.t;
                oreach = p->reach;
                p->outdate = c.t;
                p->reach << 1;
                if (!(p->reach & 0x7))
                        clock_filter(p, 0, 0, MAXDISP);
                if (!p->reach) {

                        /*
                         * The server is unreachable, so bump the
                         * unreach counter. If the unreach threshold has
                         * been reached, double the poll interval to
                         * minimize wasted network traffic. Send a burst
                         * only if enabled and the unreach threshold has
                         * not been reached.
                         */
                        if (p->flags & P_IBURST && p->unreach == 0) {
                                p->burst = BCOUNT;
                        } else if (p->unreach < UNREACH)
                                p->unreach++;
                        else
                                hpoll++;
                        p->unreach++;
                } else {

                        /*
                         * The server is reachable. However, if has not
   * been heard for three consecutive Set the poll
                         * intervals, stuff the clock register interval to
   * increase the peer dispersion. This makes old system poll interval. Send a
                         * servers less desirable burst only if enabled and eventually boots
   * them off the island. peer is fit.
                         */
                        p->unreach = 0;
   if (!(p->reach & 0x7))
   clock_filter(p, 0, 0, MAXDISP);
                        hpoll = s.poll;
                        if (p->flags & P_BURST && accept(p)) fit(p))
                                p->burst = BCOUNT;
                }
        } else {

                /*
                 * If in a burst, count it down. When the reply comes
                 * back the clock_filter() routine will call
                 * clock_select() to process the results of the burst.
                 */
                p->burst--;
        }

        /*
         * Do not transmit if in broadcast client mode.
         */
        if (p->mode (p->hmode != M_BCLN)
                peer_xmit(p);
        poll_update(p, hpoll);
}

A.8.2.

A.5.7.2.  poll_update()

/*
 * poll_update() - update the poll interval for association p
 *
 * Note: This routine is called by both the packet() and poll() routine.
 * Since the packet() routine is executed when a network packet arrives
 * and the poll() routine is executed as the result of timeout, a
 * potential race can occur, possibly causing an incorrect interval for
 * the next poll. This is considered so unlikely as to be negligible.
 */
void
poll_update(
        struct p *p,            /* peer structure pointer */
        int  hpoll     poll            /* poll interval (log2 s) */
        )
{
 int  poll;
        /*
         * This routine is called by both the poll() and packet()
         * routines to determine the next poll time. If within a burst
         * the poll interval is two seconds. Otherwise, it is the
         * minimum of the host poll interval and peer poll interval, but
         * not greater than MAXPOLL and not less than MINPOLL. The
         * design insures that a longer interval can be preempted by a
         * shorter one if required for rapid response.
         */
        p->hpoll = min(MAXPOLL, max(MINPOLL, hpoll)); max(min(MAXPOLL, poll), MINPOLL);
        if (p->burst != > 0) {
 if(c.t
                if (p->nextdate != p->next) c.t)
                        return;

 p->next
                else
                        p->nextdate += BTIME;
        } else {
 poll = min(p->hpoll, max(MINPOLL, ppoll));
 }

                /*
                 * While not shown here, an the reference implementation
                 * SHOULD randomize randonizes the poll interval by a small factor.
                 */
 p->next
                p->nextdate = p->last p->outdate + (1 << poll); max(min(p->ppoll,
                    p->hpoll), MINPOLL));
        }

        /*
         * It might happen that the due time has already passed. If so,
         * make it one second in the future.
         */
        if (p->next (p->nextdate <= c.t)
 p->next
                p->nextdate = c.t + 1;
}

A.8.3.

A.5.7.3.  peer_xmit()

/*
 * transmit() - transmit a packet for association p
 */
void
peer_xmit(
        struct p *p/* *p             /* peer structure pointer */
        )
{
        struct x x;/* x;             /* transmit packet */

        /*
         * Initialize header and transmit timestamp
         */
        x.srcaddr = p->dstaddr;
        x.dstaddr = p->srcaddr;
        x.leap = s.leap;
        x.version = VERSION; p->version;
        x.mode = p->mode; p->hmode;
        if (s.stratum == MAXSTRAT)
                x.stratum = 0;
        else
                x.stratum = s.stratum;
        x.poll = p->hpoll;
        x.precision = s.precision;
        x.rootdelay = D2FP(s.rootdelay);
        x.rootdisp = D2FP(s.rootdisp);
        x.refid = s.refid;
        x.reftime = s.reftime;
        x.org = p->org;
        x.rec = p->rec;
        x.xmt = get_time();
        p->xmt = x.xmt;

        /*
         * If the key ID is nonzero, send a valid MAC using the key ID
         * of the association and the key in the local key cache. If
         * something breaks, like a missing trusted key, don't send the
         * packet; just reset the association and stop until the problem
         * is fixed.
         */
        if (p->keyid)
                if (/* p->keyid invalid */ 0) {
                        clear(p, X_NKEY);
                        return;
                }
      x.digest
                x.mac = md5(p->keyid);
        xmit_packet(&x);
}

Authors' Addresses

   Jack Burbank (editor)
   The Johns Hopkins University Applied Physics Laboratory
   11100 Johns Hopkins Road
   Laurel, MD  20723-6099
   US

   Phone: +1 443 778 7127
   Email: jack.burbank@jhuapl.edu

   William Kasch (editor)
   The Johns Hopkins University Applied Physics Laboratory
   11100 Johns Hopkins Road
   Laurel, MD  20723-6099
   US

   Phone: +1 443 778 7463
   Email: william.kasch@jhuapl.edu

   Jim Martin (editor)
   Netzwert AG
   An den Treptowers 1
   Berlin  12435
   Germany
   The Daedelus Group
   721 Alameda de las Pulgas
   Belmont, CA  94002
   US

   Phone: +49.30/5 900 80-1180 +1 408 799-2788
   Email: jim@netzwert.ag jim@daedelus.com

   Dr. David L. Mills
   University of Delaware
   Newark, DE  19716
   US

   Phone: +1 302 831 8247
   Email: mills@udel.edu

Full Copyright Statement

   Copyright (C) The IETF Trust (2007).

   This document is subject to the rights, licenses and restrictions
   contained in BCP 78, and except as set forth therein, the authors
   retain all their rights.

   This document and the information contained herein are provided on an
   "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
   OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
   THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
   THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
   WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.

Intellectual Property

   The IETF takes no position regarding the validity or scope of any
   Intellectual Property Rights or other rights that might be claimed to
   pertain to the implementation or use of the technology described in
   this document or the extent to which any license under such rights
   might or might not be available; nor does it represent that it has
   made any independent effort to identify any such rights.  Information
   on the procedures with respect to rights in RFC documents can be
   found in BCP 78 and BCP 79.

   Copies of IPR disclosures made to the IETF Secretariat and any
   assurances of licenses to be made available, or the result of an
   attempt made to obtain a general license or permission for the use of
   such proprietary rights by implementers or users of this
   specification can be obtained from the IETF on-line IPR repository at
   http://www.ietf.org/ipr.

   The IETF invites any interested party to bring to its attention any
   copyrights, patents or patent applications, or other proprietary
   rights that may cover technology that may be required to implement
   this standard.  Please address the information to the IETF at
   ietf-ipr@ietf.org.

Acknowledgment

   Funding for the RFC Editor function is provided by the IETF
   Administrative Support Activity (IASA).