Coverage Report

Created: 2025-07-11 07:47

/src/PcapPlusPlus/Packet++/header/NtpLayer.h
Line
Count
Source
1
#pragma once
2
3
#include "Logger.h"
4
#include "Layer.h"
5
#include "IpAddress.h"
6
7
/// @file
8
9
/// @namespace pcpp
10
/// @brief The main namespace for the PcapPlusPlus lib
11
namespace pcpp
12
{
13
  /// @class NtpLayer
14
  /// Represents a NTP (Network Time Protocol) layer
15
  ///
16
  /// @brief The NTP packet consists of an integral number of 32-bit (4 octet) words in network byte order.
17
  /// The packet format consists of three components: the header itself, one or more optional extension fields (for
18
  /// v4), and an optional message authentication code (MAC). Currently the extension fields are not supported. The
19
  /// NTP header is:
20
  ///
21
  /// @code{.unparsed}
22
  ///  0                   1                   2                   3
23
  ///  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
24
  /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25
  /// |LI | VN  |Mode |    Stratum     |     Poll      |  Precision   |
26
  /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27
  /// |                         Root Delay                            |
28
  /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29
  /// |                         Root Dispersion                       |
30
  /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31
  /// |                          Reference ID                         |
32
  /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33
  /// |                                                               |
34
  /// +                     Reference Timestamp (64)                  +
35
  /// |                                                               |
36
  /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37
  /// |                                                               |
38
  /// +                      Origin Timestamp (64)                    +
39
  /// |                                                               |
40
  /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41
  /// |                                                               |
42
  /// +                      Receive Timestamp (64)                   +
43
  /// |                                                               |
44
  /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45
  /// |                                                               |
46
  /// +                      Transmit Timestamp (64)                  +
47
  /// |                                                               |
48
  /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49
  /// |                                                               |
50
  /// .                                                               .
51
  /// .                Extension Field 1 (variable, only v4)          .
52
  /// .                                                               .
53
  /// |                                                               |
54
  /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55
  /// |                                                               |
56
  /// .                                                               .
57
  /// .                Extension Field 1 (variable, only v4)          .
58
  /// .                                                               .
59
  /// |                                                               |
60
  /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61
  /// |                          Key Identifier                       |
62
  /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63
  /// |                                                               |
64
  /// |                   dgst (128 for v4, 64 for v3)                |
65
  /// |                                                               |
66
  /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
67
  /// @endcode
68
  class NtpLayer : public Layer
69
  {
70
  private:
71
#pragma pack(push, 1)
72
    struct ntp_header
73
    {
74
#if (BYTE_ORDER == LITTLE_ENDIAN)
75
      /// 3-bit integer representing the mode
76
      uint8_t mode : 3,
77
          /// 3-bit integer representing the NTP version number
78
          version : 3,
79
          /// LI Leap Indicator (leap): 2-bit integer warning of an impending leap second to be inserted or
80
          /// deleted in the last minute of the current month
81
          leapIndicator : 2;
82
#else
83
      /// LI Leap Indicator (leap): 2-bit integer warning of an impending leap second to be inserted or deleted in
84
      /// the last minute of the current month
85
      uint8_t leapIndicator : 2,
86
          /// 3-bit integer representing the NTP version number
87
          version : 3,
88
          /// 3-bit integer representing the mode
89
          mode : 3;
90
#endif
91
      /// 8-bit integer representing the stratum
92
      uint8_t stratum;
93
      /// Total round-trip delay to the reference clock, in log2 seconds.
94
      int8_t pollInterval,
95
          /// 8-bit signed integer representing the precision of the system clock, in log2 seconds.
96
          precision;
97
      /// Total round-trip delay to the reference clock, in NTP short format.
98
      uint32_t rootDelay,
99
          /// Total dispersion to the reference clock, in NTP short format.
100
          rootDispersion,
101
          /// 32-bit code identifying the particular server or reference clock.  The interpretation depends on the
102
          /// value in the stratum field.
103
          referenceIdentifier;
104
      /// Time when the system clock was last set or corrected, in NTP timestamp format.
105
      uint64_t referenceTimestamp,
106
          /// Time at the client when the request departed for the server, in NTP timestamp format.
107
          originTimestamp,
108
          /// Time at the client when the request departed for the server, in NTP timestamp format.
109
          receiveTimestamp,
110
          /// Time at the server when the response left for the client, in NTP timestamp format.
111
          transmitTimestamp;
112
    };
113
#pragma pack(pop)
114
    static_assert(sizeof(ntp_header) == 48, "ntp_header size is not 48 bytes");
115
116
#pragma pack(push, 1)
117
    struct ntp_v3_auth
118
    {
119
      /// An integer identifying the cryptographic key used to generate the message-authentication code
120
      uint32_t keyID;
121
      /// This is an integer identifying the cryptographic key used to generate the message-authentication code.
122
      uint8_t dgst[8];  // 64 bit DES based
123
    };
124
#pragma pack(pop)
125
    static_assert(sizeof(ntp_v3_auth) == 12, "ntp_v3_auth size is not 12 bytes");
126
127
#pragma pack(push, 1)
128
    struct ntp_v4_auth_md5
129
    {
130
      /// 32-bit unsigned integer used by the client and server to designate a secret 128-bit MD5 key.
131
      uint32_t keyID;
132
      /// 128-bit MD5 hash
133
      uint8_t dgst[16];
134
    };
135
#pragma pack(pop)
136
    static_assert(sizeof(ntp_v4_auth_md5) == 20, "ntp_v4_auth_md5 size is not 20 bytes");
137
138
#pragma pack(push, 1)
139
    struct ntp_v4_auth_sha1
140
    {
141
      /// 32-bit unsigned integer used by the client and server to designate a secret 160-bit SHA1 key.
142
      uint32_t keyID;
143
      /// 160-bit SHA1 hash
144
      uint8_t dgst[20];
145
    };
146
#pragma pack(pop)
147
    static_assert(sizeof(ntp_v4_auth_sha1) == 24, "ntp_v4_auth_sha1 size is not 24 bytes");
148
149
    ntp_header* getNtpHeader() const
150
29.6k
    {
151
29.6k
      return reinterpret_cast<ntp_header*>(m_Data);
152
29.6k
    }
153
154
  public:
155
    /// Warning of an impending leap second to be inserted or deleted in the last minute of the current month
156
    enum LeapIndicator
157
    {
158
      /// Normal, no leap second
159
      NoWarning = 0,
160
      /// Last minute of the day has 61 seconds
161
      Last61Secs,
162
      /// Last minute of the day has 59 seconds
163
      Last59Secs,
164
      /// Unknown (clock unsynchronized)
165
      Unknown
166
    };
167
168
    /// Representing the NTP association modes
169
    enum Mode
170
    {
171
      /// Reserved variable
172
      Reserved = 0,
173
      /// Symmetrically active
174
      SymActive,
175
      /// Symmetrically passive
176
      SymPassive,
177
      /// Client mode
178
      Client,
179
      /// Server mode
180
      Server,
181
      /// Broadcasting mode
182
      Broadcast,
183
      /// NTP control messages
184
      Control,
185
      /// Reserved for private use
186
      PrivateUse
187
    };
188
189
    /// 32-bit code identifying the particular server or reference clock.
190
    /// The interpretation depends on the value in the stratum field.
191
    enum class ClockSource : uint32_t
192
    {
193
      // NTPv4
194
195
      /// Geosynchronous Orbit Environment Satellite
196
      GOES = ('G') | ('O' << 8) | ('E' << 16) | ('S' << 24),
197
      /// Global Position System
198
      GPS = ('G') | ('P' << 8) | ('S' << 16),
199
      /// Galileo Positioning System
200
      GAL = ('G') | ('A' << 8) | ('L' << 16),
201
      /// Generic pulse-per-second
202
      PPS = ('P') | ('P' << 8) | ('S' << 16),
203
      /// Inter-Range Instrumentation Group
204
      IRIG = ('I') | ('R' << 8) | ('I' << 16) | ('G' << 24),
205
      /// LF Radio WWVB Ft. Collins, CO 60 kHz
206
      WWVB = ('W') | ('W' << 8) | ('V' << 16) | ('B' << 24),
207
      /// LF Radio DCF77 Mainflingen, DE 77.5 kHz
208
      DCF = ('D') | ('C' << 8) | ('F' << 16),
209
      /// LF Radio HBG Prangins, HB 75 kHz
210
      HBG = ('H') | ('B' << 8) | ('G' << 16),
211
      /// LF Radio MSF Anthorn, UK 60 kHz
212
      MSF = ('M') | ('S' << 8) | ('F' << 16),
213
      /// LF Radio JJY Fukushima, JP 40 kHz, Saga, JP 60 kHz
214
      JJY = ('J') | ('J' << 8) | ('Y' << 16),
215
      /// MF Radio LORAN C station, 100 kHz
216
      LORC = ('L') | ('O' << 8) | ('R' << 16) | ('C' << 24),
217
      /// MF Radio Allouis, FR 162 kHz
218
      TDF = ('T') | ('D' << 8) | ('F' << 16),
219
      /// HF Radio CHU Ottawa, Ontario
220
      CHU = ('C') | ('H' << 8) | ('U' << 16),
221
      /// HF Radio WWV Ft. Collins, CO
222
      WWV = ('W') | ('W' << 8) | ('V' << 16),
223
      /// HF Radio WWVH Kauai, HI
224
      WWVH = ('W') | ('W' << 8) | ('V' << 16) | ('H' << 24),
225
      /// NIST telephone modem
226
      NIST = ('N') | ('I' << 8) | ('S' << 16) | ('T' << 24),
227
      /// NIST telephone modem
228
      ACTS = ('A') | ('C' << 8) | ('T' << 16) | ('S' << 24),
229
      /// USNO telephone modem
230
      USNO = ('U') | ('S' << 8) | ('N' << 16) | ('O' << 24),
231
      /// European telephone modem
232
      PTB = ('P') | ('T' << 8) | ('B' << 16),
233
      /// Multi Reference Sources
234
      MRS = ('M') | ('R' << 8) | ('S' << 16),
235
      /// Inter Face Association Changed
236
      XFAC = ('X') | ('F' << 8) | ('A' << 16) | ('C' << 24),
237
      /// Step time change
238
      STEP = ('S') | ('T' << 8) | ('E' << 16) | ('P' << 24),
239
      /// Google Refid used by Google NTP servers as time4.google.com
240
      GOOG = ('G') | ('O' << 8) | ('O' << 16) | ('G' << 24),
241
      /// Meinberg DCF77 with amplitude modulation (Ref:
242
      /// https://www.meinbergglobal.com/english/info/ntp-refid.htm)
243
      DCFa = ('D') | ('C' << 8) | ('F' << 16) | ('a' << 24),
244
      /// Meinberg DCF77 with phase modulation)/pseudo random phase modulation (Ref:
245
      /// https://www.meinbergglobal.com/english/info/ntp-refid.htm)
246
      DCFp = ('D') | ('C' << 8) | ('F' << 16) | ('p' << 24),
247
      /// Meinberg GPS (with shared memory access) (Ref:
248
      /// https://www.meinbergglobal.com/english/info/ntp-refid.htm)
249
      GPSs = ('G') | ('P' << 8) | ('S' << 16) | ('s' << 24),
250
      /// Meinberg GPS (with interrupt based access) (Ref:
251
      /// https://www.meinbergglobal.com/english/info/ntp-refid.htm)
252
      GPSi = ('G') | ('P' << 8) | ('S' << 16) | ('i' << 24),
253
      /// Meinberg GPS/GLONASS (with shared memory access) (Ref:
254
      /// https://www.meinbergglobal.com/english/info/ntp-refid.htm)
255
      GLNs = ('G') | ('L' << 8) | ('N' << 16) | ('s' << 24),
256
      /// Meinberg GPS/GLONASS (with interrupt based access) (Ref:
257
      /// https://www.meinbergglobal.com/english/info/ntp-refid.htm)
258
      GLNi = ('G') | ('L' << 8) | ('N' << 16) | ('i' << 24),
259
      /// Meinberg Undisciplined local clock (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm)
260
      LCL = ('L') | ('C' << 8) | ('L' << 16),
261
      /// Meinberg Undisciplined local clock (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm)
262
      LOCL = ('L') | ('O' << 8) | ('C' << 16) | ('L' << 24),
263
264
      // NTPv3
265
266
      /// DCN routing protocol
267
      DCN = ('D') | ('C' << 8) | ('N' << 16),
268
      /// TSP time protocol
269
      TSP = ('T') | ('S' << 8) | ('P' << 16),
270
      /// Digital Time Service
271
      DTS = ('D') | ('T' << 8) | ('S' << 16),
272
      /// Atomic clock (calibrated)
273
      ATOM = ('A') | ('T' << 8) | ('O' << 16) | ('M' << 24),
274
      /// VLF radio (OMEGA, etc.)
275
      VLF = ('V') | ('L' << 8) | ('F' << 16)
276
    };
277
278
    /// 32-bit Kiss of Death (KoD) codes
279
    enum class KissODeath : uint32_t
280
    {
281
      /// The association belongs to a anycast server
282
      ACST = ('A') | ('C' << 8) | ('S' << 16) | ('T' << 24),
283
      /// Server authentication failed
284
      AUTH = ('A') | ('U' << 8) | ('T' << 16) | ('H' << 24),
285
      /// Autokey sequence failed
286
      AUTO = ('A') | ('U' << 8) | ('T' << 16) | ('O' << 24),
287
      /// The association belongs to a broadcast server
288
      BCST = ('B') | ('C' << 8) | ('S' << 16) | ('T' << 24),
289
      /// Cryptographic authentication or identification failed
290
      CRYP = ('C') | ('R' << 8) | ('Y' << 16) | ('P' << 24),
291
      /// Access denied by remote server
292
      DENY = ('D') | ('E' << 8) | ('N' << 16) | ('Y' << 24),
293
      /// Lost peer in symmetric mode
294
      DROP = ('D') | ('R' << 8) | ('O' << 16) | ('P' << 24),
295
      /// Access denied due to local policy
296
      RSTR = ('R') | ('S' << 8) | ('T' << 16) | ('R' << 24),
297
      /// The association has not yet synchronized for the first time
298
      INIT = ('I') | ('N' << 8) | ('I' << 16) | ('T' << 24),
299
      /// The association belongs to a manycast server
300
      MCST = ('M') | ('C' << 8) | ('S' << 16) | ('T' << 24),
301
      /// No key found.  Either the key was never installed or is not trusted
302
      NKEY = ('N') | ('K' << 8) | ('E' << 16) | ('Y' << 24),
303
      /// Rate exceeded.  The server has temporarily denied access because the client exceeded the rate threshold
304
      RATE = ('R') | ('A' << 8) | ('T' << 16) | ('E' << 24),
305
      /// Somebody is tinkering with the association from a remote host running ntpdc.  Not to worry unless some
306
      /// rascal has stolen your keys
307
      RMOT = ('R') | ('M' << 8) | ('O' << 16) | ('T' << 24),
308
      /// A step change in system time has occurred, but the association has not yet resynchronized
309
      STEP = ('S') | ('T' << 8) | ('E' << 16) | ('P' << 24),
310
    };
311
312
    /// A constructor that creates the layer from an existing packet raw data
313
    /// @param[in] data A pointer to the raw data
314
    /// @param[in] dataLen Size of the data in bytes
315
    /// @param[in] prevLayer A pointer to the previous layer
316
    /// @param[in] packet A pointer to the Packet instance where layer will be stored in
317
    NtpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
318
3.58k
        : Layer(data, dataLen, prevLayer, packet, NTP)
319
3.58k
    {}
320
321
    /// Empty c'tor
322
    NtpLayer();
323
324
    /// @return The leap indicator
325
    LeapIndicator getLeapIndicator() const;
326
327
    /// Set the leap indicator
328
    void setLeapIndicator(LeapIndicator val);
329
330
    /// @return The version of NTP
331
    uint8_t getVersion() const;
332
333
    /// Set the version of NTP
334
    void setVersion(uint8_t val);
335
336
    /// @return The mode value
337
    Mode getMode() const;
338
339
    /// @return The mode as string
340
    std::string getModeString() const;
341
342
    /// Set the mode
343
    void setMode(Mode val);
344
345
    /// @return The value of stratum
346
    uint8_t getStratum() const;
347
348
    /// Set the value of stratum
349
    void setStratum(uint8_t val);
350
351
    /// @return The value of poll interval in log2 seconds
352
    int8_t getPollInterval() const;
353
354
    /// Set the value of poll interval
355
    /// @param[in] val Poll interval in log2 seconds
356
    void setPollInterval(int8_t val);
357
358
    /// @return The value of poll interval in seconds
359
    double getPollIntervalInSecs() const;
360
361
    /// @return The value of precision in log2 seconds
362
    int8_t getPrecision() const;
363
364
    /// Set the value of precision
365
    /// @param[in] val Precision in log2 seconds
366
    void setPrecision(int8_t val);
367
368
    /// @return The value of precision in seconds
369
    double getPrecisionInSecs() const;
370
371
    /// @return The value of root delay in NTP short format
372
    uint32_t getRootDelay() const;
373
374
    /// Set the value of root delay
375
    /// @param[in] val Root delay in NTP short format
376
    void setRootDelay(uint32_t val);
377
378
    /// @return The value of root delay in seconds
379
    double getRootDelayInSecs() const;
380
381
    /// Set the value of root delay
382
    /// @param[in] val Root delay in seconds
383
    void setRootDelayInSecs(double val);
384
385
    /// @return The value of root dispersion in NTP short format
386
    uint32_t getRootDispersion() const;
387
388
    /// Set the value of root delay
389
    /// @param[in] val Root dispersion in NTP short format
390
    void setRootDispersion(uint32_t val);
391
392
    /// @return The value of root dispersion in seconds
393
    double getRootDispersionInSecs() const;
394
395
    /// Set the value of root dispersion
396
    /// @param[in] val Root dispersion in seconds
397
    void setRootDispersionInSecs(double val);
398
399
    /// @return The value of reference identifier
400
    uint32_t getReferenceIdentifier() const;
401
402
    /// Set the value of reference identifier
403
    /// @param[in] val Value of the reference identifier as IPv4 address
404
    void setReferenceIdentifier(IPv4Address val);
405
406
    /// Set the value of reference identifier
407
    /// @param[in] val Value of the reference identifier as ClockSource
408
    void setReferenceIdentifier(ClockSource val);
409
410
    /// Set the value of reference identifier
411
    /// @param[in] val Value of the reference identifier as Kiss-O-Death code
412
    void setReferenceIdentifier(KissODeath val);
413
414
    /// @return The value of reference identifier as a string. String representation of NTP clock source if
415
    /// stratum is 1, IPv4 address or MD5 hash of first four octets of IPv6
416
    std::string getReferenceIdentifierString() const;
417
418
    /// @return The value of reference timestamp in NTP timestamp format
419
    uint64_t getReferenceTimestamp() const;
420
421
    /// Set the value of reference timestamp
422
    /// @param[in] val Timestamp in NTP timestamp format
423
    void setReferenceTimestamp(uint64_t val);
424
425
    /// @return The value of reference timestamp in seconds from Unix Epoch (1 Jan 1970)
426
    double getReferenceTimestampInSecs() const;
427
428
    /// Set the value of reference timestamp
429
    /// @param[in] val Value in seconds from Unix Epoch (1 Jan 1970)
430
    void setReferenceTimestampInSecs(double val);
431
432
    /// @return The reference timestamp value as readable string in ISO8601 format
433
    std::string getReferenceTimestampAsString();
434
435
    /// @return The value of origin timestamp in NTP timestamp format
436
    uint64_t getOriginTimestamp() const;
437
438
    /// Set the value of origin timestamp
439
    /// @param[in] val Value in NTP timestamp format
440
    void setOriginTimestamp(uint64_t val);
441
442
    /// @return The value of origin timestamp in seconds from Unix Epoch (1 Jan 1970)
443
    double getOriginTimestampInSecs() const;
444
445
    /// Set the value of origin timestamp
446
    /// @param[in] val Value in seconds from Unix Epoch (1 Jan 1970)
447
    void setOriginTimestampInSecs(double val);
448
449
    /// @return the origin timestamp value as readable string in ISO8601 format
450
    std::string getOriginTimestampAsString();
451
452
    /// @return The value of receive timestamp in NTP timestamp format
453
    uint64_t getReceiveTimestamp() const;
454
455
    /// Set the value of receive timestamp
456
    /// @param[in] val Value in NTP timestamp format
457
    void setReceiveTimestamp(uint64_t val);
458
459
    /// @return The value of receive timestampin seconds from Unix Epoch (1 Jan 1970)
460
    double getReceiveTimestampInSecs() const;
461
462
    /// Set the value of receive timestamp
463
    /// @param[in] val Value in seconds from Unix Epoch (1 Jan 1970)
464
    void setReceiveTimestampInSecs(double val);
465
466
    /// @return The receive timestamp value as readable string in ISO8601 format
467
    std::string getReceiveTimestampAsString();
468
469
    /// @return The value of transmit timestamp in NTP timestamp format
470
    uint64_t getTransmitTimestamp() const;
471
472
    /// Set the value of transmit timestamp
473
    /// @param[in] val Value in NTP timestamp format
474
    void setTransmitTimestamp(uint64_t val);
475
476
    /// @return The value of transmit timestamp in seconds from Unix Epoch (1 Jan 1970)
477
    double getTransmitTimestampInSecs() const;
478
479
    /// Set the value of transmit timestamp
480
    /// @param[in] val Value in seconds from Unix Epoch (1 Jan 1970)
481
    void setTransmitTimestampInSecs(double val);
482
483
    /// @return The transmit timestamp value as readable string in ISO8601 format
484
    std::string getTransmitTimestampAsString();
485
486
    /// @return Returns the key identifier if exists, returns 0 on unsupported NTP version or key identifier not
487
    /// found
488
    uint32_t getKeyID() const;
489
490
    /// @return Get the digest value as hexadecimal string, empty string on unsupported version
491
    std::string getDigest() const;
492
493
    /// Convert NTP short format to seconds from the Unix Epoch
494
    /// @param[in] val Value in NTP short format
495
    /// @return Value in seconds from Unix Epoch (1 Jan 1970)
496
    static double convertFromShortFormat(const uint32_t val);
497
498
    /// Convert NTP timestamp format to seconds from the Unix Epoch
499
    /// @param[in] val Value in NTP timestamp format
500
    /// @return Value in seconds from Unix Epoch (1 Jan 1970)
501
    static double convertFromTimestampFormat(const uint64_t val);
502
503
    /// Convert seconds from the Unix Epoch to NTP short format
504
    /// @param[in] val Value in seconds from Unix Epoch (1 Jan 1970)
505
    /// @return Value in NTP short format
506
    static uint32_t convertToShortFormat(const double val);
507
508
    /// Convert seconds from the Unix Epoch to NTP timestamp format
509
    /// @param[in] val Value in seconds from Unix Epoch (1 Jan 1970)
510
    /// @return Value in NTP timestamp format
511
    static uint64_t convertToTimestampFormat(const double val);
512
513
    /// A static method to convert timestamp value to ISO8601 date time format
514
    /// @param[in] timestamp Value in seconds from the Unix Epoch
515
    /// @return std::string ISO8601 formatted string
516
    static std::string convertToIsoFormat(const double timestamp);
517
518
    /// A static method to convert timestamp value to ISO8601 date time format
519
    /// @param[in] timestampInNTPformat Value in NTP timestamp format
520
    /// @return std::string ISO8601 formatted string
521
    static std::string convertToIsoFormat(const uint64_t timestampInNTPformat);
522
523
    /// A static method that takes a byte array and detects whether it is a NTP message
524
    /// @param[in] data A byte array
525
    /// @param[in] dataSize The byte array size (in bytes)
526
    /// @return True if the data is identified as NTP message
527
    static bool isDataValid(const uint8_t* data, size_t dataSize);
528
529
    /// A static method that checks whether the port is considered as NTP
530
    /// @param[in] port The port number to be checked
531
    static bool isNTPPort(uint16_t port)
532
55.4k
    {
533
55.4k
      return port == 123;
534
55.4k
    }
535
536
    // overridden methods
537
538
    /// Parses the next layer. NTP is the always last so does nothing for this layer
539
    void parseNextLayer() override
540
3.58k
    {}
541
542
    /// @return Get the size of the layer (Including the extension and authentication fields if exists)
543
    size_t getHeaderLen() const override
544
1.43k
    {
545
1.43k
      return m_DataLen;
546
1.43k
    }
547
548
    /// Does nothing for this layer
549
    void computeCalculateFields() override
550
716
    {}
551
552
    /// @return The OSI layer level of NTP (Application Layer).
553
    OsiModelLayer getOsiModelLayer() const override
554
716
    {
555
716
      return OsiModelApplicationLayer;
556
716
    }
557
558
    /// @return Returns the protocol info as readable string
559
    std::string toString() const override;
560
  };
561
}  // namespace pcpp