pcapplusplus-sys 0.1.0

Compile PcapPlusPlus and make its library and header files available. See also https://github.com/seladb/PcapPlusPlus
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
#ifndef PACKETPP_NTP_LAYER
#define PACKETPP_NTP_LAYER

#include "Logger.h"
#include "Layer.h"
#include "IpAddress.h"

/// @file

/**
 * \namespace pcpp
 * \brief The main namespace for the PcapPlusPlus lib
 */
namespace pcpp
{
    /**
	 * @class NtpLayer
	 * Represents a NTP (Network Time Protocol) layer
     *
     * @brief The NTP packet consists of an integral number of 32-bit (4 octet) words in network byte order.
     * The packet format consists of three components: the header itself, one or more optional extension fields (for v4),
     * and an optional message authentication code (MAC). Currently the extension fields are not supported. The NTP header is:
     *
     * @verbatim
       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, only v4)          .
      .                                                               .
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                               |
      .                                                               .
      .                Extension Field 1 (variable, only v4)          .
      .                                                               .
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                          Key Identifier                       |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                               |
      |                   dgst (128 for v4, 64 for v3)                |
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     @endverbatim
     *
	 */
    class NtpLayer : public Layer
    {
    private:
#pragma pack(push, 1)
        struct ntp_header
        {
#if (BYTE_ORDER == LITTLE_ENDIAN)
            /// 3-bit integer representing the mode
            uint8_t mode:3,
            /// 3-bit integer representing the NTP version number
            version:3,
            /// LI Leap Indicator (leap): 2-bit integer warning of an impending leap second to be inserted or deleted in the last minute of the current month
            leapIndicator:2;
#else
            /// LI Leap Indicator (leap): 2-bit integer warning of an impending leap second to be inserted or deleted in the last minute of the current month
            uint8_t leapIndicator:2,
            /// 3-bit integer representing the NTP version number
            version:3,
            /// 3-bit integer representing the mode
            mode:3;
#endif
            /// 8-bit integer representing the stratum
            uint8_t stratum;
            /// Total round-trip delay to the reference clock, in log2 seconds.
            int8_t pollInterval,
            /// 8-bit signed integer representing the precision of the system clock, in log2 seconds.
            precision;
            /// Total round-trip delay to the reference clock, in NTP short format.
            uint32_t rootDelay,
            /// Total dispersion to the reference clock, in NTP short format.
            rootDispersion,
            /// 32-bit code identifying the particular server or reference clock.  The interpretation depends on the value in the stratum field.
            referenceIdentifier;
            /// Time when the system clock was last set or corrected, in NTP timestamp format.
            uint64_t referenceTimestamp,
            /// Time at the client when the request departed for the server, in NTP timestamp format.
            originTimestamp,
            /// Time at the client when the request departed for the server, in NTP timestamp format.
            receiveTimestamp,
            /// Time at the server when the response left for the client, in NTP timestamp format.
            transmitTimestamp;
        };
#pragma pack(pop)

#pragma pack(push, 1)
        struct ntp_v3_auth
        {
            /// An integer identifying the cryptographic key used to generate the message-authentication code
            uint32_t keyID;
            /// This is an integer identifying the cryptographic key used to generate the message-authentication code.
            uint8_t dgst[8]; // 64 bit DES based
        };
#pragma pack(pop)

#pragma pack(push, 1)
        struct ntp_v4_auth_md5
        {
            /// 32-bit unsigned integer used by the client and server to designate a secret 128-bit MD5 key.
            uint32_t keyID;
            /// 128-bit MD5 hash
            uint8_t dgst[16];
        };
#pragma pack(pop)

#pragma pack(push, 1)
        struct ntp_v4_auth_sha1
        {
            /// 32-bit unsigned integer used by the client and server to designate a secret 160-bit SHA1 key.
            uint32_t keyID;
            /// 160-bit SHA1 hash
            uint8_t dgst[20];
        };
#pragma pack(pop)

        ntp_header *getNtpHeader() const { return (ntp_header *)m_Data; }

    public:
        /**
        * Warning of an impending leap second to be inserted or deleted in the last minute of the current month
        */
        enum LeapIndicator
        {
            /// Normal, no leap second
            NoWarning = 0,
            /// Last minute of the day has 61 seconds
            Last61Secs,
            /// Last minute of the day has 59 seconds
            Last59Secs,
            /// Unknown (clock unsynchronized)
            Unknown
        };

