Matteo Scandolo | a6a3aee | 2019-11-26 13:30:14 -0700 | [diff] [blame] | 1 | // Copyright 2016 Google, Inc. All rights reserved. |
| 2 | // |
| 3 | // Use of this source code is governed by a BSD-style license |
| 4 | // that can be found in the LICENSE file in the root of the source |
| 5 | // tree. |
| 6 | // |
| 7 | //****************************************************************************** |
| 8 | |
| 9 | package layers |
| 10 | |
| 11 | import ( |
| 12 | "encoding/binary" |
| 13 | "errors" |
| 14 | |
| 15 | "github.com/google/gopacket" |
| 16 | ) |
| 17 | |
| 18 | //****************************************************************************** |
| 19 | // |
| 20 | // Network Time Protocol (NTP) Decoding Layer |
| 21 | // ------------------------------------------ |
| 22 | // This file provides a GoPacket decoding layer for NTP. |
| 23 | // |
| 24 | //****************************************************************************** |
| 25 | // |
| 26 | // About The Network Time Protocol (NTP) |
| 27 | // ------------------------------------- |
| 28 | // NTP is a protocol that enables computers on the internet to set their |
| 29 | // clocks to the correct time (or to a time that is acceptably close to the |
| 30 | // correct time). NTP runs on top of UDP. |
| 31 | // |
| 32 | // There have been a series of versions of the NTP protocol. The latest |
| 33 | // version is V4 and is specified in RFC 5905: |
| 34 | // http://www.ietf.org/rfc/rfc5905.txt |
| 35 | // |
| 36 | //****************************************************************************** |
| 37 | // |
| 38 | // References |
| 39 | // ---------- |
| 40 | // |
| 41 | // Wikipedia's NTP entry: |
| 42 | // https://en.wikipedia.org/wiki/Network_Time_Protocol |
| 43 | // This is the best place to get an overview of NTP. |
| 44 | // |
| 45 | // Network Time Protocol Home Website: |
| 46 | // http://www.ntp.org/ |
| 47 | // This appears to be the official website of NTP. |
| 48 | // |
| 49 | // List of current NTP Protocol RFCs: |
| 50 | // http://www.ntp.org/rfc.html |
| 51 | // |
| 52 | // RFC 958: "Network Time Protocol (NTP)" (1985) |
| 53 | // https://tools.ietf.org/html/rfc958 |
| 54 | // This is the original NTP specification. |
| 55 | // |
| 56 | // RFC 1305: "Network Time Protocol (Version 3) Specification, Implementation and Analysis" (1992) |
| 57 | // https://tools.ietf.org/html/rfc1305 |
| 58 | // The protocol was updated in 1992 yielding NTP V3. |
| 59 | // |
| 60 | // RFC 5905: "Network Time Protocol Version 4: Protocol and Algorithms Specification" (2010) |
| 61 | // https://www.ietf.org/rfc/rfc5905.txt |
| 62 | // The protocol was updated in 2010 yielding NTP V4. |
| 63 | // V4 is backwards compatible with all previous versions of NTP. |
| 64 | // |
| 65 | // RFC 5906: "Network Time Protocol Version 4: Autokey Specification" |
| 66 | // https://tools.ietf.org/html/rfc5906 |
| 67 | // This document addresses the security of the NTP protocol |
| 68 | // and is probably not relevant to this package. |
| 69 | // |
| 70 | // RFC 5907: "Definitions of Managed Objects for Network Time Protocol Version 4 (NTPv4)" |
| 71 | // https://tools.ietf.org/html/rfc5907 |
| 72 | // This document addresses the management of NTP servers and |
| 73 | // is probably not relevant to this package. |
| 74 | // |
| 75 | // RFC 5908: "Network Time Protocol (NTP) Server Option for DHCPv6" |
| 76 | // https://tools.ietf.org/html/rfc5908 |
| 77 | // This document addresses the use of NTP in DHCPv6 and is |
| 78 | // probably not relevant to this package. |
| 79 | // |
| 80 | // "Let's make a NTP Client in C" |
| 81 | // https://lettier.github.io/posts/2016-04-26-lets-make-a-ntp-client-in-c.html |
| 82 | // This web page contains useful information about the details of NTP, |
| 83 | // including an NTP record struture in C, and C code. |
| 84 | // |
| 85 | // "NTP Packet Header (NTP Reference Implementation) (Computer Network Time Synchronization)" |
| 86 | // http://what-when-how.com/computer-network-time-synchronization/ |
| 87 | // ntp-packet-header-ntp-reference-implementation-computer-network-time-synchronization/ |
| 88 | // This web page contains useful information on the details of NTP. |
| 89 | // |
| 90 | // "Technical information - NTP Data Packet" |
| 91 | // https://www.meinbergglobal.com/english/info/ntp-packet.htm |
| 92 | // This page has a helpful diagram of an NTP V4 packet. |
| 93 | // |
| 94 | //****************************************************************************** |
| 95 | // |
| 96 | // Obsolete References |
| 97 | // ------------------- |
| 98 | // |
| 99 | // RFC 1119: "RFC-1119 "Network Time Protocol (Version 2) Specification and Implementation" (1989) |
| 100 | // https://tools.ietf.org/html/rfc1119 |
| 101 | // Version 2 was drafted in 1989. |
| 102 | // It is unclear whether V2 was ever implememented or whether the |
| 103 | // ideas ended up in V3 (which was implemented in 1992). |
| 104 | // |
| 105 | // RFC 1361: "Simple Network Time Protocol (SNTP)" |
| 106 | // https://tools.ietf.org/html/rfc1361 |
| 107 | // This document is obsoleted by RFC 1769 and is included only for completeness. |
| 108 | // |
| 109 | // RFC 1769: "Simple Network Time Protocol (SNTP)" |
| 110 | // https://tools.ietf.org/html/rfc1769 |
| 111 | // This document is obsoleted by RFC 2030 and RFC 4330 and is included only for completeness. |
| 112 | // |
| 113 | // RFC 2030: "Simple Network Time Protocol (SNTP) Version 4 for IPv4, IPv6 and OSI" |
| 114 | // https://tools.ietf.org/html/rfc2030 |
| 115 | // This document is obsoleted by RFC 4330 and is included only for completeness. |
| 116 | // |
| 117 | // RFC 4330: "Simple Network Time Protocol (SNTP) Version 4 for IPv4, IPv6 and OSI" |
| 118 | // https://tools.ietf.org/html/rfc4330 |
| 119 | // This document is obsoleted by RFC 5905 and is included only for completeness. |
| 120 | // |
| 121 | //****************************************************************************** |
| 122 | // |
| 123 | // Endian And Bit Numbering Issues |
| 124 | // ------------------------------- |
| 125 | // |
| 126 | // Endian and bit numbering issues can be confusing. Here is some |
| 127 | // clarification: |
| 128 | // |
| 129 | // ENDIAN: Values are sent big endian. |
| 130 | // https://en.wikipedia.org/wiki/Endianness |
| 131 | // |
| 132 | // BIT NUMBERING: Bits are numbered 0 upwards from the most significant |
| 133 | // bit to the least significant bit. This means that if there is a 32-bit |
| 134 | // value, the most significant bit is called bit 0 and the least |
| 135 | // significant bit is called bit 31. |
| 136 | // |
| 137 | // See RFC 791 Appendix B for more discussion. |
| 138 | // |
| 139 | //****************************************************************************** |
| 140 | // |
| 141 | // NTP V3 and V4 Packet Format |
| 142 | // --------------------------- |
| 143 | // NTP packets are UDP packets whose payload contains an NTP record. |
| 144 | // |
| 145 | // The NTP RFC defines the format of the NTP record. |
| 146 | // |
| 147 | // There have been four versions of the protocol: |
| 148 | // |
| 149 | // V1 in 1985 |
| 150 | // V2 in 1989 |
| 151 | // V3 in 1992 |
| 152 | // V4 in 2010 |
| 153 | // |
| 154 | // It is clear that V1 and V2 are obsolete, and there is no need to |
| 155 | // cater for these formats. |
| 156 | // |
| 157 | // V3 and V4 essentially use the same format, with V4 adding some optional |
| 158 | // fields on the end. So this package supports the V3 and V4 formats. |
| 159 | // |
| 160 | // The current version of NTP (NTP V4)'s RFC (V4 - RFC 5905) contains |
| 161 | // the following diagram for the NTP record format: |
| 162 | |
| 163 | // 0 1 2 3 |
| 164 | // 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 |
| 165 | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 166 | // |LI | VN |Mode | Stratum | Poll | Precision | |
| 167 | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 168 | // | Root Delay | |
| 169 | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 170 | // | Root Dispersion | |
| 171 | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 172 | // | Reference ID | |
| 173 | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 174 | // | | |
| 175 | // + Reference Timestamp (64) + |
| 176 | // | | |
| 177 | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 178 | // | | |
| 179 | // + Origin Timestamp (64) + |
| 180 | // | | |
| 181 | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 182 | // | | |
| 183 | // + Receive Timestamp (64) + |
| 184 | // | | |
| 185 | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 186 | // | | |
| 187 | // + Transmit Timestamp (64) + |
| 188 | // | | |
| 189 | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 190 | // | | |
| 191 | // . . |
| 192 | // . Extension Field 1 (variable) . |
| 193 | // . . |
| 194 | // | | |
| 195 | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 196 | // | | |
| 197 | // . . |
| 198 | // . Extension Field 2 (variable) . |
| 199 | // . . |
| 200 | // | | |
| 201 | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 202 | // | Key Identifier | |
| 203 | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 204 | // | | |
| 205 | // | dgst (128) | |
| 206 | // | | |
| 207 | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 208 | // From http://www.ietf.org/rfc/rfc5905.txt |
| 209 | // |
| 210 | // The fields "Extension Field 1 (variable)" and later are optional fields, |
| 211 | // and so we can set a minimum NTP record size of 48 bytes. |
| 212 | // |
| 213 | const ntpMinimumRecordSizeInBytes int = 48 |
| 214 | |
| 215 | //****************************************************************************** |
| 216 | |
| 217 | // NTP Type |
| 218 | // -------- |
| 219 | // Type NTP implements the DecodingLayer interface. Each NTP object |
| 220 | // represents in a structured form the NTP record present as the UDP |
| 221 | // payload in an NTP UDP packet. |
| 222 | // |
| 223 | |
| 224 | type NTPLeapIndicator uint8 |
| 225 | type NTPVersion uint8 |
| 226 | type NTPMode uint8 |
| 227 | type NTPStratum uint8 |
| 228 | type NTPLog2Seconds int8 |
| 229 | type NTPFixed16Seconds uint32 |
| 230 | type NTPReferenceID uint32 |
| 231 | type NTPTimestamp uint64 |
| 232 | |
| 233 | type NTP struct { |
| 234 | BaseLayer // Stores the packet bytes and payload bytes. |
| 235 | |
| 236 | LeapIndicator NTPLeapIndicator // [0,3]. Indicates whether leap second(s) is to be added. |
| 237 | Version NTPVersion // [0,7]. Version of the NTP protocol. |
| 238 | Mode NTPMode // [0,7]. Mode. |
| 239 | Stratum NTPStratum // [0,255]. Stratum of time server in the server tree. |
| 240 | Poll NTPLog2Seconds // [-128,127]. The maximum interval between successive messages, in log2 seconds. |
| 241 | Precision NTPLog2Seconds // [-128,127]. The precision of the system clock, in log2 seconds. |
| 242 | RootDelay NTPFixed16Seconds // [0,2^32-1]. Total round trip delay to the reference clock in seconds times 2^16. |
| 243 | RootDispersion NTPFixed16Seconds // [0,2^32-1]. Total dispersion to the reference clock, in seconds times 2^16. |
| 244 | ReferenceID NTPReferenceID // ID code of reference clock [0,2^32-1]. |
| 245 | ReferenceTimestamp NTPTimestamp // Most recent timestamp from the reference clock. |
| 246 | OriginTimestamp NTPTimestamp // Local time when request was sent from local host. |
| 247 | ReceiveTimestamp NTPTimestamp // Local time (on server) that request arrived at server host. |
| 248 | TransmitTimestamp NTPTimestamp // Local time (on server) that request departed server host. |
| 249 | |
| 250 | // FIX: This package should analyse the extension fields and represent the extension fields too. |
| 251 | ExtensionBytes []byte // Just put extensions in a byte slice. |
| 252 | } |
| 253 | |
| 254 | //****************************************************************************** |
| 255 | |
| 256 | // LayerType returns the layer type of the NTP object, which is LayerTypeNTP. |
| 257 | func (d *NTP) LayerType() gopacket.LayerType { |
| 258 | return LayerTypeNTP |
| 259 | } |
| 260 | |
| 261 | //****************************************************************************** |
| 262 | |
| 263 | // decodeNTP analyses a byte slice and attempts to decode it as an NTP |
| 264 | // record of a UDP packet. |
| 265 | // |
| 266 | // If it succeeds, it loads p with information about the packet and returns nil. |
| 267 | // If it fails, it returns an error (non nil). |
| 268 | // |
| 269 | // This function is employed in layertypes.go to register the NTP layer. |
| 270 | func decodeNTP(data []byte, p gopacket.PacketBuilder) error { |
| 271 | |
| 272 | // Attempt to decode the byte slice. |
| 273 | d := &NTP{} |
| 274 | err := d.DecodeFromBytes(data, p) |
| 275 | if err != nil { |
| 276 | return err |
| 277 | } |
| 278 | |
| 279 | // If the decoding worked, add the layer to the packet and set it |
| 280 | // as the application layer too, if there isn't already one. |
| 281 | p.AddLayer(d) |
| 282 | p.SetApplicationLayer(d) |
| 283 | |
| 284 | return nil |
| 285 | } |
| 286 | |
| 287 | //****************************************************************************** |
| 288 | |
| 289 | // DecodeFromBytes analyses a byte slice and attempts to decode it as an NTP |
| 290 | // record of a UDP packet. |
| 291 | // |
| 292 | // Upon succeeds, it loads the NTP object with information about the packet |
| 293 | // and returns nil. |
| 294 | // Upon failure, it returns an error (non nil). |
| 295 | func (d *NTP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { |
| 296 | |
| 297 | // If the data block is too short to be a NTP record, then return an error. |
| 298 | if len(data) < ntpMinimumRecordSizeInBytes { |
| 299 | df.SetTruncated() |
| 300 | return errors.New("NTP packet too short") |
| 301 | } |
| 302 | |
| 303 | // RFC 5905 does not appear to define a maximum NTP record length. |
| 304 | // The protocol allows "extension fields" to be included in the record, |
| 305 | // and states about these fields:" |
| 306 | // |
| 307 | // "While the minimum field length containing required fields is |
| 308 | // four words (16 octets), a maximum field length remains to be |
| 309 | // established." |
| 310 | // |
| 311 | // For this reason, the packet length is not checked here for being too long. |
| 312 | |
| 313 | // NTP type embeds type BaseLayer which contains two fields: |
| 314 | // Contents is supposed to contain the bytes of the data at this level. |
| 315 | // Payload is supposed to contain the payload of this level. |
| 316 | // Here we set the baselayer to be the bytes of the NTP record. |
| 317 | d.BaseLayer = BaseLayer{Contents: data[:len(data)]} |
| 318 | |
| 319 | // Extract the fields from the block of bytes. |
| 320 | // To make sense of this, refer to the packet diagram |
| 321 | // above and the section on endian conventions. |
| 322 | |
| 323 | // The first few fields are all packed into the first 32 bits. Unpack them. |
| 324 | f := data[0] |
| 325 | d.LeapIndicator = NTPLeapIndicator((f & 0xC0) >> 6) |
| 326 | d.Version = NTPVersion((f & 0x38) >> 3) |
| 327 | d.Mode = NTPMode(f & 0x07) |
| 328 | d.Stratum = NTPStratum(data[1]) |
| 329 | d.Poll = NTPLog2Seconds(data[2]) |
| 330 | d.Precision = NTPLog2Seconds(data[3]) |
| 331 | |
| 332 | // The remaining fields can just be copied in big endian order. |
| 333 | d.RootDelay = NTPFixed16Seconds(binary.BigEndian.Uint32(data[4:8])) |
| 334 | d.RootDispersion = NTPFixed16Seconds(binary.BigEndian.Uint32(data[8:12])) |
| 335 | d.ReferenceID = NTPReferenceID(binary.BigEndian.Uint32(data[12:16])) |
| 336 | d.ReferenceTimestamp = NTPTimestamp(binary.BigEndian.Uint64(data[16:24])) |
| 337 | d.OriginTimestamp = NTPTimestamp(binary.BigEndian.Uint64(data[24:32])) |
| 338 | d.ReceiveTimestamp = NTPTimestamp(binary.BigEndian.Uint64(data[32:40])) |
| 339 | d.TransmitTimestamp = NTPTimestamp(binary.BigEndian.Uint64(data[40:48])) |
| 340 | |
| 341 | // This layer does not attempt to analyse the extension bytes. |
| 342 | // But if there are any, we'd like the user to know. So we just |
| 343 | // place them all in an ExtensionBytes field. |
| 344 | d.ExtensionBytes = data[48:] |
| 345 | |
| 346 | // Return no error. |
| 347 | return nil |
| 348 | } |
| 349 | |
| 350 | // SerializeTo writes the serialized form of this layer into the |
| 351 | // SerializationBuffer, implementing gopacket.SerializableLayer. |
| 352 | // See the docs for gopacket.SerializableLayer for more info. |
| 353 | func (d *NTP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { |
| 354 | data, err := b.PrependBytes(ntpMinimumRecordSizeInBytes) |
| 355 | if err != nil { |
| 356 | return err |
| 357 | } |
| 358 | |
| 359 | // Pack the first few fields into the first 32 bits. |
| 360 | h := uint8(0) |
| 361 | h |= (uint8(d.LeapIndicator) << 6) & 0xC0 |
| 362 | h |= (uint8(d.Version) << 3) & 0x38 |
| 363 | h |= (uint8(d.Mode)) & 0x07 |
| 364 | data[0] = byte(h) |
| 365 | data[1] = byte(d.Stratum) |
| 366 | data[2] = byte(d.Poll) |
| 367 | data[3] = byte(d.Precision) |
| 368 | |
| 369 | // The remaining fields can just be copied in big endian order. |
| 370 | binary.BigEndian.PutUint32(data[4:8], uint32(d.RootDelay)) |
| 371 | binary.BigEndian.PutUint32(data[8:12], uint32(d.RootDispersion)) |
| 372 | binary.BigEndian.PutUint32(data[12:16], uint32(d.ReferenceID)) |
| 373 | binary.BigEndian.PutUint64(data[16:24], uint64(d.ReferenceTimestamp)) |
| 374 | binary.BigEndian.PutUint64(data[24:32], uint64(d.OriginTimestamp)) |
| 375 | binary.BigEndian.PutUint64(data[32:40], uint64(d.ReceiveTimestamp)) |
| 376 | binary.BigEndian.PutUint64(data[40:48], uint64(d.TransmitTimestamp)) |
| 377 | |
| 378 | ex, err := b.AppendBytes(len(d.ExtensionBytes)) |
| 379 | if err != nil { |
| 380 | return err |
| 381 | } |
| 382 | copy(ex, d.ExtensionBytes) |
| 383 | |
| 384 | return nil |
| 385 | } |
| 386 | |
| 387 | //****************************************************************************** |
| 388 | |
| 389 | // CanDecode returns a set of layers that NTP objects can decode. |
| 390 | // As NTP objects can only decide the NTP layer, we can return just that layer. |
| 391 | // Apparently a single layer type implements LayerClass. |
| 392 | func (d *NTP) CanDecode() gopacket.LayerClass { |
| 393 | return LayerTypeNTP |
| 394 | } |
| 395 | |
| 396 | //****************************************************************************** |
| 397 | |
| 398 | // NextLayerType specifies the next layer that GoPacket should attempt to |
| 399 | // analyse after this (NTP) layer. As NTP packets do not contain any payload |
| 400 | // bytes, there are no further layers to analyse. |
| 401 | func (d *NTP) NextLayerType() gopacket.LayerType { |
| 402 | return gopacket.LayerTypeZero |
| 403 | } |
| 404 | |
| 405 | //****************************************************************************** |
| 406 | |
| 407 | // NTP packets do not carry any data payload, so the empty byte slice is retured. |
| 408 | // In Go, a nil slice is functionally identical to an empty slice, so we |
| 409 | // return nil to avoid a heap allocation. |
| 410 | func (d *NTP) Payload() []byte { |
| 411 | return nil |
| 412 | } |
| 413 | |
| 414 | //****************************************************************************** |
| 415 | //* End Of NTP File * |
| 416 | //****************************************************************************** |