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 pub fn set_payload_len(&mut self, payload_len: u16) {
1135 self.fixed_hdr.payload_len = U16::new(payload_len);
1136 }
1137}
1138
1139pub enum NextHeader {
1142 NextLayer(Ipv6Proto),
1144 Extension(Ipv6ExtHdrType),
1146}
1147
1148impl From<NextHeader> for u8 {
1149 fn from(next_hdr: NextHeader) -> Self {
1150 match next_hdr {
1151 NextHeader::NextLayer(n) => n.into(),
1152 NextHeader::Extension(e) => e.into(),
1153 }
1154 }
1155}
1156
1157mod sealed {
1158 use super::*;
1159 pub trait Ipv6HeaderBefore<T> {}
1167
1168 impl<'a, O, T> Ipv6HeaderBefore<T> for &'a O where O: Ipv6HeaderBefore<T> {}
1169
1170 pub trait Ipv6HeaderBuilder {
1172 fn fixed_header(&self) -> &Ipv6PacketBuilder;
1174
1175 fn extension_headers_len(&self) -> usize;
1178
1179 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1184 &self,
1185 buffer: &mut BV,
1186 next_header: NextHeader,
1187 payload_len: usize,
1188 );
1189 }
1190}
1191use sealed::{Ipv6HeaderBefore, Ipv6HeaderBuilder};
1192
1193impl<'a, O> Ipv6HeaderBuilder for &'a O
1194where
1195 O: Ipv6HeaderBuilder,
1196{
1197 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1198 O::fixed_header(self)
1199 }
1200
1201 fn extension_headers_len(&self) -> usize {
1202 O::extension_headers_len(self)
1203 }
1204
1205 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1206 &self,
1207 buffer: &mut BV,
1208 next_header: NextHeader,
1209 payload_len: usize,
1210 ) {
1211 O::serialize_header(self, buffer, next_header, payload_len)
1212 }
1213}
1214
1215macro_rules! impl_packet_builder_base {
1220 {} => {
1221 fn constraints(&self) -> PacketConstraints {
1222 let ext_headers = self.extension_headers_len();
1223 let header_len = IPV6_FIXED_HDR_LEN + ext_headers;
1224 let footer_len = 0;
1225 let min_body_len = 0;
1226 let max_body_len = IPV6_MAX_PAYLOAD_LENGTH - ext_headers;
1229 PacketConstraints::new(header_len, footer_len, min_body_len, max_body_len)
1230 }
1231 }
1232}
1233
1234macro_rules! impl_packet_builder {
1235 {} => {
1236 fn context_state(&self) -> C::ContextState {
1237 C::envelope_to_state(IpEnvelope::new(self.extension_headers_len() > 0))
1238 }
1239
1240 fn serialize(
1241 &self,
1242 _context: &mut C,
1243 target: &mut SerializeTarget<'_>,
1244 body: FragmentedBytesMut<'_, '_>,
1245 ) {
1246 let mut bv = &mut target.header;
1247 self.serialize_header(
1248 &mut bv,
1249 NextHeader::NextLayer(
1250 <Ipv6PacketBuilder as IpPacketBuilder<C, Ipv6>>::proto(self.fixed_header())
1251 ),
1252 body.len(),
1253 );
1254 }
1255 }
1256}
1257
1258macro_rules! impl_partial_packet_builder {
1259 {} => {
1260 fn partial_serialize(
1261 &self,
1262 _context: &mut C,
1263 body_len: usize,
1264 mut buffer: &mut [u8],
1265 ) {
1266 self.serialize_header(
1267 &mut &mut buffer,
1268 NextHeader::NextLayer(
1269 <Ipv6PacketBuilder as IpPacketBuilder<C, Ipv6>>::proto(self.fixed_header())
1270 ),
1271 body_len,
1272 );
1273 }
1274 }
1275}
1276#[derive(Debug, Clone, Eq, PartialEq)]
1278pub struct Ipv6PacketBuilder {
1279 dscp_and_ecn: DscpAndEcn,
1280 flowlabel: u32,
1281 hop_limit: u8,
1282 proto: Ipv6Proto,
1285 src_ip: Ipv6Addr,
1286 dst_ip: Ipv6Addr,
1287}
1288
1289impl Ipv6PacketBuilder {
1290 pub fn new<S: Into<Ipv6Addr>, D: Into<Ipv6Addr>>(
1296 src_ip: S,
1297 dst_ip: D,
1298 hop_limit: u8,
1299 proto: Ipv6Proto,
1300 ) -> Ipv6PacketBuilder {
1301 Ipv6PacketBuilder {
1302 dscp_and_ecn: DscpAndEcn::default(),
1303 flowlabel: 0,
1304 hop_limit,
1305 proto,
1306 src_ip: src_ip.into(),
1307 dst_ip: dst_ip.into(),
1308 }
1309 }
1310
1311 pub fn dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1314 self.dscp_and_ecn = dscp_and_ecn;
1315 }
1316
1317 pub fn flowlabel(&mut self, flowlabel: u32) {
1323 assert!(flowlabel <= 1 << 20, "invalid flowlabel: {:x}", flowlabel);
1324 self.flowlabel = flowlabel;
1325 }
1326}
1327
1328impl Ipv6HeaderBuilder for Ipv6PacketBuilder {
1329 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1330 self
1331 }
1332
1333 fn extension_headers_len(&self) -> usize {
1334 0
1335 }
1336
1337 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1338 &self,
1339 buffer: &mut BV,
1340 next_header: NextHeader,
1341 payload_len: usize,
1342 ) {
1343 buffer
1344 .write_obj_front(&FixedHeader::new(
1345 self.dscp_and_ecn,
1346 self.flowlabel,
1347 {
1348 debug_assert!(payload_len <= u16::MAX as usize);
1355 payload_len as u16
1356 },
1357 next_header.into(),
1358 self.hop_limit,
1359 self.src_ip,
1360 self.dst_ip,
1361 ))
1362 .expect("not enough bytes for IPv6 fixed header");
1363 }
1364}
1365
1366impl NestablePacketBuilder for Ipv6PacketBuilder {
1367 impl_packet_builder_base! {}
1368}
1369
1370impl<C: IpSerializationContext<Ipv6>> PacketBuilder<C> for Ipv6PacketBuilder {
1371 impl_packet_builder! {}
1372}
1373
1374impl<C: IpSerializationContext<Ipv6>> PartialPacketBuilder<C> for Ipv6PacketBuilder {
1375 impl_partial_packet_builder! {}
1376}
1377
1378#[derive(Debug, Clone)]
1380pub struct Ipv6PacketBuilderWithHbhOptions<'a, I> {
1381 prefix_builder: Ipv6PacketBuilder,
1382 hbh_options: AlignedRecordSequenceBuilder<HopByHopOption<'a>, I>,
1383}
1384
1385impl<'a, I> Ipv6PacketBuilderWithHbhOptions<'a, I>
1386where
1387 I: Iterator + Clone,
1388 I::Item: Borrow<HopByHopOption<'a>>,
1389{
1390 pub fn new<T: IntoIterator<Item = I::Item, IntoIter = I>>(
1392 prefix_builder: Ipv6PacketBuilder,
1393 options: T,
1394 ) -> Option<Ipv6PacketBuilderWithHbhOptions<'a, I>> {
1395 let iter = options.into_iter();
1396 if iter
1399 .clone()
1400 .filter(|r| matches!(r.borrow().data, HopByHopOptionData::RouterAlert { .. }))
1401 .count()
1402 > 1
1403 {
1404 return None;
1405 }
1406 let hbh_options = AlignedRecordSequenceBuilder::new(2, iter);
1407 if next_multiple_of_eight(2 + hbh_options.serialized_len()) > IPV6_HBH_OPTIONS_MAX_LEN {
1409 return None;
1410 }
1411 Some(Ipv6PacketBuilderWithHbhOptions { prefix_builder, hbh_options })
1412 }
1413
1414 fn aligned_hbh_len(&self) -> usize {
1415 let opt_len = self.hbh_options.serialized_len();
1416 let hbh_len = opt_len + 2;
1417 next_multiple_of_eight(hbh_len)
1418 }
1419}
1420
1421fn next_multiple_of_eight(x: usize) -> usize {
1422 (x + 7) & (!7)
1423}
1424
1425impl<C: IpSerializationContext<Ipv6>> IpPacketBuilder<C, Ipv6> for Ipv6PacketBuilder {
1426 fn new(src_ip: Ipv6Addr, dst_ip: Ipv6Addr, ttl: u8, proto: Ipv6Proto) -> Self {
1427 Ipv6PacketBuilder::new(src_ip, dst_ip, ttl, proto)
1428 }
1429
1430 fn src_ip(&self) -> Ipv6Addr {
1431 self.src_ip
1432 }
1433
1434 fn set_src_ip(&mut self, addr: Ipv6Addr) {
1435 self.src_ip = addr;
1436 }
1437
1438 fn dst_ip(&self) -> Ipv6Addr {
1439 self.dst_ip
1440 }
1441
1442 fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1443 self.dst_ip = addr;
1444 }
1445
1446 fn proto(&self) -> Ipv6Proto {
1447 self.proto
1448 }
1449
1450 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1451 self.dscp_and_ecn = dscp_and_ecn;
1452 }
1453}
1454
1455impl<'a, I> Ipv6HeaderBuilder for Ipv6PacketBuilderWithHbhOptions<'a, I>
1456where
1457 I: Iterator + Clone,
1458 I::Item: Borrow<HopByHopOption<'a>>,
1459{
1460 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1461 &self.prefix_builder
1462 }
1463
1464 fn extension_headers_len(&self) -> usize {
1465 self.prefix_builder.extension_headers_len() + self.aligned_hbh_len()
1466 }
1467
1468 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1469 &self,
1470 buffer: &mut BV,
1471 next_header: NextHeader,
1472 payload_len: usize,
1473 ) {
1474 let aligned_hbh_len = self.aligned_hbh_len();
1475 self.prefix_builder.serialize_header(
1477 buffer,
1478 NextHeader::Extension(Ipv6ExtHdrType::HopByHopOptions),
1479 payload_len + aligned_hbh_len,
1480 );
1481 let mut hbh_header = buffer.take_front(aligned_hbh_len).unwrap();
1483 let hbh_header: &mut [u8] = hbh_header.as_mut();
1484 hbh_header[0] = next_header.into();
1485 hbh_header[1] = u8::try_from((aligned_hbh_len - 8) / 8).expect("extension header too big");
1486 self.hbh_options.serialize_into(&mut hbh_header[2..]);
1487 }
1488}
1489
1490impl<'a, I> NestablePacketBuilder for Ipv6PacketBuilderWithHbhOptions<'a, I>
1491where
1492 I: Iterator + Clone,
1493 I::Item: Borrow<HopByHopOption<'a>>,
1494{
1495 impl_packet_builder_base! {}
1496}
1497
1498impl<'a, I, C: IpSerializationContext<Ipv6>> PacketBuilder<C>
1499 for Ipv6PacketBuilderWithHbhOptions<'a, I>
1500where
1501 I: Iterator + Clone,
1502 I::Item: Borrow<HopByHopOption<'a>>,
1503{
1504 impl_packet_builder! {}
1505}
1506
1507impl<'a, I, C: IpSerializationContext<Ipv6>> PartialPacketBuilder<C>
1508 for Ipv6PacketBuilderWithHbhOptions<'a, I>
1509where
1510 I: Iterator + Clone,
1511 I::Item: Borrow<HopByHopOption<'a>>,
1512{
1513 impl_partial_packet_builder! {}
1514}
1515
1516impl<'a, C: IpSerializationContext<Ipv6>, I> IpPacketBuilder<C, Ipv6>
1517 for Ipv6PacketBuilderWithHbhOptions<'a, I>
1518where
1519 I: Iterator<Item: Borrow<HopByHopOption<'a>>> + Debug + Default + Clone,
1520{
1521 fn new(src_ip: Ipv6Addr, dst_ip: Ipv6Addr, ttl: u8, proto: Ipv6Proto) -> Self {
1522 Ipv6PacketBuilderWithHbhOptions::new(
1523 Ipv6PacketBuilder::new(src_ip, dst_ip, ttl, proto),
1524 I::default(),
1525 )
1526 .expect("packet builder with no options should be valid")
1527 }
1528
1529 fn src_ip(&self) -> Ipv6Addr {
1530 self.prefix_builder.src_ip
1531 }
1532
1533 fn set_src_ip(&mut self, addr: Ipv6Addr) {
1534 self.prefix_builder.src_ip = addr;
1535 }
1536
1537 fn dst_ip(&self) -> Ipv6Addr {
1538 self.prefix_builder.dst_ip
1539 }
1540
1541 fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1542 self.prefix_builder.dst_ip = addr;
1543 }
1544
1545 fn proto(&self) -> Ipv6Proto {
1546 self.prefix_builder.proto
1547 }
1548
1549 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1550 <Ipv6PacketBuilder as IpPacketBuilder<C, Ipv6>>::set_dscp_and_ecn(
1551 &mut self.prefix_builder,
1552 dscp_and_ecn,
1553 )
1554 }
1555}
1556
1557#[derive(Debug, Clone, Eq, PartialEq)]
1559struct Ipv6PerFragmentMeta<B> {
1560 ext_hdrs: B,
1561 first_ext_hdr: Ipv6ExtHdrType,
1562 last_next_hdr_offset: usize,
1563}
1564
1565#[derive(Debug, Clone, Eq, PartialEq)]
1570pub struct Ipv6PerFragmentHeaderBuilder<B> {
1571 prefix_builder: Ipv6PacketBuilder,
1572 meta: Option<Ipv6PerFragmentMeta<B>>,
1573}
1574
1575impl<B: AsRef<[u8]>> Ipv6PerFragmentHeaderBuilder<B> {
1576 pub fn header_len(&self) -> usize {
1578 self.extension_headers_len() + IPV6_FIXED_HDR_LEN
1579 }
1580
1581 pub fn as_ref(&self) -> Ipv6PerFragmentHeaderBuilder<&[u8]> {
1584 let Self { prefix_builder, meta } = self;
1585 let meta = meta.as_ref().map(
1586 |Ipv6PerFragmentMeta { ext_hdrs, first_ext_hdr, last_next_hdr_offset }| {
1587 Ipv6PerFragmentMeta {
1588 ext_hdrs: ext_hdrs.as_ref(),
1589 first_ext_hdr: *first_ext_hdr,
1590 last_next_hdr_offset: *last_next_hdr_offset,
1591 }
1592 },
1593 );
1594 Ipv6PerFragmentHeaderBuilder { prefix_builder: prefix_builder.clone(), meta }
1595 }
1596}
1597
1598impl<B: AsRef<[u8]>> Ipv6HeaderBuilder for Ipv6PerFragmentHeaderBuilder<B> {
1599 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1600 &self.prefix_builder
1601 }
1602
1603 fn extension_headers_len(&self) -> usize {
1604 self.meta
1605 .as_ref()
1606 .map(|Ipv6PerFragmentMeta { ext_hdrs, .. }| ext_hdrs.as_ref().len())
1607 .unwrap_or(0)
1608 }
1609
1610 fn serialize_header<BB: SplitByteSliceMut, BV: BufferViewMut<BB>>(
1611 &self,
1612 buffer: &mut BV,
1613 next_header: NextHeader,
1614 payload_len: usize,
1615 ) {
1616 let Self { prefix_builder, meta } = self;
1617 match meta {
1618 None => prefix_builder.serialize_header(buffer, next_header, payload_len),
1619 Some(Ipv6PerFragmentMeta { ext_hdrs, first_ext_hdr, last_next_hdr_offset }) => {
1620 let ext_hdrs = ext_hdrs.as_ref();
1621 let ext_hdrs_len = ext_hdrs.len();
1622 prefix_builder.serialize_header(
1623 buffer,
1624 NextHeader::Extension(*first_ext_hdr),
1625 payload_len + ext_hdrs_len,
1626 );
1627 let mut ext_hdr_buf =
1628 buffer.take_front(ext_hdrs_len).expect("buffer should be long enough");
1629 let ext_hdr_buf: &mut [u8] = ext_hdr_buf.as_mut();
1630 ext_hdr_buf.copy_from_slice(ext_hdrs);
1631 ext_hdr_buf[*last_next_hdr_offset] = u8::from(next_header);
1632 }
1633 }
1634 }
1635}
1636
1637impl<B: AsRef<[u8]>> NestablePacketBuilder for Ipv6PerFragmentHeaderBuilder<B> {
1638 impl_packet_builder_base! {}
1639}
1640
1641impl<B: AsRef<[u8]>, C: IpSerializationContext<Ipv6>> PacketBuilder<C>
1642 for Ipv6PerFragmentHeaderBuilder<B>
1643{
1644 impl_packet_builder! {}
1645}
1646
1647impl<B: AsRef<[u8]>, C: IpSerializationContext<Ipv6>> PartialPacketBuilder<C>
1648 for Ipv6PerFragmentHeaderBuilder<B>
1649{
1650 impl_partial_packet_builder! {}
1651}
1652
1653#[derive(Debug, Eq, PartialEq)]
1662pub struct Ipv6PacketBuilderWithFragmentHeader<B> {
1663 header_builder: B,
1664 fragment_offset: FragmentOffset,
1665 more_fragments: bool,
1666 identification: u32,
1667}
1668
1669impl<B: Ipv6HeaderBefore<Self>> Ipv6PacketBuilderWithFragmentHeader<B> {
1670 pub fn new(
1672 header_builder: B,
1673 fragment_offset: FragmentOffset,
1674 more_fragments: bool,
1675 identification: u32,
1676 ) -> Self {
1677 Self { header_builder, fragment_offset, more_fragments, identification }
1678 }
1679}
1680
1681impl<B> Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>> for Ipv6PacketBuilder {}
1682impl<B, I> Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>>
1683 for Ipv6PacketBuilderWithHbhOptions<'_, I>
1684{
1685}
1686impl<HB, B> Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<HB>>
1687 for Ipv6PerFragmentHeaderBuilder<B>
1688{
1689}
1690
1691pub trait Ipv6PacketBuilderBeforeFragment:
1694 Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<Self>> + Ipv6HeaderBuilder + Sized
1695{
1696}
1697impl<B> Ipv6PacketBuilderBeforeFragment for B where
1698 B: Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<Self>> + Ipv6HeaderBuilder + Sized
1699{
1700}
1701
1702impl<B: Ipv6HeaderBuilder> Ipv6HeaderBuilder for Ipv6PacketBuilderWithFragmentHeader<B> {
1703 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1704 self.header_builder.fixed_header()
1705 }
1706
1707 fn extension_headers_len(&self) -> usize {
1708 self.header_builder.extension_headers_len() + IPV6_FRAGMENT_EXT_HDR_LEN
1709 }
1710
1711 fn serialize_header<BB: SplitByteSliceMut, BV: BufferViewMut<BB>>(
1712 &self,
1713 buffer: &mut BV,
1714 next_header: NextHeader,
1715 payload_len: usize,
1716 ) {
1717 let Self { header_builder, fragment_offset, more_fragments, identification } = self;
1718 let payload_len = payload_len + IPV6_FRAGMENT_EXT_HDR_LEN;
1719 header_builder.serialize_header(
1720 buffer,
1721 NextHeader::Extension(Ipv6ExtHdrType::Fragment),
1722 payload_len,
1723 );
1724 buffer.write_obj_front(&u8::from(next_header)).unwrap();
1725 let _: BB = buffer.take_front_zero(1).unwrap();
1727 let more_fragments = u16::from(*more_fragments);
1728 buffer
1729 .write_obj_front(&U16::new(fragment_offset.into_raw() << 3 | more_fragments))
1730 .unwrap();
1731 buffer.write_obj_front(&U32::new(*identification)).unwrap();
1732 }
1733}
1734
1735impl<B: Ipv6HeaderBuilder> NestablePacketBuilder for Ipv6PacketBuilderWithFragmentHeader<B> {
1736 impl_packet_builder_base! {}
1737}
1738
1739impl<B: Ipv6HeaderBuilder, C: IpSerializationContext<Ipv6>> PacketBuilder<C>
1740 for Ipv6PacketBuilderWithFragmentHeader<B>
1741{
1742 impl_packet_builder! {}
1743}
1744
1745impl<B: Ipv6HeaderBuilder, C: IpSerializationContext<Ipv6>> PartialPacketBuilder<C>
1746 for Ipv6PacketBuilderWithFragmentHeader<B>
1747{
1748 impl_partial_packet_builder! {}
1749}
1750
1751pub(crate) fn reassemble_fragmented_packet<
1757 'a,
1758 B: SplitByteSliceMut,
1759 BV: BufferViewMut<B>,
1760 I: Iterator<Item = &'a [u8]>,
1761>(
1762 mut buffer: BV,
1763 header: &[u8],
1764 body_fragments: I,
1765) -> IpParseResult<Ipv6, ()> {
1766 assert!(header.len() >= IPV6_FIXED_HDR_LEN);
1767
1768 let bytes = buffer.as_mut();
1769
1770 bytes[0..header.len()].copy_from_slice(header);
1772 let mut byte_count = header.len();
1773
1774 for p in body_fragments {
1776 bytes[byte_count..byte_count + p.len()].copy_from_slice(p);
1777 byte_count += p.len();
1778 }
1779
1780 let payload_length = byte_count - IPV6_FIXED_HDR_LEN;
1792
1793 if payload_length > usize::from(u16::MAX) {
1796 return debug_err!(
1797 Err(ParseError::Format.into()),
1798 "fragmented packet payload length of {} bytes is too large",
1799 payload_length
1800 );
1801 }
1802
1803 let mut header = Ref::<_, FixedHeader>::from_prefix(bytes).unwrap().0;
1806
1807 header.payload_len.set(u16::try_from(payload_length).unwrap());
1809
1810 Ok(())
1811}
1812
1813#[cfg(test)]
1814mod tests {
1815 use assert_matches::assert_matches;
1816 use packet::{Buf, FragmentedBuffer, ParseBuffer, PartialSerializeResult};
1817 use test_case::test_case;
1818
1819 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1820 use crate::testutil::*;
1821
1822 use super::ext_hdrs::*;
1823 use super::*;
1824
1825 const DEFAULT_SRC_IP: Ipv6Addr =
1826 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1827 const DEFAULT_DST_IP: Ipv6Addr =
1828 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1829
1830 const DEFAULT_V4_SRC_IP: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1831 const DEFAULT_V4_DST_IP: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1832
1833 #[test]
1834 fn test_parse_serialize_full_tcp() {
1835 use crate::testdata::syn_v6::*;
1836
1837 let mut buf = ETHERNET_FRAME.bytes;
1838 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1839 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1840
1841 let mut body = frame.body();
1842 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1843 verify_ipv6_packet(&packet, IPV6_PACKET);
1844
1845 let buffer = packet
1847 .body()
1848 .into_serializer()
1849 .wrap_in(packet.builder())
1850 .wrap_in(frame.builder())
1851 .serialize_vec_outer(&mut NoOpSerializationContext)
1852 .unwrap();
1853 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1854
1855 assert_eq!(&packet.to_vec()[..], IPV6_PACKET.bytes);
1857 }
1858
1859 #[test]
1860 fn test_parse_serialize_full_udp() {
1861 use crate::testdata::dns_request_v6::*;
1862
1863 let mut buf = ETHERNET_FRAME.bytes;
1864 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1865 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1866
1867 let mut body = frame.body();
1868 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1869 verify_ipv6_packet(&packet, IPV6_PACKET);
1870
1871 let buffer = packet
1873 .body()
1874 .into_serializer()
1875 .wrap_in(packet.builder())
1876 .wrap_in(frame.builder())
1877 .serialize_vec_outer(&mut NoOpSerializationContext)
1878 .unwrap();
1879 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1880
1881 assert_eq!(&packet.to_vec()[..], IPV6_PACKET.bytes);
1883 }
1884
1885 #[test]
1886 fn test_parse_serialize_with_extension_headers() {
1887 use crate::testdata::mld_router_report::*;
1890
1891 let mut buf = REPORT;
1892 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1893 assert_eq!(packet.iter_extension_hdrs().count(), 1);
1894
1895 assert_eq!(&packet.to_vec()[..], REPORT);
1900 }
1901
1902 fn fixed_hdr_to_bytes(fixed_hdr: FixedHeader) -> [u8; IPV6_FIXED_HDR_LEN] {
1903 zerocopy::transmute!(fixed_hdr)
1904 }
1905
1906 fn new_fixed_hdr() -> FixedHeader {
1908 FixedHeader::new(
1909 DscpAndEcn::new(0, 2),
1910 0x77,
1911 0,
1912 IpProto::Tcp.into(),
1913 64,
1914 DEFAULT_SRC_IP,
1915 DEFAULT_DST_IP,
1916 )
1917 }
1918
1919 #[test]
1920 fn test_parse() {
1921 let mut buf = &fixed_hdr_to_bytes(new_fixed_hdr())[..];
1922 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1923 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1924 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1925 assert_eq!(packet.flowlabel(), 0x77);
1926 assert_eq!(packet.hop_limit(), 64);
1927 assert_eq!(packet.fixed_hdr.next_hdr, IpProto::Tcp.into());
1928 assert_eq!(packet.proto(), IpProto::Tcp.into());
1929 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1930 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1931 assert_eq!(packet.body(), []);
1932 }
1933
1934 #[test]
1935 fn test_parse_with_ext_hdrs() {
1936 #[rustfmt::skip]
1937 let mut buf = [
1938 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1940 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1941
1942 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,
1957 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1958
1959 IpProto::Tcp.into(), 1, 0, 1, 0, 1, 1, 0, 1, 6, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
1969 ];
1970 let mut fixed_hdr = new_fixed_hdr();
1971 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
1972 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1973 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1974 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1975 let mut buf = &buf[..];
1976 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1977 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1978 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1979 assert_eq!(packet.flowlabel(), 0x77);
1980 assert_eq!(packet.hop_limit(), 64);
1981 assert_eq!(packet.fixed_hdr.next_hdr, Ipv6ExtHdrType::HopByHopOptions.into());
1982 assert_eq!(packet.proto(), IpProto::Tcp.into());
1983 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1984 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1985 assert_eq!(packet.body(), [1, 2, 3, 4, 5]);
1986 let ext_hdrs: Vec<Ipv6ExtensionHeader<'_>> = packet.iter_extension_hdrs().collect();
1987 assert_eq!(ext_hdrs.len(), 3);
1988 if let Ipv6ExtensionHeader::HopByHopOptions { options } = &ext_hdrs[0] {
1990 assert_eq!(options.iter().count(), 0);
1992 } else {
1993 panic!("Should have matched HopByHopOptions!");
1994 }
1995
1996 if let Ipv6ExtensionHeader::Routing { routing_data } = &ext_hdrs[1] {
1998 assert_eq!(routing_data.routing_type(), Err(RoutingTypeParseError::UnsupportedType(0)));
1999 assert_eq!(routing_data.segments_left(), 0);
2000 } else {
2001 panic!("Should have matched RoutingExtensionHeader: {:?}", &ext_hdrs[1]);
2002 }
2003
2004 if let Ipv6ExtensionHeader::DestinationOptions { options } = &ext_hdrs[2] {
2006 assert_eq!(options.iter().count(), 0);
2008 } else {
2009 panic!("Should have matched DestinationOptions!");
2010 }
2011
2012 #[rustfmt::skip]
2014 let mut buf = [
2015 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2017 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2018
2019 Ipv6Proto::NoNextHeader.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2028 ];
2029 let mut fixed_hdr = new_fixed_hdr();
2030 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2031 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2032 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2033 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2034 let mut buf = &buf[..];
2035 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2036 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
2037 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
2038 assert_eq!(packet.flowlabel(), 0x77);
2039 assert_eq!(packet.hop_limit(), 64);
2040 assert_eq!(packet.fixed_hdr.next_hdr, Ipv6ExtHdrType::HopByHopOptions.into());
2041 assert_eq!(packet.proto(), Ipv6Proto::NoNextHeader);
2042 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
2043 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
2044 assert_eq!(packet.body(), [1, 2, 3, 4, 5]);
2045 let ext_hdrs: Vec<Ipv6ExtensionHeader<'_>> = packet.iter_extension_hdrs().collect();
2046 assert_eq!(ext_hdrs.len(), 1);
2047 if let Ipv6ExtensionHeader::HopByHopOptions { options } = &ext_hdrs[0] {
2049 assert_eq!(options.iter().count(), 0);
2051 } else {
2052 panic!("Should have matched HopByHopOptions!");
2053 }
2054 }
2055
2056 #[test]
2057 fn test_parse_error() {
2058 let mut fixed_hdr = new_fixed_hdr();
2060 fixed_hdr.version_tc_flowlabel[0] = 0x50;
2061 assert_eq!(
2062 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
2063 ParseError::Format.into()
2064 );
2065
2066 let mut fixed_hdr = new_fixed_hdr();
2068 fixed_hdr.payload_len = U16::new(2);
2069 assert_eq!(
2070 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
2071 ParseError::Format.into()
2072 );
2073
2074 let mut fixed_hdr = new_fixed_hdr();
2076 fixed_hdr.next_hdr = 255;
2077 let packet = fixed_hdr_to_bytes(fixed_hdr);
2078
2079 assert!((&packet[..]).parse::<Ipv6PacketRaw<_>>().is_ok());
2081
2082 assert_eq!(
2084 (&packet[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
2085 Ipv6ParseError::ParameterProblem {
2086 src_ip: DEFAULT_SRC_IP,
2087 dst_ip: DEFAULT_DST_IP,
2088 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2089 pointer: u32::from(NEXT_HEADER_OFFSET),
2090 must_send_icmp: false,
2091 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2092 }
2093 );
2094
2095 let mut fixed_hdr = new_fixed_hdr();
2097 fixed_hdr.next_hdr = Ipv4Proto::Icmp.into();
2098 assert_eq!(
2099 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
2100 Ipv6ParseError::ParameterProblem {
2101 src_ip: DEFAULT_SRC_IP,
2102 dst_ip: DEFAULT_DST_IP,
2103 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2104 pointer: u32::from(NEXT_HEADER_OFFSET),
2105 must_send_icmp: false,
2106 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2107 }
2108 );
2109
2110 #[rustfmt::skip]
2112 let mut buf = [
2113 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2115 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2116
2117 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,
2125 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2126
2127 IpProto::Tcp.into(), 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::Routing.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 let mut buf = &buf[..];
2143 assert_eq!(
2144 buf.parse::<Ipv6Packet<_>>().unwrap_err(),
2145 Ipv6ParseError::ParameterProblem {
2146 src_ip: DEFAULT_SRC_IP,
2147 dst_ip: DEFAULT_DST_IP,
2148 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2149 pointer: IPV6_FIXED_HDR_LEN as u32,
2150 must_send_icmp: false,
2151 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2152 }
2153 );
2154
2155 #[rustfmt::skip]
2157 let mut buf = [
2158 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2160 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2161
2162 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,
2170 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2171
2172 1, 2, 3, 4, 5,
2174 ];
2175 let mut fixed_hdr = new_fixed_hdr();
2176 fixed_hdr.next_hdr = Ipv6ExtHdrType::Routing.into();
2177 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2178 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2179 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2180 let expected_error = Ipv6ParseError::ParameterProblem {
2181 src_ip: DEFAULT_SRC_IP,
2182 dst_ip: DEFAULT_DST_IP,
2183 code: Icmpv6ParameterProblemCode::ErroneousHeaderField,
2184 pointer: (IPV6_FIXED_HDR_LEN as u32) + 2,
2185 must_send_icmp: true,
2186 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2187 };
2188 assert_eq!((&buf[..]).parse::<Ipv6Packet<_>>().unwrap_err(), expected_error);
2189
2190 buf[IPV6_FIXED_HDR_LEN] = 250; assert_eq!((&buf[..]).parse::<Ipv6Packet<_>>().unwrap_err(), expected_error);
2196 }
2197
2198 #[test]
2199 fn test_parse_all_next_header_values() {
2200 let mut buf = [
2206 0x81, 0x13, 0x27, 0xeb, 0x75, 0x92, 0x33, 0x89, 0x01, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
2207 0x03, 0x70, 0x00, 0x22, 0xf7, 0x30, 0x2c, 0x06, 0xfe, 0xc9, 0x00, 0x2d, 0x3b, 0xeb,
2208 0xad, 0x3e, 0x5c, 0x41, 0xc8, 0x70, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x11, 0x00,
2209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x4f, 0x4f, 0x6f, 0x4f, 0x4f, 0x4f, 0x4f,
2210 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x19, 0x19,
2211 0x19, 0x19, 0x19, 0x4f, 0x4f, 0x4f, 0x4f, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2212 0x00, 0x4f, 0x4f, 0x5a, 0x5a, 0x5a, 0xc9, 0x5a, 0x46, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
2213 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0xe4, 0x5a, 0x5a, 0x5a, 0x5a,
2214 ];
2215
2216 assert_matches!(
2219 (&buf[..]).parse::<Ipv6Packet<_>>(),
2220 Err(Ipv6ParseError::ParameterProblem {
2221 src_ip: _,
2222 dst_ip: _,
2223 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2224 pointer: 6,
2225 must_send_icmp: false,
2226 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2227 })
2228 );
2229
2230 for b in 0u8..=255 {
2233 buf[6] = b;
2235 let _: Result<_, _> = (&buf[..]).parse::<Ipv6Packet<_>>();
2236 }
2237 }
2238
2239 #[test]
2240 fn test_esp_packet() {
2241 const ESP_NEXT_HEADER: u8 = 50;
2246
2247 let mut fixed_hdr = new_fixed_hdr();
2249 fixed_hdr.next_hdr = ESP_NEXT_HEADER;
2250 fixed_hdr.payload_len = U16::new(8);
2251 let mut buf = fixed_hdr_to_bytes(fixed_hdr).to_vec();
2252 buf.extend_from_slice(&[0; 8]);
2253
2254 assert_matches!(
2256 (&buf[..]).parse::<Ipv6Packet<_>>(),
2257 Err(Ipv6ParseError::ParameterProblem {
2258 src_ip: _,
2259 dst_ip: _,
2260 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2261 pointer: 6, must_send_icmp: false,
2263 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2264 })
2265 );
2266
2267 let mut buf_ref = &buf[..];
2269 assert!(buf_ref.parse::<Ipv6PacketRaw<_>>().is_ok());
2270
2271 let mut fixed_hdr = new_fixed_hdr();
2273 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2274 fixed_hdr.payload_len = U16::new(16);
2275 let mut buf = fixed_hdr_to_bytes(fixed_hdr).to_vec();
2276 buf.extend_from_slice(&[ESP_NEXT_HEADER, 0, 0, 0, 0, 0, 0, 0]);
2278 buf.extend_from_slice(&[0; 8]);
2280
2281 assert_matches!(
2283 (&buf[..]).parse::<Ipv6Packet<_>>(),
2284 Err(Ipv6ParseError::ParameterProblem {
2285 src_ip: _,
2286 dst_ip: _,
2287 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2288 pointer: 40, must_send_icmp: false,
2290 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2291 })
2292 );
2293
2294 let mut buf_ref = &buf[..];
2296 assert!(buf_ref.parse::<Ipv6PacketRaw<_>>().is_ok());
2297 }
2298
2299 #[test]
2300 fn test_parse_ext_hdr_unrecognized_next_header() {
2301 #[rustfmt::skip]
2305 let mut buf = [
2306 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2308 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2309
2310 250, 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2319 ];
2320 let mut fixed_hdr = new_fixed_hdr();
2321 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2322 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2323 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2324 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2325
2326 assert!((&buf[..]).parse::<Ipv6PacketRaw<_>>().is_ok());
2328
2329 assert_eq!(
2331 (&buf[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
2332 Ipv6ParseError::ParameterProblem {
2333 src_ip: DEFAULT_SRC_IP,
2334 dst_ip: DEFAULT_DST_IP,
2335 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2336 pointer: IPV6_FIXED_HDR_LEN as u32,
2337 must_send_icmp: false,
2338 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2339 }
2340 );
2341 }
2342
2343 #[test]
2344 fn test_partial_parse() {
2345 use core::convert::TryInto as _;
2346 use core::ops::Deref as _;
2347
2348 #[rustfmt::skip]
2350 let mut buf = [
2351 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2353 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2354
2355 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2364 ];
2365 let len = buf.len() - IPV6_FIXED_HDR_LEN;
2366 let len = len.try_into().unwrap();
2367 let make_fixed_hdr = || {
2368 let mut fixed_hdr = new_fixed_hdr();
2369 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2370 fixed_hdr.payload_len = U16::new(len);
2371 fixed_hdr
2372 };
2373 const MALFORMED_BYTE: u8 = 10;
2375 buf[IPV6_FIXED_HDR_LEN + 1] = MALFORMED_BYTE;
2376 let fixed_hdr = fixed_hdr_to_bytes(make_fixed_hdr());
2377 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr);
2378 let mut buf = &buf[..];
2379 let partial = buf.parse::<Ipv6PacketRaw<_>>().unwrap();
2380 let Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto } = &partial;
2381 assert_eq!(fixed_hdr.deref(), &make_fixed_hdr());
2382 let b = extension_hdrs.as_ref().incomplete().unwrap();
2383 assert_eq!(*b, &[IpProto::Tcp.into(), MALFORMED_BYTE][..]);
2384 assert_eq!(body_proto, &Err(ExtHdrParseError));
2385 assert!(Ipv6Packet::try_from_raw(partial).is_err());
2386
2387 let mut buf = [
2389 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,
2391 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
2393 ];
2394 let make_fixed_hdr = || {
2395 let mut fixed_hdr = new_fixed_hdr();
2396 fixed_hdr.next_hdr = IpProto::Tcp.into();
2397 fixed_hdr.payload_len = U16::new(10);
2398 fixed_hdr
2399 };
2400 let fixed_hdr = fixed_hdr_to_bytes(make_fixed_hdr());
2401 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr);
2402 let mut parsebuff = &buf[..];
2403 let partial = parsebuff.parse::<Ipv6PacketRaw<_>>().unwrap();
2404 let Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto } = &partial;
2405 assert_eq!(fixed_hdr.deref(), &make_fixed_hdr());
2406 assert_eq!(extension_hdrs.as_ref().complete().unwrap().deref(), []);
2407 let (body, proto) = body_proto.unwrap();
2408 assert_eq!(body.incomplete().unwrap(), &buf[IPV6_FIXED_HDR_LEN..]);
2409 assert_eq!(proto, IpProto::Tcp.into());
2410 assert!(Ipv6Packet::try_from_raw(partial).is_err());
2411 }
2412
2413 fn new_builder() -> Ipv6PacketBuilder {
2415 Ipv6PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, 64, IpProto::Tcp.into())
2416 }
2417
2418 #[test]
2419 fn test_serialize() {
2420 let mut builder = new_builder();
2421 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
2422 builder.flowlabel(0x10405);
2423 let mut buf = (&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2424 .into_serializer()
2425 .wrap_in(builder)
2426 .serialize_vec_outer(&mut NoOpSerializationContext)
2427 .unwrap();
2428 assert_eq!(
2430 buf.as_ref(),
2431 &[
2432 100, 177, 4, 5, 0, 10, 6, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
2433 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, 1, 2, 3, 4,
2434 5, 6, 7, 8, 9
2435 ][..],
2436 );
2437
2438 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2439 assert_eq!(packet.dscp_and_ecn().dscp(), 0x12);
2442 assert_eq!(packet.dscp_and_ecn().ecn(), 3);
2443 assert_eq!(packet.flowlabel(), 0x10405);
2444 }
2445
2446 #[test]
2447 fn test_partial_serialize() {
2448 let mut builder = new_builder();
2449 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
2450 builder.flowlabel(0x10405);
2451 const BODY: &[u8] = &[0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2452 let packet = (&BODY).into_serializer().wrap_in(builder);
2453
2454 const HEADER: &[u8] = &[
2457 100, 177, 4, 5, 0, 10, 6, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
2458 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
2459 ];
2460 const PACKET_SIZE: usize = HEADER.len() + BODY.len();
2461
2462 let buf = assert_matches!(
2465 packet.partial_serialize(&mut NoOpSerializationContext, packet::new_buf_vec),
2466 Ok(PartialSerializeResult::NewBuffer { buffer, total_size: PACKET_SIZE }) => buffer
2467 );
2468 assert_eq!(buf.as_ref(), HEADER);
2469 }
2470
2471 #[test]
2472 fn test_serialize_zeroes() {
2473 let mut buf_0 = [0; IPV6_FIXED_HDR_LEN];
2476 let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], IPV6_FIXED_HDR_LEN..)
2477 .wrap_in(new_builder())
2478 .serialize_vec_outer(&mut NoOpSerializationContext)
2479 .unwrap()
2480 .unwrap_a();
2481 let mut buf_1 = [0xFF; IPV6_FIXED_HDR_LEN];
2482 let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], IPV6_FIXED_HDR_LEN..)
2483 .wrap_in(new_builder())
2484 .serialize_vec_outer(&mut NoOpSerializationContext)
2485 .unwrap()
2486 .unwrap_a();
2487 assert_eq!(&buf_0[..], &buf_1[..]);
2488 }
2489
2490 #[test]
2491 fn test_packet_builder_proto_not_next_header() {
2492 let mut buf = (&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2496 .into_serializer()
2497 .wrap_in(
2498 Ipv6PacketBuilderWithHbhOptions::new(
2499 new_builder(),
2500 &[HopByHopOption {
2501 action: ExtensionHeaderOptionAction::SkipAndContinue,
2502 mutable: false,
2503 data: HopByHopOptionData::RouterAlert { data: 0 },
2504 }],
2505 )
2506 .unwrap(),
2507 )
2508 .serialize_vec_outer(&mut NoOpSerializationContext)
2509 .unwrap();
2510 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2511 assert_eq!(packet.proto(), IpProto::Tcp.into());
2512 assert_eq!(packet.next_header(), Ipv6ExtHdrType::HopByHopOptions.into());
2513 }
2514
2515 #[test]
2516 #[should_panic(expected = "SizeLimitExceeded, Nested { inner: Buf { buf:")]
2517 fn test_serialize_panic_packet_length() {
2518 let _: Buf<&mut [u8]> = Buf::new(&mut [0; 1 << 16][..], ..)
2521 .wrap_in(new_builder())
2522 .serialize_vec_outer(&mut NoOpSerializationContext)
2523 .unwrap()
2524 .unwrap_a();
2525 }
2526
2527 #[test]
2528 #[should_panic(expected = "packet must have at least one extension header")]
2529 fn test_copy_header_bytes_for_fragment_without_ext_hdrs() {
2530 let mut buf = &fixed_hdr_to_bytes(new_fixed_hdr())[..];
2531 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2532 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2533 }
2534
2535 #[test]
2536 #[should_panic(expected = "exhausted all extension headers without finding fragment header")]
2537 fn test_copy_header_bytes_for_fragment_with_1_ext_hdr_no_fragment() {
2538 #[rustfmt::skip]
2539 let mut buf = [
2540 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2542 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2543
2544 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2553 ];
2554 let mut fixed_hdr = new_fixed_hdr();
2555 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2556 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2557 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2558 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2559 let mut buf = &buf[..];
2560 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2561 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2562 }
2563
2564 #[test]
2565 #[should_panic(expected = "exhausted all extension headers without finding fragment header")]
2566 fn test_copy_header_bytes_for_fragment_with_2_ext_hdr_no_fragment() {
2567 #[rustfmt::skip]
2568 let mut buf = [
2569 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2571 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2572
2573 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,
2590 ];
2591 let mut fixed_hdr = new_fixed_hdr();
2592 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2593 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2594 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2595 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2596 let mut buf = &buf[..];
2597 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2598 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2599 }
2600
2601 #[test]
2602 fn test_copy_header_bytes_for_fragment() {
2603 #[rustfmt::skip]
2608 let mut bytes = [
2609 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2611 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2612
2613 IpProto::Tcp.into(), 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5,
2621 ];
2622 let mut fixed_hdr = new_fixed_hdr();
2623 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2624 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2625 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2626 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2627 let mut buf = &bytes[..];
2628 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2629 let copied_bytes = packet.copy_header_bytes_for_fragment();
2630 bytes[6] = IpProto::Tcp.into();
2631 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN]);
2632
2633 #[rustfmt::skip]
2638 let mut bytes = [
2639 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2641 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2642
2643 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,
2658 ];
2659 let mut fixed_hdr = new_fixed_hdr();
2660 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2661 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2662 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2663 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2664 let mut buf = &bytes[..];
2665 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2666 let copied_bytes = packet.copy_header_bytes_for_fragment();
2667 bytes[IPV6_FIXED_HDR_LEN] = IpProto::Tcp.into();
2668 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN + 8]);
2669
2670 #[rustfmt::skip]
2675 let mut bytes = [
2676 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2678 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2679
2680 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,
2703 ];
2704 let mut fixed_hdr = new_fixed_hdr();
2705 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2706 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2707 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2708 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2709 let mut buf = &bytes[..];
2710 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2711 let copied_bytes = packet.copy_header_bytes_for_fragment();
2712 bytes[IPV6_FIXED_HDR_LEN + 8] = IpProto::Tcp.into();
2713 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN + 24]);
2714
2715 #[rustfmt::skip]
2720 let mut bytes = [
2721 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2723 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2724
2725 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,
2741 ];
2742 let mut fixed_hdr = new_fixed_hdr();
2743 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2744 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2745 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2746 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2747 let mut buf = &bytes[..];
2748 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2749 let copied_bytes = packet.copy_header_bytes_for_fragment();
2750 let mut expected_bytes = Vec::new();
2751 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2752 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2753 expected_bytes[6] = Ipv6ExtHdrType::DestinationOptions.into();
2754 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2755
2756 #[rustfmt::skip]
2761 let mut bytes = [
2762 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2764 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2765
2766 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,
2788 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2789
2790 1, 2, 3, 4, 5,
2792 ];
2793 let mut fixed_hdr = new_fixed_hdr();
2794 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2795 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2796 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2797 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2798 let mut buf = &bytes[..];
2799 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2800 let copied_bytes = packet.copy_header_bytes_for_fragment();
2801 let mut expected_bytes = Vec::new();
2802 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2803 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2804 expected_bytes[6] = Ipv6ExtHdrType::DestinationOptions.into();
2805 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2806
2807 #[rustfmt::skip]
2812 let mut bytes = [
2813 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2815 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2816
2817 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,
2840 ];
2841 let mut fixed_hdr = new_fixed_hdr();
2842 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2843 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2844 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2845 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2846 let mut buf = &bytes[..];
2847 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2848 let copied_bytes = packet.copy_header_bytes_for_fragment();
2849 let mut expected_bytes = Vec::new();
2850 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN + 8]);
2851 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 16..bytes.len() - 5]);
2852 expected_bytes[IPV6_FIXED_HDR_LEN] = Ipv6ExtHdrType::DestinationOptions.into();
2853 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2854
2855 #[rustfmt::skip]
2860 let mut bytes = [
2861 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2863 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2864
2865 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,
2879 ];
2880 let mut fixed_hdr = new_fixed_hdr();
2881 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2882 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2883 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2884 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2885 let mut buf = &bytes[..];
2886 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2887 let copied_bytes = packet.copy_header_bytes_for_fragment();
2888 let mut expected_bytes = Vec::new();
2889 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2890 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2891 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2892
2893 #[rustfmt::skip]
2899 let mut bytes = [
2900 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2902 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2903
2904 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,
2919 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2920
2921 IpProto::Tcp.into(), 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5,
2929 ];
2930 let mut fixed_hdr = new_fixed_hdr();
2931 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2932 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2933 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2934 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2935 let mut buf = &bytes[..];
2936 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2937 let copied_bytes = packet.copy_header_bytes_for_fragment();
2938 let mut expected_bytes = Vec::new();
2939 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN + 48]);
2941 expected_bytes[IPV6_FIXED_HDR_LEN + 8] = IpProto::Tcp.into();
2942 assert_eq!(copied_bytes, expected_bytes);
2943 }
2944
2945 #[test_case(
2946 &[],
2947 &[],
2948 None;
2949 "no_ext_hdrs"
2950 )]
2951 #[test_case(
2952 &[Ipv6ExtHdrType::DestinationOptions],
2953 &[],
2954 Some(Ipv6ExtHdrType::DestinationOptions);
2955 "ignore_dst_options"
2956 )]
2957 #[test_case(
2958 &[
2959 Ipv6ExtHdrType::DestinationOptions,
2960 Ipv6ExtHdrType::Routing,
2961 Ipv6ExtHdrType::DestinationOptions
2962 ],
2963 &[Ipv6ExtHdrType::DestinationOptions, Ipv6ExtHdrType::Routing],
2964 Some(Ipv6ExtHdrType::DestinationOptions);
2965 "include_routing_and_everything_before"
2966 )]
2967 #[test_case(
2968 &[Ipv6ExtHdrType::HopByHopOptions, Ipv6ExtHdrType::DestinationOptions],
2969 &[Ipv6ExtHdrType::HopByHopOptions],
2970 Some(Ipv6ExtHdrType::DestinationOptions);
2971 "include_hop_by_hop_if_first"
2972 )]
2973 #[test_case(
2974 &[
2975 Ipv6ExtHdrType::HopByHopOptions,
2976 Ipv6ExtHdrType::DestinationOptions,
2977 Ipv6ExtHdrType::Routing
2978 ],
2979 &[
2980 Ipv6ExtHdrType::HopByHopOptions,
2981 Ipv6ExtHdrType::DestinationOptions,
2982 Ipv6ExtHdrType::Routing
2983 ],
2984 None;
2985 "routing_header_takes_precedence_over_hop_by_hop"
2986 )]
2987 fn test_per_fragment_header_builder(
2988 original_ext_hdrs: &[Ipv6ExtHdrType],
2989 expected_ext_hdrs: &[Ipv6ExtHdrType],
2990 expected_next_hdr: Option<Ipv6ExtHdrType>,
2991 ) {
2992 #[rustfmt::skip]
2993 fn build_routing_header(nh: u8) -> [u8; 40] {
2994 [
2995 nh, 4, 0, 0, 0, 0, 0, 0,
2996 1, 2, 3, 4, 5, 6, 7, 8,
2997 9, 10, 11, 12, 13, 14, 15, 16,
2998 17, 18, 19, 20, 21, 22, 23, 24,
2999 25, 26, 27, 28, 29, 30, 31, 32
3000 ]
3001 }
3002 fn build_hop_by_hop_header(nh: u8) -> [u8; 8] {
3003 [nh, 0, 0, 1, 0, 1, 1, 0]
3004 }
3005 #[rustfmt::skip]
3006 fn build_destination_options_header(nh: u8) -> [u8; 16] {
3007 [
3008 nh, 1, 0, 1, 0, 1, 1, 0,
3009 1, 6, 0, 0, 0, 0, 0, 0
3010 ]
3011 }
3012 fn build_fragment_header(nh: u8, id: u32) -> [u8; 8] {
3013 let [id1, id2, id3, id4] = id.to_be_bytes();
3014 [nh, 0, 0, 0, id1, id2, id3, id4]
3015 }
3016 fn build_header_bytes(ext_hdrs: &[Ipv6ExtHdrType], final_header: u8) -> Vec<u8> {
3017 let mut fixed_hdr = new_fixed_hdr();
3019 if ext_hdrs.is_empty() {
3020 fixed_hdr.next_hdr = final_header;
3021 } else {
3022 fixed_hdr.next_hdr = u8::from(ext_hdrs[0]);
3023 }
3024
3025 let mut ext_hdr_bytes = Vec::new();
3027 for i in 0..ext_hdrs.len() {
3028 let next_header =
3029 if i + 1 >= ext_hdrs.len() { final_header } else { u8::from(ext_hdrs[i + 1]) };
3030 match ext_hdrs[i] {
3031 Ipv6ExtHdrType::DestinationOptions => ext_hdr_bytes
3032 .extend_from_slice(&build_destination_options_header(next_header)),
3033 Ipv6ExtHdrType::Routing => {
3034 ext_hdr_bytes.extend_from_slice(&build_routing_header(next_header))
3035 }
3036 Ipv6ExtHdrType::HopByHopOptions => {
3037 ext_hdr_bytes.extend_from_slice(&build_hop_by_hop_header(next_header))
3038 }
3039 h => panic!("unexpected header type: {h}"),
3040 }
3041 }
3042
3043 let mut bytes = fixed_hdr_to_bytes(fixed_hdr).to_vec();
3044 bytes.extend_from_slice(&ext_hdr_bytes[..]);
3045 bytes
3046 }
3047
3048 const BODY: [u8; 5] = [1, 2, 3, 4, 5];
3050 let payload_header = u8::from(IpProto::Tcp);
3051 let mut bytes = build_header_bytes(original_ext_hdrs, payload_header);
3052 bytes.extend_from_slice(&BODY);
3053 let len = u16::try_from(bytes.len() - IPV6_FIXED_HDR_LEN).expect("should fit in a u16");
3054 bytes.as_mut_slice()[IPV6_PAYLOAD_LEN_BYTE_RANGE].copy_from_slice(&len.to_be_bytes());
3055 let mut buf = &bytes[..];
3056 let packet = buf.parse::<Ipv6Packet<_>>().expect("parse should succeed");
3057
3058 let serialized = packet
3060 .per_fragment_builder()
3061 .wrap_body(EmptyBuf)
3062 .serialize_vec_outer(&mut NoOpSerializationContext)
3063 .unwrap()
3064 .unwrap_b();
3065 let expected_next_hdr = expected_next_hdr.map(u8::from).unwrap_or(payload_header);
3066 let mut expected_bytes = build_header_bytes(expected_ext_hdrs, expected_next_hdr);
3067 let len =
3068 u16::try_from(expected_bytes.len() - IPV6_FIXED_HDR_LEN).expect("should fit in a u16");
3069 expected_bytes.as_mut_slice()[IPV6_PAYLOAD_LEN_BYTE_RANGE]
3070 .copy_from_slice(&len.to_be_bytes());
3071 assert_eq!(serialized.as_ref(), &expected_bytes[..]);
3072
3073 let builder = packet.per_fragment_builder();
3077 let body = &bytes[builder.header_len()..];
3078 const ID: u32 = 0x12345678;
3079 let frag_builder =
3080 Ipv6PacketBuilderWithFragmentHeader::new(builder, FragmentOffset::ZERO, false, ID);
3081 let serialized = frag_builder
3082 .wrap_body(body.into_serializer())
3083 .serialize_vec_outer(&mut NoOpSerializationContext)
3084 .unwrap()
3085 .unwrap_b();
3086 let mut expected_bytes =
3087 build_header_bytes(expected_ext_hdrs, u8::from(Ipv6ExtHdrType::Fragment));
3088 expected_bytes.extend_from_slice(&build_fragment_header(expected_next_hdr, ID));
3089 expected_bytes.extend_from_slice(body);
3090 let len =
3091 u16::try_from(expected_bytes.len() - IPV6_FIXED_HDR_LEN).expect("should fit in a u16");
3092 expected_bytes.as_mut_slice()[IPV6_PAYLOAD_LEN_BYTE_RANGE]
3093 .copy_from_slice(&len.to_be_bytes());
3094 assert_eq!(serialized.as_ref(), &expected_bytes[..]);
3095 }
3096
3097 #[test]
3098 fn test_next_multiple_of_eight() {
3099 for x in 0usize..=IPV6_HBH_OPTIONS_MAX_LEN {
3100 let y = next_multiple_of_eight(x);
3101 assert_eq!(y % 8, 0);
3102 assert!(y >= x);
3103 if x % 8 == 0 {
3104 assert_eq!(x, y);
3105 } else {
3106 assert_eq!(x + (8 - x % 8), y);
3107 }
3108 }
3109 }
3110
3111 fn create_ipv4_and_ipv6_builders(
3112 proto_v4: Ipv4Proto,
3113 proto_v6: Ipv6Proto,
3114 ) -> (Ipv4PacketBuilder, Ipv6PacketBuilder) {
3115 const IP_DSCP_AND_ECN: DscpAndEcn = DscpAndEcn::new(0x12, 3);
3116 const IP_TTL: u8 = 64;
3117
3118 let mut ipv4_builder =
3119 Ipv4PacketBuilder::new(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP, IP_TTL, proto_v4);
3120 ipv4_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
3121 ipv4_builder.df_flag(false);
3122 ipv4_builder.mf_flag(false);
3123 ipv4_builder.fragment_offset(FragmentOffset::ZERO);
3124
3125 let mut ipv6_builder =
3126 Ipv6PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, IP_TTL, proto_v6);
3127 ipv6_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
3128 ipv6_builder.flowlabel(0x456);
3129
3130 (ipv4_builder, ipv6_builder)
3131 }
3132
3133 fn create_tcp_ipv4_and_ipv6_pkt()
3134 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
3135 use crate::tcp::TcpSegmentBuilder;
3136 use core::num::NonZeroU16;
3137
3138 let tcp_src_port: NonZeroU16 = NonZeroU16::new(20).unwrap();
3139 let tcp_dst_port: NonZeroU16 = NonZeroU16::new(30).unwrap();
3140 const TCP_SEQ_NUM: u32 = 4321;
3141 const TCP_ACK_NUM: Option<u32> = Some(1234);
3142 const TCP_WINDOW_SIZE: u16 = 12345;
3143 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
3144
3145 let (ipv4_builder, ipv6_builder) =
3146 create_ipv4_and_ipv6_builders(IpProto::Tcp.into(), IpProto::Tcp.into());
3147
3148 let tcp_builder = TcpSegmentBuilder::new(
3149 DEFAULT_V4_SRC_IP,
3150 DEFAULT_V4_DST_IP,
3151 tcp_src_port,
3152 tcp_dst_port,
3153 TCP_SEQ_NUM,
3154 TCP_ACK_NUM,
3155 TCP_WINDOW_SIZE,
3156 );
3157
3158 let v4_pkt_buf = (&PAYLOAD)
3159 .into_serializer()
3160 .wrap_in(tcp_builder)
3161 .wrap_in(ipv4_builder)
3162 .serialize_vec_outer(&mut NoOpSerializationContext)
3163 .expect("Failed to serialize to v4_pkt_buf");
3164
3165 let v6_tcp_builder = TcpSegmentBuilder::new(
3166 DEFAULT_SRC_IP,
3167 DEFAULT_DST_IP,
3168 tcp_src_port,
3169 tcp_dst_port,
3170 TCP_SEQ_NUM,
3171 TCP_ACK_NUM,
3172 TCP_WINDOW_SIZE,
3173 );
3174
3175 let v6_pkt_buf = (&PAYLOAD)
3176 .into_serializer()
3177 .wrap_in(v6_tcp_builder)
3178 .wrap_in(ipv6_builder)
3179 .serialize_vec_outer(&mut NoOpSerializationContext)
3180 .expect("Failed to serialize to v4_pkt_buf");
3181
3182 (v4_pkt_buf, v6_pkt_buf)
3183 }
3184
3185 #[test]
3186 fn test_nat64_translate_tcp() {
3187 let (expected_v4_pkt_buf, mut v6_pkt_buf) = create_tcp_ipv4_and_ipv6_pkt();
3188
3189 let parsed_v6_packet =
3190 v6_pkt_buf.parse::<Ipv6Packet<_>>().expect("Failed to parse v6_pkt_buf");
3191 let nat64_translation_result =
3192 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
3193
3194 let serializable_pkt =
3195 assert_matches!(nat64_translation_result, Nat64TranslationResult::Forward(s) => s);
3196
3197 let translated_v4_pkt_buf = serializable_pkt
3198 .serialize_vec_outer(&mut NoOpSerializationContext)
3199 .expect("Failed to serialize to translated_v4_pkt_buf");
3200
3201 assert_eq!(
3202 expected_v4_pkt_buf.to_flattened_vec(),
3203 translated_v4_pkt_buf.to_flattened_vec()
3204 );
3205 }
3206
3207 fn create_udp_ipv4_and_ipv6_pkt()
3208 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
3209 use crate::udp::UdpPacketBuilder;
3210 use core::num::NonZeroU16;
3211
3212 let udp_src_port: NonZeroU16 = NonZeroU16::new(35000).unwrap();
3213 let udp_dst_port: NonZeroU16 = NonZeroU16::new(53).unwrap();
3214 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
3215
3216 let (ipv4_builder, ipv6_builder) =
3217 create_ipv4_and_ipv6_builders(IpProto::Udp.into(), IpProto::Udp.into());
3218
3219 let v4_udp_builder = UdpPacketBuilder::new(
3220 DEFAULT_V4_SRC_IP,
3221 DEFAULT_V4_DST_IP,
3222 Some(udp_src_port),
3223 udp_dst_port,
3224 );
3225
3226 let v4_pkt_buf = (&PAYLOAD)
3227 .into_serializer()
3228 .wrap_in(v4_udp_builder)
3229 .wrap_in(ipv4_builder)
3230 .serialize_vec_outer(&mut NoOpSerializationContext)
3231 .expect("Unable to serialize to v4_pkt_buf");
3232
3233 let v6_udp_builder =
3234 UdpPacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, Some(udp_src_port), udp_dst_port);
3235
3236 let v6_pkt_buf = (&PAYLOAD)
3237 .into_serializer()
3238 .wrap_in(v6_udp_builder)
3239 .wrap_in(ipv6_builder)
3240 .serialize_vec_outer(&mut NoOpSerializationContext)
3241 .expect("Unable to serialize to v6_pkt_buf");
3242
3243 (v4_pkt_buf, v6_pkt_buf)
3244 }
3245
3246 #[test]
3247 fn test_nat64_translate_udp() {
3248 let (expected_v4_pkt_buf, mut v6_pkt_buf) = create_udp_ipv4_and_ipv6_pkt();
3249
3250 let parsed_v6_packet =
3251 v6_pkt_buf.parse::<Ipv6Packet<_>>().expect("Unable to parse Ipv6Packet");
3252 let nat64_translation_result =
3253 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
3254
3255 let serializable_pkt = assert_matches!(nat64_translation_result,
3256 Nat64TranslationResult::Forward(s) => s);
3257
3258 let translated_v4_pkt_buf = serializable_pkt
3259 .serialize_vec_outer(&mut NoOpSerializationContext)
3260 .expect("Unable to serialize to translated_v4_pkt_buf");
3261
3262 assert_eq!(
3263 expected_v4_pkt_buf.to_flattened_vec(),
3264 translated_v4_pkt_buf.to_flattened_vec()
3265 );
3266 }
3267
3268 #[test]
3269 fn test_nat64_translate_non_tcp_udp_icmp() {
3270 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
3271
3272 let (ipv4_builder, ipv6_builder) =
3273 create_ipv4_and_ipv6_builders(Ipv4Proto::Other(59), Ipv6Proto::Other(59));
3274
3275 let expected_v4_pkt_buf = (&PAYLOAD)
3276 .into_serializer()
3277 .wrap_in(ipv4_builder)
3278 .serialize_vec_outer(&mut NoOpSerializationContext)
3279 .expect("Unable to serialize to expected_v4_pkt_buf");
3280
3281 let mut v6_pkt_buf = (&PAYLOAD)
3282 .into_serializer()
3283 .wrap_in(ipv6_builder)
3284 .serialize_vec_outer(&mut NoOpSerializationContext)
3285 .expect("Unable to serialize to v6_pkt_buf");
3286
3287 let translated_v4_pkt_buf = {
3288 let parsed_v6_packet = v6_pkt_buf
3289 .parse::<Ipv6Packet<_>>()
3290 .expect("Unable to serialize to translated_v4_pkt_buf");
3291
3292 let nat64_translation_result =
3293 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
3294
3295 let serializable_pkt = assert_matches!(nat64_translation_result,
3296 Nat64TranslationResult::Forward(s) => s);
3297
3298 let translated_buf = serializable_pkt
3299 .serialize_vec_outer(&mut NoOpSerializationContext)
3300 .expect("Unable to serialize to translated_buf");
3301
3302 translated_buf
3303 };
3304
3305 assert_eq!(
3306 expected_v4_pkt_buf.to_flattened_vec(),
3307 translated_v4_pkt_buf.to_flattened_vec()
3308 );
3309 }
3310
3311 #[test_case(new_builder(), true; "fixed header more frags")]
3312 #[test_case(Ipv6PacketBuilderWithHbhOptions::new(
3313 new_builder(),
3314 &[HopByHopOption {
3315 action: ExtensionHeaderOptionAction::SkipAndContinue,
3316 mutable: false,
3317 data: HopByHopOptionData::RouterAlert { data: 0 },
3318 }]).unwrap(), false; "hbh last frag")]
3319 fn ipv6_packet_builder_with_fragment_header<
3320 B: Ipv6HeaderBuilder + Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>> + Debug,
3321 >(
3322 inner: B,
3323 more_fragments: bool,
3324 ) {
3325 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
3326 let fragment_offset = FragmentOffset::new(13).unwrap();
3327 let identification = 0xABCDABCD;
3328 let builder = Ipv6PacketBuilderWithFragmentHeader::new(
3329 inner,
3330 fragment_offset,
3331 more_fragments,
3332 identification,
3333 );
3334 let mut serialized = builder
3335 .wrap_body(PAYLOAD.into_serializer())
3336 .serialize_vec_outer(&mut NoOpSerializationContext)
3337 .unwrap()
3338 .unwrap_b();
3339 let packet = serialized.parse::<Ipv6Packet<_>>().unwrap();
3340 assert!(packet.fragment_header_present());
3341 assert_eq!(packet.proto(), Ipv6Proto::Proto(IpProto::Tcp));
3342 let fragment_data = packet
3343 .extension_hdrs
3344 .into_iter()
3345 .find_map(|ext_hdr| match ext_hdr {
3346 Ipv6ExtensionHeader::Fragment { fragment_data } => Some(fragment_data),
3347 _ => None,
3348 })
3349 .unwrap();
3350 assert_eq!(fragment_data.fragment_offset(), fragment_offset);
3351 assert_eq!(fragment_data.identification(), identification);
3352 assert_eq!(fragment_data.m_flag(), more_fragments);
3353 }
3354
3355 #[test]
3358 fn extension_headers_take_from_max_body_size() {
3359 let builder = new_builder();
3360 assert_eq!(builder.constraints().max_body_len(), IPV6_MAX_PAYLOAD_LENGTH);
3361 let builder =
3362 Ipv6PacketBuilderWithFragmentHeader::new(builder, FragmentOffset::ZERO, false, 1234);
3363 assert_eq!(
3364 builder.constraints().max_body_len(),
3365 IPV6_MAX_PAYLOAD_LENGTH - IPV6_FRAGMENT_EXT_HDR_LEN
3366 );
3367 }
3368
3369 #[test]
3370 fn test_partial_serialize_parsed() {
3371 const PACKET_BYTES: &[u8] = &[
3372 100, 177, 4, 5, 0, 10, 6, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
3373 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, 1, 2, 3, 4, 5, 6, 7,
3374 8, 9,
3375 ];
3376 const PACKET_LEN: usize = PACKET_BYTES.len();
3377 let mut packet_bytes_copy = Vec::from(PACKET_BYTES);
3378 let mut packet_bytes_ref: &mut [u8] = &mut packet_bytes_copy[..];
3379 let packet = packet_bytes_ref.parse::<Ipv6Packet<_>>().unwrap();
3380
3381 let buf = assert_matches!(
3382 packet.partial_serialize(&mut NoOpSerializationContext, packet::new_buf_vec),
3383 Ok(PartialSerializeResult::NewBuffer { buffer, total_size: PACKET_LEN }) => buffer
3384 );
3385 assert_eq!(buf.as_ref(), PACKET_BYTES);
3386 }
3387}