RFC 1165

Network Time Protocol (NTP) over the OSI Remote Operations Service

πŸ“… published June 1990, from ietf

Network Time Protocol (NTP) over the OSI Remote Operations Service β°πŸ’…

okay bestie, welcome to RFC 1165, the one where NTP gets a glow-up and moves into the OSI world πŸ¦‹

πŸ“‹ the title block tea β˜• It's written by J. Crowcroft (UCL) and J. Onions (Nottingham University), in the Network Working Group, and it's dated June 1990. The category is Experimental, and the title block doesn't list anything it obsoletes or updates 🌸

Status of This Memo πŸ“œ

this memo suggests an Experimental Protocol for the OSI and Internet communities πŸ§ͺ hosts in either community, especially those in both, are encouraged to experiment with this mechanism 🫢 for the standardization state and status of this protocol, check the current edition of the "IAB Official Protocol Standards" πŸ“š distribution of this memo is unlimited 🌈

Table of Contents πŸ—‚οΈ

   1. Introduction...........................................    1
   1.1 Motivation............................................    1
   2. Protocol Overview......................................    2
   3. Operation of the Protocol..............................    3
   4. Network Considerations.................................    4
   5. Implementation Model...................................    4
   6. Constructing NTP Data Fields...........................    4
   7. Discussion.............................................    4
   8. Prototype Experience...................................    5
   9. References.............................................    5
   10. Acknowledgements......................................    6
   Appendix A. NTP Remote Operations Service Specification...    6
   11. Security Considerations...............................    9
   12. Authors' Addresses....................................    9

1. Introduction πŸŽ€

okay so this doc describes the Remote Operations and Abstract Syntax for running NTP (the clock-syncing protocol πŸ•°οΈ) over an ISO OSI stack ✨

NTP itself is documented in great detail in RFC 1119, so go check that out too πŸ“–

1.1. Motivation πŸ’­

the motivation for a Remote Operations Service version of NTP is fourfold, because we love a good list πŸ’…

  1. The inclusion of a useful service to an OSI environment.
  2. The feasibility of automatically checking a ROS/ASN.1 specification, and automatically generating code to implement the protocol.
  3. The feasibility of running NTP on connection oriented network services (CONS or X.25), and consequentially, the ability to use connection success or failure to optimise reachability discovery.
  4. The generalisation of the last point: the use of ROS makes NTP independent of the underlying communications architecture.

the need for time sync is so clear, and RFC 1119 already lists a few of the key uses ⏱️ but OSI apps are super in need of this too, and not just locally. across the wide area as well 🌍 like, a ton of the strong authentication in X.511 is built on encrypted packets with timestamps that say how long the packet is valid for πŸ” if two hosts have clocks that aren't closely synchronised, the host with the faster clock is more prone to cryptographic attacks from the slower one (rude πŸ’€), and the slower host might find it's "unauthentable" 😭

a similar problem happens with the X.500 directory and the service control that limits how much time a search is allowed to take ⏳

authentication between NTP peers, and between clients and servers, isn't addressed here, because the choice of mechanism is still being debated πŸ€·β€β™€οΈ

2. Protocol Overview πŸ—ΊοΈ

the NTP app functions exactly as in RFC 1119 πŸ™Œ with remote operations and the underlying Application support, for NTP daemons to peer with one another, they send an A-ASSOCIATE.REQUEST and receive an A-ASSOCIATE.INDICATION 🀝

once the association succeeds, they periodically invoke the appropriate Remote Operation with the appropriate parameters at the appropriate frequency πŸ” if it fails, they mark the peer as unreachable 🚫

the states an NTP daemon records for each peer are enhanced from RFC 1119 to include:

  • Connected: this means the host is connected with its peer and synchronisation data is being exchanged 🀝
  • Connecting: this state means a connection is in progress. hosts far away may take several seconds to connect, and that blocking can mess with the data exchange with other hosts, so the connection is made asynchronously 🐒
  • Accepting: this state means a connection is being accepted from another host, but the negotiation of the transport session etc hasn't been finished yet. this is another asynchronous part 🧩
  • Disconnected: this state is reached if the remote host can't be contacted πŸ“΅

3. Operation of the Protocol βš™οΈ

okay so a connection-oriented service changes how the NTP algorithm works a little ✨ this comes partly from some necessary adjustments to the protocol, and partly from optimisations that connections make possible πŸ”“

