Coverage Report

Created: 2025-07-23 07:29

/rust/registry/src/index.crates.io-6f17d22bba15001f/ntp-parser-0.6.0/src/ntp.rs
Line
Count
Source (jump to first uncovered line)
1
use nom::bytes::streaming::take;
2
use nom::combinator::{complete, map, map_parser, opt};
3
use nom::error::{make_error, ErrorKind};
4
use nom::multi::many1;
5
use nom::number::streaming::be_u8;
6
pub use nom::{Err, IResult};
7
use nom_derive::*;
8
9
#[derive(Debug, PartialEq)]
10
pub enum NtpPacket<'a> {
11
    V3(NtpV3Packet<'a>),
12
    V4(NtpV4Packet<'a>),
13
}
14
15
0
#[derive(Clone, Copy, Debug, Eq, PartialEq, NomBE)]
Unexecuted instantiation: <ntp_parser::ntp::NtpMode as nom_derive::traits::Parse<&[u8]>>::parse_be
Unexecuted instantiation: <ntp_parser::ntp::NtpMode as nom_derive::traits::Parse<&[u8]>>::parse_le
Unexecuted instantiation: <ntp_parser::ntp::NtpMode as nom_derive::traits::Parse<&[u8]>>::parse
Unexecuted instantiation: <ntp_parser::ntp::NtpMode as nom_derive::traits::Parse<&[u8]>>::parse_be
Unexecuted instantiation: <ntp_parser::ntp::NtpMode as nom_derive::traits::Parse<&[u8]>>::parse_le
Unexecuted instantiation: <ntp_parser::ntp::NtpMode as nom_derive::traits::Parse<&[u8]>>::parse
16
pub struct NtpMode(pub u8);
17
18
#[allow(non_upper_case_globals)]
19
impl NtpMode {
20
    pub const Reserved: NtpMode = NtpMode(0);
21
    pub const SymmetricActive: NtpMode = NtpMode(1);
22
    pub const SymmetricPassive: NtpMode = NtpMode(2);
23
    pub const Client: NtpMode = NtpMode(3);
24
    pub const Server: NtpMode = NtpMode(4);
25
    pub const Broadcast: NtpMode = NtpMode(5);
26
    pub const NtpControlMessage: NtpMode = NtpMode(6);
27
    pub const Private: NtpMode = NtpMode(7);
28
}
29
30
/// An NTP version 3 packet
31
307k
#[derive(Debug, PartialEq, NomBE)]
<ntp_parser::ntp::NtpV3Packet as nom_derive::traits::Parse<&[u8]>>::parse_be::{closure#0}
Line
Count
Source
31
39.0k
#[derive(Debug, PartialEq, NomBE)]
<ntp_parser::ntp::NtpV3Packet as nom_derive::traits::Parse<&[u8]>>::parse_be::{closure#1}
Line
Count
Source
31
39.0k
#[derive(Debug, PartialEq, NomBE)]
<ntp_parser::ntp::NtpV3Packet as nom_derive::traits::Parse<&[u8]>>::parse_be::{closure#2}
Line
Count
Source
31
39.0k
#[derive(Debug, PartialEq, NomBE)]
Unexecuted instantiation: <ntp_parser::ntp::NtpV3Packet as nom_derive::traits::Parse<&[u8]>>::parse_le::{closure#0}
Unexecuted instantiation: <ntp_parser::ntp::NtpV3Packet as nom_derive::traits::Parse<&[u8]>>::parse_le::{closure#1}
Unexecuted instantiation: <ntp_parser::ntp::NtpV3Packet as nom_derive::traits::Parse<&[u8]>>::parse_le::{closure#2}
<ntp_parser::ntp::NtpV3Packet as nom_derive::traits::Parse<&[u8]>>::parse
Line
Count
Source
31
39.0k
#[derive(Debug, PartialEq, NomBE)]
<ntp_parser::ntp::NtpV3Packet as nom_derive::traits::Parse<&[u8]>>::parse_be::{closure#0}
Line
Count
Source
31
37.9k
#[derive(Debug, PartialEq, NomBE)]
<ntp_parser::ntp::NtpV3Packet as nom_derive::traits::Parse<&[u8]>>::parse_be::{closure#1}
Line
Count
Source
31
37.9k
#[derive(Debug, PartialEq, NomBE)]
<ntp_parser::ntp::NtpV3Packet as nom_derive::traits::Parse<&[u8]>>::parse_be::{closure#2}
Line
Count
Source
31
37.9k
#[derive(Debug, PartialEq, NomBE)]
Unexecuted instantiation: <ntp_parser::ntp::NtpV3Packet as nom_derive::traits::Parse<&[u8]>>::parse_le::{closure#0}
Unexecuted instantiation: <ntp_parser::ntp::NtpV3Packet as nom_derive::traits::Parse<&[u8]>>::parse_le::{closure#1}
Unexecuted instantiation: <ntp_parser::ntp::NtpV3Packet as nom_derive::traits::Parse<&[u8]>>::parse_le::{closure#2}
<ntp_parser::ntp::NtpV3Packet as nom_derive::traits::Parse<&[u8]>>::parse
Line
Count
Source
31
37.9k
#[derive(Debug, PartialEq, NomBE)]
<ntp_parser::ntp::NtpV3Packet as nom_derive::traits::Parse<&[u8]>>::parse_be
Line
Count
Source
31
39.0k
#[derive(Debug, PartialEq, NomBE)]
Unexecuted instantiation: <ntp_parser::ntp::NtpV3Packet as nom_derive::traits::Parse<&[u8]>>::parse_le
<ntp_parser::ntp::NtpV3Packet as nom_derive::traits::Parse<&[u8]>>::parse_be
Line
Count
Source
31
37.9k
#[derive(Debug, PartialEq, NomBE)]
Unexecuted instantiation: <ntp_parser::ntp::NtpV3Packet as nom_derive::traits::Parse<&[u8]>>::parse_le
32
pub struct NtpV3Packet<'a> {
33
    #[nom(PreExec = "let (i, b0) = be_u8(i)?;")]
34
    #[nom(Value(b0 >> 6))]
35
    pub li: u8,
36
    #[nom(Value((b0 >> 3) & 0b111))]
37
    pub version: u8,
38
    #[nom(Value(NtpMode(b0 & 0b111)))]
39
    pub mode: NtpMode,
40
    pub stratum: u8,
41
    pub poll: i8,
42
    pub precision: i8,
43
    pub root_delay: u32,
44
    pub root_dispersion: u32,
45
    pub ref_id: u32,
46
    pub ts_ref: u64,
47
    pub ts_orig: u64,
48
    pub ts_recv: u64,
49
    pub ts_xmit: u64,
50
51
    #[nom(Parse = "opt(complete(take(12usize)))")]
52
    pub authenticator: Option<&'a [u8]>,
53
}
54
55
/// An NTP version 4 packet
56
57.6k
#[derive(Debug, PartialEq, NomBE)]
<ntp_parser::ntp::NtpV4Packet as nom_derive::traits::Parse<&[u8]>>::parse_be::{closure#0}
Line
Count
Source
56
8.37k
#[derive(Debug, PartialEq, NomBE)]
<ntp_parser::ntp::NtpV4Packet as nom_derive::traits::Parse<&[u8]>>::parse_be::{closure#1}
Line
Count
Source
56
8.37k
#[derive(Debug, PartialEq, NomBE)]
<ntp_parser::ntp::NtpV4Packet as nom_derive::traits::Parse<&[u8]>>::parse_be::{closure#2}
Line
Count
Source
56
8.37k
#[derive(Debug, PartialEq, NomBE)]
Unexecuted instantiation: <ntp_parser::ntp::NtpV4Packet as nom_derive::traits::Parse<&[u8]>>::parse_le::{closure#0}
Unexecuted instantiation: <ntp_parser::ntp::NtpV4Packet as nom_derive::traits::Parse<&[u8]>>::parse_le::{closure#1}
Unexecuted instantiation: <ntp_parser::ntp::NtpV4Packet as nom_derive::traits::Parse<&[u8]>>::parse_le::{closure#2}
<ntp_parser::ntp::NtpV4Packet as nom_derive::traits::Parse<&[u8]>>::parse
Line
Count
Source
56
8.37k
#[derive(Debug, PartialEq, NomBE)]
<ntp_parser::ntp::NtpV4Packet as nom_derive::traits::Parse<&[u8]>>::parse_be::{closure#0}
Line
Count
Source
56
6.04k
#[derive(Debug, PartialEq, NomBE)]
<ntp_parser::ntp::NtpV4Packet as nom_derive::traits::Parse<&[u8]>>::parse_be::{closure#1}
Line
Count
Source
56
6.04k
#[derive(Debug, PartialEq, NomBE)]
<ntp_parser::ntp::NtpV4Packet as nom_derive::traits::Parse<&[u8]>>::parse_be::{closure#2}
Line
Count
Source
56
6.04k
#[derive(Debug, PartialEq, NomBE)]
Unexecuted instantiation: <ntp_parser::ntp::NtpV4Packet as nom_derive::traits::Parse<&[u8]>>::parse_le::{closure#0}
Unexecuted instantiation: <ntp_parser::ntp::NtpV4Packet as nom_derive::traits::Parse<&[u8]>>::parse_le::{closure#1}
Unexecuted instantiation: <ntp_parser::ntp::NtpV4Packet as nom_derive::traits::Parse<&[u8]>>::parse_le::{closure#2}
<ntp_parser::ntp::NtpV4Packet as nom_derive::traits::Parse<&[u8]>>::parse
Line
Count
Source
56
6.04k
#[derive(Debug, PartialEq, NomBE)]
<ntp_parser::ntp::NtpV4Packet as nom_derive::traits::Parse<&[u8]>>::parse_be
Line
Count
Source
56
8.37k
#[derive(Debug, PartialEq, NomBE)]
Unexecuted instantiation: <ntp_parser::ntp::NtpV4Packet as nom_derive::traits::Parse<&[u8]>>::parse_le
<ntp_parser::ntp::NtpV4Packet as nom_derive::traits::Parse<&[u8]>>::parse_be
Line
Count
Source
56
6.04k
#[derive(Debug, PartialEq, NomBE)]
Unexecuted instantiation: <ntp_parser::ntp::NtpV4Packet as nom_derive::traits::Parse<&[u8]>>::parse_le
57
pub struct NtpV4Packet<'a> {
58
    #[nom(PreExec = "let (i, b0) = be_u8(i)?;")]
59
    #[nom(Value(b0 >> 6))]
60
    pub li: u8,
61
    #[nom(Value((b0 >> 3) & 0b111))]
62
    pub version: u8,
63
    #[nom(Value(NtpMode(b0 & 0b111)))]
64
    pub mode: NtpMode,
65
    pub stratum: u8,
66
    pub poll: i8,
67
    pub precision: i8,
68
    pub root_delay: u32,
69
    pub root_dispersion: u32,
70
    pub ref_id: u32,
71
    pub ts_ref: u64,
72
    pub ts_orig: u64,
73
    pub ts_recv: u64,
74
    pub ts_xmit: u64,
75
76
    #[nom(Parse = "try_parse_extensions")]
77
    pub extensions: Vec<NtpExtension<'a>>,
78
    #[nom(Cond(!i.is_empty()))]
79
    pub auth: Option<NtpMac<'a>>,
80
}
81
82
impl<'a> NtpV4Packet<'a> {
83
0
    pub fn get_precision(&self) -> f32 {
84
0
        2.0_f32.powf(self.precision as f32)
85
0
    }
Unexecuted instantiation: <ntp_parser::ntp::NtpV4Packet>::get_precision
Unexecuted instantiation: <ntp_parser::ntp::NtpV4Packet>::get_precision
86
}
87
88
5.93M
#[derive(Debug, PartialEq, NomBE)]
<ntp_parser::ntp::NtpExtension as nom_derive::traits::Parse<&[u8]>>::parse_be
Line
Count
Source
88
3.37M
#[derive(Debug, PartialEq, NomBE)]
Unexecuted instantiation: <ntp_parser::ntp::NtpExtension as nom_derive::traits::Parse<&[u8]>>::parse_le
<ntp_parser::ntp::NtpExtension as nom_derive::traits::Parse<&[u8]>>::parse
Line
Count
Source
88
3.36M
#[derive(Debug, PartialEq, NomBE)]
<ntp_parser::ntp::NtpExtension as nom_derive::traits::Parse<&[u8]>>::parse_be
Line
Count
Source
88
2.56M
#[derive(Debug, PartialEq, NomBE)]
Unexecuted instantiation: <ntp_parser::ntp::NtpExtension as nom_derive::traits::Parse<&[u8]>>::parse_le
<ntp_parser::ntp::NtpExtension as nom_derive::traits::Parse<&[u8]>>::parse
Line
Count
Source
88
2.55M
#[derive(Debug, PartialEq, NomBE)]
89
pub struct NtpExtension<'a> {
90
    pub field_type: u16,
91
    pub length: u16,
92
    #[nom(Parse = "take(length)")]
93
    pub value: &'a [u8],
94
    /*padding*/
95
}
96
97
9.64k
#[derive(Debug, PartialEq, NomBE)]
<ntp_parser::ntp::NtpMac as nom_derive::traits::Parse<&[u8]>>::parse_be
Line
Count
Source
97
5.90k
#[derive(Debug, PartialEq, NomBE)]
Unexecuted instantiation: <ntp_parser::ntp::NtpMac as nom_derive::traits::Parse<&[u8]>>::parse_le
Unexecuted instantiation: <ntp_parser::ntp::NtpMac as nom_derive::traits::Parse<&[u8]>>::parse
<ntp_parser::ntp::NtpMac as nom_derive::traits::Parse<&[u8]>>::parse_be
Line
Count
Source
97
3.73k
#[derive(Debug, PartialEq, NomBE)]
Unexecuted instantiation: <ntp_parser::ntp::NtpMac as nom_derive::traits::Parse<&[u8]>>::parse_le
Unexecuted instantiation: <ntp_parser::ntp::NtpMac as nom_derive::traits::Parse<&[u8]>>::parse
98
pub struct NtpMac<'a> {
99
    pub key_id: u32,
100
    #[nom(Parse = "take(16usize)")]
101
    pub mac: &'a [u8],
102
}
103
104
#[inline]
105
5.92M
pub fn parse_ntp_extension(i: &[u8]) -> IResult<&[u8], NtpExtension> {
106
5.92M
    NtpExtension::parse(i)
107
5.92M
}
ntp_parser::ntp::parse_ntp_extension
Line
Count
Source
105
3.36M
pub fn parse_ntp_extension(i: &[u8]) -> IResult<&[u8], NtpExtension> {
106
3.36M
    NtpExtension::parse(i)
107
3.36M
}
ntp_parser::ntp::parse_ntp_extension
Line
Count
Source
105
2.55M
pub fn parse_ntp_extension(i: &[u8]) -> IResult<&[u8], NtpExtension> {
106
2.55M
    NtpExtension::parse(i)
107
2.55M
}
108
109
// Attempt to parse extensions.
110
//
111
// See section 7.5 of [RFC5905] and [RFC7822]:
112
// In NTPv4, one or more extension fields can be inserted after the
113
//    header and before the MAC, which is always present when an extension
114
//    field is present.
115
//
116
// So:
117
//  if == 20, only MAC
118
//  if >  20, ext + MAC
119
//  if ==  0, nothing
120
//  else      error
121
14.1k
fn try_parse_extensions(i: &[u8]) -> IResult<&[u8], Vec<NtpExtension>> {
122
14.1k
    if i.is_empty() || i.len() == 20 {
123
        // if empty, or if remaining length is exactly the MAC length (20), assume we do not have
124
        // extensions
125
4.83k
        return Ok((i, Vec::new()));
126
9.32k
    }
127
9.32k
    if i.len() < 20 {
128
58
        return Err(Err::Error(make_error(i, ErrorKind::Eof)));
129
9.27k
    }
130
9.27k
    map_parser(take(i.len() - 20), many1(complete(parse_ntp_extension)))(i)
131
14.1k
}
ntp_parser::ntp::try_parse_extensions
Line
Count
Source
121
8.26k
fn try_parse_extensions(i: &[u8]) -> IResult<&[u8], Vec<NtpExtension>> {
122
8.26k
    if i.is_empty() || i.len() == 20 {
123
        // if empty, or if remaining length is exactly the MAC length (20), assume we do not have
124
        // extensions
125
2.65k
        return Ok((i, Vec::new()));
126
5.60k
    }
127
5.60k
    if i.len() < 20 {
128
27
        return Err(Err::Error(make_error(i, ErrorKind::Eof)));
129
5.58k
    }
130
5.58k
    map_parser(take(i.len() - 20), many1(complete(parse_ntp_extension)))(i)
131
8.26k
}
ntp_parser::ntp::try_parse_extensions
Line
Count
Source
121
5.89k
fn try_parse_extensions(i: &[u8]) -> IResult<&[u8], Vec<NtpExtension>> {
122
5.89k
    if i.is_empty() || i.len() == 20 {
123
        // if empty, or if remaining length is exactly the MAC length (20), assume we do not have
124
        // extensions
125
2.17k
        return Ok((i, Vec::new()));
126
3.72k
    }
127
3.72k
    if i.len() < 20 {
128
31
        return Err(Err::Error(make_error(i, ErrorKind::Eof)));
129
3.68k
    }
130
3.68k
    map_parser(take(i.len() - 20), many1(complete(parse_ntp_extension)))(i)
131
5.89k
}
132
133
/// Parse an NTP version 3 packet (RFC 1305)
134
#[inline]
135
0
pub fn parse_ntpv3(i: &[u8]) -> IResult<&[u8], NtpV3Packet> {
136
0
    NtpV3Packet::parse(i)
137
0
}
Unexecuted instantiation: ntp_parser::ntp::parse_ntpv3
Unexecuted instantiation: ntp_parser::ntp::parse_ntpv3
138
139
/// Parse an NTP version 4 packet (RFC 1305)
140
#[inline]
141
0
pub fn parse_ntpv4(i: &[u8]) -> IResult<&[u8], NtpV4Packet> {
142
0
    NtpV4Packet::parse(i)
143
0
}
Unexecuted instantiation: ntp_parser::ntp::parse_ntpv4
Unexecuted instantiation: ntp_parser::ntp::parse_ntpv4
144
145
/// Parse an NTP packet, version 3 or 4
146
#[inline]
147
91.4k
pub fn parse_ntp(i: &[u8]) -> IResult<&[u8], NtpPacket> {
148
91.4k
    let (_, b0) = be_u8(i)?;
149
91.4k
    match (b0 >> 3) & 0b111 {
150
76.9k
        3 => map(NtpV3Packet::parse, NtpPacket::V3)(i),
151
14.4k
        4 => map(NtpV4Packet::parse, NtpPacket::V4)(i),
152
83
        _ => Err(Err::Error(make_error(i, ErrorKind::Tag))),
153
    }
154
91.4k
}
ntp_parser::ntp::parse_ntp
Line
Count
Source
147
47.4k
pub fn parse_ntp(i: &[u8]) -> IResult<&[u8], NtpPacket> {
148
47.4k
    let (_, b0) = be_u8(i)?;
149
47.4k
    match (b0 >> 3) & 0b111 {
150
39.0k
        3 => map(NtpV3Packet::parse, NtpPacket::V3)(i),
151
8.37k
        4 => map(NtpV4Packet::parse, NtpPacket::V4)(i),
152
38
        _ => Err(Err::Error(make_error(i, ErrorKind::Tag))),
153
    }
154
47.4k
}
ntp_parser::ntp::parse_ntp
Line
Count
Source
147
43.9k
pub fn parse_ntp(i: &[u8]) -> IResult<&[u8], NtpPacket> {
148
43.9k
    let (_, b0) = be_u8(i)?;
149
43.9k
    match (b0 >> 3) & 0b111 {
150
37.9k
        3 => map(NtpV3Packet::parse, NtpPacket::V3)(i),
151
6.04k
        4 => map(NtpV4Packet::parse, NtpPacket::V4)(i),
152
45
        _ => Err(Err::Error(make_error(i, ErrorKind::Tag))),
153
    }
154
43.9k
}
155
156
#[cfg(test)]
157
mod tests {
158
    use crate::ntp::*;
159
160
    static NTP_REQ1: &[u8] = &[
161
        0xd9, 0x00, 0x0a, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x90, 0x00, 0x00, 0x00,
162
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x02, 0x04, 0xec, 0xec,
164
        0x42, 0xee, 0x92,
165
    ];
166
167
    #[test]
168
    fn test_ntp_packet_simple() {
169
        let empty = &b""[..];
170
        let bytes = NTP_REQ1;
171
        let expected = NtpV4Packet {
172
            li: 3,
173
            version: 3,
174
            mode: NtpMode::SymmetricActive,
175
            stratum: 0,
176
            poll: 10,
177
            precision: -6,
178
            root_delay: 0,
179
            root_dispersion: 0x010290,
180
            ref_id: 0,
181
            ts_ref: 0,
182
            ts_orig: 0,
183
            ts_recv: 0,
184
            ts_xmit: 14195914391047827090u64,
185
            extensions: Vec::new(),
186
            auth: None,
187
        };
188
        let res = parse_ntpv4(&bytes);
189
        assert_eq!(res, Ok((empty, expected)));
190
    }
191
192
    static NTP_REQ2: &[u8] = &[
193
        0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
194
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x25, 0xcc, 0x13, 0x2b,
196
        0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x52, 0x80, 0x0c, 0x2b, 0x59, 0x00, 0x64, 0x66,
197
        0x84, 0xf4, 0x4c, 0xa4, 0xee, 0xce, 0x12, 0xb8,
198
    ];
199
200
    #[test]
201
    fn test_ntp_packet_mac() {
202
        let empty = &b""[..];
203
        let bytes = NTP_REQ2;
204
        let expected = NtpV4Packet {
205
            li: 0,
206
            version: 4,
207
            mode: NtpMode::Client,
208
            stratum: 0,
209
            poll: 0,
210
            precision: 0,
211
            root_delay: 12,
212
            root_dispersion: 0,
213
            ref_id: 0,
214
            ts_ref: 0,
215
            ts_orig: 0,
216
            ts_recv: 0,
217
            ts_xmit: 14710388140573593600,
218
            extensions: Vec::new(),
219
            auth: Some(NtpMac {
220
                key_id: 1,
221
                mac: &bytes[52..],
222
            }),
223
        };
224
        let res = parse_ntpv4(&bytes);
225
        assert_eq!(res, Ok((empty, expected)));
226
    }
227
228
    static NTP_REQ2B: &[u8] = &[
229
        0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
231
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x25, 0xcc, 0x13, 0x2b,
232
        0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x52, 0x80, 0x0c, 0x2b,
233
        0x59, 0x00, 0x64, 0x66, 0x84, 0xf4, 0x4c, 0xa4, 0xee, 0xce, 0x12, 0xb8,
234
    ];
235
236
    #[test]
237
    fn test_ntp_packet_extension() {
238
        let empty = &b""[..];
239
        let bytes = NTP_REQ2B;
240
        let expected = NtpV4Packet {
241
            li: 0,
242
            version: 4,
243
            mode: NtpMode::Client,
244
            stratum: 0,
245
            poll: 0,
246
            precision: 0,
247
            root_delay: 12,
248
            root_dispersion: 0,
249
            ref_id: 0,
250
            ts_ref: 0,
251
            ts_orig: 0,
252
            ts_recv: 0,
253
            ts_xmit: 14710388140573593600,
254
            extensions: vec![NtpExtension {
255
                field_type: 0,
256
                length: 0,
257
                value: empty,
258
            }],
259
            auth: Some(NtpMac {
260
                key_id: 1,
261
                mac: &bytes[56..],
262
            }),
263
        };
264
        let res = parse_ntpv4(&bytes);
265
        assert_eq!(res, Ok((empty, expected)));
266
    }
267
268
    // from wireshark test captures 'ntp.pcap'
269
    static NTPV3_REQ: &[u8] = &[
270
        0x1b, 0x04, 0x06, 0xf5, 0x00, 0x00, 0x10, 0x0d, 0x00, 0x00, 0x05, 0x57, 0x82, 0xdc, 0x18,
271
        0x18, 0xba, 0x29, 0x66, 0x36, 0x7d, 0xd0, 0x00, 0x00, 0xba, 0x29, 0x66, 0x36, 0x7d, 0x58,
272
        0x40, 0x00, 0xba, 0x29, 0x66, 0x36, 0x7d, 0xd0, 0x00, 0x00, 0xba, 0x29, 0x66, 0x76, 0x7d,
273
        0x50, 0x50, 0x00,
274
    ];
275
276
    #[test]
277
    fn test_ntp_packet_v3() {
278
        let empty = &b""[..];
279
        let bytes = NTPV3_REQ;
280
        let expected = NtpV3Packet {
281
            li: 0,
282
            version: 3,
283
            mode: NtpMode::Client,
284
            stratum: 4,
285
            poll: 6,
286
            precision: -11,
287
            root_delay: 4109,
288
            root_dispersion: 0x0557,
289
            ref_id: 0x82dc1818,
290
            ts_ref: 0xba296636_7dd00000,
291
            ts_orig: 0xba296636_7d584000,
292
            ts_recv: 0xba296636_7dd00000,
293
            ts_xmit: 0xba296676_7d505000,
294
            authenticator: None,
295
        };
296
        let res = NtpV3Packet::parse(&bytes);
297
        assert_eq!(res, Ok((empty, expected)));
298
    }
299
}