1pub mod ext_hdrs;
12
13use alloc::vec::Vec;
14use core::borrow::Borrow;
15use core::fmt::{self, Debug, Formatter};
16use core::ops::Range;
17
18use log::debug;
19use net_types::ip::{GenericOverIp, Ipv4Addr, Ipv6, Ipv6Addr, Ipv6SourceAddr};
20use packet::records::{AlignedRecordSequenceBuilder, Records, RecordsRaw};
21use packet::{
22 BufferProvider, BufferView, BufferViewMut, EmptyBuf, FragmentedBytesMut, FromRaw,
23 GrowBufferMut, InnerPacketBuilder, LayoutBufferAlloc, MaybeParsed, NestablePacketBuilder,
24 NestableSerializer, NoOpSerializationContext, PacketBuilder, PacketConstraints, ParsablePacket,
25 ParseMetadata, PartialPacketBuilder, PartialSerializer, SerializeError, SerializeTarget,
26 Serializer,
27};
28use zerocopy::byteorder::network_endian::{U16, U32};
29use zerocopy::{
30 FromBytes, Immutable, IntoBytes, KnownLayout, Ref, SplitByteSlice, SplitByteSliceMut, Unaligned,
31};
32
33use crate::TRANSPORT_HEADER_MAX_SIZE;
34use crate::error::{IpParseErrorAction, IpParseResult, Ipv6ParseError, ParseError};
35use crate::icmp::Icmpv6ParameterProblemCode;
36use crate::ip::{
37 DscpAndEcn, FragmentOffset, IpEnvelope, IpExt, IpPacketBuilder, IpProto,
38 IpSerializationContext, Ipv4Proto, Ipv6ExtHdrType, Ipv6Proto, Nat64Error,
39 Nat64TranslationResult,
40};
41use crate::ipv4::{HDR_PREFIX_LEN, Ipv4PacketBuilder};
42use crate::ipv6::ext_hdrs::ExtensionHeaderOptionAction;
43use crate::tcp::{TcpParseArgs, TcpSegment};
44use crate::udp::{UdpPacket, UdpParseArgs};
45
46use ext_hdrs::{
47 HopByHopOption, HopByHopOptionData, IPV6_FRAGMENT_EXT_HDR_LEN, Ipv6ExtensionHeader,
48 Ipv6ExtensionHeaderImpl, Ipv6ExtensionHeaderParsingContext, Ipv6ExtensionHeaderParsingError,
49 is_valid_next_header_upper_layer,
50};
51
52pub const IPV6_FIXED_HDR_LEN: usize = 40;
54
55pub const IPV6_PAYLOAD_LEN_BYTE_RANGE: Range<usize> = 4..6;
58
59const NEXT_HEADER_OFFSET: u8 = 6;
61
62const IPV6_HBH_OPTIONS_MAX_LEN: usize = (core::u8::MAX as usize) * 8 + 8;
66
67const IPV6_MAX_PAYLOAD_LENGTH: usize = core::u16::MAX as usize;
74
75fn ext_hdr_err_fn(hdr: &FixedHeader, err: Ipv6ExtensionHeaderParsingError) -> Ipv6ParseError {
78 match err {
97 Ipv6ExtensionHeaderParsingError::ErroneousHeaderField { pointer, must_send_icmp } => {
98 Ipv6ParseError::ParameterProblem {
99 src_ip: hdr.src_ip,
100 dst_ip: hdr.dst_ip,
101 code: Icmpv6ParameterProblemCode::ErroneousHeaderField,
102 pointer,
103 must_send_icmp,
104 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
105 }
106 }
107 Ipv6ExtensionHeaderParsingError::UnrecognizedNextHeader { pointer, must_send_icmp } => {
108 Ipv6ParseError::ParameterProblem {
109 src_ip: hdr.src_ip,
110 dst_ip: hdr.dst_ip,
111 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
112 pointer,
113 must_send_icmp,
114 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
115 }
116 }
117 Ipv6ExtensionHeaderParsingError::UnrecognizedOption { pointer, must_send_icmp, action } => {
118 let action = match action {
119 ExtensionHeaderOptionAction::SkipAndContinue => unreachable!(
120 "Should never end up here because this action should never result in an error"
121 ),
122 ExtensionHeaderOptionAction::DiscardPacket => IpParseErrorAction::DiscardPacket,
123 ExtensionHeaderOptionAction::DiscardPacketSendIcmp => {
124 IpParseErrorAction::DiscardPacketSendIcmp
125 }
126 ExtensionHeaderOptionAction::DiscardPacketSendIcmpNoMulticast => {
127 IpParseErrorAction::DiscardPacketSendIcmpNoMulticast
128 }
129 };
130
131 Ipv6ParseError::ParameterProblem {
132 src_ip: hdr.src_ip,
133 dst_ip: hdr.dst_ip,
134 code: Icmpv6ParameterProblemCode::UnrecognizedIpv6Option,
135 pointer,
136 must_send_icmp,
137 action,
138 }
139 }
140 Ipv6ExtensionHeaderParsingError::BufferExhausted
141 | Ipv6ExtensionHeaderParsingError::MalformedData => {
142 Ipv6ParseError::Parse { error: ParseError::Format }
145 }
146 }
147}
148
149#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
151#[repr(C)]
152pub struct FixedHeader {
153 version_tc_flowlabel: [u8; 4],
154 payload_len: U16,
155 next_hdr: u8,
156 hop_limit: u8,
157 src_ip: Ipv6Addr,
158 dst_ip: Ipv6Addr,
159}
160
161const IP_VERSION: u8 = 6;
162const VERSION_OFFSET: u8 = 4;
163const FLOW_LABEL_MAX: u32 = (1 << 20) - 1;
164
165impl FixedHeader {
166 #[allow(clippy::too_many_arguments)]
167 fn new(
168 dscp_and_ecn: DscpAndEcn,
169 flow_label: u32,
170 payload_len: u16,
171 next_hdr: u8,
172 hop_limit: u8,
173 src_ip: Ipv6Addr,
174 dst_ip: Ipv6Addr,
175 ) -> FixedHeader {
176 debug_assert!(flow_label <= FLOW_LABEL_MAX);
177
178 let traffic_class = dscp_and_ecn.raw();
179 FixedHeader {
180 version_tc_flowlabel: [
181 IP_VERSION << VERSION_OFFSET | traffic_class >> 4,
182 (traffic_class << 4) | ((flow_label >> 16) as u8),
183 (flow_label >> 8) as u8,
184 flow_label as u8,
185 ],
186 payload_len: U16::new(payload_len),
187 next_hdr,
188 hop_limit,
189 src_ip,
190 dst_ip,
191 }
192 }
193
194 fn version(&self) -> u8 {
195 self.version_tc_flowlabel[0] >> 4
196 }
197
198 fn dscp_and_ecn(&self) -> DscpAndEcn {
199 ((self.version_tc_flowlabel[0] & 0xF) << 4 | self.version_tc_flowlabel[1] >> 4).into()
200 }
201
202 fn flowlabel(&self) -> u32 {
203 (u32::from(self.version_tc_flowlabel[1]) & 0xF) << 16
204 | u32::from(self.version_tc_flowlabel[2]) << 8
205 | u32::from(self.version_tc_flowlabel[3])
206 }
207}
208
209pub trait Ipv6Header {
214 fn get_fixed_header(&self) -> &FixedHeader;
216
217 fn hop_limit(&self) -> u8 {
219 self.get_fixed_header().hop_limit
220 }
221
222 fn next_header(&self) -> u8 {
224 self.get_fixed_header().next_hdr
225 }
226
227 fn src_ip(&self) -> Ipv6Addr {
229 self.get_fixed_header().src_ip
230 }
231
232 fn dst_ip(&self) -> Ipv6Addr {
234 self.get_fixed_header().dst_ip
235 }
236
237 fn dscp_and_ecn(&self) -> DscpAndEcn {
240 self.get_fixed_header().dscp_and_ecn()
241 }
242}
243
244impl Ipv6Header for FixedHeader {
245 fn get_fixed_header(&self) -> &FixedHeader {
246 self
247 }
248}
249
250pub struct Ipv6Packet<B> {
256 fixed_hdr: Ref<B, FixedHeader>,
257 extension_hdrs: Records<B, Ipv6ExtensionHeaderImpl>,
258 body: B,
259 proto: Ipv6Proto,
260}
261
262impl<B: SplitByteSlice, I: IpExt> GenericOverIp<I> for Ipv6Packet<B> {
263 type Type = <I as IpExt>::Packet<B>;
264}
265
266impl<B: SplitByteSlice> Ipv6Header for Ipv6Packet<B> {
267 fn get_fixed_header(&self) -> &FixedHeader {
268 &self.fixed_hdr
269 }
270}
271
272impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv6Packet<B> {
273 type Error = Ipv6ParseError;
274
275 fn parse_metadata(&self) -> ParseMetadata {
276 let header_len = Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.bytes().len();
277 ParseMetadata::from_packet(header_len, self.body.len(), 0)
278 }
279
280 fn parse<BV: BufferView<B>>(buffer: BV, _args: ()) -> Result<Self, Ipv6ParseError> {
281 Ipv6PacketRaw::parse(buffer, ()).and_then(Ipv6Packet::try_from_raw)
282 }
283}
284
285impl<B: SplitByteSlice> FromRaw<Ipv6PacketRaw<B>, ()> for Ipv6Packet<B> {
286 type Error = Ipv6ParseError;
287
288 fn try_from_raw_with(raw: Ipv6PacketRaw<B>, _args: ()) -> Result<Self, Self::Error> {
289 let fixed_hdr = raw.fixed_hdr;
290
291 let extension_hdrs = match raw.extension_hdrs {
292 MaybeParsed::Complete(v) => Records::try_from_raw(v),
293 MaybeParsed::Incomplete(buffer) => {
294 let context = Ipv6ExtensionHeaderParsingContext::new(fixed_hdr.next_hdr);
298 match Records::<_, Ipv6ExtensionHeaderImpl>::parse_with_context(buffer, context) {
299 Err(err) => Err(err),
300 Ok(_) => panic!("Extension Header parsing succeeded after raw parse failure."),
301 }
302 }
303 };
304 let extension_hdrs = extension_hdrs.map_err(|e| ext_hdr_err_fn(&fixed_hdr, e))?;
305
306 let (body, proto) =
310 raw.body_proto.expect("Unable to retrieve Ipv6Proto or MaybeParsed body from raw");
311 debug_assert!(is_valid_next_header_upper_layer(proto.into()));
312
313 let body = match body {
314 MaybeParsed::Complete(b) => b,
315 MaybeParsed::Incomplete(_b) => {
316 return debug_err!(Err(ParseError::Format.into()), "IPv6 body unretrievable.");
317 }
318 };
319
320 if extension_hdrs.bytes().len() + body.len() != usize::from(fixed_hdr.payload_len.get()) {
325 return debug_err!(
326 Err(ParseError::Format.into()),
327 "Payload len does not match body and extension headers"
328 );
329 }
330
331 if fixed_hdr.version() != 6 {
333 return debug_err!(
334 Err(ParseError::Format.into()),
335 "unexpected IP version: {}",
336 fixed_hdr.version()
337 );
338 }
339
340 Ok(Ipv6Packet { fixed_hdr, extension_hdrs, body, proto })
341 }
342}
343
344impl<B, C> PartialSerializer<C> for Ipv6Packet<B>
345where
346 B: SplitByteSlice,
347 C: IpSerializationContext<Ipv6>,
348{
349 fn partial_serialize_new_buf<BB: GrowBufferMut, A: LayoutBufferAlloc<BB>>(
354 &self,
355 _context: &mut C,
356 constraints: PacketConstraints,
357 alloc: A,
358 ) -> Result<(BB, usize), SerializeError<A::Error>> {
359 let fixed_hdr = Ref::bytes(&self.fixed_hdr);
362 let extension_hdrs = self.extension_hdrs.bytes();
363 let fixed_hdr_len = fixed_hdr.len();
364 let header_len = fixed_hdr_len + extension_hdrs.len();
365 let body_to_copy = self.body().len().min(TRANSPORT_HEADER_MAX_SIZE);
366 let outer_header_len = constraints.header_len();
367 let mut buffer = alloc.layout_alloc(outer_header_len + header_len, body_to_copy, 0)?;
368 buffer.with_parts_mut(|prefix, mut body, _suffix| {
369 let extensions_pos = outer_header_len + fixed_hdr_len;
370 prefix[outer_header_len..extensions_pos].copy_from_slice(fixed_hdr);
371 prefix[extensions_pos..].copy_from_slice(extension_hdrs);
372 body.copy_from_slice(&self.body()[..body_to_copy]);
373 });
374 buffer.grow_front(header_len);
375 let total_size = header_len + self.body.len();
376 Ok((buffer, total_size))
377 }
378}
379
380impl<B: SplitByteSlice> Ipv6Packet<B> {
381 pub fn iter_extension_hdrs(&self) -> impl Iterator<Item = Ipv6ExtensionHeader<'_>> {
383 self.extension_hdrs.iter()
384 }
385
386 pub fn body(&self) -> &[u8] {
388 &self.body
389 }
390
391 pub fn dscp_and_ecn(&self) -> DscpAndEcn {
394 self.fixed_hdr.dscp_and_ecn()
395 }
396
397 pub fn flowlabel(&self) -> u32 {
399 self.fixed_hdr.flowlabel()
400 }
401
402 pub fn proto(&self) -> Ipv6Proto {
408 self.proto
409 }
410
411 pub fn src_ipv6(&self) -> Option<Ipv6SourceAddr> {
418 Ipv6SourceAddr::new(self.fixed_hdr.src_ip)
419 }
420
421 pub fn copy_header_bytes_for_fragment(&self) -> Vec<u8> {
432 let expected_bytes_len = self.header_len() - IPV6_FRAGMENT_EXT_HDR_LEN;
435 let mut bytes = Vec::with_capacity(expected_bytes_len);
436
437 bytes.extend_from_slice(Ref::bytes(&self.fixed_hdr));
438
439 let mut iter = self.extension_hdrs.iter();
443
444 let ext_hdr = iter.next().expect("packet must have at least one extension header");
448
449 if self.fixed_hdr.next_hdr == Ipv6ExtHdrType::Fragment.into() {
450 bytes[6] = iter.context().next_header;
456
457 bytes.extend_from_slice(&self.extension_hdrs.bytes()[IPV6_FRAGMENT_EXT_HDR_LEN..]);
459 } else {
460 let mut ext_hdr = ext_hdr;
461 let mut ext_hdr_start = IPV6_FIXED_HDR_LEN;
462 let mut ext_hdr_end = iter.context().position;
463
464 loop {
470 let next_ext_hdr = iter
476 .next()
477 .expect("exhausted all extension headers without finding fragment header");
478
479 if let Ipv6ExtensionHeader::Fragment { .. } = next_ext_hdr {
480 let fragment_hdr_start = ext_hdr_end - IPV6_FIXED_HDR_LEN;
487
488 let fragment_hdr_end = fragment_hdr_start + IPV6_FRAGMENT_EXT_HDR_LEN;
490 assert_eq!(fragment_hdr_end, iter.context().position - IPV6_FIXED_HDR_LEN);
491
492 let extension_hdr_bytes = self.extension_hdrs.bytes();
493
494 bytes.extend_from_slice(&extension_hdr_bytes[..fragment_hdr_start]);
496
497 bytes.extend_from_slice(&extension_hdr_bytes[fragment_hdr_end..]);
499
500 match ext_hdr {
503 Ipv6ExtensionHeader::HopByHopOptions { .. }
506 | Ipv6ExtensionHeader::DestinationOptions { .. }
507 | Ipv6ExtensionHeader::Routing { .. } => {
508 bytes[ext_hdr_start] = iter.context().next_header;
509 }
510 Ipv6ExtensionHeader::Fragment { .. } => unreachable!(
511 "If we had a fragment header before `ext_hdr`, we should have used that instead"
512 ),
513 }
514
515 break;
516 }
517
518 ext_hdr = next_ext_hdr;
519 ext_hdr_start = ext_hdr_end;
520 ext_hdr_end = iter.context().position;
521 }
522 }
523
524 assert_eq!(bytes.len(), expected_bytes_len);
526 bytes
527 }
528
529 fn header_len(&self) -> usize {
530 Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.bytes().len()
531 }
532
533 fn fragment_header_present(&self) -> bool {
534 for ext_hdr in self.extension_hdrs.iter() {
535 if matches!(ext_hdr, Ipv6ExtensionHeader::Fragment { .. }) {
536 return true;
537 }
538 }
539 false
540 }
541
542 pub fn builder(&self) -> Ipv6PacketBuilder {
544 Ipv6PacketBuilder {
545 dscp_and_ecn: self.dscp_and_ecn(),
546 flowlabel: self.flowlabel(),
547 hop_limit: self.hop_limit(),
548 proto: self.proto(),
549 src_ip: self.src_ip(),
550 dst_ip: self.dst_ip(),
551 }
552 }
553
554 pub fn nat64_translate(
580 &self,
581 v4_src_addr: Ipv4Addr,
582 v4_dst_addr: Ipv4Addr,
583 ) -> Nat64TranslationResult<
584 impl Serializer<NoOpSerializationContext, Buffer = EmptyBuf> + Debug + '_,
585 Nat64Error,
586 > {
587 #[derive(Debug)]
590 enum Nat64Serializer<T, U, O> {
591 Tcp(T),
592 Udp(U),
593 Other(O),
594 }
595 impl<T, U, O> Serializer<NoOpSerializationContext> for Nat64Serializer<T, U, O>
596 where
597 T: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
598 U: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
599 O: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
600 {
601 type Buffer = EmptyBuf;
602 fn serialize<B, P>(
603 self,
604 context: &mut NoOpSerializationContext,
605 outer: PacketConstraints,
606 provider: P,
607 ) -> Result<B, (SerializeError<P::Error>, Self)>
608 where
609 B: GrowBufferMut,
610 P: BufferProvider<Self::Buffer, B>,
611 {
612 match self {
613 Nat64Serializer::Tcp(serializer) => serializer
614 .serialize(context, outer, provider)
615 .map_err(|(err, ser)| (err, Nat64Serializer::Tcp(ser))),
616 Nat64Serializer::Udp(serializer) => serializer
617 .serialize(context, outer, provider)
618 .map_err(|(err, ser)| (err, Nat64Serializer::Udp(ser))),
619 Nat64Serializer::Other(serializer) => serializer
620 .serialize(context, outer, provider)
621 .map_err(|(err, ser)| (err, Nat64Serializer::Other(ser))),
622 }
623 }
624
625 fn serialize_new_buf<B: GrowBufferMut, A: LayoutBufferAlloc<B>>(
626 &self,
627 context: &mut NoOpSerializationContext,
628 outer: PacketConstraints,
629 alloc: A,
630 ) -> Result<B, SerializeError<A::Error>> {
631 match self {
632 Nat64Serializer::Tcp(serializer) => {
633 serializer.serialize_new_buf(context, outer, alloc)
634 }
635 Nat64Serializer::Udp(serializer) => {
636 serializer.serialize_new_buf(context, outer, alloc)
637 }
638 Nat64Serializer::Other(serializer) => {
639 serializer.serialize_new_buf(context, outer, alloc)
640 }
641 }
642 }
643 }
644
645 impl<T, U, O> NestableSerializer for Nat64Serializer<T, U, O>
646 where
647 T: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
648 U: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
649 O: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
650 {
651 }
652
653 if self.fragment_header_present() {
656 return Nat64TranslationResult::Err(Nat64Error::NotImplemented);
657 }
658
659 let v4_builder = |v4_proto| {
660 let mut builder =
661 Ipv4PacketBuilder::new(v4_src_addr, v4_dst_addr, self.hop_limit(), v4_proto);
662 builder.dscp_and_ecn(self.dscp_and_ecn());
663
664 const IPV4_HEADER_LEN_BYTES: usize = HDR_PREFIX_LEN;
669
670 builder.df_flag(self.body().len() + IPV4_HEADER_LEN_BYTES > 1260);
676
677 builder.fragment_offset(FragmentOffset::ZERO);
680 builder.mf_flag(false);
681
682 builder
683 };
684
685 match self.proto() {
686 Ipv6Proto::Proto(IpProto::Tcp) => {
687 let v4_pkt_builder = v4_builder(Ipv4Proto::Proto(IpProto::Tcp));
688 let args = TcpParseArgs::new(self.src_ip(), self.dst_ip());
689 match TcpSegment::parse(&mut self.body.as_bytes(), args) {
694 Ok(tcp) => {
695 let tcp_serializer =
699 Nat64Serializer::Tcp(tcp.into_serializer(v4_src_addr, v4_dst_addr));
700 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(tcp_serializer))
701 }
702 Err(msg) => {
703 debug!("Parsing of TCP segment failed: {:?}", msg);
704
705 let common_serializer =
714 Nat64Serializer::Other(self.body().into_serializer());
715 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
716 }
717 }
718 }
719
720 Ipv6Proto::Proto(IpProto::Udp) => {
725 let v4_pkt_builder = v4_builder(Ipv4Proto::Proto(IpProto::Udp));
726 let args = UdpParseArgs::new(self.src_ip(), self.dst_ip());
727 match UdpPacket::parse(&mut self.body.as_bytes(), args) {
728 Ok(udp) => {
729 let udp_serializer =
733 Nat64Serializer::Udp(udp.into_serializer(v4_src_addr, v4_dst_addr));
734 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(udp_serializer))
735 }
736 Err(msg) => {
737 debug!("Parsing of UDP packet failed: {:?}", msg);
738
739 let common_serializer =
749 Nat64Serializer::Other(self.body().into_serializer());
750 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
751 }
752 }
753 }
754
755 Ipv6Proto::Icmpv6 => Nat64TranslationResult::Err(Nat64Error::NotImplemented),
758
759 Ipv6Proto::Other(val) => {
779 let v4_pkt_builder = v4_builder(Ipv4Proto::Other(val));
780 let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
781 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
782 }
783
784 Ipv6Proto::NoNextHeader => {
785 let v4_pkt_builder = v4_builder(Ipv4Proto::Other(Ipv6Proto::NoNextHeader.into()));
786 let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
787 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
788 }
789
790 Ipv6Proto::Proto(IpProto::Reserved) => Nat64TranslationResult::Drop,
793 }
794 }
795
796 pub fn to_vec(&self) -> Vec<u8> {
798 let Ipv6Packet { fixed_hdr, extension_hdrs, body, proto: _ } = self;
799 let mut buf = Vec::with_capacity(
800 Ref::bytes(&fixed_hdr).len() + extension_hdrs.bytes().len() + body.as_bytes().len(),
801 );
802 buf.extend(Ref::bytes(&fixed_hdr));
803 buf.extend(extension_hdrs.bytes());
804 buf.extend(body.as_bytes());
805 buf
806 }
807}
808
809impl<B: SplitByteSliceMut> Ipv6Packet<B> {
810 pub fn set_src_ip(&mut self, addr: Ipv6Addr) {
812 self.fixed_hdr.src_ip = addr;
813 }
814
815 pub fn set_dst_ip(&mut self, addr: Ipv6Addr) {
817 self.fixed_hdr.dst_ip = addr;
818 }
819
820 pub fn set_hop_limit(&mut self, hlim: u8) {
822 self.fixed_hdr.hop_limit = hlim;
823 }
824
825 pub fn body_mut(&mut self) -> &mut [u8] {
827 &mut self.body
828 }
829
830 pub fn parts_with_body_mut(&mut self) -> (&FixedHeader, ExtensionHeaders<'_>, &mut [u8]) {
833 (&self.fixed_hdr, ExtensionHeaders(self.extension_hdrs.as_ref()), &mut self.body)
834 }
835}
836
837impl<B: SplitByteSlice> Debug for Ipv6Packet<B> {
838 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
839 f.debug_struct("Ipv6Packet")
840 .field("src_ip", &self.src_ip())
841 .field("dst_ip", &self.dst_ip())
842 .field("hop_limit", &self.hop_limit())
843 .field("proto", &self.proto())
844 .field("dscp", &self.dscp_and_ecn().dscp())
845 .field("ecn", &self.dscp_and_ecn().ecn())
846 .field("flowlabel", &self.flowlabel())
847 .field("extension headers", &"TODO")
848 .field("body", &alloc::format!("<{} bytes>", self.body.len()))
849 .finish()
850 }
851}
852
853pub struct ExtensionHeaders<'a>(Records<&'a [u8], Ipv6ExtensionHeaderImpl>);
855
856impl<'a> ExtensionHeaders<'a> {
857 pub fn iter(&self) -> impl Iterator<Item = Ipv6ExtensionHeader<'_>> {
859 self.0.iter()
860 }
861
862 pub fn bytes(&self) -> &[u8] {
864 self.0.bytes()
865 }
866}
867
868#[derive(Copy, Clone, Debug, Eq, PartialEq)]
874pub struct ExtHdrParseError;
875
876pub struct Ipv6PacketRaw<B> {
886 fixed_hdr: Ref<B, FixedHeader>,
888 extension_hdrs: MaybeParsed<RecordsRaw<B, Ipv6ExtensionHeaderImpl>, B>,
894 body_proto: Result<(MaybeParsed<B, B>, Ipv6Proto), ExtHdrParseError>,
907}
908
909impl<B> Ipv6PacketRaw<B> {
910 pub fn body_mut(&mut self) -> Option<&mut B> {
914 match self.body_proto {
915 Ok(ref mut b) => match b {
916 (MaybeParsed::Complete(b), _) => Some(b),
917 (MaybeParsed::Incomplete(b), _) => Some(b),
918 },
919 Err(_) => None,
920 }
921 }
922}
923
924impl<B: SplitByteSlice> Ipv6Header for Ipv6PacketRaw<B> {
925 fn get_fixed_header(&self) -> &FixedHeader {
926 &self.fixed_hdr
927 }
928}
929
930impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv6PacketRaw<B> {
931 type Error = Ipv6ParseError;
932
933 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> Result<Self, Self::Error> {
934 let fixed_hdr = buffer
935 .take_obj_front::<FixedHeader>()
936 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for header"))?;
937 let payload_len = fixed_hdr.payload_len.get().into();
938 let _: Option<B> = buffer.len().checked_sub(payload_len).map(|padding| {
940 buffer.take_back(padding).unwrap_or_else(|| {
941 panic!("buffer.len()={} padding={}", buffer.len(), padding);
942 })
943 });
944
945 let mut extension_hdr_context = Ipv6ExtensionHeaderParsingContext::new(fixed_hdr.next_hdr);
946
947 let extension_hdrs =
948 RecordsRaw::parse_raw_with_mut_context(&mut buffer, &mut extension_hdr_context)
949 .map_incomplete(|(b, _)| b);
950
951 let body_proto = match &extension_hdrs {
952 MaybeParsed::Complete(r) => {
953 let _: &RecordsRaw<B, _> = r;
954 assert!(is_valid_next_header_upper_layer(extension_hdr_context.next_header));
975 let proto = Ipv6Proto::from(extension_hdr_context.next_header);
976 let body = MaybeParsed::new_with_min_len(
977 buffer.into_rest(),
978 payload_len.saturating_sub(extension_hdrs.len()),
979 );
980 Ok((body, proto))
981 }
982 MaybeParsed::Incomplete(b) => {
983 let _: &B = b;
984 Err(ExtHdrParseError)
985 }
986 };
987
988 Ok(Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto })
989 }
990
991 fn parse_metadata(&self) -> ParseMetadata {
992 let header_len = Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.len();
993 let body_len = self.body_proto.as_ref().map(|(b, _p)| b.len()).unwrap_or(0);
994 ParseMetadata::from_packet(header_len, body_len, 0)
995 }
996}
997
998impl<B: SplitByteSlice> Ipv6PacketRaw<B> {
999 pub fn body_proto(&self) -> Result<(MaybeParsed<&[u8], &[u8]>, Ipv6Proto), ExtHdrParseError> {
1012 self.body_proto
1013 .as_ref()
1014 .map(|(mp, proto)| {
1015 (mp.as_ref().map(|b| b.deref()).map_incomplete(|b| b.deref()), *proto)
1016 })
1017 .map_err(|e| *e)
1018 }
1019
1020 pub fn body(&self) -> Result<MaybeParsed<&[u8], &[u8]>, ExtHdrParseError> {
1031 self.body_proto().map(|(body, _proto)| body)
1032 }
1033
1034 pub fn proto(&self) -> Result<Ipv6Proto, ExtHdrParseError> {
1041 self.body_proto().map(|(_body, proto)| proto)
1042 }
1043}
1044
1045impl<B: SplitByteSliceMut> Ipv6PacketRaw<B> {
1046 pub fn set_src_ip(&mut self, addr: Ipv6Addr) {
1048 self.fixed_hdr.src_ip = addr;
1049 }
1050
1051 pub fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1053 self.fixed_hdr.dst_ip = addr;
1054 }
1055}
1056
1057pub enum NextHeader {
1060 NextLayer(Ipv6Proto),
1062 Extension(Ipv6ExtHdrType),
1064}
1065
1066impl From<NextHeader> for u8 {
1067 fn from(next_hdr: NextHeader) -> Self {
1068 match next_hdr {
1069 NextHeader::NextLayer(n) => n.into(),
1070 NextHeader::Extension(e) => e.into(),
1071 }
1072 }
1073}
1074
1075mod sealed {
1076 use super::*;
1077 pub trait Ipv6HeaderBefore<T> {}
1085
1086 impl<'a, O, T> Ipv6HeaderBefore<T> for &'a O where O: Ipv6HeaderBefore<T> {}
1087
1088 pub trait Ipv6HeaderBuilder {
1090 fn fixed_header(&self) -> &Ipv6PacketBuilder;
1092
1093 fn extension_headers_len(&self) -> usize;
1096
1097 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1102 &self,
1103 buffer: &mut BV,
1104 next_header: NextHeader,
1105 payload_len: usize,
1106 );
1107 }
1108}
1109use sealed::{Ipv6HeaderBefore, Ipv6HeaderBuilder};
1110
1111impl<'a, O> Ipv6HeaderBuilder for &'a O
1112where
1113 O: Ipv6HeaderBuilder,
1114{
1115 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1116 O::fixed_header(self)
1117 }
1118
1119 fn extension_headers_len(&self) -> usize {
1120 O::extension_headers_len(self)
1121 }
1122
1123 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1124 &self,
1125 buffer: &mut BV,
1126 next_header: NextHeader,
1127 payload_len: usize,
1128 ) {
1129 O::serialize_header(self, buffer, next_header, payload_len)
1130 }
1131}
1132
1133macro_rules! impl_packet_builder_base {
1138 {} => {
1139 fn constraints(&self) -> PacketConstraints {
1140 let ext_headers = self.extension_headers_len();
1141 let header_len = IPV6_FIXED_HDR_LEN + ext_headers;
1142 let footer_len = 0;
1143 let min_body_len = 0;
1144 let max_body_len = IPV6_MAX_PAYLOAD_LENGTH - ext_headers;
1147 PacketConstraints::new(header_len, footer_len, min_body_len, max_body_len)
1148 }
1149 }
1150}
1151
1152macro_rules! impl_packet_builder {
1153 {} => {
1154 fn context_state(&self) -> C::ContextState {
1155 C::envelope_to_state(IpEnvelope::new(self.extension_headers_len() > 0))
1156 }
1157
1158 fn serialize(
1159 &self,
1160 _context: &mut C,
1161 target: &mut SerializeTarget<'_>,
1162 body: FragmentedBytesMut<'_, '_>,
1163 ) {
1164 let mut bv = &mut target.header;
1165 self.serialize_header(
1166 &mut bv,
1167 NextHeader::NextLayer(
1168 <Ipv6PacketBuilder as IpPacketBuilder<C, Ipv6>>::proto(self.fixed_header())
1169 ),
1170 body.len(),
1171 );
1172 }
1173 }
1174}
1175
1176macro_rules! impl_partial_packet_builder {
1177 {} => {
1178 fn partial_serialize(
1179 &self,
1180 _context: &mut C,
1181 body_len: usize,
1182 mut buffer: &mut [u8],
1183 ) {
1184 self.serialize_header(
1185 &mut &mut buffer,
1186 NextHeader::NextLayer(
1187 <Ipv6PacketBuilder as IpPacketBuilder<C, Ipv6>>::proto(self.fixed_header())
1188 ),
1189 body_len,
1190 );
1191 }
1192 }
1193}
1194#[derive(Debug, Clone, Eq, PartialEq)]
1196pub struct Ipv6PacketBuilder {
1197 dscp_and_ecn: DscpAndEcn,
1198 flowlabel: u32,
1199 hop_limit: u8,
1200 proto: Ipv6Proto,
1203 src_ip: Ipv6Addr,
1204 dst_ip: Ipv6Addr,
1205}
1206
1207impl Ipv6PacketBuilder {
1208 pub fn new<S: Into<Ipv6Addr>, D: Into<Ipv6Addr>>(
1214 src_ip: S,
1215 dst_ip: D,
1216 hop_limit: u8,
1217 proto: Ipv6Proto,
1218 ) -> Ipv6PacketBuilder {
1219 Ipv6PacketBuilder {
1220 dscp_and_ecn: DscpAndEcn::default(),
1221 flowlabel: 0,
1222 hop_limit,
1223 proto,
1224 src_ip: src_ip.into(),
1225 dst_ip: dst_ip.into(),
1226 }
1227 }
1228
1229 pub fn dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1232 self.dscp_and_ecn = dscp_and_ecn;
1233 }
1234
1235 pub fn flowlabel(&mut self, flowlabel: u32) {
1241 assert!(flowlabel <= 1 << 20, "invalid flowlabel: {:x}", flowlabel);
1242 self.flowlabel = flowlabel;
1243 }
1244}
1245
1246impl Ipv6HeaderBuilder for Ipv6PacketBuilder {
1247 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1248 self
1249 }
1250
1251 fn extension_headers_len(&self) -> usize {
1252 0
1253 }
1254
1255 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1256 &self,
1257 buffer: &mut BV,
1258 next_header: NextHeader,
1259 payload_len: usize,
1260 ) {
1261 buffer
1262 .write_obj_front(&FixedHeader::new(
1263 self.dscp_and_ecn,
1264 self.flowlabel,
1265 {
1266 debug_assert!(payload_len <= core::u16::MAX as usize);
1273 payload_len as u16
1274 },
1275 next_header.into(),
1276 self.hop_limit,
1277 self.src_ip,
1278 self.dst_ip,
1279 ))
1280 .expect("not enough bytes for IPv6 fixed header");
1281 }
1282}
1283
1284impl NestablePacketBuilder for Ipv6PacketBuilder {
1285 impl_packet_builder_base! {}
1286}
1287
1288impl<C: IpSerializationContext<Ipv6>> PacketBuilder<C> for Ipv6PacketBuilder {
1289 impl_packet_builder! {}
1290}
1291
1292impl<C: IpSerializationContext<Ipv6>> PartialPacketBuilder<C> for Ipv6PacketBuilder {
1293 impl_partial_packet_builder! {}
1294}
1295
1296#[derive(Debug, Clone)]
1298pub struct Ipv6PacketBuilderWithHbhOptions<'a, I> {
1299 prefix_builder: Ipv6PacketBuilder,
1300 hbh_options: AlignedRecordSequenceBuilder<HopByHopOption<'a>, I>,
1301}
1302
1303impl<'a, I> Ipv6PacketBuilderWithHbhOptions<'a, I>
1304where
1305 I: Iterator + Clone,
1306 I::Item: Borrow<HopByHopOption<'a>>,
1307{
1308 pub fn new<T: IntoIterator<Item = I::Item, IntoIter = I>>(
1310 prefix_builder: Ipv6PacketBuilder,
1311 options: T,
1312 ) -> Option<Ipv6PacketBuilderWithHbhOptions<'a, I>> {
1313 let iter = options.into_iter();
1314 if iter
1317 .clone()
1318 .filter(|r| matches!(r.borrow().data, HopByHopOptionData::RouterAlert { .. }))
1319 .count()
1320 > 1
1321 {
1322 return None;
1323 }
1324 let hbh_options = AlignedRecordSequenceBuilder::new(2, iter);
1325 if next_multiple_of_eight(2 + hbh_options.serialized_len()) > IPV6_HBH_OPTIONS_MAX_LEN {
1327 return None;
1328 }
1329 Some(Ipv6PacketBuilderWithHbhOptions { prefix_builder, hbh_options })
1330 }
1331
1332 fn aligned_hbh_len(&self) -> usize {
1333 let opt_len = self.hbh_options.serialized_len();
1334 let hbh_len = opt_len + 2;
1335 next_multiple_of_eight(hbh_len)
1336 }
1337}
1338
1339fn next_multiple_of_eight(x: usize) -> usize {
1340 (x + 7) & (!7)
1341}
1342
1343impl<C: IpSerializationContext<Ipv6>> IpPacketBuilder<C, Ipv6> for Ipv6PacketBuilder {
1344 fn new(src_ip: Ipv6Addr, dst_ip: Ipv6Addr, ttl: u8, proto: Ipv6Proto) -> Self {
1345 Ipv6PacketBuilder::new(src_ip, dst_ip, ttl, proto)
1346 }
1347
1348 fn src_ip(&self) -> Ipv6Addr {
1349 self.src_ip
1350 }
1351
1352 fn set_src_ip(&mut self, addr: Ipv6Addr) {
1353 self.src_ip = addr;
1354 }
1355
1356 fn dst_ip(&self) -> Ipv6Addr {
1357 self.dst_ip
1358 }
1359
1360 fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1361 self.dst_ip = addr;
1362 }
1363
1364 fn proto(&self) -> Ipv6Proto {
1365 self.proto
1366 }
1367
1368 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1369 self.dscp_and_ecn = dscp_and_ecn;
1370 }
1371}
1372
1373impl<'a, I> Ipv6HeaderBuilder for Ipv6PacketBuilderWithHbhOptions<'a, I>
1374where
1375 I: Iterator + Clone,
1376 I::Item: Borrow<HopByHopOption<'a>>,
1377{
1378 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1379 &self.prefix_builder
1380 }
1381
1382 fn extension_headers_len(&self) -> usize {
1383 self.prefix_builder.extension_headers_len() + self.aligned_hbh_len()
1384 }
1385
1386 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1387 &self,
1388 buffer: &mut BV,
1389 next_header: NextHeader,
1390 payload_len: usize,
1391 ) {
1392 let aligned_hbh_len = self.aligned_hbh_len();
1393 self.prefix_builder.serialize_header(
1395 buffer,
1396 NextHeader::Extension(Ipv6ExtHdrType::HopByHopOptions),
1397 payload_len + aligned_hbh_len,
1398 );
1399 let mut hbh_header = buffer.take_front(aligned_hbh_len).unwrap();
1401 let hbh_header = hbh_header.as_mut();
1402 hbh_header[0] = next_header.into();
1403 hbh_header[1] = u8::try_from((aligned_hbh_len - 8) / 8).expect("extension header too big");
1404 self.hbh_options.serialize_into(&mut hbh_header[2..]);
1405 }
1406}
1407
1408impl<'a, I> NestablePacketBuilder for Ipv6PacketBuilderWithHbhOptions<'a, I>
1409where
1410 I: Iterator + Clone,
1411 I::Item: Borrow<HopByHopOption<'a>>,
1412{
1413 impl_packet_builder_base! {}
1414}
1415
1416impl<'a, I, C: IpSerializationContext<Ipv6>> PacketBuilder<C>
1417 for Ipv6PacketBuilderWithHbhOptions<'a, I>
1418where
1419 I: Iterator + Clone,
1420 I::Item: Borrow<HopByHopOption<'a>>,
1421{
1422 impl_packet_builder! {}
1423}
1424
1425impl<'a, I, C: IpSerializationContext<Ipv6>> PartialPacketBuilder<C>
1426 for Ipv6PacketBuilderWithHbhOptions<'a, I>
1427where
1428 I: Iterator + Clone,
1429 I::Item: Borrow<HopByHopOption<'a>>,
1430{
1431 impl_partial_packet_builder! {}
1432}
1433
1434impl<'a, C: IpSerializationContext<Ipv6>, I> IpPacketBuilder<C, Ipv6>
1435 for Ipv6PacketBuilderWithHbhOptions<'a, I>
1436where
1437 I: Iterator<Item: Borrow<HopByHopOption<'a>>> + Debug + Default + Clone,
1438{
1439 fn new(src_ip: Ipv6Addr, dst_ip: Ipv6Addr, ttl: u8, proto: Ipv6Proto) -> Self {
1440 Ipv6PacketBuilderWithHbhOptions::new(
1441 Ipv6PacketBuilder::new(src_ip, dst_ip, ttl, proto),
1442 I::default(),
1443 )
1444 .expect("packet builder with no options should be valid")
1445 }
1446
1447 fn src_ip(&self) -> Ipv6Addr {
1448 self.prefix_builder.src_ip
1449 }
1450
1451 fn set_src_ip(&mut self, addr: Ipv6Addr) {
1452 self.prefix_builder.src_ip = addr;
1453 }
1454
1455 fn dst_ip(&self) -> Ipv6Addr {
1456 self.prefix_builder.dst_ip
1457 }
1458
1459 fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1460 self.prefix_builder.dst_ip = addr;
1461 }
1462
1463 fn proto(&self) -> Ipv6Proto {
1464 self.prefix_builder.proto
1465 }
1466
1467 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1468 <Ipv6PacketBuilder as IpPacketBuilder<C, Ipv6>>::set_dscp_and_ecn(
1469 &mut self.prefix_builder,
1470 dscp_and_ecn,
1471 )
1472 }
1473}
1474
1475#[derive(Debug, Eq, PartialEq)]
1484pub struct Ipv6PacketBuilderWithFragmentHeader<B> {
1485 header_builder: B,
1486 fragment_offset: FragmentOffset,
1487 more_fragments: bool,
1488 identification: u32,
1489}
1490
1491impl<B: Ipv6HeaderBefore<Self>> Ipv6PacketBuilderWithFragmentHeader<B> {
1492 pub fn new(
1494 header_builder: B,
1495 fragment_offset: FragmentOffset,
1496 more_fragments: bool,
1497 identification: u32,
1498 ) -> Self {
1499 Self { header_builder, fragment_offset, more_fragments, identification }
1500 }
1501}
1502
1503impl<B> Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>> for Ipv6PacketBuilder {}
1504impl<B, I> Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>>
1505 for Ipv6PacketBuilderWithHbhOptions<'_, I>
1506{
1507}
1508
1509pub trait Ipv6PacketBuilderBeforeFragment:
1512 Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<Self>> + Ipv6HeaderBuilder + Sized
1513{
1514}
1515impl<B> Ipv6PacketBuilderBeforeFragment for B where
1516 B: Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<Self>> + Ipv6HeaderBuilder + Sized
1517{
1518}
1519
1520impl<B: Ipv6HeaderBuilder> Ipv6HeaderBuilder for Ipv6PacketBuilderWithFragmentHeader<B> {
1521 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1522 self.header_builder.fixed_header()
1523 }
1524
1525 fn extension_headers_len(&self) -> usize {
1526 self.header_builder.extension_headers_len() + IPV6_FRAGMENT_EXT_HDR_LEN
1527 }
1528
1529 fn serialize_header<BB: SplitByteSliceMut, BV: BufferViewMut<BB>>(
1530 &self,
1531 buffer: &mut BV,
1532 next_header: NextHeader,
1533 payload_len: usize,
1534 ) {
1535 let Self { header_builder, fragment_offset, more_fragments, identification } = self;
1536 let payload_len = payload_len + IPV6_FRAGMENT_EXT_HDR_LEN;
1537 header_builder.serialize_header(
1538 buffer,
1539 NextHeader::Extension(Ipv6ExtHdrType::Fragment),
1540 payload_len,
1541 );
1542 buffer.write_obj_front(&u8::from(next_header)).unwrap();
1543 let _: BB = buffer.take_front_zero(1).unwrap();
1545 let more_fragments = u16::from(*more_fragments);
1546 buffer
1547 .write_obj_front(&U16::new(fragment_offset.into_raw() << 3 | more_fragments))
1548 .unwrap();
1549 buffer.write_obj_front(&U32::new(*identification)).unwrap();
1550 }
1551}
1552
1553impl<B: Ipv6HeaderBuilder> NestablePacketBuilder for Ipv6PacketBuilderWithFragmentHeader<B> {
1554 impl_packet_builder_base! {}
1555}
1556
1557impl<B: Ipv6HeaderBuilder, C: IpSerializationContext<Ipv6>> PacketBuilder<C>
1558 for Ipv6PacketBuilderWithFragmentHeader<B>
1559{
1560 impl_packet_builder! {}
1561}
1562
1563impl<B: Ipv6HeaderBuilder, C: IpSerializationContext<Ipv6>> PartialPacketBuilder<C>
1564 for Ipv6PacketBuilderWithFragmentHeader<B>
1565{
1566 impl_partial_packet_builder! {}
1567}
1568
1569pub(crate) fn reassemble_fragmented_packet<
1575 B: SplitByteSliceMut,
1576 BV: BufferViewMut<B>,
1577 I: Iterator<Item = Vec<u8>>,
1578>(
1579 mut buffer: BV,
1580 header: Vec<u8>,
1581 body_fragments: I,
1582) -> IpParseResult<Ipv6, ()> {
1583 assert!(header.len() >= IPV6_FIXED_HDR_LEN);
1584
1585 let bytes = buffer.as_mut();
1586
1587 bytes[0..header.len()].copy_from_slice(&header[..]);
1589 let mut byte_count = header.len();
1590
1591 for p in body_fragments {
1593 bytes[byte_count..byte_count + p.len()].copy_from_slice(&p[..]);
1594 byte_count += p.len();
1595 }
1596
1597 let payload_length = byte_count - IPV6_FIXED_HDR_LEN;
1609
1610 if payload_length > usize::from(core::u16::MAX) {
1613 return debug_err!(
1614 Err(ParseError::Format.into()),
1615 "fragmented packet payload length of {} bytes is too large",
1616 payload_length
1617 );
1618 }
1619
1620 let mut header = Ref::<_, FixedHeader>::from_prefix(bytes).unwrap().0;
1623
1624 header.payload_len.set(u16::try_from(payload_length).unwrap());
1626
1627 Ok(())
1628}
1629
1630#[cfg(test)]
1631mod tests {
1632 use assert_matches::assert_matches;
1633 use packet::{Buf, FragmentedBuffer, ParseBuffer, PartialSerializeResult};
1634 use test_case::test_case;
1635
1636 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1637 use crate::testutil::*;
1638
1639 use super::ext_hdrs::*;
1640 use super::*;
1641
1642 const DEFAULT_SRC_IP: Ipv6Addr =
1643 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1644 const DEFAULT_DST_IP: Ipv6Addr =
1645 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1646
1647 const DEFAULT_V4_SRC_IP: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1648 const DEFAULT_V4_DST_IP: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1649
1650 #[test]
1651 fn test_parse_serialize_full_tcp() {
1652 use crate::testdata::syn_v6::*;
1653
1654 let mut buf = ETHERNET_FRAME.bytes;
1655 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1656 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1657
1658 let mut body = frame.body();
1659 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1660 verify_ipv6_packet(&packet, IPV6_PACKET);
1661
1662 let buffer = packet
1664 .body()
1665 .into_serializer()
1666 .wrap_in(packet.builder())
1667 .wrap_in(frame.builder())
1668 .serialize_vec_outer(&mut NoOpSerializationContext)
1669 .unwrap();
1670 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1671
1672 assert_eq!(&packet.to_vec()[..], IPV6_PACKET.bytes);
1674 }
1675
1676 #[test]
1677 fn test_parse_serialize_full_udp() {
1678 use crate::testdata::dns_request_v6::*;
1679
1680 let mut buf = ETHERNET_FRAME.bytes;
1681 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1682 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1683
1684 let mut body = frame.body();
1685 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1686 verify_ipv6_packet(&packet, IPV6_PACKET);
1687
1688 let buffer = packet
1690 .body()
1691 .into_serializer()
1692 .wrap_in(packet.builder())
1693 .wrap_in(frame.builder())
1694 .serialize_vec_outer(&mut NoOpSerializationContext)
1695 .unwrap();
1696 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1697
1698 assert_eq!(&packet.to_vec()[..], IPV6_PACKET.bytes);
1700 }
1701
1702 #[test]
1703 fn test_parse_serialize_with_extension_headers() {
1704 use crate::testdata::mld_router_report::*;
1707
1708 let mut buf = REPORT;
1709 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1710 assert_eq!(packet.iter_extension_hdrs().count(), 1);
1711
1712 assert_eq!(&packet.to_vec()[..], REPORT);
1717 }
1718
1719 fn fixed_hdr_to_bytes(fixed_hdr: FixedHeader) -> [u8; IPV6_FIXED_HDR_LEN] {
1720 zerocopy::transmute!(fixed_hdr)
1721 }
1722
1723 fn new_fixed_hdr() -> FixedHeader {
1725 FixedHeader::new(
1726 DscpAndEcn::new(0, 2),
1727 0x77,
1728 0,
1729 IpProto::Tcp.into(),
1730 64,
1731 DEFAULT_SRC_IP,
1732 DEFAULT_DST_IP,
1733 )
1734 }
1735
1736 #[test]
1737 fn test_parse() {
1738 let mut buf = &fixed_hdr_to_bytes(new_fixed_hdr())[..];
1739 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1740 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1741 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1742 assert_eq!(packet.flowlabel(), 0x77);
1743 assert_eq!(packet.hop_limit(), 64);
1744 assert_eq!(packet.fixed_hdr.next_hdr, IpProto::Tcp.into());
1745 assert_eq!(packet.proto(), IpProto::Tcp.into());
1746 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1747 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1748 assert_eq!(packet.body(), []);
1749 }
1750
1751 #[test]
1752 fn test_parse_with_ext_hdrs() {
1753 #[rustfmt::skip]
1754 let mut buf = [
1755 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1757 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1758
1759 Ipv6ExtHdrType::Routing.into(), 0, 0, 1, 0, 1, 1, 0, Ipv6ExtHdrType::DestinationOptions.into(), 4, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
1774 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1775
1776 IpProto::Tcp.into(), 1, 0, 1, 0, 1, 1, 0, 1, 6, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
1786 ];
1787 let mut fixed_hdr = new_fixed_hdr();
1788 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
1789 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1790 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1791 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1792 let mut buf = &buf[..];
1793 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1794 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1795 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1796 assert_eq!(packet.flowlabel(), 0x77);
1797 assert_eq!(packet.hop_limit(), 64);
1798 assert_eq!(packet.fixed_hdr.next_hdr, Ipv6ExtHdrType::HopByHopOptions.into());
1799 assert_eq!(packet.proto(), IpProto::Tcp.into());
1800 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1801 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1802 assert_eq!(packet.body(), [1, 2, 3, 4, 5]);
1803 let ext_hdrs: Vec<Ipv6ExtensionHeader<'_>> = packet.iter_extension_hdrs().collect();
1804 assert_eq!(ext_hdrs.len(), 3);
1805 if let Ipv6ExtensionHeader::HopByHopOptions { options } = &ext_hdrs[0] {
1807 assert_eq!(options.iter().count(), 0);
1809 } else {
1810 panic!("Should have matched HopByHopOptions!");
1811 }
1812
1813 if let Ipv6ExtensionHeader::Routing { routing_data } = &ext_hdrs[1] {
1815 assert_eq!(routing_data.routing_type(), Err(RoutingTypeParseError::UnsupportedType(0)));
1816 assert_eq!(routing_data.segments_left(), 0);
1817 } else {
1818 panic!("Should have matched RoutingExtensionHeader: {:?}", &ext_hdrs[1]);
1819 }
1820
1821 if let Ipv6ExtensionHeader::DestinationOptions { options } = &ext_hdrs[2] {
1823 assert_eq!(options.iter().count(), 0);
1825 } else {
1826 panic!("Should have matched DestinationOptions!");
1827 }
1828
1829 #[rustfmt::skip]
1831 let mut buf = [
1832 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1834 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1835
1836 Ipv6Proto::NoNextHeader.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
1845 ];
1846 let mut fixed_hdr = new_fixed_hdr();
1847 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
1848 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1849 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1850 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1851 let mut buf = &buf[..];
1852 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1853 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1854 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1855 assert_eq!(packet.flowlabel(), 0x77);
1856 assert_eq!(packet.hop_limit(), 64);
1857 assert_eq!(packet.fixed_hdr.next_hdr, Ipv6ExtHdrType::HopByHopOptions.into());
1858 assert_eq!(packet.proto(), Ipv6Proto::NoNextHeader);
1859 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1860 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1861 assert_eq!(packet.body(), [1, 2, 3, 4, 5]);
1862 let ext_hdrs: Vec<Ipv6ExtensionHeader<'_>> = packet.iter_extension_hdrs().collect();
1863 assert_eq!(ext_hdrs.len(), 1);
1864 if let Ipv6ExtensionHeader::HopByHopOptions { options } = &ext_hdrs[0] {
1866 assert_eq!(options.iter().count(), 0);
1868 } else {
1869 panic!("Should have matched HopByHopOptions!");
1870 }
1871 }
1872
1873 #[test]
1874 fn test_parse_error() {
1875 let mut fixed_hdr = new_fixed_hdr();
1877 fixed_hdr.version_tc_flowlabel[0] = 0x50;
1878 assert_eq!(
1879 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1880 ParseError::Format.into()
1881 );
1882
1883 let mut fixed_hdr = new_fixed_hdr();
1885 fixed_hdr.payload_len = U16::new(2);
1886 assert_eq!(
1887 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1888 ParseError::Format.into()
1889 );
1890
1891 let mut fixed_hdr = new_fixed_hdr();
1893 fixed_hdr.next_hdr = 255;
1894 let packet = fixed_hdr_to_bytes(fixed_hdr);
1895
1896 assert!((&packet[..]).parse::<Ipv6PacketRaw<_>>().is_ok());
1898
1899 assert_eq!(
1901 (&packet[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1902 Ipv6ParseError::ParameterProblem {
1903 src_ip: DEFAULT_SRC_IP,
1904 dst_ip: DEFAULT_DST_IP,
1905 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1906 pointer: u32::from(NEXT_HEADER_OFFSET),
1907 must_send_icmp: false,
1908 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1909 }
1910 );
1911
1912 let mut fixed_hdr = new_fixed_hdr();
1914 fixed_hdr.next_hdr = Ipv4Proto::Icmp.into();
1915 assert_eq!(
1916 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1917 Ipv6ParseError::ParameterProblem {
1918 src_ip: DEFAULT_SRC_IP,
1919 dst_ip: DEFAULT_DST_IP,
1920 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1921 pointer: u32::from(NEXT_HEADER_OFFSET),
1922 must_send_icmp: false,
1923 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1924 }
1925 );
1926
1927 #[rustfmt::skip]
1929 let mut buf = [
1930 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1932 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1933
1934 Ipv6ExtHdrType::HopByHopOptions.into(), 4, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
1942 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1943
1944 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
1953 ];
1954 let mut fixed_hdr = new_fixed_hdr();
1955 fixed_hdr.next_hdr = Ipv6ExtHdrType::Routing.into();
1956 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1957 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1958 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1959 let mut buf = &buf[..];
1960 assert_eq!(
1961 buf.parse::<Ipv6Packet<_>>().unwrap_err(),
1962 Ipv6ParseError::ParameterProblem {
1963 src_ip: DEFAULT_SRC_IP,
1964 dst_ip: DEFAULT_DST_IP,
1965 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1966 pointer: IPV6_FIXED_HDR_LEN as u32,
1967 must_send_icmp: false,
1968 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1969 }
1970 );
1971
1972 #[rustfmt::skip]
1974 let mut buf = [
1975 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1977 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1978
1979 IpProto::Tcp.into(), 4, 255, 1, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
1987 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1988
1989 1, 2, 3, 4, 5,
1991 ];
1992 let mut fixed_hdr = new_fixed_hdr();
1993 fixed_hdr.next_hdr = Ipv6ExtHdrType::Routing.into();
1994 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1995 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1996 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1997 let expected_error = Ipv6ParseError::ParameterProblem {
1998 src_ip: DEFAULT_SRC_IP,
1999 dst_ip: DEFAULT_DST_IP,
2000 code: Icmpv6ParameterProblemCode::ErroneousHeaderField,
2001 pointer: (IPV6_FIXED_HDR_LEN as u32) + 2,
2002 must_send_icmp: true,
2003 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2004 };
2005 assert_eq!((&buf[..]).parse::<Ipv6Packet<_>>().unwrap_err(), expected_error);
2006
2007 buf[IPV6_FIXED_HDR_LEN] = 250; assert_eq!((&buf[..]).parse::<Ipv6Packet<_>>().unwrap_err(), expected_error);
2013 }
2014
2015 #[test]
2016 fn test_parse_all_next_header_values() {
2017 let mut buf = [
2023 0x81, 0x13, 0x27, 0xeb, 0x75, 0x92, 0x33, 0x89, 0x01, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
2024 0x03, 0x70, 0x00, 0x22, 0xf7, 0x30, 0x2c, 0x06, 0xfe, 0xc9, 0x00, 0x2d, 0x3b, 0xeb,
2025 0xad, 0x3e, 0x5c, 0x41, 0xc8, 0x70, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x11, 0x00,
2026 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x4f, 0x4f, 0x6f, 0x4f, 0x4f, 0x4f, 0x4f,
2027 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x19, 0x19,
2028 0x19, 0x19, 0x19, 0x4f, 0x4f, 0x4f, 0x4f, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2029 0x00, 0x4f, 0x4f, 0x5a, 0x5a, 0x5a, 0xc9, 0x5a, 0x46, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
2030 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0xe4, 0x5a, 0x5a, 0x5a, 0x5a,
2031 ];
2032
2033 assert_matches!(
2036 (&buf[..]).parse::<Ipv6Packet<_>>(),
2037 Err(Ipv6ParseError::ParameterProblem {
2038 src_ip: _,
2039 dst_ip: _,
2040 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2041 pointer: 6,
2042 must_send_icmp: false,
2043 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2044 })
2045 );
2046
2047 for b in 0u8..=255 {
2050 buf[6] = b;
2052 let _: Result<_, _> = (&buf[..]).parse::<Ipv6Packet<_>>();
2053 }
2054 }
2055
2056 #[test]
2057 fn test_esp_packet() {
2058 const ESP_NEXT_HEADER: u8 = 50;
2063
2064 let mut fixed_hdr = new_fixed_hdr();
2066 fixed_hdr.next_hdr = ESP_NEXT_HEADER;
2067 fixed_hdr.payload_len = U16::new(8);
2068 let mut buf = fixed_hdr_to_bytes(fixed_hdr).to_vec();
2069 buf.extend_from_slice(&[0; 8]);
2070
2071 assert_matches!(
2073 (&buf[..]).parse::<Ipv6Packet<_>>(),
2074 Err(Ipv6ParseError::ParameterProblem {
2075 src_ip: _,
2076 dst_ip: _,
2077 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2078 pointer: 6, must_send_icmp: false,
2080 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2081 })
2082 );
2083
2084 let mut buf_ref = &buf[..];
2086 assert!(buf_ref.parse::<Ipv6PacketRaw<_>>().is_ok());
2087
2088 let mut fixed_hdr = new_fixed_hdr();
2090 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2091 fixed_hdr.payload_len = U16::new(16);
2092 let mut buf = fixed_hdr_to_bytes(fixed_hdr).to_vec();
2093 buf.extend_from_slice(&[ESP_NEXT_HEADER, 0, 0, 0, 0, 0, 0, 0]);
2095 buf.extend_from_slice(&[0; 8]);
2097
2098 assert_matches!(
2100 (&buf[..]).parse::<Ipv6Packet<_>>(),
2101 Err(Ipv6ParseError::ParameterProblem {
2102 src_ip: _,
2103 dst_ip: _,
2104 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2105 pointer: 40, must_send_icmp: false,
2107 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2108 })
2109 );
2110
2111 let mut buf_ref = &buf[..];
2113 assert!(buf_ref.parse::<Ipv6PacketRaw<_>>().is_ok());
2114 }
2115
2116 #[test]
2117 fn test_parse_ext_hdr_unrecognized_next_header() {
2118 #[rustfmt::skip]
2122 let mut buf = [
2123 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2125 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2126
2127 250, 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2136 ];
2137 let mut fixed_hdr = new_fixed_hdr();
2138 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2139 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2140 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2141 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2142
2143 assert!((&buf[..]).parse::<Ipv6PacketRaw<_>>().is_ok());
2145
2146 assert_eq!(
2148 (&buf[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
2149 Ipv6ParseError::ParameterProblem {
2150 src_ip: DEFAULT_SRC_IP,
2151 dst_ip: DEFAULT_DST_IP,
2152 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2153 pointer: IPV6_FIXED_HDR_LEN as u32,
2154 must_send_icmp: false,
2155 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2156 }
2157 );
2158 }
2159
2160 #[test]
2161 fn test_partial_parse() {
2162 use core::convert::TryInto as _;
2163 use core::ops::Deref as _;
2164
2165 #[rustfmt::skip]
2167 let mut buf = [
2168 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2170 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2171
2172 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2181 ];
2182 let len = buf.len() - IPV6_FIXED_HDR_LEN;
2183 let len = len.try_into().unwrap();
2184 let make_fixed_hdr = || {
2185 let mut fixed_hdr = new_fixed_hdr();
2186 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2187 fixed_hdr.payload_len = U16::new(len);
2188 fixed_hdr
2189 };
2190 const MALFORMED_BYTE: u8 = 10;
2192 buf[IPV6_FIXED_HDR_LEN + 1] = MALFORMED_BYTE;
2193 let fixed_hdr = fixed_hdr_to_bytes(make_fixed_hdr());
2194 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr);
2195 let mut buf = &buf[..];
2196 let partial = buf.parse::<Ipv6PacketRaw<_>>().unwrap();
2197 let Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto } = &partial;
2198 assert_eq!(fixed_hdr.deref(), &make_fixed_hdr());
2199 let b = extension_hdrs.as_ref().incomplete().unwrap();
2200 assert_eq!(*b, &[IpProto::Tcp.into(), MALFORMED_BYTE][..]);
2201 assert_eq!(body_proto, &Err(ExtHdrParseError));
2202 assert!(Ipv6Packet::try_from_raw(partial).is_err());
2203
2204 let mut buf = [
2206 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2208 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
2210 ];
2211 let make_fixed_hdr = || {
2212 let mut fixed_hdr = new_fixed_hdr();
2213 fixed_hdr.next_hdr = IpProto::Tcp.into();
2214 fixed_hdr.payload_len = U16::new(10);
2215 fixed_hdr
2216 };
2217 let fixed_hdr = fixed_hdr_to_bytes(make_fixed_hdr());
2218 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr);
2219 let mut parsebuff = &buf[..];
2220 let partial = parsebuff.parse::<Ipv6PacketRaw<_>>().unwrap();
2221 let Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto } = &partial;
2222 assert_eq!(fixed_hdr.deref(), &make_fixed_hdr());
2223 assert_eq!(extension_hdrs.as_ref().complete().unwrap().deref(), []);
2224 let (body, proto) = body_proto.unwrap();
2225 assert_eq!(body.incomplete().unwrap(), &buf[IPV6_FIXED_HDR_LEN..]);
2226 assert_eq!(proto, IpProto::Tcp.into());
2227 assert!(Ipv6Packet::try_from_raw(partial).is_err());
2228 }
2229
2230 fn new_builder() -> Ipv6PacketBuilder {
2232 Ipv6PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, 64, IpProto::Tcp.into())
2233 }
2234
2235 #[test]
2236 fn test_serialize() {
2237 let mut builder = new_builder();
2238 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
2239 builder.flowlabel(0x10405);
2240 let mut buf = (&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2241 .into_serializer()
2242 .wrap_in(builder)
2243 .serialize_vec_outer(&mut NoOpSerializationContext)
2244 .unwrap();
2245 assert_eq!(
2247 buf.as_ref(),
2248 &[
2249 100, 177, 4, 5, 0, 10, 6, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
2250 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, 1, 2, 3, 4,
2251 5, 6, 7, 8, 9
2252 ][..],
2253 );
2254
2255 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2256 assert_eq!(packet.dscp_and_ecn().dscp(), 0x12);
2259 assert_eq!(packet.dscp_and_ecn().ecn(), 3);
2260 assert_eq!(packet.flowlabel(), 0x10405);
2261 }
2262
2263 #[test]
2264 fn test_partial_serialize() {
2265 let mut builder = new_builder();
2266 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
2267 builder.flowlabel(0x10405);
2268 const BODY: &[u8] = &[0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2269 let packet = (&BODY).into_serializer().wrap_in(builder);
2270
2271 const HEADER: &[u8] = &[
2274 100, 177, 4, 5, 0, 10, 6, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
2275 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
2276 ];
2277 const PACKET_SIZE: usize = HEADER.len() + BODY.len();
2278
2279 let buf = assert_matches!(
2282 packet.partial_serialize(&mut NoOpSerializationContext, packet::new_buf_vec),
2283 Ok(PartialSerializeResult::NewBuffer { buffer, total_size: PACKET_SIZE }) => buffer
2284 );
2285 assert_eq!(buf.as_ref(), HEADER);
2286 }
2287
2288 #[test]
2289 fn test_serialize_zeroes() {
2290 let mut buf_0 = [0; IPV6_FIXED_HDR_LEN];
2293 let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], IPV6_FIXED_HDR_LEN..)
2294 .wrap_in(new_builder())
2295 .serialize_vec_outer(&mut NoOpSerializationContext)
2296 .unwrap()
2297 .unwrap_a();
2298 let mut buf_1 = [0xFF; IPV6_FIXED_HDR_LEN];
2299 let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], IPV6_FIXED_HDR_LEN..)
2300 .wrap_in(new_builder())
2301 .serialize_vec_outer(&mut NoOpSerializationContext)
2302 .unwrap()
2303 .unwrap_a();
2304 assert_eq!(&buf_0[..], &buf_1[..]);
2305 }
2306
2307 #[test]
2308 fn test_packet_builder_proto_not_next_header() {
2309 let mut buf = (&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2313 .into_serializer()
2314 .wrap_in(
2315 Ipv6PacketBuilderWithHbhOptions::new(
2316 new_builder(),
2317 &[HopByHopOption {
2318 action: ExtensionHeaderOptionAction::SkipAndContinue,
2319 mutable: false,
2320 data: HopByHopOptionData::RouterAlert { data: 0 },
2321 }],
2322 )
2323 .unwrap(),
2324 )
2325 .serialize_vec_outer(&mut NoOpSerializationContext)
2326 .unwrap();
2327 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2328 assert_eq!(packet.proto(), IpProto::Tcp.into());
2329 assert_eq!(packet.next_header(), Ipv6ExtHdrType::HopByHopOptions.into());
2330 }
2331
2332 #[test]
2333 #[should_panic(expected = "SizeLimitExceeded, Nested { inner: Buf { buf:")]
2334 fn test_serialize_panic_packet_length() {
2335 let _: Buf<&mut [u8]> = Buf::new(&mut [0; 1 << 16][..], ..)
2338 .wrap_in(new_builder())
2339 .serialize_vec_outer(&mut NoOpSerializationContext)
2340 .unwrap()
2341 .unwrap_a();
2342 }
2343
2344 #[test]
2345 #[should_panic(expected = "packet must have at least one extension header")]
2346 fn test_copy_header_bytes_for_fragment_without_ext_hdrs() {
2347 let mut buf = &fixed_hdr_to_bytes(new_fixed_hdr())[..];
2348 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2349 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2350 }
2351
2352 #[test]
2353 #[should_panic(expected = "exhausted all extension headers without finding fragment header")]
2354 fn test_copy_header_bytes_for_fragment_with_1_ext_hdr_no_fragment() {
2355 #[rustfmt::skip]
2356 let mut buf = [
2357 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2359 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2360
2361 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2370 ];
2371 let mut fixed_hdr = new_fixed_hdr();
2372 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2373 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2374 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2375 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2376 let mut buf = &buf[..];
2377 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2378 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2379 }
2380
2381 #[test]
2382 #[should_panic(expected = "exhausted all extension headers without finding fragment header")]
2383 fn test_copy_header_bytes_for_fragment_with_2_ext_hdr_no_fragment() {
2384 #[rustfmt::skip]
2385 let mut buf = [
2386 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2388 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2389
2390 Ipv6ExtHdrType::DestinationOptions.into(), 0, 0, 1, 0, 1, 1, 0, IpProto::Tcp.into(), 1, 0, 1, 0, 1, 1, 0, 1, 6, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
2407 ];
2408 let mut fixed_hdr = new_fixed_hdr();
2409 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2410 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2411 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2412 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2413 let mut buf = &buf[..];
2414 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2415 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2416 }
2417
2418 #[test]
2419 fn test_copy_header_bytes_for_fragment() {
2420 #[rustfmt::skip]
2425 let mut bytes = [
2426 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2428 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2429
2430 IpProto::Tcp.into(), 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5,
2438 ];
2439 let mut fixed_hdr = new_fixed_hdr();
2440 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2441 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2442 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2443 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2444 let mut buf = &bytes[..];
2445 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2446 let copied_bytes = packet.copy_header_bytes_for_fragment();
2447 bytes[6] = IpProto::Tcp.into();
2448 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN]);
2449
2450 #[rustfmt::skip]
2455 let mut bytes = [
2456 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2458 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2459
2460 Ipv6ExtHdrType::Fragment.into(), 0, 0, 1, 0, 1, 1, 0, IpProto::Tcp.into(), 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5,
2475 ];
2476 let mut fixed_hdr = new_fixed_hdr();
2477 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2478 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2479 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2480 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2481 let mut buf = &bytes[..];
2482 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2483 let copied_bytes = packet.copy_header_bytes_for_fragment();
2484 bytes[IPV6_FIXED_HDR_LEN] = IpProto::Tcp.into();
2485 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN + 8]);
2486
2487 #[rustfmt::skip]
2492 let mut bytes = [
2493 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2495 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2496
2497 Ipv6ExtHdrType::DestinationOptions.into(), 0, 0, 1, 0, 1, 1, 0, Ipv6ExtHdrType::Fragment.into(), 1, 0, 1, 0, 1, 1, 0, 1, 6, 0, 0, 0, 0, 0, 0, IpProto::Tcp.into(), 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5,
2520 ];
2521 let mut fixed_hdr = new_fixed_hdr();
2522 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2523 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2524 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2525 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2526 let mut buf = &bytes[..];
2527 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2528 let copied_bytes = packet.copy_header_bytes_for_fragment();
2529 bytes[IPV6_FIXED_HDR_LEN + 8] = IpProto::Tcp.into();
2530 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN + 24]);
2531
2532 #[rustfmt::skip]
2537 let mut bytes = [
2538 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2540 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2541
2542 Ipv6ExtHdrType::DestinationOptions.into(), 0, 0, 0, 1, 1, 1, 1, IpProto::Tcp.into(), 1, 0, 1, 0, 1, 1, 0, 1, 6, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
2558 ];
2559 let mut fixed_hdr = new_fixed_hdr();
2560 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2561 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2562 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2563 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2564 let mut buf = &bytes[..];
2565 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2566 let copied_bytes = packet.copy_header_bytes_for_fragment();
2567 let mut expected_bytes = Vec::new();
2568 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2569 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2570 expected_bytes[6] = Ipv6ExtHdrType::DestinationOptions.into();
2571 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2572
2573 #[rustfmt::skip]
2578 let mut bytes = [
2579 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2581 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2582
2583 Ipv6ExtHdrType::DestinationOptions.into(), 0, 0, 0, 1, 1, 1, 1, Ipv6ExtHdrType::Routing.into(), 1, 0, 1, 0, 1, 1, 0, 1, 6, 0, 0, 0, 0, 0, 0, IpProto::Tcp.into(), 4, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
2605 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2606
2607 1, 2, 3, 4, 5,
2609 ];
2610 let mut fixed_hdr = new_fixed_hdr();
2611 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2612 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2613 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2614 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2615 let mut buf = &bytes[..];
2616 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2617 let copied_bytes = packet.copy_header_bytes_for_fragment();
2618 let mut expected_bytes = Vec::new();
2619 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2620 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2621 expected_bytes[6] = Ipv6ExtHdrType::DestinationOptions.into();
2622 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2623
2624 #[rustfmt::skip]
2629 let mut bytes = [
2630 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2632 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2633
2634 Ipv6ExtHdrType::Fragment.into(), 0, 0, 1, 0, 1, 1, 0, Ipv6ExtHdrType::DestinationOptions.into(), 0, 0, 0, 1, 1, 1, 1, IpProto::Tcp.into(), 1, 0, 1, 0, 1, 1, 0, 1, 6, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
2657 ];
2658 let mut fixed_hdr = new_fixed_hdr();
2659 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2660 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2661 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2662 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2663 let mut buf = &bytes[..];
2664 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2665 let copied_bytes = packet.copy_header_bytes_for_fragment();
2666 let mut expected_bytes = Vec::new();
2667 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN + 8]);
2668 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 16..bytes.len() - 5]);
2669 expected_bytes[IPV6_FIXED_HDR_LEN] = Ipv6ExtHdrType::DestinationOptions.into();
2670 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2671
2672 #[rustfmt::skip]
2677 let mut bytes = [
2678 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2680 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2681
2682 Ipv6ExtHdrType::Fragment.into(), 0, 0, 0, 1, 1, 1, 1, IpProto::Tcp.into(), 0, 0, 0, 2, 2, 2, 2, 1, 2, 3, 4, 5,
2696 ];
2697 let mut fixed_hdr = new_fixed_hdr();
2698 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2699 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2700 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2701 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2702 let mut buf = &bytes[..];
2703 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2704 let copied_bytes = packet.copy_header_bytes_for_fragment();
2705 let mut expected_bytes = Vec::new();
2706 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2707 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2708 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2709
2710 #[rustfmt::skip]
2716 let mut bytes = [
2717 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2719 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2720
2721 Ipv6ExtHdrType::Routing.into(), 0, 0, 1, 0, 1, 1, 0, Ipv6ExtHdrType::Fragment.into(), 4, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
2736 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2737
2738 IpProto::Tcp.into(), 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5,
2746 ];
2747 let mut fixed_hdr = new_fixed_hdr();
2748 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2749 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2750 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2751 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2752 let mut buf = &bytes[..];
2753 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2754 let copied_bytes = packet.copy_header_bytes_for_fragment();
2755 let mut expected_bytes = Vec::new();
2756 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN + 48]);
2758 expected_bytes[IPV6_FIXED_HDR_LEN + 8] = IpProto::Tcp.into();
2759 assert_eq!(copied_bytes, expected_bytes);
2760 }
2761
2762 #[test]
2763 fn test_next_multiple_of_eight() {
2764 for x in 0usize..=IPV6_HBH_OPTIONS_MAX_LEN {
2765 let y = next_multiple_of_eight(x);
2766 assert_eq!(y % 8, 0);
2767 assert!(y >= x);
2768 if x % 8 == 0 {
2769 assert_eq!(x, y);
2770 } else {
2771 assert_eq!(x + (8 - x % 8), y);
2772 }
2773 }
2774 }
2775
2776 fn create_ipv4_and_ipv6_builders(
2777 proto_v4: Ipv4Proto,
2778 proto_v6: Ipv6Proto,
2779 ) -> (Ipv4PacketBuilder, Ipv6PacketBuilder) {
2780 const IP_DSCP_AND_ECN: DscpAndEcn = DscpAndEcn::new(0x12, 3);
2781 const IP_TTL: u8 = 64;
2782
2783 let mut ipv4_builder =
2784 Ipv4PacketBuilder::new(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP, IP_TTL, proto_v4);
2785 ipv4_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
2786 ipv4_builder.df_flag(false);
2787 ipv4_builder.mf_flag(false);
2788 ipv4_builder.fragment_offset(FragmentOffset::ZERO);
2789
2790 let mut ipv6_builder =
2791 Ipv6PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, IP_TTL, proto_v6);
2792 ipv6_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
2793 ipv6_builder.flowlabel(0x456);
2794
2795 (ipv4_builder, ipv6_builder)
2796 }
2797
2798 fn create_tcp_ipv4_and_ipv6_pkt()
2799 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
2800 use crate::tcp::TcpSegmentBuilder;
2801 use core::num::NonZeroU16;
2802
2803 let tcp_src_port: NonZeroU16 = NonZeroU16::new(20).unwrap();
2804 let tcp_dst_port: NonZeroU16 = NonZeroU16::new(30).unwrap();
2805 const TCP_SEQ_NUM: u32 = 4321;
2806 const TCP_ACK_NUM: Option<u32> = Some(1234);
2807 const TCP_WINDOW_SIZE: u16 = 12345;
2808 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2809
2810 let (ipv4_builder, ipv6_builder) =
2811 create_ipv4_and_ipv6_builders(IpProto::Tcp.into(), IpProto::Tcp.into());
2812
2813 let tcp_builder = TcpSegmentBuilder::new(
2814 DEFAULT_V4_SRC_IP,
2815 DEFAULT_V4_DST_IP,
2816 tcp_src_port,
2817 tcp_dst_port,
2818 TCP_SEQ_NUM,
2819 TCP_ACK_NUM,
2820 TCP_WINDOW_SIZE,
2821 );
2822
2823 let v4_pkt_buf = (&PAYLOAD)
2824 .into_serializer()
2825 .wrap_in(tcp_builder)
2826 .wrap_in(ipv4_builder)
2827 .serialize_vec_outer(&mut NoOpSerializationContext)
2828 .expect("Failed to serialize to v4_pkt_buf");
2829
2830 let v6_tcp_builder = TcpSegmentBuilder::new(
2831 DEFAULT_SRC_IP,
2832 DEFAULT_DST_IP,
2833 tcp_src_port,
2834 tcp_dst_port,
2835 TCP_SEQ_NUM,
2836 TCP_ACK_NUM,
2837 TCP_WINDOW_SIZE,
2838 );
2839
2840 let v6_pkt_buf = (&PAYLOAD)
2841 .into_serializer()
2842 .wrap_in(v6_tcp_builder)
2843 .wrap_in(ipv6_builder)
2844 .serialize_vec_outer(&mut NoOpSerializationContext)
2845 .expect("Failed to serialize to v4_pkt_buf");
2846
2847 (v4_pkt_buf, v6_pkt_buf)
2848 }
2849
2850 #[test]
2851 fn test_nat64_translate_tcp() {
2852 let (expected_v4_pkt_buf, mut v6_pkt_buf) = create_tcp_ipv4_and_ipv6_pkt();
2853
2854 let parsed_v6_packet =
2855 v6_pkt_buf.parse::<Ipv6Packet<_>>().expect("Failed to parse v6_pkt_buf");
2856 let nat64_translation_result =
2857 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2858
2859 let serializable_pkt =
2860 assert_matches!(nat64_translation_result, Nat64TranslationResult::Forward(s) => s);
2861
2862 let translated_v4_pkt_buf = serializable_pkt
2863 .serialize_vec_outer(&mut NoOpSerializationContext)
2864 .expect("Failed to serialize to translated_v4_pkt_buf");
2865
2866 assert_eq!(
2867 expected_v4_pkt_buf.to_flattened_vec(),
2868 translated_v4_pkt_buf.to_flattened_vec()
2869 );
2870 }
2871
2872 fn create_udp_ipv4_and_ipv6_pkt()
2873 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
2874 use crate::udp::UdpPacketBuilder;
2875 use core::num::NonZeroU16;
2876
2877 let udp_src_port: NonZeroU16 = NonZeroU16::new(35000).unwrap();
2878 let udp_dst_port: NonZeroU16 = NonZeroU16::new(53).unwrap();
2879 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2880
2881 let (ipv4_builder, ipv6_builder) =
2882 create_ipv4_and_ipv6_builders(IpProto::Udp.into(), IpProto::Udp.into());
2883
2884 let v4_udp_builder = UdpPacketBuilder::new(
2885 DEFAULT_V4_SRC_IP,
2886 DEFAULT_V4_DST_IP,
2887 Some(udp_src_port),
2888 udp_dst_port,
2889 );
2890
2891 let v4_pkt_buf = (&PAYLOAD)
2892 .into_serializer()
2893 .wrap_in(v4_udp_builder)
2894 .wrap_in(ipv4_builder)
2895 .serialize_vec_outer(&mut NoOpSerializationContext)
2896 .expect("Unable to serialize to v4_pkt_buf");
2897
2898 let v6_udp_builder =
2899 UdpPacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, Some(udp_src_port), udp_dst_port);
2900
2901 let v6_pkt_buf = (&PAYLOAD)
2902 .into_serializer()
2903 .wrap_in(v6_udp_builder)
2904 .wrap_in(ipv6_builder)
2905 .serialize_vec_outer(&mut NoOpSerializationContext)
2906 .expect("Unable to serialize to v6_pkt_buf");
2907
2908 (v4_pkt_buf, v6_pkt_buf)
2909 }
2910
2911 #[test]
2912 fn test_nat64_translate_udp() {
2913 let (expected_v4_pkt_buf, mut v6_pkt_buf) = create_udp_ipv4_and_ipv6_pkt();
2914
2915 let parsed_v6_packet =
2916 v6_pkt_buf.parse::<Ipv6Packet<_>>().expect("Unable to parse Ipv6Packet");
2917 let nat64_translation_result =
2918 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2919
2920 let serializable_pkt = assert_matches!(nat64_translation_result,
2921 Nat64TranslationResult::Forward(s) => s);
2922
2923 let translated_v4_pkt_buf = serializable_pkt
2924 .serialize_vec_outer(&mut NoOpSerializationContext)
2925 .expect("Unable to serialize to translated_v4_pkt_buf");
2926
2927 assert_eq!(
2928 expected_v4_pkt_buf.to_flattened_vec(),
2929 translated_v4_pkt_buf.to_flattened_vec()
2930 );
2931 }
2932
2933 #[test]
2934 fn test_nat64_translate_non_tcp_udp_icmp() {
2935 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2936
2937 let (ipv4_builder, ipv6_builder) =
2938 create_ipv4_and_ipv6_builders(Ipv4Proto::Other(59), Ipv6Proto::Other(59));
2939
2940 let expected_v4_pkt_buf = (&PAYLOAD)
2941 .into_serializer()
2942 .wrap_in(ipv4_builder)
2943 .serialize_vec_outer(&mut NoOpSerializationContext)
2944 .expect("Unable to serialize to expected_v4_pkt_buf");
2945
2946 let mut v6_pkt_buf = (&PAYLOAD)
2947 .into_serializer()
2948 .wrap_in(ipv6_builder)
2949 .serialize_vec_outer(&mut NoOpSerializationContext)
2950 .expect("Unable to serialize to v6_pkt_buf");
2951
2952 let translated_v4_pkt_buf = {
2953 let parsed_v6_packet = v6_pkt_buf
2954 .parse::<Ipv6Packet<_>>()
2955 .expect("Unable to serialize to translated_v4_pkt_buf");
2956
2957 let nat64_translation_result =
2958 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2959
2960 let serializable_pkt = assert_matches!(nat64_translation_result,
2961 Nat64TranslationResult::Forward(s) => s);
2962
2963 let translated_buf = serializable_pkt
2964 .serialize_vec_outer(&mut NoOpSerializationContext)
2965 .expect("Unable to serialize to translated_buf");
2966
2967 translated_buf
2968 };
2969
2970 assert_eq!(
2971 expected_v4_pkt_buf.to_flattened_vec(),
2972 translated_v4_pkt_buf.to_flattened_vec()
2973 );
2974 }
2975
2976 #[test_case(new_builder(), true; "fixed header more frags")]
2977 #[test_case(Ipv6PacketBuilderWithHbhOptions::new(
2978 new_builder(),
2979 &[HopByHopOption {
2980 action: ExtensionHeaderOptionAction::SkipAndContinue,
2981 mutable: false,
2982 data: HopByHopOptionData::RouterAlert { data: 0 },
2983 }]).unwrap(), false; "hbh last frag")]
2984 fn ipv6_packet_builder_with_fragment_header<
2985 B: Ipv6HeaderBuilder + Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>> + Debug,
2986 >(
2987 inner: B,
2988 more_fragments: bool,
2989 ) {
2990 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2991 let fragment_offset = FragmentOffset::new(13).unwrap();
2992 let identification = 0xABCDABCD;
2993 let builder = Ipv6PacketBuilderWithFragmentHeader::new(
2994 inner,
2995 fragment_offset,
2996 more_fragments,
2997 identification,
2998 );
2999 let mut serialized = builder
3000 .wrap_body(PAYLOAD.into_serializer())
3001 .serialize_vec_outer(&mut NoOpSerializationContext)
3002 .unwrap()
3003 .unwrap_b();
3004 let packet = serialized.parse::<Ipv6Packet<_>>().unwrap();
3005 assert!(packet.fragment_header_present());
3006 assert_eq!(packet.proto(), Ipv6Proto::Proto(IpProto::Tcp));
3007 let fragment_data = packet
3008 .extension_hdrs
3009 .into_iter()
3010 .find_map(|ext_hdr| match ext_hdr {
3011 Ipv6ExtensionHeader::Fragment { fragment_data } => Some(fragment_data),
3012 _ => None,
3013 })
3014 .unwrap();
3015 assert_eq!(fragment_data.fragment_offset(), fragment_offset);
3016 assert_eq!(fragment_data.identification(), identification);
3017 assert_eq!(fragment_data.m_flag(), more_fragments);
3018 }
3019
3020 #[test]
3023 fn extension_headers_take_from_max_body_size() {
3024 let builder = new_builder();
3025 assert_eq!(builder.constraints().max_body_len(), IPV6_MAX_PAYLOAD_LENGTH);
3026 let builder =
3027 Ipv6PacketBuilderWithFragmentHeader::new(builder, FragmentOffset::ZERO, false, 1234);
3028 assert_eq!(
3029 builder.constraints().max_body_len(),
3030 IPV6_MAX_PAYLOAD_LENGTH - IPV6_FRAGMENT_EXT_HDR_LEN
3031 );
3032 }
3033
3034 #[test]
3035 fn test_partial_serialize_parsed() {
3036 const PACKET_BYTES: &[u8] = &[
3037 100, 177, 4, 5, 0, 10, 6, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
3038 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, 1, 2, 3, 4, 5, 6, 7,
3039 8, 9,
3040 ];
3041 const PACKET_LEN: usize = PACKET_BYTES.len();
3042 let mut packet_bytes_copy = Vec::from(PACKET_BYTES);
3043 let mut packet_bytes_ref: &mut [u8] = &mut packet_bytes_copy[..];
3044 let packet = packet_bytes_ref.parse::<Ipv6Packet<_>>().unwrap();
3045
3046 let buf = assert_matches!(
3047 packet.partial_serialize(&mut NoOpSerializationContext, packet::new_buf_vec),
3048 Ok(PartialSerializeResult::NewBuffer { buffer, total_size: PACKET_LEN }) => buffer
3049 );
3050 assert_eq!(buf.as_ref(), PACKET_BYTES);
3051 }
3052}