1use pnet::packet::Packet;
2use std::net::Ipv6Addr;
3use crate::packet::ethernet::ETHERNET_HEADER_LEN;
4use crate::packet::ipv6::IPV6_HEADER_LEN;
5
6pub const ICMPV6_HEADER_LEN: usize =
7 pnet::packet::icmpv6::echo_request::MutableEchoRequestPacket::minimum_packet_size();
8pub const ICMPV6_PACKET_LEN: usize = ETHERNET_HEADER_LEN + IPV6_HEADER_LEN + ICMPV6_HEADER_LEN;
10pub const ICMPV6_IP_PACKET_LEN: usize = IPV6_HEADER_LEN + ICMPV6_HEADER_LEN;
12
13#[derive(Clone, Debug, PartialEq)]
16pub enum Icmpv6Type {
17 DestinationUnreachable,
18 PacketTooBig,
19 TimeExceeded,
20 ParameterProblem,
21 EchoRequest,
22 EchoReply,
23 MulticastListenerQuery,
24 MulticastListenerReport,
25 MulticastListenerDone,
26 RouterSolicitation,
27 RouterAdvertisement,
28 NeighborSolicitation,
29 NeighborAdvertisement,
30 RedirectMessage,
31 RouterRenumbering,
32 NodeInformationQuery,
33 NodeInformationResponse,
34 InverseNeighborDiscoverySolicitation,
35 InverseNeighborDiscoveryAdvertisement,
36 Version2MulticastListenerReport,
37 HomeAgentAddressDiscoveryRequest,
38 HomeAgentAddressDiscoveryReply,
39 MobilePrefixSolicitation,
40 MobilePrefixAdvertisement,
41 CertificationPathSolicitationMessage,
42 CertificationPathAdvertisementMessage,
43 ExperimentalMobilityProtocols,
44 MulticastRouterAdvertisement,
45 MulticastRouterSolicitation,
46 MulticastRouterTermination,
47 FMIPv6Messages,
48 RPLControlMessage,
49 ILNPv6LocatorUpdateMessage,
50 DuplicateAddressRequest,
51 DuplicateAddressConfirmation,
52 MPLControlMessage,
53 ExtendedEchoRequest,
54 ExtendedEchoReply,
55 Unknown(u8),
56}
57
58impl Icmpv6Type {
59 pub fn number(&self) -> u8 {
61 match *self {
62 Icmpv6Type::DestinationUnreachable => 1,
63 Icmpv6Type::PacketTooBig => 2,
64 Icmpv6Type::TimeExceeded => 3,
65 Icmpv6Type::ParameterProblem => 4,
66 Icmpv6Type::EchoRequest => 128,
67 Icmpv6Type::EchoReply => 129,
68 Icmpv6Type::MulticastListenerQuery => 130,
69 Icmpv6Type::MulticastListenerReport => 131,
70 Icmpv6Type::MulticastListenerDone => 132,
71 Icmpv6Type::RouterSolicitation => 133,
72 Icmpv6Type::RouterAdvertisement => 134,
73 Icmpv6Type::NeighborSolicitation => 135,
74 Icmpv6Type::NeighborAdvertisement => 136,
75 Icmpv6Type::RedirectMessage => 137,
76 Icmpv6Type::RouterRenumbering => 138,
77 Icmpv6Type::NodeInformationQuery => 139,
78 Icmpv6Type::NodeInformationResponse => 140,
79 Icmpv6Type::InverseNeighborDiscoverySolicitation => 141,
80 Icmpv6Type::InverseNeighborDiscoveryAdvertisement => 142,
81 Icmpv6Type::Version2MulticastListenerReport => 143,
82 Icmpv6Type::HomeAgentAddressDiscoveryRequest => 144,
83 Icmpv6Type::HomeAgentAddressDiscoveryReply => 145,
84 Icmpv6Type::MobilePrefixSolicitation => 146,
85 Icmpv6Type::MobilePrefixAdvertisement => 147,
86 Icmpv6Type::CertificationPathSolicitationMessage => 148,
87 Icmpv6Type::CertificationPathAdvertisementMessage => 149,
88 Icmpv6Type::ExperimentalMobilityProtocols => 150,
89 Icmpv6Type::MulticastRouterAdvertisement => 151,
90 Icmpv6Type::MulticastRouterSolicitation => 152,
91 Icmpv6Type::MulticastRouterTermination => 153,
92 Icmpv6Type::FMIPv6Messages => 154,
93 Icmpv6Type::RPLControlMessage => 155,
94 Icmpv6Type::ILNPv6LocatorUpdateMessage => 156,
95 Icmpv6Type::DuplicateAddressRequest => 157,
96 Icmpv6Type::DuplicateAddressConfirmation => 158,
97 Icmpv6Type::MPLControlMessage => 159,
98 Icmpv6Type::ExtendedEchoRequest => 160,
99 Icmpv6Type::ExtendedEchoReply => 161,
100 Icmpv6Type::Unknown(n) => n,
101 }
102 }
103 pub fn id(&self) -> String {
105 match *self {
106 Icmpv6Type::DestinationUnreachable => String::from("destination_unreachable"),
107 Icmpv6Type::PacketTooBig => String::from("packet_too_big"),
108 Icmpv6Type::TimeExceeded => String::from("time_exceeded"),
109 Icmpv6Type::ParameterProblem => String::from("parameter_problem"),
110 Icmpv6Type::EchoRequest => String::from("echo_request"),
111 Icmpv6Type::EchoReply => String::from("echo_reply"),
112 Icmpv6Type::MulticastListenerQuery => String::from("multicast_listener_query"),
113 Icmpv6Type::MulticastListenerReport => String::from("multicast_listener_report"),
114 Icmpv6Type::MulticastListenerDone => String::from("multicast_listener_done"),
115 Icmpv6Type::RouterSolicitation => String::from("router_solicitation"),
116 Icmpv6Type::RouterAdvertisement => String::from("router_advertisement"),
117 Icmpv6Type::NeighborSolicitation => String::from("neighbor_solicitation"),
118 Icmpv6Type::NeighborAdvertisement => String::from("neighbor_advertisement"),
119 Icmpv6Type::RedirectMessage => String::from("redirect_message"),
120 Icmpv6Type::RouterRenumbering => String::from("router_renumbering"),
121 Icmpv6Type::NodeInformationQuery => String::from("node_information_query"),
122 Icmpv6Type::NodeInformationResponse => String::from("node_information_response"),
123 Icmpv6Type::InverseNeighborDiscoverySolicitation => {
124 String::from("inverse_neighbor_discovery_solicitation")
125 }
126 Icmpv6Type::InverseNeighborDiscoveryAdvertisement => {
127 String::from("inverse_neighbor_discovery_advertisement")
128 }
129 Icmpv6Type::Version2MulticastListenerReport => {
130 String::from("version_2_multicast_listener_report")
131 }
132 Icmpv6Type::HomeAgentAddressDiscoveryRequest => {
133 String::from("home_agent_address_discovery_request")
134 }
135 Icmpv6Type::HomeAgentAddressDiscoveryReply => {
136 String::from("home_agent_address_discovery_reply")
137 }
138 Icmpv6Type::MobilePrefixSolicitation => String::from("mobile_prefix_solicitation"),
139 Icmpv6Type::MobilePrefixAdvertisement => String::from("mobile_prefix_advertisement"),
140 Icmpv6Type::CertificationPathSolicitationMessage => {
141 String::from("certification_path_solicitation_message")
142 }
143 Icmpv6Type::CertificationPathAdvertisementMessage => {
144 String::from("certification_path_advertisement_message")
145 }
146 Icmpv6Type::ExperimentalMobilityProtocols => {
147 String::from("experimental_mobility_protocols")
148 }
149 Icmpv6Type::MulticastRouterAdvertisement => {
150 String::from("multicast_router_advertisement")
151 }
152 Icmpv6Type::MulticastRouterSolicitation => {
153 String::from("multicast_router_solicitation")
154 }
155 Icmpv6Type::MulticastRouterTermination => String::from("multicast_router_termination"),
156 Icmpv6Type::FMIPv6Messages => String::from("fmipv6_messages"),
157 Icmpv6Type::RPLControlMessage => String::from("rpl_control_message"),
158 Icmpv6Type::ILNPv6LocatorUpdateMessage => String::from("ilnpv6_locator_update_message"),
159 Icmpv6Type::DuplicateAddressRequest => String::from("duplicate_address_request"),
160 Icmpv6Type::DuplicateAddressConfirmation => {
161 String::from("duplicate_address_confirmation")
162 }
163 Icmpv6Type::MPLControlMessage => String::from("mpl_control_message"),
164 Icmpv6Type::ExtendedEchoRequest => String::from("extended_echo_request"),
165 Icmpv6Type::ExtendedEchoReply => String::from("extended_echo_reply"),
166 Icmpv6Type::Unknown(n) => format!("unknown_{}", n),
167 }
168 }
169 pub fn name(&self) -> String {
171 match *self {
172 Icmpv6Type::DestinationUnreachable => String::from("Destination Unreachable"),
173 Icmpv6Type::PacketTooBig => String::from("Packet Too Big"),
174 Icmpv6Type::TimeExceeded => String::from("Time Exceeded"),
175 Icmpv6Type::ParameterProblem => String::from("Parameter Problem"),
176 Icmpv6Type::EchoRequest => String::from("Echo Request"),
177 Icmpv6Type::EchoReply => String::from("Echo Reply"),
178 Icmpv6Type::MulticastListenerQuery => String::from("Multicast Listener Query"),
179 Icmpv6Type::MulticastListenerReport => String::from("Multicast Listener Report"),
180 Icmpv6Type::MulticastListenerDone => String::from("Multicast Listener Done"),
181 Icmpv6Type::RouterSolicitation => String::from("Router Solicitation"),
182 Icmpv6Type::RouterAdvertisement => String::from("Router Advertisement"),
183 Icmpv6Type::NeighborSolicitation => String::from("Neighbor Solicitation"),
184 Icmpv6Type::NeighborAdvertisement => String::from("Neighbor Advertisement"),
185 Icmpv6Type::RedirectMessage => String::from("Redirect Message"),
186 Icmpv6Type::RouterRenumbering => String::from("Router Renumbering"),
187 Icmpv6Type::NodeInformationQuery => String::from("Node Information Query"),
188 Icmpv6Type::NodeInformationResponse => String::from("Node Information Response"),
189 Icmpv6Type::InverseNeighborDiscoverySolicitation => {
190 String::from("Inverse Neighbor Discovery Solicitation")
191 }
192 Icmpv6Type::InverseNeighborDiscoveryAdvertisement => {
193 String::from("Inverse Neighbor Discovery Advertisement")
194 }
195 Icmpv6Type::Version2MulticastListenerReport => {
196 String::from("Version 2 Multicast Listener Report")
197 }
198 Icmpv6Type::HomeAgentAddressDiscoveryRequest => {
199 String::from("Home Agent Address Discovery Request")
200 }
201 Icmpv6Type::HomeAgentAddressDiscoveryReply => {
202 String::from("Home Agent Address Discovery Reply")
203 }
204 Icmpv6Type::MobilePrefixSolicitation => String::from("Mobile Prefix Solicitation"),
205 Icmpv6Type::MobilePrefixAdvertisement => String::from("Mobile Prefix Advertisement"),
206 Icmpv6Type::CertificationPathSolicitationMessage => {
207 String::from("Certification Path Solicitation Message")
208 }
209 Icmpv6Type::CertificationPathAdvertisementMessage => {
210 String::from("Certification Path Advertisement Message")
211 }
212 Icmpv6Type::ExperimentalMobilityProtocols => {
213 String::from("Experimental Mobility Protocols")
214 }
215 Icmpv6Type::MulticastRouterAdvertisement => {
216 String::from("Multicast Router Advertisement")
217 }
218 Icmpv6Type::MulticastRouterSolicitation => {
219 String::from("Multicast Router Solicitation")
220 }
221 Icmpv6Type::MulticastRouterTermination => String::from("Multicast Router Termination"),
222 Icmpv6Type::FMIPv6Messages => String::from("FMIPv6 Messages"),
223 Icmpv6Type::RPLControlMessage => String::from("RPL Control Message"),
224 Icmpv6Type::ILNPv6LocatorUpdateMessage => String::from("ILNPv6 Locator Update Message"),
225 Icmpv6Type::DuplicateAddressRequest => String::from("Duplicate Address Request"),
226 Icmpv6Type::DuplicateAddressConfirmation => {
227 String::from("Duplicate Address Confirmation")
228 }
229 Icmpv6Type::MPLControlMessage => String::from("MPL Control Message"),
230 Icmpv6Type::ExtendedEchoRequest => String::from("Extended Echo Request"),
231 Icmpv6Type::ExtendedEchoReply => String::from("Extended Echo Reply"),
232 Icmpv6Type::Unknown(n) => format!("Unknown ({})", n),
233 }
234 }
235 pub(crate) fn from_pnet_type(t: pnet::packet::icmpv6::Icmpv6Type) -> Icmpv6Type {
236 match t {
237 pnet::packet::icmpv6::Icmpv6Types::DestinationUnreachable => {
238 Icmpv6Type::DestinationUnreachable
239 }
240 pnet::packet::icmpv6::Icmpv6Types::PacketTooBig => Icmpv6Type::PacketTooBig,
241 pnet::packet::icmpv6::Icmpv6Types::TimeExceeded => Icmpv6Type::TimeExceeded,
242 pnet::packet::icmpv6::Icmpv6Types::ParameterProblem => Icmpv6Type::ParameterProblem,
243 pnet::packet::icmpv6::Icmpv6Types::EchoRequest => Icmpv6Type::EchoRequest,
244 pnet::packet::icmpv6::Icmpv6Types::EchoReply => Icmpv6Type::EchoReply,
245 pnet::packet::icmpv6::Icmpv6Types::NeighborSolicit => Icmpv6Type::NeighborSolicitation,
246 pnet::packet::icmpv6::Icmpv6Types::NeighborAdvert => Icmpv6Type::NeighborAdvertisement,
247 pnet::packet::icmpv6::Icmpv6Types::RouterSolicit => Icmpv6Type::RouterSolicitation,
248 pnet::packet::icmpv6::Icmpv6Types::RouterAdvert => Icmpv6Type::RouterAdvertisement,
249 _ => Icmpv6Type::Unknown(t.0),
250 }
251 }
252}
253
254#[derive(Clone, Debug, PartialEq)]
256pub struct Icmpv6Packet {
257 pub icmpv6_type: Icmpv6Type,
259 pub icmpv6_code: u8,
261 pub checksum: u16,
263 pub payload: Vec<u8>,
265}
266
267impl Icmpv6Packet {
268 pub(crate) fn from_pnet_packet(packet: &pnet::packet::icmpv6::Icmpv6Packet) -> Icmpv6Packet {
269 Icmpv6Packet {
270 icmpv6_type: Icmpv6Type::from_pnet_type(packet.get_icmpv6_type()),
271 icmpv6_code: packet.get_icmpv6_code().0,
272 checksum: packet.get_checksum(),
273 payload: packet.payload().to_vec(),
274 }
275 }
276 pub fn from_bytes(packet: &[u8]) -> Icmpv6Packet {
278 let icmpv6_packet = pnet::packet::icmpv6::Icmpv6Packet::new(packet).unwrap();
279 Icmpv6Packet::from_pnet_packet(&icmpv6_packet)
280 }
281}
282
283pub(crate) fn build_icmpv6_echo_packet(
285 icmp_packet: &mut pnet::packet::icmpv6::echo_request::MutableEchoRequestPacket,
286 src_ip: Ipv6Addr,
287 dst_ip: Ipv6Addr,
288) {
289 icmp_packet.set_icmpv6_type(pnet::packet::icmpv6::Icmpv6Types::EchoRequest);
290 icmp_packet.set_identifier(rand::random::<u16>());
291 icmp_packet.set_sequence_number(rand::random::<u16>());
292 let icmpv6_packet = pnet::packet::icmpv6::Icmpv6Packet::new(icmp_packet.packet()).unwrap();
293 let icmpv6_checksum = pnet::packet::icmpv6::checksum(&icmpv6_packet, &src_ip, &dst_ip);
294 icmp_packet.set_checksum(icmpv6_checksum);
296}
297
298#[derive(Clone, Debug)]
300pub struct Icmpv6PacketBuilder {
301 pub src_ip: Ipv6Addr,
303 pub dst_ip: Ipv6Addr,
305 pub icmpv6_type: Icmpv6Type,
307 pub sequence_number: Option<u16>,
309 pub identifier: Option<u16>,
311}
312
313impl Icmpv6PacketBuilder {
314 pub fn new(src_ip: Ipv6Addr, dst_ip: Ipv6Addr) -> Icmpv6PacketBuilder {
316 Icmpv6PacketBuilder {
317 src_ip,
318 dst_ip,
319 icmpv6_type: Icmpv6Type::EchoRequest,
320 sequence_number: None,
321 identifier: None,
322 }
323 }
324 pub fn build(&self) -> Vec<u8> {
326 let buffer: &mut [u8] = &mut [0u8; ICMPV6_HEADER_LEN];
327 let mut icmp_packet =
328 pnet::packet::icmpv6::echo_request::MutableEchoRequestPacket::new(buffer).unwrap();
329 icmp_packet.set_icmpv6_type(pnet::packet::icmpv6::Icmpv6Type(self.icmpv6_type.number()));
330 icmp_packet.set_identifier(self.identifier.unwrap_or(rand::random::<u16>()));
331 icmp_packet.set_sequence_number(self.sequence_number.unwrap_or(rand::random::<u16>()));
332 let icmpv6_packet = pnet::packet::icmpv6::Icmpv6Packet::new(icmp_packet.packet()).unwrap();
333 let icmpv6_checksum =
334 pnet::packet::icmpv6::checksum(&icmpv6_packet, &self.src_ip, &self.dst_ip);
335 icmp_packet.set_checksum(icmpv6_checksum);
336 icmp_packet.packet().to_vec()
337 }
338}