first up, the reachability of the host can be determined directly 🎯 NTP keeps a shift register to figure out if a peer is still responding and exchanging data. it works by recording how many responses have come back over the last eight transfers. if there have been no responses to the last eight packets, the host is deemed unreachable πŸͺ¦

with a connection to the remote host, reachability is immediately determinable. either a connection is established, or it's broken or not yet made. so there's no need to rely on the shift register for this πŸ™…β€β™€οΈ

second, connection-oriented mode unlocks a bunch of optimisations πŸ”₯ the NTP packet format can be broken into three categories:

  • a) Synchronisation data
  • b) Authentication data
  • c) Protocol data

of these, only the first (a) is needed to keep hosts synchronised 🫢 info like protocol version and the precision of the local clock isn't likely to change over the lifetime of the connection 🧊 same goes for authentication: if it's in use, it only needs to happen at connection establishment, and it isn't necessarily required for every packet πŸ”

for these reasons, NTP can be simplified a bit by removing that info. you can see this in the specification for the Packet in Appendix A πŸ“Ž

4. Network Considerations 🌐

ok this one's spicy 🌢️ on first inspection you might think a high speed network is necessary for accurate synchronisation, but nope πŸ™…β€β™€οΈ what matters more is the dispersion of the packet traversal times. it's normally the case that a low speed network with little variance in packet transit times gives better results than a high speed network with big differences between individual packet transit times 🐌

this makes connection-oriented networks, with resource allocation done at connection time, look like they might lead to higher accuracies than connectionless networks, which can suffer large swings in packet transit time under high loading πŸ“ˆ (this is heresy! 😱)

5. Implementation Model πŸ› οΈ

ideally, the implementor will provide interoperability between the existing UDP based NTP service and a ROS based service 🀝

to make that happen, the internal records that hold NTP state information can stay the same as in existing implementations 🧠 and for optimisation reasons, the internal representations of NTP packets can be the same too. translation between these and the appropriate ROS/ASN concrete encodings can be provided by automatic translators such as Rosy [ISODE] πŸͺ„

6. Constructing NTP Data Fields 🧱

the data fields in the Packet described in Appendix A are unchanged from RFC 1119 πŸ’… this simplifies implementations based on existing ones, and encourages interworking 🫢

7. Discussion πŸ’¬

from the limited testing of this model so far, the ROS based model running over an X.25 service seems to be about as reliable as the UDP model πŸ“Š until more experimentation can be done, specific data can't be given yet πŸ§ͺ

however, in the UK, the most common method of time synchronisation is the system administrator's watch plus typing the time in to the nearest minute βŒšπŸ’€ this method is clearly far superior πŸ™ƒ (sarcasm, obviously)

connection management is transparent to NTP, since it's implemented beneath the Remote Operations Service 🫧 however, an NTP implementation does need access to the status of connections. it uses that not only for reachability information, but also to find the information gleaned at connect time that is no longer exchanged in NTP operations πŸ”

8. Prototype Experience πŸ§ͺ

there are a number of UK sites running NTP over ROS over X.25, using an earlier ROS specification πŸ‡¬πŸ‡§ at least one site is peering both over ROS with UK sites on X.25, and over UDP with US Internet sites 🌐

initial experience is promising πŸ₯Ή the table below shows the reachabilities, delays, offsets and dispersions for the central UK site peering with 2 JANET sites (IP addresses not meaningful, but shown as 126.0.0.1 πŸ™ˆ) and three US sites

   Address            Strat Poll Reach    Delay   Offset    Disp
   =============================================================
   +126.0.0.1            3   64  377     718.0      0.0      3.0
   +umd1.umd.edu         1 1024  177     535.0     13.0     13.0
   *128.4.0.5            1   64  167     545.0     10.0    524.0

more of this coming in part 2 πŸ’œπŸ¦‹

Appendix A. ROS "Header" Format ✨

Okay bestie, here's the whole ROS "header" module. It's all ASN.1, so it's giving formal, serious vibes πŸ’… Julian Onions wrote it at Nottingham University, and it's the blueprint for how the NTP packets and data get shaped 🌸

-- NTP definitions for ROS specification
--
-- Julian Onions, Nottingham University, UK.
--
-- Mon Jun  5 10:07:07 1989
--

NTP DEFINITIONS ::=

BEGIN

update OPERATION
 ARGUMENT Packet
 ::= 0

query OPERATION
 ARGUMENT NULL
 RESULT ClockInfoList
 ::= 1

-- Data Structures