        /**
         * Representing the NTP association modes
         */
        enum Mode
        {
            /// Reserved variable
            Reserved = 0,
            /// Symmetrically active
            SymActive,
            /// Symmetrically passive
            SymPassive,
            /// Client mode
            Client,
            /// Server mode
            Server,
            /// Broadcasting mode
            Broadcast,
            /// NTP control messages
            Control,
            /// Reserved for private use
            PrivateUse
        };

        /**
         * 32-bit code identifying the particular server or reference clock.
         * The interpretation depends on the value in the stratum field.
         */
        enum class ClockSource : uint32_t
        {
            // NTPv4

            /// Geosynchronous Orbit Environment Satellite
            GOES = ('G') | ('O' << 8) | ('E' << 16) | ('S' << 24),
            /// Global Position System
            GPS = ('G') | ('P' << 8) | ('S' << 16),
            /// Galileo Positioning System
            GAL = ('G') | ('A' << 8) | ('L' << 16),
            /// Generic pulse-per-second
            PPS = ('P') | ('P' << 8) | ('S' << 16),
            /// Inter-Range Instrumentation Group
            IRIG = ('I') | ('R' << 8) | ('I' << 16) | ('G' << 24),
            /// LF Radio WWVB Ft. Collins, CO 60 kHz
            WWVB = ('W') | ('W' << 8) | ('V' << 16) | ('B' << 24),
            /// LF Radio DCF77 Mainflingen, DE 77.5 kHz
            DCF = ('D') | ('C' << 8) | ('F' << 16),
            /// LF Radio HBG Prangins, HB 75 kHz
            HBG = ('H') | ('B' << 8) | ('G' << 16),
            /// LF Radio MSF Anthorn, UK 60 kHz
            MSF = ('M') | ('S' << 8) | ('F' << 16),
            /// LF Radio JJY Fukushima, JP 40 kHz, Saga, JP 60 kHz
            JJY = ('J') | ('J' << 8) | ('Y' << 16),
            /// MF Radio LORAN C station, 100 kHz
            LORC = ('L') | ('O' << 8) | ('R' << 16) | ('C' << 24),
            /// MF Radio Allouis, FR 162 kHz
            TDF = ('T') | ('D' << 8) | ('F' << 16),
            /// HF Radio CHU Ottawa, Ontario
            CHU = ('C') | ('H' << 8) | ('U' << 16),
            /// HF Radio WWV Ft. Collins, CO
            WWV = ('W') | ('W' << 8) | ('V' << 16),
            /// HF Radio WWVH Kauai, HI
            WWVH = ('W') | ('W' << 8) | ('V' << 16) | ('H' << 24),
            /// NIST telephone modem
            NIST = ('N') | ('I' << 8) | ('S' << 16) | ('T' << 24),
            /// NIST telephone modem
            ACTS = ('A') | ('C' << 8) | ('T' << 16) | ('S' << 24),
            /// USNO telephone modem
            USNO = ('U') | ('S' << 8) | ('N' << 16) | ('O' << 24),
            /// European telephone modem
            PTB = ('P') | ('T' << 8) | ('B' << 16),
            /// Multi Reference Sources
            MRS = ('M') | ('R' << 8) | ('S' << 16),
            /// Inter Face Association Changed
            XFAC = ('X') | ('F' << 8) | ('A' << 16) | ('C' << 24),
            /// Step time change
            STEP = ('S') | ('T' << 8) | ('E' << 16) | ('P' << 24),
            /// Google Refid used by Google NTP servers as time4.google.com
            GOOG = ('G') | ('O' << 8) | ('O' << 16) | ('G' << 24),
            /// Meinberg DCF77 with amplitude modulation (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm)
            DCFa = ('D') | ('C' << 8) | ('F' << 16) | ('a' << 24),
            /// Meinberg DCF77 with phase modulation)/pseudo random phase modulation (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm)
            DCFp = ('D') | ('C' << 8) | ('F' << 16) | ('p' << 24),
            /// Meinberg GPS (with shared memory access) (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm)
            GPSs = ('G') | ('P' << 8) | ('S' << 16) | ('s' << 24),
            /// Meinberg GPS (with interrupt based access) (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm)
            GPSi = ('G') | ('P' << 8) | ('S' << 16) | ('i' << 24),
            /// Meinberg GPS/GLONASS (with shared memory access) (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm)
            GLNs = ('G') | ('L' << 8) | ('N' << 16) | ('s' << 24),
            /// Meinberg GPS/GLONASS (with interrupt based access) (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm)
            GLNi = ('G') | ('L' << 8) | ('N' << 16) | ('i' << 24),
            /// Meinberg Undisciplined local clock (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm)
            LCL = ('L') | ('C' << 8) | ('L' << 16),
            /// Meinberg Undisciplined local clock (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm)
            LOCL = ('L') | ('O' << 8) | ('C' << 16) | ('L' << 24),

