icmp_packet/
echo_request.rs1use crate::{
2 types::{Identifier, LenWithPayloadLengthDelimited, Payload, SequenceNumber},
3 ICMP_HEADER_SIZE,
4};
5
6#[derive(Debug, Clone)]
8#[non_exhaustive]
9pub struct PayloadLengthDelimitedEchoRequest {
10 pub identifier: Identifier,
11 pub sequence_number: SequenceNumber,
12 payload_with_len: Payload,
13}
14
15impl PayloadLengthDelimitedEchoRequest {
16 pub fn new(
17 identifier: Option<Identifier>,
18 sequence_number: Option<SequenceNumber>,
19 payload: impl AsRef<[u8]>,
20 ) -> Self {
21 let payload = payload.as_ref();
22 let len = LenWithPayloadLengthDelimited::new(payload.len());
23
24 let mut payload_with_len = len.to_bytes().to_vec();
25 payload_with_len.extend_from_slice(payload);
26
27 Self {
28 identifier: identifier.unwrap_or_else(Identifier::gen),
29 sequence_number: sequence_number.unwrap_or_default(),
30 payload_with_len: payload_with_len.into(),
31 }
32 }
33
34 pub fn payload(&self) -> &[u8] {
35 &self.payload_with_len[2..]
36 }
37
38 pub fn len(&self) -> LenWithPayloadLengthDelimited {
39 LenWithPayloadLengthDelimited::from_bytes(
40 self.payload_with_len[..2].try_into().expect("Never"),
41 )
42 }
43
44 pub fn render_v4_packet_bytes(&self) -> Vec<u8> {
45 use pnet_packet::{
46 icmp::{checksum, echo_request::MutableEchoRequestPacket, IcmpPacket, IcmpTypes},
47 Packet as _,
48 };
49
50 let mut buf = vec![0; ICMP_HEADER_SIZE + self.payload_with_len.len()];
52 let mut echo_request_packet = MutableEchoRequestPacket::new(&mut buf[..])
53 .expect("Never when MutableEchoRequestPacket::new");
54 echo_request_packet.set_icmp_type(IcmpTypes::EchoRequest);
55 echo_request_packet.set_identifier(self.identifier.into_inner());
56 echo_request_packet.set_sequence_number(self.sequence_number.into_inner());
57 echo_request_packet.set_payload(&self.payload_with_len);
58
59 let icmp_packet =
60 IcmpPacket::new(echo_request_packet.packet()).expect("Never when IcmpPacket::new");
61 let checksum = checksum(&icmp_packet);
62 echo_request_packet.set_checksum(checksum);
63
64 echo_request_packet.packet().to_vec()
65 }
66
67 pub fn render_v6_packet_bytes(&self) -> Vec<u8> {
68 use pnet_packet::{
69 icmpv6::{echo_request::MutableEchoRequestPacket, Icmpv6Types},
70 Packet as _,
71 };
72
73 let mut buf = vec![0; ICMP_HEADER_SIZE + self.payload_with_len.len()];
74 let mut echo_request_packet = MutableEchoRequestPacket::new(&mut buf[..])
75 .expect("Never when MutableEchoRequestPacket::new");
76 echo_request_packet.set_icmpv6_type(Icmpv6Types::EchoRequest);
77 echo_request_packet.set_identifier(self.identifier.into_inner());
78 echo_request_packet.set_sequence_number(self.sequence_number.into_inner());
79 echo_request_packet.set_payload(&self.payload_with_len);
80
81 echo_request_packet.packet().to_vec()
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn test_new() {
95 let echo_request =
96 PayloadLengthDelimitedEchoRequest::new(Some(1.into()), Some(2.into()), b"1234");
97 assert_eq!(echo_request.payload(), b"1234");
98 assert_eq!(echo_request.len(), LenWithPayloadLengthDelimited::new(4));
99 }
100
101 #[test]
102 fn test_render() {
103 let echo_request =
104 PayloadLengthDelimitedEchoRequest::new(Some(1.into()), Some(2.into()), b"1234");
105 assert_eq!(
106 echo_request.render_v4_packet_bytes(),
107 vec![8, 0, 147, 146, 0, 1, 0, 2, 0, 4, 49, 50, 51, 52]
108 );
109 assert_eq!(
110 echo_request.render_v6_packet_bytes(),
111 vec![128, 0, 0, 0, 0, 1, 0, 2, 0, 4, 49, 50, 51, 52]
112 );
113 }
114}