BindArgument ::=
 fullbind SEQUENCE {
         psap[0] IA5String OPTIONAL,
         version[1] BITSTRING {
                 version-0(0),
                 version-1(1),
                 version-2(2)
         } DEFAULT version-2,
         authentication[2] Authentication OPTIONAL,
         mode[3] BindMode
 }

Authentication ::= ANY

BindMode ::= ENUMERATED {
         normal(0),      -- standard NTP
         query(1)        -- queries only
 }

BindResult ::=
 SEQUENCE {
         version[1] INTEGER DEFAULT 2,
         authentication[2] Authentication OPTIONAL,
         mode[3] BindMode
 }

BindError ::=
 SEQUENCE {
         reason[0] INTEGER {
                 refused(0),
                 validation(1),
                 version(2),     -- version not supported
                 badarg(3),      -- bad bind argument
                 congested(4)    -- catch all!
         },
         supplementary[1] IA5String OPTIONAL
 }


                                 -- basic exchange packet

Packet ::= SEQUENCE {
 leap                    Leap,
 mode                    Mode,
 stratum[1]              INTEGER,
 pollInterval[2]         INTEGER,
 precision[3]            INTEGER,
 synchDistance           SmallFixed,
 synchDispersion         SmallFixed,
 referenceClockIdentifier ClockIdentifier,
 referenceTimestamp      TimeStamp,
 originateTimestamp      TimeStamp,
 receiveTimestamp        TimeStamp,
 transmitTimestamp       TimeStamp
}

ClockInfoList ::= SET OF ClockInfo

ClockInfo ::= SEQUENCE {
 remoteAddress           Address,
 localAddress            Address,
 flags[0]                BIT STRING {
                 configured(0),
                 authentable(1),
                 sane(2),
                 candidate(3),
                 sync(4),
                 broadcast(5),
                 referenceClock(6),
                 selected(7),
                 inactive(8)
 },
 packetsSent[1]          INTEGER,
 packetsReceived[2]      INTEGER,
 packetsDropped[3]       INTEGER,
 timer[4]                INTEGER,
 leap                    Leap,
 stratum[5]              INTEGER,
 ppoll[6]                INTEGER,
 hpoll[7]                INTEGER,
 precision[8]            INTEGER,
 reachability[9]         INTEGER,
 estdisp[10]             INTEGER,
 estdelay[11]            INTEGER,
 estoffset[12]           INTEGER,
 reference[13]           ClockIdentifier OPTIONAL,
 reftime                 TimeStamp,
 filters                 SEQUENCE OF Filter
}

Leap ::= [APPLICATION 0] ENUMERATED {
         nowarning(0),
         plussecond(1),
         minussecond(2),
         alarm(3)
 }

SmallFixed ::= [APPLICATION 1] IMPLICIT SEQUENCE {
         integer INTEGER,
         fraction INTEGER
 }

ClockIdentifier ::= CHOICE {
                 referenceClock[0] PrintableString,
                 inetaddr[1] OCTET STRING,
                 psapaddr[2] OCTET STRING
 }

TimeStamp ::= [APPLICATION 2] IMPLICIT SEQUENCE {
         integer INTEGER,
         fraction INTEGER
 }

KeyId ::= [APPLICATION 4] INTEGER

Mode ::= [APPLICATION 4] ENUMERATED {
         unspecified (0),
         symmetricActive (1),
         symmetricPassive (2),
         client (3),
         server (4),
         broadcast (5),
         reservered (6),
         private (7)
 }

Filter ::= SEQUENCE {
         offset INTEGER,
         delay INTEGER
 }

Address ::= OCTET STRING -- for now
END

11. Security Considerations πŸ”₯

Okay bestie, serious moment 😭 This memo does not discuss security issues at all. Zero. Nada. The whole security page is basically a blank mirror πŸͺž so go in with your eyes wide open πŸ‘€ and don't assume the memo covers anything it doesn't say 🫢

12. Authors' Addresses 🧚

Meet the brains behind it, bestie πŸ’œ

Jon Crowcroft
Computer Science Department
University College London
Gower Street
London WC1E 6BT UK

EMail:  JON@CS.UCL.AC.UK


Julian P. Onions
Computer Science Department
Nottingham University
University Park
Nottingham, NG7 2RD UK

EMail:  JPO@CS.NOTT.AC.UK

That's a wrap on RFC 1165, slay! πŸŒˆπŸ’–βœ¨

πŸ“¦ where this page comes from