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) =
316 raw.body_proto.expect("Unable to retrieve Ipv6Proto or MaybeParsed body from raw");
317 debug_assert!(
318 extension_hdrs
319 .iter()
320 .any(|ext_hdr| matches!(ext_hdr, Ipv6ExtensionHeader::Fragment { .. }))
321 || is_valid_next_header_upper_layer(proto.into())
322 );
323
324 let body = match body {
325 MaybeParsed::Complete(b) => b,
326 MaybeParsed::Incomplete(_b) => {
327 return debug_err!(Err(ParseError::Format.into()), "IPv6 body unretrievable.");
328 }
329 };
330
331 if extension_hdrs.bytes().len() + body.len() != usize::from(fixed_hdr.payload_len.get()) {
336 return debug_err!(
337 Err(ParseError::Format.into()),
338 "Payload len does not match body and extension headers"
339 );
340 }
341
342 if fixed_hdr.version() != 6 {
344 return debug_err!(
345 Err(ParseError::Format.into()),
346 "unexpected IP version: {}",
347 fixed_hdr.version()
348 );
349 }
350
351 Ok(Ipv6Packet { fixed_hdr, extension_hdrs, body, proto })
352 }
353}
354
355impl<B, C> PartialSerializer<C> for Ipv6Packet<B>
356where
357 B: SplitByteSlice,
358 C: IpSerializationContext<Ipv6>,
359{
360 fn partial_serialize_new_buf<BB: GrowBufferMut, A: LayoutBufferAlloc<BB>>(
365 &self,
366 _context: &mut C,
367 constraints: PacketConstraints,
368 alloc: A,
369 ) -> Result<(BB, usize), SerializeError<A::Error>> {
370 let fixed_hdr = Ref::bytes(&self.fixed_hdr);
373 let extension_hdrs = self.extension_hdrs.bytes();
374 let fixed_hdr_len = fixed_hdr.len();
375 let header_len = fixed_hdr_len + extension_hdrs.len();
376 let body_to_copy = self.body().len().min(TRANSPORT_HEADER_MAX_SIZE);
377 let outer_header_len = constraints.header_len();
378 let mut buffer = alloc.layout_alloc(outer_header_len + header_len, body_to_copy, 0)?;
379 buffer.with_parts_mut(|prefix, mut body, _suffix| {
380 let extensions_pos = outer_header_len + fixed_hdr_len;
381 prefix[outer_header_len..extensions_pos].copy_from_slice(fixed_hdr);
382 prefix[extensions_pos..].copy_from_slice(extension_hdrs);
383 body.copy_from_slice(&self.body()[..body_to_copy]);
384 });
385 buffer.grow_front(header_len);
386 let total_size = header_len + self.body.len();
387 Ok((buffer, total_size))
388 }
389}
390
391impl<B: SplitByteSlice> Ipv6Packet<B> {
392 pub fn iter_extension_hdrs(&self) -> impl Iterator<Item = Ipv6ExtensionHeader<'_>> {
399 self.extension_hdrs.iter()
400 }
401
402 pub fn body(&self) -> &[u8] {
404 &self.body
405 }
406
407 pub fn dscp_and_ecn(&self) -> DscpAndEcn {
410 self.fixed_hdr.dscp_and_ecn()
411 }
412
413 pub fn flowlabel(&self) -> u32 {
415 self.fixed_hdr.flowlabel()
416 }
417
418 pub fn proto(&self) -> Ipv6Proto {
434 self.proto
435 }
436
437 pub fn src_ipv6(&self) -> Option<Ipv6SourceAddr> {
444 Ipv6SourceAddr::new(self.fixed_hdr.src_ip)
445 }
446
447 pub fn copy_header_bytes_for_fragment(&self) -> Vec<u8> {
460 let expected_bytes_len = self.header_len() - IPV6_FRAGMENT_EXT_HDR_LEN;
463 let mut bytes = Vec::with_capacity(expected_bytes_len);
464
465 bytes.extend_from_slice(Ref::bytes(&self.fixed_hdr));
466
467 let mut iter = self.extension_hdrs.iter();
473 let fragment_hdr_next_header_offset = loop {
474 let next_header_offset = iter.context().next_header_offset;
475 match iter
478 .next()
479 .expect("exhausted all extension headers without finding fragment header")
480 {
481 Ipv6ExtensionHeader::Fragment { .. } => break next_header_offset,
482 Ipv6ExtensionHeader::HopByHopOptions { .. }
483 | Ipv6ExtensionHeader::DestinationOptions { .. }
484 | Ipv6ExtensionHeader::Routing { .. } => {}
485 }
486 };
487 debug_assert!(iter.next().is_none(), "fragment header must be the last extension header");
488
489 let extension_hdr_bytes = self.extension_hdrs.bytes();
491 let (preceding_hdrs, fragment_hdr) =
492 extension_hdr_bytes.split_at(extension_hdr_bytes.len() - IPV6_FRAGMENT_EXT_HDR_LEN);
493 bytes.extend_from_slice(preceding_hdrs);
494
495 bytes[fragment_hdr_next_header_offset] = fragment_hdr[0];
499
500 assert_eq!(bytes.len(), expected_bytes_len);
502 bytes
503 }
504
505 pub fn per_fragment_builder(&self) -> Ipv6PerFragmentHeaderBuilder<Vec<u8>> {
522 let mut routing_point = None;
523 let mut hbh_point = None;
524 let mut iter = self.extension_hdrs.iter();
525 let mut is_first_ext_hdr = true;
526
527 while let Some(ext_hdr) = iter.next() {
528 match ext_hdr {
529 Ipv6ExtensionHeader::HopByHopOptions { .. } => {
530 if is_first_ext_hdr {
539 hbh_point = Some((
540 iter.context().position,
541 iter.context().next_header_offset,
542 iter.context().next_header,
543 ));
544 }
545 }
546 Ipv6ExtensionHeader::Routing { .. } => {
547 routing_point = Some((
548 iter.context().position,
549 iter.context().next_header_offset,
550 iter.context().next_header,
551 ));
552 break;
553 }
554 _ => {}
555 }
556 is_first_ext_hdr = false;
557 }
558
559 let split_point = routing_point.or(hbh_point);
560 let (meta, next_header) = match split_point {
561 Some((position, next_header_offset, next_header)) => (
562 Some(Ipv6PerFragmentMeta {
563 ext_hdrs: self.extension_hdrs.bytes()[..position - IPV6_FIXED_HDR_LEN].to_vec(),
564 first_ext_hdr: Ipv6ExtHdrType::from(self.fixed_hdr.next_hdr),
565 last_next_hdr_offset: next_header_offset - IPV6_FIXED_HDR_LEN,
566 }),
567 next_header,
568 ),
569 None => (None, self.fixed_hdr.next_hdr),
570 };
571 let mut prefix_builder = self.builder();
576 prefix_builder.proto = Ipv6Proto::from(next_header);
577
578 Ipv6PerFragmentHeaderBuilder { prefix_builder, meta }
579 }
580
581 pub fn header_len(&self) -> usize {
583 Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.bytes().len()
584 }
585
586 fn fragment_header_present(&self) -> bool {
587 for ext_hdr in self.extension_hdrs.iter() {
588 if matches!(ext_hdr, Ipv6ExtensionHeader::Fragment { .. }) {
589 return true;
590 }
591 }
592 false
593 }
594
595 pub fn builder(&self) -> Ipv6PacketBuilder {
597 Ipv6PacketBuilder {
598 dscp_and_ecn: self.dscp_and_ecn(),
599 flowlabel: self.flowlabel(),
600 hop_limit: self.hop_limit(),
601 proto: self.proto(),
602 src_ip: self.src_ip(),
603 dst_ip: self.dst_ip(),
604 }
605 }
606
607 pub fn nat64_translate(
633 &self,
634 v4_src_addr: Ipv4Addr,
635 v4_dst_addr: Ipv4Addr,
636 ) -> Nat64TranslationResult<
637 impl Serializer<NoOpSerializationContext, Buffer = EmptyBuf> + Debug + '_,
638 Nat64Error,
639 > {
640 #[derive(Debug)]
643 enum Nat64Serializer<T, U, O> {
644 Tcp(T),
645 Udp(U),
646 Other(O),
647 }
648 impl<T, U, O> Serializer<NoOpSerializationContext> for Nat64Serializer<T, U, O>
649 where
650 T: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
651 U: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
652 O: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
653 {
654 type Buffer = EmptyBuf;
655 fn serialize<B, P>(
656 self,
657 context: &mut NoOpSerializationContext,
658 outer: PacketConstraints,
659 provider: P,
660 ) -> Result<B, (SerializeError<P::Error>, Self)>
661 where
662 B: GrowBufferMut,
663 P: BufferProvider<Self::Buffer, B>,
664 {
665 match self {
666 Nat64Serializer::Tcp(serializer) => serializer
667 .serialize(context, outer, provider)
668 .map_err(|(err, ser)| (err, Nat64Serializer::Tcp(ser))),
669 Nat64Serializer::Udp(serializer) => serializer
670 .serialize(context, outer, provider)
671 .map_err(|(err, ser)| (err, Nat64Serializer::Udp(ser))),
672 Nat64Serializer::Other(serializer) => serializer
673 .serialize(context, outer, provider)
674 .map_err(|(err, ser)| (err, Nat64Serializer::Other(ser))),
675 }
676 }
677
678 fn serialize_new_buf<B: GrowBufferMut, A: LayoutBufferAlloc<B>>(
679 &self,
680 context: &mut NoOpSerializationContext,
681 outer: PacketConstraints,
682 alloc: A,
683 ) -> Result<B, SerializeError<A::Error>> {
684 match self {
685 Nat64Serializer::Tcp(serializer) => {
686 serializer.serialize_new_buf(context, outer, alloc)
687 }
688 Nat64Serializer::Udp(serializer) => {
689 serializer.serialize_new_buf(context, outer, alloc)
690 }
691 Nat64Serializer::Other(serializer) => {
692 serializer.serialize_new_buf(context, outer, alloc)
693 }
694 }
695 }
696 }
697
698 impl<T, U, O> NestableSerializer for Nat64Serializer<T, U, O>
699 where
700 T: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
701 U: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
702 O: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
703 {
704 }
705
706 if self.fragment_header_present() {
709 return Nat64TranslationResult::Err(Nat64Error::NotImplemented);
710 }
711
712 let v4_builder = |v4_proto| {
713 let mut builder =
714 Ipv4PacketBuilder::new(v4_src_addr, v4_dst_addr, self.hop_limit(), v4_proto);
715 builder.dscp_and_ecn(self.dscp_and_ecn());
716
717 const IPV4_HEADER_LEN_BYTES: usize = HDR_PREFIX_LEN;
722
723 builder.df_flag(self.body().len() + IPV4_HEADER_LEN_BYTES > 1260);
729
730 builder.fragment_offset(FragmentOffset::ZERO);
733 builder.mf_flag(false);
734
735 builder
736 };
737
738 match self.proto() {
739 Ipv6Proto::Proto(IpProto::Tcp) => {
740 let v4_pkt_builder = v4_builder(Ipv4Proto::Proto(IpProto::Tcp));
741 let args = TcpParseArgs::new(self.src_ip(), self.dst_ip());
742 match TcpSegment::parse(&mut self.body.as_bytes(), args) {
747 Ok(tcp) => {
748 let tcp_serializer =
752 Nat64Serializer::Tcp(tcp.into_serializer(v4_src_addr, v4_dst_addr));
753 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(tcp_serializer))
754 }
755 Err(msg) => {
756 debug!("Parsing of TCP segment failed: {:?}", msg);
757
758 let common_serializer =
767 Nat64Serializer::Other(self.body().into_serializer());
768 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
769 }
770 }
771 }
772
773 Ipv6Proto::Proto(IpProto::Udp) => {
778 let v4_pkt_builder = v4_builder(Ipv4Proto::Proto(IpProto::Udp));
779 let args = UdpParseArgs::new(self.src_ip(), self.dst_ip());
780 match UdpPacket::parse(&mut self.body.as_bytes(), args) {
781 Ok(udp) => {
782 let udp_serializer =
786 Nat64Serializer::Udp(udp.into_serializer(v4_src_addr, v4_dst_addr));
787 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(udp_serializer))
788 }
789 Err(msg) => {
790 debug!("Parsing of UDP packet failed: {:?}", msg);
791
792 let common_serializer =
802 Nat64Serializer::Other(self.body().into_serializer());
803 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
804 }
805 }
806 }
807
808 Ipv6Proto::Icmpv6 => Nat64TranslationResult::Err(Nat64Error::NotImplemented),
811
812 Ipv6Proto::Other(val) => {
832 let v4_pkt_builder = v4_builder(Ipv4Proto::Other(val));
833 let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
834 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
835 }
836
837 Ipv6Proto::NoNextHeader => {
838 let v4_pkt_builder = v4_builder(Ipv4Proto::Other(Ipv6Proto::NoNextHeader.into()));
839 let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
840 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
841 }
842
843 Ipv6Proto::Proto(IpProto::Reserved) => Nat64TranslationResult::Drop,
846 }
847 }
848
849 pub fn to_vec(&self) -> Vec<u8> {
851 let Ipv6Packet { fixed_hdr, extension_hdrs, body, proto: _ } = self;
852 let mut buf = Vec::with_capacity(
853 Ref::bytes(&fixed_hdr).len() + extension_hdrs.bytes().len() + body.as_bytes().len(),
854 );
855 buf.extend(Ref::bytes(&fixed_hdr));
856 buf.extend(extension_hdrs.bytes());
857 buf.extend(body.as_bytes());
858 buf
859 }
860}
861
862impl<B: SplitByteSliceMut> Ipv6Packet<B> {
863 pub fn set_src_ip(&mut self, addr: Ipv6Addr) {
865 self.fixed_hdr.src_ip = addr;
866 }
867
868 pub fn set_dst_ip(&mut self, addr: Ipv6Addr) {
870 self.fixed_hdr.dst_ip = addr;
871 }
872
873 pub fn set_hop_limit(&mut self, hlim: u8) {
875 self.fixed_hdr.hop_limit = hlim;
876 }
877
878 pub fn body_mut(&mut self) -> &mut [u8] {
880 &mut self.body
881 }
882
883 pub fn parts_with_body_mut(&mut self) -> (&FixedHeader, ExtensionHeaders<'_>, &mut [u8]) {
886 (&self.fixed_hdr, ExtensionHeaders(self.extension_hdrs.as_ref()), &mut self.body)
887 }
888}
889
890impl<B: SplitByteSlice> Debug for Ipv6Packet<B> {
891 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
892 f.debug_struct("Ipv6Packet")
893 .field("src_ip", &self.src_ip())
894 .field("dst_ip", &self.dst_ip())
895 .field("hop_limit", &self.hop_limit())
896 .field("proto", &self.proto())
897 .field("dscp", &self.dscp_and_ecn().dscp())
898 .field("ecn", &self.dscp_and_ecn().ecn())
899 .field("flowlabel", &self.flowlabel())
900 .field("extension headers", &"TODO")
901 .field("body", &alloc::format!("<{} bytes>", self.body.len()))
902 .finish()
903 }
904}
905
906pub struct ExtensionHeaders<'a>(Records<&'a [u8], Ipv6ExtensionHeaderImpl>);
908
909impl<'a> ExtensionHeaders<'a> {
910 pub fn iter(&self) -> impl Iterator<Item = Ipv6ExtensionHeader<'_>> {
912 self.0.iter()
913 }
914
915 pub fn bytes(&self) -> &[u8] {
917 self.0.bytes()
918 }
919}
920
921#[derive(Copy, Clone, Debug, Eq, PartialEq)]
927pub struct ExtHdrParseError;
928
929pub struct Ipv6PacketRaw<B> {
939 fixed_hdr: Ref<B, FixedHeader>,
941 extension_hdrs: MaybeParsed<RecordsRaw<B, Ipv6ExtensionHeaderImpl>, B>,
947 body_proto: Result<(MaybeParsed<B, B>, Ipv6Proto), ExtHdrParseError>,
960}
961
962impl<B> Ipv6PacketRaw<B> {
963 pub fn body_mut(&mut self) -> Option<&mut B> {
967 match self.body_proto {
968 Ok(ref mut b) => match b {
969 (MaybeParsed::Complete(b), _) => Some(b),
970 (MaybeParsed::Incomplete(b), _) => Some(b),
971 },
972 Err(_) => None,
973 }
974 }
975}
976
977impl<B: SplitByteSlice> Ipv6Header for Ipv6PacketRaw<B> {
978 fn get_fixed_header(&self) -> &FixedHeader {
979 &self.fixed_hdr
980 }
981}
982
983impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv6PacketRaw<B> {
984 type Error = Ipv6ParseError;
985
986 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> Result<Self, Self::Error> {
987 let fixed_hdr = buffer
988 .take_obj_front::<FixedHeader>()
989 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for header"))?;
990 let payload_len = fixed_hdr.payload_len.get().into();
991 let _: Option<B> = buffer.len().checked_sub(payload_len).map(|padding| {
993 buffer.take_back(padding).unwrap_or_else(|| {
994 panic!("buffer.len()={} padding={}", buffer.len(), padding);
995 })
996 });
997
998 let mut extension_hdr_context = Ipv6ExtensionHeaderParsingContext::new(fixed_hdr.next_hdr);
999
1000 let extension_hdrs =
1001 RecordsRaw::parse_raw_with_mut_context(&mut buffer, &mut extension_hdr_context)
1002 .map_incomplete(|(b, _)| b);
1003
1004 let body_proto = match &extension_hdrs {
1005 MaybeParsed::Complete(r) => {
1006 let _: &RecordsRaw<B, _> = r;
1007 assert!(
1029 extension_hdr_context.saw_fragment
1030 || is_valid_next_header_upper_layer(extension_hdr_context.next_header)
1031 );
1032 let proto = Ipv6Proto::from(extension_hdr_context.next_header);
1033 let body = MaybeParsed::new_with_min_len(
1034 buffer.into_rest(),
1035 payload_len.saturating_sub(extension_hdrs.len()),
1036 );
1037 Ok((body, proto))
1038 }
1039 MaybeParsed::Incomplete(b) => {
1040 let _: &B = b;
1041 Err(ExtHdrParseError)
1042 }
1043 };
1044
1045 Ok(Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto })
1046 }
1047
1048 fn parse_metadata(&self) -> ParseMetadata {
1049 let header_len = Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.len();
1050 let body_len = self.body_proto.as_ref().map(|(b, _p)| b.len()).unwrap_or(0);
1051 ParseMetadata::from_packet(header_len, body_len, 0)
1052 }
1053}
1054
1055impl<B: SplitByteSlice> Ipv6PacketRaw<B> {
1056 pub fn body_proto(&self) -> Result<(MaybeParsed<&[u8], &[u8]>, Ipv6Proto), ExtHdrParseError> {
1076 self.body_proto
1077 .as_ref()
1078 .map(|(mp, proto)| {
1079 (mp.as_ref().map(|b| b.deref()).map_incomplete(|b| b.deref()), *proto)
1080 })
1081 .map_err(|e| *e)
1082 }
1083
1084 pub fn body(&self) -> Result<MaybeParsed<&[u8], &[u8]>, ExtHdrParseError> {
1099 self.body_proto().map(|(body, _proto)| body)
1100 }
1101
1102 pub fn proto(&self) -> Result<Ipv6Proto, ExtHdrParseError> {
1113 self.body_proto().map(|(_body, proto)| proto)
1114 }
1115}
1116
1117impl<B: SplitByteSliceMut> Ipv6PacketRaw<B> {
1118 pub fn set_src_ip(&mut self, addr: Ipv6Addr) {
1120 self.fixed_hdr.src_ip = addr;
1121 }
1122
1123 pub fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1125 self.fixed_hdr.dst_ip = addr;
1126 }
1127
1128 pub fn set_payload_len(&mut self, payload_len: u16) {
1130 self.fixed_hdr.payload_len = U16::new(payload_len);
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 = "exhausted all extension headers without finding fragment 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[usize::from(NEXT_HEADER_OFFSET)] = Ipv6ExtHdrType::DestinationOptions.into();
2748 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2749 assert_eq!(packet.body(), &bytes[IPV6_FIXED_HDR_LEN + IPV6_FRAGMENT_EXT_HDR_LEN..]);
2751
2752 #[rustfmt::skip]
2757 let mut bytes = [
2758 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2760 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2761
2762 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,
2784 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2785
2786 1, 2, 3, 4, 5,
2788 ];
2789 let mut fixed_hdr = new_fixed_hdr();
2790 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2791 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2792 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2793 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2794 let mut buf = &bytes[..];
2795 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2796 let copied_bytes = packet.copy_header_bytes_for_fragment();
2797 let mut expected_bytes = Vec::new();
2798 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2799 expected_bytes[usize::from(NEXT_HEADER_OFFSET)] = Ipv6ExtHdrType::DestinationOptions.into();
2800 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2801 assert_eq!(packet.body(), &bytes[IPV6_FIXED_HDR_LEN + IPV6_FRAGMENT_EXT_HDR_LEN..]);
2803
2804 const HBH_EXT_HDR_LEN: usize = 8;
2809 #[rustfmt::skip]
2810 let mut bytes = [
2811 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2813 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2814
2815 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,
2838 ];
2839 let mut fixed_hdr = new_fixed_hdr();
2840 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2841 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2842 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2843 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2844 let mut buf = &bytes[..];
2845 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2846 let copied_bytes = packet.copy_header_bytes_for_fragment();
2847 let mut expected_bytes = Vec::new();
2848 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN + HBH_EXT_HDR_LEN]);
2849 expected_bytes[IPV6_FIXED_HDR_LEN] = Ipv6ExtHdrType::DestinationOptions.into();
2850 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2851 assert_eq!(
2853 packet.body(),
2854 &bytes[IPV6_FIXED_HDR_LEN + HBH_EXT_HDR_LEN + IPV6_FRAGMENT_EXT_HDR_LEN..]
2855 );
2856
2857 #[rustfmt::skip]
2862 let mut bytes = [
2863 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2865 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2866
2867 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,
2881 ];
2882 let mut fixed_hdr = new_fixed_hdr();
2883 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2884 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2885 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2886 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2887 let mut buf = &bytes[..];
2888 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2889 let copied_bytes = packet.copy_header_bytes_for_fragment();
2890 let mut expected_bytes = Vec::new();
2891 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2892 expected_bytes[usize::from(NEXT_HEADER_OFFSET)] = Ipv6ExtHdrType::Fragment.into();
2893 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2894 assert_eq!(packet.body(), &bytes[IPV6_FIXED_HDR_LEN + IPV6_FRAGMENT_EXT_HDR_LEN..]);
2895
2896 #[rustfmt::skip]
2902 let mut bytes = [
2903 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2905 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2906
2907 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,
2922 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2923
2924 IpProto::Tcp.into(), 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5,
2932 ];
2933 let mut fixed_hdr = new_fixed_hdr();
2934 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2935 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2936 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2937 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2938 let mut buf = &bytes[..];
2939 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2940 let copied_bytes = packet.copy_header_bytes_for_fragment();
2941 let mut expected_bytes = Vec::new();
2942 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN + 48]);
2944 expected_bytes[IPV6_FIXED_HDR_LEN + 8] = IpProto::Tcp.into();
2945 assert_eq!(copied_bytes, expected_bytes);
2946 }
2947
2948 #[test_case(
2949 &[],
2950 &[],
2951 None;
2952 "no_ext_hdrs"
2953 )]
2954 #[test_case(
2955 &[Ipv6ExtHdrType::DestinationOptions],
2956 &[],
2957 Some(Ipv6ExtHdrType::DestinationOptions);
2958 "ignore_dst_options"
2959 )]
2960 #[test_case(
2961 &[
2962 Ipv6ExtHdrType::DestinationOptions,
2963 Ipv6ExtHdrType::Routing,
2964 Ipv6ExtHdrType::DestinationOptions
2965 ],
2966 &[Ipv6ExtHdrType::DestinationOptions, Ipv6ExtHdrType::Routing],
2967 Some(Ipv6ExtHdrType::DestinationOptions);
2968 "include_routing_and_everything_before"
2969 )]
2970 #[test_case(
2971 &[Ipv6ExtHdrType::HopByHopOptions, Ipv6ExtHdrType::DestinationOptions],
2972 &[Ipv6ExtHdrType::HopByHopOptions],
2973 Some(Ipv6ExtHdrType::DestinationOptions);
2974 "include_hop_by_hop_if_first"
2975 )]
2976 #[test_case(
2977 &[
2978 Ipv6ExtHdrType::HopByHopOptions,
2979 Ipv6ExtHdrType::DestinationOptions,
2980 Ipv6ExtHdrType::Routing
2981 ],
2982 &[
2983 Ipv6ExtHdrType::HopByHopOptions,
2984 Ipv6ExtHdrType::DestinationOptions,
2985 Ipv6ExtHdrType::Routing
2986 ],
2987 None;
2988 "routing_header_takes_precedence_over_hop_by_hop"
2989 )]
2990 fn test_per_fragment_header_builder(
2991 original_ext_hdrs: &[Ipv6ExtHdrType],
2992 expected_ext_hdrs: &[Ipv6ExtHdrType],
2993 expected_next_hdr: Option<Ipv6ExtHdrType>,
2994 ) {
2995 #[rustfmt::skip]
2996 fn build_routing_header(nh: u8) -> [u8; 40] {
2997 [
2998 nh, 4, 0, 0, 0, 0, 0, 0,
2999 1, 2, 3, 4, 5, 6, 7, 8,
3000 9, 10, 11, 12, 13, 14, 15, 16,
3001 17, 18, 19, 20, 21, 22, 23, 24,
3002 25, 26, 27, 28, 29, 30, 31, 32
3003 ]
3004 }
3005 fn build_hop_by_hop_header(nh: u8) -> [u8; 8] {
3006 [nh, 0, 0, 1, 0, 1, 1, 0]
3007 }
3008 #[rustfmt::skip]
3009 fn build_destination_options_header(nh: u8) -> [u8; 16] {
3010 [
3011 nh, 1, 0, 1, 0, 1, 1, 0,
3012 1, 6, 0, 0, 0, 0, 0, 0
3013 ]
3014 }
3015 fn build_fragment_header(nh: u8, id: u32) -> [u8; 8] {
3016 let [id1, id2, id3, id4] = id.to_be_bytes();
3017 [nh, 0, 0, 0, id1, id2, id3, id4]
3018 }
3019 fn build_header_bytes(ext_hdrs: &[Ipv6ExtHdrType], final_header: u8) -> Vec<u8> {
3020 let mut fixed_hdr = new_fixed_hdr();
3022 if ext_hdrs.is_empty() {
3023 fixed_hdr.next_hdr = final_header;
3024 } else {
3025 fixed_hdr.next_hdr = u8::from(ext_hdrs[0]);
3026 }
3027
3028 let mut ext_hdr_bytes = Vec::new();
3030 for i in 0..ext_hdrs.len() {
3031 let next_header =
3032 if i + 1 >= ext_hdrs.len() { final_header } else { u8::from(ext_hdrs[i + 1]) };
3033 match ext_hdrs[i] {
3034 Ipv6ExtHdrType::DestinationOptions => ext_hdr_bytes
3035 .extend_from_slice(&build_destination_options_header(next_header)),
3036 Ipv6ExtHdrType::Routing => {
3037 ext_hdr_bytes.extend_from_slice(&build_routing_header(next_header))
3038 }
3039 Ipv6ExtHdrType::HopByHopOptions => {
3040 ext_hdr_bytes.extend_from_slice(&build_hop_by_hop_header(next_header))
3041 }
3042 h => panic!("unexpected header type: {h}"),
3043 }
3044 }
3045
3046 let mut bytes = fixed_hdr_to_bytes(fixed_hdr).to_vec();
3047 bytes.extend_from_slice(&ext_hdr_bytes[..]);
3048 bytes
3049 }
3050
3051 const BODY: [u8; 5] = [1, 2, 3, 4, 5];
3053 let payload_header = u8::from(IpProto::Tcp);
3054 let mut bytes = build_header_bytes(original_ext_hdrs, payload_header);
3055 bytes.extend_from_slice(&BODY);
3056 let len = u16::try_from(bytes.len() - IPV6_FIXED_HDR_LEN).expect("should fit in a u16");
3057 bytes.as_mut_slice()[IPV6_PAYLOAD_LEN_BYTE_RANGE].copy_from_slice(&len.to_be_bytes());
3058 let mut buf = &bytes[..];
3059 let packet = buf.parse::<Ipv6Packet<_>>().expect("parse should succeed");
3060
3061 let serialized = packet
3063 .per_fragment_builder()
3064 .wrap_body(EmptyBuf)
3065 .serialize_vec_outer(&mut NoOpSerializationContext)
3066 .unwrap()
3067 .unwrap_b();
3068 let expected_next_hdr = expected_next_hdr.map(u8::from).unwrap_or(payload_header);
3069 let mut expected_bytes = build_header_bytes(expected_ext_hdrs, expected_next_hdr);
3070 let len =
3071 u16::try_from(expected_bytes.len() - IPV6_FIXED_HDR_LEN).expect("should fit in a u16");
3072 expected_bytes.as_mut_slice()[IPV6_PAYLOAD_LEN_BYTE_RANGE]
3073 .copy_from_slice(&len.to_be_bytes());
3074 assert_eq!(serialized.as_ref(), &expected_bytes[..]);
3075
3076 let builder = packet.per_fragment_builder();
3080 let body = &bytes[builder.header_len()..];
3081 const ID: u32 = 0x12345678;
3082 let frag_builder =
3083 Ipv6PacketBuilderWithFragmentHeader::new(builder, FragmentOffset::ZERO, false, ID);
3084 let serialized = frag_builder
3085 .wrap_body(body.into_serializer())
3086 .serialize_vec_outer(&mut NoOpSerializationContext)
3087 .unwrap()
3088 .unwrap_b();
3089 let mut expected_bytes =
3090 build_header_bytes(expected_ext_hdrs, u8::from(Ipv6ExtHdrType::Fragment));
3091 expected_bytes.extend_from_slice(&build_fragment_header(expected_next_hdr, ID));
3092 expected_bytes.extend_from_slice(body);
3093 let len =
3094 u16::try_from(expected_bytes.len() - IPV6_FIXED_HDR_LEN).expect("should fit in a u16");
3095 expected_bytes.as_mut_slice()[IPV6_PAYLOAD_LEN_BYTE_RANGE]
3096 .copy_from_slice(&len.to_be_bytes());
3097 assert_eq!(serialized.as_ref(), &expected_bytes[..]);
3098 }
3099
3100 #[test]
3101 fn test_next_multiple_of_eight() {
3102 for x in 0usize..=IPV6_HBH_OPTIONS_MAX_LEN {
3103 let y = next_multiple_of_eight(x);
3104 assert_eq!(y % 8, 0);
3105 assert!(y >= x);
3106 if x % 8 == 0 {
3107 assert_eq!(x, y);
3108 } else {
3109 assert_eq!(x + (8 - x % 8), y);
3110 }
3111 }
3112 }
3113
3114 fn create_ipv4_and_ipv6_builders(
3115 proto_v4: Ipv4Proto,
3116 proto_v6: Ipv6Proto,
3117 ) -> (Ipv4PacketBuilder, Ipv6PacketBuilder) {
3118 const IP_DSCP_AND_ECN: DscpAndEcn = DscpAndEcn::new(0x12, 3);
3119 const IP_TTL: u8 = 64;
3120
3121 let mut ipv4_builder =
3122 Ipv4PacketBuilder::new(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP, IP_TTL, proto_v4);
3123 ipv4_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
3124 ipv4_builder.df_flag(false);
3125 ipv4_builder.mf_flag(false);
3126 ipv4_builder.fragment_offset(FragmentOffset::ZERO);
3127
3128 let mut ipv6_builder =
3129 Ipv6PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, IP_TTL, proto_v6);
3130 ipv6_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
3131 ipv6_builder.flowlabel(0x456);
3132
3133 (ipv4_builder, ipv6_builder)
3134 }
3135
3136 fn create_tcp_ipv4_and_ipv6_pkt()
3137 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
3138 use crate::tcp::TcpSegmentBuilder;
3139 use core::num::NonZeroU16;
3140
3141 let tcp_src_port: NonZeroU16 = NonZeroU16::new(20).unwrap();
3142 let tcp_dst_port: NonZeroU16 = NonZeroU16::new(30).unwrap();
3143 const TCP_SEQ_NUM: u32 = 4321;
3144 const TCP_ACK_NUM: Option<u32> = Some(1234);
3145 const TCP_WINDOW_SIZE: u16 = 12345;
3146 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
3147
3148 let (ipv4_builder, ipv6_builder) =
3149 create_ipv4_and_ipv6_builders(IpProto::Tcp.into(), IpProto::Tcp.into());
3150
3151 let tcp_builder = TcpSegmentBuilder::new(
3152 DEFAULT_V4_SRC_IP,
3153 DEFAULT_V4_DST_IP,
3154 tcp_src_port,
3155 tcp_dst_port,
3156 TCP_SEQ_NUM,
3157 TCP_ACK_NUM,
3158 TCP_WINDOW_SIZE,
3159 );
3160
3161 let v4_pkt_buf = (&PAYLOAD)
3162 .into_serializer()
3163 .wrap_in(tcp_builder)
3164 .wrap_in(ipv4_builder)
3165 .serialize_vec_outer(&mut NoOpSerializationContext)
3166 .expect("Failed to serialize to v4_pkt_buf");
3167
3168 let v6_tcp_builder = TcpSegmentBuilder::new(
3169 DEFAULT_SRC_IP,
3170 DEFAULT_DST_IP,
3171 tcp_src_port,
3172 tcp_dst_port,
3173 TCP_SEQ_NUM,
3174 TCP_ACK_NUM,
3175 TCP_WINDOW_SIZE,
3176 );
3177
3178 let v6_pkt_buf = (&PAYLOAD)
3179 .into_serializer()
3180 .wrap_in(v6_tcp_builder)
3181 .wrap_in(ipv6_builder)
3182 .serialize_vec_outer(&mut NoOpSerializationContext)
3183 .expect("Failed to serialize to v4_pkt_buf");
3184
3185 (v4_pkt_buf, v6_pkt_buf)
3186 }
3187
3188 #[test]
3189 fn test_nat64_translate_tcp() {
3190 let (expected_v4_pkt_buf, mut v6_pkt_buf) = create_tcp_ipv4_and_ipv6_pkt();
3191
3192 let parsed_v6_packet =
3193 v6_pkt_buf.parse::<Ipv6Packet<_>>().expect("Failed to parse v6_pkt_buf");
3194 let nat64_translation_result =
3195 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
3196
3197 let serializable_pkt =
3198 assert_matches!(nat64_translation_result, Nat64TranslationResult::Forward(s) => s);
3199
3200 let translated_v4_pkt_buf = serializable_pkt
3201 .serialize_vec_outer(&mut NoOpSerializationContext)
3202 .expect("Failed to serialize to translated_v4_pkt_buf");
3203
3204 assert_eq!(
3205 expected_v4_pkt_buf.to_flattened_vec(),
3206 translated_v4_pkt_buf.to_flattened_vec()
3207 );
3208 }
3209
3210 fn create_udp_ipv4_and_ipv6_pkt()
3211 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
3212 use crate::udp::UdpPacketBuilder;
3213 use core::num::NonZeroU16;
3214
3215 let udp_src_port: NonZeroU16 = NonZeroU16::new(35000).unwrap();
3216 let udp_dst_port: NonZeroU16 = NonZeroU16::new(53).unwrap();
3217 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
3218
3219 let (ipv4_builder, ipv6_builder) =
3220 create_ipv4_and_ipv6_builders(IpProto::Udp.into(), IpProto::Udp.into());
3221
3222 let v4_udp_builder = UdpPacketBuilder::new(
3223 DEFAULT_V4_SRC_IP,
3224 DEFAULT_V4_DST_IP,
3225 Some(udp_src_port),
3226 udp_dst_port,
3227 );
3228
3229 let v4_pkt_buf = (&PAYLOAD)
3230 .into_serializer()
3231 .wrap_in(v4_udp_builder)
3232 .wrap_in(ipv4_builder)
3233 .serialize_vec_outer(&mut NoOpSerializationContext)
3234 .expect("Unable to serialize to v4_pkt_buf");
3235
3236 let v6_udp_builder =
3237 UdpPacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, Some(udp_src_port), udp_dst_port);
3238
3239 let v6_pkt_buf = (&PAYLOAD)
3240 .into_serializer()
3241 .wrap_in(v6_udp_builder)
3242 .wrap_in(ipv6_builder)
3243 .serialize_vec_outer(&mut NoOpSerializationContext)
3244 .expect("Unable to serialize to v6_pkt_buf");
3245
3246 (v4_pkt_buf, v6_pkt_buf)
3247 }
3248
3249 #[test]
3250 fn test_nat64_translate_udp() {
3251 let (expected_v4_pkt_buf, mut v6_pkt_buf) = create_udp_ipv4_and_ipv6_pkt();
3252
3253 let parsed_v6_packet =
3254 v6_pkt_buf.parse::<Ipv6Packet<_>>().expect("Unable to parse Ipv6Packet");
3255 let nat64_translation_result =
3256 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
3257
3258 let serializable_pkt = assert_matches!(nat64_translation_result,
3259 Nat64TranslationResult::Forward(s) => s);
3260
3261 let translated_v4_pkt_buf = serializable_pkt
3262 .serialize_vec_outer(&mut NoOpSerializationContext)
3263 .expect("Unable to serialize to translated_v4_pkt_buf");
3264
3265 assert_eq!(
3266 expected_v4_pkt_buf.to_flattened_vec(),
3267 translated_v4_pkt_buf.to_flattened_vec()
3268 );
3269 }
3270
3271 #[test]
3272 fn test_nat64_translate_non_tcp_udp_icmp() {
3273 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
3274
3275 let (ipv4_builder, ipv6_builder) =
3276 create_ipv4_and_ipv6_builders(Ipv4Proto::Other(59), Ipv6Proto::Other(59));
3277
3278 let expected_v4_pkt_buf = (&PAYLOAD)
3279 .into_serializer()
3280 .wrap_in(ipv4_builder)
3281 .serialize_vec_outer(&mut NoOpSerializationContext)
3282 .expect("Unable to serialize to expected_v4_pkt_buf");
3283
3284 let mut v6_pkt_buf = (&PAYLOAD)
3285 .into_serializer()
3286 .wrap_in(ipv6_builder)
3287 .serialize_vec_outer(&mut NoOpSerializationContext)
3288 .expect("Unable to serialize to v6_pkt_buf");
3289
3290 let translated_v4_pkt_buf = {
3291 let parsed_v6_packet = v6_pkt_buf
3292 .parse::<Ipv6Packet<_>>()
3293 .expect("Unable to serialize to translated_v4_pkt_buf");
3294
3295 let nat64_translation_result =
3296 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
3297
3298 let serializable_pkt = assert_matches!(nat64_translation_result,
3299 Nat64TranslationResult::Forward(s) => s);
3300
3301 let translated_buf = serializable_pkt
3302 .serialize_vec_outer(&mut NoOpSerializationContext)
3303 .expect("Unable to serialize to translated_buf");
3304
3305 translated_buf
3306 };
3307
3308 assert_eq!(
3309 expected_v4_pkt_buf.to_flattened_vec(),
3310 translated_v4_pkt_buf.to_flattened_vec()
3311 );
3312 }
3313
3314 #[test_case(new_builder(), true; "fixed header more frags")]
3315 #[test_case(Ipv6PacketBuilderWithHbhOptions::new(
3316 new_builder(),
3317 &[HopByHopOption {
3318 action: ExtensionHeaderOptionAction::SkipAndContinue,
3319 mutable: false,
3320 data: HopByHopOptionData::RouterAlert { data: 0 },
3321 }]).unwrap(), false; "hbh last frag")]
3322 fn ipv6_packet_builder_with_fragment_header<
3323 B: Ipv6HeaderBuilder + Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>> + Debug,
3324 >(
3325 inner: B,
3326 more_fragments: bool,
3327 ) {
3328 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
3329 let fragment_offset = FragmentOffset::new(13).unwrap();
3330 let identification = 0xABCDABCD;
3331 let builder = Ipv6PacketBuilderWithFragmentHeader::new(
3332 inner,
3333 fragment_offset,
3334 more_fragments,
3335 identification,
3336 );
3337 let mut serialized = builder
3338 .wrap_body(PAYLOAD.into_serializer())
3339 .serialize_vec_outer(&mut NoOpSerializationContext)
3340 .unwrap()
3341 .unwrap_b();
3342 let packet = serialized.parse::<Ipv6Packet<_>>().unwrap();
3343 assert!(packet.fragment_header_present());
3344 assert_eq!(packet.proto(), Ipv6Proto::Proto(IpProto::Tcp));
3345 let fragment_data = packet
3346 .extension_hdrs
3347 .into_iter()
3348 .find_map(|ext_hdr| match ext_hdr {
3349 Ipv6ExtensionHeader::Fragment { fragment_data } => Some(fragment_data),
3350 _ => None,
3351 })
3352 .unwrap();
3353 assert_eq!(fragment_data.fragment_offset(), fragment_offset);
3354 assert_eq!(fragment_data.identification(), identification);
3355 assert_eq!(fragment_data.m_flag(), more_fragments);
3356 }
3357
3358 #[test]
3361 fn extension_headers_take_from_max_body_size() {
3362 let builder = new_builder();
3363 assert_eq!(builder.constraints().max_body_len(), IPV6_MAX_PAYLOAD_LENGTH);
3364 let builder =
3365 Ipv6PacketBuilderWithFragmentHeader::new(builder, FragmentOffset::ZERO, false, 1234);
3366 assert_eq!(
3367 builder.constraints().max_body_len(),
3368 IPV6_MAX_PAYLOAD_LENGTH - IPV6_FRAGMENT_EXT_HDR_LEN
3369 );
3370 }
3371
3372 #[test]
3373 fn test_partial_serialize_parsed() {
3374 const PACKET_BYTES: &[u8] = &[
3375 100, 177, 4, 5, 0, 10, 6, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
3376 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, 1, 2, 3, 4, 5, 6, 7,
3377 8, 9,
3378 ];
3379 const PACKET_LEN: usize = PACKET_BYTES.len();
3380 let mut packet_bytes_copy = Vec::from(PACKET_BYTES);
3381 let mut packet_bytes_ref: &mut [u8] = &mut packet_bytes_copy[..];
3382 let packet = packet_bytes_ref.parse::<Ipv6Packet<_>>().unwrap();
3383
3384 let buf = assert_matches!(
3385 packet.partial_serialize(&mut NoOpSerializationContext, packet::new_buf_vec),
3386 Ok(PartialSerializeResult::NewBuffer { buffer, total_size: PACKET_LEN }) => buffer
3387 );
3388 assert_eq!(buf.as_ref(), PACKET_BYTES);
3389 }
3390
3391 #[test]
3392 fn test_fragmented_packet_with_destination_options_reassembly() {
3393 const ID: u32 = 12345;
3394 let tcp_payload_part0 = [1u8, 2, 3, 4, 5, 6, 7, 8];
3395 let tcp_payload_part1 =
3398 [Ipv6ExtHdrType::DestinationOptions.into(), 0, 0, 0, 0, 0, 0, 0, 99, 100];
3399
3400 let builder_0 = Ipv6PacketBuilder::new(
3404 DEFAULT_SRC_IP,
3405 DEFAULT_DST_IP,
3406 64,
3407 Ipv6Proto::Other(Ipv6ExtHdrType::DestinationOptions.into()),
3408 );
3409 let builder_0 = Ipv6PacketBuilderWithFragmentHeader::new(
3410 builder_0,
3411 FragmentOffset::ZERO,
3412 true,
3413 ID,
3414 );
3415 let body_0: Vec<u8> = [IpProto::Tcp.into(), 0, 0, 0, 0, 0, 0, 0]
3418 .into_iter()
3419 .chain(tcp_payload_part0)
3420 .collect();
3421
3422 let mut buf_0 = (&body_0[..])
3423 .into_serializer()
3424 .wrap_in(builder_0)
3425 .serialize_vec_outer(&mut NoOpSerializationContext)
3426 .unwrap();
3427 let packet_0 = buf_0.parse::<Ipv6Packet<_>>().unwrap();
3428
3429 assert_matches!(
3431 &packet_0.iter_extension_hdrs().collect::<Vec<_>>()[..],
3432 [Ipv6ExtensionHeader::Fragment { .. }]
3433 );
3434 assert_eq!(packet_0.proto(), Ipv6Proto::Other(Ipv6ExtHdrType::DestinationOptions.into()));
3436
3437 assert_eq!(packet_0.body(), &body_0[..]);
3439
3440 let header = packet_0.copy_header_bytes_for_fragment();
3442 assert_eq!(header.len(), IPV6_FIXED_HDR_LEN);
3443 assert_eq!(
3444 header[usize::from(NEXT_HEADER_OFFSET)],
3445 Ipv6ExtHdrType::DestinationOptions.into()
3446 );
3447
3448 let builder_1 =
3452 Ipv6PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, 64, IpProto::Tcp.into());
3453 let builder_1 = Ipv6PacketBuilderWithFragmentHeader::new(
3454 builder_1,
3455 FragmentOffset::new(2).unwrap(),
3456 false,
3457 ID,
3458 );
3459 let body_1 = tcp_payload_part1.to_vec();
3460
3461 let mut buf_1 = (&body_1[..])
3462 .into_serializer()
3463 .wrap_in(builder_1)
3464 .serialize_vec_outer(&mut NoOpSerializationContext)
3465 .unwrap();
3466 let packet_1 = buf_1.parse::<Ipv6Packet<_>>().unwrap();
3467
3468 assert_matches!(
3470 &packet_1.iter_extension_hdrs().collect::<Vec<_>>()[..],
3471 [Ipv6ExtensionHeader::Fragment { .. }]
3472 );
3473 assert_eq!(packet_1.body(), &body_1[..]);
3475
3476 let mut reassembled_buf =
3478 vec![0u8; header.len() + packet_0.body().len() + packet_1.body().len()];
3479 let mut reassembled_slice = &mut reassembled_buf[..];
3480 reassemble_fragmented_packet(
3481 &mut reassembled_slice,
3482 &header,
3483 [packet_0.body(), packet_1.body()].into_iter(),
3484 )
3485 .unwrap();
3486
3487 let mut reassembled_ref = &reassembled_buf[..];
3488 let reassembled_packet = reassembled_ref.parse::<Ipv6Packet<_>>().unwrap();
3489
3490 assert_matches!(
3491 &reassembled_packet.iter_extension_hdrs().collect::<Vec<_>>()[..],
3492 [Ipv6ExtensionHeader::DestinationOptions { .. }]
3493 );
3494 assert_eq!(reassembled_packet.proto(), IpProto::Tcp.into());
3495 let expected_reassembled_body: Vec<u8> =
3496 tcp_payload_part0.into_iter().chain(tcp_payload_part1).collect();
3497 assert_eq!(reassembled_packet.body(), &expected_reassembled_body[..]);
3498 }
3499}