            // NTPv3

            /// DCN routing protocol
            DCN = ('D') | ('C' << 8) | ('N' << 16),
            /// TSP time protocol
            TSP = ('T') | ('S' << 8) | ('P' << 16),
            /// Digital Time Service
            DTS = ('D') | ('T' << 8) | ('S' << 16),
            /// Atomic clock (calibrated)
            ATOM = ('A') | ('T' << 8) | ('O' << 16) | ('M' << 24),
            /// VLF radio (OMEGA, etc.)
            VLF = ('V') | ('L' << 8) | ('F' << 16)

        };

        /**
         * 32-bit Kiss of Death (KoD) codes
         */
        enum class KissODeath : uint32_t
        {
            /// The association belongs to a anycast server
            ACST = ('A') | ('C' << 8) | ('S' << 16) | ('T' << 24),
            /// Server authentication failed
            AUTH = ('A') | ('U' << 8) | ('T' << 16) | ('H' << 24),
            /// Autokey sequence failed
            AUTO = ('A') | ('U' << 8) | ('T' << 16) | ('O' << 24),
            /// The association belongs to a broadcast server
            BCST = ('B') | ('C' << 8) | ('S' << 16) | ('T' << 24),
            /// Cryptographic authentication or identification failed
            CRYP = ('C') | ('R' << 8) | ('Y' << 16) | ('P' << 24),
            /// Access denied by remote server
            DENY = ('D') | ('E' << 8) | ('N' << 16) | ('Y' << 24),
            /// Lost peer in symmetric mode
            DROP = ('D') | ('R' << 8) | ('O' << 16) | ('P' << 24),
            /// Access denied due to local policy
            RSTR = ('R') | ('S' << 8) | ('T' << 16) | ('R' << 24),
            /// The association has not yet synchronized for the first time
            INIT = ('I') | ('N' << 8) | ('I' << 16) | ('T' << 24),
            /// The association belongs to a manycast server
            MCST = ('M') | ('C' << 8) | ('S' << 16) | ('T' << 24),
            /// No key found.  Either the key was never installed or is not trusted
            NKEY = ('N') | ('K' << 8) | ('E' << 16) | ('Y' << 24),
            /// Rate exceeded.  The server has temporarily denied access because the client exceeded the rate threshold
            RATE = ('R') | ('A' << 8) | ('T' << 16) | ('E' << 24),
            /// Somebody is tinkering with the association from a remote host running ntpdc.  Not to worry unless some rascal has stolen your keys
            RMOT = ('R') | ('M' << 8) | ('O' << 16) | ('T' << 24),
            /// A step change in system time has occurred, but the association has not yet resynchronized
            STEP = ('S') | ('T' << 8) | ('E' << 16) | ('P' << 24),
        };

        /**
		 * A constructor that creates the layer from an existing packet raw data
		 * @param[in] data A pointer to the raw data
		 * @param[in] dataLen Size of the data in bytes
		 * @param[in] prevLayer A pointer to the previous layer
		 * @param[in] packet A pointer to the Packet instance where layer will be stored in
		 */
        NtpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = NTP; }

        /**
         * Empty c'tor
         */
        NtpLayer();

        /**
         * @return The leap indicator
         */
        LeapIndicator getLeapIndicator() const;

        /**
         * Set the leap indicator
         */
        void setLeapIndicator(LeapIndicator val);

        /**
         * @return The version of NTP
         */
        uint8_t getVersion() const;

        /**
         * Set the version of NTP
         */
        void setVersion(uint8_t val);

        /**
         * @return The mode value
         */
        Mode getMode() const;

        /**
         * @return The mode as string
         */
        std::string getModeString() const;

