1use crate::checksum::{ChecksumMode, ChecksumState, TransportChecksumContext};
4use crate::ip::IpNextProtocol;
5use crate::ipv6::IPV6_HEADER_LEN;
6use crate::{
7 ethernet::ETHERNET_HEADER_LEN,
8 packet::{MutablePacket, Packet},
9};
10use std::net::Ipv6Addr;
11
12use bytes::Bytes;
13#[cfg(feature = "serde")]
14use serde::{Deserialize, Serialize};
15
16pub const ICMPV6_COMMON_HEADER_LEN: usize = 4;
18pub const ICMPV6_HEADER_LEN: usize = 8;
20pub const ICMPV6_PACKET_LEN: usize = ETHERNET_HEADER_LEN + IPV6_HEADER_LEN + ICMPV6_HEADER_LEN;
22pub const ICMPV6_IP_PACKET_LEN: usize = IPV6_HEADER_LEN + ICMPV6_HEADER_LEN;
24
25#[repr(u8)]
28#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
29#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
30pub enum Icmpv6Type {
31 DestinationUnreachable,
32 PacketTooBig,
33 TimeExceeded,
34 ParameterProblem,
35 EchoRequest,
36 EchoReply,
37 MulticastListenerQuery,
38 MulticastListenerReport,
39 MulticastListenerDone,
40 RouterSolicitation,
41 RouterAdvertisement,
42 NeighborSolicitation,
43 NeighborAdvertisement,
44 RedirectMessage,
45 RouterRenumbering,
46 NodeInformationQuery,
47 NodeInformationResponse,
48 InverseNeighborDiscoverySolicitation,
49 InverseNeighborDiscoveryAdvertisement,
50 Version2MulticastListenerReport,
51 HomeAgentAddressDiscoveryRequest,
52 HomeAgentAddressDiscoveryReply,
53 MobilePrefixSolicitation,
54 MobilePrefixAdvertisement,
55 CertificationPathSolicitationMessage,
56 CertificationPathAdvertisementMessage,
57 ExperimentalMobilityProtocols,
58 MulticastRouterAdvertisement,
59 MulticastRouterSolicitation,
60 MulticastRouterTermination,
61 FMIPv6Messages,
62 RPLControlMessage,
63 ILNPv6LocatorUpdateMessage,
64 DuplicateAddressRequest,
65 DuplicateAddressConfirmation,
66 MPLControlMessage,
67 ExtendedEchoRequest,
68 ExtendedEchoReply,
69 Unknown(u8),
70}
71
72impl Icmpv6Type {
73 pub fn new(value: u8) -> Self {
74 match value {
75 1 => Icmpv6Type::DestinationUnreachable,
76 2 => Icmpv6Type::PacketTooBig,
77 3 => Icmpv6Type::TimeExceeded,
78 4 => Icmpv6Type::ParameterProblem,
79 128 => Icmpv6Type::EchoRequest,
80 129 => Icmpv6Type::EchoReply,
81 130 => Icmpv6Type::MulticastListenerQuery,
82 131 => Icmpv6Type::MulticastListenerReport,
83 132 => Icmpv6Type::MulticastListenerDone,
84 133 => Icmpv6Type::RouterSolicitation,
85 134 => Icmpv6Type::RouterAdvertisement,
86 135 => Icmpv6Type::NeighborSolicitation,
87 136 => Icmpv6Type::NeighborAdvertisement,
88 137 => Icmpv6Type::RedirectMessage,
89 138 => Icmpv6Type::RouterRenumbering,
90 139 => Icmpv6Type::NodeInformationQuery,
91 140 => Icmpv6Type::NodeInformationResponse,
92 141 => Icmpv6Type::InverseNeighborDiscoverySolicitation,
93 142 => Icmpv6Type::InverseNeighborDiscoveryAdvertisement,
94 143 => Icmpv6Type::Version2MulticastListenerReport,
95 144 => Icmpv6Type::HomeAgentAddressDiscoveryRequest,
96 145 => Icmpv6Type::HomeAgentAddressDiscoveryReply,
97 146 => Icmpv6Type::MobilePrefixSolicitation,
98 147 => Icmpv6Type::MobilePrefixAdvertisement,
99 148 => Icmpv6Type::CertificationPathSolicitationMessage,
100 149 => Icmpv6Type::CertificationPathAdvertisementMessage,
101 150 => Icmpv6Type::ExperimentalMobilityProtocols,
102 151 => Icmpv6Type::MulticastRouterAdvertisement,
103 152 => Icmpv6Type::MulticastRouterSolicitation,
104 153 => Icmpv6Type::MulticastRouterTermination,
105 154 => Icmpv6Type::FMIPv6Messages,
106 155 => Icmpv6Type::RPLControlMessage,
107 156 => Icmpv6Type::ILNPv6LocatorUpdateMessage,
108 157 => Icmpv6Type::DuplicateAddressRequest,
109 158 => Icmpv6Type::DuplicateAddressConfirmation,
110 159 => Icmpv6Type::MPLControlMessage,
111 160 => Icmpv6Type::ExtendedEchoRequest,
112 161 => Icmpv6Type::ExtendedEchoReply,
113 n => Icmpv6Type::Unknown(n),
114 }
115 }
116 pub fn name(&self) -> &'static str {
117 match self {
118 Icmpv6Type::DestinationUnreachable => "Destination Unreachable",
119 Icmpv6Type::PacketTooBig => "Packet Too Big",
120 Icmpv6Type::TimeExceeded => "Time Exceeded",
121 Icmpv6Type::ParameterProblem => "Parameter Problem",
122 Icmpv6Type::EchoRequest => "Echo Request",
123 Icmpv6Type::EchoReply => "Echo Reply",
124 Icmpv6Type::MulticastListenerQuery => "Multicast Listener Query",
125 Icmpv6Type::MulticastListenerReport => "Multicast Listener Report",
126 Icmpv6Type::MulticastListenerDone => "Multicast Listener Done",
127 Icmpv6Type::RouterSolicitation => "Router Solicitation",
128 Icmpv6Type::RouterAdvertisement => "Router Advertisement",
129 Icmpv6Type::NeighborSolicitation => "Neighbor Solicitation",
130 Icmpv6Type::NeighborAdvertisement => "Neighbor Advertisement",
131 Icmpv6Type::RedirectMessage => "Redirect Message",
132 Icmpv6Type::RouterRenumbering => "Router Renumbering",
133 Icmpv6Type::NodeInformationQuery => "Node Information Query",
134 Icmpv6Type::NodeInformationResponse => "Node Information Response",
135 Icmpv6Type::InverseNeighborDiscoverySolicitation => {
136 "Inverse Neighbor Discovery Solicitation"
137 }
138 Icmpv6Type::InverseNeighborDiscoveryAdvertisement => {
139 "Inverse Neighbor Discovery Advertisement"
140 }
141 Icmpv6Type::Version2MulticastListenerReport => "Version 2 Multicast Listener Report",
142 Icmpv6Type::HomeAgentAddressDiscoveryRequest => "Home Agent Address Discovery Request",
143 Icmpv6Type::HomeAgentAddressDiscoveryReply => "Home Agent Address Discovery Reply",
144 Icmpv6Type::MobilePrefixSolicitation => "Mobile Prefix Solicitation",
145 Icmpv6Type::MobilePrefixAdvertisement => "Mobile Prefix Advertisement",
146 Icmpv6Type::CertificationPathSolicitationMessage => {
147 "Certification Path Solicitation Message"
148 }
149 Icmpv6Type::CertificationPathAdvertisementMessage => {
150 "Certification Path Advertisement Message"
151 }
152 Icmpv6Type::ExperimentalMobilityProtocols => "Experimental Mobility Protocols",
153 Icmpv6Type::MulticastRouterAdvertisement => "Multicast Router Advertisement",
154 Icmpv6Type::MulticastRouterSolicitation => "Multicast Router Solicitation",
155 Icmpv6Type::MulticastRouterTermination => "Multicast Router Termination",
156 Icmpv6Type::FMIPv6Messages => "FMIPv6 Messages",
157 Icmpv6Type::RPLControlMessage => "RPL Control Message",
158 Icmpv6Type::ILNPv6LocatorUpdateMessage => "ILNPv6 Locator Update Message",
159 Icmpv6Type::DuplicateAddressRequest => "Duplicate Address Request",
160 Icmpv6Type::DuplicateAddressConfirmation => "Duplicate Address Confirmation",
161 Icmpv6Type::MPLControlMessage => "MPL Control Message",
162 Icmpv6Type::ExtendedEchoRequest => "Extended Echo Request",
163 Icmpv6Type::ExtendedEchoReply => "Extended Echo Reply",
164 Icmpv6Type::Unknown(_) => "Unknown",
165 }
166 }
167 pub fn value(&self) -> u8 {
168 match self {
169 Icmpv6Type::DestinationUnreachable => 1,
170 Icmpv6Type::PacketTooBig => 2,
171 Icmpv6Type::TimeExceeded => 3,
172 Icmpv6Type::ParameterProblem => 4,
173 Icmpv6Type::EchoRequest => 128,
174 Icmpv6Type::EchoReply => 129,
175 Icmpv6Type::MulticastListenerQuery => 130,
176 Icmpv6Type::MulticastListenerReport => 131,
177 Icmpv6Type::MulticastListenerDone => 132,
178 Icmpv6Type::RouterSolicitation => 133,
179 Icmpv6Type::RouterAdvertisement => 134,
180 Icmpv6Type::NeighborSolicitation => 135,
181 Icmpv6Type::NeighborAdvertisement => 136,
182 Icmpv6Type::RedirectMessage => 137,
183 Icmpv6Type::RouterRenumbering => 138,
184 Icmpv6Type::NodeInformationQuery => 139,
185 Icmpv6Type::NodeInformationResponse => 140,
186 Icmpv6Type::InverseNeighborDiscoverySolicitation => 141,
187 Icmpv6Type::InverseNeighborDiscoveryAdvertisement => 142,
188 Icmpv6Type::Version2MulticastListenerReport => 143,
189 Icmpv6Type::HomeAgentAddressDiscoveryRequest => 144,
190 Icmpv6Type::HomeAgentAddressDiscoveryReply => 145,
191 Icmpv6Type::MobilePrefixSolicitation => 146,
192 Icmpv6Type::MobilePrefixAdvertisement => 147,
193 Icmpv6Type::CertificationPathSolicitationMessage => 148,
194 Icmpv6Type::CertificationPathAdvertisementMessage => 149,
195 Icmpv6Type::ExperimentalMobilityProtocols => 150,
196 Icmpv6Type::MulticastRouterAdvertisement => 151,
197 Icmpv6Type::MulticastRouterSolicitation => 152,
198 Icmpv6Type::MulticastRouterTermination => 153,
199 Icmpv6Type::FMIPv6Messages => 154,
200 Icmpv6Type::RPLControlMessage => 155,
201 Icmpv6Type::ILNPv6LocatorUpdateMessage => 156,
202 Icmpv6Type::DuplicateAddressRequest => 157,
203 Icmpv6Type::DuplicateAddressConfirmation => 158,
204 Icmpv6Type::MPLControlMessage => 159,
205 Icmpv6Type::ExtendedEchoRequest => 160,
206 Icmpv6Type::ExtendedEchoReply => 161,
207 Icmpv6Type::Unknown(n) => *n,
208 }
209 }
210}
211
212#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
214#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
215pub struct Icmpv6Code(pub u8);
216
217impl Icmpv6Code {
218 pub fn new(val: u8) -> Icmpv6Code {
220 Icmpv6Code(val)
221 }
222 pub fn value(&self) -> u8 {
224 self.0
225 }
226}
227
228#[derive(Clone, Debug, PartialEq, Eq)]
230#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
231pub struct Icmpv6Header {
232 pub icmpv6_type: Icmpv6Type,
233 pub icmpv6_code: Icmpv6Code,
234 pub checksum: u16,
235}
236
237#[derive(Clone, Debug, PartialEq, Eq)]
239pub struct Icmpv6Packet {
240 pub header: Icmpv6Header,
241 pub payload: Bytes,
242}
243
244impl Packet for Icmpv6Packet {
245 type Header = Icmpv6Header;
246
247 fn from_buf(bytes: &[u8]) -> Option<Self> {
248 if bytes.len() < ICMPV6_HEADER_LEN {
249 return None;
250 }
251 let icmpv6_type = Icmpv6Type::new(bytes[0]);
252 let icmpv6_code = Icmpv6Code::new(bytes[1]);
253 let checksum = u16::from_be_bytes([bytes[2], bytes[3]]);
254 let header = Icmpv6Header {
255 icmpv6_type,
256 icmpv6_code,
257 checksum,
258 };
259 let payload = Bytes::copy_from_slice(&bytes[ICMPV6_COMMON_HEADER_LEN..]);
260 Some(Icmpv6Packet { header, payload })
261 }
262 fn from_bytes(bytes: Bytes) -> Option<Self> {
263 Self::from_buf(&bytes)
264 }
265 fn to_bytes(&self) -> Bytes {
266 let mut bytes = Vec::with_capacity(ICMPV6_COMMON_HEADER_LEN + self.payload.len());
267 bytes.push(self.header.icmpv6_type.value());
268 bytes.push(self.header.icmpv6_code.value());
269 bytes.extend_from_slice(&self.header.checksum.to_be_bytes());
270 bytes.extend_from_slice(&self.payload);
271 Bytes::from(bytes)
272 }
273 fn header(&self) -> Bytes {
274 self.to_bytes().slice(..self.header_len())
275 }
276
277 fn payload(&self) -> Bytes {
278 self.payload.clone()
279 }
280
281 fn header_len(&self) -> usize {
282 ICMPV6_COMMON_HEADER_LEN
283 }
284
285 fn payload_len(&self) -> usize {
286 self.payload.len()
287 }
288
289 fn total_len(&self) -> usize {
290 self.header_len() + self.payload_len()
291 }
292
293 fn into_parts(self) -> (Self::Header, Bytes) {
294 (self.header, self.payload)
295 }
296}
297
298pub struct MutableIcmpv6Packet<'a> {
300 buffer: &'a mut [u8],
301 checksum: ChecksumState,
302 checksum_context: Option<TransportChecksumContext>,
303}
304
305impl<'a> MutablePacket<'a> for MutableIcmpv6Packet<'a> {
306 type Packet = Icmpv6Packet;
307
308 fn new(buffer: &'a mut [u8]) -> Option<Self> {
309 Icmpv6Packet::from_buf(buffer)?;
310 Some(Self {
311 buffer,
312 checksum: ChecksumState::new(),
313 checksum_context: None,
314 })
315 }
316
317 fn packet(&self) -> &[u8] {
318 &*self.buffer
319 }
320
321 fn packet_mut(&mut self) -> &mut [u8] {
322 &mut *self.buffer
323 }
324
325 fn header(&self) -> &[u8] {
326 &self.packet()[..ICMPV6_COMMON_HEADER_LEN]
327 }
328
329 fn header_mut(&mut self) -> &mut [u8] {
330 let (header, _) = (&mut *self.buffer).split_at_mut(ICMPV6_COMMON_HEADER_LEN);
331 header
332 }
333
334 fn payload(&self) -> &[u8] {
335 &self.packet()[ICMPV6_COMMON_HEADER_LEN..]
336 }
337
338 fn payload_mut(&mut self) -> &mut [u8] {
339 let (_, payload) = (&mut *self.buffer).split_at_mut(ICMPV6_COMMON_HEADER_LEN);
340 payload
341 }
342}
343
344impl<'a> MutableIcmpv6Packet<'a> {
345 pub fn new_unchecked(buffer: &'a mut [u8]) -> Self {
347 Self {
348 buffer,
349 checksum: ChecksumState::new(),
350 checksum_context: None,
351 }
352 }
353
354 fn raw(&self) -> &[u8] {
355 &*self.buffer
356 }
357
358 fn raw_mut(&mut self) -> &mut [u8] {
359 &mut *self.buffer
360 }
361
362 fn after_field_mutation(&mut self) {
363 self.checksum.mark_dirty();
364 if self.checksum.automatic() {
365 let _ = self.recompute_checksum();
366 }
367 }
368
369 fn write_checksum(&mut self, value: u16) {
370 self.raw_mut()[2..4].copy_from_slice(&value.to_be_bytes());
371 }
372
373 pub fn checksum_mode(&self) -> ChecksumMode {
375 self.checksum.mode()
376 }
377
378 pub fn set_checksum_mode(&mut self, mode: ChecksumMode) {
380 self.checksum.set_mode(mode);
381 if self.checksum.automatic() && self.checksum.is_dirty() {
382 let _ = self.recompute_checksum();
383 }
384 }
385
386 pub fn enable_auto_checksum(&mut self) {
388 self.set_checksum_mode(ChecksumMode::Automatic);
389 }
390
391 pub fn disable_auto_checksum(&mut self) {
393 self.set_checksum_mode(ChecksumMode::Manual);
394 }
395
396 pub fn is_checksum_dirty(&self) -> bool {
398 self.checksum.is_dirty()
399 }
400
401 pub fn mark_checksum_dirty(&mut self) {
403 self.checksum.mark_dirty();
404 if self.checksum.automatic() {
405 let _ = self.recompute_checksum();
406 }
407 }
408
409 pub fn set_checksum_context(&mut self, context: TransportChecksumContext) {
411 self.checksum_context = match context {
412 TransportChecksumContext::Ipv6 { .. } => Some(context),
413 _ => None,
414 };
415
416 if self.checksum.automatic() && self.checksum.is_dirty() {
417 let _ = self.recompute_checksum();
418 }
419 }
420
421 pub fn set_ipv6_checksum_context(&mut self, source: Ipv6Addr, destination: Ipv6Addr) {
423 self.set_checksum_context(TransportChecksumContext::ipv6(source, destination));
424 }
425
426 pub fn clear_checksum_context(&mut self) {
428 self.checksum_context = None;
429 }
430
431 pub fn checksum_context(&self) -> Option<TransportChecksumContext> {
433 self.checksum_context
434 }
435
436 pub fn recompute_checksum(&mut self) -> Option<u16> {
438 let context = match self.checksum_context? {
439 TransportChecksumContext::Ipv6 {
440 source,
441 destination,
442 } => (source, destination),
443 _ => return None,
444 };
445
446 let checksum = crate::util::ipv6_checksum(
447 self.raw(),
448 1,
449 &[],
450 &context.0,
451 &context.1,
452 IpNextProtocol::Icmpv6,
453 ) as u16;
454
455 self.write_checksum(checksum);
456 self.checksum.clear_dirty();
457 Some(checksum)
458 }
459
460 pub fn get_type(&self) -> Icmpv6Type {
462 Icmpv6Type::new(self.raw()[0])
463 }
464
465 pub fn set_type(&mut self, icmpv6_type: Icmpv6Type) {
467 self.raw_mut()[0] = icmpv6_type.value();
468 self.after_field_mutation();
469 }
470
471 pub fn get_code(&self) -> Icmpv6Code {
473 Icmpv6Code::new(self.raw()[1])
474 }
475
476 pub fn set_code(&mut self, icmpv6_code: Icmpv6Code) {
478 self.raw_mut()[1] = icmpv6_code.value();
479 self.after_field_mutation();
480 }
481
482 pub fn get_checksum(&self) -> u16 {
484 u16::from_be_bytes([self.raw()[2], self.raw()[3]])
485 }
486
487 pub fn set_checksum(&mut self, checksum: u16) {
489 self.write_checksum(checksum);
490 self.checksum.clear_dirty();
491 }
492}
493
494#[cfg(test)]
495mod tests {
496 use super::*;
497
498 #[test]
499 fn test_mutable_icmpv6_packet_manual_checksum() {
500 let mut raw = [
501 Icmpv6Type::EchoRequest.value(),
502 0,
503 0,
504 0,
505 0,
506 1,
507 0,
508 1,
509 b'p',
510 b'i',
511 ];
512
513 let mut packet = MutableIcmpv6Packet::new(&mut raw).expect("mutable icmpv6");
514 let addr = Ipv6Addr::LOCALHOST;
515 packet.set_ipv6_checksum_context(addr, addr);
516 packet.set_type(Icmpv6Type::EchoReply);
517
518 assert!(packet.is_checksum_dirty());
519
520 let updated = packet.recompute_checksum().expect("checksum");
521 assert_eq!(packet.get_checksum(), updated);
522
523 let frozen = packet.freeze().expect("freeze");
524 let expected = checksum(&frozen, &addr, &addr);
525 assert_eq!(packet.get_checksum(), expected);
526 }
527
528 #[test]
529 fn test_mutable_icmpv6_packet_auto_checksum() {
530 let mut raw = [
531 Icmpv6Type::EchoRequest.value(),
532 0,
533 0,
534 0,
535 0,
536 1,
537 0,
538 1,
539 b'p',
540 b'i',
541 ];
542
543 let mut packet = MutableIcmpv6Packet::new(&mut raw).expect("mutable icmpv6");
544 let addr = Ipv6Addr::LOCALHOST;
545 packet.set_ipv6_checksum_context(addr, addr);
546 let baseline = packet.recompute_checksum().expect("checksum");
547
548 packet.enable_auto_checksum();
549 packet.set_code(Icmpv6Code::new(1));
550
551 assert!(!packet.is_checksum_dirty());
552
553 let frozen = packet.freeze().expect("freeze");
554 let expected = checksum(&frozen, &addr, &addr);
555 assert_ne!(baseline, expected);
556 assert_eq!(packet.get_checksum(), expected);
557 }
558}
559
560pub fn checksum(packet: &Icmpv6Packet, source: &Ipv6Addr, destination: &Ipv6Addr) -> u16 {
562 use crate::util;
563 util::ipv6_checksum(
564 &packet.to_bytes(),
565 1, &[],
567 source,
568 destination,
569 crate::ip::IpNextProtocol::Icmpv6,
570 )
571}
572
573#[cfg(test)]
574mod checksum_tests {
575 use super::*;
576
577 #[test]
578 fn checksum_echo_request() {
579 let lo = &Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
581 let data = Bytes::from_static(&[
582 0x80, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x20, 0x20, 0x75, 0x73, 0x74, 0x20, 0x61, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20,
589 0x77, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x20, 0x74, 0x69, 0x73, 0x20, 0x62, 0x75, 0x74,
590 0x20, 0x61, 0x20, 0x73, 0x63, 0x72, 0x61, 0x74, 0x63, 0x68, 0x20, 0x20, 0x6b, 0x6e,
591 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x6e, 0x69, 0x20, 0x20, 0x20,
592 ]);
593 let mut pkg = Icmpv6Packet::from_bytes(data.clone()).unwrap();
594 assert_eq!(pkg.header.icmpv6_type, Icmpv6Type::EchoRequest);
595 assert_eq!(pkg.header.icmpv6_code, Icmpv6Code::new(0));
596 assert_eq!(pkg.header.checksum, 0xffff);
597 assert_eq!(pkg.to_bytes(), data);
598 assert_eq!(checksum(&pkg, lo, lo), 0x1d2e);
599
600 pkg.header.icmpv6_type = Icmpv6Type::new(0x81);
602 assert_eq!(checksum(&pkg, lo, lo), 0x1c2e);
603 }
604}
605
606pub mod ndp {
607 use bytes::Bytes;
612 use nex_core::bitfield::{self, u24be, u32be};
613
614 use crate::icmpv6::{ICMPV6_HEADER_LEN, Icmpv6Code, Icmpv6Header, Icmpv6Packet, Icmpv6Type};
615 use crate::packet::Packet;
616 use std::net::Ipv6Addr;
617
618 pub const NDP_SOL_PACKET_LEN: usize = 24;
620 pub const NDP_ADV_PACKET_LEN: usize = 24;
622 pub const NDP_REDIRECT_PACKET_LEN: usize = 40;
624 pub const NDP_OPT_PACKET_LEN: usize = 2;
626
627 #[allow(non_snake_case)]
628 #[allow(non_upper_case_globals)]
629 pub mod Icmpv6Codes {
630 use crate::icmpv6::Icmpv6Code;
631 pub const NoCode: Icmpv6Code = Icmpv6Code(0);
633 }
634
635 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
637 pub struct NdpOptionType(pub u8);
638
639 impl NdpOptionType {
640 pub fn new(value: u8) -> NdpOptionType {
642 NdpOptionType(value)
643 }
644 pub fn value(&self) -> u8 {
646 self.0
647 }
648 }
649
650 #[allow(non_snake_case)]
654 #[allow(non_upper_case_globals)]
655 pub mod NdpOptionTypes {
656 use super::NdpOptionType;
657
658 pub const SourceLLAddr: NdpOptionType = NdpOptionType(1);
668
669 pub const TargetLLAddr: NdpOptionType = NdpOptionType(2);
679
680 pub const PrefixInformation: NdpOptionType = NdpOptionType(3);
704
705 pub const RedirectedHeader: NdpOptionType = NdpOptionType(4);
721
722 pub const MTU: NdpOptionType = NdpOptionType(5);
734 }
735
736 #[derive(Clone, Debug, PartialEq, Eq)]
748 pub struct NdpOptionPacket {
749 pub option_type: NdpOptionType,
750 pub length: u8,
751 pub payload: Bytes,
752 }
753
754 impl Packet for NdpOptionPacket {
755 type Header = ();
756 fn from_buf(bytes: &[u8]) -> Option<Self> {
757 if bytes.len() < 2 {
758 return None;
759 }
760
761 let option_type = NdpOptionType::new(bytes[0]);
762 let length = bytes[1]; let total_len = (length as usize) * 8;
765 if bytes.len() < total_len {
766 return None;
767 }
768
769 let data_len = total_len - 2;
770 let payload = Bytes::copy_from_slice(&bytes[2..2 + data_len]);
771
772 Some(Self {
773 option_type,
774 length,
775 payload,
776 })
777 }
778 fn from_bytes(bytes: Bytes) -> Option<Self> {
779 Self::from_buf(&bytes)
780 }
781
782 fn to_bytes(&self) -> Bytes {
783 let mut bytes = Vec::with_capacity(NDP_OPT_PACKET_LEN + self.payload.len());
784 bytes.push(self.option_type.value());
785 bytes.push(self.length);
786 bytes.extend_from_slice(&self.payload);
787 Bytes::from(bytes)
788 }
789
790 fn header(&self) -> Bytes {
791 self.to_bytes().slice(..NDP_OPT_PACKET_LEN)
792 }
793
794 fn payload(&self) -> Bytes {
795 self.payload.clone()
796 }
797
798 fn header_len(&self) -> usize {
799 NDP_OPT_PACKET_LEN
800 }
801
802 fn payload_len(&self) -> usize {
803 self.payload.len()
804 }
805
806 fn total_len(&self) -> usize {
807 self.header_len() + self.payload_len()
808 }
809
810 fn into_parts(self) -> (Self::Header, Bytes) {
811 ((), self.payload)
812 }
813 }
814
815 impl NdpOptionPacket {
816 pub fn option_payload_length(&self) -> usize {
818 let len = self.payload.len();
820 if len > 0 { ((len * 8) - 2) as usize } else { 0 }
821 }
822 }
823
824 #[derive(Clone, Debug, PartialEq, Eq)]
839 pub struct RouterSolicitPacket {
840 pub header: Icmpv6Header,
841 pub reserved: u32,
842 pub options: Vec<NdpOptionPacket>,
843 pub payload: Bytes,
844 }
845
846 impl TryFrom<Icmpv6Packet> for RouterSolicitPacket {
847 type Error = &'static str;
848
849 fn try_from(value: Icmpv6Packet) -> Result<Self, Self::Error> {
850 if value.header.icmpv6_type != Icmpv6Type::RouterSolicitation {
851 return Err("Not a Router Solicitation packet");
852 }
853 if value.payload.len() < 8 {
854 return Err("Payload too short for Router Solicitation");
855 }
856 let reserved = u32::from_be_bytes([
857 value.payload[0],
858 value.payload[1],
859 value.payload[2],
860 value.payload[3],
861 ]);
862 let options = value
863 .payload
864 .slice(4..)
865 .chunks(8)
866 .map(|chunk| {
867 let option_type = NdpOptionType::new(chunk[0]);
868 let length = chunk[1];
869 let payload = Bytes::from(chunk[2..].to_vec());
870 NdpOptionPacket {
871 option_type,
872 length,
873 payload,
874 }
875 })
876 .collect();
877 Ok(RouterSolicitPacket {
878 header: value.header,
879 reserved,
880 options,
881 payload: Bytes::new(),
882 })
883 }
884 }
885
886 impl Packet for RouterSolicitPacket {
887 type Header = ();
888 fn from_buf(bytes: &[u8]) -> Option<Self> {
889 if bytes.len() < NDP_SOL_PACKET_LEN {
890 return None;
891 }
892
893 let icmpv6_type = Icmpv6Type::new(bytes[0]);
894 let icmpv6_code = Icmpv6Code::new(bytes[1]);
895 let checksum = u16::from_be_bytes([bytes[2], bytes[3]]);
896 let header = Icmpv6Header {
897 icmpv6_type,
898 icmpv6_code,
899 checksum,
900 };
901 let reserved = u32::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]);
902
903 let mut options = Vec::new();
904 let mut i = 8;
905 while i + 2 <= bytes.len() {
906 let option_type = NdpOptionType::new(bytes[i]);
907 let length = bytes[i + 1];
908 let option_len = (length as usize) * 8;
909
910 if i + option_len > bytes.len() {
911 break;
912 }
913
914 let payload = Bytes::copy_from_slice(&bytes[i + 2..i + option_len]);
915 options.push(NdpOptionPacket {
916 option_type,
917 length,
918 payload,
919 });
920 i += option_len;
921 }
922
923 let payload = Bytes::copy_from_slice(&bytes[i..]);
924
925 Some(RouterSolicitPacket {
926 header,
927 reserved,
928 options,
929 payload,
930 })
931 }
932 fn from_bytes(bytes: Bytes) -> Option<Self> {
933 Self::from_buf(&bytes)
934 }
935
936 fn to_bytes(&self) -> Bytes {
937 let mut bytes = Vec::with_capacity(NDP_SOL_PACKET_LEN);
938 bytes.push(self.header.icmpv6_type.value());
939 bytes.push(self.header.icmpv6_code.value());
940 bytes.extend_from_slice(&self.header.checksum.to_be_bytes());
941 bytes.extend_from_slice(&self.reserved.to_be_bytes());
942 for option in &self.options {
943 bytes.push(option.option_type.value());
944 bytes.push(option.length);
945 bytes.extend_from_slice(&option.payload);
946 }
947 Bytes::from(bytes)
948 }
949
950 fn header(&self) -> Bytes {
951 self.to_bytes().slice(..ICMPV6_HEADER_LEN)
952 }
953
954 fn payload(&self) -> Bytes {
955 self.payload.clone()
956 }
957
958 fn header_len(&self) -> usize {
959 ICMPV6_HEADER_LEN + 4 }
961
962 fn payload_len(&self) -> usize {
963 self.payload.len()
964 }
965
966 fn total_len(&self) -> usize {
967 self.header_len() + self.payload_len()
968 }
969 fn into_parts(self) -> (Self::Header, Bytes) {
970 ((), self.payload)
971 }
972 }
973
974 impl RouterSolicitPacket {
975 pub fn options_length(&self) -> usize {
977 if self.to_bytes().len() > 8 {
978 self.to_bytes().len() - 8
979 } else {
980 0
981 }
982 }
983 }
984
985 #[allow(non_snake_case)]
987 #[allow(non_upper_case_globals)]
988 pub mod RouterAdvertFlags {
989 pub const ManagedAddressConf: u8 = 0b10000000;
992 pub const OtherConf: u8 = 0b01000000;
995 }
996
997 #[derive(Clone, Debug, PartialEq, Eq)]
1015 pub struct RouterAdvertPacket {
1016 pub header: Icmpv6Header,
1017 pub hop_limit: u8,
1018 pub flags: u8,
1019 pub lifetime: u16,
1020 pub reachable_time: u32,
1021 pub retrans_time: u32,
1022 pub options: Vec<NdpOptionPacket>,
1023 pub payload: Bytes,
1024 }
1025
1026 impl TryFrom<Icmpv6Packet> for RouterAdvertPacket {
1027 type Error = &'static str;
1028
1029 fn try_from(value: Icmpv6Packet) -> Result<Self, Self::Error> {
1030 if value.header.icmpv6_type != Icmpv6Type::RouterAdvertisement {
1031 return Err("Not a Router Advertisement packet");
1032 }
1033 if value.payload.len() < 16 {
1034 return Err("Payload too short for Router Advertisement");
1035 }
1036 let hop_limit = value.payload[0];
1037 let flags = value.payload[1];
1038 let lifetime = u16::from_be_bytes([value.payload[2], value.payload[3]]);
1039 let reachable_time = u32::from_be_bytes([
1040 value.payload[4],
1041 value.payload[5],
1042 value.payload[6],
1043 value.payload[7],
1044 ]);
1045 let retrans_time = u32::from_be_bytes([
1046 value.payload[8],
1047 value.payload[9],
1048 value.payload[10],
1049 value.payload[11],
1050 ]);
1051 let options = value
1052 .payload
1053 .slice(12..)
1054 .chunks(8)
1055 .map(|chunk| {
1056 let option_type = NdpOptionType::new(chunk[0]);
1057 let length = chunk[1];
1058 let payload = Bytes::from(chunk[2..].to_vec());
1059 NdpOptionPacket {
1060 option_type,
1061 length,
1062 payload,
1063 }
1064 })
1065 .collect();
1066 Ok(RouterAdvertPacket {
1067 header: value.header,
1068 hop_limit,
1069 flags,
1070 lifetime,
1071 reachable_time,
1072 retrans_time,
1073 options,
1074 payload: Bytes::new(),
1075 })
1076 }
1077 }
1078 impl Packet for RouterAdvertPacket {
1079 type Header = ();
1080 fn from_buf(bytes: &[u8]) -> Option<Self> {
1081 if bytes.len() < NDP_ADV_PACKET_LEN {
1082 return None;
1083 }
1084
1085 let icmpv6_type = Icmpv6Type::new(bytes[0]);
1086 let icmpv6_code = Icmpv6Code::new(bytes[1]);
1087 let checksum = u16::from_be_bytes([bytes[2], bytes[3]]);
1088 let header = Icmpv6Header {
1089 icmpv6_type,
1090 icmpv6_code,
1091 checksum,
1092 };
1093
1094 let hop_limit = bytes[4];
1095 let flags = bytes[5];
1096 let lifetime = u16::from_be_bytes([bytes[6], bytes[7]]);
1097 let reachable_time = u32::from_be_bytes([bytes[8], bytes[9], bytes[10], bytes[11]]);
1098 let retrans_time = u32::from_be_bytes([bytes[12], bytes[13], bytes[14], bytes[15]]);
1099
1100 let mut options = Vec::new();
1101 let mut i = 16;
1102 while i + 2 <= bytes.len() {
1103 let option_type = NdpOptionType::new(bytes[i]);
1104 let length = bytes[i + 1];
1105 let option_len = (length as usize) * 8;
1106
1107 if i + option_len > bytes.len() {
1108 break;
1109 }
1110
1111 let payload = Bytes::copy_from_slice(&bytes[i + 2..i + option_len]);
1112 options.push(NdpOptionPacket {
1113 option_type,
1114 length,
1115 payload,
1116 });
1117 i += option_len;
1118 }
1119
1120 let payload = Bytes::copy_from_slice(&bytes[i..]);
1121
1122 Some(RouterAdvertPacket {
1123 header,
1124 hop_limit,
1125 flags,
1126 lifetime,
1127 reachable_time,
1128 retrans_time,
1129 options,
1130 payload,
1131 })
1132 }
1133
1134 fn from_bytes(bytes: Bytes) -> Option<Self> {
1135 Self::from_buf(&bytes)
1136 }
1137
1138 fn to_bytes(&self) -> Bytes {
1139 let mut bytes = Vec::with_capacity(NDP_ADV_PACKET_LEN);
1140 bytes.push(self.header.icmpv6_type.value());
1141 bytes.push(self.header.icmpv6_code.value());
1142 bytes.extend_from_slice(&self.header.checksum.to_be_bytes());
1143 bytes.push(self.hop_limit);
1144 bytes.push(self.flags);
1145 bytes.extend_from_slice(&self.lifetime.to_be_bytes());
1146 bytes.extend_from_slice(&self.reachable_time.to_be_bytes());
1147 bytes.extend_from_slice(&self.retrans_time.to_be_bytes());
1148 for option in &self.options {
1149 bytes.push(option.option_type.value());
1150 bytes.push(option.length);
1151 bytes.extend_from_slice(&option.payload);
1152 }
1153 Bytes::from(bytes)
1154 }
1155
1156 fn header(&self) -> Bytes {
1157 self.to_bytes().slice(..ICMPV6_HEADER_LEN + 16) }
1159 fn payload(&self) -> Bytes {
1160 self.payload.clone()
1161 }
1162 fn header_len(&self) -> usize {
1163 ICMPV6_HEADER_LEN + 16 }
1165
1166 fn payload_len(&self) -> usize {
1167 self.payload.len()
1168 }
1169
1170 fn total_len(&self) -> usize {
1171 self.header_len() + self.payload_len()
1172 }
1173 fn into_parts(self) -> (Self::Header, Bytes) {
1174 ((), self.payload)
1175 }
1176 }
1177
1178 impl RouterAdvertPacket {
1179 pub fn options_length(&self) -> usize {
1181 if self.to_bytes().len() > 16 {
1182 self.to_bytes().len() - 16
1183 } else {
1184 0
1185 }
1186 }
1187 }
1188
1189 #[derive(Clone, Debug, PartialEq, Eq)]
1211 pub struct NeighborSolicitPacket {
1212 pub header: Icmpv6Header,
1213 pub reserved: u32,
1214 pub target_addr: Ipv6Addr,
1215 pub options: Vec<NdpOptionPacket>,
1216 pub payload: Bytes,
1217 }
1218
1219 impl TryFrom<Icmpv6Packet> for NeighborSolicitPacket {
1220 type Error = &'static str;
1221
1222 fn try_from(value: Icmpv6Packet) -> Result<Self, Self::Error> {
1223 if value.header.icmpv6_type != Icmpv6Type::NeighborSolicitation {
1224 return Err("Not a Neighbor Solicitation packet");
1225 }
1226 if value.payload.len() < 24 {
1227 return Err("Payload too short for Neighbor Solicitation");
1228 }
1229 let reserved = u32::from_be_bytes([
1230 value.payload[0],
1231 value.payload[1],
1232 value.payload[2],
1233 value.payload[3],
1234 ]);
1235 let target_addr = Ipv6Addr::new(
1236 u16::from_be_bytes([value.payload[4], value.payload[5]]),
1237 u16::from_be_bytes([value.payload[6], value.payload[7]]),
1238 u16::from_be_bytes([value.payload[8], value.payload[9]]),
1239 u16::from_be_bytes([value.payload[10], value.payload[11]]),
1240 u16::from_be_bytes([value.payload[12], value.payload[13]]),
1241 u16::from_be_bytes([value.payload[14], value.payload[15]]),
1242 u16::from_be_bytes([value.payload[16], value.payload[17]]),
1243 u16::from_be_bytes([value.payload[18], value.payload[19]]),
1244 );
1245 let options = value
1246 .payload
1247 .slice(20..)
1248 .chunks(8)
1249 .map(|chunk| {
1250 let option_type = NdpOptionType::new(chunk[0]);
1251 let length = chunk[1];
1252 let payload: Bytes = Bytes::from(chunk[2..].to_vec());
1253 NdpOptionPacket {
1254 option_type,
1255 length,
1256 payload,
1257 }
1258 })
1259 .collect();
1260 Ok(NeighborSolicitPacket {
1261 header: value.header,
1262 reserved,
1263 target_addr,
1264 options,
1265 payload: Bytes::new(),
1266 })
1267 }
1268 }
1269
1270 impl Packet for NeighborSolicitPacket {
1271 type Header = ();
1272 fn from_buf(bytes: &[u8]) -> Option<Self> {
1273 if bytes.len() < 24 {
1274 return None;
1275 }
1276
1277 let icmpv6_type = Icmpv6Type::new(bytes[0]);
1278 let icmpv6_code = Icmpv6Code::new(bytes[1]);
1279 let checksum = u16::from_be_bytes([bytes[2], bytes[3]]);
1280 let reserved = u32::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]);
1281 let target_addr = Ipv6Addr::new(
1282 u16::from_be_bytes([bytes[8], bytes[9]]),
1283 u16::from_be_bytes([bytes[10], bytes[11]]),
1284 u16::from_be_bytes([bytes[12], bytes[13]]),
1285 u16::from_be_bytes([bytes[14], bytes[15]]),
1286 u16::from_be_bytes([bytes[16], bytes[17]]),
1287 u16::from_be_bytes([bytes[18], bytes[19]]),
1288 u16::from_be_bytes([bytes[20], bytes[21]]),
1289 u16::from_be_bytes([bytes[22], bytes[23]]),
1290 );
1291
1292 let mut options = Vec::new();
1293 let mut i = 24;
1294 while i + 2 <= bytes.len() {
1295 let option_type = NdpOptionType::new(bytes[i]);
1296 let length = bytes[i + 1];
1297 let option_len = (length as usize) * 8;
1298
1299 if option_len < 2 || i + option_len > bytes.len() {
1300 break;
1301 }
1302
1303 let payload = Bytes::copy_from_slice(&bytes[i + 2..i + option_len]);
1304 options.push(NdpOptionPacket {
1305 option_type,
1306 length,
1307 payload,
1308 });
1309
1310 i += option_len;
1311 }
1312
1313 let payload = Bytes::copy_from_slice(&bytes[i..]);
1314
1315 Some(NeighborSolicitPacket {
1316 header: Icmpv6Header {
1317 icmpv6_type,
1318 icmpv6_code,
1319 checksum,
1320 },
1321 reserved,
1322 target_addr,
1323 options,
1324 payload,
1325 })
1326 }
1327 fn from_bytes(bytes: Bytes) -> Option<Self> {
1328 Self::from_buf(&bytes)
1329 }
1330
1331 fn to_bytes(&self) -> Bytes {
1332 let mut bytes = Vec::with_capacity(NDP_SOL_PACKET_LEN);
1333 bytes.push(self.header.icmpv6_type.value());
1334 bytes.push(self.header.icmpv6_code.value());
1335 bytes.extend_from_slice(&self.header.checksum.to_be_bytes());
1336 bytes.extend_from_slice(&self.reserved.to_be_bytes());
1337 for (_, segment) in self.target_addr.segments().iter().enumerate() {
1338 bytes.extend_from_slice(&segment.to_be_bytes());
1339 }
1340 for option in &self.options {
1341 bytes.push(option.option_type.value());
1342 bytes.push(option.length);
1343 bytes.extend_from_slice(&option.payload);
1344 }
1345 Bytes::from(bytes)
1346 }
1347 fn header(&self) -> Bytes {
1348 self.to_bytes().slice(..ICMPV6_HEADER_LEN + 24) }
1350 fn payload(&self) -> Bytes {
1351 self.payload.clone()
1352 }
1353 fn header_len(&self) -> usize {
1354 ICMPV6_HEADER_LEN + 24 }
1356
1357 fn payload_len(&self) -> usize {
1358 self.payload.len()
1359 }
1360
1361 fn total_len(&self) -> usize {
1362 self.header_len() + self.payload_len()
1363 }
1364
1365 fn into_parts(self) -> (Self::Header, Bytes) {
1366 ((), self.payload)
1367 }
1368 }
1369
1370 impl NeighborSolicitPacket {
1371 pub fn options_length(&self) -> usize {
1373 if self.to_bytes().len() > 24 {
1375 self.to_bytes().len() - 24
1376 } else {
1377 0
1378 }
1379 }
1380 }
1381
1382 #[allow(non_snake_case)]
1384 #[allow(non_upper_case_globals)]
1385 pub mod NeighborAdvertFlags {
1386 pub const Router: u8 = 0b10000000;
1388 pub const Solicited: u8 = 0b01000000;
1391 pub const Override: u8 = 0b00100000;
1394 }
1395
1396 #[derive(Clone, Debug, PartialEq, Eq)]
1418 pub struct NeighborAdvertPacket {
1419 pub header: Icmpv6Header,
1420 pub flags: u8,
1421 pub reserved: u24be,
1422 pub target_addr: Ipv6Addr,
1423 pub options: Vec<NdpOptionPacket>,
1424 pub payload: Bytes,
1425 }
1426
1427 impl TryFrom<Icmpv6Packet> for NeighborAdvertPacket {
1428 type Error = &'static str;
1429
1430 fn try_from(value: Icmpv6Packet) -> Result<Self, Self::Error> {
1431 if value.header.icmpv6_type != Icmpv6Type::NeighborAdvertisement {
1432 return Err("Not a Neighbor Advert packet");
1433 }
1434 if value.payload.len() < 20 {
1439 return Err("Payload too short for Neighbor Advert");
1440 }
1441 let flags = value.payload[0];
1442 let reserved = bitfield::utils::u24be_from_bytes([
1443 value.payload[1],
1444 value.payload[2],
1445 value.payload[3],
1446 ]);
1447 let target_addr = Ipv6Addr::new(
1448 u16::from_be_bytes([value.payload[4], value.payload[5]]),
1449 u16::from_be_bytes([value.payload[6], value.payload[7]]),
1450 u16::from_be_bytes([value.payload[8], value.payload[9]]),
1451 u16::from_be_bytes([value.payload[10], value.payload[11]]),
1452 u16::from_be_bytes([value.payload[12], value.payload[13]]),
1453 u16::from_be_bytes([value.payload[14], value.payload[15]]),
1454 u16::from_be_bytes([value.payload[16], value.payload[17]]),
1455 u16::from_be_bytes([value.payload[18], value.payload[19]]),
1456 );
1457 let options = value
1458 .payload
1459 .slice(20..)
1460 .chunks(8)
1461 .map(|chunk| {
1462 let option_type = NdpOptionType::new(chunk[0]);
1463 let length = chunk[1];
1464 let payload = Bytes::from(chunk[2..].to_vec());
1465 NdpOptionPacket {
1466 option_type,
1467 length,
1468 payload,
1469 }
1470 })
1471 .collect();
1472 Ok(NeighborAdvertPacket {
1473 header: value.header,
1474 flags,
1475 reserved,
1476 target_addr,
1477 options,
1478 payload: Bytes::new(),
1479 })
1480 }
1481 }
1482
1483 impl Packet for NeighborAdvertPacket {
1484 type Header = ();
1485 fn from_buf(bytes: &[u8]) -> Option<Self> {
1486 if bytes.len() < 24 {
1487 return None;
1488 }
1489
1490 let icmpv6_type = Icmpv6Type::new(bytes[0]);
1491 let icmpv6_code = Icmpv6Code::new(bytes[1]);
1492 let checksum = u16::from_be_bytes([bytes[2], bytes[3]]);
1493 let header = Icmpv6Header {
1494 icmpv6_type,
1495 icmpv6_code,
1496 checksum,
1497 };
1498
1499 let flags = bytes[4];
1500 let reserved = bitfield::utils::u24be_from_bytes([bytes[5], bytes[6], bytes[7]]);
1501
1502 let target_addr = Ipv6Addr::new(
1503 u16::from_be_bytes([bytes[8], bytes[9]]),
1504 u16::from_be_bytes([bytes[10], bytes[11]]),
1505 u16::from_be_bytes([bytes[12], bytes[13]]),
1506 u16::from_be_bytes([bytes[14], bytes[15]]),
1507 u16::from_be_bytes([bytes[16], bytes[17]]),
1508 u16::from_be_bytes([bytes[18], bytes[19]]),
1509 u16::from_be_bytes([bytes[20], bytes[21]]),
1510 u16::from_be_bytes([bytes[22], bytes[23]]),
1511 );
1512
1513 let mut options = Vec::new();
1514 let mut i = 24;
1515 while i + 2 <= bytes.len() {
1516 let option_type = NdpOptionType::new(bytes[i]);
1517 let length = bytes[i + 1];
1518 let option_len = (length as usize) * 8;
1519
1520 if option_len < 2 || i + option_len > bytes.len() {
1521 break;
1522 }
1523
1524 let payload = Bytes::copy_from_slice(&bytes[i + 2..i + option_len]);
1525 options.push(NdpOptionPacket {
1526 option_type,
1527 length,
1528 payload,
1529 });
1530
1531 i += option_len;
1532 }
1533
1534 let payload = Bytes::copy_from_slice(&bytes[i..]);
1535
1536 Some(NeighborAdvertPacket {
1537 header,
1538 flags,
1539 reserved,
1540 target_addr,
1541 options,
1542 payload,
1543 })
1544 }
1545 fn from_bytes(bytes: Bytes) -> Option<Self> {
1546 Self::from_buf(&bytes)
1547 }
1548
1549 fn to_bytes(&self) -> Bytes {
1550 let mut bytes = Vec::with_capacity(NDP_ADV_PACKET_LEN);
1551 bytes.push(self.header.icmpv6_type.value());
1552 bytes.push(self.header.icmpv6_code.value());
1553 bytes.extend_from_slice(&self.header.checksum.to_be_bytes());
1554
1555 let flags_reserved = (self.flags as u32) << 24 | (self.reserved & 0x00FF_FFFF);
1557 bytes.extend_from_slice(&flags_reserved.to_be_bytes());
1558
1559 for segment in self.target_addr.segments().iter() {
1560 bytes.extend_from_slice(&segment.to_be_bytes());
1561 }
1562
1563 for option in &self.options {
1564 bytes.push(option.option_type.value());
1565 bytes.push(option.length);
1566 bytes.extend_from_slice(&option.payload);
1567 }
1568
1569 Bytes::from(bytes)
1570 }
1571 fn header(&self) -> Bytes {
1572 self.to_bytes().slice(..ICMPV6_HEADER_LEN + 24) }
1574 fn payload(&self) -> Bytes {
1575 self.payload.clone()
1576 }
1577 fn header_len(&self) -> usize {
1578 ICMPV6_HEADER_LEN + 24 }
1580 fn payload_len(&self) -> usize {
1581 self.payload.len()
1582 }
1583
1584 fn total_len(&self) -> usize {
1585 self.header_len() + self.payload_len()
1586 }
1587
1588 fn into_parts(self) -> (Self::Header, Bytes) {
1589 ((), self.payload)
1590 }
1591 }
1592
1593 impl NeighborAdvertPacket {
1594 pub fn options_length(&self) -> usize {
1596 if self.to_bytes().len() > 24 {
1598 self.to_bytes().len() - 24
1599 } else {
1600 0
1601 }
1602 }
1603 }
1604
1605 #[derive(Clone, Debug, PartialEq, Eq)]
1635 pub struct RedirectPacket {
1636 pub header: Icmpv6Header,
1637 pub reserved: u32be,
1638 pub target_addr: Ipv6Addr,
1639 pub dest_addr: Ipv6Addr,
1640 pub options: Vec<NdpOptionPacket>,
1641 pub payload: Bytes,
1642 }
1643
1644 impl TryFrom<Icmpv6Packet> for RedirectPacket {
1645 type Error = &'static str;
1646
1647 fn try_from(value: Icmpv6Packet) -> Result<Self, Self::Error> {
1648 if value.header.icmpv6_type != Icmpv6Type::RedirectMessage {
1649 return Err("Not a Redirect packet");
1650 }
1651 if value.payload.len() < 40 {
1652 return Err("Payload too short for Redirect");
1653 }
1654 let reserved = u32be::from_be_bytes([
1655 value.payload[0],
1656 value.payload[1],
1657 value.payload[2],
1658 value.payload[3],
1659 ]);
1660 let target_addr = Ipv6Addr::new(
1661 u16::from_be_bytes([value.payload[4], value.payload[5]]),
1662 u16::from_be_bytes([value.payload[6], value.payload[7]]),
1663 u16::from_be_bytes([value.payload[8], value.payload[9]]),
1664 u16::from_be_bytes([value.payload[10], value.payload[11]]),
1665 u16::from_be_bytes([value.payload[12], value.payload[13]]),
1666 u16::from_be_bytes([value.payload[14], value.payload[15]]),
1667 u16::from_be_bytes([value.payload[16], value.payload[17]]),
1668 u16::from_be_bytes([value.payload[18], value.payload[19]]),
1669 );
1670 let dest_addr = Ipv6Addr::new(
1671 u16::from_be_bytes([value.payload[20], value.payload[21]]),
1672 u16::from_be_bytes([value.payload[22], value.payload[23]]),
1673 u16::from_be_bytes([value.payload[24], value.payload[25]]),
1674 u16::from_be_bytes([value.payload[26], value.payload[27]]),
1675 u16::from_be_bytes([value.payload[28], value.payload[29]]),
1676 u16::from_be_bytes([value.payload[30], value.payload[31]]),
1677 u16::from_be_bytes([value.payload[32], value.payload[33]]),
1678 u16::from_be_bytes([value.payload[34], value.payload[35]]),
1679 );
1680 let options = value
1681 .payload
1682 .slice(36..)
1683 .chunks(8)
1684 .map(|chunk| {
1685 let option_type = NdpOptionType::new(chunk[0]);
1686 let length = chunk[1];
1687 let payload = Bytes::from(chunk[2..].to_vec());
1688 NdpOptionPacket {
1689 option_type,
1690 length,
1691 payload,
1692 }
1693 })
1694 .collect();
1695 Ok(RedirectPacket {
1696 header: value.header,
1697 reserved,
1698 target_addr,
1699 dest_addr,
1700 options,
1701 payload: Bytes::new(),
1702 })
1703 }
1704 }
1705
1706 impl Packet for RedirectPacket {
1707 type Header = ();
1708 fn from_buf(bytes: &[u8]) -> Option<Self> {
1709 if bytes.len() < 40 {
1710 return None;
1711 }
1712
1713 let icmpv6_type = Icmpv6Type::new(bytes[0]);
1714 let icmpv6_code = Icmpv6Code::new(bytes[1]);
1715 let checksum = u16::from_be_bytes([bytes[2], bytes[3]]);
1716 let header = Icmpv6Header {
1717 icmpv6_type,
1718 icmpv6_code,
1719 checksum,
1720 };
1721
1722 let reserved = u32be::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]);
1723
1724 let target_addr = Ipv6Addr::new(
1725 u16::from_be_bytes([bytes[8], bytes[9]]),
1726 u16::from_be_bytes([bytes[10], bytes[11]]),
1727 u16::from_be_bytes([bytes[12], bytes[13]]),
1728 u16::from_be_bytes([bytes[14], bytes[15]]),
1729 u16::from_be_bytes([bytes[16], bytes[17]]),
1730 u16::from_be_bytes([bytes[18], bytes[19]]),
1731 u16::from_be_bytes([bytes[20], bytes[21]]),
1732 u16::from_be_bytes([bytes[22], bytes[23]]),
1733 );
1734
1735 let dest_addr = Ipv6Addr::new(
1736 u16::from_be_bytes([bytes[24], bytes[25]]),
1737 u16::from_be_bytes([bytes[26], bytes[27]]),
1738 u16::from_be_bytes([bytes[28], bytes[29]]),
1739 u16::from_be_bytes([bytes[30], bytes[31]]),
1740 u16::from_be_bytes([bytes[32], bytes[33]]),
1741 u16::from_be_bytes([bytes[34], bytes[35]]),
1742 u16::from_be_bytes([bytes[36], bytes[37]]),
1743 u16::from_be_bytes([bytes[38], bytes[39]]),
1744 );
1745
1746 let mut options = Vec::new();
1747 let mut i = 40;
1748 while i + 2 <= bytes.len() {
1749 let option_type = NdpOptionType::new(bytes[i]);
1750 let length = bytes[i + 1];
1751 let option_len = (length as usize) * 8;
1752
1753 if option_len < 2 || i + option_len > bytes.len() {
1754 break;
1755 }
1756
1757 let payload = Bytes::copy_from_slice(&bytes[i + 2..i + option_len]);
1758 options.push(NdpOptionPacket {
1759 option_type,
1760 length,
1761 payload,
1762 });
1763
1764 i += option_len;
1765 }
1766
1767 let payload = Bytes::copy_from_slice(&bytes[i..]);
1768
1769 Some(RedirectPacket {
1770 header,
1771 reserved,
1772 target_addr,
1773 dest_addr,
1774 options,
1775 payload,
1776 })
1777 }
1778 fn from_bytes(bytes: Bytes) -> Option<Self> {
1779 Self::from_buf(&bytes)
1780 }
1781 fn to_bytes(&self) -> Bytes {
1782 let mut bytes = Vec::with_capacity(NDP_REDIRECT_PACKET_LEN);
1783 bytes.push(self.header.icmpv6_type.value());
1784 bytes.push(self.header.icmpv6_code.value());
1785 bytes.extend_from_slice(&self.header.checksum.to_be_bytes());
1786 bytes.extend_from_slice(&self.reserved.to_be_bytes());
1787 for (_, segment) in self.target_addr.segments().iter().enumerate() {
1788 bytes.extend_from_slice(&segment.to_be_bytes());
1789 }
1790 for (_, segment) in self.dest_addr.segments().iter().enumerate() {
1791 bytes.extend_from_slice(&segment.to_be_bytes());
1792 }
1793 for option in &self.options {
1794 bytes.push(option.option_type.value());
1795 bytes.push(option.length);
1796 bytes.extend_from_slice(&option.payload);
1797 }
1798 Bytes::from(bytes)
1799 }
1800 fn header(&self) -> Bytes {
1801 self.to_bytes().slice(..ICMPV6_HEADER_LEN + 40) }
1803 fn payload(&self) -> Bytes {
1804 self.payload.clone()
1805 }
1806 fn header_len(&self) -> usize {
1807 ICMPV6_HEADER_LEN + 40 }
1809
1810 fn payload_len(&self) -> usize {
1811 self.payload.len()
1812 }
1813
1814 fn total_len(&self) -> usize {
1815 self.header_len() + self.payload_len()
1816 }
1817
1818 fn into_parts(self) -> (Self::Header, Bytes) {
1819 ((), self.payload)
1820 }
1821 }
1822
1823 impl RedirectPacket {
1824 pub fn options_length(&self) -> usize {
1826 if self.to_bytes().len() > 40 {
1828 self.to_bytes().len() - 40
1829 } else {
1830 0
1831 }
1832 }
1833 }
1834
1835 #[cfg(test)]
1836 mod ndp_tests {
1837 use super::*;
1838 use crate::icmpv6::{Icmpv6Code, Icmpv6Type};
1839
1840 #[test]
1841 fn basic_option_parsing() {
1842 let data = Bytes::from_static(&[
1843 0x02, 0x01, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
1844 0x00, 0x00, 0x00,
1846 ]);
1847 let pkg = NdpOptionPacket::from_bytes(data).unwrap();
1848 assert_eq!(pkg.option_type, NdpOptionTypes::TargetLLAddr);
1849 assert_eq!(pkg.length, 0x01);
1850 assert_eq!(pkg.payload.len(), 6);
1851 assert_eq!(pkg.payload.as_ref(), &[0x06, 0x05, 0x04, 0x03, 0x02, 0x01]);
1852 }
1853
1854 #[test]
1855 fn basic_rs_parse() {
1856 let data = Bytes::from_static(&[
1857 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
1862 0x00, 0x00,
1863 ]);
1864
1865 let pkg = RouterSolicitPacket::from_bytes(data).unwrap();
1866 assert_eq!(pkg.header.icmpv6_type, Icmpv6Type::RouterSolicitation);
1867 assert_eq!(pkg.header.icmpv6_code, Icmpv6Code(0));
1868 assert_eq!(pkg.header.checksum, 0);
1869 assert_eq!(pkg.reserved, 0);
1870 assert_eq!(pkg.options.len(), 2);
1871
1872 let option = &pkg.options[0];
1873 assert_eq!(option.option_type, NdpOptionTypes::TargetLLAddr);
1874 assert_eq!(option.length, 0x01);
1875 assert_eq!(
1876 option.payload.as_ref(),
1877 &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1878 );
1879 assert_eq!(option.payload.len(), 6);
1880
1881 let option = &pkg.options[1];
1882 assert_eq!(option.option_type, NdpOptionTypes::SourceLLAddr);
1883 assert_eq!(option.length, 1);
1884 assert_eq!(
1885 option.payload.as_ref(),
1886 &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1887 );
1888 }
1889
1890 #[test]
1891 fn basic_rs_create() {
1892 use crate::icmpv6::ndp::{NdpOptionPacket, RouterSolicitPacket};
1893
1894 let options = vec![NdpOptionPacket {
1895 option_type: NdpOptionTypes::SourceLLAddr,
1896 length: 1,
1897 payload: Bytes::from_static(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
1898 }];
1899
1900 let packet = RouterSolicitPacket {
1901 header: Icmpv6Header {
1902 icmpv6_type: Icmpv6Type::RouterSolicitation,
1903 icmpv6_code: Icmpv6Code(0),
1904 checksum: 0,
1905 },
1906 reserved: 0,
1907 options,
1908 payload: Bytes::new(),
1909 };
1910
1911 let bytes = packet.to_bytes();
1912
1913 let expected = Bytes::from_static(&[
1914 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
1919
1920 assert_eq!(bytes, expected);
1921 }
1922
1923 #[test]
1924 fn basic_ra_parse() {
1925 let data = Bytes::from_static(&[
1926 0x86, 0x00, 0x00, 0x00, 0xff, 0x80, 0x09, 0x00, 0x12, 0x34, 0x56, 0x78, 0x87, 0x65, 0x43, 0x21, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0x57, 0x68, 0x61, 0x74, ]);
1937 let pkg = RouterAdvertPacket::from_bytes(data).unwrap();
1938 assert_eq!(pkg.header.icmpv6_type, Icmpv6Type::RouterAdvertisement);
1939 assert_eq!(pkg.header.icmpv6_code, Icmpv6Code(0));
1940 assert_eq!(pkg.header.checksum, 0x00);
1941 assert_eq!(pkg.hop_limit, 0xff);
1942 assert_eq!(pkg.flags, RouterAdvertFlags::ManagedAddressConf);
1943 assert_eq!(pkg.lifetime, 0x900);
1944 assert_eq!(pkg.reachable_time, 0x12345678);
1945 assert_eq!(pkg.retrans_time, 0x87654321);
1946 assert_eq!(pkg.options.len(), 2);
1947
1948 let option = &pkg.options[0];
1949 assert_eq!(option.option_type, NdpOptionTypes::SourceLLAddr);
1950 assert_eq!(option.length, 1);
1951 assert_eq!(
1952 option.payload.as_ref(),
1953 &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1954 );
1955
1956 let option = &pkg.options[1];
1957 assert_eq!(option.option_type, NdpOptionTypes::MTU);
1958 assert_eq!(option.length, 1);
1959 assert_eq!(
1960 option.payload.as_ref(),
1961 &[0x00, 0x00, 0x57, 0x68, 0x61, 0x74]
1962 );
1963 }
1964
1965 #[test]
1966 fn basic_ra_create() {
1967 use crate::icmpv6::ndp::{NdpOptionPacket, RouterAdvertFlags, RouterAdvertPacket};
1968
1969 let options = vec![NdpOptionPacket {
1970 option_type: NdpOptionTypes::MTU,
1971 length: 1,
1972 payload: Bytes::from_static(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
1973 }];
1974
1975 let packet = RouterAdvertPacket {
1976 header: Icmpv6Header {
1977 icmpv6_type: Icmpv6Type::RouterAdvertisement,
1978 icmpv6_code: Icmpv6Code(0),
1979 checksum: 0,
1980 },
1981 hop_limit: 0xff,
1982 flags: RouterAdvertFlags::ManagedAddressConf,
1983 lifetime: 0,
1984 reachable_time: 0,
1985 retrans_time: 0,
1986 options,
1987 payload: Bytes::new(),
1988 };
1989
1990 let bytes = packet.to_bytes();
1991 let expected = Bytes::from_static(&[
1992 0x86, 0x00, 0x00, 0x00, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
1999
2000 assert_eq!(bytes, expected);
2001 }
2002
2003 #[test]
2004 fn basic_ns_parse() {
2005 let data = Bytes::from_static(&[
2006 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00,
2007 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
2008 ]);
2009 let pkg = NeighborSolicitPacket::from_bytes(data).unwrap();
2010 assert_eq!(pkg.header.icmpv6_type, Icmpv6Type::NeighborSolicitation);
2011 assert_eq!(pkg.header.icmpv6_code, Icmpv6Code(0));
2012 assert_eq!(pkg.header.checksum, 0x00);
2013 assert_eq!(pkg.reserved, 0x00);
2014 assert_eq!(pkg.target_addr, Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1));
2015 }
2016
2017 #[test]
2018 fn basic_ns_create() {
2019 use crate::icmpv6::ndp::NeighborSolicitPacket;
2020
2021 let packet = NeighborSolicitPacket {
2022 header: Icmpv6Header {
2023 icmpv6_type: Icmpv6Type::NeighborSolicitation,
2024 icmpv6_code: Icmpv6Code(0),
2025 checksum: 0,
2026 },
2027 reserved: 0,
2028 target_addr: Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1),
2029 options: vec![],
2030 payload: Bytes::new(),
2031 };
2032
2033 let bytes = packet.to_bytes();
2034
2035 let expected = Bytes::from_static(&[
2036 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2039 0x00, 0x01, ]);
2041
2042 assert_eq!(bytes, expected);
2043 }
2044
2045 #[test]
2046 fn basic_na_parse() {
2047 let data = Bytes::from_static(&[
2048 0x88, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00,
2049 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
2050 ]);
2051 let pkg = NeighborAdvertPacket::from_bytes(data).unwrap();
2052 assert_eq!(pkg.header.icmpv6_type, Icmpv6Type::NeighborAdvertisement);
2053 assert_eq!(pkg.header.icmpv6_code, Icmpv6Code(0));
2054 assert_eq!(pkg.header.checksum, 0x00);
2055 assert_eq!(pkg.reserved, 0x00);
2056 assert_eq!(pkg.flags, 0x80);
2057 assert_eq!(pkg.target_addr, Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1));
2058 }
2059
2060 #[test]
2061 fn basic_na_create() {
2062 use crate::icmpv6::ndp::{NeighborAdvertFlags, NeighborAdvertPacket};
2063
2064 let packet = NeighborAdvertPacket {
2065 header: Icmpv6Header {
2066 icmpv6_type: Icmpv6Type::NeighborAdvertisement,
2067 icmpv6_code: Icmpv6Code(0),
2068 checksum: 0,
2069 },
2070 flags: NeighborAdvertFlags::Router,
2071 reserved: 0,
2072 target_addr: Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1),
2073 options: vec![],
2074 payload: Bytes::new(),
2075 };
2076
2077 let bytes = packet.to_bytes();
2078
2079 let expected = Bytes::from_static(&[
2080 0x88, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2083 0x00, 0x01,
2084 ]);
2085
2086 assert_eq!(bytes, expected);
2087 }
2088
2089 #[test]
2090 fn basic_redirect_parse() {
2091 let data = Bytes::from_static(&[
2092 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00,
2093 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
2094 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2095 ]);
2096 let pkg = RedirectPacket::from_bytes(data).unwrap();
2097 assert_eq!(pkg.header.icmpv6_type, Icmpv6Type::RedirectMessage);
2098 assert_eq!(pkg.header.icmpv6_code, Icmpv6Code(0));
2099 assert_eq!(pkg.header.checksum, 0x00);
2100 assert_eq!(pkg.reserved, 0x00);
2101 assert_eq!(pkg.target_addr, Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1));
2102 assert_eq!(pkg.dest_addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
2103 }
2104
2105 #[test]
2106 fn basic_redirect_create() {
2107 use crate::icmpv6::ndp::RedirectPacket;
2108
2109 let packet = RedirectPacket {
2110 header: Icmpv6Header {
2111 icmpv6_type: Icmpv6Type::RedirectMessage,
2112 icmpv6_code: Icmpv6Code(0),
2113 checksum: 0,
2114 },
2115 reserved: 0,
2116 target_addr: Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1),
2117 dest_addr: Ipv6Addr::UNSPECIFIED,
2118 options: vec![],
2119 payload: Bytes::new(),
2120 };
2121
2122 let bytes = packet.to_bytes();
2123
2124 let expected = Bytes::from_static(&[
2125 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2128 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2130 0x00, 0x00, ]);
2132
2133 assert_eq!(bytes, expected);
2134 }
2135 }
2136}
2137
2138pub mod echo_request {
2139 use bytes::Bytes;
2152
2153 use crate::{
2154 icmpv6::{Icmpv6Code, Icmpv6Header, Icmpv6Packet, Icmpv6Type},
2155 packet::Packet,
2156 };
2157
2158 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
2160 pub struct Identifier(pub u16);
2161
2162 impl Identifier {
2163 pub fn new(val: u16) -> Identifier {
2165 Identifier(val)
2166 }
2167 pub fn value(&self) -> u16 {
2169 self.0
2170 }
2171 }
2172
2173 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
2175 pub struct SequenceNumber(pub u16);
2176
2177 impl SequenceNumber {
2178 pub fn new(val: u16) -> SequenceNumber {
2180 SequenceNumber(val)
2181 }
2182 pub fn value(&self) -> u16 {
2184 self.0
2185 }
2186 }
2187
2188 #[allow(non_snake_case)]
2191 #[allow(non_upper_case_globals)]
2192 pub mod Icmpv6Codes {
2193 use crate::icmpv6::Icmpv6Code;
2194 pub const NoCode: Icmpv6Code = Icmpv6Code(0);
2196 }
2197
2198 #[derive(Clone, Debug, PartialEq, Eq)]
2200 pub struct EchoRequestPacket {
2201 pub header: Icmpv6Header,
2202 pub identifier: u16,
2203 pub sequence_number: u16,
2204 pub payload: Bytes,
2205 }
2206
2207 impl TryFrom<Icmpv6Packet> for EchoRequestPacket {
2208 type Error = &'static str;
2209
2210 fn try_from(value: Icmpv6Packet) -> Result<Self, Self::Error> {
2211 if value.header.icmpv6_type != Icmpv6Type::EchoRequest {
2212 return Err("Not an Echo Request packet");
2213 }
2214 if value.payload.len() < 8 {
2215 return Err("Payload too short for Echo Request");
2216 }
2217 let identifier = u16::from_be_bytes([value.payload[0], value.payload[1]]);
2218 let sequence_number = u16::from_be_bytes([value.payload[2], value.payload[3]]);
2219 Ok(EchoRequestPacket {
2220 header: value.header,
2221 identifier,
2222 sequence_number,
2223 payload: value.payload.slice(4..),
2224 })
2225 }
2226 }
2227
2228 impl Packet for EchoRequestPacket {
2229 type Header = ();
2230 fn from_buf(bytes: &[u8]) -> Option<Self> {
2231 if bytes.len() < 8 {
2232 return None;
2233 }
2234 let icmpv6_type = Icmpv6Type::new(bytes[0]);
2235 let icmpv6_code = Icmpv6Code::new(bytes[1]);
2236 let checksum = u16::from_be_bytes([bytes[2], bytes[3]]);
2237 let identifier = u16::from_be_bytes([bytes[4], bytes[5]]);
2238 let sequence_number = u16::from_be_bytes([bytes[6], bytes[7]]);
2239 Some(EchoRequestPacket {
2240 header: Icmpv6Header {
2241 icmpv6_type,
2242 icmpv6_code,
2243 checksum,
2244 },
2245 identifier,
2246 sequence_number,
2247 payload: Bytes::copy_from_slice(&bytes[8..]),
2248 })
2249 }
2250 fn from_bytes(bytes: Bytes) -> Option<Self> {
2251 Self::from_buf(&bytes)
2252 }
2253
2254 fn to_bytes(&self) -> Bytes {
2255 let mut bytes = Vec::with_capacity(8 + self.payload.len());
2256 bytes.push(self.header.icmpv6_type.value());
2257 bytes.push(self.header.icmpv6_code.value());
2258 bytes.extend_from_slice(&self.header.checksum.to_be_bytes());
2259 bytes.extend_from_slice(&self.identifier.to_be_bytes());
2260 bytes.extend_from_slice(&self.sequence_number.to_be_bytes());
2261 bytes.extend_from_slice(&self.payload);
2262 Bytes::from(bytes)
2263 }
2264
2265 fn header(&self) -> Bytes {
2266 self.to_bytes().slice(..8)
2267 }
2268
2269 fn payload(&self) -> Bytes {
2270 self.payload.clone()
2271 }
2272
2273 fn header_len(&self) -> usize {
2274 8 }
2276
2277 fn payload_len(&self) -> usize {
2278 self.payload.len()
2279 }
2280
2281 fn total_len(&self) -> usize {
2282 self.header_len() + self.payload_len()
2283 }
2284
2285 fn into_parts(self) -> (Self::Header, Bytes) {
2286 ((), self.payload)
2287 }
2288 }
2289}
2290
2291pub mod echo_reply {
2292 use bytes::Bytes;
2305
2306 use crate::{
2307 icmpv6::{Icmpv6Code, Icmpv6Header, Icmpv6Packet, Icmpv6Type},
2308 packet::Packet,
2309 };
2310 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
2312 pub struct Identifier(pub u16);
2313
2314 impl Identifier {
2315 pub fn new(val: u16) -> Identifier {
2317 Identifier(val)
2318 }
2319 pub fn value(&self) -> u16 {
2321 self.0
2322 }
2323 }
2324
2325 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
2327 pub struct SequenceNumber(pub u16);
2328
2329 impl SequenceNumber {
2330 pub fn new(val: u16) -> SequenceNumber {
2332 SequenceNumber(val)
2333 }
2334 pub fn value(&self) -> u16 {
2336 self.0
2337 }
2338 }
2339
2340 #[allow(non_snake_case)]
2343 #[allow(non_upper_case_globals)]
2344 pub mod Icmpv6Codes {
2345 use crate::icmpv6::Icmpv6Code;
2346 pub const NoCode: Icmpv6Code = Icmpv6Code(0);
2348 }
2349
2350 #[derive(Clone, Debug, PartialEq, Eq)]
2352 pub struct EchoReplyPacket {
2353 pub header: Icmpv6Header,
2354 pub identifier: u16,
2355 pub sequence_number: u16,
2356 pub payload: Bytes,
2357 }
2358 impl TryFrom<Icmpv6Packet> for EchoReplyPacket {
2359 type Error = &'static str;
2360
2361 fn try_from(value: Icmpv6Packet) -> Result<Self, Self::Error> {
2362 if value.header.icmpv6_type != Icmpv6Type::EchoReply {
2363 return Err("Not an Echo Reply packet");
2364 }
2365 if value.payload.len() < 8 {
2366 return Err("Payload too short for Echo Reply");
2367 }
2368 let identifier = u16::from_be_bytes([value.payload[0], value.payload[1]]);
2369 let sequence_number = u16::from_be_bytes([value.payload[2], value.payload[3]]);
2370 Ok(EchoReplyPacket {
2371 header: value.header,
2372 identifier,
2373 sequence_number,
2374 payload: value.payload.slice(4..),
2375 })
2376 }
2377 }
2378 impl Packet for EchoReplyPacket {
2379 type Header = ();
2380 fn from_buf(bytes: &[u8]) -> Option<Self> {
2381 if bytes.len() < 8 {
2382 return None;
2383 }
2384 let icmpv6_type = Icmpv6Type::new(bytes[0]);
2385 let icmpv6_code = Icmpv6Code::new(bytes[1]);
2386 let checksum = u16::from_be_bytes([bytes[2], bytes[3]]);
2387 let identifier = u16::from_be_bytes([bytes[4], bytes[5]]);
2388 let sequence_number = u16::from_be_bytes([bytes[6], bytes[7]]);
2389 Some(EchoReplyPacket {
2390 header: Icmpv6Header {
2391 icmpv6_type,
2392 icmpv6_code,
2393 checksum,
2394 },
2395 identifier,
2396 sequence_number,
2397 payload: Bytes::copy_from_slice(&bytes[8..]),
2398 })
2399 }
2400 fn from_bytes(bytes: Bytes) -> Option<Self> {
2401 Self::from_buf(&bytes)
2402 }
2403
2404 fn to_bytes(&self) -> Bytes {
2405 let mut bytes = Vec::with_capacity(8 + self.payload.len());
2406 bytes.push(self.header.icmpv6_type.value());
2407 bytes.push(self.header.icmpv6_code.value());
2408 bytes.extend_from_slice(&self.header.checksum.to_be_bytes());
2409 bytes.extend_from_slice(&self.identifier.to_be_bytes());
2410 bytes.extend_from_slice(&self.sequence_number.to_be_bytes());
2411 bytes.extend_from_slice(&self.payload);
2412 Bytes::from(bytes)
2413 }
2414
2415 fn header(&self) -> Bytes {
2416 self.to_bytes().slice(..8)
2417 }
2418
2419 fn payload(&self) -> Bytes {
2420 self.payload.clone()
2421 }
2422
2423 fn header_len(&self) -> usize {
2424 8 }
2426
2427 fn payload_len(&self) -> usize {
2428 self.payload.len()
2429 }
2430
2431 fn total_len(&self) -> usize {
2432 self.header_len() + self.payload_len()
2433 }
2434
2435 fn into_parts(self) -> (Self::Header, Bytes) {
2436 ((), self.payload)
2437 }
2438 }
2439}
2440
2441#[cfg(test)]
2442mod echo_tests {
2443 use super::*;
2444 use crate::icmpv6::{
2445 Icmpv6Code, Icmpv6Type, echo_reply::EchoReplyPacket, echo_request::EchoRequestPacket,
2446 };
2447
2448 #[test]
2449 fn test_echo_request_parse() {
2450 let raw = Bytes::from_static(&[
2451 0x80, 0x00, 0xbe, 0xef, 0x12, 0x34, 0x56, 0x78, b'p', b'i', b'n', b'g', b'!',
2455 ]);
2456
2457 let parsed = EchoRequestPacket::from_bytes(raw.clone())
2458 .expect("Failed to parse Echo Request packet");
2459
2460 assert_eq!(parsed.header.icmpv6_type, Icmpv6Type::EchoRequest);
2461 assert_eq!(parsed.header.icmpv6_code, Icmpv6Code(0));
2462 assert_eq!(parsed.header.checksum, 0xbeef);
2463 assert_eq!(parsed.identifier, 0x1234);
2464 assert_eq!(parsed.sequence_number, 0x5678);
2465 assert_eq!(parsed.payload, Bytes::from_static(b"ping!"));
2466 }
2467
2468 #[test]
2469 fn test_echo_request_create() {
2470 let payload = Bytes::from_static(b"hello");
2471 let packet = EchoRequestPacket {
2472 header: Icmpv6Header {
2473 icmpv6_type: Icmpv6Type::EchoRequest,
2474 icmpv6_code: Icmpv6Code(0),
2475 checksum: 0,
2476 },
2477 identifier: 0x1234,
2478 sequence_number: 0x5678,
2479 payload: payload.clone(),
2480 };
2481 let bytes = packet.to_bytes();
2482 let parsed = EchoRequestPacket::from_bytes(bytes).unwrap();
2483
2484 assert_eq!(parsed.identifier, 0x1234);
2485 assert_eq!(parsed.sequence_number, 0x5678);
2486 assert_eq!(parsed.payload, payload);
2487 }
2488
2489 #[test]
2490 fn test_echo_reply_parse() {
2491 let raw = Bytes::from_static(&[
2492 0x81, 0x00, 0x12, 0x34, 0xab, 0xcd, 0x56, 0x78, b'h', b'e', b'l', b'l', b'o',
2496 ]);
2497
2498 let parsed =
2499 EchoReplyPacket::from_bytes(raw.clone()).expect("Failed to parse Echo Reply packet");
2500
2501 assert_eq!(parsed.header.icmpv6_type, Icmpv6Type::EchoReply);
2502 assert_eq!(parsed.header.icmpv6_code, Icmpv6Code(0));
2503 assert_eq!(parsed.header.checksum, 0x1234);
2504 assert_eq!(parsed.identifier, 0xabcd);
2505 assert_eq!(parsed.sequence_number, 0x5678);
2506 assert_eq!(parsed.payload, Bytes::from_static(b"hello"));
2507 }
2508
2509 #[test]
2510 fn test_echo_reply_create() {
2511 let payload = Bytes::from_static(b"world");
2512 let packet = EchoReplyPacket {
2513 header: Icmpv6Header {
2514 icmpv6_type: Icmpv6Type::EchoReply,
2515 icmpv6_code: Icmpv6Code(0),
2516 checksum: 0,
2517 },
2518 identifier: 0xabcd,
2519 sequence_number: 0x1234,
2520 payload: payload.clone(),
2521 };
2522
2523 let bytes = packet.to_bytes();
2524 let parsed = EchoReplyPacket::from_bytes(bytes).expect("Failed to parse Echo Reply packet");
2525
2526 assert_eq!(parsed.header.icmpv6_type, Icmpv6Type::EchoReply);
2527 assert_eq!(parsed.identifier, 0xabcd);
2528 assert_eq!(parsed.sequence_number, 0x1234);
2529 assert_eq!(parsed.payload, payload);
2530 }
2531}