ntp.go 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843
  1. // Copyright © 2015-2023 Brett Vickers.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Package ntp provides an implementation of a Simple NTP (SNTP) client
  5. // capable of querying the current time from a remote NTP server. See
  6. // RFC 5905 (https://tools.ietf.org/html/rfc5905) for more details.
  7. //
  8. // This approach grew out of a go-nuts post by Michael Hofmann:
  9. // https://groups.google.com/forum/?fromgroups#!topic/golang-nuts/FlcdMU5fkLQ
  10. package ntp
  11. import (
  12. "bytes"
  13. "crypto/rand"
  14. "encoding/binary"
  15. "errors"
  16. "fmt"
  17. "net"
  18. "strconv"
  19. "strings"
  20. "time"
  21. "golang.org/x/net/ipv4"
  22. )
  23. var (
  24. ErrAuthFailed = errors.New("authentication failed")
  25. ErrInvalidAuthKey = errors.New("invalid authentication key")
  26. ErrInvalidDispersion = errors.New("invalid dispersion in response")
  27. ErrInvalidLeapSecond = errors.New("invalid leap second in response")
  28. ErrInvalidMode = errors.New("invalid mode in response")
  29. ErrInvalidProtocolVersion = errors.New("invalid protocol version requested")
  30. ErrInvalidStratum = errors.New("invalid stratum in response")
  31. ErrInvalidTime = errors.New("invalid time reported")
  32. ErrInvalidTransmitTime = errors.New("invalid transmit time in response")
  33. ErrKissOfDeath = errors.New("kiss of death received")
  34. ErrServerClockFreshness = errors.New("server clock not fresh")
  35. ErrServerResponseMismatch = errors.New("server response didn't match request")
  36. ErrServerTickedBackwards = errors.New("server clock ticked backwards")
  37. )
  38. // The LeapIndicator is used to warn if a leap second should be inserted
  39. // or deleted in the last minute of the current month.
  40. type LeapIndicator uint8
  41. const (
  42. // LeapNoWarning indicates no impending leap second.
  43. LeapNoWarning LeapIndicator = 0
  44. // LeapAddSecond indicates the last minute of the day has 61 seconds.
  45. LeapAddSecond = 1
  46. // LeapDelSecond indicates the last minute of the day has 59 seconds.
  47. LeapDelSecond = 2
  48. // LeapNotInSync indicates an unsynchronized leap second.
  49. LeapNotInSync = 3
  50. )
  51. // Internal constants
  52. const (
  53. defaultNtpVersion = 4
  54. defaultNtpPort = 123
  55. nanoPerSec = 1000000000
  56. maxStratum = 16
  57. defaultTimeout = 5 * time.Second
  58. maxPollInterval = (1 << 17) * time.Second
  59. maxDispersion = 16 * time.Second
  60. )
  61. // Internal variables
  62. var (
  63. ntpEra0 = time.Date(1900, 1, 1, 0, 0, 0, 0, time.UTC)
  64. ntpEra1 = time.Date(2036, 2, 7, 6, 28, 16, 0, time.UTC)
  65. )
  66. type mode uint8
  67. // NTP modes. This package uses only client mode.
  68. const (
  69. reserved mode = 0 + iota
  70. symmetricActive
  71. symmetricPassive
  72. client
  73. server
  74. broadcast
  75. controlMessage
  76. reservedPrivate
  77. )
  78. // An ntpTime is a 64-bit fixed-point (Q32.32) representation of the number of
  79. // seconds elapsed.
  80. type ntpTime uint64
  81. // Duration interprets the fixed-point ntpTime as a number of elapsed seconds
  82. // and returns the corresponding time.Duration value.
  83. func (t ntpTime) Duration() time.Duration {
  84. sec := (t >> 32) * nanoPerSec
  85. frac := (t & 0xffffffff) * nanoPerSec
  86. nsec := frac >> 32
  87. if uint32(frac) >= 0x80000000 {
  88. nsec++
  89. }
  90. return time.Duration(sec + nsec)
  91. }
  92. // Time interprets the fixed-point ntpTime as an absolute time and returns
  93. // the corresponding time.Time value.
  94. func (t ntpTime) Time() time.Time {
  95. // Assume NTP era 1 (year 2036+) if the raw timestamp suggests a year
  96. // before 1970. Otherwise assume NTP era 0. This allows the function to
  97. // report an accurate time value both before and after the 0-to-1 era
  98. // rollover.
  99. const t1970 = 0x83aa7e8000000000
  100. if uint64(t) < t1970 {
  101. return ntpEra1.Add(t.Duration())
  102. }
  103. return ntpEra0.Add(t.Duration())
  104. }
  105. // toNtpTime converts the time.Time value t into its 64-bit fixed-point
  106. // ntpTime representation.
  107. func toNtpTime(t time.Time) ntpTime {
  108. nsec := uint64(t.Sub(ntpEra0))
  109. sec := nsec / nanoPerSec
  110. nsec = uint64(nsec-sec*nanoPerSec) << 32
  111. frac := uint64(nsec / nanoPerSec)
  112. if nsec%nanoPerSec >= nanoPerSec/2 {
  113. frac++
  114. }
  115. return ntpTime(sec<<32 | frac)
  116. }
  117. // An ntpTimeShort is a 32-bit fixed-point (Q16.16) representation of the
  118. // number of seconds elapsed.
  119. type ntpTimeShort uint32
  120. // Duration interprets the fixed-point ntpTimeShort as a number of elapsed
  121. // seconds and returns the corresponding time.Duration value.
  122. func (t ntpTimeShort) Duration() time.Duration {
  123. sec := uint64(t>>16) * nanoPerSec
  124. frac := uint64(t&0xffff) * nanoPerSec
  125. nsec := frac >> 16
  126. if uint16(frac) >= 0x8000 {
  127. nsec++
  128. }
  129. return time.Duration(sec + nsec)
  130. }
  131. // header is an internal representation of an NTP packet header.
  132. type header struct {
  133. LiVnMode uint8 // Leap Indicator (2) + Version (3) + Mode (3)
  134. Stratum uint8
  135. Poll int8
  136. Precision int8
  137. RootDelay ntpTimeShort
  138. RootDispersion ntpTimeShort
  139. ReferenceID uint32 // KoD code if Stratum == 0
  140. ReferenceTime ntpTime
  141. OriginTime ntpTime
  142. ReceiveTime ntpTime
  143. TransmitTime ntpTime
  144. }
  145. // setVersion sets the NTP protocol version on the header.
  146. func (h *header) setVersion(v int) {
  147. h.LiVnMode = (h.LiVnMode & 0xc7) | uint8(v)<<3
  148. }
  149. // setMode sets the NTP protocol mode on the header.
  150. func (h *header) setMode(md mode) {
  151. h.LiVnMode = (h.LiVnMode & 0xf8) | uint8(md)
  152. }
  153. // setLeap modifies the leap indicator on the header.
  154. func (h *header) setLeap(li LeapIndicator) {
  155. h.LiVnMode = (h.LiVnMode & 0x3f) | uint8(li)<<6
  156. }
  157. // getVersion returns the version value in the header.
  158. func (h *header) getVersion() int {
  159. return int((h.LiVnMode >> 3) & 0x7)
  160. }
  161. // getMode returns the mode value in the header.
  162. func (h *header) getMode() mode {
  163. return mode(h.LiVnMode & 0x07)
  164. }
  165. // getLeap returns the leap indicator on the header.
  166. func (h *header) getLeap() LeapIndicator {
  167. return LeapIndicator((h.LiVnMode >> 6) & 0x03)
  168. }
  169. // An Extension adds custom behaviors capable of modifying NTP packets before
  170. // being sent to the server and processing packets after being received by the
  171. // server.
  172. type Extension interface {
  173. // ProcessQuery is called when the client is about to send a query to the
  174. // NTP server. The buffer contains the NTP header. It may also contain
  175. // extension fields added by extensions processed prior to this one.
  176. ProcessQuery(buf *bytes.Buffer) error
  177. // ProcessResponse is called after the client has received the server's
  178. // NTP response. The buffer contains the entire message returned by the
  179. // server.
  180. ProcessResponse(buf []byte) error
  181. }
  182. // QueryOptions contains configurable options used by the QueryWithOptions
  183. // function.
  184. type QueryOptions struct {
  185. // Timeout determines how long the client waits for a response from the
  186. // server before failing with a timeout error. Defaults to 5 seconds.
  187. Timeout time.Duration
  188. // Version of the NTP protocol to use. Defaults to 4.
  189. Version int
  190. // LocalAddress contains the local IP address to use when creating a
  191. // connection to the remote NTP server. This may be useful when the local
  192. // system has more than one IP address. This address should not contain
  193. // a port number.
  194. LocalAddress string
  195. // TTL specifies the maximum number of IP hops before the query datagram
  196. // is dropped by the network. Defaults to the local system's default value.
  197. TTL int
  198. // Auth contains the settings used to configure NTP symmetric key
  199. // authentication. See RFC 5905 for further details.
  200. Auth AuthOptions
  201. // Extensions may be added to modify NTP queries before they are
  202. // transmitted and to process NTP responses after they arrive.
  203. Extensions []Extension
  204. // GetSystemTime is a callback used to override the default method of
  205. // obtaining the local system time during time synchronization. If not
  206. // specified, time.Now is used.
  207. GetSystemTime func() time.Time
  208. // Dialer is a callback used to override the default UDP network dialer.
  209. // The localAddress is directly copied from the LocalAddress field
  210. // specified in QueryOptions. It may be the empty string or a host address
  211. // (without port number). The remoteAddress is the "host:port" string
  212. // derived from the first parameter to QueryWithOptions. The
  213. // remoteAddress is guaranteed to include a port number.
  214. Dialer func(localAddress, remoteAddress string) (net.Conn, error)
  215. // Dial is a callback used to override the default UDP network dialer.
  216. //
  217. // DEPRECATED. Use Dialer instead.
  218. Dial func(laddr string, lport int, raddr string, rport int) (net.Conn, error)
  219. // Port indicates the port used to reach the remote NTP server.
  220. //
  221. // DEPRECATED. Embed the port number in the query address string instead.
  222. Port int
  223. }
  224. // A Response contains time data, some of which is returned by the NTP server
  225. // and some of which is calculated by this client.
  226. type Response struct {
  227. // ClockOffset is the estimated offset of the local system clock relative
  228. // to the server's clock. Add this value to subsequent local system clock
  229. // times in order to obtain a time that is synchronized to the server's
  230. // clock.
  231. ClockOffset time.Duration
  232. // Time is the time the server transmitted this response, measured using
  233. // its own clock. You should not use this value for time synchronization
  234. // purposes. Add ClockOffset to your system clock instead.
  235. Time time.Time
  236. // RTT is the measured round-trip-time delay estimate between the client
  237. // and the server.
  238. RTT time.Duration
  239. // Precision is the reported precision of the server's clock.
  240. Precision time.Duration
  241. // Version is the NTP protocol version number reported by the server.
  242. Version int
  243. // Stratum is the "stratum level" of the server. The smaller the number,
  244. // the closer the server is to the reference clock. Stratum 1 servers are
  245. // attached directly to the reference clock. A stratum value of 0
  246. // indicates the "kiss of death," which typically occurs when the client
  247. // issues too many requests to the server in a short period of time.
  248. Stratum uint8
  249. // ReferenceID is a 32-bit integer identifying the server or reference
  250. // clock. For stratum 1 servers, this is typically a meaningful
  251. // zero-padded ASCII-encoded string assigned to the clock. For stratum 2+
  252. // servers, this is a reference identifier for the server and is either
  253. // the server's IPv4 address or a hash of its IPv6 address. For
  254. // kiss-of-death responses (stratum 0), this is the ASCII-encoded "kiss
  255. // code".
  256. ReferenceID uint32
  257. // ReferenceTime is the time the server last updated its local clock.
  258. ReferenceTime time.Time
  259. // RootDelay is the server's estimated aggregate round-trip-time delay to
  260. // the stratum 1 server.
  261. RootDelay time.Duration
  262. // RootDispersion is the server's estimated maximum measurement error
  263. // relative to the stratum 1 server.
  264. RootDispersion time.Duration
  265. // RootDistance is an estimate of the total synchronization distance
  266. // between the client and the stratum 1 server.
  267. RootDistance time.Duration
  268. // Leap indicates whether a leap second should be added or removed from
  269. // the current month's last minute.
  270. Leap LeapIndicator
  271. // MinError is a lower bound on the error between the client and server
  272. // clocks. When the client and server are not synchronized to the same
  273. // clock, the reported timestamps may appear to violate the principle of
  274. // causality. In other words, the NTP server's response may indicate
  275. // that a message was received before it was sent. In such cases, the
  276. // minimum error may be useful.
  277. MinError time.Duration
  278. // KissCode is a 4-character string describing the reason for a
  279. // "kiss of death" response (stratum=0). For a list of standard kiss
  280. // codes, see https://tools.ietf.org/html/rfc5905#section-7.4.
  281. KissCode string
  282. // Poll is the maximum interval between successive NTP query messages to
  283. // the server.
  284. Poll time.Duration
  285. authErr error
  286. }
  287. // IsKissOfDeath returns true if the response is a "kiss of death" from the
  288. // remote server. If this function returns true, you may examine the
  289. // response's KissCode value to determine the reason for the kiss of death.
  290. func (r *Response) IsKissOfDeath() bool {
  291. return r.Stratum == 0
  292. }
  293. // ReferenceString returns the response's ReferenceID value formatted as a
  294. // string. If the response's stratum is zero, then the "kiss o' death" string
  295. // is returned. If stratum is one, then the server is a reference clock and
  296. // the reference clock's name is returned. If stratum is two or greater, then
  297. // the ID is either an IPv4 address or an MD5 hash of the IPv6 address; in
  298. // either case the reference string is reported as 4 dot-separated
  299. // decimal-based integers.
  300. func (r *Response) ReferenceString() string {
  301. if r.Stratum == 0 {
  302. return kissCode(r.ReferenceID)
  303. }
  304. var b [4]byte
  305. binary.BigEndian.PutUint32(b[:], r.ReferenceID)
  306. if r.Stratum == 1 {
  307. const dot = rune(0x22c5)
  308. var r []rune
  309. for i := range b {
  310. if b[i] == 0 {
  311. break
  312. }
  313. if b[i] >= 32 && b[i] <= 126 {
  314. r = append(r, rune(b[i]))
  315. } else {
  316. r = append(r, dot)
  317. }
  318. }
  319. return fmt.Sprintf(".%s.", string(r))
  320. }
  321. return fmt.Sprintf("%d.%d.%d.%d", b[0], b[1], b[2], b[3])
  322. }
  323. // Validate checks if the response is valid for the purposes of time
  324. // synchronization.
  325. func (r *Response) Validate() error {
  326. // Forward authentication errors.
  327. if r.authErr != nil {
  328. return r.authErr
  329. }
  330. // Handle invalid stratum values.
  331. if r.Stratum == 0 {
  332. return ErrKissOfDeath
  333. }
  334. if r.Stratum >= maxStratum {
  335. return ErrInvalidStratum
  336. }
  337. // Estimate the "freshness" of the time. If it exceeds the maximum
  338. // polling interval (~36 hours), then it cannot be considered "fresh".
  339. freshness := r.Time.Sub(r.ReferenceTime)
  340. if freshness > maxPollInterval {
  341. return ErrServerClockFreshness
  342. }
  343. // Calculate the peer synchronization distance, lambda:
  344. // lambda := RootDelay/2 + RootDispersion
  345. // If this value exceeds MAXDISP (16s), then the time is not suitable
  346. // for synchronization purposes.
  347. // https://tools.ietf.org/html/rfc5905#appendix-A.5.1.1.
  348. lambda := r.RootDelay/2 + r.RootDispersion
  349. if lambda > maxDispersion {
  350. return ErrInvalidDispersion
  351. }
  352. // If the server's transmit time is before its reference time, the
  353. // response is invalid.
  354. if r.Time.Before(r.ReferenceTime) {
  355. return ErrInvalidTime
  356. }
  357. // Handle invalid leap second indicator.
  358. if r.Leap == LeapNotInSync {
  359. return ErrInvalidLeapSecond
  360. }
  361. // nil means the response is valid.
  362. return nil
  363. }
  364. // Query requests time data from a remote NTP server. The response contains
  365. // information from which a more accurate local time can be inferred.
  366. //
  367. // The server address is of the form "host", "host:port", "host%zone:port",
  368. // "[host]:port" or "[host%zone]:port". The host may contain an IPv4, IPv6 or
  369. // domain name address. When specifying both a port and an IPv6 address, one
  370. // of the bracket formats must be used. If no port is included, NTP default
  371. // port 123 is used.
  372. func Query(address string) (*Response, error) {
  373. return QueryWithOptions(address, QueryOptions{})
  374. }
  375. // QueryWithOptions performs the same function as Query but allows for the
  376. // customization of certain query behaviors. See the comments for Query and
  377. // QueryOptions for further details.
  378. func QueryWithOptions(address string, opt QueryOptions) (*Response, error) {
  379. h, now, err := getTime(address, &opt)
  380. if err != nil && err != ErrAuthFailed {
  381. return nil, err
  382. }
  383. return generateResponse(h, now, err), nil
  384. }
  385. // Time returns the current, corrected local time using information returned
  386. // from the remote NTP server. On error, Time returns the uncorrected local
  387. // system time.
  388. //
  389. // The server address is of the form "host", "host:port", "host%zone:port",
  390. // "[host]:port" or "[host%zone]:port". The host may contain an IPv4, IPv6 or
  391. // domain name address. When specifying both a port and an IPv6 address, one
  392. // of the bracket formats must be used. If no port is included, NTP default
  393. // port 123 is used.
  394. func Time(address string) (time.Time, error) {
  395. r, err := Query(address)
  396. if err != nil {
  397. return time.Now(), err
  398. }
  399. err = r.Validate()
  400. if err != nil {
  401. return time.Now(), err
  402. }
  403. // Use the response's clock offset to calculate an accurate time.
  404. return time.Now().Add(r.ClockOffset), nil
  405. }
  406. // getTime performs the NTP server query and returns the response header
  407. // along with the local system time it was received.
  408. func getTime(address string, opt *QueryOptions) (*header, ntpTime, error) {
  409. if opt.Timeout == 0 {
  410. opt.Timeout = defaultTimeout
  411. }
  412. if opt.Version == 0 {
  413. opt.Version = defaultNtpVersion
  414. }
  415. if opt.Version < 2 || opt.Version > 4 {
  416. return nil, 0, ErrInvalidProtocolVersion
  417. }
  418. if opt.Port == 0 {
  419. opt.Port = defaultNtpPort
  420. }
  421. if opt.Dial != nil {
  422. // wrapper for the deprecated Dial callback.
  423. opt.Dialer = func(la, ra string) (net.Conn, error) {
  424. return dialWrapper(la, ra, opt.Dial)
  425. }
  426. }
  427. if opt.Dialer == nil {
  428. opt.Dialer = defaultDialer
  429. }
  430. if opt.GetSystemTime == nil {
  431. opt.GetSystemTime = time.Now
  432. }
  433. // Compose a conforming host:port remote address string if the address
  434. // string doesn't already contain a port.
  435. remoteAddress, err := fixHostPort(address, opt.Port)
  436. if err != nil {
  437. return nil, 0, err
  438. }
  439. // Connect to the remote server.
  440. con, err := opt.Dialer(opt.LocalAddress, remoteAddress)
  441. if err != nil {
  442. return nil, 0, err
  443. }
  444. defer con.Close()
  445. // Set a TTL for the packet if requested.
  446. if opt.TTL != 0 {
  447. ipcon := ipv4.NewConn(con)
  448. err = ipcon.SetTTL(opt.TTL)
  449. if err != nil {
  450. return nil, 0, err
  451. }
  452. }
  453. // Set a timeout on the connection.
  454. con.SetDeadline(time.Now().Add(opt.Timeout))
  455. // Allocate a buffer big enough to hold an entire response datagram.
  456. recvBuf := make([]byte, 8192)
  457. recvHdr := new(header)
  458. // Allocate the query message header.
  459. xmitHdr := new(header)
  460. xmitHdr.setMode(client)
  461. xmitHdr.setVersion(opt.Version)
  462. xmitHdr.setLeap(LeapNoWarning)
  463. xmitHdr.Precision = 0x20
  464. // To help prevent spoofing and client fingerprinting, use a
  465. // cryptographically random 64-bit value for the TransmitTime. See:
  466. // https://www.ietf.org/archive/id/draft-ietf-ntp-data-minimization-04.txt
  467. bits := make([]byte, 8)
  468. _, err = rand.Read(bits)
  469. if err != nil {
  470. return nil, 0, err
  471. }
  472. xmitHdr.TransmitTime = ntpTime(binary.BigEndian.Uint64(bits))
  473. // Write the query header to a transmit buffer.
  474. var xmitBuf bytes.Buffer
  475. binary.Write(&xmitBuf, binary.BigEndian, xmitHdr)
  476. // Allow extensions to process the query and add to the transmit buffer.
  477. for _, e := range opt.Extensions {
  478. err = e.ProcessQuery(&xmitBuf)
  479. if err != nil {
  480. return nil, 0, err
  481. }
  482. }
  483. // If using symmetric key authentication, decode and validate the auth key
  484. // string.
  485. authKey, err := decodeAuthKey(opt.Auth)
  486. if err != nil {
  487. return nil, 0, err
  488. }
  489. // Append a MAC if authentication is being used.
  490. appendMAC(&xmitBuf, opt.Auth, authKey)
  491. // Transmit the query and keep track of when it was transmitted.
  492. xmitTime := opt.GetSystemTime()
  493. _, err = con.Write(xmitBuf.Bytes())
  494. if err != nil {
  495. return nil, 0, err
  496. }
  497. // Receive the response.
  498. recvBytes, err := con.Read(recvBuf)
  499. if err != nil {
  500. return nil, 0, err
  501. }
  502. // Keep track of the time the response was received. As of go 1.9, the
  503. // time package uses a monotonic clock, so delta will never be less than
  504. // zero for go version 1.9 or higher.
  505. recvTime := opt.GetSystemTime()
  506. if recvTime.Sub(xmitTime) < 0 {
  507. recvTime = xmitTime
  508. }
  509. // Parse the response header.
  510. recvBuf = recvBuf[:recvBytes]
  511. recvReader := bytes.NewReader(recvBuf)
  512. err = binary.Read(recvReader, binary.BigEndian, recvHdr)
  513. if err != nil {
  514. return nil, 0, err
  515. }
  516. // Allow extensions to process the response.
  517. for i := len(opt.Extensions) - 1; i >= 0; i-- {
  518. err = opt.Extensions[i].ProcessResponse(recvBuf)
  519. if err != nil {
  520. return nil, 0, err
  521. }
  522. }
  523. // Check for invalid fields.
  524. if recvHdr.getMode() != server {
  525. return nil, 0, ErrInvalidMode
  526. }
  527. if recvHdr.TransmitTime == ntpTime(0) {
  528. return nil, 0, ErrInvalidTransmitTime
  529. }
  530. if recvHdr.OriginTime != xmitHdr.TransmitTime {
  531. return nil, 0, ErrServerResponseMismatch
  532. }
  533. if recvHdr.ReceiveTime > recvHdr.TransmitTime {
  534. return nil, 0, ErrServerTickedBackwards
  535. }
  536. // Correct the received message's origin time using the actual
  537. // transmit time.
  538. recvHdr.OriginTime = toNtpTime(xmitTime)
  539. // Perform authentication of the server response.
  540. authErr := verifyMAC(recvBuf, opt.Auth, authKey)
  541. return recvHdr, toNtpTime(recvTime), authErr
  542. }
  543. // defaultDialer provides a UDP dialer based on Go's built-in net stack.
  544. func defaultDialer(localAddress, remoteAddress string) (net.Conn, error) {
  545. var laddr *net.UDPAddr
  546. if localAddress != "" {
  547. var err error
  548. laddr, err = net.ResolveUDPAddr("udp", net.JoinHostPort(localAddress, "0"))
  549. if err != nil {
  550. return nil, err
  551. }
  552. }
  553. raddr, err := net.ResolveUDPAddr("udp", remoteAddress)
  554. if err != nil {
  555. return nil, err
  556. }
  557. return net.DialUDP("udp", laddr, raddr)
  558. }
  559. // dialWrapper is used to wrap the deprecated Dial callback in QueryOptions.
  560. func dialWrapper(la, ra string,
  561. dial func(la string, lp int, ra string, rp int) (net.Conn, error)) (net.Conn, error) {
  562. rhost, rport, err := net.SplitHostPort(ra)
  563. if err != nil {
  564. return nil, err
  565. }
  566. rportValue, err := strconv.Atoi(rport)
  567. if err != nil {
  568. return nil, err
  569. }
  570. return dial(la, 0, rhost, rportValue)
  571. }
  572. // fixHostPort examines an address in one of the accepted forms and fixes it
  573. // to include a port number if necessary.
  574. func fixHostPort(address string, defaultPort int) (fixed string, err error) {
  575. if len(address) == 0 {
  576. return "", errors.New("address string is empty")
  577. }
  578. // If the address is wrapped in brackets, append a port if necessary.
  579. if address[0] == '[' {
  580. end := strings.IndexByte(address, ']')
  581. switch {
  582. case end < 0:
  583. return "", errors.New("missing ']' in address")
  584. case end+1 == len(address):
  585. return fmt.Sprintf("%s:%d", address, defaultPort), nil
  586. case address[end+1] == ':':
  587. return address, nil
  588. default:
  589. return "", errors.New("unexpected character following ']' in address")
  590. }
  591. }
  592. // No colons? Must be a port-less IPv4 or domain address.
  593. last := strings.LastIndexByte(address, ':')
  594. if last < 0 {
  595. return fmt.Sprintf("%s:%d", address, defaultPort), nil
  596. }
  597. // Exactly one colon? A port have been included along with an IPv4 or
  598. // domain address. (IPv6 addresses are guaranteed to have more than one
  599. // colon.)
  600. prev := strings.LastIndexByte(address[:last], ':')
  601. if prev < 0 {
  602. return address, nil
  603. }
  604. // Two or more colons means we must have an IPv6 address without a port.
  605. return fmt.Sprintf("[%s]:%d", address, defaultPort), nil
  606. }
  607. // generateResponse processes NTP header fields along with the its receive
  608. // time to generate a Response record.
  609. func generateResponse(h *header, recvTime ntpTime, authErr error) *Response {
  610. r := &Response{
  611. Time: h.TransmitTime.Time(),
  612. ClockOffset: offset(h.OriginTime, h.ReceiveTime, h.TransmitTime, recvTime),
  613. RTT: rtt(h.OriginTime, h.ReceiveTime, h.TransmitTime, recvTime),
  614. Precision: toInterval(h.Precision),
  615. Version: h.getVersion(),
  616. Stratum: h.Stratum,
  617. ReferenceID: h.ReferenceID,
  618. ReferenceTime: h.ReferenceTime.Time(),
  619. RootDelay: h.RootDelay.Duration(),
  620. RootDispersion: h.RootDispersion.Duration(),
  621. Leap: h.getLeap(),
  622. MinError: minError(h.OriginTime, h.ReceiveTime, h.TransmitTime, recvTime),
  623. Poll: toInterval(h.Poll),
  624. authErr: authErr,
  625. }
  626. // Calculate values depending on other calculated values
  627. r.RootDistance = rootDistance(r.RTT, r.RootDelay, r.RootDispersion)
  628. // If a kiss of death was received, interpret the reference ID as
  629. // a kiss code.
  630. if r.Stratum == 0 {
  631. r.KissCode = kissCode(r.ReferenceID)
  632. }
  633. return r
  634. }
  635. // The following helper functions calculate additional metadata about the
  636. // timestamps received from an NTP server. The timestamps returned by
  637. // the server are given the following variable names:
  638. //
  639. // org = Origin Timestamp (client send time)
  640. // rec = Receive Timestamp (server receive time)
  641. // xmt = Transmit Timestamp (server reply time)
  642. // dst = Destination Timestamp (client receive time)
  643. func rtt(org, rec, xmt, dst ntpTime) time.Duration {
  644. a := int64(dst - org)
  645. b := int64(xmt - rec)
  646. rtt := a - b
  647. if rtt < 0 {
  648. rtt = 0
  649. }
  650. return ntpTime(rtt).Duration()
  651. }
  652. func offset(org, rec, xmt, dst ntpTime) time.Duration {
  653. // The inputs are 64-bit unsigned integer timestamps. These timestamps can
  654. // "roll over" at the end of an NTP era, which occurs approximately every
  655. // 136 years starting from the year 1900. To ensure an accurate offset
  656. // calculation when an era boundary is crossed, we need to take care that
  657. // the difference between two 64-bit timestamp values is accurately
  658. // calculated even when they are in neighboring eras.
  659. //
  660. // See: https://www.eecis.udel.edu/~mills/y2k.html
  661. a := int64(rec - org)
  662. b := int64(xmt - dst)
  663. offset := a + (b-a)/2
  664. if offset < 0 {
  665. return -ntpTime(-offset).Duration()
  666. }
  667. return ntpTime(offset).Duration()
  668. }
  669. func minError(org, rec, xmt, dst ntpTime) time.Duration {
  670. // Each NTP response contains two pairs of send/receive timestamps.
  671. // When either pair indicates a "causality violation", we calculate the
  672. // error as the difference in time between them. The minimum error is
  673. // the greater of the two causality violations.
  674. var error0, error1 ntpTime
  675. if org >= rec {
  676. error0 = org - rec
  677. }
  678. if xmt >= dst {
  679. error1 = xmt - dst
  680. }
  681. if error0 > error1 {
  682. return error0.Duration()
  683. }
  684. return error1.Duration()
  685. }
  686. func rootDistance(rtt, rootDelay, rootDisp time.Duration) time.Duration {
  687. // The root distance is:
  688. // the maximum error due to all causes of the local clock
  689. // relative to the primary server. It is defined as half the
  690. // total delay plus total dispersion plus peer jitter.
  691. // (https://tools.ietf.org/html/rfc5905#appendix-A.5.5.2)
  692. //
  693. // In the reference implementation, it is calculated as follows:
  694. // rootDist = max(MINDISP, rootDelay + rtt)/2 + rootDisp
  695. // + peerDisp + PHI * (uptime - peerUptime)
  696. // + peerJitter
  697. // For an SNTP client which sends only a single packet, most of these
  698. // terms are irrelevant and become 0.
  699. totalDelay := rtt + rootDelay
  700. return totalDelay/2 + rootDisp
  701. }
  702. func toInterval(t int8) time.Duration {
  703. switch {
  704. case t > 0:
  705. return time.Duration(uint64(time.Second) << uint(t))
  706. case t < 0:
  707. return time.Duration(uint64(time.Second) >> uint(-t))
  708. default:
  709. return time.Second
  710. }
  711. }
  712. func kissCode(id uint32) string {
  713. isPrintable := func(ch byte) bool { return ch >= 32 && ch <= 126 }
  714. b := [4]byte{
  715. byte(id >> 24),
  716. byte(id >> 16),
  717. byte(id >> 8),
  718. byte(id),
  719. }
  720. for _, ch := range b {
  721. if !isPrintable(ch) {
  722. return ""
  723. }
  724. }
  725. return string(b[:])
  726. }