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}