1use crate::ip::IpNextLevelProtocol;
4use crate::PrimitiveValues;
5
6use alloc::vec::Vec;
7
8use crate::ethernet::ETHERNET_HEADER_LEN;
9use crate::ipv6::IPV6_HEADER_LEN;
10use std::net::Ipv6Addr;
11use xenet_macro::packet;
12use xenet_macro_helper::types::*;
13
14#[cfg(feature = "serde")]
15use serde::{Deserialize, Serialize};
16
17pub const ICMPV6_HEADER_LEN: usize = echo_request::MutableEchoRequestPacket::minimum_packet_size();
19pub const ICMPV6_PACKET_LEN: usize = ETHERNET_HEADER_LEN + IPV6_HEADER_LEN + ICMPV6_HEADER_LEN;
21pub const ICMPV6_IP_PACKET_LEN: usize = IPV6_HEADER_LEN + ICMPV6_HEADER_LEN;
23
24#[derive(Clone, Debug, PartialEq, Eq)]
26#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
27pub struct Icmpv6Header {
28 pub icmpv6_type: Icmpv6Type,
29 pub icmpv6_code: Icmpv6Code,
30 pub checksum: u16be,
31}
32
33impl Icmpv6Header {
34 pub fn from_bytes(packet: &[u8]) -> Result<Icmpv6Header, String> {
36 if packet.len() < ICMPV6_HEADER_LEN {
37 return Err("Packet is too small for ICMPv6 header".to_string());
38 }
39 match Icmpv6Packet::new(packet) {
40 Some(icmpv6_packet) => Ok(Icmpv6Header {
41 icmpv6_type: icmpv6_packet.get_icmpv6_type(),
42 icmpv6_code: icmpv6_packet.get_icmpv6_code(),
43 checksum: icmpv6_packet.get_checksum(),
44 }),
45 None => Err("Failed to parse ICMPv6 packet".to_string()),
46 }
47 }
48 pub(crate) fn from_packet(icmpv6_packet: &Icmpv6Packet) -> Icmpv6Header {
50 Icmpv6Header {
51 icmpv6_type: icmpv6_packet.get_icmpv6_type(),
52 icmpv6_code: icmpv6_packet.get_icmpv6_code(),
53 checksum: icmpv6_packet.get_checksum(),
54 }
55 }
56}
57
58#[repr(u8)]
61#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
62#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
63pub enum Icmpv6Type {
64 DestinationUnreachable,
65 PacketTooBig,
66 TimeExceeded,
67 ParameterProblem,
68 EchoRequest,
69 EchoReply,
70 MulticastListenerQuery,
71 MulticastListenerReport,
72 MulticastListenerDone,
73 RouterSolicitation,
74 RouterAdvertisement,
75 NeighborSolicitation,
76 NeighborAdvertisement,
77 RedirectMessage,
78 RouterRenumbering,
79 NodeInformationQuery,
80 NodeInformationResponse,
81 InverseNeighborDiscoverySolicitation,
82 InverseNeighborDiscoveryAdvertisement,
83 Version2MulticastListenerReport,
84 HomeAgentAddressDiscoveryRequest,
85 HomeAgentAddressDiscoveryReply,
86 MobilePrefixSolicitation,
87 MobilePrefixAdvertisement,
88 CertificationPathSolicitationMessage,
89 CertificationPathAdvertisementMessage,
90 ExperimentalMobilityProtocols,
91 MulticastRouterAdvertisement,
92 MulticastRouterSolicitation,
93 MulticastRouterTermination,
94 FMIPv6Messages,
95 RPLControlMessage,
96 ILNPv6LocatorUpdateMessage,
97 DuplicateAddressRequest,
98 DuplicateAddressConfirmation,
99 MPLControlMessage,
100 ExtendedEchoRequest,
101 ExtendedEchoReply,
102 Unknown(u8),
103}
104
105impl Icmpv6Type {
106 pub fn new(value: u8) -> Self {
107 match value {
108 1 => Icmpv6Type::DestinationUnreachable,
109 2 => Icmpv6Type::PacketTooBig,
110 3 => Icmpv6Type::TimeExceeded,
111 4 => Icmpv6Type::ParameterProblem,
112 128 => Icmpv6Type::EchoRequest,
113 129 => Icmpv6Type::EchoReply,
114 130 => Icmpv6Type::MulticastListenerQuery,
115 131 => Icmpv6Type::MulticastListenerReport,
116 132 => Icmpv6Type::MulticastListenerDone,
117 133 => Icmpv6Type::RouterSolicitation,
118 134 => Icmpv6Type::RouterAdvertisement,
119 135 => Icmpv6Type::NeighborSolicitation,
120 136 => Icmpv6Type::NeighborAdvertisement,
121 137 => Icmpv6Type::RedirectMessage,
122 138 => Icmpv6Type::RouterRenumbering,
123 139 => Icmpv6Type::NodeInformationQuery,
124 140 => Icmpv6Type::NodeInformationResponse,
125 141 => Icmpv6Type::InverseNeighborDiscoverySolicitation,
126 142 => Icmpv6Type::InverseNeighborDiscoveryAdvertisement,
127 143 => Icmpv6Type::Version2MulticastListenerReport,
128 144 => Icmpv6Type::HomeAgentAddressDiscoveryRequest,
129 145 => Icmpv6Type::HomeAgentAddressDiscoveryReply,
130 146 => Icmpv6Type::MobilePrefixSolicitation,
131 147 => Icmpv6Type::MobilePrefixAdvertisement,
132 148 => Icmpv6Type::CertificationPathSolicitationMessage,
133 149 => Icmpv6Type::CertificationPathAdvertisementMessage,
134 150 => Icmpv6Type::ExperimentalMobilityProtocols,
135 151 => Icmpv6Type::MulticastRouterAdvertisement,
136 152 => Icmpv6Type::MulticastRouterSolicitation,
137 153 => Icmpv6Type::MulticastRouterTermination,
138 154 => Icmpv6Type::FMIPv6Messages,
139 155 => Icmpv6Type::RPLControlMessage,
140 156 => Icmpv6Type::ILNPv6LocatorUpdateMessage,
141 157 => Icmpv6Type::DuplicateAddressRequest,
142 158 => Icmpv6Type::DuplicateAddressConfirmation,
143 159 => Icmpv6Type::MPLControlMessage,
144 160 => Icmpv6Type::ExtendedEchoRequest,
145 161 => Icmpv6Type::ExtendedEchoReply,
146 n => Icmpv6Type::Unknown(n),
147 }
148 }
149}
150
151impl PrimitiveValues for Icmpv6Type {
152 type T = (u8,);
153 fn to_primitive_values(&self) -> (u8,) {
154 match *self {
155 Icmpv6Type::DestinationUnreachable => (1,),
156 Icmpv6Type::PacketTooBig => (2,),
157 Icmpv6Type::TimeExceeded => (3,),
158 Icmpv6Type::ParameterProblem => (4,),
159 Icmpv6Type::EchoRequest => (128,),
160 Icmpv6Type::EchoReply => (129,),
161 Icmpv6Type::MulticastListenerQuery => (130,),
162 Icmpv6Type::MulticastListenerReport => (131,),
163 Icmpv6Type::MulticastListenerDone => (132,),
164 Icmpv6Type::RouterSolicitation => (133,),
165 Icmpv6Type::RouterAdvertisement => (134,),
166 Icmpv6Type::NeighborSolicitation => (135,),
167 Icmpv6Type::NeighborAdvertisement => (136,),
168 Icmpv6Type::RedirectMessage => (137,),
169 Icmpv6Type::RouterRenumbering => (138,),
170 Icmpv6Type::NodeInformationQuery => (139,),
171 Icmpv6Type::NodeInformationResponse => (140,),
172 Icmpv6Type::InverseNeighborDiscoverySolicitation => (141,),
173 Icmpv6Type::InverseNeighborDiscoveryAdvertisement => (142,),
174 Icmpv6Type::Version2MulticastListenerReport => (143,),
175 Icmpv6Type::HomeAgentAddressDiscoveryRequest => (144,),
176 Icmpv6Type::HomeAgentAddressDiscoveryReply => (145,),
177 Icmpv6Type::MobilePrefixSolicitation => (146,),
178 Icmpv6Type::MobilePrefixAdvertisement => (147,),
179 Icmpv6Type::CertificationPathSolicitationMessage => (148,),
180 Icmpv6Type::CertificationPathAdvertisementMessage => (149,),
181 Icmpv6Type::ExperimentalMobilityProtocols => (150,),
182 Icmpv6Type::MulticastRouterAdvertisement => (151,),
183 Icmpv6Type::MulticastRouterSolicitation => (152,),
184 Icmpv6Type::MulticastRouterTermination => (153,),
185 Icmpv6Type::FMIPv6Messages => (154,),
186 Icmpv6Type::RPLControlMessage => (155,),
187 Icmpv6Type::ILNPv6LocatorUpdateMessage => (156,),
188 Icmpv6Type::DuplicateAddressRequest => (157,),
189 Icmpv6Type::DuplicateAddressConfirmation => (158,),
190 Icmpv6Type::MPLControlMessage => (159,),
191 Icmpv6Type::ExtendedEchoRequest => (160,),
192 Icmpv6Type::ExtendedEchoReply => (161,),
193 Icmpv6Type::Unknown(n) => (n,),
194 }
195 }
196}
197
198#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
200#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
201pub struct Icmpv6Code(pub u8);
202
203impl Icmpv6Code {
204 pub fn new(val: u8) -> Icmpv6Code {
206 Icmpv6Code(val)
207 }
208}
209
210impl PrimitiveValues for Icmpv6Code {
211 type T = (u8,);
212 fn to_primitive_values(&self) -> (u8,) {
213 (self.0,)
214 }
215}
216
217#[packet]
230pub struct Icmpv6 {
231 #[construct_with(u8)]
232 pub icmpv6_type: Icmpv6Type,
233 #[construct_with(u8)]
234 pub icmpv6_code: Icmpv6Code,
235 pub checksum: u16be,
236 #[payload]
237 pub payload: Vec<u8>,
238}
239
240pub fn checksum(packet: &Icmpv6Packet, source: &Ipv6Addr, destination: &Ipv6Addr) -> u16be {
242 use crate::util;
243 use crate::Packet;
244
245 util::ipv6_checksum(
246 packet.packet(),
247 1,
248 &[],
249 source,
250 destination,
251 IpNextLevelProtocol::Icmpv6,
252 )
253}
254
255#[cfg(test)]
256mod checksum_tests {
257 use super::*;
258 use alloc::vec;
259
260 #[test]
261 fn checksum_echo_request() {
262 let lo = &Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
264 let mut data = vec![
265 0x80, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x20, 0x20, 0x75, 0x73, 0x74, 0x20, 0x61, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20,
272 0x77, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x20, 0x74, 0x69, 0x73, 0x20, 0x62, 0x75, 0x74,
273 0x20, 0x61, 0x20, 0x73, 0x63, 0x72, 0x61, 0x74, 0x63, 0x68, 0x20, 0x20, 0x6b, 0x6e,
274 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x6e, 0x69, 0x20, 0x20, 0x20,
275 ];
276 let mut pkg = MutableIcmpv6Packet::new(&mut data[..]).unwrap();
277 assert_eq!(checksum(&pkg.to_immutable(), lo, lo), 0x1d2e);
278
279 pkg.set_icmpv6_type(Icmpv6Type::new(0x81));
281 assert_eq!(checksum(&pkg.to_immutable(), lo, lo), 0x1c2e);
282 }
283}
284
285pub mod ndp {
286 use crate::icmpv6::{Icmpv6Code, Icmpv6Type};
291 use crate::Packet;
292 use crate::PrimitiveValues;
293
294 use alloc::vec::Vec;
295
296 use std::net::Ipv6Addr;
297 use xenet_macro::packet;
298 use xenet_macro_helper::types::*;
299
300 pub const NDP_SOL_PACKET_LEN: usize = NeighborSolicitPacket::minimum_packet_size();
302 pub const NDP_ADV_PACKET_LEN: usize = NeighborAdvertPacket::minimum_packet_size();
304 pub const NDP_OPT_PACKET_LEN: usize = NdpOptionPacket::minimum_packet_size();
306
307 #[allow(non_snake_case)]
308 #[allow(non_upper_case_globals)]
309 pub mod Icmpv6Codes {
310 use crate::icmpv6::Icmpv6Code;
311 pub const NoCode: Icmpv6Code = Icmpv6Code(0);
313 }
314
315 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
317 pub struct NdpOptionType(pub u8);
318
319 impl NdpOptionType {
320 pub fn new(value: u8) -> NdpOptionType {
322 NdpOptionType(value)
323 }
324 }
325
326 impl PrimitiveValues for NdpOptionType {
327 type T = (u8,);
328 fn to_primitive_values(&self) -> (u8,) {
329 (self.0,)
330 }
331 }
332
333 #[allow(non_snake_case)]
337 #[allow(non_upper_case_globals)]
338 pub mod NdpOptionTypes {
339 use super::NdpOptionType;
340
341 pub const SourceLLAddr: NdpOptionType = NdpOptionType(1);
351
352 pub const TargetLLAddr: NdpOptionType = NdpOptionType(2);
362
363 pub const PrefixInformation: NdpOptionType = NdpOptionType(3);
387
388 pub const RedirectedHeader: NdpOptionType = NdpOptionType(4);
404
405 pub const MTU: NdpOptionType = NdpOptionType(5);
417 }
418
419 #[packet]
431 pub struct NdpOption {
432 #[construct_with(u8)]
433 pub option_type: NdpOptionType,
434 #[construct_with(u8)]
435 pub length: u8,
436 #[length_fn = "ndp_option_payload_length"]
437 #[payload]
438 pub data: Vec<u8>,
439 }
440
441 fn ndp_option_payload_length(option: &NdpOptionPacket) -> usize {
443 let len = option.get_length();
444 if len > 0 {
445 ((len * 8) - 2) as usize
446 } else {
447 0
448 }
449 }
450
451 #[packet]
464 pub struct RouterSolicit {
465 #[construct_with(u8)]
466 pub icmpv6_type: Icmpv6Type,
467 #[construct_with(u8)]
468 pub icmpv6_code: Icmpv6Code,
469 pub checksum: u16be,
470 pub reserved: u32be,
471 #[length_fn = "rs_ndp_options_length"]
472 pub options: Vec<NdpOption>,
473 #[payload]
474 #[length = "0"]
475 pub payload: Vec<u8>,
476 }
477
478 fn rs_ndp_options_length(pkt: &RouterSolicitPacket) -> usize {
480 if pkt.packet().len() > 8 {
481 pkt.packet().len() - 8
482 } else {
483 0
484 }
485 }
486
487 #[allow(non_snake_case)]
489 #[allow(non_upper_case_globals)]
490 pub mod RouterAdvertFlags {
491 pub const ManagedAddressConf: u8 = 0b10000000;
494 pub const OtherConf: u8 = 0b01000000;
497 }
498
499 #[packet]
517 pub struct RouterAdvert {
518 #[construct_with(u8)]
519 pub icmpv6_type: Icmpv6Type,
520 #[construct_with(u8)]
521 pub icmpv6_code: Icmpv6Code,
522 pub checksum: u16be,
523 pub hop_limit: u8,
524 pub flags: u8,
525 pub lifetime: u16be,
526 pub reachable_time: u32be,
527 pub retrans_time: u32be,
528 #[length_fn = "ra_ndp_options_length"]
529 pub options: Vec<NdpOption>,
530 #[payload]
531 #[length = "0"]
532 pub payload: Vec<u8>,
533 }
534
535 fn ra_ndp_options_length(pkt: &RouterAdvertPacket) -> usize {
537 if pkt.packet().len() > 16 {
538 pkt.packet().len() - 16
539 } else {
540 0
541 }
542 }
543
544 #[packet]
566 pub struct NeighborSolicit {
567 #[construct_with(u8)]
568 pub icmpv6_type: Icmpv6Type,
569 #[construct_with(u8)]
570 pub icmpv6_code: Icmpv6Code,
571 pub checksum: u16be,
572 pub reserved: u32be,
573 #[construct_with(u16, u16, u16, u16, u16, u16, u16, u16)]
574 pub target_addr: Ipv6Addr,
575 #[length_fn = "ns_ndp_options_length"]
576 pub options: Vec<NdpOption>,
577 #[payload]
578 #[length = "0"]
579 pub payload: Vec<u8>,
580 }
581
582 fn ns_ndp_options_length(pkt: &NeighborSolicitPacket) -> usize {
584 if pkt.packet().len() > 24 {
585 pkt.packet().len() - 24
586 } else {
587 0
588 }
589 }
590
591 #[allow(non_snake_case)]
593 #[allow(non_upper_case_globals)]
594 pub mod NeighborAdvertFlags {
595 pub const Router: u8 = 0b10000000;
597 pub const Solicited: u8 = 0b01000000;
600 pub const Override: u8 = 0b00100000;
603 }
604
605 #[packet]
627 pub struct NeighborAdvert {
628 #[construct_with(u8)]
629 pub icmpv6_type: Icmpv6Type,
630 #[construct_with(u8)]
631 pub icmpv6_code: Icmpv6Code,
632 pub checksum: u16be,
633 pub flags: u8,
634 pub reserved: u24be,
635 #[construct_with(u16, u16, u16, u16, u16, u16, u16, u16)]
636 pub target_addr: Ipv6Addr,
637 #[length_fn = "na_ndp_options_length"]
638 pub options: Vec<NdpOption>,
639 #[payload]
640 #[length = "0"]
641 pub payload: Vec<u8>,
642 }
643
644 fn na_ndp_options_length(pkt: &NeighborAdvertPacket) -> usize {
646 if pkt.packet().len() > 24 {
647 pkt.packet().len() - 24
648 } else {
649 0
650 }
651 }
652
653 #[packet]
683 pub struct Redirect {
684 #[construct_with(u8)]
685 pub icmpv6_type: Icmpv6Type,
686 #[construct_with(u8)]
687 pub icmpv6_code: Icmpv6Code,
688 pub checksum: u16be,
689 pub reserved: u32be,
690 #[construct_with(u16, u16, u16, u16, u16, u16, u16, u16)]
691 pub target_addr: Ipv6Addr,
692 #[construct_with(u16, u16, u16, u16, u16, u16, u16, u16)]
693 pub dest_addr: Ipv6Addr,
694 #[length_fn = "redirect_options_length"]
695 pub options: Vec<NdpOption>,
696 #[payload]
697 #[length = "0"]
698 pub payload: Vec<u8>,
699 }
700
701 fn redirect_options_length(pkt: &RedirectPacket) -> usize {
703 if pkt.packet().len() > 40 {
704 pkt.packet().len() - 40
705 } else {
706 0
707 }
708 }
709
710 #[cfg(test)]
711 mod ndp_tests {
712 use super::*;
713 use crate::icmpv6::{Icmpv6Code, Icmpv6Type};
714 use alloc::vec;
715
716 #[test]
717 fn basic_option_parsing() {
718 let mut data = vec![
719 0x02, 0x01, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
720 0x00, 0x00, 0x00,
722 ];
723 let pkg = MutableNdpOptionPacket::new(&mut data[..]).unwrap();
724 assert_eq!(pkg.get_option_type(), NdpOptionTypes::TargetLLAddr);
725 assert_eq!(pkg.get_length(), 0x01);
726 assert_eq!(pkg.payload().len(), 6);
727 assert_eq!(pkg.payload(), &[0x06, 0x05, 0x04, 0x03, 0x02, 0x01]);
728 }
729
730 #[test]
731 fn basic_rs_parse() {
732 let mut data = vec![
733 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
738 0x00, 0x00,
739 ];
740
741 let pkg = MutableRouterSolicitPacket::new(&mut data[..]).unwrap();
742 assert_eq!(pkg.get_icmpv6_type(), Icmpv6Type::RouterSolicitation);
743 assert_eq!(pkg.get_icmpv6_code(), Icmpv6Code(0));
744 assert_eq!(pkg.get_checksum(), 0);
745 assert_eq!(pkg.get_reserved(), 0);
746 assert_eq!(pkg.get_options().len(), 2);
747
748 let option = &pkg.get_options()[0];
749 assert_eq!(option.option_type, NdpOptionTypes::TargetLLAddr);
750 assert_eq!(option.length, 0x01);
751 assert_eq!(option.data, &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
752 assert_eq!(option.data.len(), 6);
753
754 let option = &pkg.get_options()[1];
755 assert_eq!(option.option_type, NdpOptionTypes::SourceLLAddr);
756 assert_eq!(option.length, 1);
757 assert_eq!(option.data, &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
758 }
759
760 #[test]
761 fn basic_rs_create() {
762 let ref_packet = vec![
763 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
764 0x00, 0x00,
765 ];
766 let mut packet = [0u8; 16];
767 let options = vec![NdpOption {
768 option_type: NdpOptionTypes::SourceLLAddr,
769 length: 1,
770 data: vec![0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
771 }];
772 {
773 let mut rs_packet = MutableRouterSolicitPacket::new(&mut packet[..]).unwrap();
774 rs_packet.set_icmpv6_type(Icmpv6Type::RouterSolicitation);
775 rs_packet.set_icmpv6_code(Icmpv6Code(0));
776 rs_packet.set_options(&options[..]);
777 }
778 assert_eq!(&ref_packet[..], &packet[..]);
779 }
780
781 #[test]
782 fn basic_ra_parse() {
783 let mut data = vec![
784 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, ];
795 let pkg = MutableRouterAdvertPacket::new(&mut data[..]).unwrap();
796 assert_eq!(pkg.get_icmpv6_type(), Icmpv6Type::RouterAdvertisement);
797 assert_eq!(pkg.get_icmpv6_code(), Icmpv6Code(0));
798 assert_eq!(pkg.get_checksum(), 0x00);
799 assert_eq!(pkg.get_hop_limit(), 0xff);
800 assert_eq!(pkg.get_flags(), RouterAdvertFlags::ManagedAddressConf);
801 assert_eq!(pkg.get_lifetime(), 0x900);
802 assert_eq!(pkg.get_reachable_time(), 0x12345678);
803 assert_eq!(pkg.get_retrans_time(), 0x87654321);
804 assert_eq!(pkg.get_options().len(), 2);
805
806 let option = &pkg.get_options()[0];
807 assert_eq!(option.option_type, NdpOptionTypes::SourceLLAddr);
808 assert_eq!(option.length, 1);
809 assert_eq!(option.data, &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
810
811 let option = &pkg.get_options()[1];
812 assert_eq!(option.option_type, NdpOptionTypes::MTU);
813 assert_eq!(option.length, 1);
814 assert_eq!(option.data, &[0x00, 0x00, 0x57, 0x68, 0x61, 0x74]);
815 }
816
817 #[test]
818 fn basic_ra_create() {
819 let ref_packet = vec![
820 0x86, 0x00, 0x00, 0x00, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
821 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
822 ];
823 let mut packet = [0u8; 24];
824 let options = vec![NdpOption {
825 option_type: NdpOptionTypes::MTU,
826 length: 1,
827 data: vec![0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
828 }];
829 {
830 let mut ra_packet = MutableRouterAdvertPacket::new(&mut packet[..]).unwrap();
831 ra_packet.set_icmpv6_type(Icmpv6Type::RouterAdvertisement);
832 ra_packet.set_icmpv6_code(Icmpv6Code(0));
833 ra_packet.set_hop_limit(0xff);
834 ra_packet.set_flags(RouterAdvertFlags::ManagedAddressConf);
835 ra_packet.set_options(&options[..]);
836 }
837 assert_eq!(&ref_packet[..], &packet[..]);
838 }
839
840 #[test]
841 fn basic_ns_parse() {
842 let mut data = vec![
843 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00,
844 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
845 ];
846 let pkg = MutableNeighborSolicitPacket::new(&mut data[..]).unwrap();
847 assert_eq!(pkg.get_icmpv6_type(), Icmpv6Type::NeighborSolicitation);
848 assert_eq!(pkg.get_icmpv6_code(), Icmpv6Code(0));
849 assert_eq!(pkg.get_checksum(), 0x00);
850 assert_eq!(pkg.get_reserved(), 0x00);
851 assert_eq!(
852 pkg.get_target_addr(),
853 Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1)
854 );
855 }
856
857 #[test]
858 fn basic_ns_create() {
859 let ref_packet = vec![
860 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00,
861 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
862 ];
863 let mut packet = [0u8; 24];
864 {
865 let mut ns_packet = MutableNeighborSolicitPacket::new(&mut packet[..]).unwrap();
866 ns_packet.set_icmpv6_type(Icmpv6Type::NeighborSolicitation);
867 ns_packet.set_icmpv6_code(Icmpv6Code(0));
868 ns_packet.set_target_addr(Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1));
869 }
870 assert_eq!(&ref_packet[..], &packet[..]);
871 }
872
873 #[test]
874 fn basic_na_parse() {
875 let mut data = vec![
876 0x88, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00,
877 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
878 ];
879 let pkg = MutableNeighborAdvertPacket::new(&mut data[..]).unwrap();
880 assert_eq!(pkg.get_icmpv6_type(), Icmpv6Type::NeighborAdvertisement);
881 assert_eq!(pkg.get_icmpv6_code(), Icmpv6Code(0));
882 assert_eq!(pkg.get_checksum(), 0x00);
883 assert_eq!(pkg.get_reserved(), 0x00);
884 assert_eq!(pkg.get_flags(), 0x80);
885 assert_eq!(
886 pkg.get_target_addr(),
887 Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1)
888 );
889 }
890
891 #[test]
892 fn basic_na_create() {
893 let ref_packet = vec![
894 0x88, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00,
895 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
896 ];
897 let mut packet = [0u8; 24];
898 {
899 let mut na_packet = MutableNeighborAdvertPacket::new(&mut packet[..]).unwrap();
900 na_packet.set_icmpv6_type(Icmpv6Type::NeighborAdvertisement);
901 na_packet.set_icmpv6_code(Icmpv6Code(0));
902 na_packet.set_target_addr(Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1));
903 na_packet.set_flags(NeighborAdvertFlags::Router);
904 }
905 assert_eq!(&ref_packet[..], &packet[..]);
906 }
907
908 #[test]
909 fn basic_redirect_parse() {
910 let mut data = vec![
911 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00,
912 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
913 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
914 ];
915 let pkg = MutableRedirectPacket::new(&mut data[..]).unwrap();
916 assert_eq!(pkg.get_icmpv6_type(), Icmpv6Type::RedirectMessage);
917 assert_eq!(pkg.get_icmpv6_code(), Icmpv6Code(0));
918 assert_eq!(pkg.get_checksum(), 0x00);
919 assert_eq!(pkg.get_reserved(), 0x00);
920 assert_eq!(
921 pkg.get_target_addr(),
922 Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1)
923 );
924 assert_eq!(pkg.get_dest_addr(), Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
925 }
926
927 #[test]
928 fn basic_redirect_create() {
929 let ref_packet = vec![
930 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00,
931 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
932 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
933 ];
934 let mut packet = [0u8; 40];
935 {
936 let mut rdr_packet = MutableRedirectPacket::new(&mut packet[..]).unwrap();
937 rdr_packet.set_icmpv6_type(Icmpv6Type::RedirectMessage);
938 rdr_packet.set_icmpv6_code(Icmpv6Code(0));
939 rdr_packet.set_target_addr(Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1));
940 rdr_packet.set_dest_addr(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
941 }
942 assert_eq!(&ref_packet[..], &packet[..]);
943 }
944 }
945}
946
947pub mod echo_reply {
948 use crate::icmpv6::{Icmpv6Code, Icmpv6Type};
961 use crate::PrimitiveValues;
962
963 use alloc::vec::Vec;
964
965 use xenet_macro::packet;
966 use xenet_macro_helper::types::*;
967
968 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
970 pub struct Identifier(pub u16);
971
972 impl Identifier {
973 pub fn new(val: u16) -> Identifier {
975 Identifier(val)
976 }
977 }
978
979 impl PrimitiveValues for Identifier {
980 type T = (u16,);
981 fn to_primitive_values(&self) -> (u16,) {
982 (self.0,)
983 }
984 }
985
986 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
988 pub struct SequenceNumber(pub u16);
989
990 impl SequenceNumber {
991 pub fn new(val: u16) -> SequenceNumber {
993 SequenceNumber(val)
994 }
995 }
996
997 impl PrimitiveValues for SequenceNumber {
998 type T = (u16,);
999 fn to_primitive_values(&self) -> (u16,) {
1000 (self.0,)
1001 }
1002 }
1003
1004 #[allow(non_snake_case)]
1007 #[allow(non_upper_case_globals)]
1008 pub mod Icmpv6Codes {
1009 use crate::icmpv6::Icmpv6Code;
1010 pub const NoCode: Icmpv6Code = Icmpv6Code(0);
1012 }
1013
1014 #[packet]
1016 pub struct EchoReply {
1017 #[construct_with(u8)]
1018 pub icmpv6_type: Icmpv6Type,
1019 #[construct_with(u8)]
1020 pub icmpv6_code: Icmpv6Code,
1021 pub checksum: u16be,
1022 pub identifier: u16be,
1023 pub sequence_number: u16be,
1024 #[payload]
1025 pub payload: Vec<u8>,
1026 }
1027}
1028
1029pub mod echo_request {
1030 use crate::icmpv6::{Icmpv6Code, Icmpv6Type};
1043 use crate::PrimitiveValues;
1044
1045 use alloc::vec::Vec;
1046
1047 use xenet_macro::packet;
1048 use xenet_macro_helper::types::*;
1049
1050 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1052 pub struct Identifier(pub u16);
1053
1054 impl Identifier {
1055 pub fn new(val: u16) -> Identifier {
1057 Identifier(val)
1058 }
1059 }
1060
1061 impl PrimitiveValues for Identifier {
1062 type T = (u16,);
1063 fn to_primitive_values(&self) -> (u16,) {
1064 (self.0,)
1065 }
1066 }
1067
1068 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1070 pub struct SequenceNumber(pub u16);
1071
1072 impl SequenceNumber {
1073 pub fn new(val: u16) -> SequenceNumber {
1075 SequenceNumber(val)
1076 }
1077 }
1078
1079 impl PrimitiveValues for SequenceNumber {
1080 type T = (u16,);
1081 fn to_primitive_values(&self) -> (u16,) {
1082 (self.0,)
1083 }
1084 }
1085
1086 #[allow(non_snake_case)]
1089 #[allow(non_upper_case_globals)]
1090 pub mod Icmpv6Codes {
1091 use crate::icmpv6::Icmpv6Code;
1092 pub const NoCode: Icmpv6Code = Icmpv6Code(0);
1094 }
1095
1096 #[packet]
1098 pub struct EchoRequest {
1099 #[construct_with(u8)]
1100 pub icmpv6_type: Icmpv6Type,
1101 #[construct_with(u8)]
1102 pub icmpv6_code: Icmpv6Code,
1103 pub checksum: u16be,
1104 pub identifier: u16be,
1105 pub sequence_number: u16be,
1106 #[payload]
1107 pub payload: Vec<u8>,
1108 }
1109}