1use crate::ipv6::IPV6_HEADER_LEN;
4use crate::{ethernet::ETHERNET_HEADER_LEN, packet::Packet};
5use std::net::Ipv6Addr;
6
7use bytes::Bytes;
8#[cfg(feature = "serde")]
9use serde::{Deserialize, Serialize};
10
11pub const ICMPV6_COMMON_HEADER_LEN: usize = 4;
13pub const ICMPV6_HEADER_LEN: usize = 8;
15pub const ICMPV6_PACKET_LEN: usize = ETHERNET_HEADER_LEN + IPV6_HEADER_LEN + ICMPV6_HEADER_LEN;
17pub const ICMPV6_IP_PACKET_LEN: usize = IPV6_HEADER_LEN + ICMPV6_HEADER_LEN;
19
20#[repr(u8)]
23#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
24#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
25pub enum Icmpv6Type {
26 DestinationUnreachable,
27 PacketTooBig,
28 TimeExceeded,
29 ParameterProblem,
30 EchoRequest,
31 EchoReply,
32 MulticastListenerQuery,
33 MulticastListenerReport,
34 MulticastListenerDone,
35 RouterSolicitation,
36 RouterAdvertisement,
37 NeighborSolicitation,
38 NeighborAdvertisement,
39 RedirectMessage,
40 RouterRenumbering,
41 NodeInformationQuery,
42 NodeInformationResponse,
43 InverseNeighborDiscoverySolicitation,
44 InverseNeighborDiscoveryAdvertisement,
45 Version2MulticastListenerReport,
46 HomeAgentAddressDiscoveryRequest,
47 HomeAgentAddressDiscoveryReply,
48 MobilePrefixSolicitation,
49 MobilePrefixAdvertisement,
50 CertificationPathSolicitationMessage,
51 CertificationPathAdvertisementMessage,
52 ExperimentalMobilityProtocols,
53 MulticastRouterAdvertisement,
54 MulticastRouterSolicitation,
55 MulticastRouterTermination,
56 FMIPv6Messages,
57 RPLControlMessage,
58 ILNPv6LocatorUpdateMessage,
59 DuplicateAddressRequest,
60 DuplicateAddressConfirmation,
61 MPLControlMessage,
62 ExtendedEchoRequest,
63 ExtendedEchoReply,
64 Unknown(u8),
65}
66
67impl Icmpv6Type {
68 pub fn new(value: u8) -> Self {
69 match value {
70 1 => Icmpv6Type::DestinationUnreachable,
71 2 => Icmpv6Type::PacketTooBig,
72 3 => Icmpv6Type::TimeExceeded,
73 4 => Icmpv6Type::ParameterProblem,
74 128 => Icmpv6Type::EchoRequest,
75 129 => Icmpv6Type::EchoReply,
76 130 => Icmpv6Type::MulticastListenerQuery,
77 131 => Icmpv6Type::MulticastListenerReport,
78 132 => Icmpv6Type::MulticastListenerDone,
79 133 => Icmpv6Type::RouterSolicitation,
80 134 => Icmpv6Type::RouterAdvertisement,
81 135 => Icmpv6Type::NeighborSolicitation,
82 136 => Icmpv6Type::NeighborAdvertisement,
83 137 => Icmpv6Type::RedirectMessage,
84 138 => Icmpv6Type::RouterRenumbering,
85 139 => Icmpv6Type::NodeInformationQuery,
86 140 => Icmpv6Type::NodeInformationResponse,
87 141 => Icmpv6Type::InverseNeighborDiscoverySolicitation,
88 142 => Icmpv6Type::InverseNeighborDiscoveryAdvertisement,
89 143 => Icmpv6Type::Version2MulticastListenerReport,
90 144 => Icmpv6Type::HomeAgentAddressDiscoveryRequest,
91 145 => Icmpv6Type::HomeAgentAddressDiscoveryReply,
92 146 => Icmpv6Type::MobilePrefixSolicitation,
93 147 => Icmpv6Type::MobilePrefixAdvertisement,
94 148 => Icmpv6Type::CertificationPathSolicitationMessage,
95 149 => Icmpv6Type::CertificationPathAdvertisementMessage,
96 150 => Icmpv6Type::ExperimentalMobilityProtocols,
97 151 => Icmpv6Type::MulticastRouterAdvertisement,
98 152 => Icmpv6Type::MulticastRouterSolicitation,
99 153 => Icmpv6Type::MulticastRouterTermination,
100 154 => Icmpv6Type::FMIPv6Messages,
101 155 => Icmpv6Type::RPLControlMessage,
102 156 => Icmpv6Type::ILNPv6LocatorUpdateMessage,
103 157 => Icmpv6Type::DuplicateAddressRequest,
104 158 => Icmpv6Type::DuplicateAddressConfirmation,
105 159 => Icmpv6Type::MPLControlMessage,
106 160 => Icmpv6Type::ExtendedEchoRequest,
107 161 => Icmpv6Type::ExtendedEchoReply,
108 n => Icmpv6Type::Unknown(n),
109 }
110 }
111 pub fn name(&self) -> &'static str {
112 match self {
113 Icmpv6Type::DestinationUnreachable => "Destination Unreachable",
114 Icmpv6Type::PacketTooBig => "Packet Too Big",
115 Icmpv6Type::TimeExceeded => "Time Exceeded",
116 Icmpv6Type::ParameterProblem => "Parameter Problem",
117 Icmpv6Type::EchoRequest => "Echo Request",
118 Icmpv6Type::EchoReply => "Echo Reply",
119 Icmpv6Type::MulticastListenerQuery => "Multicast Listener Query",
120 Icmpv6Type::MulticastListenerReport => "Multicast Listener Report",
121 Icmpv6Type::MulticastListenerDone => "Multicast Listener Done",
122 Icmpv6Type::RouterSolicitation => "Router Solicitation",
123 Icmpv6Type::RouterAdvertisement => "Router Advertisement",
124 Icmpv6Type::NeighborSolicitation => "Neighbor Solicitation",
125 Icmpv6Type::NeighborAdvertisement => "Neighbor Advertisement",
126 Icmpv6Type::RedirectMessage => "Redirect Message",
127 Icmpv6Type::RouterRenumbering => "Router Renumbering",
128 Icmpv6Type::NodeInformationQuery => "Node Information Query",
129 Icmpv6Type::NodeInformationResponse => "Node Information Response",
130 Icmpv6Type::InverseNeighborDiscoverySolicitation => {
131 "Inverse Neighbor Discovery Solicitation"
132 }
133 Icmpv6Type::InverseNeighborDiscoveryAdvertisement => {
134 "Inverse Neighbor Discovery Advertisement"
135 }
136 Icmpv6Type::Version2MulticastListenerReport => "Version 2 Multicast Listener Report",
137 Icmpv6Type::HomeAgentAddressDiscoveryRequest => "Home Agent Address Discovery Request",
138 Icmpv6Type::HomeAgentAddressDiscoveryReply => "Home Agent Address Discovery Reply",
139 Icmpv6Type::MobilePrefixSolicitation => "Mobile Prefix Solicitation",
140 Icmpv6Type::MobilePrefixAdvertisement => "Mobile Prefix Advertisement",
141 Icmpv6Type::CertificationPathSolicitationMessage => {
142 "Certification Path Solicitation Message"
143 }
144 Icmpv6Type::CertificationPathAdvertisementMessage => {
145 "Certification Path Advertisement Message"
146 }
147 Icmpv6Type::ExperimentalMobilityProtocols => "Experimental Mobility Protocols",
148 Icmpv6Type::MulticastRouterAdvertisement => "Multicast Router Advertisement",
149 Icmpv6Type::MulticastRouterSolicitation => "Multicast Router Solicitation",
150 Icmpv6Type::MulticastRouterTermination => "Multicast Router Termination",
151 Icmpv6Type::FMIPv6Messages => "FMIPv6 Messages",
152 Icmpv6Type::RPLControlMessage => "RPL Control Message",
153 Icmpv6Type::ILNPv6LocatorUpdateMessage => "ILNPv6 Locator Update Message",
154 Icmpv6Type::DuplicateAddressRequest => "Duplicate Address Request",
155 Icmpv6Type::DuplicateAddressConfirmation => "Duplicate Address Confirmation",
156 Icmpv6Type::MPLControlMessage => "MPL Control Message",
157 Icmpv6Type::ExtendedEchoRequest => "Extended Echo Request",
158 Icmpv6Type::ExtendedEchoReply => "Extended Echo Reply",
159 Icmpv6Type::Unknown(_) => "Unknown",
160 }
161 }
162 pub fn value(&self) -> u8 {
163 match self {
164 Icmpv6Type::DestinationUnreachable => 1,
165 Icmpv6Type::PacketTooBig => 2,
166 Icmpv6Type::TimeExceeded => 3,
167 Icmpv6Type::ParameterProblem => 4,
168 Icmpv6Type::EchoRequest => 128,
169 Icmpv6Type::EchoReply => 129,
170 Icmpv6Type::MulticastListenerQuery => 130,
171 Icmpv6Type::MulticastListenerReport => 131,
172 Icmpv6Type::MulticastListenerDone => 132,
173 Icmpv6Type::RouterSolicitation => 133,
174 Icmpv6Type::RouterAdvertisement => 134,
175 Icmpv6Type::NeighborSolicitation => 135,
176 Icmpv6Type::NeighborAdvertisement => 136,
177 Icmpv6Type::RedirectMessage => 137,
178 Icmpv6Type::RouterRenumbering => 138,
179 Icmpv6Type::NodeInformationQuery => 139,
180 Icmpv6Type::NodeInformationResponse => 140,
181 Icmpv6Type::InverseNeighborDiscoverySolicitation => 141,
182 Icmpv6Type::InverseNeighborDiscoveryAdvertisement => 142,
183 Icmpv6Type::Version2MulticastListenerReport => 143,
184 Icmpv6Type::HomeAgentAddressDiscoveryRequest => 144,
185 Icmpv6Type::HomeAgentAddressDiscoveryReply => 145,
186 Icmpv6Type::MobilePrefixSolicitation => 146,
187 Icmpv6Type::MobilePrefixAdvertisement => 147,
188 Icmpv6Type::CertificationPathSolicitationMessage => 148,
189 Icmpv6Type::CertificationPathAdvertisementMessage => 149,
190 Icmpv6Type::ExperimentalMobilityProtocols => 150,
191 Icmpv6Type::MulticastRouterAdvertisement => 151,
192 Icmpv6Type::MulticastRouterSolicitation => 152,
193 Icmpv6Type::MulticastRouterTermination => 153,
194 Icmpv6Type::FMIPv6Messages => 154,
195 Icmpv6Type::RPLControlMessage => 155,
196 Icmpv6Type::ILNPv6LocatorUpdateMessage => 156,
197 Icmpv6Type::DuplicateAddressRequest => 157,
198 Icmpv6Type::DuplicateAddressConfirmation => 158,
199 Icmpv6Type::MPLControlMessage => 159,
200 Icmpv6Type::ExtendedEchoRequest => 160,
201 Icmpv6Type::ExtendedEchoReply => 161,
202 Icmpv6Type::Unknown(n) => *n,
203 }
204 }
205}
206
207#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
209#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
210pub struct Icmpv6Code(pub u8);
211
212impl Icmpv6Code {
213 pub fn new(val: u8) -> Icmpv6Code {
215 Icmpv6Code(val)
216 }
217 pub fn value(&self) -> u8 {
219 self.0
220 }
221}
222
223#[derive(Clone, Debug, PartialEq, Eq)]
225#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
226pub struct Icmpv6Header {
227 pub icmpv6_type: Icmpv6Type,
228 pub icmpv6_code: Icmpv6Code,
229 pub checksum: u16,
230}
231
232#[derive(Clone, Debug, PartialEq, Eq)]
234pub struct Icmpv6Packet {
235 pub header: Icmpv6Header,
236 pub payload: Bytes,
237}
238
239impl Packet for Icmpv6Packet {
240 type Header = Icmpv6Header;
241
242 fn from_buf(bytes: &[u8]) -> Option<Self> {
243 if bytes.len() < ICMPV6_HEADER_LEN {
244 return None;
245 }
246 let icmpv6_type = Icmpv6Type::new(bytes[0]);
247 let icmpv6_code = Icmpv6Code::new(bytes[1]);
248 let checksum = u16::from_be_bytes([bytes[2], bytes[3]]);
249 let header = Icmpv6Header {
250 icmpv6_type,
251 icmpv6_code,
252 checksum,
253 };
254 let payload = Bytes::copy_from_slice(&bytes[ICMPV6_COMMON_HEADER_LEN..]);
255 Some(Icmpv6Packet { header, payload })
256 }
257 fn from_bytes(bytes: Bytes) -> Option<Self> {
258 Self::from_buf(&bytes)
259 }
260 fn to_bytes(&self) -> Bytes {
261 let mut bytes = Vec::with_capacity(ICMPV6_COMMON_HEADER_LEN + self.payload.len());
262 bytes.push(self.header.icmpv6_type.value());
263 bytes.push(self.header.icmpv6_code.value());
264 bytes.extend_from_slice(&self.header.checksum.to_be_bytes());
265 bytes.extend_from_slice(&self.payload);
266 Bytes::from(bytes)
267 }
268 fn header(&self) -> Bytes {
269 self.to_bytes().slice(..self.header_len())
270 }
271
272 fn payload(&self) -> Bytes {
273 self.payload.clone()
274 }
275
276 fn header_len(&self) -> usize {
277 ICMPV6_COMMON_HEADER_LEN
278 }
279
280 fn payload_len(&self) -> usize {
281 self.payload.len()
282 }
283
284 fn total_len(&self) -> usize {
285 self.header_len() + self.payload_len()
286 }
287
288 fn into_parts(self) -> (Self::Header, Bytes) {
289 (self.header, self.payload)
290 }
291}
292
293pub fn checksum(packet: &Icmpv6Packet, source: &Ipv6Addr, destination: &Ipv6Addr) -> u16 {
295 use crate::util;
296 util::ipv6_checksum(
297 &packet.to_bytes(),
298 1, &[],
300 source,
301 destination,
302 crate::ip::IpNextProtocol::Icmpv6,
303 )
304}
305
306#[cfg(test)]
307mod checksum_tests {
308 use super::*;
309
310 #[test]
311 fn checksum_echo_request() {
312 let lo = &Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
314 let data = Bytes::from_static(&[
315 0x80, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x20, 0x20, 0x75, 0x73, 0x74, 0x20, 0x61, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20,
322 0x77, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x20, 0x74, 0x69, 0x73, 0x20, 0x62, 0x75, 0x74,
323 0x20, 0x61, 0x20, 0x73, 0x63, 0x72, 0x61, 0x74, 0x63, 0x68, 0x20, 0x20, 0x6b, 0x6e,
324 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x6e, 0x69, 0x20, 0x20, 0x20,
325 ]);
326 let mut pkg = Icmpv6Packet::from_bytes(data.clone()).unwrap();
327 assert_eq!(pkg.header.icmpv6_type, Icmpv6Type::EchoRequest);
328 assert_eq!(pkg.header.icmpv6_code, Icmpv6Code::new(0));
329 assert_eq!(pkg.header.checksum, 0xffff);
330 assert_eq!(pkg.to_bytes(), data);
331 assert_eq!(checksum(&pkg, lo, lo), 0x1d2e);
332
333 pkg.header.icmpv6_type = Icmpv6Type::new(0x81);
335 assert_eq!(checksum(&pkg, lo, lo), 0x1c2e);
336 }
337}
338
339pub mod ndp {
340 use bytes::Bytes;
345 use nex_core::bitfield::{self, u24be, u32be};
346
347 use crate::icmpv6::{Icmpv6Code, Icmpv6Header, Icmpv6Packet, Icmpv6Type, ICMPV6_HEADER_LEN};
348 use crate::packet::Packet;
349 use std::net::Ipv6Addr;
350
351 pub const NDP_SOL_PACKET_LEN: usize = 24;
353 pub const NDP_ADV_PACKET_LEN: usize = 24;
355 pub const NDP_REDIRECT_PACKET_LEN: usize = 40;
357 pub const NDP_OPT_PACKET_LEN: usize = 2;
359
360 #[allow(non_snake_case)]
361 #[allow(non_upper_case_globals)]
362 pub mod Icmpv6Codes {
363 use crate::icmpv6::Icmpv6Code;
364 pub const NoCode: Icmpv6Code = Icmpv6Code(0);
366 }
367
368 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
370 pub struct NdpOptionType(pub u8);
371
372 impl NdpOptionType {
373 pub fn new(value: u8) -> NdpOptionType {
375 NdpOptionType(value)
376 }
377 pub fn value(&self) -> u8 {
379 self.0
380 }
381 }
382
383 #[allow(non_snake_case)]
387 #[allow(non_upper_case_globals)]
388 pub mod NdpOptionTypes {
389 use super::NdpOptionType;
390
391 pub const SourceLLAddr: NdpOptionType = NdpOptionType(1);
401
402 pub const TargetLLAddr: NdpOptionType = NdpOptionType(2);
412
413 pub const PrefixInformation: NdpOptionType = NdpOptionType(3);
437
438 pub const RedirectedHeader: NdpOptionType = NdpOptionType(4);
454
455 pub const MTU: NdpOptionType = NdpOptionType(5);
467 }
468
469 #[derive(Clone, Debug, PartialEq, Eq)]
481 pub struct NdpOptionPacket {
482 pub option_type: NdpOptionType,
483 pub length: u8,
484 pub payload: Bytes,
485 }
486
487 impl Packet for NdpOptionPacket {
488 type Header = ();
489 fn from_buf(bytes: &[u8]) -> Option<Self> {
490 if bytes.len() < 2 {
491 return None;
492 }
493
494 let option_type = NdpOptionType::new(bytes[0]);
495 let length = bytes[1]; let total_len = (length as usize) * 8;
498 if bytes.len() < total_len {
499 return None;
500 }
501
502 let data_len = total_len - 2;
503 let payload = Bytes::copy_from_slice(&bytes[2..2 + data_len]);
504
505 Some(Self {
506 option_type,
507 length,
508 payload,
509 })
510 }
511 fn from_bytes(bytes: Bytes) -> Option<Self> {
512 Self::from_buf(&bytes)
513 }
514
515 fn to_bytes(&self) -> Bytes {
516 let mut bytes = Vec::with_capacity(NDP_OPT_PACKET_LEN + self.payload.len());
517 bytes.push(self.option_type.value());
518 bytes.push(self.length);
519 bytes.extend_from_slice(&self.payload);
520 Bytes::from(bytes)
521 }
522
523 fn header(&self) -> Bytes {
524 self.to_bytes().slice(..NDP_OPT_PACKET_LEN)
525 }
526
527 fn payload(&self) -> Bytes {
528 self.payload.clone()
529 }
530
531 fn header_len(&self) -> usize {
532 NDP_OPT_PACKET_LEN
533 }
534
535 fn payload_len(&self) -> usize {
536 self.payload.len()
537 }
538
539 fn total_len(&self) -> usize {
540 self.header_len() + self.payload_len()
541 }
542
543 fn into_parts(self) -> (Self::Header, Bytes) {
544 ((), self.payload)
545 }
546 }
547
548 impl NdpOptionPacket {
549 pub fn option_payload_length(&self) -> usize {
551 let len = self.payload.len();
553 if len > 0 {
554 ((len * 8) - 2) as usize
555 } else {
556 0
557 }
558 }
559 }
560
561 #[derive(Clone, Debug, PartialEq, Eq)]
576 pub struct RouterSolicitPacket {
577 pub header: Icmpv6Header,
578 pub reserved: u32,
579 pub options: Vec<NdpOptionPacket>,
580 pub payload: Bytes,
581 }
582
583 impl TryFrom<Icmpv6Packet> for RouterSolicitPacket {
584 type Error = &'static str;
585
586 fn try_from(value: Icmpv6Packet) -> Result<Self, Self::Error> {
587 if value.header.icmpv6_type != Icmpv6Type::RouterSolicitation {
588 return Err("Not a Router Solicitation packet");
589 }
590 if value.payload.len() < 8 {
591 return Err("Payload too short for Router Solicitation");
592 }
593 let reserved = u32::from_be_bytes([
594 value.payload[0],
595 value.payload[1],
596 value.payload[2],
597 value.payload[3],
598 ]);
599 let options = value
600 .payload
601 .slice(4..)
602 .chunks(8)
603 .map(|chunk| {
604 let option_type = NdpOptionType::new(chunk[0]);
605 let length = chunk[1];
606 let payload = Bytes::from(chunk[2..].to_vec());
607 NdpOptionPacket {
608 option_type,
609 length,
610 payload,
611 }
612 })
613 .collect();
614 Ok(RouterSolicitPacket {
615 header: value.header,
616 reserved,
617 options,
618 payload: Bytes::new(),
619 })
620 }
621 }
622
623 impl Packet for RouterSolicitPacket {
624 type Header = ();
625 fn from_buf(bytes: &[u8]) -> Option<Self> {
626 if bytes.len() < NDP_SOL_PACKET_LEN {
627 return None;
628 }
629
630 let icmpv6_type = Icmpv6Type::new(bytes[0]);
631 let icmpv6_code = Icmpv6Code::new(bytes[1]);
632 let checksum = u16::from_be_bytes([bytes[2], bytes[3]]);
633 let header = Icmpv6Header {
634 icmpv6_type,
635 icmpv6_code,
636 checksum,
637 };
638 let reserved = u32::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]);
639
640 let mut options = Vec::new();
641 let mut i = 8;
642 while i + 2 <= bytes.len() {
643 let option_type = NdpOptionType::new(bytes[i]);
644 let length = bytes[i + 1];
645 let option_len = (length as usize) * 8;
646
647 if i + option_len > bytes.len() {
648 break;
649 }
650
651 let payload = Bytes::copy_from_slice(&bytes[i + 2..i + option_len]);
652 options.push(NdpOptionPacket {
653 option_type,
654 length,
655 payload,
656 });
657 i += option_len;
658 }
659
660 let payload = Bytes::copy_from_slice(&bytes[i..]);
661
662 Some(RouterSolicitPacket {
663 header,
664 reserved,
665 options,
666 payload,
667 })
668 }
669 fn from_bytes(bytes: Bytes) -> Option<Self> {
670 Self::from_buf(&bytes)
671 }
672
673 fn to_bytes(&self) -> Bytes {
674 let mut bytes = Vec::with_capacity(NDP_SOL_PACKET_LEN);
675 bytes.push(self.header.icmpv6_type.value());
676 bytes.push(self.header.icmpv6_code.value());
677 bytes.extend_from_slice(&self.header.checksum.to_be_bytes());
678 bytes.extend_from_slice(&self.reserved.to_be_bytes());
679 for option in &self.options {
680 bytes.push(option.option_type.value());
681 bytes.push(option.length);
682 bytes.extend_from_slice(&option.payload);
683 }
684 Bytes::from(bytes)
685 }
686
687 fn header(&self) -> Bytes {
688 self.to_bytes().slice(..ICMPV6_HEADER_LEN)
689 }
690
691 fn payload(&self) -> Bytes {
692 self.payload.clone()
693 }
694
695 fn header_len(&self) -> usize {
696 ICMPV6_HEADER_LEN + 4 }
698
699 fn payload_len(&self) -> usize {
700 self.payload.len()
701 }
702
703 fn total_len(&self) -> usize {
704 self.header_len() + self.payload_len()
705 }
706 fn into_parts(self) -> (Self::Header, Bytes) {
707 ((), self.payload)
708 }
709 }
710
711 impl RouterSolicitPacket {
712 pub fn options_length(&self) -> usize {
714 if self.to_bytes().len() > 8 {
715 self.to_bytes().len() - 8
716 } else {
717 0
718 }
719 }
720 }
721
722 #[allow(non_snake_case)]
724 #[allow(non_upper_case_globals)]
725 pub mod RouterAdvertFlags {
726 pub const ManagedAddressConf: u8 = 0b10000000;
729 pub const OtherConf: u8 = 0b01000000;
732 }
733
734 #[derive(Clone, Debug, PartialEq, Eq)]
752 pub struct RouterAdvertPacket {
753 pub header: Icmpv6Header,
754 pub hop_limit: u8,
755 pub flags: u8,
756 pub lifetime: u16,
757 pub reachable_time: u32,
758 pub retrans_time: u32,
759 pub options: Vec<NdpOptionPacket>,
760 pub payload: Bytes,
761 }
762
763 impl TryFrom<Icmpv6Packet> for RouterAdvertPacket {
764 type Error = &'static str;
765
766 fn try_from(value: Icmpv6Packet) -> Result<Self, Self::Error> {
767 if value.header.icmpv6_type != Icmpv6Type::RouterAdvertisement {
768 return Err("Not a Router Advertisement packet");
769 }
770 if value.payload.len() < 16 {
771 return Err("Payload too short for Router Advertisement");
772 }
773 let hop_limit = value.payload[0];
774 let flags = value.payload[1];
775 let lifetime = u16::from_be_bytes([value.payload[2], value.payload[3]]);
776 let reachable_time = u32::from_be_bytes([
777 value.payload[4],
778 value.payload[5],
779 value.payload[6],
780 value.payload[7],
781 ]);
782 let retrans_time = u32::from_be_bytes([
783 value.payload[8],
784 value.payload[9],
785 value.payload[10],
786 value.payload[11],
787 ]);
788 let options = value
789 .payload
790 .slice(12..)
791 .chunks(8)
792 .map(|chunk| {
793 let option_type = NdpOptionType::new(chunk[0]);
794 let length = chunk[1];
795 let payload = Bytes::from(chunk[2..].to_vec());
796 NdpOptionPacket {
797 option_type,
798 length,
799 payload,
800 }
801 })
802 .collect();
803 Ok(RouterAdvertPacket {
804 header: value.header,
805 hop_limit,
806 flags,
807 lifetime,
808 reachable_time,
809 retrans_time,
810 options,
811 payload: Bytes::new(),
812 })
813 }
814 }
815 impl Packet for RouterAdvertPacket {
816 type Header = ();
817 fn from_buf(bytes: &[u8]) -> Option<Self> {
818 if bytes.len() < NDP_ADV_PACKET_LEN {
819 return None;
820 }
821
822 let icmpv6_type = Icmpv6Type::new(bytes[0]);
823 let icmpv6_code = Icmpv6Code::new(bytes[1]);
824 let checksum = u16::from_be_bytes([bytes[2], bytes[3]]);
825 let header = Icmpv6Header {
826 icmpv6_type,
827 icmpv6_code,
828 checksum,
829 };
830
831 let hop_limit = bytes[4];
832 let flags = bytes[5];
833 let lifetime = u16::from_be_bytes([bytes[6], bytes[7]]);
834 let reachable_time = u32::from_be_bytes([bytes[8], bytes[9], bytes[10], bytes[11]]);
835 let retrans_time = u32::from_be_bytes([bytes[12], bytes[13], bytes[14], bytes[15]]);
836
837 let mut options = Vec::new();
838 let mut i = 16;
839 while i + 2 <= bytes.len() {
840 let option_type = NdpOptionType::new(bytes[i]);
841 let length = bytes[i + 1];
842 let option_len = (length as usize) * 8;
843
844 if i + option_len > bytes.len() {
845 break;
846 }
847
848 let payload = Bytes::copy_from_slice(&bytes[i + 2..i + option_len]);
849 options.push(NdpOptionPacket {
850 option_type,
851 length,
852 payload,
853 });
854 i += option_len;
855 }
856
857 let payload = Bytes::copy_from_slice(&bytes[i..]);
858
859 Some(RouterAdvertPacket {
860 header,
861 hop_limit,
862 flags,
863 lifetime,
864 reachable_time,
865 retrans_time,
866 options,
867 payload,
868 })
869 }
870
871 fn from_bytes(bytes: Bytes) -> Option<Self> {
872 Self::from_buf(&bytes)
873 }
874
875 fn to_bytes(&self) -> Bytes {
876 let mut bytes = Vec::with_capacity(NDP_ADV_PACKET_LEN);
877 bytes.push(self.header.icmpv6_type.value());
878 bytes.push(self.header.icmpv6_code.value());
879 bytes.extend_from_slice(&self.header.checksum.to_be_bytes());
880 bytes.push(self.hop_limit);
881 bytes.push(self.flags);
882 bytes.extend_from_slice(&self.lifetime.to_be_bytes());
883 bytes.extend_from_slice(&self.reachable_time.to_be_bytes());
884 bytes.extend_from_slice(&self.retrans_time.to_be_bytes());
885 for option in &self.options {
886 bytes.push(option.option_type.value());
887 bytes.push(option.length);
888 bytes.extend_from_slice(&option.payload);
889 }
890 Bytes::from(bytes)
891 }
892
893 fn header(&self) -> Bytes {
894 self.to_bytes().slice(..ICMPV6_HEADER_LEN + 16) }
896 fn payload(&self) -> Bytes {
897 self.payload.clone()
898 }
899 fn header_len(&self) -> usize {
900 ICMPV6_HEADER_LEN + 16 }
902
903 fn payload_len(&self) -> usize {
904 self.payload.len()
905 }
906
907 fn total_len(&self) -> usize {
908 self.header_len() + self.payload_len()
909 }
910 fn into_parts(self) -> (Self::Header, Bytes) {
911 ((), self.payload)
912 }
913 }
914
915 impl RouterAdvertPacket {
916 pub fn options_length(&self) -> usize {
918 if self.to_bytes().len() > 16 {
919 self.to_bytes().len() - 16
920 } else {
921 0
922 }
923 }
924 }
925
926 #[derive(Clone, Debug, PartialEq, Eq)]
948 pub struct NeighborSolicitPacket {
949 pub header: Icmpv6Header,
950 pub reserved: u32,
951 pub target_addr: Ipv6Addr,
952 pub options: Vec<NdpOptionPacket>,
953 pub payload: Bytes,
954 }
955
956 impl TryFrom<Icmpv6Packet> for NeighborSolicitPacket {
957 type Error = &'static str;
958
959 fn try_from(value: Icmpv6Packet) -> Result<Self, Self::Error> {
960 if value.header.icmpv6_type != Icmpv6Type::NeighborSolicitation {
961 return Err("Not a Neighbor Solicitation packet");
962 }
963 if value.payload.len() < 24 {
964 return Err("Payload too short for Neighbor Solicitation");
965 }
966 let reserved = u32::from_be_bytes([
967 value.payload[0],
968 value.payload[1],
969 value.payload[2],
970 value.payload[3],
971 ]);
972 let target_addr = Ipv6Addr::new(
973 u16::from_be_bytes([value.payload[4], value.payload[5]]),
974 u16::from_be_bytes([value.payload[6], value.payload[7]]),
975 u16::from_be_bytes([value.payload[8], value.payload[9]]),
976 u16::from_be_bytes([value.payload[10], value.payload[11]]),
977 u16::from_be_bytes([value.payload[12], value.payload[13]]),
978 u16::from_be_bytes([value.payload[14], value.payload[15]]),
979 u16::from_be_bytes([value.payload[16], value.payload[17]]),
980 u16::from_be_bytes([value.payload[18], value.payload[19]]),
981 );
982 let options = value
983 .payload
984 .slice(20..)
985 .chunks(8)
986 .map(|chunk| {
987 let option_type = NdpOptionType::new(chunk[0]);
988 let length = chunk[1];
989 let payload: Bytes = Bytes::from(chunk[2..].to_vec());
990 NdpOptionPacket {
991 option_type,
992 length,
993 payload,
994 }
995 })
996 .collect();
997 Ok(NeighborSolicitPacket {
998 header: value.header,
999 reserved,
1000 target_addr,
1001 options,
1002 payload: Bytes::new(),
1003 })
1004 }
1005 }
1006
1007 impl Packet for NeighborSolicitPacket {
1008 type Header = ();
1009 fn from_buf(bytes: &[u8]) -> Option<Self> {
1010 if bytes.len() < 24 {
1011 return None;
1012 }
1013
1014 let icmpv6_type = Icmpv6Type::new(bytes[0]);
1015 let icmpv6_code = Icmpv6Code::new(bytes[1]);
1016 let checksum = u16::from_be_bytes([bytes[2], bytes[3]]);
1017 let reserved = u32::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]);
1018 let target_addr = Ipv6Addr::new(
1019 u16::from_be_bytes([bytes[8], bytes[9]]),
1020 u16::from_be_bytes([bytes[10], bytes[11]]),
1021 u16::from_be_bytes([bytes[12], bytes[13]]),
1022 u16::from_be_bytes([bytes[14], bytes[15]]),
1023 u16::from_be_bytes([bytes[16], bytes[17]]),
1024 u16::from_be_bytes([bytes[18], bytes[19]]),
1025 u16::from_be_bytes([bytes[20], bytes[21]]),
1026 u16::from_be_bytes([bytes[22], bytes[23]]),
1027 );
1028
1029 let mut options = Vec::new();
1030 let mut i = 24;
1031 while i + 2 <= bytes.len() {
1032 let option_type = NdpOptionType::new(bytes[i]);
1033 let length = bytes[i + 1];
1034 let option_len = (length as usize) * 8;
1035
1036 if option_len < 2 || i + option_len > bytes.len() {
1037 break;
1038 }
1039
1040 let payload = Bytes::copy_from_slice(&bytes[i + 2..i + option_len]);
1041 options.push(NdpOptionPacket {
1042 option_type,
1043 length,
1044 payload,
1045 });
1046
1047 i += option_len;
1048 }
1049
1050 let payload = Bytes::copy_from_slice(&bytes[i..]);
1051
1052 Some(NeighborSolicitPacket {
1053 header: Icmpv6Header {
1054 icmpv6_type,
1055 icmpv6_code,
1056 checksum,
1057 },
1058 reserved,
1059 target_addr,
1060 options,
1061 payload,
1062 })
1063 }
1064 fn from_bytes(bytes: Bytes) -> Option<Self> {
1065 Self::from_buf(&bytes)
1066 }
1067
1068 fn to_bytes(&self) -> Bytes {
1069 let mut bytes = Vec::with_capacity(NDP_SOL_PACKET_LEN);
1070 bytes.push(self.header.icmpv6_type.value());
1071 bytes.push(self.header.icmpv6_code.value());
1072 bytes.extend_from_slice(&self.header.checksum.to_be_bytes());
1073 bytes.extend_from_slice(&self.reserved.to_be_bytes());
1074 for (_, segment) in self.target_addr.segments().iter().enumerate() {
1075 bytes.extend_from_slice(&segment.to_be_bytes());
1076 }
1077 for option in &self.options {
1078 bytes.push(option.option_type.value());
1079 bytes.push(option.length);
1080 bytes.extend_from_slice(&option.payload);
1081 }
1082 Bytes::from(bytes)
1083 }
1084 fn header(&self) -> Bytes {
1085 self.to_bytes().slice(..ICMPV6_HEADER_LEN + 24) }
1087 fn payload(&self) -> Bytes {
1088 self.payload.clone()
1089 }
1090 fn header_len(&self) -> usize {
1091 ICMPV6_HEADER_LEN + 24 }
1093
1094 fn payload_len(&self) -> usize {
1095 self.payload.len()
1096 }
1097
1098 fn total_len(&self) -> usize {
1099 self.header_len() + self.payload_len()
1100 }
1101
1102 fn into_parts(self) -> (Self::Header, Bytes) {
1103 ((), self.payload)
1104 }
1105 }
1106
1107 impl NeighborSolicitPacket {
1108 pub fn options_length(&self) -> usize {
1110 if self.to_bytes().len() > 24 {
1112 self.to_bytes().len() - 24
1113 } else {
1114 0
1115 }
1116 }
1117 }
1118
1119 #[allow(non_snake_case)]
1121 #[allow(non_upper_case_globals)]
1122 pub mod NeighborAdvertFlags {
1123 pub const Router: u8 = 0b10000000;
1125 pub const Solicited: u8 = 0b01000000;
1128 pub const Override: u8 = 0b00100000;
1131 }
1132
1133 #[derive(Clone, Debug, PartialEq, Eq)]
1155 pub struct NeighborAdvertPacket {
1156 pub header: Icmpv6Header,
1157 pub flags: u8,
1158 pub reserved: u24be,
1159 pub target_addr: Ipv6Addr,
1160 pub options: Vec<NdpOptionPacket>,
1161 pub payload: Bytes,
1162 }
1163
1164 impl TryFrom<Icmpv6Packet> for NeighborAdvertPacket {
1165 type Error = &'static str;
1166
1167 fn try_from(value: Icmpv6Packet) -> Result<Self, Self::Error> {
1168 if value.header.icmpv6_type != Icmpv6Type::NeighborAdvertisement {
1169 return Err("Not a Neighbor Advert packet");
1170 }
1171 if value.payload.len() < 20 {
1176 return Err("Payload too short for Neighbor Advert");
1177 }
1178 let flags = value.payload[0];
1179 let reserved = bitfield::utils::u24be_from_bytes([
1180 value.payload[1],
1181 value.payload[2],
1182 value.payload[3],
1183 ]);
1184 let target_addr = Ipv6Addr::new(
1185 u16::from_be_bytes([value.payload[4], value.payload[5]]),
1186 u16::from_be_bytes([value.payload[6], value.payload[7]]),
1187 u16::from_be_bytes([value.payload[8], value.payload[9]]),
1188 u16::from_be_bytes([value.payload[10], value.payload[11]]),
1189 u16::from_be_bytes([value.payload[12], value.payload[13]]),
1190 u16::from_be_bytes([value.payload[14], value.payload[15]]),
1191 u16::from_be_bytes([value.payload[16], value.payload[17]]),
1192 u16::from_be_bytes([value.payload[18], value.payload[19]]),
1193 );
1194 let options = value
1195 .payload
1196 .slice(20..)
1197 .chunks(8)
1198 .map(|chunk| {
1199 let option_type = NdpOptionType::new(chunk[0]);
1200 let length = chunk[1];
1201 let payload = Bytes::from(chunk[2..].to_vec());
1202 NdpOptionPacket {
1203 option_type,
1204 length,
1205 payload,
1206 }
1207 })
1208 .collect();
1209 Ok(NeighborAdvertPacket {
1210 header: value.header,
1211 flags,
1212 reserved,
1213 target_addr,
1214 options,
1215 payload: Bytes::new(),
1216 })
1217 }
1218 }
1219
1220 impl Packet for NeighborAdvertPacket {
1221 type Header = ();
1222 fn from_buf(bytes: &[u8]) -> Option<Self> {
1223 if bytes.len() < 24 {
1224 return None;
1225 }
1226
1227 let icmpv6_type = Icmpv6Type::new(bytes[0]);
1228 let icmpv6_code = Icmpv6Code::new(bytes[1]);
1229 let checksum = u16::from_be_bytes([bytes[2], bytes[3]]);
1230 let header = Icmpv6Header {
1231 icmpv6_type,
1232 icmpv6_code,
1233 checksum,
1234 };
1235
1236 let flags = bytes[4];
1237 let reserved = bitfield::utils::u24be_from_bytes([bytes[5], bytes[6], bytes[7]]);
1238
1239 let target_addr = Ipv6Addr::new(
1240 u16::from_be_bytes([bytes[8], bytes[9]]),
1241 u16::from_be_bytes([bytes[10], bytes[11]]),
1242 u16::from_be_bytes([bytes[12], bytes[13]]),
1243 u16::from_be_bytes([bytes[14], bytes[15]]),
1244 u16::from_be_bytes([bytes[16], bytes[17]]),
1245 u16::from_be_bytes([bytes[18], bytes[19]]),
1246 u16::from_be_bytes([bytes[20], bytes[21]]),
1247 u16::from_be_bytes([bytes[22], bytes[23]]),
1248 );
1249
1250 let mut options = Vec::new();
1251 let mut i = 24;
1252 while i + 2 <= bytes.len() {
1253 let option_type = NdpOptionType::new(bytes[i]);
1254 let length = bytes[i + 1];
1255 let option_len = (length as usize) * 8;
1256
1257 if option_len < 2 || i + option_len > bytes.len() {
1258 break;
1259 }
1260
1261 let payload = Bytes::copy_from_slice(&bytes[i + 2..i + option_len]);
1262 options.push(NdpOptionPacket {
1263 option_type,
1264 length,
1265 payload,
1266 });
1267
1268 i += option_len;
1269 }
1270
1271 let payload = Bytes::copy_from_slice(&bytes[i..]);
1272
1273 Some(NeighborAdvertPacket {
1274 header,
1275 flags,
1276 reserved,
1277 target_addr,
1278 options,
1279 payload,
1280 })
1281 }
1282 fn from_bytes(bytes: Bytes) -> Option<Self> {
1283 Self::from_buf(&bytes)
1284 }
1285
1286 fn to_bytes(&self) -> Bytes {
1287 let mut bytes = Vec::with_capacity(NDP_ADV_PACKET_LEN);
1288 bytes.push(self.header.icmpv6_type.value());
1289 bytes.push(self.header.icmpv6_code.value());
1290 bytes.extend_from_slice(&self.header.checksum.to_be_bytes());
1291
1292 let flags_reserved = (self.flags as u32) << 24 | (self.reserved & 0x00FF_FFFF);
1294 bytes.extend_from_slice(&flags_reserved.to_be_bytes());
1295
1296 for segment in self.target_addr.segments().iter() {
1297 bytes.extend_from_slice(&segment.to_be_bytes());
1298 }
1299
1300 for option in &self.options {
1301 bytes.push(option.option_type.value());
1302 bytes.push(option.length);
1303 bytes.extend_from_slice(&option.payload);
1304 }
1305
1306 Bytes::from(bytes)
1307 }
1308 fn header(&self) -> Bytes {
1309 self.to_bytes().slice(..ICMPV6_HEADER_LEN + 24) }
1311 fn payload(&self) -> Bytes {
1312 self.payload.clone()
1313 }
1314 fn header_len(&self) -> usize {
1315 ICMPV6_HEADER_LEN + 24 }
1317 fn payload_len(&self) -> usize {
1318 self.payload.len()
1319 }
1320
1321 fn total_len(&self) -> usize {
1322 self.header_len() + self.payload_len()
1323 }
1324
1325 fn into_parts(self) -> (Self::Header, Bytes) {
1326 ((), self.payload)
1327 }
1328 }
1329
1330 impl NeighborAdvertPacket {
1331 pub fn options_length(&self) -> usize {
1333 if self.to_bytes().len() > 24 {
1335 self.to_bytes().len() - 24
1336 } else {
1337 0
1338 }
1339 }
1340 }
1341
1342 #[derive(Clone, Debug, PartialEq, Eq)]
1372 pub struct RedirectPacket {
1373 pub header: Icmpv6Header,
1374 pub reserved: u32be,
1375 pub target_addr: Ipv6Addr,
1376 pub dest_addr: Ipv6Addr,
1377 pub options: Vec<NdpOptionPacket>,
1378 pub payload: Bytes,
1379 }
1380
1381 impl TryFrom<Icmpv6Packet> for RedirectPacket {
1382 type Error = &'static str;
1383
1384 fn try_from(value: Icmpv6Packet) -> Result<Self, Self::Error> {
1385 if value.header.icmpv6_type != Icmpv6Type::RedirectMessage {
1386 return Err("Not a Redirect packet");
1387 }
1388 if value.payload.len() < 40 {
1389 return Err("Payload too short for Redirect");
1390 }
1391 let reserved = u32be::from_be_bytes([
1392 value.payload[0],
1393 value.payload[1],
1394 value.payload[2],
1395 value.payload[3],
1396 ]);
1397 let target_addr = Ipv6Addr::new(
1398 u16::from_be_bytes([value.payload[4], value.payload[5]]),
1399 u16::from_be_bytes([value.payload[6], value.payload[7]]),
1400 u16::from_be_bytes([value.payload[8], value.payload[9]]),
1401 u16::from_be_bytes([value.payload[10], value.payload[11]]),
1402 u16::from_be_bytes([value.payload[12], value.payload[13]]),
1403 u16::from_be_bytes([value.payload[14], value.payload[15]]),
1404 u16::from_be_bytes([value.payload[16], value.payload[17]]),
1405 u16::from_be_bytes([value.payload[18], value.payload[19]]),
1406 );
1407 let dest_addr = Ipv6Addr::new(
1408 u16::from_be_bytes([value.payload[20], value.payload[21]]),
1409 u16::from_be_bytes([value.payload[22], value.payload[23]]),
1410 u16::from_be_bytes([value.payload[24], value.payload[25]]),
1411 u16::from_be_bytes([value.payload[26], value.payload[27]]),
1412 u16::from_be_bytes([value.payload[28], value.payload[29]]),
1413 u16::from_be_bytes([value.payload[30], value.payload[31]]),
1414 u16::from_be_bytes([value.payload[32], value.payload[33]]),
1415 u16::from_be_bytes([value.payload[34], value.payload[35]]),
1416 );
1417 let options = value
1418 .payload
1419 .slice(36..)
1420 .chunks(8)
1421 .map(|chunk| {
1422 let option_type = NdpOptionType::new(chunk[0]);
1423 let length = chunk[1];
1424 let payload = Bytes::from(chunk[2..].to_vec());
1425 NdpOptionPacket {
1426 option_type,
1427 length,
1428 payload,
1429 }
1430 })
1431 .collect();
1432 Ok(RedirectPacket {
1433 header: value.header,
1434 reserved,
1435 target_addr,
1436 dest_addr,
1437 options,
1438 payload: Bytes::new(),
1439 })
1440 }
1441 }
1442
1443 impl Packet for RedirectPacket {
1444 type Header = ();
1445 fn from_buf(bytes: &[u8]) -> Option<Self> {
1446 if bytes.len() < 40 {
1447 return None;
1448 }
1449
1450 let icmpv6_type = Icmpv6Type::new(bytes[0]);
1451 let icmpv6_code = Icmpv6Code::new(bytes[1]);
1452 let checksum = u16::from_be_bytes([bytes[2], bytes[3]]);
1453 let header = Icmpv6Header {
1454 icmpv6_type,
1455 icmpv6_code,
1456 checksum,
1457 };
1458
1459 let reserved = u32be::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]);
1460
1461 let target_addr = Ipv6Addr::new(
1462 u16::from_be_bytes([bytes[8], bytes[9]]),
1463 u16::from_be_bytes([bytes[10], bytes[11]]),
1464 u16::from_be_bytes([bytes[12], bytes[13]]),
1465 u16::from_be_bytes([bytes[14], bytes[15]]),
1466 u16::from_be_bytes([bytes[16], bytes[17]]),
1467 u16::from_be_bytes([bytes[18], bytes[19]]),
1468 u16::from_be_bytes([bytes[20], bytes[21]]),
1469 u16::from_be_bytes([bytes[22], bytes[23]]),
1470 );
1471
1472 let dest_addr = Ipv6Addr::new(
1473 u16::from_be_bytes([bytes[24], bytes[25]]),
1474 u16::from_be_bytes([bytes[26], bytes[27]]),
1475 u16::from_be_bytes([bytes[28], bytes[29]]),
1476 u16::from_be_bytes([bytes[30], bytes[31]]),
1477 u16::from_be_bytes([bytes[32], bytes[33]]),
1478 u16::from_be_bytes([bytes[34], bytes[35]]),
1479 u16::from_be_bytes([bytes[36], bytes[37]]),
1480 u16::from_be_bytes([bytes[38], bytes[39]]),
1481 );
1482
1483 let mut options = Vec::new();
1484 let mut i = 40;
1485 while i + 2 <= bytes.len() {
1486 let option_type = NdpOptionType::new(bytes[i]);
1487 let length = bytes[i + 1];
1488 let option_len = (length as usize) * 8;
1489
1490 if option_len < 2 || i + option_len > bytes.len() {
1491 break;
1492 }
1493
1494 let payload = Bytes::copy_from_slice(&bytes[i + 2..i + option_len]);
1495 options.push(NdpOptionPacket {
1496 option_type,
1497 length,
1498 payload,
1499 });
1500
1501 i += option_len;
1502 }
1503
1504 let payload = Bytes::copy_from_slice(&bytes[i..]);
1505
1506 Some(RedirectPacket {
1507 header,
1508 reserved,
1509 target_addr,
1510 dest_addr,
1511 options,
1512 payload,
1513 })
1514 }
1515 fn from_bytes(bytes: Bytes) -> Option<Self> {
1516 Self::from_buf(&bytes)
1517 }
1518 fn to_bytes(&self) -> Bytes {
1519 let mut bytes = Vec::with_capacity(NDP_REDIRECT_PACKET_LEN);
1520 bytes.push(self.header.icmpv6_type.value());
1521 bytes.push(self.header.icmpv6_code.value());
1522 bytes.extend_from_slice(&self.header.checksum.to_be_bytes());
1523 bytes.extend_from_slice(&self.reserved.to_be_bytes());
1524 for (_, segment) in self.target_addr.segments().iter().enumerate() {
1525 bytes.extend_from_slice(&segment.to_be_bytes());
1526 }
1527 for (_, segment) in self.dest_addr.segments().iter().enumerate() {
1528 bytes.extend_from_slice(&segment.to_be_bytes());
1529 }
1530 for option in &self.options {
1531 bytes.push(option.option_type.value());
1532 bytes.push(option.length);
1533 bytes.extend_from_slice(&option.payload);
1534 }
1535 Bytes::from(bytes)
1536 }
1537 fn header(&self) -> Bytes {
1538 self.to_bytes().slice(..ICMPV6_HEADER_LEN + 40) }
1540 fn payload(&self) -> Bytes {
1541 self.payload.clone()
1542 }
1543 fn header_len(&self) -> usize {
1544 ICMPV6_HEADER_LEN + 40 }
1546
1547 fn payload_len(&self) -> usize {
1548 self.payload.len()
1549 }
1550
1551 fn total_len(&self) -> usize {
1552 self.header_len() + self.payload_len()
1553 }
1554
1555 fn into_parts(self) -> (Self::Header, Bytes) {
1556 ((), self.payload)
1557 }
1558 }
1559
1560 impl RedirectPacket {
1561 pub fn options_length(&self) -> usize {
1563 if self.to_bytes().len() > 40 {
1565 self.to_bytes().len() - 40
1566 } else {
1567 0
1568 }
1569 }
1570 }
1571
1572 #[cfg(test)]
1573 mod ndp_tests {
1574 use super::*;
1575 use crate::icmpv6::{Icmpv6Code, Icmpv6Type};
1576
1577 #[test]
1578 fn basic_option_parsing() {
1579 let data = Bytes::from_static(&[
1580 0x02, 0x01, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
1581 0x00, 0x00, 0x00,
1583 ]);
1584 let pkg = NdpOptionPacket::from_bytes(data).unwrap();
1585 assert_eq!(pkg.option_type, NdpOptionTypes::TargetLLAddr);
1586 assert_eq!(pkg.length, 0x01);
1587 assert_eq!(pkg.payload.len(), 6);
1588 assert_eq!(pkg.payload.as_ref(), &[0x06, 0x05, 0x04, 0x03, 0x02, 0x01]);
1589 }
1590
1591 #[test]
1592 fn basic_rs_parse() {
1593 let data = Bytes::from_static(&[
1594 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
1599 0x00, 0x00,
1600 ]);
1601
1602 let pkg = RouterSolicitPacket::from_bytes(data).unwrap();
1603 assert_eq!(pkg.header.icmpv6_type, Icmpv6Type::RouterSolicitation);
1604 assert_eq!(pkg.header.icmpv6_code, Icmpv6Code(0));
1605 assert_eq!(pkg.header.checksum, 0);
1606 assert_eq!(pkg.reserved, 0);
1607 assert_eq!(pkg.options.len(), 2);
1608
1609 let option = &pkg.options[0];
1610 assert_eq!(option.option_type, NdpOptionTypes::TargetLLAddr);
1611 assert_eq!(option.length, 0x01);
1612 assert_eq!(
1613 option.payload.as_ref(),
1614 &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1615 );
1616 assert_eq!(option.payload.len(), 6);
1617
1618 let option = &pkg.options[1];
1619 assert_eq!(option.option_type, NdpOptionTypes::SourceLLAddr);
1620 assert_eq!(option.length, 1);
1621 assert_eq!(
1622 option.payload.as_ref(),
1623 &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1624 );
1625 }
1626
1627 #[test]
1628 fn basic_rs_create() {
1629 use crate::icmpv6::ndp::{NdpOptionPacket, RouterSolicitPacket};
1630
1631 let options = vec![NdpOptionPacket {
1632 option_type: NdpOptionTypes::SourceLLAddr,
1633 length: 1,
1634 payload: Bytes::from_static(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
1635 }];
1636
1637 let packet = RouterSolicitPacket {
1638 header: Icmpv6Header {
1639 icmpv6_type: Icmpv6Type::RouterSolicitation,
1640 icmpv6_code: Icmpv6Code(0),
1641 checksum: 0,
1642 },
1643 reserved: 0,
1644 options,
1645 payload: Bytes::new(),
1646 };
1647
1648 let bytes = packet.to_bytes();
1649
1650 let expected = Bytes::from_static(&[
1651 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
1656
1657 assert_eq!(bytes, expected);
1658 }
1659
1660 #[test]
1661 fn basic_ra_parse() {
1662 let data = Bytes::from_static(&[
1663 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, ]);
1674 let pkg = RouterAdvertPacket::from_bytes(data).unwrap();
1675 assert_eq!(pkg.header.icmpv6_type, Icmpv6Type::RouterAdvertisement);
1676 assert_eq!(pkg.header.icmpv6_code, Icmpv6Code(0));
1677 assert_eq!(pkg.header.checksum, 0x00);
1678 assert_eq!(pkg.hop_limit, 0xff);
1679 assert_eq!(pkg.flags, RouterAdvertFlags::ManagedAddressConf);
1680 assert_eq!(pkg.lifetime, 0x900);
1681 assert_eq!(pkg.reachable_time, 0x12345678);
1682 assert_eq!(pkg.retrans_time, 0x87654321);
1683 assert_eq!(pkg.options.len(), 2);
1684
1685 let option = &pkg.options[0];
1686 assert_eq!(option.option_type, NdpOptionTypes::SourceLLAddr);
1687 assert_eq!(option.length, 1);
1688 assert_eq!(
1689 option.payload.as_ref(),
1690 &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1691 );
1692
1693 let option = &pkg.options[1];
1694 assert_eq!(option.option_type, NdpOptionTypes::MTU);
1695 assert_eq!(option.length, 1);
1696 assert_eq!(
1697 option.payload.as_ref(),
1698 &[0x00, 0x00, 0x57, 0x68, 0x61, 0x74]
1699 );
1700 }
1701
1702 #[test]
1703 fn basic_ra_create() {
1704 use crate::icmpv6::ndp::{NdpOptionPacket, RouterAdvertFlags, RouterAdvertPacket};
1705
1706 let options = vec![NdpOptionPacket {
1707 option_type: NdpOptionTypes::MTU,
1708 length: 1,
1709 payload: Bytes::from_static(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
1710 }];
1711
1712 let packet = RouterAdvertPacket {
1713 header: Icmpv6Header {
1714 icmpv6_type: Icmpv6Type::RouterAdvertisement,
1715 icmpv6_code: Icmpv6Code(0),
1716 checksum: 0,
1717 },
1718 hop_limit: 0xff,
1719 flags: RouterAdvertFlags::ManagedAddressConf,
1720 lifetime: 0,
1721 reachable_time: 0,
1722 retrans_time: 0,
1723 options,
1724 payload: Bytes::new(),
1725 };
1726
1727 let bytes = packet.to_bytes();
1728 let expected = Bytes::from_static(&[
1729 0x86, 0x00, 0x00, 0x00, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
1736
1737 assert_eq!(bytes, expected);
1738 }
1739
1740 #[test]
1741 fn basic_ns_parse() {
1742 let data = Bytes::from_static(&[
1743 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00,
1744 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1745 ]);
1746 let pkg = NeighborSolicitPacket::from_bytes(data).unwrap();
1747 assert_eq!(pkg.header.icmpv6_type, Icmpv6Type::NeighborSolicitation);
1748 assert_eq!(pkg.header.icmpv6_code, Icmpv6Code(0));
1749 assert_eq!(pkg.header.checksum, 0x00);
1750 assert_eq!(pkg.reserved, 0x00);
1751 assert_eq!(pkg.target_addr, Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1));
1752 }
1753
1754 #[test]
1755 fn basic_ns_create() {
1756 use crate::icmpv6::ndp::NeighborSolicitPacket;
1757
1758 let packet = NeighborSolicitPacket {
1759 header: Icmpv6Header {
1760 icmpv6_type: Icmpv6Type::NeighborSolicitation,
1761 icmpv6_code: Icmpv6Code(0),
1762 checksum: 0,
1763 },
1764 reserved: 0,
1765 target_addr: Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1),
1766 options: vec![],
1767 payload: Bytes::new(),
1768 };
1769
1770 let bytes = packet.to_bytes();
1771
1772 let expected = Bytes::from_static(&[
1773 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1776 0x00, 0x01, ]);
1778
1779 assert_eq!(bytes, expected);
1780 }
1781
1782 #[test]
1783 fn basic_na_parse() {
1784 let data = Bytes::from_static(&[
1785 0x88, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00,
1786 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1787 ]);
1788 let pkg = NeighborAdvertPacket::from_bytes(data).unwrap();
1789 assert_eq!(pkg.header.icmpv6_type, Icmpv6Type::NeighborAdvertisement);
1790 assert_eq!(pkg.header.icmpv6_code, Icmpv6Code(0));
1791 assert_eq!(pkg.header.checksum, 0x00);
1792 assert_eq!(pkg.reserved, 0x00);
1793 assert_eq!(pkg.flags, 0x80);
1794 assert_eq!(pkg.target_addr, Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1));
1795 }
1796
1797 #[test]
1798 fn basic_na_create() {
1799 use crate::icmpv6::ndp::{NeighborAdvertFlags, NeighborAdvertPacket};
1800
1801 let packet = NeighborAdvertPacket {
1802 header: Icmpv6Header {
1803 icmpv6_type: Icmpv6Type::NeighborAdvertisement,
1804 icmpv6_code: Icmpv6Code(0),
1805 checksum: 0,
1806 },
1807 flags: NeighborAdvertFlags::Router,
1808 reserved: 0,
1809 target_addr: Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1),
1810 options: vec![],
1811 payload: Bytes::new(),
1812 };
1813
1814 let bytes = packet.to_bytes();
1815
1816 let expected = Bytes::from_static(&[
1817 0x88, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1820 0x00, 0x01,
1821 ]);
1822
1823 assert_eq!(bytes, expected);
1824 }
1825
1826 #[test]
1827 fn basic_redirect_parse() {
1828 let data = Bytes::from_static(&[
1829 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00,
1830 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
1831 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1832 ]);
1833 let pkg = RedirectPacket::from_bytes(data).unwrap();
1834 assert_eq!(pkg.header.icmpv6_type, Icmpv6Type::RedirectMessage);
1835 assert_eq!(pkg.header.icmpv6_code, Icmpv6Code(0));
1836 assert_eq!(pkg.header.checksum, 0x00);
1837 assert_eq!(pkg.reserved, 0x00);
1838 assert_eq!(pkg.target_addr, Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1));
1839 assert_eq!(pkg.dest_addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
1840 }
1841
1842 #[test]
1843 fn basic_redirect_create() {
1844 use crate::icmpv6::ndp::RedirectPacket;
1845
1846 let packet = RedirectPacket {
1847 header: Icmpv6Header {
1848 icmpv6_type: Icmpv6Type::RedirectMessage,
1849 icmpv6_code: Icmpv6Code(0),
1850 checksum: 0,
1851 },
1852 reserved: 0,
1853 target_addr: Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1),
1854 dest_addr: Ipv6Addr::UNSPECIFIED,
1855 options: vec![],
1856 payload: Bytes::new(),
1857 };
1858
1859 let bytes = packet.to_bytes();
1860
1861 let expected = Bytes::from_static(&[
1862 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1865 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1867 0x00, 0x00, ]);
1869
1870 assert_eq!(bytes, expected);
1871 }
1872 }
1873}
1874
1875pub mod echo_request {
1876 use bytes::Bytes;
1889
1890 use crate::{
1891 icmpv6::{Icmpv6Code, Icmpv6Header, Icmpv6Packet, Icmpv6Type},
1892 packet::Packet,
1893 };
1894
1895 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1897 pub struct Identifier(pub u16);
1898
1899 impl Identifier {
1900 pub fn new(val: u16) -> Identifier {
1902 Identifier(val)
1903 }
1904 pub fn value(&self) -> u16 {
1906 self.0
1907 }
1908 }
1909
1910 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1912 pub struct SequenceNumber(pub u16);
1913
1914 impl SequenceNumber {
1915 pub fn new(val: u16) -> SequenceNumber {
1917 SequenceNumber(val)
1918 }
1919 pub fn value(&self) -> u16 {
1921 self.0
1922 }
1923 }
1924
1925 #[allow(non_snake_case)]
1928 #[allow(non_upper_case_globals)]
1929 pub mod Icmpv6Codes {
1930 use crate::icmpv6::Icmpv6Code;
1931 pub const NoCode: Icmpv6Code = Icmpv6Code(0);
1933 }
1934
1935 #[derive(Clone, Debug, PartialEq, Eq)]
1937 pub struct EchoRequestPacket {
1938 pub header: Icmpv6Header,
1939 pub identifier: u16,
1940 pub sequence_number: u16,
1941 pub payload: Bytes,
1942 }
1943
1944 impl TryFrom<Icmpv6Packet> for EchoRequestPacket {
1945 type Error = &'static str;
1946
1947 fn try_from(value: Icmpv6Packet) -> Result<Self, Self::Error> {
1948 if value.header.icmpv6_type != Icmpv6Type::EchoRequest {
1949 return Err("Not an Echo Request packet");
1950 }
1951 if value.payload.len() < 8 {
1952 return Err("Payload too short for Echo Request");
1953 }
1954 let identifier = u16::from_be_bytes([value.payload[0], value.payload[1]]);
1955 let sequence_number = u16::from_be_bytes([value.payload[2], value.payload[3]]);
1956 Ok(EchoRequestPacket {
1957 header: value.header,
1958 identifier,
1959 sequence_number,
1960 payload: value.payload.slice(4..),
1961 })
1962 }
1963 }
1964
1965 impl Packet for EchoRequestPacket {
1966 type Header = ();
1967 fn from_buf(bytes: &[u8]) -> Option<Self> {
1968 if bytes.len() < 8 {
1969 return None;
1970 }
1971 let icmpv6_type = Icmpv6Type::new(bytes[0]);
1972 let icmpv6_code = Icmpv6Code::new(bytes[1]);
1973 let checksum = u16::from_be_bytes([bytes[2], bytes[3]]);
1974 let identifier = u16::from_be_bytes([bytes[4], bytes[5]]);
1975 let sequence_number = u16::from_be_bytes([bytes[6], bytes[7]]);
1976 Some(EchoRequestPacket {
1977 header: Icmpv6Header {
1978 icmpv6_type,
1979 icmpv6_code,
1980 checksum,
1981 },
1982 identifier,
1983 sequence_number,
1984 payload: Bytes::copy_from_slice(&bytes[8..]),
1985 })
1986 }
1987 fn from_bytes(bytes: Bytes) -> Option<Self> {
1988 Self::from_buf(&bytes)
1989 }
1990
1991 fn to_bytes(&self) -> Bytes {
1992 let mut bytes = Vec::with_capacity(8 + self.payload.len());
1993 bytes.push(self.header.icmpv6_type.value());
1994 bytes.push(self.header.icmpv6_code.value());
1995 bytes.extend_from_slice(&self.header.checksum.to_be_bytes());
1996 bytes.extend_from_slice(&self.identifier.to_be_bytes());
1997 bytes.extend_from_slice(&self.sequence_number.to_be_bytes());
1998 bytes.extend_from_slice(&self.payload);
1999 Bytes::from(bytes)
2000 }
2001
2002 fn header(&self) -> Bytes {
2003 self.to_bytes().slice(..8)
2004 }
2005
2006 fn payload(&self) -> Bytes {
2007 self.payload.clone()
2008 }
2009
2010 fn header_len(&self) -> usize {
2011 8 }
2013
2014 fn payload_len(&self) -> usize {
2015 self.payload.len()
2016 }
2017
2018 fn total_len(&self) -> usize {
2019 self.header_len() + self.payload_len()
2020 }
2021
2022 fn into_parts(self) -> (Self::Header, Bytes) {
2023 ((), self.payload)
2024 }
2025 }
2026}
2027
2028pub mod echo_reply {
2029 use bytes::Bytes;
2042
2043 use crate::{
2044 icmpv6::{Icmpv6Code, Icmpv6Header, Icmpv6Packet, Icmpv6Type},
2045 packet::Packet,
2046 };
2047 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
2049 pub struct Identifier(pub u16);
2050
2051 impl Identifier {
2052 pub fn new(val: u16) -> Identifier {
2054 Identifier(val)
2055 }
2056 pub fn value(&self) -> u16 {
2058 self.0
2059 }
2060 }
2061
2062 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
2064 pub struct SequenceNumber(pub u16);
2065
2066 impl SequenceNumber {
2067 pub fn new(val: u16) -> SequenceNumber {
2069 SequenceNumber(val)
2070 }
2071 pub fn value(&self) -> u16 {
2073 self.0
2074 }
2075 }
2076
2077 #[allow(non_snake_case)]
2080 #[allow(non_upper_case_globals)]
2081 pub mod Icmpv6Codes {
2082 use crate::icmpv6::Icmpv6Code;
2083 pub const NoCode: Icmpv6Code = Icmpv6Code(0);
2085 }
2086
2087 #[derive(Clone, Debug, PartialEq, Eq)]
2089 pub struct EchoReplyPacket {
2090 pub header: Icmpv6Header,
2091 pub identifier: u16,
2092 pub sequence_number: u16,
2093 pub payload: Bytes,
2094 }
2095 impl TryFrom<Icmpv6Packet> for EchoReplyPacket {
2096 type Error = &'static str;
2097
2098 fn try_from(value: Icmpv6Packet) -> Result<Self, Self::Error> {
2099 if value.header.icmpv6_type != Icmpv6Type::EchoReply {
2100 return Err("Not an Echo Reply packet");
2101 }
2102 if value.payload.len() < 8 {
2103 return Err("Payload too short for Echo Reply");
2104 }
2105 let identifier = u16::from_be_bytes([value.payload[0], value.payload[1]]);
2106 let sequence_number = u16::from_be_bytes([value.payload[2], value.payload[3]]);
2107 Ok(EchoReplyPacket {
2108 header: value.header,
2109 identifier,
2110 sequence_number,
2111 payload: value.payload.slice(4..),
2112 })
2113 }
2114 }
2115 impl Packet for EchoReplyPacket {
2116 type Header = ();
2117 fn from_buf(bytes: &[u8]) -> Option<Self> {
2118 if bytes.len() < 8 {
2119 return None;
2120 }
2121 let icmpv6_type = Icmpv6Type::new(bytes[0]);
2122 let icmpv6_code = Icmpv6Code::new(bytes[1]);
2123 let checksum = u16::from_be_bytes([bytes[2], bytes[3]]);
2124 let identifier = u16::from_be_bytes([bytes[4], bytes[5]]);
2125 let sequence_number = u16::from_be_bytes([bytes[6], bytes[7]]);
2126 Some(EchoReplyPacket {
2127 header: Icmpv6Header {
2128 icmpv6_type,
2129 icmpv6_code,
2130 checksum,
2131 },
2132 identifier,
2133 sequence_number,
2134 payload: Bytes::copy_from_slice(&bytes[8..]),
2135 })
2136 }
2137 fn from_bytes(bytes: Bytes) -> Option<Self> {
2138 Self::from_buf(&bytes)
2139 }
2140
2141 fn to_bytes(&self) -> Bytes {
2142 let mut bytes = Vec::with_capacity(8 + self.payload.len());
2143 bytes.push(self.header.icmpv6_type.value());
2144 bytes.push(self.header.icmpv6_code.value());
2145 bytes.extend_from_slice(&self.header.checksum.to_be_bytes());
2146 bytes.extend_from_slice(&self.identifier.to_be_bytes());
2147 bytes.extend_from_slice(&self.sequence_number.to_be_bytes());
2148 bytes.extend_from_slice(&self.payload);
2149 Bytes::from(bytes)
2150 }
2151
2152 fn header(&self) -> Bytes {
2153 self.to_bytes().slice(..8)
2154 }
2155
2156 fn payload(&self) -> Bytes {
2157 self.payload.clone()
2158 }
2159
2160 fn header_len(&self) -> usize {
2161 8 }
2163
2164 fn payload_len(&self) -> usize {
2165 self.payload.len()
2166 }
2167
2168 fn total_len(&self) -> usize {
2169 self.header_len() + self.payload_len()
2170 }
2171
2172 fn into_parts(self) -> (Self::Header, Bytes) {
2173 ((), self.payload)
2174 }
2175 }
2176}
2177
2178#[cfg(test)]
2179mod echo_tests {
2180 use super::*;
2181 use crate::icmpv6::{
2182 echo_reply::EchoReplyPacket, echo_request::EchoRequestPacket, Icmpv6Code, Icmpv6Type,
2183 };
2184
2185 #[test]
2186 fn test_echo_request_parse() {
2187 let raw = Bytes::from_static(&[
2188 0x80, 0x00, 0xbe, 0xef, 0x12, 0x34, 0x56, 0x78, b'p', b'i', b'n', b'g', b'!',
2192 ]);
2193
2194 let parsed = EchoRequestPacket::from_bytes(raw.clone())
2195 .expect("Failed to parse Echo Request packet");
2196
2197 assert_eq!(parsed.header.icmpv6_type, Icmpv6Type::EchoRequest);
2198 assert_eq!(parsed.header.icmpv6_code, Icmpv6Code(0));
2199 assert_eq!(parsed.header.checksum, 0xbeef);
2200 assert_eq!(parsed.identifier, 0x1234);
2201 assert_eq!(parsed.sequence_number, 0x5678);
2202 assert_eq!(parsed.payload, Bytes::from_static(b"ping!"));
2203 }
2204
2205 #[test]
2206 fn test_echo_request_create() {
2207 let payload = Bytes::from_static(b"hello");
2208 let packet = EchoRequestPacket {
2209 header: Icmpv6Header {
2210 icmpv6_type: Icmpv6Type::EchoRequest,
2211 icmpv6_code: Icmpv6Code(0),
2212 checksum: 0,
2213 },
2214 identifier: 0x1234,
2215 sequence_number: 0x5678,
2216 payload: payload.clone(),
2217 };
2218 let bytes = packet.to_bytes();
2219 let parsed = EchoRequestPacket::from_bytes(bytes).unwrap();
2220
2221 assert_eq!(parsed.identifier, 0x1234);
2222 assert_eq!(parsed.sequence_number, 0x5678);
2223 assert_eq!(parsed.payload, payload);
2224 }
2225
2226 #[test]
2227 fn test_echo_reply_parse() {
2228 let raw = Bytes::from_static(&[
2229 0x81, 0x00, 0x12, 0x34, 0xab, 0xcd, 0x56, 0x78, b'h', b'e', b'l', b'l', b'o',
2233 ]);
2234
2235 let parsed =
2236 EchoReplyPacket::from_bytes(raw.clone()).expect("Failed to parse Echo Reply packet");
2237
2238 assert_eq!(parsed.header.icmpv6_type, Icmpv6Type::EchoReply);
2239 assert_eq!(parsed.header.icmpv6_code, Icmpv6Code(0));
2240 assert_eq!(parsed.header.checksum, 0x1234);
2241 assert_eq!(parsed.identifier, 0xabcd);
2242 assert_eq!(parsed.sequence_number, 0x5678);
2243 assert_eq!(parsed.payload, Bytes::from_static(b"hello"));
2244 }
2245
2246 #[test]
2247 fn test_echo_reply_create() {
2248 let payload = Bytes::from_static(b"world");
2249 let packet = EchoReplyPacket {
2250 header: Icmpv6Header {
2251 icmpv6_type: Icmpv6Type::EchoReply,
2252 icmpv6_code: Icmpv6Code(0),
2253 checksum: 0,
2254 },
2255 identifier: 0xabcd,
2256 sequence_number: 0x1234,
2257 payload: payload.clone(),
2258 };
2259
2260 let bytes = packet.to_bytes();
2261 let parsed = EchoReplyPacket::from_bytes(bytes).expect("Failed to parse Echo Reply packet");
2262
2263 assert_eq!(parsed.header.icmpv6_type, Icmpv6Type::EchoReply);
2264 assert_eq!(parsed.identifier, 0xabcd);
2265 assert_eq!(parsed.sequence_number, 0x1234);
2266 assert_eq!(parsed.payload, payload);
2267 }
2268}