123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416 |
- // Copyright 2016 Google, Inc. All rights reserved.
- //
- // Use of this source code is governed by a BSD-style license
- // that can be found in the LICENSE file in the root of the source
- // tree.
- //
- //******************************************************************************
- package layers
- import (
- "encoding/binary"
- "errors"
- "github.com/google/gopacket"
- )
- //******************************************************************************
- //
- // Network Time Protocol (NTP) Decoding Layer
- // ------------------------------------------
- // This file provides a GoPacket decoding layer for NTP.
- //
- //******************************************************************************
- //
- // About The Network Time Protocol (NTP)
- // -------------------------------------
- // NTP is a protocol that enables computers on the internet to set their
- // clocks to the correct time (or to a time that is acceptably close to the
- // correct time). NTP runs on top of UDP.
- //
- // There have been a series of versions of the NTP protocol. The latest
- // version is V4 and is specified in RFC 5905:
- // http://www.ietf.org/rfc/rfc5905.txt
- //
- //******************************************************************************
- //
- // References
- // ----------
- //
- // Wikipedia's NTP entry:
- // https://en.wikipedia.org/wiki/Network_Time_Protocol
- // This is the best place to get an overview of NTP.
- //
- // Network Time Protocol Home Website:
- // http://www.ntp.org/
- // This appears to be the official website of NTP.
- //
- // List of current NTP Protocol RFCs:
- // http://www.ntp.org/rfc.html
- //
- // RFC 958: "Network Time Protocol (NTP)" (1985)
- // https://tools.ietf.org/html/rfc958
- // This is the original NTP specification.
- //
- // RFC 1305: "Network Time Protocol (Version 3) Specification, Implementation and Analysis" (1992)
- // https://tools.ietf.org/html/rfc1305
- // The protocol was updated in 1992 yielding NTP V3.
- //
- // RFC 5905: "Network Time Protocol Version 4: Protocol and Algorithms Specification" (2010)
- // https://www.ietf.org/rfc/rfc5905.txt
- // The protocol was updated in 2010 yielding NTP V4.
- // V4 is backwards compatible with all previous versions of NTP.
- //
- // RFC 5906: "Network Time Protocol Version 4: Autokey Specification"
- // https://tools.ietf.org/html/rfc5906
- // This document addresses the security of the NTP protocol
- // and is probably not relevant to this package.
- //
- // RFC 5907: "Definitions of Managed Objects for Network Time Protocol Version 4 (NTPv4)"
- // https://tools.ietf.org/html/rfc5907
- // This document addresses the management of NTP servers and
- // is probably not relevant to this package.
- //
- // RFC 5908: "Network Time Protocol (NTP) Server Option for DHCPv6"
- // https://tools.ietf.org/html/rfc5908
- // This document addresses the use of NTP in DHCPv6 and is
- // probably not relevant to this package.
- //
- // "Let's make a NTP Client in C"
- // https://lettier.github.io/posts/2016-04-26-lets-make-a-ntp-client-in-c.html
- // This web page contains useful information about the details of NTP,
- // including an NTP record struture in C, and C code.
- //
- // "NTP Packet Header (NTP Reference Implementation) (Computer Network Time Synchronization)"
- // http://what-when-how.com/computer-network-time-synchronization/
- // ntp-packet-header-ntp-reference-implementation-computer-network-time-synchronization/
- // This web page contains useful information on the details of NTP.
- //
- // "Technical information - NTP Data Packet"
- // https://www.meinbergglobal.com/english/info/ntp-packet.htm
- // This page has a helpful diagram of an NTP V4 packet.
- //
- //******************************************************************************
- //
- // Obsolete References
- // -------------------
- //
- // RFC 1119: "RFC-1119 "Network Time Protocol (Version 2) Specification and Implementation" (1989)
- // https://tools.ietf.org/html/rfc1119
- // Version 2 was drafted in 1989.
- // It is unclear whether V2 was ever implememented or whether the
- // ideas ended up in V3 (which was implemented in 1992).
- //
- // RFC 1361: "Simple Network Time Protocol (SNTP)"
- // https://tools.ietf.org/html/rfc1361
- // This document is obsoleted by RFC 1769 and is included only for completeness.
- //
- // RFC 1769: "Simple Network Time Protocol (SNTP)"
- // https://tools.ietf.org/html/rfc1769
- // This document is obsoleted by RFC 2030 and RFC 4330 and is included only for completeness.
- //
- // RFC 2030: "Simple Network Time Protocol (SNTP) Version 4 for IPv4, IPv6 and OSI"
- // https://tools.ietf.org/html/rfc2030
- // This document is obsoleted by RFC 4330 and is included only for completeness.
- //
- // RFC 4330: "Simple Network Time Protocol (SNTP) Version 4 for IPv4, IPv6 and OSI"
- // https://tools.ietf.org/html/rfc4330
- // This document is obsoleted by RFC 5905 and is included only for completeness.
- //
- //******************************************************************************
- //
- // Endian And Bit Numbering Issues
- // -------------------------------
- //
- // Endian and bit numbering issues can be confusing. Here is some
- // clarification:
- //
- // ENDIAN: Values are sent big endian.
- // https://en.wikipedia.org/wiki/Endianness
- //
- // BIT NUMBERING: Bits are numbered 0 upwards from the most significant
- // bit to the least significant bit. This means that if there is a 32-bit
- // value, the most significant bit is called bit 0 and the least
- // significant bit is called bit 31.
- //
- // See RFC 791 Appendix B for more discussion.
- //
- //******************************************************************************
- //
- // NTP V3 and V4 Packet Format
- // ---------------------------
- // NTP packets are UDP packets whose payload contains an NTP record.
- //
- // The NTP RFC defines the format of the NTP record.
- //
- // There have been four versions of the protocol:
- //
- // V1 in 1985
- // V2 in 1989
- // V3 in 1992
- // V4 in 2010
- //
- // It is clear that V1 and V2 are obsolete, and there is no need to
- // cater for these formats.
- //
- // V3 and V4 essentially use the same format, with V4 adding some optional
- // fields on the end. So this package supports the V3 and V4 formats.
- //
- // The current version of NTP (NTP V4)'s RFC (V4 - RFC 5905) contains
- // the following diagram for the NTP record 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
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // |LI | VN |Mode | Stratum | Poll | 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 |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | |
- // | dgst (128) |
- // | |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // From http://www.ietf.org/rfc/rfc5905.txt
- //
- // The fields "Extension Field 1 (variable)" and later are optional fields,
- // and so we can set a minimum NTP record size of 48 bytes.
- //
- const ntpMinimumRecordSizeInBytes int = 48
- //******************************************************************************
- // NTP Type
- // --------
- // Type NTP implements the DecodingLayer interface. Each NTP object
- // represents in a structured form the NTP record present as the UDP
- // payload in an NTP UDP packet.
- //
- type NTPLeapIndicator uint8
- type NTPVersion uint8
- type NTPMode uint8
- type NTPStratum uint8
- type NTPLog2Seconds int8
- type NTPFixed16Seconds uint32
- type NTPReferenceID uint32
- type NTPTimestamp uint64
- type NTP struct {
- BaseLayer // Stores the packet bytes and payload bytes.
- LeapIndicator NTPLeapIndicator // [0,3]. Indicates whether leap second(s) is to be added.
- Version NTPVersion // [0,7]. Version of the NTP protocol.
- Mode NTPMode // [0,7]. Mode.
- Stratum NTPStratum // [0,255]. Stratum of time server in the server tree.
- Poll NTPLog2Seconds // [-128,127]. The maximum interval between successive messages, in log2 seconds.
- Precision NTPLog2Seconds // [-128,127]. The precision of the system clock, in log2 seconds.
- RootDelay NTPFixed16Seconds // [0,2^32-1]. Total round trip delay to the reference clock in seconds times 2^16.
- RootDispersion NTPFixed16Seconds // [0,2^32-1]. Total dispersion to the reference clock, in seconds times 2^16.
- ReferenceID NTPReferenceID // ID code of reference clock [0,2^32-1].
- ReferenceTimestamp NTPTimestamp // Most recent timestamp from the reference clock.
- OriginTimestamp NTPTimestamp // Local time when request was sent from local host.
- ReceiveTimestamp NTPTimestamp // Local time (on server) that request arrived at server host.
- TransmitTimestamp NTPTimestamp // Local time (on server) that request departed server host.
- // FIX: This package should analyse the extension fields and represent the extension fields too.
- ExtensionBytes []byte // Just put extensions in a byte slice.
- }
- //******************************************************************************
- // LayerType returns the layer type of the NTP object, which is LayerTypeNTP.
- func (d *NTP) LayerType() gopacket.LayerType {
- return LayerTypeNTP
- }
- //******************************************************************************
- // decodeNTP analyses a byte slice and attempts to decode it as an NTP
- // record of a UDP packet.
- //
- // If it succeeds, it loads p with information about the packet and returns nil.
- // If it fails, it returns an error (non nil).
- //
- // This function is employed in layertypes.go to register the NTP layer.
- func decodeNTP(data []byte, p gopacket.PacketBuilder) error {
- // Attempt to decode the byte slice.
- d := &NTP{}
- err := d.DecodeFromBytes(data, p)
- if err != nil {
- return err
- }
- // If the decoding worked, add the layer to the packet and set it
- // as the application layer too, if there isn't already one.
- p.AddLayer(d)
- p.SetApplicationLayer(d)
- return nil
- }
- //******************************************************************************
- // DecodeFromBytes analyses a byte slice and attempts to decode it as an NTP
- // record of a UDP packet.
- //
- // Upon succeeds, it loads the NTP object with information about the packet
- // and returns nil.
- // Upon failure, it returns an error (non nil).
- func (d *NTP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
- // If the data block is too short to be a NTP record, then return an error.
- if len(data) < ntpMinimumRecordSizeInBytes {
- df.SetTruncated()
- return errors.New("NTP packet too short")
- }
- // RFC 5905 does not appear to define a maximum NTP record length.
- // The protocol allows "extension fields" to be included in the record,
- // and states about these fields:"
- //
- // "While the minimum field length containing required fields is
- // four words (16 octets), a maximum field length remains to be
- // established."
- //
- // For this reason, the packet length is not checked here for being too long.
- // NTP type embeds type BaseLayer which contains two fields:
- // Contents is supposed to contain the bytes of the data at this level.
- // Payload is supposed to contain the payload of this level.
- // Here we set the baselayer to be the bytes of the NTP record.
- d.BaseLayer = BaseLayer{Contents: data[:len(data)]}
- // Extract the fields from the block of bytes.
- // To make sense of this, refer to the packet diagram
- // above and the section on endian conventions.
- // The first few fields are all packed into the first 32 bits. Unpack them.
- f := data[0]
- d.LeapIndicator = NTPLeapIndicator((f & 0xC0) >> 6)
- d.Version = NTPVersion((f & 0x38) >> 3)
- d.Mode = NTPMode(f & 0x07)
- d.Stratum = NTPStratum(data[1])
- d.Poll = NTPLog2Seconds(data[2])
- d.Precision = NTPLog2Seconds(data[3])
- // The remaining fields can just be copied in big endian order.
- d.RootDelay = NTPFixed16Seconds(binary.BigEndian.Uint32(data[4:8]))
- d.RootDispersion = NTPFixed16Seconds(binary.BigEndian.Uint32(data[8:12]))
- d.ReferenceID = NTPReferenceID(binary.BigEndian.Uint32(data[12:16]))
- d.ReferenceTimestamp = NTPTimestamp(binary.BigEndian.Uint64(data[16:24]))
- d.OriginTimestamp = NTPTimestamp(binary.BigEndian.Uint64(data[24:32]))
- d.ReceiveTimestamp = NTPTimestamp(binary.BigEndian.Uint64(data[32:40]))
- d.TransmitTimestamp = NTPTimestamp(binary.BigEndian.Uint64(data[40:48]))
- // This layer does not attempt to analyse the extension bytes.
- // But if there are any, we'd like the user to know. So we just
- // place them all in an ExtensionBytes field.
- d.ExtensionBytes = data[48:]
- // Return no error.
- return nil
- }
- // SerializeTo writes the serialized form of this layer into the
- // SerializationBuffer, implementing gopacket.SerializableLayer.
- // See the docs for gopacket.SerializableLayer for more info.
- func (d *NTP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
- data, err := b.PrependBytes(ntpMinimumRecordSizeInBytes)
- if err != nil {
- return err
- }
- // Pack the first few fields into the first 32 bits.
- h := uint8(0)
- h |= (uint8(d.LeapIndicator) << 6) & 0xC0
- h |= (uint8(d.Version) << 3) & 0x38
- h |= (uint8(d.Mode)) & 0x07
- data[0] = byte(h)
- data[1] = byte(d.Stratum)
- data[2] = byte(d.Poll)
- data[3] = byte(d.Precision)
- // The remaining fields can just be copied in big endian order.
- binary.BigEndian.PutUint32(data[4:8], uint32(d.RootDelay))
- binary.BigEndian.PutUint32(data[8:12], uint32(d.RootDispersion))
- binary.BigEndian.PutUint32(data[12:16], uint32(d.ReferenceID))
- binary.BigEndian.PutUint64(data[16:24], uint64(d.ReferenceTimestamp))
- binary.BigEndian.PutUint64(data[24:32], uint64(d.OriginTimestamp))
- binary.BigEndian.PutUint64(data[32:40], uint64(d.ReceiveTimestamp))
- binary.BigEndian.PutUint64(data[40:48], uint64(d.TransmitTimestamp))
- ex, err := b.AppendBytes(len(d.ExtensionBytes))
- if err != nil {
- return err
- }
- copy(ex, d.ExtensionBytes)
- return nil
- }
- //******************************************************************************
- // CanDecode returns a set of layers that NTP objects can decode.
- // As NTP objects can only decide the NTP layer, we can return just that layer.
- // Apparently a single layer type implements LayerClass.
- func (d *NTP) CanDecode() gopacket.LayerClass {
- return LayerTypeNTP
- }
- //******************************************************************************
- // NextLayerType specifies the next layer that GoPacket should attempt to
- // analyse after this (NTP) layer. As NTP packets do not contain any payload
- // bytes, there are no further layers to analyse.
- func (d *NTP) NextLayerType() gopacket.LayerType {
- return gopacket.LayerTypeZero
- }
- //******************************************************************************
- // NTP packets do not carry any data payload, so the empty byte slice is retured.
- // In Go, a nil slice is functionally identical to an empty slice, so we
- // return nil to avoid a heap allocation.
- func (d *NTP) Payload() []byte {
- return nil
- }
- //******************************************************************************
- //* End Of NTP File *
- //******************************************************************************
|