        /**
         * Set the mode
         */
        void setMode(Mode val);

        /**
         * @return The value of stratum
         */
        uint8_t getStratum() const;

        /**
         * Set the value of stratum
         */
        void setStratum(uint8_t val);

        /**
         * @return The value of poll interval in log2 seconds
         */
        int8_t getPollInterval() const;

        /**
         * Set the value of poll interval
         * @param[in] val Poll interval in log2 seconds
         */
        void setPollInterval(int8_t val);

        /**
         * @return The value of poll interval in seconds
         */
        double getPollIntervalInSecs() const;

        /**
         * @return The value of precision in log2 seconds
         */
        int8_t getPrecision() const;

        /**
         * Set the value of precision
         * @param[in] val Precision in log2 seconds
         */
        void setPrecision(int8_t val);

        /**
         * @return The value of precision in seconds
         */
        double getPrecisionInSecs() const;

        /**
         * @return The value of root delay in NTP short format
         */
        uint32_t getRootDelay() const;

        /**
         * Set the value of root delay
         * @param[in] val Root delay in NTP short format
         */
        void setRootDelay(uint32_t val);

        /**
         * @return The value of root delay in seconds
         */
        double getRootDelayInSecs() const;

        /**
         * Set the value of root delay
         * @param[in] val Root delay in seconds
         */
        void setRootDelayInSecs(double val);

        /**
         * @return The value of root dispersion in NTP short format
         */
        uint32_t getRootDispersion() const;

        /**
         * Set the value of root delay
         * @param[in] val Root dispersion in NTP short format
         */
        void setRootDispersion(uint32_t val);

        /**
         * @return The value of root dispersion in seconds
         */
        double getRootDispersionInSecs() const;

        /**
         * Set the value of root dispersion
         * @param[in] val Root dispersion in seconds
         */
        void setRootDispersionInSecs(double val);

        /**
         * @return The value of reference identifier
         */
        uint32_t getReferenceIdentifier() const;

        /**
         * Set the value of reference identifier
         * @param[in] val Value of the reference identifier as IPv4 address
         */
        void setReferenceIdentifier(IPv4Address val);

        /**
         * Set the value of reference identifier
         * @param[in] val Value of the reference identifier as ClockSource
         */
        void setReferenceIdentifier(ClockSource val);

        /**
         * Set the value of reference identifier
         * @param[in] val Value of the reference identifier as Kiss-O-Death code
         */
        void setReferenceIdentifier(KissODeath val);

        /**
         * @return The value of reference identifier as a string. String representation of NTP clock source if stratum is 1,
         * IPv4 address or MD5 hash of first four octets of IPv6
         */
        std::string getReferenceIdentifierString() const;

        /**
         * @return The value of reference timestamp in NTP timestamp format
         */
        uint64_t getReferenceTimestamp() const;

        /**
         * Set the value of reference timestamp
         * @param[in] val Timestamp in NTP timestamp format
         */
        void setReferenceTimestamp(uint64_t val);

        /**
         * @return The value of reference timestamp in seconds from Unix Epoch (1 Jan 1970)
         */
        double getReferenceTimestampInSecs() const;

        /**
         * Set the value of reference timestamp
         * @param[in] val Value in seconds from Unix Epoch (1 Jan 1970)
         */
        void setReferenceTimestampInSecs(double val);

        /**
         * @return The reference timestamp value as readable string in ISO8601 format
         */
        std::string getReferenceTimestampAsString();

        /**
         * @return The value of origin timestamp in NTP timestamp format
         */
        uint64_t getOriginTimestamp() const;

        /**
         * Set the value of origin timestamp
         * @param[in] val Value in NTP timestamp format
         */
        void setOriginTimestamp(uint64_t val);

        /**
         * @return The value of origin timestamp in seconds from Unix Epoch (1 Jan 1970)
         */
        double getOriginTimestampInSecs() const;

        /**
         * Set the value of origin timestamp
         * @param[in] val Value in seconds from Unix Epoch (1 Jan 1970)
         */
        void setOriginTimestampInSecs(double val);

        /**
         * @return the origin timestamp value as readable string in ISO8601 format
         */
        std::string getOriginTimestampAsString();

        /**
         * @return The value of receive timestamp in NTP timestamp format
         */
        uint64_t getReceiveTimestamp() const;

