surge_ping/icmp/
icmpv6.rs1use std::convert::TryInto;
2use std::net::Ipv6Addr;
3
4use pnet_packet::icmpv6::{self, Icmpv6Code, Icmpv6Type};
5use pnet_packet::Packet;
6use pnet_packet::PacketSize;
7
8use crate::error::{MalformedPacketError, Result, SurgeError};
9
10use super::{PingIdentifier, PingSequence};
11
12#[allow(dead_code)]
13pub fn make_icmpv6_echo_packet(
14 ident: PingIdentifier,
15 seq_cnt: PingSequence,
16 payload: &[u8],
17) -> Result<Vec<u8>> {
18 let mut buf = vec![0; 8 + payload.len()]; let mut packet = icmpv6::echo_request::MutableEchoRequestPacket::new(&mut buf[..])
20 .ok_or(SurgeError::IncorrectBufferSize)?;
21 packet.set_icmpv6_type(icmpv6::Icmpv6Types::EchoRequest);
22 packet.set_identifier(ident.into_u16());
23 packet.set_sequence_number(seq_cnt.into_u16());
24 packet.set_payload(payload);
25
26 Ok(packet.packet().to_vec())
30}
31
32#[derive(Debug)]
34pub struct Icmpv6Packet {
35 source: Ipv6Addr,
36 destination: Ipv6Addr,
37 max_hop_limit: u8,
38 icmpv6_type: Icmpv6Type,
39 icmpv6_code: Icmpv6Code,
40 size: usize,
41 real_dest: Ipv6Addr,
42 identifier: PingIdentifier,
43 sequence: PingSequence,
44}
45
46impl Default for Icmpv6Packet {
47 fn default() -> Self {
48 Icmpv6Packet {
49 source: Ipv6Addr::LOCALHOST,
50 destination: Ipv6Addr::LOCALHOST,
51 max_hop_limit: 0,
52 icmpv6_type: Icmpv6Type::new(0),
53 icmpv6_code: Icmpv6Code::new(0),
54 size: 0,
55 real_dest: Ipv6Addr::LOCALHOST,
56 identifier: PingIdentifier(0),
57 sequence: PingSequence(0),
58 }
59 }
60}
61
62impl Icmpv6Packet {
63 fn source(&mut self, source: Ipv6Addr) -> &mut Self {
64 self.source = source;
65 self
66 }
67
68 pub fn get_source(&self) -> Ipv6Addr {
70 self.source
71 }
72
73 fn destination(&mut self, destination: Ipv6Addr) -> &mut Self {
74 self.destination = destination;
75 self
76 }
77
78 pub fn get_destination(&self) -> Ipv6Addr {
80 self.destination
81 }
82
83 fn max_hop_limit(&mut self, max_hop_limit: u8) -> &mut Self {
84 self.max_hop_limit = max_hop_limit;
85 self
86 }
87
88 pub fn get_max_hop_limit(&self) -> u8 {
90 self.max_hop_limit
91 }
92
93 fn icmpv6_type(&mut self, icmpv6_type: Icmpv6Type) -> &mut Self {
94 self.icmpv6_type = icmpv6_type;
95 self
96 }
97
98 pub fn get_icmpv6_type(&self) -> Icmpv6Type {
100 self.icmpv6_type
101 }
102
103 fn icmpv6_code(&mut self, icmpv6_code: Icmpv6Code) -> &mut Self {
104 self.icmpv6_code = icmpv6_code;
105 self
106 }
107
108 pub fn get_icmpv6_code(&self) -> Icmpv6Code {
110 self.icmpv6_code
111 }
112
113 fn size(&mut self, size: usize) -> &mut Self {
114 self.size = size;
115 self
116 }
117
118 pub fn get_size(&self) -> usize {
120 self.size
121 }
122
123 fn real_dest(&mut self, addr: Ipv6Addr) -> &mut Self {
124 self.real_dest = addr;
125 self
126 }
127
128 pub fn get_real_dest(&self) -> Ipv6Addr {
131 self.real_dest
132 }
133
134 fn identifier(&mut self, identifier: PingIdentifier) -> &mut Self {
135 self.identifier = identifier;
136 self
137 }
138
139 pub fn get_identifier(&self) -> PingIdentifier {
141 self.identifier
142 }
143
144 fn sequence(&mut self, sequence: PingSequence) -> &mut Self {
145 self.sequence = sequence;
146 self
147 }
148
149 pub fn get_sequence(&self) -> PingSequence {
151 self.sequence
152 }
153
154 pub fn decode(buf: &[u8], destination: Ipv6Addr) -> Result<Self> {
156 let icmpv6_packet = icmpv6::Icmpv6Packet::new(buf)
158 .ok_or_else(|| SurgeError::from(MalformedPacketError::NotIcmpv6Packet))?;
159 let icmpv6_payload = icmpv6_packet.payload();
160 match icmpv6_packet.get_icmpv6_type() {
161 icmpv6::Icmpv6Types::EchoRequest => Err(SurgeError::EchoRequestPacket),
162 icmpv6::Icmpv6Types::EchoReply => {
163 if icmpv6_payload.len() < 4 {
164 return Err(SurgeError::from(MalformedPacketError::PayloadTooShort {
165 got: icmpv6_payload.len(),
166 want: 4,
167 }));
168 }
169 let identifier = u16::from_be_bytes(icmpv6_payload[0..2].try_into().unwrap());
170 let sequence = u16::from_be_bytes(icmpv6_payload[2..4].try_into().unwrap());
171 let mut packet = Icmpv6Packet::default();
172 packet
173 .source(destination)
174 .destination(Ipv6Addr::LOCALHOST)
175 .max_hop_limit(0)
176 .icmpv6_type(icmpv6_packet.get_icmpv6_type())
177 .icmpv6_code(icmpv6_packet.get_icmpv6_code())
178 .size(icmpv6_packet.packet().len())
179 .real_dest(destination)
180 .identifier(identifier.into())
181 .sequence(sequence.into());
182 Ok(packet)
183 }
184 _ => {
185 if icmpv6_payload.len() < 48 {
187 return Err(SurgeError::from(MalformedPacketError::PayloadTooShort {
188 got: icmpv6_payload.len(),
189 want: 48,
190 }));
191 }
192 let identifier = u16::from_be_bytes(icmpv6_payload[44..46].try_into().unwrap());
193 let sequence = u16::from_be_bytes(icmpv6_payload[46..48].try_into().unwrap());
194 let mut packet = Icmpv6Packet::default();
195 packet
196 .source(destination)
197 .destination(destination)
198 .max_hop_limit(0)
199 .icmpv6_type(icmpv6_packet.get_icmpv6_type())
200 .icmpv6_code(icmpv6_packet.get_icmpv6_code())
201 .size(icmpv6_packet.packet_size())
202 .identifier(identifier.into())
203 .sequence(sequence.into());
204 Ok(packet)
205 }
206 }
207 }
208}