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 = (u8::MAX as usize) * 8 + 8;
66
67const IPV6_MAX_PAYLOAD_LENGTH: usize = 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 pub fn per_fragment_builder(&self) -> Ipv6PerFragmentHeaderBuilder<Vec<u8>> {
546 let mut routing_point = None;
547 let mut hbh_point = None;
548 let mut iter = self.extension_hdrs.iter();
549 let mut is_first_ext_hdr = true;
550
551 while let Some(ext_hdr) = iter.next() {
552 match ext_hdr {
553 Ipv6ExtensionHeader::HopByHopOptions { .. } => {
554 if is_first_ext_hdr {
563 hbh_point = Some((
564 iter.context().position,
565 iter.context().next_header_offset,
566 iter.context().next_header,
567 ));
568 }
569 }
570 Ipv6ExtensionHeader::Routing { .. } => {
571 routing_point = Some((
572 iter.context().position,
573 iter.context().next_header_offset,
574 iter.context().next_header,
575 ));
576 break;
577 }
578 _ => {}
579 }
580 is_first_ext_hdr = false;
581 }
582
583 let split_point = routing_point.or(hbh_point);
584 let (meta, next_header) = match split_point {
585 Some((position, next_header_offset, next_header)) => (
586 Some(Ipv6PerFragmentMeta {
587 ext_hdrs: self.extension_hdrs.bytes()[..position - IPV6_FIXED_HDR_LEN].to_vec(),
588 first_ext_hdr: Ipv6ExtHdrType::from(self.fixed_hdr.next_hdr),
589 last_next_hdr_offset: next_header_offset - IPV6_FIXED_HDR_LEN,
590 }),
591 next_header,
592 ),
593 None => (None, self.fixed_hdr.next_hdr),
594 };
595 let mut prefix_builder = self.builder();
600 prefix_builder.proto = Ipv6Proto::from(next_header);
601
602 Ipv6PerFragmentHeaderBuilder { prefix_builder, meta }
603 }
604
605 pub fn header_len(&self) -> usize {
607 Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.bytes().len()
608 }
609
610 fn fragment_header_present(&self) -> bool {
611 for ext_hdr in self.extension_hdrs.iter() {
612 if matches!(ext_hdr, Ipv6ExtensionHeader::Fragment { .. }) {
613 return true;
614 }
615 }
616 false
617 }
618
619 pub fn builder(&self) -> Ipv6PacketBuilder {
621 Ipv6PacketBuilder {
622 dscp_and_ecn: self.dscp_and_ecn(),
623 flowlabel: self.flowlabel(),
624 hop_limit: self.hop_limit(),
625 proto: self.proto(),
626 src_ip: self.src_ip(),
627 dst_ip: self.dst_ip(),
628 }
629 }
630
631 pub fn nat64_translate(
657 &self,
658 v4_src_addr: Ipv4Addr,
659 v4_dst_addr: Ipv4Addr,
660 ) -> Nat64TranslationResult<
661 impl Serializer<NoOpSerializationContext, Buffer = EmptyBuf> + Debug + '_,
662 Nat64Error,
663 > {
664 #[derive(Debug)]
667 enum Nat64Serializer<T, U, O> {
668 Tcp(T),
669 Udp(U),
670 Other(O),
671 }
672 impl<T, U, O> Serializer<NoOpSerializationContext> for Nat64Serializer<T, U, O>
673 where
674 T: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
675 U: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
676 O: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
677 {
678 type Buffer = EmptyBuf;
679 fn serialize<B, P>(
680 self,
681 context: &mut NoOpSerializationContext,
682 outer: PacketConstraints,
683 provider: P,
684 ) -> Result<B, (SerializeError<P::Error>, Self)>
685 where
686 B: GrowBufferMut,
687 P: BufferProvider<Self::Buffer, B>,
688 {
689 match self {
690 Nat64Serializer::Tcp(serializer) => serializer
691 .serialize(context, outer, provider)
692 .map_err(|(err, ser)| (err, Nat64Serializer::Tcp(ser))),
693 Nat64Serializer::Udp(serializer) => serializer
694 .serialize(context, outer, provider)
695 .map_err(|(err, ser)| (err, Nat64Serializer::Udp(ser))),
696 Nat64Serializer::Other(serializer) => serializer
697 .serialize(context, outer, provider)
698 .map_err(|(err, ser)| (err, Nat64Serializer::Other(ser))),
699 }
700 }
701
702 fn serialize_new_buf<B: GrowBufferMut, A: LayoutBufferAlloc<B>>(
703 &self,
704 context: &mut NoOpSerializationContext,
705 outer: PacketConstraints,
706 alloc: A,
707 ) -> Result<B, SerializeError<A::Error>> {
708 match self {
709 Nat64Serializer::Tcp(serializer) => {
710 serializer.serialize_new_buf(context, outer, alloc)
711 }
712 Nat64Serializer::Udp(serializer) => {
713 serializer.serialize_new_buf(context, outer, alloc)
714 }
715 Nat64Serializer::Other(serializer) => {
716 serializer.serialize_new_buf(context, outer, alloc)
717 }
718 }
719 }
720 }
721
722 impl<T, U, O> NestableSerializer for Nat64Serializer<T, U, O>
723 where
724 T: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
725 U: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
726 O: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
727 {
728 }
729
730 if self.fragment_header_present() {
733 return Nat64TranslationResult::Err(Nat64Error::NotImplemented);
734 }
735
736 let v4_builder = |v4_proto| {
737 let mut builder =
738 Ipv4PacketBuilder::new(v4_src_addr, v4_dst_addr, self.hop_limit(), v4_proto);
739 builder.dscp_and_ecn(self.dscp_and_ecn());
740
741 const IPV4_HEADER_LEN_BYTES: usize = HDR_PREFIX_LEN;
746
747 builder.df_flag(self.body().len() + IPV4_HEADER_LEN_BYTES > 1260);
753
754 builder.fragment_offset(FragmentOffset::ZERO);
757 builder.mf_flag(false);
758
759 builder
760 };
761
762 match self.proto() {
763 Ipv6Proto::Proto(IpProto::Tcp) => {
764 let v4_pkt_builder = v4_builder(Ipv4Proto::Proto(IpProto::Tcp));
765 let args = TcpParseArgs::new(self.src_ip(), self.dst_ip());
766 match TcpSegment::parse(&mut self.body.as_bytes(), args) {
771 Ok(tcp) => {
772 let tcp_serializer =
776 Nat64Serializer::Tcp(tcp.into_serializer(v4_src_addr, v4_dst_addr));
777 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(tcp_serializer))
778 }
779 Err(msg) => {
780 debug!("Parsing of TCP segment failed: {:?}", msg);
781
782 let common_serializer =
791 Nat64Serializer::Other(self.body().into_serializer());
792 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
793 }
794 }
795 }
796
797 Ipv6Proto::Proto(IpProto::Udp) => {
802 let v4_pkt_builder = v4_builder(Ipv4Proto::Proto(IpProto::Udp));
803 let args = UdpParseArgs::new(self.src_ip(), self.dst_ip());
804 match UdpPacket::parse(&mut self.body.as_bytes(), args) {
805 Ok(udp) => {
806 let udp_serializer =
810 Nat64Serializer::Udp(udp.into_serializer(v4_src_addr, v4_dst_addr));
811 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(udp_serializer))
812 }
813 Err(msg) => {
814 debug!("Parsing of UDP packet failed: {:?}", msg);
815
816 let common_serializer =
826 Nat64Serializer::Other(self.body().into_serializer());
827 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
828 }
829 }
830 }
831
832 Ipv6Proto::Icmpv6 => Nat64TranslationResult::Err(Nat64Error::NotImplemented),
835
836 Ipv6Proto::Other(val) => {
856 let v4_pkt_builder = v4_builder(Ipv4Proto::Other(val));
857 let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
858 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
859 }
860
861 Ipv6Proto::NoNextHeader => {
862 let v4_pkt_builder = v4_builder(Ipv4Proto::Other(Ipv6Proto::NoNextHeader.into()));
863 let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
864 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
865 }
866
867 Ipv6Proto::Proto(IpProto::Reserved) => Nat64TranslationResult::Drop,
870 }
871 }
872
873 pub fn to_vec(&self) -> Vec<u8> {
875 let Ipv6Packet { fixed_hdr, extension_hdrs, body, proto: _ } = self;
876 let mut buf = Vec::with_capacity(
877 Ref::bytes(&fixed_hdr).len() + extension_hdrs.bytes().len() + body.as_bytes().len(),
878 );
879 buf.extend(Ref::bytes(&fixed_hdr));
880 buf.extend(extension_hdrs.bytes());
881 buf.extend(body.as_bytes());
882 buf
883 }
884}
885
886impl<B: SplitByteSliceMut> Ipv6Packet<B> {
887 pub fn set_src_ip(&mut self, addr: Ipv6Addr) {
889 self.fixed_hdr.src_ip = addr;
890 }
891
892 pub fn set_dst_ip(&mut self, addr: Ipv6Addr) {
894 self.fixed_hdr.dst_ip = addr;
895 }
896
897 pub fn set_hop_limit(&mut self, hlim: u8) {
899 self.fixed_hdr.hop_limit = hlim;
900 }
901
902 pub fn body_mut(&mut self) -> &mut [u8] {
904 &mut self.body
905 }
906
907 pub fn parts_with_body_mut(&mut self) -> (&FixedHeader, ExtensionHeaders<'_>, &mut [u8]) {
910 (&self.fixed_hdr, ExtensionHeaders(self.extension_hdrs.as_ref()), &mut self.body)
911 }
912}
913
914impl<B: SplitByteSlice> Debug for Ipv6Packet<B> {
915 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
916 f.debug_struct("Ipv6Packet")
917 .field("src_ip", &self.src_ip())
918 .field("dst_ip", &self.dst_ip())
919 .field("hop_limit", &self.hop_limit())
920 .field("proto", &self.proto())
921 .field("dscp", &self.dscp_and_ecn().dscp())
922 .field("ecn", &self.dscp_and_ecn().ecn())
923 .field("flowlabel", &self.flowlabel())
924 .field("extension headers", &"TODO")
925 .field("body", &alloc::format!("<{} bytes>", self.body.len()))
926 .finish()
927 }
928}
929
930pub struct ExtensionHeaders<'a>(Records<&'a [u8], Ipv6ExtensionHeaderImpl>);
932
933impl<'a> ExtensionHeaders<'a> {
934 pub fn iter(&self) -> impl Iterator<Item = Ipv6ExtensionHeader<'_>> {
936 self.0.iter()
937 }
938
939 pub fn bytes(&self) -> &[u8] {
941 self.0.bytes()
942 }
943}
944
945#[derive(Copy, Clone, Debug, Eq, PartialEq)]
951pub struct ExtHdrParseError;
952
953pub struct Ipv6PacketRaw<B> {
963 fixed_hdr: Ref<B, FixedHeader>,
965 extension_hdrs: MaybeParsed<RecordsRaw<B, Ipv6ExtensionHeaderImpl>, B>,
971 body_proto: Result<(MaybeParsed<B, B>, Ipv6Proto), ExtHdrParseError>,
984}
985
986impl<B> Ipv6PacketRaw<B> {
987 pub fn body_mut(&mut self) -> Option<&mut B> {
991 match self.body_proto {
992 Ok(ref mut b) => match b {
993 (MaybeParsed::Complete(b), _) => Some(b),
994 (MaybeParsed::Incomplete(b), _) => Some(b),
995 },
996 Err(_) => None,
997 }
998 }
999}
1000
1001impl<B: SplitByteSlice> Ipv6Header for Ipv6PacketRaw<B> {
1002 fn get_fixed_header(&self) -> &FixedHeader {
1003 &self.fixed_hdr
1004 }
1005}
1006
1007impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv6PacketRaw<B> {
1008 type Error = Ipv6ParseError;
1009
1010 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> Result<Self, Self::Error> {
1011 let fixed_hdr = buffer
1012 .take_obj_front::<FixedHeader>()
1013 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for header"))?;
1014 let payload_len = fixed_hdr.payload_len.get().into();
1015 let _: Option<B> = buffer.len().checked_sub(payload_len).map(|padding| {
1017 buffer.take_back(padding).unwrap_or_else(|| {
1018 panic!("buffer.len()={} padding={}", buffer.len(), padding);
1019 })
1020 });
1021
1022 let mut extension_hdr_context = Ipv6ExtensionHeaderParsingContext::new(fixed_hdr.next_hdr);
1023
1024 let extension_hdrs =
1025 RecordsRaw::parse_raw_with_mut_context(&mut buffer, &mut extension_hdr_context)
1026 .map_incomplete(|(b, _)| b);
1027
1028 let body_proto = match &extension_hdrs {
1029 MaybeParsed::Complete(r) => {
1030 let _: &RecordsRaw<B, _> = r;
1031 assert!(is_valid_next_header_upper_layer(extension_hdr_context.next_header));
1052 let proto = Ipv6Proto::from(extension_hdr_context.next_header);
1053 let body = MaybeParsed::new_with_min_len(
1054 buffer.into_rest(),
1055 payload_len.saturating_sub(extension_hdrs.len()),
1056 );
1057 Ok((body, proto))
1058 }
1059 MaybeParsed::Incomplete(b) => {
1060 let _: &B = b;
1061 Err(ExtHdrParseError)
1062 }
1063 };
1064
1065 Ok(Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto })
1066 }
1067
1068 fn parse_metadata(&self) -> ParseMetadata {
1069 let header_len = Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.len();
1070 let body_len = self.body_proto.as_ref().map(|(b, _p)| b.len()).unwrap_or(0);
1071 ParseMetadata::from_packet(header_len, body_len, 0)
1072 }
1073}
1074
1075impl<B: SplitByteSlice> Ipv6PacketRaw<B> {
1076 pub fn body_proto(&self) -> Result<(MaybeParsed<&[u8], &[u8]>, Ipv6Proto), ExtHdrParseError> {
1089 self.body_proto
1090 .as_ref()
1091 .map(|(mp, proto)| {
1092 (mp.as_ref().map(|b| b.deref()).map_incomplete(|b| b.deref()), *proto)
1093 })
1094 .map_err(|e| *e)
1095 }
1096
1097 pub fn body(&self) -> Result<MaybeParsed<&[u8], &[u8]>, ExtHdrParseError> {
1108 self.body_proto().map(|(body, _proto)| body)
1109 }
1110
1111 pub fn proto(&self) -> Result<Ipv6Proto, ExtHdrParseError> {
1118 self.body_proto().map(|(_body, proto)| proto)
1119 }
1120}
1121
1122impl<B: SplitByteSliceMut> Ipv6PacketRaw<B> {
1123 pub fn set_src_ip(&mut self, addr: Ipv6Addr) {
1125 self.fixed_hdr.src_ip = addr;
1126 }
1127
1128 pub fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1130 self.fixed_hdr.dst_ip = addr;
1131 }
1132}
1133
1134pub enum NextHeader {
1137 NextLayer(Ipv6Proto),
1139 Extension(Ipv6ExtHdrType),
1141}
1142
1143impl From<NextHeader> for u8 {
1144 fn from(next_hdr: NextHeader) -> Self {
1145 match next_hdr {
1146 NextHeader::NextLayer(n) => n.into(),
1147 NextHeader::Extension(e) => e.into(),
1148 }
1149 }
1150}
1151
1152mod sealed {
1153 use super::*;
1154 pub trait Ipv6HeaderBefore<T> {}
1162
1163 impl<'a, O, T> Ipv6HeaderBefore<T> for &'a O where O: Ipv6HeaderBefore<T> {}
1164
1165 pub trait Ipv6HeaderBuilder {
1167 fn fixed_header(&self) -> &Ipv6PacketBuilder;
1169
1170 fn extension_headers_len(&self) -> usize;
1173
1174 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1179 &self,
1180 buffer: &mut BV,
1181 next_header: NextHeader,
1182 payload_len: usize,
1183 );
1184 }
1185}
1186use sealed::{Ipv6HeaderBefore, Ipv6HeaderBuilder};
1187
1188impl<'a, O> Ipv6HeaderBuilder for &'a O
1189where
1190 O: Ipv6HeaderBuilder,
1191{
1192 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1193 O::fixed_header(self)
1194 }
1195
1196 fn extension_headers_len(&self) -> usize {
1197 O::extension_headers_len(self)
1198 }
1199
1200 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1201 &self,
1202 buffer: &mut BV,
1203 next_header: NextHeader,
1204 payload_len: usize,
1205 ) {
1206 O::serialize_header(self, buffer, next_header, payload_len)
1207 }
1208}
1209
1210macro_rules! impl_packet_builder_base {
1215 {} => {
1216 fn constraints(&self) -> PacketConstraints {
1217 let ext_headers = self.extension_headers_len();
1218 let header_len = IPV6_FIXED_HDR_LEN + ext_headers;
1219 let footer_len = 0;
1220 let min_body_len = 0;
1221 let max_body_len = IPV6_MAX_PAYLOAD_LENGTH - ext_headers;
1224 PacketConstraints::new(header_len, footer_len, min_body_len, max_body_len)
1225 }
1226 }
1227}
1228
1229macro_rules! impl_packet_builder {
1230 {} => {
1231 fn context_state(&self) -> C::ContextState {
1232 C::envelope_to_state(IpEnvelope::new(self.extension_headers_len() > 0))
1233 }
1234
1235 fn serialize(
1236 &self,
1237 _context: &mut C,
1238 target: &mut SerializeTarget<'_>,
1239 body: FragmentedBytesMut<'_, '_>,
1240 ) {
1241 let mut bv = &mut target.header;
1242 self.serialize_header(
1243 &mut bv,
1244 NextHeader::NextLayer(
1245 <Ipv6PacketBuilder as IpPacketBuilder<C, Ipv6>>::proto(self.fixed_header())
1246 ),
1247 body.len(),
1248 );
1249 }
1250 }
1251}
1252
1253macro_rules! impl_partial_packet_builder {
1254 {} => {
1255 fn partial_serialize(
1256 &self,
1257 _context: &mut C,
1258 body_len: usize,
1259 mut buffer: &mut [u8],
1260 ) {
1261 self.serialize_header(
1262 &mut &mut buffer,
1263 NextHeader::NextLayer(
1264 <Ipv6PacketBuilder as IpPacketBuilder<C, Ipv6>>::proto(self.fixed_header())
1265 ),
1266 body_len,
1267 );
1268 }
1269 }
1270}
1271#[derive(Debug, Clone, Eq, PartialEq)]
1273pub struct Ipv6PacketBuilder {
1274 dscp_and_ecn: DscpAndEcn,
1275 flowlabel: u32,
1276 hop_limit: u8,
1277 proto: Ipv6Proto,
1280 src_ip: Ipv6Addr,
1281 dst_ip: Ipv6Addr,
1282}
1283
1284impl Ipv6PacketBuilder {
1285 pub fn new<S: Into<Ipv6Addr>, D: Into<Ipv6Addr>>(
1291 src_ip: S,
1292 dst_ip: D,
1293 hop_limit: u8,
1294 proto: Ipv6Proto,
1295 ) -> Ipv6PacketBuilder {
1296 Ipv6PacketBuilder {
1297 dscp_and_ecn: DscpAndEcn::default(),
1298 flowlabel: 0,
1299 hop_limit,
1300 proto,
1301 src_ip: src_ip.into(),
1302 dst_ip: dst_ip.into(),
1303 }
1304 }
1305
1306 pub fn dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1309 self.dscp_and_ecn = dscp_and_ecn;
1310 }
1311
1312 pub fn flowlabel(&mut self, flowlabel: u32) {
1318 assert!(flowlabel <= 1 << 20, "invalid flowlabel: {:x}", flowlabel);
1319 self.flowlabel = flowlabel;
1320 }
1321}
1322
1323impl Ipv6HeaderBuilder for Ipv6PacketBuilder {
1324 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1325 self
1326 }
1327
1328 fn extension_headers_len(&self) -> usize {
1329 0
1330 }
1331
1332 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1333 &self,
1334 buffer: &mut BV,
1335 next_header: NextHeader,
1336 payload_len: usize,
1337 ) {
1338 buffer
1339 .write_obj_front(&FixedHeader::new(
1340 self.dscp_and_ecn,
1341 self.flowlabel,
1342 {
1343 debug_assert!(payload_len <= u16::MAX as usize);
1350 payload_len as u16
1351 },
1352 next_header.into(),
1353 self.hop_limit,
1354 self.src_ip,
1355 self.dst_ip,
1356 ))
1357 .expect("not enough bytes for IPv6 fixed header");
1358 }
1359}
1360
1361impl NestablePacketBuilder for Ipv6PacketBuilder {
1362 impl_packet_builder_base! {}
1363}
1364
1365impl<C: IpSerializationContext<Ipv6>> PacketBuilder<C> for Ipv6PacketBuilder {
1366 impl_packet_builder! {}
1367}
1368
1369impl<C: IpSerializationContext<Ipv6>> PartialPacketBuilder<C> for Ipv6PacketBuilder {
1370 impl_partial_packet_builder! {}
1371}
1372
1373#[derive(Debug, Clone)]
1375pub struct Ipv6PacketBuilderWithHbhOptions<'a, I> {
1376 prefix_builder: Ipv6PacketBuilder,
1377 hbh_options: AlignedRecordSequenceBuilder<HopByHopOption<'a>, I>,
1378}
1379
1380impl<'a, I> Ipv6PacketBuilderWithHbhOptions<'a, I>
1381where
1382 I: Iterator + Clone,
1383 I::Item: Borrow<HopByHopOption<'a>>,
1384{
1385 pub fn new<T: IntoIterator<Item = I::Item, IntoIter = I>>(
1387 prefix_builder: Ipv6PacketBuilder,
1388 options: T,
1389 ) -> Option<Ipv6PacketBuilderWithHbhOptions<'a, I>> {
1390 let iter = options.into_iter();
1391 if iter
1394 .clone()
1395 .filter(|r| matches!(r.borrow().data, HopByHopOptionData::RouterAlert { .. }))
1396 .count()
1397 > 1
1398 {
1399 return None;
1400 }
1401 let hbh_options = AlignedRecordSequenceBuilder::new(2, iter);
1402 if next_multiple_of_eight(2 + hbh_options.serialized_len()) > IPV6_HBH_OPTIONS_MAX_LEN {
1404 return None;
1405 }
1406 Some(Ipv6PacketBuilderWithHbhOptions { prefix_builder, hbh_options })
1407 }
1408
1409 fn aligned_hbh_len(&self) -> usize {
1410 let opt_len = self.hbh_options.serialized_len();
1411 let hbh_len = opt_len + 2;
1412 next_multiple_of_eight(hbh_len)
1413 }
1414}
1415
1416fn next_multiple_of_eight(x: usize) -> usize {
1417 (x + 7) & (!7)
1418}
1419
1420impl<C: IpSerializationContext<Ipv6>> IpPacketBuilder<C, Ipv6> for Ipv6PacketBuilder {
1421 fn new(src_ip: Ipv6Addr, dst_ip: Ipv6Addr, ttl: u8, proto: Ipv6Proto) -> Self {
1422 Ipv6PacketBuilder::new(src_ip, dst_ip, ttl, proto)
1423 }
1424
1425 fn src_ip(&self) -> Ipv6Addr {
1426 self.src_ip
1427 }
1428
1429 fn set_src_ip(&mut self, addr: Ipv6Addr) {
1430 self.src_ip = addr;
1431 }
1432
1433 fn dst_ip(&self) -> Ipv6Addr {
1434 self.dst_ip
1435 }
1436
1437 fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1438 self.dst_ip = addr;
1439 }
1440
1441 fn proto(&self) -> Ipv6Proto {
1442 self.proto
1443 }
1444
1445 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1446 self.dscp_and_ecn = dscp_and_ecn;
1447 }
1448}
1449
1450impl<'a, I> Ipv6HeaderBuilder for Ipv6PacketBuilderWithHbhOptions<'a, I>
1451where
1452 I: Iterator + Clone,
1453 I::Item: Borrow<HopByHopOption<'a>>,
1454{
1455 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1456 &self.prefix_builder
1457 }
1458
1459 fn extension_headers_len(&self) -> usize {
1460 self.prefix_builder.extension_headers_len() + self.aligned_hbh_len()
1461 }
1462
1463 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1464 &self,
1465 buffer: &mut BV,
1466 next_header: NextHeader,
1467 payload_len: usize,
1468 ) {
1469 let aligned_hbh_len = self.aligned_hbh_len();
1470 self.prefix_builder.serialize_header(
1472 buffer,
1473 NextHeader::Extension(Ipv6ExtHdrType::HopByHopOptions),
1474 payload_len + aligned_hbh_len,
1475 );
1476 let mut hbh_header = buffer.take_front(aligned_hbh_len).unwrap();
1478 let hbh_header: &mut [u8] = hbh_header.as_mut();
1479 hbh_header[0] = next_header.into();
1480 hbh_header[1] = u8::try_from((aligned_hbh_len - 8) / 8).expect("extension header too big");
1481 self.hbh_options.serialize_into(&mut hbh_header[2..]);
1482 }
1483}
1484
1485impl<'a, I> NestablePacketBuilder for Ipv6PacketBuilderWithHbhOptions<'a, I>
1486where
1487 I: Iterator + Clone,
1488 I::Item: Borrow<HopByHopOption<'a>>,
1489{
1490 impl_packet_builder_base! {}
1491}
1492
1493impl<'a, I, C: IpSerializationContext<Ipv6>> PacketBuilder<C>
1494 for Ipv6PacketBuilderWithHbhOptions<'a, I>
1495where
1496 I: Iterator + Clone,
1497 I::Item: Borrow<HopByHopOption<'a>>,
1498{
1499 impl_packet_builder! {}
1500}
1501
1502impl<'a, I, C: IpSerializationContext<Ipv6>> PartialPacketBuilder<C>
1503 for Ipv6PacketBuilderWithHbhOptions<'a, I>
1504where
1505 I: Iterator + Clone,
1506 I::Item: Borrow<HopByHopOption<'a>>,
1507{
1508 impl_partial_packet_builder! {}
1509}
1510
1511impl<'a, C: IpSerializationContext<Ipv6>, I> IpPacketBuilder<C, Ipv6>
1512 for Ipv6PacketBuilderWithHbhOptions<'a, I>
1513where
1514 I: Iterator<Item: Borrow<HopByHopOption<'a>>> + Debug + Default + Clone,
1515{
1516 fn new(src_ip: Ipv6Addr, dst_ip: Ipv6Addr, ttl: u8, proto: Ipv6Proto) -> Self {
1517 Ipv6PacketBuilderWithHbhOptions::new(
1518 Ipv6PacketBuilder::new(src_ip, dst_ip, ttl, proto),
1519 I::default(),
1520 )
1521 .expect("packet builder with no options should be valid")
1522 }
1523
1524 fn src_ip(&self) -> Ipv6Addr {
1525 self.prefix_builder.src_ip
1526 }
1527
1528 fn set_src_ip(&mut self, addr: Ipv6Addr) {
1529 self.prefix_builder.src_ip = addr;
1530 }
1531
1532 fn dst_ip(&self) -> Ipv6Addr {
1533 self.prefix_builder.dst_ip
1534 }
1535
1536 fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1537 self.prefix_builder.dst_ip = addr;
1538 }
1539
1540 fn proto(&self) -> Ipv6Proto {
1541 self.prefix_builder.proto
1542 }
1543
1544 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1545 <Ipv6PacketBuilder as IpPacketBuilder<C, Ipv6>>::set_dscp_and_ecn(
1546 &mut self.prefix_builder,
1547 dscp_and_ecn,
1548 )
1549 }
1550}
1551
1552#[derive(Debug, Clone, Eq, PartialEq)]
1554struct Ipv6PerFragmentMeta<B> {
1555 ext_hdrs: B,
1556 first_ext_hdr: Ipv6ExtHdrType,
1557 last_next_hdr_offset: usize,
1558}
1559
1560#[derive(Debug, Clone, Eq, PartialEq)]
1565pub struct Ipv6PerFragmentHeaderBuilder<B> {
1566 prefix_builder: Ipv6PacketBuilder,
1567 meta: Option<Ipv6PerFragmentMeta<B>>,
1568}
1569
1570impl<B: AsRef<[u8]>> Ipv6PerFragmentHeaderBuilder<B> {
1571 pub fn header_len(&self) -> usize {
1573 self.extension_headers_len() + IPV6_FIXED_HDR_LEN
1574 }
1575
1576 pub fn as_ref(&self) -> Ipv6PerFragmentHeaderBuilder<&[u8]> {
1579 let Self { prefix_builder, meta } = self;
1580 let meta = meta.as_ref().map(
1581 |Ipv6PerFragmentMeta { ext_hdrs, first_ext_hdr, last_next_hdr_offset }| {
1582 Ipv6PerFragmentMeta {
1583 ext_hdrs: ext_hdrs.as_ref(),
1584 first_ext_hdr: *first_ext_hdr,
1585 last_next_hdr_offset: *last_next_hdr_offset,
1586 }
1587 },
1588 );
1589 Ipv6PerFragmentHeaderBuilder { prefix_builder: prefix_builder.clone(), meta }
1590 }
1591}
1592
1593impl<B: AsRef<[u8]>> Ipv6HeaderBuilder for Ipv6PerFragmentHeaderBuilder<B> {
1594 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1595 &self.prefix_builder
1596 }
1597
1598 fn extension_headers_len(&self) -> usize {
1599 self.meta
1600 .as_ref()
1601 .map(|Ipv6PerFragmentMeta { ext_hdrs, .. }| ext_hdrs.as_ref().len())
1602 .unwrap_or(0)
1603 }
1604
1605 fn serialize_header<BB: SplitByteSliceMut, BV: BufferViewMut<BB>>(
1606 &self,
1607 buffer: &mut BV,
1608 next_header: NextHeader,
1609 payload_len: usize,
1610 ) {
1611 let Self { prefix_builder, meta } = self;
1612 match meta {
1613 None => prefix_builder.serialize_header(buffer, next_header, payload_len),
1614 Some(Ipv6PerFragmentMeta { ext_hdrs, first_ext_hdr, last_next_hdr_offset }) => {
1615 let ext_hdrs = ext_hdrs.as_ref();
1616 let ext_hdrs_len = ext_hdrs.len();
1617 prefix_builder.serialize_header(
1618 buffer,
1619 NextHeader::Extension(*first_ext_hdr),
1620 payload_len + ext_hdrs_len,
1621 );
1622 let mut ext_hdr_buf =
1623 buffer.take_front(ext_hdrs_len).expect("buffer should be long enough");
1624 let ext_hdr_buf: &mut [u8] = ext_hdr_buf.as_mut();
1625 ext_hdr_buf.copy_from_slice(ext_hdrs);
1626 ext_hdr_buf[*last_next_hdr_offset] = u8::from(next_header);
1627 }
1628 }
1629 }
1630}
1631
1632impl<B: AsRef<[u8]>> NestablePacketBuilder for Ipv6PerFragmentHeaderBuilder<B> {
1633 impl_packet_builder_base! {}
1634}
1635
1636impl<B: AsRef<[u8]>, C: IpSerializationContext<Ipv6>> PacketBuilder<C>
1637 for Ipv6PerFragmentHeaderBuilder<B>
1638{
1639 impl_packet_builder! {}
1640}
1641
1642impl<B: AsRef<[u8]>, C: IpSerializationContext<Ipv6>> PartialPacketBuilder<C>
1643 for Ipv6PerFragmentHeaderBuilder<B>
1644{
1645 impl_partial_packet_builder! {}
1646}
1647
1648#[derive(Debug, Eq, PartialEq)]
1657pub struct Ipv6PacketBuilderWithFragmentHeader<B> {
1658 header_builder: B,
1659 fragment_offset: FragmentOffset,
1660 more_fragments: bool,
1661 identification: u32,
1662}
1663
1664impl<B: Ipv6HeaderBefore<Self>> Ipv6PacketBuilderWithFragmentHeader<B> {
1665 pub fn new(
1667 header_builder: B,
1668 fragment_offset: FragmentOffset,
1669 more_fragments: bool,
1670 identification: u32,
1671 ) -> Self {
1672 Self { header_builder, fragment_offset, more_fragments, identification }
1673 }
1674}
1675
1676impl<B> Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>> for Ipv6PacketBuilder {}
1677impl<B, I> Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>>
1678 for Ipv6PacketBuilderWithHbhOptions<'_, I>
1679{
1680}
1681impl<HB, B> Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<HB>>
1682 for Ipv6PerFragmentHeaderBuilder<B>
1683{
1684}
1685
1686pub trait Ipv6PacketBuilderBeforeFragment:
1689 Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<Self>> + Ipv6HeaderBuilder + Sized
1690{
1691}
1692impl<B> Ipv6PacketBuilderBeforeFragment for B where
1693 B: Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<Self>> + Ipv6HeaderBuilder + Sized
1694{
1695}
1696
1697impl<B: Ipv6HeaderBuilder> Ipv6HeaderBuilder for Ipv6PacketBuilderWithFragmentHeader<B> {
1698 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1699 self.header_builder.fixed_header()
1700 }
1701
1702 fn extension_headers_len(&self) -> usize {
1703 self.header_builder.extension_headers_len() + IPV6_FRAGMENT_EXT_HDR_LEN
1704 }
1705
1706 fn serialize_header<BB: SplitByteSliceMut, BV: BufferViewMut<BB>>(
1707 &self,
1708 buffer: &mut BV,
1709 next_header: NextHeader,
1710 payload_len: usize,
1711 ) {
1712 let Self { header_builder, fragment_offset, more_fragments, identification } = self;
1713 let payload_len = payload_len + IPV6_FRAGMENT_EXT_HDR_LEN;
1714 header_builder.serialize_header(
1715 buffer,
1716 NextHeader::Extension(Ipv6ExtHdrType::Fragment),
1717 payload_len,
1718 );
1719 buffer.write_obj_front(&u8::from(next_header)).unwrap();
1720 let _: BB = buffer.take_front_zero(1).unwrap();
1722 let more_fragments = u16::from(*more_fragments);
1723 buffer
1724 .write_obj_front(&U16::new(fragment_offset.into_raw() << 3 | more_fragments))
1725 .unwrap();
1726 buffer.write_obj_front(&U32::new(*identification)).unwrap();
1727 }
1728}
1729
1730impl<B: Ipv6HeaderBuilder> NestablePacketBuilder for Ipv6PacketBuilderWithFragmentHeader<B> {
1731 impl_packet_builder_base! {}
1732}
1733
1734impl<B: Ipv6HeaderBuilder, C: IpSerializationContext<Ipv6>> PacketBuilder<C>
1735 for Ipv6PacketBuilderWithFragmentHeader<B>
1736{
1737 impl_packet_builder! {}
1738}
1739
1740impl<B: Ipv6HeaderBuilder, C: IpSerializationContext<Ipv6>> PartialPacketBuilder<C>
1741 for Ipv6PacketBuilderWithFragmentHeader<B>
1742{
1743 impl_partial_packet_builder! {}
1744}
1745
1746pub(crate) fn reassemble_fragmented_packet<
1752 'a,
1753 B: SplitByteSliceMut,
1754 BV: BufferViewMut<B>,
1755 I: Iterator<Item = &'a [u8]>,
1756>(
1757 mut buffer: BV,
1758 header: &[u8],
1759 body_fragments: I,
1760) -> IpParseResult<Ipv6, ()> {
1761 assert!(header.len() >= IPV6_FIXED_HDR_LEN);
1762
1763 let bytes = buffer.as_mut();
1764
1765 bytes[0..header.len()].copy_from_slice(header);
1767 let mut byte_count = header.len();
1768
1769 for p in body_fragments {
1771 bytes[byte_count..byte_count + p.len()].copy_from_slice(p);
1772 byte_count += p.len();
1773 }
1774
1775 let payload_length = byte_count - IPV6_FIXED_HDR_LEN;
1787
1788 if payload_length > usize::from(u16::MAX) {
1791 return debug_err!(
1792 Err(ParseError::Format.into()),
1793 "fragmented packet payload length of {} bytes is too large",
1794 payload_length
1795 );
1796 }
1797
1798 let mut header = Ref::<_, FixedHeader>::from_prefix(bytes).unwrap().0;
1801
1802 header.payload_len.set(u16::try_from(payload_length).unwrap());
1804
1805 Ok(())
1806}
1807
1808#[cfg(test)]
1809mod tests {
1810 use assert_matches::assert_matches;
1811 use packet::{Buf, FragmentedBuffer, ParseBuffer, PartialSerializeResult};
1812 use test_case::test_case;
1813
1814 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1815 use crate::testutil::*;
1816
1817 use super::ext_hdrs::*;
1818 use super::*;
1819
1820 const DEFAULT_SRC_IP: Ipv6Addr =
1821 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1822 const DEFAULT_DST_IP: Ipv6Addr =
1823 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1824
1825 const DEFAULT_V4_SRC_IP: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1826 const DEFAULT_V4_DST_IP: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1827
1828 #[test]
1829 fn test_parse_serialize_full_tcp() {
1830 use crate::testdata::syn_v6::*;
1831
1832 let mut buf = ETHERNET_FRAME.bytes;
1833 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1834 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1835
1836 let mut body = frame.body();
1837 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1838 verify_ipv6_packet(&packet, IPV6_PACKET);
1839
1840 let buffer = packet
1842 .body()
1843 .into_serializer()
1844 .wrap_in(packet.builder())
1845 .wrap_in(frame.builder())
1846 .serialize_vec_outer(&mut NoOpSerializationContext)
1847 .unwrap();
1848 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1849
1850 assert_eq!(&packet.to_vec()[..], IPV6_PACKET.bytes);
1852 }
1853
1854 #[test]
1855 fn test_parse_serialize_full_udp() {
1856 use crate::testdata::dns_request_v6::*;
1857
1858 let mut buf = ETHERNET_FRAME.bytes;
1859 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1860 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1861
1862 let mut body = frame.body();
1863 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1864 verify_ipv6_packet(&packet, IPV6_PACKET);
1865
1866 let buffer = packet
1868 .body()
1869 .into_serializer()
1870 .wrap_in(packet.builder())
1871 .wrap_in(frame.builder())
1872 .serialize_vec_outer(&mut NoOpSerializationContext)
1873 .unwrap();
1874 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1875
1876 assert_eq!(&packet.to_vec()[..], IPV6_PACKET.bytes);
1878 }
1879
1880 #[test]
1881 fn test_parse_serialize_with_extension_headers() {
1882 use crate::testdata::mld_router_report::*;
1885
1886 let mut buf = REPORT;
1887 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1888 assert_eq!(packet.iter_extension_hdrs().count(), 1);
1889
1890 assert_eq!(&packet.to_vec()[..], REPORT);
1895 }
1896
1897 fn fixed_hdr_to_bytes(fixed_hdr: FixedHeader) -> [u8; IPV6_FIXED_HDR_LEN] {
1898 zerocopy::transmute!(fixed_hdr)
1899 }
1900
1901 fn new_fixed_hdr() -> FixedHeader {
1903 FixedHeader::new(
1904 DscpAndEcn::new(0, 2),
1905 0x77,
1906 0,
1907 IpProto::Tcp.into(),
1908 64,
1909 DEFAULT_SRC_IP,
1910 DEFAULT_DST_IP,
1911 )
1912 }
1913
1914 #[test]
1915 fn test_parse() {
1916 let mut buf = &fixed_hdr_to_bytes(new_fixed_hdr())[..];
1917 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1918 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1919 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1920 assert_eq!(packet.flowlabel(), 0x77);
1921 assert_eq!(packet.hop_limit(), 64);
1922 assert_eq!(packet.fixed_hdr.next_hdr, IpProto::Tcp.into());
1923 assert_eq!(packet.proto(), IpProto::Tcp.into());
1924 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1925 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1926 assert_eq!(packet.body(), []);
1927 }
1928
1929 #[test]
1930 fn test_parse_with_ext_hdrs() {
1931 #[rustfmt::skip]
1932 let mut buf = [
1933 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1935 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1936
1937 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,
1952 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1953
1954 IpProto::Tcp.into(), 1, 0, 1, 0, 1, 1, 0, 1, 6, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
1964 ];
1965 let mut fixed_hdr = new_fixed_hdr();
1966 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
1967 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1968 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1969 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1970 let mut buf = &buf[..];
1971 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1972 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1973 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1974 assert_eq!(packet.flowlabel(), 0x77);
1975 assert_eq!(packet.hop_limit(), 64);
1976 assert_eq!(packet.fixed_hdr.next_hdr, Ipv6ExtHdrType::HopByHopOptions.into());
1977 assert_eq!(packet.proto(), IpProto::Tcp.into());
1978 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1979 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1980 assert_eq!(packet.body(), [1, 2, 3, 4, 5]);
1981 let ext_hdrs: Vec<Ipv6ExtensionHeader<'_>> = packet.iter_extension_hdrs().collect();
1982 assert_eq!(ext_hdrs.len(), 3);
1983 if let Ipv6ExtensionHeader::HopByHopOptions { options } = &ext_hdrs[0] {
1985 assert_eq!(options.iter().count(), 0);
1987 } else {
1988 panic!("Should have matched HopByHopOptions!");
1989 }
1990
1991 if let Ipv6ExtensionHeader::Routing { routing_data } = &ext_hdrs[1] {
1993 assert_eq!(routing_data.routing_type(), Err(RoutingTypeParseError::UnsupportedType(0)));
1994 assert_eq!(routing_data.segments_left(), 0);
1995 } else {
1996 panic!("Should have matched RoutingExtensionHeader: {:?}", &ext_hdrs[1]);
1997 }
1998
1999 if let Ipv6ExtensionHeader::DestinationOptions { options } = &ext_hdrs[2] {
2001 assert_eq!(options.iter().count(), 0);
2003 } else {
2004 panic!("Should have matched DestinationOptions!");
2005 }
2006
2007 #[rustfmt::skip]
2009 let mut buf = [
2010 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2012 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2013
2014 Ipv6Proto::NoNextHeader.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2023 ];
2024 let mut fixed_hdr = new_fixed_hdr();
2025 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2026 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2027 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2028 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2029 let mut buf = &buf[..];
2030 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2031 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
2032 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
2033 assert_eq!(packet.flowlabel(), 0x77);
2034 assert_eq!(packet.hop_limit(), 64);
2035 assert_eq!(packet.fixed_hdr.next_hdr, Ipv6ExtHdrType::HopByHopOptions.into());
2036 assert_eq!(packet.proto(), Ipv6Proto::NoNextHeader);
2037 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
2038 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
2039 assert_eq!(packet.body(), [1, 2, 3, 4, 5]);
2040 let ext_hdrs: Vec<Ipv6ExtensionHeader<'_>> = packet.iter_extension_hdrs().collect();
2041 assert_eq!(ext_hdrs.len(), 1);
2042 if let Ipv6ExtensionHeader::HopByHopOptions { options } = &ext_hdrs[0] {
2044 assert_eq!(options.iter().count(), 0);
2046 } else {
2047 panic!("Should have matched HopByHopOptions!");
2048 }
2049 }
2050
2051 #[test]
2052 fn test_parse_error() {
2053 let mut fixed_hdr = new_fixed_hdr();
2055 fixed_hdr.version_tc_flowlabel[0] = 0x50;
2056 assert_eq!(
2057 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
2058 ParseError::Format.into()
2059 );
2060
2061 let mut fixed_hdr = new_fixed_hdr();
2063 fixed_hdr.payload_len = U16::new(2);
2064 assert_eq!(
2065 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
2066 ParseError::Format.into()
2067 );
2068
2069 let mut fixed_hdr = new_fixed_hdr();
2071 fixed_hdr.next_hdr = 255;
2072 let packet = fixed_hdr_to_bytes(fixed_hdr);
2073
2074 assert!((&packet[..]).parse::<Ipv6PacketRaw<_>>().is_ok());
2076
2077 assert_eq!(
2079 (&packet[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
2080 Ipv6ParseError::ParameterProblem {
2081 src_ip: DEFAULT_SRC_IP,
2082 dst_ip: DEFAULT_DST_IP,
2083 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2084 pointer: u32::from(NEXT_HEADER_OFFSET),
2085 must_send_icmp: false,
2086 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2087 }
2088 );
2089
2090 let mut fixed_hdr = new_fixed_hdr();
2092 fixed_hdr.next_hdr = Ipv4Proto::Icmp.into();
2093 assert_eq!(
2094 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
2095 Ipv6ParseError::ParameterProblem {
2096 src_ip: DEFAULT_SRC_IP,
2097 dst_ip: DEFAULT_DST_IP,
2098 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2099 pointer: u32::from(NEXT_HEADER_OFFSET),
2100 must_send_icmp: false,
2101 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2102 }
2103 );
2104
2105 #[rustfmt::skip]
2107 let mut buf = [
2108 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2111
2112 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,
2120 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2121
2122 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2131 ];
2132 let mut fixed_hdr = new_fixed_hdr();
2133 fixed_hdr.next_hdr = Ipv6ExtHdrType::Routing.into();
2134 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2135 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2136 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2137 let mut buf = &buf[..];
2138 assert_eq!(
2139 buf.parse::<Ipv6Packet<_>>().unwrap_err(),
2140 Ipv6ParseError::ParameterProblem {
2141 src_ip: DEFAULT_SRC_IP,
2142 dst_ip: DEFAULT_DST_IP,
2143 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2144 pointer: IPV6_FIXED_HDR_LEN as u32,
2145 must_send_icmp: false,
2146 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2147 }
2148 );
2149
2150 #[rustfmt::skip]
2152 let mut buf = [
2153 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2155 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2156
2157 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,
2165 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2166
2167 1, 2, 3, 4, 5,
2169 ];
2170 let mut fixed_hdr = new_fixed_hdr();
2171 fixed_hdr.next_hdr = Ipv6ExtHdrType::Routing.into();
2172 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2173 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2174 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2175 let expected_error = Ipv6ParseError::ParameterProblem {
2176 src_ip: DEFAULT_SRC_IP,
2177 dst_ip: DEFAULT_DST_IP,
2178 code: Icmpv6ParameterProblemCode::ErroneousHeaderField,
2179 pointer: (IPV6_FIXED_HDR_LEN as u32) + 2,
2180 must_send_icmp: true,
2181 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2182 };
2183 assert_eq!((&buf[..]).parse::<Ipv6Packet<_>>().unwrap_err(), expected_error);
2184
2185 buf[IPV6_FIXED_HDR_LEN] = 250; assert_eq!((&buf[..]).parse::<Ipv6Packet<_>>().unwrap_err(), expected_error);
2191 }
2192
2193 #[test]
2194 fn test_parse_all_next_header_values() {
2195 let mut buf = [
2201 0x81, 0x13, 0x27, 0xeb, 0x75, 0x92, 0x33, 0x89, 0x01, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
2202 0x03, 0x70, 0x00, 0x22, 0xf7, 0x30, 0x2c, 0x06, 0xfe, 0xc9, 0x00, 0x2d, 0x3b, 0xeb,
2203 0xad, 0x3e, 0x5c, 0x41, 0xc8, 0x70, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x11, 0x00,
2204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x4f, 0x4f, 0x6f, 0x4f, 0x4f, 0x4f, 0x4f,
2205 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x19, 0x19,
2206 0x19, 0x19, 0x19, 0x4f, 0x4f, 0x4f, 0x4f, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2207 0x00, 0x4f, 0x4f, 0x5a, 0x5a, 0x5a, 0xc9, 0x5a, 0x46, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
2208 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0xe4, 0x5a, 0x5a, 0x5a, 0x5a,
2209 ];
2210
2211 assert_matches!(
2214 (&buf[..]).parse::<Ipv6Packet<_>>(),
2215 Err(Ipv6ParseError::ParameterProblem {
2216 src_ip: _,
2217 dst_ip: _,
2218 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2219 pointer: 6,
2220 must_send_icmp: false,
2221 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2222 })
2223 );
2224
2225 for b in 0u8..=255 {
2228 buf[6] = b;
2230 let _: Result<_, _> = (&buf[..]).parse::<Ipv6Packet<_>>();
2231 }
2232 }
2233
2234 #[test]
2235 fn test_esp_packet() {
2236 const ESP_NEXT_HEADER: u8 = 50;
2241
2242 let mut fixed_hdr = new_fixed_hdr();
2244 fixed_hdr.next_hdr = ESP_NEXT_HEADER;
2245 fixed_hdr.payload_len = U16::new(8);
2246 let mut buf = fixed_hdr_to_bytes(fixed_hdr).to_vec();
2247 buf.extend_from_slice(&[0; 8]);
2248
2249 assert_matches!(
2251 (&buf[..]).parse::<Ipv6Packet<_>>(),
2252 Err(Ipv6ParseError::ParameterProblem {
2253 src_ip: _,
2254 dst_ip: _,
2255 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2256 pointer: 6, must_send_icmp: false,
2258 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2259 })
2260 );
2261
2262 let mut buf_ref = &buf[..];
2264 assert!(buf_ref.parse::<Ipv6PacketRaw<_>>().is_ok());
2265
2266 let mut fixed_hdr = new_fixed_hdr();
2268 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2269 fixed_hdr.payload_len = U16::new(16);
2270 let mut buf = fixed_hdr_to_bytes(fixed_hdr).to_vec();
2271 buf.extend_from_slice(&[ESP_NEXT_HEADER, 0, 0, 0, 0, 0, 0, 0]);
2273 buf.extend_from_slice(&[0; 8]);
2275
2276 assert_matches!(
2278 (&buf[..]).parse::<Ipv6Packet<_>>(),
2279 Err(Ipv6ParseError::ParameterProblem {
2280 src_ip: _,
2281 dst_ip: _,
2282 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2283 pointer: 40, must_send_icmp: false,
2285 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2286 })
2287 );
2288
2289 let mut buf_ref = &buf[..];
2291 assert!(buf_ref.parse::<Ipv6PacketRaw<_>>().is_ok());
2292 }
2293
2294 #[test]
2295 fn test_parse_ext_hdr_unrecognized_next_header() {
2296 #[rustfmt::skip]
2300 let mut buf = [
2301 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2303 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2304
2305 250, 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2314 ];
2315 let mut fixed_hdr = new_fixed_hdr();
2316 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2317 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2318 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2319 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2320
2321 assert!((&buf[..]).parse::<Ipv6PacketRaw<_>>().is_ok());
2323
2324 assert_eq!(
2326 (&buf[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
2327 Ipv6ParseError::ParameterProblem {
2328 src_ip: DEFAULT_SRC_IP,
2329 dst_ip: DEFAULT_DST_IP,
2330 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2331 pointer: IPV6_FIXED_HDR_LEN as u32,
2332 must_send_icmp: false,
2333 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2334 }
2335 );
2336 }
2337
2338 #[test]
2339 fn test_partial_parse() {
2340 use core::convert::TryInto as _;
2341 use core::ops::Deref as _;
2342
2343 #[rustfmt::skip]
2345 let mut buf = [
2346 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2348 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2349
2350 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2359 ];
2360 let len = buf.len() - IPV6_FIXED_HDR_LEN;
2361 let len = len.try_into().unwrap();
2362 let make_fixed_hdr = || {
2363 let mut fixed_hdr = new_fixed_hdr();
2364 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2365 fixed_hdr.payload_len = U16::new(len);
2366 fixed_hdr
2367 };
2368 const MALFORMED_BYTE: u8 = 10;
2370 buf[IPV6_FIXED_HDR_LEN + 1] = MALFORMED_BYTE;
2371 let fixed_hdr = fixed_hdr_to_bytes(make_fixed_hdr());
2372 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr);
2373 let mut buf = &buf[..];
2374 let partial = buf.parse::<Ipv6PacketRaw<_>>().unwrap();
2375 let Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto } = &partial;
2376 assert_eq!(fixed_hdr.deref(), &make_fixed_hdr());
2377 let b = extension_hdrs.as_ref().incomplete().unwrap();
2378 assert_eq!(*b, &[IpProto::Tcp.into(), MALFORMED_BYTE][..]);
2379 assert_eq!(body_proto, &Err(ExtHdrParseError));
2380 assert!(Ipv6Packet::try_from_raw(partial).is_err());
2381
2382 let mut buf = [
2384 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,
2386 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
2388 ];
2389 let make_fixed_hdr = || {
2390 let mut fixed_hdr = new_fixed_hdr();
2391 fixed_hdr.next_hdr = IpProto::Tcp.into();
2392 fixed_hdr.payload_len = U16::new(10);
2393 fixed_hdr
2394 };
2395 let fixed_hdr = fixed_hdr_to_bytes(make_fixed_hdr());
2396 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr);
2397 let mut parsebuff = &buf[..];
2398 let partial = parsebuff.parse::<Ipv6PacketRaw<_>>().unwrap();
2399 let Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto } = &partial;
2400 assert_eq!(fixed_hdr.deref(), &make_fixed_hdr());
2401 assert_eq!(extension_hdrs.as_ref().complete().unwrap().deref(), []);
2402 let (body, proto) = body_proto.unwrap();
2403 assert_eq!(body.incomplete().unwrap(), &buf[IPV6_FIXED_HDR_LEN..]);
2404 assert_eq!(proto, IpProto::Tcp.into());
2405 assert!(Ipv6Packet::try_from_raw(partial).is_err());
2406 }
2407
2408 fn new_builder() -> Ipv6PacketBuilder {
2410 Ipv6PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, 64, IpProto::Tcp.into())
2411 }
2412
2413 #[test]
2414 fn test_serialize() {
2415 let mut builder = new_builder();
2416 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
2417 builder.flowlabel(0x10405);
2418 let mut buf = (&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2419 .into_serializer()
2420 .wrap_in(builder)
2421 .serialize_vec_outer(&mut NoOpSerializationContext)
2422 .unwrap();
2423 assert_eq!(
2425 buf.as_ref(),
2426 &[
2427 100, 177, 4, 5, 0, 10, 6, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
2428 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, 1, 2, 3, 4,
2429 5, 6, 7, 8, 9
2430 ][..],
2431 );
2432
2433 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2434 assert_eq!(packet.dscp_and_ecn().dscp(), 0x12);
2437 assert_eq!(packet.dscp_and_ecn().ecn(), 3);
2438 assert_eq!(packet.flowlabel(), 0x10405);
2439 }
2440
2441 #[test]
2442 fn test_partial_serialize() {
2443 let mut builder = new_builder();
2444 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
2445 builder.flowlabel(0x10405);
2446 const BODY: &[u8] = &[0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2447 let packet = (&BODY).into_serializer().wrap_in(builder);
2448
2449 const HEADER: &[u8] = &[
2452 100, 177, 4, 5, 0, 10, 6, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
2453 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
2454 ];
2455 const PACKET_SIZE: usize = HEADER.len() + BODY.len();
2456
2457 let buf = assert_matches!(
2460 packet.partial_serialize(&mut NoOpSerializationContext, packet::new_buf_vec),
2461 Ok(PartialSerializeResult::NewBuffer { buffer, total_size: PACKET_SIZE }) => buffer
2462 );
2463 assert_eq!(buf.as_ref(), HEADER);
2464 }
2465
2466 #[test]
2467 fn test_serialize_zeroes() {
2468 let mut buf_0 = [0; IPV6_FIXED_HDR_LEN];
2471 let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], IPV6_FIXED_HDR_LEN..)
2472 .wrap_in(new_builder())
2473 .serialize_vec_outer(&mut NoOpSerializationContext)
2474 .unwrap()
2475 .unwrap_a();
2476 let mut buf_1 = [0xFF; IPV6_FIXED_HDR_LEN];
2477 let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], IPV6_FIXED_HDR_LEN..)
2478 .wrap_in(new_builder())
2479 .serialize_vec_outer(&mut NoOpSerializationContext)
2480 .unwrap()
2481 .unwrap_a();
2482 assert_eq!(&buf_0[..], &buf_1[..]);
2483 }
2484
2485 #[test]
2486 fn test_packet_builder_proto_not_next_header() {
2487 let mut buf = (&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2491 .into_serializer()
2492 .wrap_in(
2493 Ipv6PacketBuilderWithHbhOptions::new(
2494 new_builder(),
2495 &[HopByHopOption {
2496 action: ExtensionHeaderOptionAction::SkipAndContinue,
2497 mutable: false,
2498 data: HopByHopOptionData::RouterAlert { data: 0 },
2499 }],
2500 )
2501 .unwrap(),
2502 )
2503 .serialize_vec_outer(&mut NoOpSerializationContext)
2504 .unwrap();
2505 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2506 assert_eq!(packet.proto(), IpProto::Tcp.into());
2507 assert_eq!(packet.next_header(), Ipv6ExtHdrType::HopByHopOptions.into());
2508 }
2509
2510 #[test]
2511 #[should_panic(expected = "SizeLimitExceeded, Nested { inner: Buf { buf:")]
2512 fn test_serialize_panic_packet_length() {
2513 let _: Buf<&mut [u8]> = Buf::new(&mut [0; 1 << 16][..], ..)
2516 .wrap_in(new_builder())
2517 .serialize_vec_outer(&mut NoOpSerializationContext)
2518 .unwrap()
2519 .unwrap_a();
2520 }
2521
2522 #[test]
2523 #[should_panic(expected = "packet must have at least one extension header")]
2524 fn test_copy_header_bytes_for_fragment_without_ext_hdrs() {
2525 let mut buf = &fixed_hdr_to_bytes(new_fixed_hdr())[..];
2526 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2527 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2528 }
2529
2530 #[test]
2531 #[should_panic(expected = "exhausted all extension headers without finding fragment header")]
2532 fn test_copy_header_bytes_for_fragment_with_1_ext_hdr_no_fragment() {
2533 #[rustfmt::skip]
2534 let mut buf = [
2535 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2537 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2538
2539 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2548 ];
2549 let mut fixed_hdr = new_fixed_hdr();
2550 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2551 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2552 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2553 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2554 let mut buf = &buf[..];
2555 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2556 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2557 }
2558
2559 #[test]
2560 #[should_panic(expected = "exhausted all extension headers without finding fragment header")]
2561 fn test_copy_header_bytes_for_fragment_with_2_ext_hdr_no_fragment() {
2562 #[rustfmt::skip]
2563 let mut buf = [
2564 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2566 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2567
2568 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,
2585 ];
2586 let mut fixed_hdr = new_fixed_hdr();
2587 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2588 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2589 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2590 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2591 let mut buf = &buf[..];
2592 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2593 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2594 }
2595
2596 #[test]
2597 fn test_copy_header_bytes_for_fragment() {
2598 #[rustfmt::skip]
2603 let mut bytes = [
2604 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2606 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2607
2608 IpProto::Tcp.into(), 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5,
2616 ];
2617 let mut fixed_hdr = new_fixed_hdr();
2618 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2619 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2620 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2621 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2622 let mut buf = &bytes[..];
2623 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2624 let copied_bytes = packet.copy_header_bytes_for_fragment();
2625 bytes[6] = IpProto::Tcp.into();
2626 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN]);
2627
2628 #[rustfmt::skip]
2633 let mut bytes = [
2634 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2636 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2637
2638 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,
2653 ];
2654 let mut fixed_hdr = new_fixed_hdr();
2655 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2656 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2657 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2658 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2659 let mut buf = &bytes[..];
2660 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2661 let copied_bytes = packet.copy_header_bytes_for_fragment();
2662 bytes[IPV6_FIXED_HDR_LEN] = IpProto::Tcp.into();
2663 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN + 8]);
2664
2665 #[rustfmt::skip]
2670 let mut bytes = [
2671 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2673 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2674
2675 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,
2698 ];
2699 let mut fixed_hdr = new_fixed_hdr();
2700 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2701 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2702 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2703 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2704 let mut buf = &bytes[..];
2705 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2706 let copied_bytes = packet.copy_header_bytes_for_fragment();
2707 bytes[IPV6_FIXED_HDR_LEN + 8] = IpProto::Tcp.into();
2708 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN + 24]);
2709
2710 #[rustfmt::skip]
2715 let mut bytes = [
2716 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2718 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2719
2720 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,
2736 ];
2737 let mut fixed_hdr = new_fixed_hdr();
2738 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2739 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2740 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2741 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2742 let mut buf = &bytes[..];
2743 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2744 let copied_bytes = packet.copy_header_bytes_for_fragment();
2745 let mut expected_bytes = Vec::new();
2746 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2747 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2748 expected_bytes[6] = Ipv6ExtHdrType::DestinationOptions.into();
2749 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2750
2751 #[rustfmt::skip]
2756 let mut bytes = [
2757 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2759 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2760
2761 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,
2783 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2784
2785 1, 2, 3, 4, 5,
2787 ];
2788 let mut fixed_hdr = new_fixed_hdr();
2789 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2790 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2791 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2792 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2793 let mut buf = &bytes[..];
2794 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2795 let copied_bytes = packet.copy_header_bytes_for_fragment();
2796 let mut expected_bytes = Vec::new();
2797 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2798 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2799 expected_bytes[6] = Ipv6ExtHdrType::DestinationOptions.into();
2800 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2801
2802 #[rustfmt::skip]
2807 let mut bytes = [
2808 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2810 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2811
2812 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,
2835 ];
2836 let mut fixed_hdr = new_fixed_hdr();
2837 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2838 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2839 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2840 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2841 let mut buf = &bytes[..];
2842 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2843 let copied_bytes = packet.copy_header_bytes_for_fragment();
2844 let mut expected_bytes = Vec::new();
2845 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN + 8]);
2846 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 16..bytes.len() - 5]);
2847 expected_bytes[IPV6_FIXED_HDR_LEN] = Ipv6ExtHdrType::DestinationOptions.into();
2848 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2849
2850 #[rustfmt::skip]
2855 let mut bytes = [
2856 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2858 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2859
2860 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,
2874 ];
2875 let mut fixed_hdr = new_fixed_hdr();
2876 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2877 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2878 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2879 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2880 let mut buf = &bytes[..];
2881 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2882 let copied_bytes = packet.copy_header_bytes_for_fragment();
2883 let mut expected_bytes = Vec::new();
2884 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2885 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2886 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2887
2888 #[rustfmt::skip]
2894 let mut bytes = [
2895 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2897 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2898
2899 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,
2914 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2915
2916 IpProto::Tcp.into(), 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5,
2924 ];
2925 let mut fixed_hdr = new_fixed_hdr();
2926 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2927 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2928 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2929 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2930 let mut buf = &bytes[..];
2931 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2932 let copied_bytes = packet.copy_header_bytes_for_fragment();
2933 let mut expected_bytes = Vec::new();
2934 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN + 48]);
2936 expected_bytes[IPV6_FIXED_HDR_LEN + 8] = IpProto::Tcp.into();
2937 assert_eq!(copied_bytes, expected_bytes);
2938 }
2939
2940 #[test_case(
2941 &[],
2942 &[],
2943 None;
2944 "no_ext_hdrs"
2945 )]
2946 #[test_case(
2947 &[Ipv6ExtHdrType::DestinationOptions],
2948 &[],
2949 Some(Ipv6ExtHdrType::DestinationOptions);
2950 "ignore_dst_options"
2951 )]
2952 #[test_case(
2953 &[
2954 Ipv6ExtHdrType::DestinationOptions,
2955 Ipv6ExtHdrType::Routing,
2956 Ipv6ExtHdrType::DestinationOptions
2957 ],
2958 &[Ipv6ExtHdrType::DestinationOptions, Ipv6ExtHdrType::Routing],
2959 Some(Ipv6ExtHdrType::DestinationOptions);
2960 "include_routing_and_everything_before"
2961 )]
2962 #[test_case(
2963 &[Ipv6ExtHdrType::HopByHopOptions, Ipv6ExtHdrType::DestinationOptions],
2964 &[Ipv6ExtHdrType::HopByHopOptions],
2965 Some(Ipv6ExtHdrType::DestinationOptions);
2966 "include_hop_by_hop_if_first"
2967 )]
2968 #[test_case(
2969 &[
2970 Ipv6ExtHdrType::HopByHopOptions,
2971 Ipv6ExtHdrType::DestinationOptions,
2972 Ipv6ExtHdrType::Routing
2973 ],
2974 &[
2975 Ipv6ExtHdrType::HopByHopOptions,
2976 Ipv6ExtHdrType::DestinationOptions,
2977 Ipv6ExtHdrType::Routing
2978 ],
2979 None;
2980 "routing_header_takes_precedence_over_hop_by_hop"
2981 )]
2982 fn test_per_fragment_header_builder(
2983 original_ext_hdrs: &[Ipv6ExtHdrType],
2984 expected_ext_hdrs: &[Ipv6ExtHdrType],
2985 expected_next_hdr: Option<Ipv6ExtHdrType>,
2986 ) {
2987 #[rustfmt::skip]
2988 fn build_routing_header(nh: u8) -> [u8; 40] {
2989 [
2990 nh, 4, 0, 0, 0, 0, 0, 0,
2991 1, 2, 3, 4, 5, 6, 7, 8,
2992 9, 10, 11, 12, 13, 14, 15, 16,
2993 17, 18, 19, 20, 21, 22, 23, 24,
2994 25, 26, 27, 28, 29, 30, 31, 32
2995 ]
2996 }
2997 fn build_hop_by_hop_header(nh: u8) -> [u8; 8] {
2998 [nh, 0, 0, 1, 0, 1, 1, 0]
2999 }
3000 #[rustfmt::skip]
3001 fn build_destination_options_header(nh: u8) -> [u8; 16] {
3002 [
3003 nh, 1, 0, 1, 0, 1, 1, 0,
3004 1, 6, 0, 0, 0, 0, 0, 0
3005 ]
3006 }
3007 fn build_fragment_header(nh: u8, id: u32) -> [u8; 8] {
3008 let [id1, id2, id3, id4] = id.to_be_bytes();
3009 [nh, 0, 0, 0, id1, id2, id3, id4]
3010 }
3011 fn build_header_bytes(ext_hdrs: &[Ipv6ExtHdrType], final_header: u8) -> Vec<u8> {
3012 let mut fixed_hdr = new_fixed_hdr();
3014 if ext_hdrs.is_empty() {
3015 fixed_hdr.next_hdr = final_header;
3016 } else {
3017 fixed_hdr.next_hdr = u8::from(ext_hdrs[0]);
3018 }
3019
3020 let mut ext_hdr_bytes = Vec::new();
3022 for i in 0..ext_hdrs.len() {
3023 let next_header =
3024 if i + 1 >= ext_hdrs.len() { final_header } else { u8::from(ext_hdrs[i + 1]) };
3025 match ext_hdrs[i] {
3026 Ipv6ExtHdrType::DestinationOptions => ext_hdr_bytes
3027 .extend_from_slice(&build_destination_options_header(next_header)),
3028 Ipv6ExtHdrType::Routing => {
3029 ext_hdr_bytes.extend_from_slice(&build_routing_header(next_header))
3030 }
3031 Ipv6ExtHdrType::HopByHopOptions => {
3032 ext_hdr_bytes.extend_from_slice(&build_hop_by_hop_header(next_header))
3033 }
3034 h => panic!("unexpected header type: {h}"),
3035 }
3036 }
3037
3038 let mut bytes = fixed_hdr_to_bytes(fixed_hdr).to_vec();
3039 bytes.extend_from_slice(&ext_hdr_bytes[..]);
3040 bytes
3041 }
3042
3043 const BODY: [u8; 5] = [1, 2, 3, 4, 5];
3045 let payload_header = u8::from(IpProto::Tcp);
3046 let mut bytes = build_header_bytes(original_ext_hdrs, payload_header);
3047 bytes.extend_from_slice(&BODY);
3048 let len = u16::try_from(bytes.len() - IPV6_FIXED_HDR_LEN).expect("should fit in a u16");
3049 bytes.as_mut_slice()[IPV6_PAYLOAD_LEN_BYTE_RANGE].copy_from_slice(&len.to_be_bytes());
3050 let mut buf = &bytes[..];
3051 let packet = buf.parse::<Ipv6Packet<_>>().expect("parse should succeed");
3052
3053 let serialized = packet
3055 .per_fragment_builder()
3056 .wrap_body(EmptyBuf)
3057 .serialize_vec_outer(&mut NoOpSerializationContext)
3058 .unwrap()
3059 .unwrap_b();
3060 let expected_next_hdr = expected_next_hdr.map(u8::from).unwrap_or(payload_header);
3061 let mut expected_bytes = build_header_bytes(expected_ext_hdrs, expected_next_hdr);
3062 let len =
3063 u16::try_from(expected_bytes.len() - IPV6_FIXED_HDR_LEN).expect("should fit in a u16");
3064 expected_bytes.as_mut_slice()[IPV6_PAYLOAD_LEN_BYTE_RANGE]
3065 .copy_from_slice(&len.to_be_bytes());
3066 assert_eq!(serialized.as_ref(), &expected_bytes[..]);
3067
3068 let builder = packet.per_fragment_builder();
3072 let body = &bytes[builder.header_len()..];
3073 const ID: u32 = 0x12345678;
3074 let frag_builder =
3075 Ipv6PacketBuilderWithFragmentHeader::new(builder, FragmentOffset::ZERO, false, ID);
3076 let serialized = frag_builder
3077 .wrap_body(body.into_serializer())
3078 .serialize_vec_outer(&mut NoOpSerializationContext)
3079 .unwrap()
3080 .unwrap_b();
3081 let mut expected_bytes =
3082 build_header_bytes(expected_ext_hdrs, u8::from(Ipv6ExtHdrType::Fragment));
3083 expected_bytes.extend_from_slice(&build_fragment_header(expected_next_hdr, ID));
3084 expected_bytes.extend_from_slice(body);
3085 let len =
3086 u16::try_from(expected_bytes.len() - IPV6_FIXED_HDR_LEN).expect("should fit in a u16");
3087 expected_bytes.as_mut_slice()[IPV6_PAYLOAD_LEN_BYTE_RANGE]
3088 .copy_from_slice(&len.to_be_bytes());
3089 assert_eq!(serialized.as_ref(), &expected_bytes[..]);
3090 }
3091
3092 #[test]
3093 fn test_next_multiple_of_eight() {
3094 for x in 0usize..=IPV6_HBH_OPTIONS_MAX_LEN {
3095 let y = next_multiple_of_eight(x);
3096 assert_eq!(y % 8, 0);
3097 assert!(y >= x);
3098 if x % 8 == 0 {
3099 assert_eq!(x, y);
3100 } else {
3101 assert_eq!(x + (8 - x % 8), y);
3102 }
3103 }
3104 }
3105
3106 fn create_ipv4_and_ipv6_builders(
3107 proto_v4: Ipv4Proto,
3108 proto_v6: Ipv6Proto,
3109 ) -> (Ipv4PacketBuilder, Ipv6PacketBuilder) {
3110 const IP_DSCP_AND_ECN: DscpAndEcn = DscpAndEcn::new(0x12, 3);
3111 const IP_TTL: u8 = 64;
3112
3113 let mut ipv4_builder =
3114 Ipv4PacketBuilder::new(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP, IP_TTL, proto_v4);
3115 ipv4_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
3116 ipv4_builder.df_flag(false);
3117 ipv4_builder.mf_flag(false);
3118 ipv4_builder.fragment_offset(FragmentOffset::ZERO);
3119
3120 let mut ipv6_builder =
3121 Ipv6PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, IP_TTL, proto_v6);
3122 ipv6_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
3123 ipv6_builder.flowlabel(0x456);
3124
3125 (ipv4_builder, ipv6_builder)
3126 }
3127
3128 fn create_tcp_ipv4_and_ipv6_pkt()
3129 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
3130 use crate::tcp::TcpSegmentBuilder;
3131 use core::num::NonZeroU16;
3132
3133 let tcp_src_port: NonZeroU16 = NonZeroU16::new(20).unwrap();
3134 let tcp_dst_port: NonZeroU16 = NonZeroU16::new(30).unwrap();
3135 const TCP_SEQ_NUM: u32 = 4321;
3136 const TCP_ACK_NUM: Option<u32> = Some(1234);
3137 const TCP_WINDOW_SIZE: u16 = 12345;
3138 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
3139
3140 let (ipv4_builder, ipv6_builder) =
3141 create_ipv4_and_ipv6_builders(IpProto::Tcp.into(), IpProto::Tcp.into());
3142
3143 let tcp_builder = TcpSegmentBuilder::new(
3144 DEFAULT_V4_SRC_IP,
3145 DEFAULT_V4_DST_IP,
3146 tcp_src_port,
3147 tcp_dst_port,
3148 TCP_SEQ_NUM,
3149 TCP_ACK_NUM,
3150 TCP_WINDOW_SIZE,
3151 );
3152
3153 let v4_pkt_buf = (&PAYLOAD)
3154 .into_serializer()
3155 .wrap_in(tcp_builder)
3156 .wrap_in(ipv4_builder)
3157 .serialize_vec_outer(&mut NoOpSerializationContext)
3158 .expect("Failed to serialize to v4_pkt_buf");
3159
3160 let v6_tcp_builder = TcpSegmentBuilder::new(
3161 DEFAULT_SRC_IP,
3162 DEFAULT_DST_IP,
3163 tcp_src_port,
3164 tcp_dst_port,
3165 TCP_SEQ_NUM,
3166 TCP_ACK_NUM,
3167 TCP_WINDOW_SIZE,
3168 );
3169
3170 let v6_pkt_buf = (&PAYLOAD)
3171 .into_serializer()
3172 .wrap_in(v6_tcp_builder)
3173 .wrap_in(ipv6_builder)
3174 .serialize_vec_outer(&mut NoOpSerializationContext)
3175 .expect("Failed to serialize to v4_pkt_buf");
3176
3177 (v4_pkt_buf, v6_pkt_buf)
3178 }
3179
3180 #[test]
3181 fn test_nat64_translate_tcp() {
3182 let (expected_v4_pkt_buf, mut v6_pkt_buf) = create_tcp_ipv4_and_ipv6_pkt();
3183
3184 let parsed_v6_packet =
3185 v6_pkt_buf.parse::<Ipv6Packet<_>>().expect("Failed to parse v6_pkt_buf");
3186 let nat64_translation_result =
3187 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
3188
3189 let serializable_pkt =
3190 assert_matches!(nat64_translation_result, Nat64TranslationResult::Forward(s) => s);
3191
3192 let translated_v4_pkt_buf = serializable_pkt
3193 .serialize_vec_outer(&mut NoOpSerializationContext)
3194 .expect("Failed to serialize to translated_v4_pkt_buf");
3195
3196 assert_eq!(
3197 expected_v4_pkt_buf.to_flattened_vec(),
3198 translated_v4_pkt_buf.to_flattened_vec()
3199 );
3200 }
3201
3202 fn create_udp_ipv4_and_ipv6_pkt()
3203 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
3204 use crate::udp::UdpPacketBuilder;
3205 use core::num::NonZeroU16;
3206
3207 let udp_src_port: NonZeroU16 = NonZeroU16::new(35000).unwrap();
3208 let udp_dst_port: NonZeroU16 = NonZeroU16::new(53).unwrap();
3209 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
3210
3211 let (ipv4_builder, ipv6_builder) =
3212 create_ipv4_and_ipv6_builders(IpProto::Udp.into(), IpProto::Udp.into());
3213
3214 let v4_udp_builder = UdpPacketBuilder::new(
3215 DEFAULT_V4_SRC_IP,
3216 DEFAULT_V4_DST_IP,
3217 Some(udp_src_port),
3218 udp_dst_port,
3219 );
3220
3221 let v4_pkt_buf = (&PAYLOAD)
3222 .into_serializer()
3223 .wrap_in(v4_udp_builder)
3224 .wrap_in(ipv4_builder)
3225 .serialize_vec_outer(&mut NoOpSerializationContext)
3226 .expect("Unable to serialize to v4_pkt_buf");
3227
3228 let v6_udp_builder =
3229 UdpPacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, Some(udp_src_port), udp_dst_port);
3230
3231 let v6_pkt_buf = (&PAYLOAD)
3232 .into_serializer()
3233 .wrap_in(v6_udp_builder)
3234 .wrap_in(ipv6_builder)
3235 .serialize_vec_outer(&mut NoOpSerializationContext)
3236 .expect("Unable to serialize to v6_pkt_buf");
3237
3238 (v4_pkt_buf, v6_pkt_buf)
3239 }
3240
3241 #[test]
3242 fn test_nat64_translate_udp() {
3243 let (expected_v4_pkt_buf, mut v6_pkt_buf) = create_udp_ipv4_and_ipv6_pkt();
3244
3245 let parsed_v6_packet =
3246 v6_pkt_buf.parse::<Ipv6Packet<_>>().expect("Unable to parse Ipv6Packet");
3247 let nat64_translation_result =
3248 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
3249
3250 let serializable_pkt = assert_matches!(nat64_translation_result,
3251 Nat64TranslationResult::Forward(s) => s);
3252
3253 let translated_v4_pkt_buf = serializable_pkt
3254 .serialize_vec_outer(&mut NoOpSerializationContext)
3255 .expect("Unable to serialize to translated_v4_pkt_buf");
3256
3257 assert_eq!(
3258 expected_v4_pkt_buf.to_flattened_vec(),
3259 translated_v4_pkt_buf.to_flattened_vec()
3260 );
3261 }
3262
3263 #[test]
3264 fn test_nat64_translate_non_tcp_udp_icmp() {
3265 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
3266
3267 let (ipv4_builder, ipv6_builder) =
3268 create_ipv4_and_ipv6_builders(Ipv4Proto::Other(59), Ipv6Proto::Other(59));
3269
3270 let expected_v4_pkt_buf = (&PAYLOAD)
3271 .into_serializer()
3272 .wrap_in(ipv4_builder)
3273 .serialize_vec_outer(&mut NoOpSerializationContext)
3274 .expect("Unable to serialize to expected_v4_pkt_buf");
3275
3276 let mut v6_pkt_buf = (&PAYLOAD)
3277 .into_serializer()
3278 .wrap_in(ipv6_builder)
3279 .serialize_vec_outer(&mut NoOpSerializationContext)
3280 .expect("Unable to serialize to v6_pkt_buf");
3281
3282 let translated_v4_pkt_buf = {
3283 let parsed_v6_packet = v6_pkt_buf
3284 .parse::<Ipv6Packet<_>>()
3285 .expect("Unable to serialize to translated_v4_pkt_buf");
3286
3287 let nat64_translation_result =
3288 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
3289
3290 let serializable_pkt = assert_matches!(nat64_translation_result,
3291 Nat64TranslationResult::Forward(s) => s);
3292
3293 let translated_buf = serializable_pkt
3294 .serialize_vec_outer(&mut NoOpSerializationContext)
3295 .expect("Unable to serialize to translated_buf");
3296
3297 translated_buf
3298 };
3299
3300 assert_eq!(
3301 expected_v4_pkt_buf.to_flattened_vec(),
3302 translated_v4_pkt_buf.to_flattened_vec()
3303 );
3304 }
3305
3306 #[test_case(new_builder(), true; "fixed header more frags")]
3307 #[test_case(Ipv6PacketBuilderWithHbhOptions::new(
3308 new_builder(),
3309 &[HopByHopOption {
3310 action: ExtensionHeaderOptionAction::SkipAndContinue,
3311 mutable: false,
3312 data: HopByHopOptionData::RouterAlert { data: 0 },
3313 }]).unwrap(), false; "hbh last frag")]
3314 fn ipv6_packet_builder_with_fragment_header<
3315 B: Ipv6HeaderBuilder + Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>> + Debug,
3316 >(
3317 inner: B,
3318 more_fragments: bool,
3319 ) {
3320 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
3321 let fragment_offset = FragmentOffset::new(13).unwrap();
3322 let identification = 0xABCDABCD;
3323 let builder = Ipv6PacketBuilderWithFragmentHeader::new(
3324 inner,
3325 fragment_offset,
3326 more_fragments,
3327 identification,
3328 );
3329 let mut serialized = builder
3330 .wrap_body(PAYLOAD.into_serializer())
3331 .serialize_vec_outer(&mut NoOpSerializationContext)
3332 .unwrap()
3333 .unwrap_b();
3334 let packet = serialized.parse::<Ipv6Packet<_>>().unwrap();
3335 assert!(packet.fragment_header_present());
3336 assert_eq!(packet.proto(), Ipv6Proto::Proto(IpProto::Tcp));
3337 let fragment_data = packet
3338 .extension_hdrs
3339 .into_iter()
3340 .find_map(|ext_hdr| match ext_hdr {
3341 Ipv6ExtensionHeader::Fragment { fragment_data } => Some(fragment_data),
3342 _ => None,
3343 })
3344 .unwrap();
3345 assert_eq!(fragment_data.fragment_offset(), fragment_offset);
3346 assert_eq!(fragment_data.identification(), identification);
3347 assert_eq!(fragment_data.m_flag(), more_fragments);
3348 }
3349
3350 #[test]
3353 fn extension_headers_take_from_max_body_size() {
3354 let builder = new_builder();
3355 assert_eq!(builder.constraints().max_body_len(), IPV6_MAX_PAYLOAD_LENGTH);
3356 let builder =
3357 Ipv6PacketBuilderWithFragmentHeader::new(builder, FragmentOffset::ZERO, false, 1234);
3358 assert_eq!(
3359 builder.constraints().max_body_len(),
3360 IPV6_MAX_PAYLOAD_LENGTH - IPV6_FRAGMENT_EXT_HDR_LEN
3361 );
3362 }
3363
3364 #[test]
3365 fn test_partial_serialize_parsed() {
3366 const PACKET_BYTES: &[u8] = &[
3367 100, 177, 4, 5, 0, 10, 6, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
3368 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, 1, 2, 3, 4, 5, 6, 7,
3369 8, 9,
3370 ];
3371 const PACKET_LEN: usize = PACKET_BYTES.len();
3372 let mut packet_bytes_copy = Vec::from(PACKET_BYTES);
3373 let mut packet_bytes_ref: &mut [u8] = &mut packet_bytes_copy[..];
3374 let packet = packet_bytes_ref.parse::<Ipv6Packet<_>>().unwrap();
3375
3376 let buf = assert_matches!(
3377 packet.partial_serialize(&mut NoOpSerializationContext, packet::new_buf_vec),
3378 Ok(PartialSerializeResult::NewBuffer { buffer, total_size: PACKET_LEN }) => buffer
3379 );
3380 assert_eq!(buf.as_ref(), PACKET_BYTES);
3381 }
3382}