        /**
         * Set the value of receive timestamp
         * @param[in] val Value in NTP timestamp format
         */
        void setReceiveTimestamp(uint64_t val);

        /**
         * @return The value of receive timestampin seconds from Unix Epoch (1 Jan 1970)
         */
        double getReceiveTimestampInSecs() const;

        /**
         * Set the value of receive timestamp
         * @param[in] val Value in seconds from Unix Epoch (1 Jan 1970)
         */
        void setReceiveTimestampInSecs(double val);

        /**
         * @return The receive timestamp value as readable string in ISO8601 format
         */
        std::string getReceiveTimestampAsString();

        /**
         * @return The value of transmit timestamp in NTP timestamp format
         */
        uint64_t getTransmitTimestamp() const;

        /**
         * Set the value of transmit timestamp
         * @param[in] val Value in NTP timestamp format
         */
        void setTransmitTimestamp(uint64_t val);

        /**
         * @return The value of transmit timestamp in seconds from Unix Epoch (1 Jan 1970)
         */
        double getTransmitTimestampInSecs() const;

        /**
         * Set the value of transmit timestamp
         * @param[in] val Value in seconds from Unix Epoch (1 Jan 1970)
         */
        void setTransmitTimestampInSecs(double val);

        /**
         * @return The transmit timestamp value as readable string in ISO8601 format
         */
        std::string getTransmitTimestampAsString();

        /**
         * @return Returns the key identifier if exists, returns 0 on unsupported NTP version or key identifier not found
         */
        uint32_t getKeyID() const;

        /**
         * @return Get the digest value as hexadecimal string, empty string on unsupported version
         */
        std::string getDigest() const;

        /**
         * Convert NTP short format to seconds from the Unix Epoch
         *
         * @param[in] val Value in NTP short format
         * @return Value in seconds from Unix Epoch (1 Jan 1970)
         */
        static double convertFromShortFormat(const uint32_t val);

        /**
         * Convert NTP timestamp format to seconds from the Unix Epoch
         *
         * @param[in] val Value in NTP timestamp format
         * @return Value in seconds from Unix Epoch (1 Jan 1970)
         */
        static double convertFromTimestampFormat(const uint64_t val);

        /**
         * Convert seconds from the Unix Epoch to NTP short format
         *
         * @param[in] val Value in seconds from Unix Epoch (1 Jan 1970)
         * @return Value in NTP short format
         */
        static uint32_t convertToShortFormat(const double val);

        /**
         * Convert seconds from the Unix Epoch to NTP timestamp format
         *
         * @param[in] val Value in seconds from Unix Epoch (1 Jan 1970)
         * @return Value in NTP timestamp format
         */
        static uint64_t convertToTimestampFormat(const double val);

        /**
         * A static method to convert timestamp value to ISO8601 date time format
         * @param[in] timestamp Value in seconds from the Unix Epoch
         * @return std::string ISO8601 formatted string
         */
        static std::string convertToIsoFormat(const double timestamp);

        /**
         * A static method to convert timestamp value to ISO8601 date time format
         * @param[in] timestampInNTPformat Value in NTP timestamp format
         * @return std::string ISO8601 formatted string
         */
        static std::string convertToIsoFormat(const uint64_t timestampInNTPformat);

        /**
		 * A static method that takes a byte array and detects whether it is a NTP message
		 * @param[in] data A byte array
		 * @param[in] dataSize The byte array size (in bytes)
		 * @return True if the data is identified as NTP message
		 */
        static bool isDataValid(const uint8_t *data, size_t dataSize);

        /**
		 * A static method that checks whether the port is considered as NTP
		 * @param[in] port The port number to be checked
		 */
        static bool isNTPPort(uint16_t port) { return port == 123; }

        // overridden methods

        /// Parses the next layer. NTP is the always last so does nothing for this layer
        void parseNextLayer() {}

        /**
         * @return Get the size of the layer (Including the extension and authentication fields if exists)
         */
        size_t getHeaderLen() const { return m_DataLen; }

        /// Does nothing for this layer
        void computeCalculateFields() {}

        /**
         * @return The OSI layer level of NTP (Application Layer).
         */
        OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; }

        /**
         * @return Returns the protocol info as readable string
         */
        std::string toString() const;
    };

} // namespace pcpp

#endif /* PACKETPP_NTP_LAYER */