warts/
ping.rs

1use crate::{Address, Flags, Timeval};
2use deku::prelude::*;
3
4/// Reason for the termination of a ping command.
5#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
6#[deku(ctx = "endian: deku::ctx::Endian", endian = "endian", type = "u8")]
7pub enum PingStopReason {
8    /// Null reason.
9    None = 0x00,
10    /// Sent all probes.
11    Completed = 0x01,
12    /// Error occurred during ping.
13    Error = 0x02,
14    /// Halted.
15    Halted = 0x03,
16}
17
18/// A ping.
19#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
20#[deku(ctx = "endian: deku::ctx::Endian", endian = "endian")]
21pub struct Ping {
22    pub length: u32,
23    /// Flags describing traceroute parameters and high-level outcomes.
24    pub flags: Flags,
25    /// Parameter length, included if any flags are set.
26    #[deku(cond = "flags.any()")]
27    pub param_length: Option<u16>,
28    /// List ID assigned by warts, included if flag 1 is set.
29    #[deku(cond = "flags.get(1)")]
30    pub list_id: Option<u32>,
31    /// Cycle ID assigned by warts, included if flag 2 is set.
32    #[deku(cond = "flags.get(2)")]
33    pub cycle_id: Option<u32>,
34    /// Src IP address ID assigned by warts, included if flag 3 is set.
35    #[deku(cond = "flags.get(3)")]
36    pub src_addr_id: Option<u32>,
37    /// Dst IP address ID assigned by warts, included if flag 4 is set.
38    #[deku(cond = "flags.get(4)")]
39    pub dst_addr_id: Option<u32>,
40    /// Time traceroute commenced, included if flag 5 is set.
41    #[deku(cond = "flags.get(5)")]
42    pub start_time: Option<Timeval>,
43    #[deku(cond = "flags.get(6)")]
44    /// Stop reason, included if flag 6 is set.
45    pub stop_reason: Option<PingStopReason>,
46    /// Stop data, included if flag 7 is set.
47    #[deku(cond = "flags.get(7)")]
48    pub stop_data: Option<u8>,
49    /// Data length, included if flag 8 is set.
50    #[deku(cond = "flags.get(8)")]
51    pub data_length: Option<u8>,
52    /// Data bytes, included if flag 9 is set.
53    #[deku(cond = "flags.get(9)", count = "data_length.unwrap()")]
54    pub data: Vec<u8>,
55    /// Probe count, included if flag 10 is set.
56    #[deku(cond = "flags.get(10)")]
57    pub probe_count: Option<u16>,
58    /// Probe size, included if flag 11 is set.
59    #[deku(cond = "flags.get(11)")]
60    pub probe_size: Option<u16>,
61    /// Probe wait (seconds), included if flag 12 is set.
62    #[deku(cond = "flags.get(12)")]
63    pub probe_wait: Option<u8>,
64    /// Probe TTL, included if flag 13 is set.
65    #[deku(cond = "flags.get(13)")]
66    pub probe_ttl: Option<u8>,
67    /// Reply count, included if flag 14 is set.
68    #[deku(cond = "flags.get(14)")]
69    pub reply_count1: Option<u16>,
70    /// Pings sent, included if flag 15 is set.
71    #[deku(cond = "flags.get(15)")]
72    pub pings_sent: Option<u16>,
73    /// Ping method, included if flag 16 is set.
74    // TODO: Enum?
75    #[deku(cond = "flags.get(16)")]
76    pub ping_method: Option<u8>,
77    /// Probe source port, included if flag 17 is set.
78    #[deku(cond = "flags.get(17)")]
79    pub src_port: Option<u16>,
80    /// Probe source port, included if flag 18 is set.
81    #[deku(cond = "flags.get(18)")]
82    pub dst_port: Option<u16>,
83    /// User ID, included if flag 19 is set.
84    #[deku(cond = "flags.get(19)")]
85    pub user_id: Option<u32>,
86    /// Source address used, included if flag 20 is set.
87    #[deku(cond = "flags.get(20)")]
88    pub src_addr: Option<Address>,
89    /// Destination address used, included if flag 21 is set.
90    #[deku(cond = "flags.get(21)")]
91    pub dst_addr: Option<Address>,
92    /// Ping flags, included if flag 22 is set.
93    // TODO: Enum?
94    #[deku(cond = "flags.get(22)")]
95    pub ping_flags1: Option<u8>,
96    /// Probe TOS, included if flag 23 is set.
97    #[deku(cond = "flags.get(23)")]
98    pub probe_tos: Option<u8>,
99    /// Probe Pre-specified timestamp option, included if flag 24 is set.
100    // TODO
101    #[deku(cond = "flags.get(24)", count = "0")]
102    pub tsprespec: Vec<u8>,
103    /// Probe ICMP checksum, included if flag 25 is set.
104    #[deku(cond = "flags.get(25)")]
105    pub icmp_checksum: Option<u16>,
106    /// Reply psuedo Path MTU, included if flag 26 is set.
107    #[deku(cond = "flags.get(26)")]
108    pub pseudo_pmtu: Option<u16>,
109    /// Probe timeout, included if flag 27 is set.
110    #[deku(cond = "flags.get(27)")]
111    pub probe_timeout: Option<u8>,
112    /// Probe wait (microseconds), included if flag 28 is set.
113    #[deku(cond = "flags.get(28)")]
114    pub probe_wait_usec: Option<u32>,
115    /// Probe TCP acknowledgment value, included if flag 29 is set.
116    #[deku(cond = "flags.get(29)")]
117    pub tcp_ack: Option<u32>,
118    /// Ping flags, included if flag 30 is set.
119    #[deku(cond = "flags.get(30)")]
120    pub ping_flags2: Option<Address>,
121    /// Probe TCP sequence number value, included if flag 31 is set.
122    #[deku(cond = "flags.get(31)")]
123    pub tcp_seq: Option<Address>,
124    /// Router address used to send probes, included if flag 32 is set.
125    #[deku(cond = "flags.get(32)")]
126    pub router_addr: Option<Address>,
127    /// Ping reply count.
128    pub reply_count2: u16,
129    // TODO
130    #[deku(count = "reply_count2")]
131    pub reply: Vec<PingProbe>,
132}
133
134/// A ping probe and its associated reply, if any.
135#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
136#[deku(ctx = "endian: deku::ctx::Endian", endian = "endian")]
137pub struct PingProbe {
138    pub flags: Flags,
139    #[deku(cond = "flags.any()")]
140    pub param_length: Option<u16>,
141    #[deku(cond = "flags.get(1)")]
142    pub addr_id: Option<u32>,
143    // TODO
144    #[deku(cond = "flags.get(2)")]
145    pub flags2: Option<u8>,
146    #[deku(cond = "flags.get(3)")]
147    pub reply_ttl: Option<u8>,
148    #[deku(cond = "flags.get(4)")]
149    pub reply_size: Option<u16>,
150    #[deku(cond = "flags.get(5)")]
151    pub icmp_type: Option<u8>,
152    #[deku(cond = "flags.get(5)")]
153    pub icmp_code: Option<u8>,
154    #[deku(cond = "flags.get(6)")]
155    pub rtt_usec: Option<u32>,
156    #[deku(cond = "flags.get(7)")]
157    pub probe_id: Option<u16>,
158    #[deku(cond = "flags.get(8)")]
159    pub reply_ipid: Option<u16>,
160    #[deku(cond = "flags.get(9)")]
161    pub probe_ipid: Option<u16>,
162    // TODO: Protocol enumeration? Already existing in Rust stdlib?
163    #[deku(cond = "flags.get(10)")]
164    pub reply_proto: Option<u8>,
165    #[deku(cond = "flags.get(11)")]
166    pub tcp_flags: Option<u8>,
167    #[deku(cond = "flags.get(12)")]
168    pub addr: Option<Address>,
169    //TODO
170    #[deku(cond = "flags.get(13)")]
171    pub rr: Option<u8>,
172    #[deku(cond = "flags.get(14)")]
173    pub ts: Option<u8>,
174    #[deku(cond = "flags.get(15)")]
175    pub reply_ipid32: Option<u32>,
176    #[deku(cond = "flags.get(16)")]
177    pub tx: Option<Timeval>,
178    // TODO: tsreply
179}