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 BufferAlloc, BufferProvider, BufferView, BufferViewMut, EmptyBuf, FragmentedBytesMut, FromRaw,
23 GrowBufferMut, InnerPacketBuilder, MaybeParsed, PacketBuilder, PacketConstraints,
24 ParsablePacket, ParseMetadata, ReusableBuffer, SerializeError, SerializeTarget, Serializer,
25};
26use zerocopy::byteorder::network_endian::{U16, U32};
27use zerocopy::{
28 FromBytes, Immutable, IntoBytes, KnownLayout, Ref, SplitByteSlice, SplitByteSliceMut, Unaligned,
29};
30
31use crate::error::{IpParseError, IpParseErrorAction, IpParseResult, ParseError};
32use crate::icmp::Icmpv6ParameterProblemCode;
33use crate::ip::{
34 DscpAndEcn, FragmentOffset, IpExt, IpPacketBuilder, IpProto, Ipv4Proto, Ipv6ExtHdrType,
35 Ipv6Proto, Nat64Error, Nat64TranslationResult,
36};
37use crate::ipv4::{Ipv4PacketBuilder, HDR_PREFIX_LEN};
38use crate::tcp::{TcpParseArgs, TcpSegment};
39use crate::udp::{UdpPacket, UdpParseArgs};
40
41use ext_hdrs::{
42 is_valid_next_header, is_valid_next_header_upper_layer, ExtensionHeaderOptionAction,
43 HopByHopOption, HopByHopOptionData, Ipv6ExtensionHeader, Ipv6ExtensionHeaderData,
44 Ipv6ExtensionHeaderImpl, Ipv6ExtensionHeaderParsingContext, Ipv6ExtensionHeaderParsingError,
45 IPV6_FRAGMENT_EXT_HDR_LEN,
46};
47
48pub const IPV6_FIXED_HDR_LEN: usize = 40;
50
51pub const IPV6_PAYLOAD_LEN_BYTE_RANGE: Range<usize> = 4..6;
54
55const NEXT_HEADER_OFFSET: u8 = 6;
57
58const IPV6_HBH_OPTIONS_MAX_LEN: usize = (core::u8::MAX as usize) * 8 + 8;
62
63const IPV6_MAX_PAYLOAD_LENGTH: usize = core::u16::MAX as usize;
70
71fn ext_hdr_err_fn(hdr: &FixedHeader, err: Ipv6ExtensionHeaderParsingError) -> IpParseError<Ipv6> {
74 match err {
93 Ipv6ExtensionHeaderParsingError::ErroneousHeaderField {
94 pointer,
95 must_send_icmp,
96 header_len: _,
97 } => {
98 let (pointer, action) = match pointer.checked_add(IPV6_FIXED_HDR_LEN as u32) {
99 None => (0, IpParseErrorAction::DiscardPacket),
103 Some(p) => (p, IpParseErrorAction::DiscardPacketSendIcmpNoMulticast),
107 };
108
109 IpParseError::ParameterProblem {
110 src_ip: hdr.src_ip,
111 dst_ip: hdr.dst_ip,
112 code: Icmpv6ParameterProblemCode::ErroneousHeaderField,
113 pointer,
114 must_send_icmp,
115 header_len: (),
116 action,
117 }
118 }
119 Ipv6ExtensionHeaderParsingError::UnrecognizedNextHeader {
120 pointer,
121 must_send_icmp,
122 header_len: _,
123 } => {
124 let (pointer, action) = match pointer.checked_add(IPV6_FIXED_HDR_LEN as u32) {
125 None => (0, IpParseErrorAction::DiscardPacket),
126 Some(p) => (p, IpParseErrorAction::DiscardPacketSendIcmpNoMulticast),
127 };
128
129 IpParseError::ParameterProblem {
130 src_ip: hdr.src_ip,
131 dst_ip: hdr.dst_ip,
132 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
133 pointer,
134 must_send_icmp,
135 header_len: (),
136 action,
137 }
138 }
139 Ipv6ExtensionHeaderParsingError::UnrecognizedOption {
140 pointer,
141 must_send_icmp,
142 header_len: _,
143 action,
144 } => {
145 let (pointer, action) = match pointer.checked_add(IPV6_FIXED_HDR_LEN as u32) {
146 None => (0, IpParseErrorAction::DiscardPacket),
147 Some(p) => {
148 let action = match action {
149 ExtensionHeaderOptionAction::SkipAndContinue => unreachable!(
150 "Should never end up here because this action should never result in an error"
151 ),
152 ExtensionHeaderOptionAction::DiscardPacket => IpParseErrorAction::DiscardPacket,
153 ExtensionHeaderOptionAction::DiscardPacketSendIcmp => {
154 IpParseErrorAction::DiscardPacketSendIcmp
155 }
156 ExtensionHeaderOptionAction::DiscardPacketSendIcmpNoMulticast => {
157 IpParseErrorAction::DiscardPacketSendIcmpNoMulticast
158 }
159 };
160
161 (p, action)
162 }
163 };
164
165 IpParseError::ParameterProblem {
166 src_ip: hdr.src_ip,
167 dst_ip: hdr.dst_ip,
168 code: Icmpv6ParameterProblemCode::UnrecognizedIpv6Option,
169 pointer,
170 must_send_icmp,
171 header_len: (),
172 action,
173 }
174 }
175 Ipv6ExtensionHeaderParsingError::BufferExhausted
176 | Ipv6ExtensionHeaderParsingError::MalformedData => {
177 IpParseError::Parse { error: ParseError::Format }
180 }
181 }
182}
183
184#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
186#[repr(C)]
187pub struct FixedHeader {
188 version_tc_flowlabel: [u8; 4],
189 payload_len: U16,
190 next_hdr: u8,
191 hop_limit: u8,
192 src_ip: Ipv6Addr,
193 dst_ip: Ipv6Addr,
194}
195
196const IP_VERSION: u8 = 6;
197const VERSION_OFFSET: u8 = 4;
198const FLOW_LABEL_MAX: u32 = (1 << 20) - 1;
199
200impl FixedHeader {
201 #[allow(clippy::too_many_arguments)]
202 fn new(
203 dscp_and_ecn: DscpAndEcn,
204 flow_label: u32,
205 payload_len: u16,
206 next_hdr: u8,
207 hop_limit: u8,
208 src_ip: Ipv6Addr,
209 dst_ip: Ipv6Addr,
210 ) -> FixedHeader {
211 debug_assert!(flow_label <= FLOW_LABEL_MAX);
212
213 let traffic_class = dscp_and_ecn.raw();
214 FixedHeader {
215 version_tc_flowlabel: [
216 IP_VERSION << VERSION_OFFSET | traffic_class >> 4,
217 (traffic_class << 4) | ((flow_label >> 16) as u8),
218 (flow_label >> 8) as u8,
219 flow_label as u8,
220 ],
221 payload_len: U16::new(payload_len),
222 next_hdr,
223 hop_limit,
224 src_ip,
225 dst_ip,
226 }
227 }
228
229 fn version(&self) -> u8 {
230 self.version_tc_flowlabel[0] >> 4
231 }
232
233 fn dscp_and_ecn(&self) -> DscpAndEcn {
234 ((self.version_tc_flowlabel[0] & 0xF) << 4 | self.version_tc_flowlabel[1] >> 4).into()
235 }
236
237 fn flowlabel(&self) -> u32 {
238 (u32::from(self.version_tc_flowlabel[1]) & 0xF) << 16
239 | u32::from(self.version_tc_flowlabel[2]) << 8
240 | u32::from(self.version_tc_flowlabel[3])
241 }
242}
243
244pub trait Ipv6Header {
249 fn get_fixed_header(&self) -> &FixedHeader;
251
252 fn hop_limit(&self) -> u8 {
254 self.get_fixed_header().hop_limit
255 }
256
257 fn next_header(&self) -> u8 {
259 self.get_fixed_header().next_hdr
260 }
261
262 fn src_ip(&self) -> Ipv6Addr {
264 self.get_fixed_header().src_ip
265 }
266
267 fn dst_ip(&self) -> Ipv6Addr {
269 self.get_fixed_header().dst_ip
270 }
271
272 fn dscp_and_ecn(&self) -> DscpAndEcn {
275 self.get_fixed_header().dscp_and_ecn()
276 }
277}
278
279impl Ipv6Header for FixedHeader {
280 fn get_fixed_header(&self) -> &FixedHeader {
281 self
282 }
283}
284
285pub struct Ipv6Packet<B> {
291 fixed_hdr: Ref<B, FixedHeader>,
292 extension_hdrs: Records<B, Ipv6ExtensionHeaderImpl>,
293 body: B,
294 proto: Ipv6Proto,
295}
296
297impl<B: SplitByteSlice, I: IpExt> GenericOverIp<I> for Ipv6Packet<B> {
298 type Type = <I as IpExt>::Packet<B>;
299}
300
301impl<B: SplitByteSlice> Ipv6Header for Ipv6Packet<B> {
302 fn get_fixed_header(&self) -> &FixedHeader {
303 &self.fixed_hdr
304 }
305}
306
307impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv6Packet<B> {
308 type Error = IpParseError<Ipv6>;
309
310 fn parse_metadata(&self) -> ParseMetadata {
311 let header_len = Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.bytes().len();
312 ParseMetadata::from_packet(header_len, self.body.len(), 0)
313 }
314
315 fn parse<BV: BufferView<B>>(buffer: BV, _args: ()) -> IpParseResult<Ipv6, Self> {
316 Ipv6PacketRaw::parse(buffer, ()).and_then(Ipv6Packet::try_from_raw)
317 }
318}
319
320impl<B: SplitByteSlice> FromRaw<Ipv6PacketRaw<B>, ()> for Ipv6Packet<B> {
321 type Error = IpParseError<Ipv6>;
322
323 fn try_from_raw_with(raw: Ipv6PacketRaw<B>, _args: ()) -> Result<Self, Self::Error> {
324 let fixed_hdr = raw.fixed_hdr;
325
326 if !is_valid_next_header(fixed_hdr.next_hdr, true) {
329 return debug_err!(
330 Err(IpParseError::ParameterProblem {
331 src_ip: fixed_hdr.src_ip,
332 dst_ip: fixed_hdr.dst_ip,
333 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
334 pointer: u32::from(NEXT_HEADER_OFFSET),
335 must_send_icmp: false,
336 header_len: (),
337 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
338 }),
339 "Unrecognized next header value"
340 );
341 }
342
343 let extension_hdrs = match raw.extension_hdrs {
344 MaybeParsed::Complete(v) => {
345 Records::try_from_raw(v).map_err(|e| ext_hdr_err_fn(&fixed_hdr, e))?
346 }
347 MaybeParsed::Incomplete(_) => {
348 return debug_err!(
349 Err(ParseError::Format.into()),
350 "Incomplete IPv6 extension headers"
351 );
352 }
353 };
354
355 let (body, proto) =
359 raw.body_proto.expect("Unable to retrieve Ipv6Proto or MaybeParsed body from raw");
360 debug_assert!(is_valid_next_header_upper_layer(proto.into()));
361
362 let body = match body {
363 MaybeParsed::Complete(b) => b,
364 MaybeParsed::Incomplete(_b) => {
365 return debug_err!(Err(ParseError::Format.into()), "IPv6 body unretrievable.");
366 }
367 };
368
369 if extension_hdrs.bytes().len() + body.len() != usize::from(fixed_hdr.payload_len.get()) {
374 return debug_err!(
375 Err(ParseError::Format.into()),
376 "Payload len does not match body and extension headers"
377 );
378 }
379
380 if fixed_hdr.version() != 6 {
382 return debug_err!(
383 Err(ParseError::Format.into()),
384 "unexpected IP version: {}",
385 fixed_hdr.version()
386 );
387 }
388
389 Ok(Ipv6Packet { fixed_hdr, extension_hdrs, body, proto })
390 }
391}
392
393impl<B: SplitByteSlice> Ipv6Packet<B> {
394 pub fn iter_extension_hdrs(&self) -> impl Iterator<Item = Ipv6ExtensionHeader<'_>> {
396 self.extension_hdrs.iter()
397 }
398
399 pub fn body(&self) -> &[u8] {
401 &self.body
402 }
403
404 pub fn dscp_and_ecn(&self) -> DscpAndEcn {
407 self.fixed_hdr.dscp_and_ecn()
408 }
409
410 pub fn flowlabel(&self) -> u32 {
412 self.fixed_hdr.flowlabel()
413 }
414
415 pub fn proto(&self) -> Ipv6Proto {
421 self.proto
422 }
423
424 pub fn src_ipv6(&self) -> Option<Ipv6SourceAddr> {
431 Ipv6SourceAddr::new(self.fixed_hdr.src_ip)
432 }
433
434 pub fn copy_header_bytes_for_fragment(&self) -> Vec<u8> {
445 let expected_bytes_len = self.header_len() - IPV6_FRAGMENT_EXT_HDR_LEN;
448 let mut bytes = Vec::with_capacity(expected_bytes_len);
449
450 bytes.extend_from_slice(Ref::bytes(&self.fixed_hdr));
451
452 let mut iter = self.extension_hdrs.iter();
456
457 let ext_hdr = iter.next().expect("packet must have at least one extension header");
461
462 if self.fixed_hdr.next_hdr == Ipv6ExtHdrType::Fragment.into() {
463 bytes[6] = ext_hdr.next_header;
469
470 bytes.extend_from_slice(&self.extension_hdrs.bytes()[IPV6_FRAGMENT_EXT_HDR_LEN..]);
472 } else {
473 let mut ext_hdr = ext_hdr;
474 let mut ext_hdr_start = 0;
475 let mut ext_hdr_end = iter.context().bytes_parsed;
476
477 loop {
483 let next_ext_hdr = iter
489 .next()
490 .expect("exhausted all extension headers without finding fragment header");
491
492 if let Ipv6ExtensionHeaderData::Fragment { .. } = next_ext_hdr.data() {
493 let fragment_hdr_end = ext_hdr_end + IPV6_FRAGMENT_EXT_HDR_LEN;
500 assert_eq!(fragment_hdr_end, iter.context().bytes_parsed);
501
502 let extension_hdr_bytes = self.extension_hdrs.bytes();
503
504 bytes.extend_from_slice(&extension_hdr_bytes[..ext_hdr_end]);
506
507 bytes.extend_from_slice(&extension_hdr_bytes[fragment_hdr_end..]);
509
510 match ext_hdr.data() {
513 Ipv6ExtensionHeaderData::HopByHopOptions { .. }
516 | Ipv6ExtensionHeaderData::DestinationOptions { .. } => {
517 bytes[IPV6_FIXED_HDR_LEN+ext_hdr_start] = next_ext_hdr.next_header;
518 }
519 Ipv6ExtensionHeaderData::Fragment { .. } => unreachable!("If we had a fragment header before `ext_hdr`, we should have used that instead"),
520 }
521
522 break;
523 }
524
525 ext_hdr = next_ext_hdr;
526 ext_hdr_start = ext_hdr_end;
527 ext_hdr_end = iter.context().bytes_parsed;
528 }
529 }
530
531 assert_eq!(bytes.len(), expected_bytes_len);
533 bytes
534 }
535
536 fn header_len(&self) -> usize {
537 Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.bytes().len()
538 }
539
540 fn fragment_header_present(&self) -> bool {
541 for ext_hdr in self.extension_hdrs.iter() {
542 if matches!(ext_hdr.data(), Ipv6ExtensionHeaderData::Fragment { .. }) {
543 return true;
544 }
545 }
546 false
547 }
548
549 pub fn builder(&self) -> Ipv6PacketBuilder {
551 Ipv6PacketBuilder {
552 dscp_and_ecn: self.dscp_and_ecn(),
553 flowlabel: self.flowlabel(),
554 hop_limit: self.hop_limit(),
555 proto: self.proto(),
556 src_ip: self.src_ip(),
557 dst_ip: self.dst_ip(),
558 }
559 }
560
561 pub fn nat64_translate(
587 &self,
588 v4_src_addr: Ipv4Addr,
589 v4_dst_addr: Ipv4Addr,
590 ) -> Nat64TranslationResult<impl Serializer<Buffer = EmptyBuf> + Debug + '_, Nat64Error> {
591 #[derive(Debug)]
594 enum Nat64Serializer<T, U, O> {
595 Tcp(T),
596 Udp(U),
597 Other(O),
598 }
599
600 impl<T, U, O> Serializer for Nat64Serializer<T, U, O>
601 where
602 T: Serializer<Buffer = EmptyBuf>,
603 U: Serializer<Buffer = EmptyBuf>,
604 O: Serializer<Buffer = EmptyBuf>,
605 {
606 type Buffer = EmptyBuf;
607 fn serialize<B, P>(
608 self,
609 outer: PacketConstraints,
610 provider: P,
611 ) -> Result<B, (SerializeError<P::Error>, Self)>
612 where
613 B: GrowBufferMut,
614 P: BufferProvider<Self::Buffer, B>,
615 {
616 match self {
617 Nat64Serializer::Tcp(serializer) => serializer
618 .serialize(outer, provider)
619 .map_err(|(err, ser)| (err, Nat64Serializer::Tcp(ser))),
620 Nat64Serializer::Udp(serializer) => serializer
621 .serialize(outer, provider)
622 .map_err(|(err, ser)| (err, Nat64Serializer::Udp(ser))),
623 Nat64Serializer::Other(serializer) => serializer
624 .serialize(outer, provider)
625 .map_err(|(err, ser)| (err, Nat64Serializer::Other(ser))),
626 }
627 }
628
629 fn serialize_new_buf<B: ReusableBuffer, A: BufferAlloc<B>>(
630 &self,
631 outer: PacketConstraints,
632 alloc: A,
633 ) -> Result<B, SerializeError<A::Error>> {
634 match self {
635 Nat64Serializer::Tcp(serializer) => serializer.serialize_new_buf(outer, alloc),
636 Nat64Serializer::Udp(serializer) => serializer.serialize_new_buf(outer, alloc),
637 Nat64Serializer::Other(serializer) => {
638 serializer.serialize_new_buf(outer, alloc)
639 }
640 }
641 }
642 }
643
644 if self.fragment_header_present() {
647 return Nat64TranslationResult::Err(Nat64Error::NotImplemented);
648 }
649
650 let v4_builder = |v4_proto| {
651 let mut builder =
652 Ipv4PacketBuilder::new(v4_src_addr, v4_dst_addr, self.hop_limit(), v4_proto);
653 builder.dscp_and_ecn(self.dscp_and_ecn());
654
655 const IPV4_HEADER_LEN_BYTES: usize = HDR_PREFIX_LEN;
660
661 builder.df_flag(self.body().len() + IPV4_HEADER_LEN_BYTES > 1260);
667
668 builder.fragment_offset(FragmentOffset::ZERO);
671 builder.mf_flag(false);
672
673 builder
674 };
675
676 match self.proto() {
677 Ipv6Proto::Proto(IpProto::Tcp) => {
678 let v4_pkt_builder = v4_builder(Ipv4Proto::Proto(IpProto::Tcp));
679 let args = TcpParseArgs::new(self.src_ip(), self.dst_ip());
680 match TcpSegment::parse(&mut self.body.as_bytes(), args) {
685 Ok(tcp) => {
686 let tcp_serializer =
690 Nat64Serializer::Tcp(tcp.into_serializer(v4_src_addr, v4_dst_addr));
691 Nat64TranslationResult::Forward(tcp_serializer.encapsulate(v4_pkt_builder))
692 }
693 Err(msg) => {
694 debug!("Parsing of TCP segment failed: {:?}", msg);
695
696 let common_serializer =
705 Nat64Serializer::Other(self.body().into_serializer());
706 Nat64TranslationResult::Forward(
707 common_serializer.encapsulate(v4_pkt_builder),
708 )
709 }
710 }
711 }
712
713 Ipv6Proto::Proto(IpProto::Udp) => {
718 let v4_pkt_builder = v4_builder(Ipv4Proto::Proto(IpProto::Udp));
719 let args = UdpParseArgs::new(self.src_ip(), self.dst_ip());
720 match UdpPacket::parse(&mut self.body.as_bytes(), args) {
721 Ok(udp) => {
722 let udp_serializer =
726 Nat64Serializer::Udp(udp.into_serializer(v4_src_addr, v4_dst_addr));
727 Nat64TranslationResult::Forward(udp_serializer.encapsulate(v4_pkt_builder))
728 }
729 Err(msg) => {
730 debug!("Parsing of UDP packet failed: {:?}", msg);
731
732 let common_serializer =
742 Nat64Serializer::Other(self.body().into_serializer());
743 Nat64TranslationResult::Forward(
744 common_serializer.encapsulate(v4_pkt_builder),
745 )
746 }
747 }
748 }
749
750 Ipv6Proto::Icmpv6 => Nat64TranslationResult::Err(Nat64Error::NotImplemented),
753
754 Ipv6Proto::Other(val) => {
774 let v4_pkt_builder = v4_builder(Ipv4Proto::Other(val));
775 let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
776 Nat64TranslationResult::Forward(common_serializer.encapsulate(v4_pkt_builder))
777 }
778
779 Ipv6Proto::NoNextHeader => {
780 let v4_pkt_builder = v4_builder(Ipv4Proto::Other(Ipv6Proto::NoNextHeader.into()));
781 let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
782 Nat64TranslationResult::Forward(common_serializer.encapsulate(v4_pkt_builder))
783 }
784
785 Ipv6Proto::Proto(IpProto::Reserved) => Nat64TranslationResult::Drop,
788 }
789 }
790
791 pub fn to_vec(&self) -> Vec<u8> {
793 let Ipv6Packet { fixed_hdr, extension_hdrs, body, proto: _ } = self;
794 let mut buf = Vec::with_capacity(
795 Ref::bytes(&fixed_hdr).len() + extension_hdrs.bytes().len() + body.as_bytes().len(),
796 );
797 buf.extend(Ref::bytes(&fixed_hdr));
798 buf.extend(extension_hdrs.bytes());
799 buf.extend(body.as_bytes());
800 buf
801 }
802}
803
804impl<B: SplitByteSliceMut> Ipv6Packet<B> {
805 pub fn set_src_ip(&mut self, addr: Ipv6Addr) {
807 self.fixed_hdr.src_ip = addr;
808 }
809
810 pub fn set_dst_ip(&mut self, addr: Ipv6Addr) {
812 self.fixed_hdr.dst_ip = addr;
813 }
814
815 pub fn set_hop_limit(&mut self, hlim: u8) {
817 self.fixed_hdr.hop_limit = hlim;
818 }
819
820 pub fn body_mut(&mut self) -> &mut [u8] {
822 &mut self.body
823 }
824
825 pub fn parts_with_body_mut(&mut self) -> (&FixedHeader, ExtensionHeaders<'_>, &mut [u8]) {
828 (&self.fixed_hdr, ExtensionHeaders(self.extension_hdrs.as_ref()), &mut self.body)
829 }
830}
831
832impl<B: SplitByteSlice> Debug for Ipv6Packet<B> {
833 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
834 f.debug_struct("Ipv6Packet")
835 .field("src_ip", &self.src_ip())
836 .field("dst_ip", &self.dst_ip())
837 .field("hop_limit", &self.hop_limit())
838 .field("proto", &self.proto())
839 .field("dscp", &self.dscp_and_ecn().dscp())
840 .field("ecn", &self.dscp_and_ecn().ecn())
841 .field("flowlabel", &self.flowlabel())
842 .field("extension headers", &"TODO")
843 .field("body", &alloc::format!("<{} bytes>", self.body.len()))
844 .finish()
845 }
846}
847
848pub struct ExtensionHeaders<'a>(Records<&'a [u8], Ipv6ExtensionHeaderImpl>);
850
851impl<'a> ExtensionHeaders<'a> {
852 pub fn iter(&self) -> impl Iterator<Item = Ipv6ExtensionHeader<'_>> {
854 self.0.iter()
855 }
856}
857
858#[derive(Copy, Clone, Debug, Eq, PartialEq)]
864pub struct ExtHdrParseError;
865
866pub struct Ipv6PacketRaw<B> {
876 fixed_hdr: Ref<B, FixedHeader>,
878 extension_hdrs: MaybeParsed<RecordsRaw<B, Ipv6ExtensionHeaderImpl>, B>,
884 body_proto: Result<(MaybeParsed<B, B>, Ipv6Proto), ExtHdrParseError>,
897}
898
899impl<B> Ipv6PacketRaw<B> {
900 pub fn body_mut(&mut self) -> Option<&mut B> {
904 match self.body_proto {
905 Ok(ref mut b) => match b {
906 (MaybeParsed::Complete(ref mut b), _) => Some(b),
907 (MaybeParsed::Incomplete(ref mut b), _) => Some(b),
908 },
909 Err(_) => None,
910 }
911 }
912}
913
914impl<B: SplitByteSlice> Ipv6Header for Ipv6PacketRaw<B> {
915 fn get_fixed_header(&self) -> &FixedHeader {
916 &self.fixed_hdr
917 }
918}
919
920impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv6PacketRaw<B> {
921 type Error = IpParseError<Ipv6>;
922
923 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> Result<Self, Self::Error> {
924 let fixed_hdr = buffer
925 .take_obj_front::<FixedHeader>()
926 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for header"))?;
927 let payload_len = fixed_hdr.payload_len.get().into();
928 let _: Option<B> = buffer.len().checked_sub(payload_len).map(|padding| {
930 buffer.take_back(padding).unwrap_or_else(|| {
931 panic!("buffer.len()={} padding={}", buffer.len(), padding);
932 })
933 });
934
935 let mut extension_hdr_context = Ipv6ExtensionHeaderParsingContext::new(fixed_hdr.next_hdr);
936
937 let extension_hdrs =
938 RecordsRaw::parse_raw_with_mut_context(&mut buffer, &mut extension_hdr_context)
939 .map_incomplete(|(b, _)| b);
940
941 let body_proto = match &extension_hdrs {
942 MaybeParsed::Complete(r) => {
943 let _: &RecordsRaw<B, _> = r;
944 assert!(is_valid_next_header_upper_layer(extension_hdr_context.next_header));
965 let proto = Ipv6Proto::from(extension_hdr_context.next_header);
966 let body = MaybeParsed::new_with_min_len(
967 buffer.into_rest(),
968 payload_len.saturating_sub(extension_hdrs.len()),
969 );
970 Ok((body, proto))
971 }
972 MaybeParsed::Incomplete(b) => {
973 let _: &B = b;
974 Err(ExtHdrParseError)
975 }
976 };
977
978 Ok(Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto })
979 }
980
981 fn parse_metadata(&self) -> ParseMetadata {
982 let header_len = Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.len();
983 let body_len = self.body_proto.as_ref().map(|(b, _p)| b.len()).unwrap_or(0);
984 ParseMetadata::from_packet(header_len, body_len, 0)
985 }
986}
987
988impl<B: SplitByteSlice> Ipv6PacketRaw<B> {
989 pub fn body_proto(&self) -> Result<(MaybeParsed<&[u8], &[u8]>, Ipv6Proto), ExtHdrParseError> {
1002 self.body_proto
1003 .as_ref()
1004 .map(|(mp, proto)| {
1005 (mp.as_ref().map(|b| b.deref()).map_incomplete(|b| b.deref()), *proto)
1006 })
1007 .map_err(|e| *e)
1008 }
1009
1010 pub fn body(&self) -> Result<MaybeParsed<&[u8], &[u8]>, ExtHdrParseError> {
1021 self.body_proto().map(|(body, _proto)| body)
1022 }
1023
1024 pub fn proto(&self) -> Result<Ipv6Proto, ExtHdrParseError> {
1031 self.body_proto().map(|(_body, proto)| proto)
1032 }
1033}
1034
1035impl<B: SplitByteSliceMut> Ipv6PacketRaw<B> {
1036 pub fn set_src_ip(&mut self, addr: Ipv6Addr) {
1038 self.fixed_hdr.src_ip = addr;
1039 }
1040
1041 pub fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1043 self.fixed_hdr.dst_ip = addr;
1044 }
1045}
1046
1047pub enum NextHeader {
1050 NextLayer(Ipv6Proto),
1052 Extension(Ipv6ExtHdrType),
1054}
1055
1056impl From<NextHeader> for u8 {
1057 fn from(next_hdr: NextHeader) -> Self {
1058 match next_hdr {
1059 NextHeader::NextLayer(n) => n.into(),
1060 NextHeader::Extension(e) => e.into(),
1061 }
1062 }
1063}
1064
1065mod sealed {
1066 use super::*;
1067 pub trait Ipv6HeaderBefore<T> {}
1075
1076 impl<'a, O, T> Ipv6HeaderBefore<T> for &'a O where O: Ipv6HeaderBefore<T> {}
1077
1078 pub trait Ipv6HeaderBuilder {
1080 fn fixed_header(&self) -> &Ipv6PacketBuilder;
1082
1083 fn extension_headers_len(&self) -> usize;
1086
1087 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1092 &self,
1093 buffer: &mut BV,
1094 next_header: NextHeader,
1095 payload_len: usize,
1096 );
1097 }
1098}
1099use sealed::{Ipv6HeaderBefore, Ipv6HeaderBuilder};
1100
1101impl<'a, O> Ipv6HeaderBuilder for &'a O
1102where
1103 O: Ipv6HeaderBuilder,
1104{
1105 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1106 O::fixed_header(self)
1107 }
1108
1109 fn extension_headers_len(&self) -> usize {
1110 O::extension_headers_len(self)
1111 }
1112
1113 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1114 &self,
1115 buffer: &mut BV,
1116 next_header: NextHeader,
1117 payload_len: usize,
1118 ) {
1119 O::serialize_header(self, buffer, next_header, payload_len)
1120 }
1121}
1122
1123macro_rules! impl_packet_builder {
1128 {} => {
1129 fn constraints(&self) -> PacketConstraints {
1130 let ext_headers = self.extension_headers_len();
1131 let header_len = IPV6_FIXED_HDR_LEN + ext_headers;
1132 let footer_len = 0;
1133 let min_body_len = 0;
1134 let max_body_len = IPV6_MAX_PAYLOAD_LENGTH - ext_headers;
1137 PacketConstraints::new(header_len, footer_len, min_body_len, max_body_len)
1138 }
1139
1140 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
1141 let mut bv = &mut target.header;
1142 self.serialize_header(
1143 &mut bv,
1144 NextHeader::NextLayer(self.fixed_header().proto()),
1145 body.len(),
1146 );
1147 }
1148 }
1149}
1150
1151#[derive(Debug, Clone, Eq, PartialEq)]
1153pub struct Ipv6PacketBuilder {
1154 dscp_and_ecn: DscpAndEcn,
1155 flowlabel: u32,
1156 hop_limit: u8,
1157 proto: Ipv6Proto,
1160 src_ip: Ipv6Addr,
1161 dst_ip: Ipv6Addr,
1162}
1163
1164impl Ipv6PacketBuilder {
1165 pub fn new<S: Into<Ipv6Addr>, D: Into<Ipv6Addr>>(
1171 src_ip: S,
1172 dst_ip: D,
1173 hop_limit: u8,
1174 proto: Ipv6Proto,
1175 ) -> Ipv6PacketBuilder {
1176 Ipv6PacketBuilder {
1177 dscp_and_ecn: DscpAndEcn::default(),
1178 flowlabel: 0,
1179 hop_limit,
1180 proto,
1181 src_ip: src_ip.into(),
1182 dst_ip: dst_ip.into(),
1183 }
1184 }
1185
1186 pub fn dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1189 self.dscp_and_ecn = dscp_and_ecn;
1190 }
1191
1192 pub fn flowlabel(&mut self, flowlabel: u32) {
1198 assert!(flowlabel <= 1 << 20, "invalid flowlabel: {:x}", flowlabel);
1199 self.flowlabel = flowlabel;
1200 }
1201}
1202
1203impl Ipv6HeaderBuilder for Ipv6PacketBuilder {
1204 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1205 self
1206 }
1207
1208 fn extension_headers_len(&self) -> usize {
1209 0
1210 }
1211
1212 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1213 &self,
1214 buffer: &mut BV,
1215 next_header: NextHeader,
1216 payload_len: usize,
1217 ) {
1218 buffer
1219 .write_obj_front(&FixedHeader::new(
1220 self.dscp_and_ecn,
1221 self.flowlabel,
1222 {
1223 debug_assert!(payload_len <= core::u16::MAX as usize);
1230 payload_len as u16
1231 },
1232 next_header.into(),
1233 self.hop_limit,
1234 self.src_ip,
1235 self.dst_ip,
1236 ))
1237 .expect("not enough bytes for IPv6 fixed header");
1238 }
1239}
1240
1241impl PacketBuilder for Ipv6PacketBuilder {
1242 impl_packet_builder! {}
1243}
1244
1245#[derive(Debug, Clone)]
1247pub struct Ipv6PacketBuilderWithHbhOptions<'a, I> {
1248 prefix_builder: Ipv6PacketBuilder,
1249 hbh_options: AlignedRecordSequenceBuilder<HopByHopOption<'a>, I>,
1250}
1251
1252impl<'a, I> Ipv6PacketBuilderWithHbhOptions<'a, I>
1253where
1254 I: Iterator + Clone,
1255 I::Item: Borrow<HopByHopOption<'a>>,
1256{
1257 pub fn new<T: IntoIterator<Item = I::Item, IntoIter = I>>(
1259 prefix_builder: Ipv6PacketBuilder,
1260 options: T,
1261 ) -> Option<Ipv6PacketBuilderWithHbhOptions<'a, I>> {
1262 let iter = options.into_iter();
1263 if iter
1266 .clone()
1267 .filter(|r| matches!(r.borrow().data, HopByHopOptionData::RouterAlert { .. }))
1268 .count()
1269 > 1
1270 {
1271 return None;
1272 }
1273 let hbh_options = AlignedRecordSequenceBuilder::new(2, iter);
1274 if next_multiple_of_eight(2 + hbh_options.serialized_len()) > IPV6_HBH_OPTIONS_MAX_LEN {
1276 return None;
1277 }
1278 Some(Ipv6PacketBuilderWithHbhOptions { prefix_builder, hbh_options })
1279 }
1280
1281 fn aligned_hbh_len(&self) -> usize {
1282 let opt_len = self.hbh_options.serialized_len();
1283 let hbh_len = opt_len + 2;
1284 next_multiple_of_eight(hbh_len)
1285 }
1286}
1287
1288fn next_multiple_of_eight(x: usize) -> usize {
1289 (x + 7) & (!7)
1290}
1291
1292impl IpPacketBuilder<Ipv6> for Ipv6PacketBuilder {
1293 fn new(src_ip: Ipv6Addr, dst_ip: Ipv6Addr, ttl: u8, proto: Ipv6Proto) -> Self {
1294 Ipv6PacketBuilder::new(src_ip, dst_ip, ttl, proto)
1295 }
1296
1297 fn src_ip(&self) -> Ipv6Addr {
1298 self.src_ip
1299 }
1300
1301 fn set_src_ip(&mut self, addr: Ipv6Addr) {
1302 self.src_ip = addr;
1303 }
1304
1305 fn dst_ip(&self) -> Ipv6Addr {
1306 self.dst_ip
1307 }
1308
1309 fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1310 self.dst_ip = addr;
1311 }
1312
1313 fn proto(&self) -> Ipv6Proto {
1314 self.proto
1315 }
1316
1317 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1318 self.dscp_and_ecn = dscp_and_ecn;
1319 }
1320}
1321
1322impl<'a, I> Ipv6HeaderBuilder for Ipv6PacketBuilderWithHbhOptions<'a, I>
1323where
1324 I: Iterator + Clone,
1325 I::Item: Borrow<HopByHopOption<'a>>,
1326{
1327 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1328 &self.prefix_builder
1329 }
1330
1331 fn extension_headers_len(&self) -> usize {
1332 self.prefix_builder.extension_headers_len() + self.aligned_hbh_len()
1333 }
1334
1335 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1336 &self,
1337 buffer: &mut BV,
1338 next_header: NextHeader,
1339 payload_len: usize,
1340 ) {
1341 let aligned_hbh_len = self.aligned_hbh_len();
1342 self.prefix_builder.serialize_header(
1344 buffer,
1345 NextHeader::Extension(Ipv6ExtHdrType::HopByHopOptions),
1346 payload_len + aligned_hbh_len,
1347 );
1348 let mut hbh_header = buffer.take_front(aligned_hbh_len).unwrap();
1350 let hbh_header = hbh_header.as_mut();
1351 hbh_header[0] = next_header.into();
1352 hbh_header[1] = u8::try_from((aligned_hbh_len - 8) / 8).expect("extension header too big");
1353 self.hbh_options.serialize_into(&mut hbh_header[2..]);
1354 }
1355}
1356
1357impl<'a, I> PacketBuilder for Ipv6PacketBuilderWithHbhOptions<'a, I>
1358where
1359 I: Iterator + Clone,
1360 I::Item: Borrow<HopByHopOption<'a>>,
1361{
1362 impl_packet_builder! {}
1363}
1364
1365impl<'a, I> IpPacketBuilder<Ipv6> for Ipv6PacketBuilderWithHbhOptions<'a, I>
1366where
1367 I: Iterator<Item: Borrow<HopByHopOption<'a>>> + Debug + Default + Clone,
1368{
1369 fn new(src_ip: Ipv6Addr, dst_ip: Ipv6Addr, ttl: u8, proto: Ipv6Proto) -> Self {
1370 Ipv6PacketBuilderWithHbhOptions::new(
1371 Ipv6PacketBuilder::new(src_ip, dst_ip, ttl, proto),
1372 I::default(),
1373 )
1374 .expect("packet builder with no options should be valid")
1375 }
1376
1377 fn src_ip(&self) -> Ipv6Addr {
1378 self.prefix_builder.src_ip
1379 }
1380
1381 fn set_src_ip(&mut self, addr: Ipv6Addr) {
1382 self.prefix_builder.src_ip = addr;
1383 }
1384
1385 fn dst_ip(&self) -> Ipv6Addr {
1386 self.prefix_builder.dst_ip
1387 }
1388
1389 fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1390 self.prefix_builder.dst_ip = addr;
1391 }
1392
1393 fn proto(&self) -> Ipv6Proto {
1394 self.prefix_builder.proto
1395 }
1396
1397 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1398 self.prefix_builder.set_dscp_and_ecn(dscp_and_ecn)
1399 }
1400}
1401
1402#[derive(Debug, Eq, PartialEq)]
1411pub struct Ipv6PacketBuilderWithFragmentHeader<B> {
1412 header_builder: B,
1413 fragment_offset: FragmentOffset,
1414 more_fragments: bool,
1415 identification: u32,
1416}
1417
1418impl<B: Ipv6HeaderBefore<Self>> Ipv6PacketBuilderWithFragmentHeader<B> {
1419 pub fn new(
1421 header_builder: B,
1422 fragment_offset: FragmentOffset,
1423 more_fragments: bool,
1424 identification: u32,
1425 ) -> Self {
1426 Self { header_builder, fragment_offset, more_fragments, identification }
1427 }
1428}
1429
1430impl<B> Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>> for Ipv6PacketBuilder {}
1431impl<B, I> Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>>
1432 for Ipv6PacketBuilderWithHbhOptions<'_, I>
1433{
1434}
1435
1436pub trait Ipv6PacketBuilderBeforeFragment:
1439 Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<Self>> + Ipv6HeaderBuilder + Sized
1440{
1441}
1442impl<B> Ipv6PacketBuilderBeforeFragment for B where
1443 B: Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<Self>> + Ipv6HeaderBuilder + Sized
1444{
1445}
1446
1447impl<B: Ipv6HeaderBuilder> Ipv6HeaderBuilder for Ipv6PacketBuilderWithFragmentHeader<B> {
1448 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1449 self.header_builder.fixed_header()
1450 }
1451
1452 fn extension_headers_len(&self) -> usize {
1453 self.header_builder.extension_headers_len() + IPV6_FRAGMENT_EXT_HDR_LEN
1454 }
1455
1456 fn serialize_header<BB: SplitByteSliceMut, BV: BufferViewMut<BB>>(
1457 &self,
1458 buffer: &mut BV,
1459 next_header: NextHeader,
1460 payload_len: usize,
1461 ) {
1462 let Self { header_builder, fragment_offset, more_fragments, identification } = self;
1463 let payload_len = payload_len + IPV6_FRAGMENT_EXT_HDR_LEN;
1464 header_builder.serialize_header(
1465 buffer,
1466 NextHeader::Extension(Ipv6ExtHdrType::Fragment),
1467 payload_len,
1468 );
1469 buffer.write_obj_front(&u8::from(next_header)).unwrap();
1470 let _: BB = buffer.take_front_zero(1).unwrap();
1472 let more_fragments = u16::from(*more_fragments);
1473 buffer
1474 .write_obj_front(&U16::new(fragment_offset.into_raw() << 3 | more_fragments))
1475 .unwrap();
1476 buffer.write_obj_front(&U32::new(*identification)).unwrap();
1477 }
1478}
1479
1480impl<B: Ipv6HeaderBuilder> PacketBuilder for Ipv6PacketBuilderWithFragmentHeader<B> {
1481 impl_packet_builder! {}
1482}
1483
1484pub(crate) fn reassemble_fragmented_packet<
1486 B: SplitByteSliceMut,
1487 BV: BufferViewMut<B>,
1488 I: Iterator<Item = Vec<u8>>,
1489>(
1490 mut buffer: BV,
1491 header: Vec<u8>,
1492 body_fragments: I,
1493) -> IpParseResult<Ipv6, ()> {
1494 let bytes = buffer.as_mut();
1495
1496 bytes[0..header.len()].copy_from_slice(&header[..]);
1498 let mut byte_count = header.len();
1499
1500 for p in body_fragments {
1502 bytes[byte_count..byte_count + p.len()].copy_from_slice(&p[..]);
1503 byte_count += p.len();
1504 }
1505
1506 let payload_length = byte_count - IPV6_FIXED_HDR_LEN;
1518
1519 if payload_length > usize::from(core::u16::MAX) {
1522 return debug_err!(
1523 Err(ParseError::Format.into()),
1524 "fragmented packet payload length of {} bytes is too large",
1525 payload_length
1526 );
1527 }
1528
1529 let mut header = Ref::<_, FixedHeader>::from_prefix(bytes).unwrap().0;
1532
1533 header.payload_len.set(u16::try_from(payload_length).unwrap());
1535
1536 Ok(())
1537}
1538
1539#[cfg(test)]
1540mod tests {
1541 use assert_matches::assert_matches;
1542 use packet::{Buf, FragmentedBuffer, ParseBuffer};
1543 use test_case::test_case;
1544
1545 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1546 use crate::testutil::*;
1547
1548 use super::ext_hdrs::*;
1549 use super::*;
1550
1551 const DEFAULT_SRC_IP: Ipv6Addr =
1552 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1553 const DEFAULT_DST_IP: Ipv6Addr =
1554 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1555
1556 const DEFAULT_V4_SRC_IP: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1557 const DEFAULT_V4_DST_IP: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1558
1559 #[test]
1560 fn test_parse_serialize_full_tcp() {
1561 use crate::testdata::syn_v6::*;
1562
1563 let mut buf = ETHERNET_FRAME.bytes;
1564 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1565 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1566
1567 let mut body = frame.body();
1568 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1569 verify_ipv6_packet(&packet, IPV6_PACKET);
1570
1571 let buffer = packet
1573 .body()
1574 .into_serializer()
1575 .encapsulate(packet.builder())
1576 .encapsulate(frame.builder())
1577 .serialize_vec_outer()
1578 .unwrap();
1579 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1580
1581 assert_eq!(&packet.to_vec()[..], IPV6_PACKET.bytes);
1583 }
1584
1585 #[test]
1586 fn test_parse_serialize_full_udp() {
1587 use crate::testdata::dns_request_v6::*;
1588
1589 let mut buf = ETHERNET_FRAME.bytes;
1590 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1591 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1592
1593 let mut body = frame.body();
1594 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1595 verify_ipv6_packet(&packet, IPV6_PACKET);
1596
1597 let buffer = packet
1599 .body()
1600 .into_serializer()
1601 .encapsulate(packet.builder())
1602 .encapsulate(frame.builder())
1603 .serialize_vec_outer()
1604 .unwrap();
1605 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1606
1607 assert_eq!(&packet.to_vec()[..], IPV6_PACKET.bytes);
1609 }
1610
1611 #[test]
1612 fn test_parse_serialize_with_extension_headers() {
1613 use crate::testdata::mld_router_report::*;
1616
1617 let mut buf = REPORT;
1618 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1619 assert_eq!(packet.iter_extension_hdrs().count(), 1);
1620
1621 assert_eq!(&packet.to_vec()[..], REPORT);
1626 }
1627
1628 fn fixed_hdr_to_bytes(fixed_hdr: FixedHeader) -> [u8; IPV6_FIXED_HDR_LEN] {
1629 zerocopy::transmute!(fixed_hdr)
1630 }
1631
1632 fn new_fixed_hdr() -> FixedHeader {
1634 FixedHeader::new(
1635 DscpAndEcn::new(0, 2),
1636 0x77,
1637 0,
1638 IpProto::Tcp.into(),
1639 64,
1640 DEFAULT_SRC_IP,
1641 DEFAULT_DST_IP,
1642 )
1643 }
1644
1645 #[test]
1646 fn test_parse() {
1647 let mut buf = &fixed_hdr_to_bytes(new_fixed_hdr())[..];
1648 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1649 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1650 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1651 assert_eq!(packet.flowlabel(), 0x77);
1652 assert_eq!(packet.hop_limit(), 64);
1653 assert_eq!(packet.fixed_hdr.next_hdr, IpProto::Tcp.into());
1654 assert_eq!(packet.proto(), IpProto::Tcp.into());
1655 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1656 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1657 assert_eq!(packet.body(), []);
1658 }
1659
1660 #[test]
1661 fn test_parse_with_ext_hdrs() {
1662 #[rustfmt::skip]
1663 let mut buf = [
1664 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1666 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1667
1668 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,
1683 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1684
1685 IpProto::Tcp.into(), 1, 0, 1, 0, 1, 1, 0, 1, 6, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
1695 ];
1696 let mut fixed_hdr = new_fixed_hdr();
1697 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
1698 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1699 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1700 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1701 let mut buf = &buf[..];
1702 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1703 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1704 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1705 assert_eq!(packet.flowlabel(), 0x77);
1706 assert_eq!(packet.hop_limit(), 64);
1707 assert_eq!(packet.fixed_hdr.next_hdr, Ipv6ExtHdrType::HopByHopOptions.into());
1708 assert_eq!(packet.proto(), IpProto::Tcp.into());
1709 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1710 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1711 assert_eq!(packet.body(), [1, 2, 3, 4, 5]);
1712 let ext_hdrs: Vec<Ipv6ExtensionHeader<'_>> = packet.iter_extension_hdrs().collect();
1713 assert_eq!(ext_hdrs.len(), 2);
1714 assert_eq!(ext_hdrs[0].next_header, Ipv6ExtHdrType::Routing.into());
1716 if let Ipv6ExtensionHeaderData::HopByHopOptions { options } = ext_hdrs[0].data() {
1717 assert_eq!(options.iter().count(), 0);
1719 } else {
1720 panic!("Should have matched HopByHopOptions!");
1721 }
1722
1723 assert_eq!(ext_hdrs[1].next_header, IpProto::Tcp.into());
1728 if let Ipv6ExtensionHeaderData::DestinationOptions { options } = ext_hdrs[1].data() {
1729 assert_eq!(options.iter().count(), 0);
1731 } else {
1732 panic!("Should have matched DestinationOptions!");
1733 }
1734
1735 #[rustfmt::skip]
1737 let mut buf = [
1738 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1740 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1741
1742 Ipv6Proto::NoNextHeader.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
1751 ];
1752 let mut fixed_hdr = new_fixed_hdr();
1753 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
1754 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1755 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1756 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1757 let mut buf = &buf[..];
1758 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1759 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1760 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1761 assert_eq!(packet.flowlabel(), 0x77);
1762 assert_eq!(packet.hop_limit(), 64);
1763 assert_eq!(packet.fixed_hdr.next_hdr, Ipv6ExtHdrType::HopByHopOptions.into());
1764 assert_eq!(packet.proto(), Ipv6Proto::NoNextHeader);
1765 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1766 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1767 assert_eq!(packet.body(), [1, 2, 3, 4, 5]);
1768 let ext_hdrs: Vec<Ipv6ExtensionHeader<'_>> = packet.iter_extension_hdrs().collect();
1769 assert_eq!(ext_hdrs.len(), 1);
1770 assert_eq!(ext_hdrs[0].next_header, Ipv6Proto::NoNextHeader.into());
1772 if let Ipv6ExtensionHeaderData::HopByHopOptions { options } = ext_hdrs[0].data() {
1773 assert_eq!(options.iter().count(), 0);
1775 } else {
1776 panic!("Should have matched HopByHopOptions!");
1777 }
1778 }
1779
1780 #[test]
1781 fn test_parse_error() {
1782 let mut fixed_hdr = new_fixed_hdr();
1784 fixed_hdr.version_tc_flowlabel[0] = 0x50;
1785 assert_eq!(
1786 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1787 ParseError::Format.into()
1788 );
1789
1790 let mut fixed_hdr = new_fixed_hdr();
1792 fixed_hdr.payload_len = U16::new(2);
1793 assert_eq!(
1794 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1795 ParseError::Format.into()
1796 );
1797
1798 let mut fixed_hdr = new_fixed_hdr();
1800 fixed_hdr.next_hdr = 255;
1801 assert_eq!(
1802 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1803 IpParseError::ParameterProblem {
1804 src_ip: DEFAULT_SRC_IP,
1805 dst_ip: DEFAULT_DST_IP,
1806 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1807 pointer: u32::from(NEXT_HEADER_OFFSET),
1808 must_send_icmp: false,
1809 header_len: (),
1810 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1811 }
1812 );
1813
1814 let mut fixed_hdr = new_fixed_hdr();
1816 fixed_hdr.next_hdr = Ipv4Proto::Icmp.into();
1817 assert_eq!(
1818 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1819 IpParseError::ParameterProblem {
1820 src_ip: DEFAULT_SRC_IP,
1821 dst_ip: DEFAULT_DST_IP,
1822 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1823 pointer: u32::from(NEXT_HEADER_OFFSET),
1824 must_send_icmp: false,
1825 header_len: (),
1826 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1827 }
1828 );
1829
1830 #[rustfmt::skip]
1832 let mut buf = [
1833 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1835 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1836
1837 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,
1845 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1846
1847 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
1856 ];
1857 let mut fixed_hdr = new_fixed_hdr();
1858 fixed_hdr.next_hdr = Ipv6ExtHdrType::Routing.into();
1859 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1860 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1861 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1862 let mut buf = &buf[..];
1863 assert_eq!(
1864 buf.parse::<Ipv6Packet<_>>().unwrap_err(),
1865 IpParseError::ParameterProblem {
1866 src_ip: DEFAULT_SRC_IP,
1867 dst_ip: DEFAULT_DST_IP,
1868 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1869 pointer: IPV6_FIXED_HDR_LEN as u32,
1870 must_send_icmp: false,
1871 header_len: (),
1872 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1873 }
1874 );
1875
1876 #[rustfmt::skip]
1878 let mut buf = [
1879 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1881 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1882
1883 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,
1891 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1892
1893 1, 2, 3, 4, 5,
1895 ];
1896 let mut fixed_hdr = new_fixed_hdr();
1897 fixed_hdr.next_hdr = Ipv6ExtHdrType::Routing.into();
1898 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1899 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1900 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1901 let mut buf = &buf[..];
1902 assert_eq!(
1903 buf.parse::<Ipv6Packet<_>>().unwrap_err(),
1904 IpParseError::ParameterProblem {
1905 src_ip: DEFAULT_SRC_IP,
1906 dst_ip: DEFAULT_DST_IP,
1907 code: Icmpv6ParameterProblemCode::ErroneousHeaderField,
1908 pointer: (IPV6_FIXED_HDR_LEN as u32) + 2,
1909 must_send_icmp: true,
1910 header_len: (),
1911 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1912 }
1913 );
1914 }
1915
1916 #[test]
1917 fn test_parse_all_next_header_values() {
1918 let mut buf = [
1924 0x81, 0x13, 0x27, 0xeb, 0x75, 0x92, 0x33, 0x89, 0x01, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
1925 0x03, 0x70, 0x00, 0x22, 0xf7, 0x30, 0x2c, 0x06, 0xfe, 0xc9, 0x00, 0x2d, 0x3b, 0xeb,
1926 0xad, 0x3e, 0x5c, 0x41, 0xc8, 0x70, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x11, 0x00,
1927 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x4f, 0x4f, 0x6f, 0x4f, 0x4f, 0x4f, 0x4f,
1928 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x19, 0x19,
1929 0x19, 0x19, 0x19, 0x4f, 0x4f, 0x4f, 0x4f, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1930 0x00, 0x4f, 0x4f, 0x5a, 0x5a, 0x5a, 0xc9, 0x5a, 0x46, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
1931 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0xe4, 0x5a, 0x5a, 0x5a, 0x5a,
1932 ];
1933
1934 assert_matches!(
1937 (&buf[..]).parse::<Ipv6Packet<_>>(),
1938 Err(IpParseError::ParameterProblem {
1939 src_ip: _,
1940 dst_ip: _,
1941 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1942 pointer: 0,
1943 must_send_icmp: false,
1944 header_len: (),
1945 action: IpParseErrorAction::DiscardPacket,
1946 })
1947 );
1948
1949 for b in 0u8..=255 {
1952 buf[6] = b;
1954 let _: Result<_, _> = (&buf[..]).parse::<Ipv6Packet<_>>();
1955 }
1956 }
1957
1958 #[test]
1959 fn test_partial_parse() {
1960 use core::convert::TryInto as _;
1961 use core::ops::Deref as _;
1962
1963 #[rustfmt::skip]
1965 let mut buf = [
1966 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1968 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1969
1970 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
1979 ];
1980 let len = buf.len() - IPV6_FIXED_HDR_LEN;
1981 let len = len.try_into().unwrap();
1982 let make_fixed_hdr = || {
1983 let mut fixed_hdr = new_fixed_hdr();
1984 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
1985 fixed_hdr.payload_len = U16::new(len);
1986 fixed_hdr
1987 };
1988 const MALFORMED_BYTE: u8 = 10;
1990 buf[IPV6_FIXED_HDR_LEN + 1] = MALFORMED_BYTE;
1991 let fixed_hdr = fixed_hdr_to_bytes(make_fixed_hdr());
1992 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr);
1993 let mut buf = &buf[..];
1994 let partial = buf.parse::<Ipv6PacketRaw<_>>().unwrap();
1995 let Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto } = &partial;
1996 assert_eq!(fixed_hdr.deref(), &make_fixed_hdr());
1997 assert_eq!(
1998 *extension_hdrs.as_ref().incomplete().unwrap(),
1999 [IpProto::Tcp.into(), MALFORMED_BYTE]
2000 );
2001 assert_eq!(body_proto, &Err(ExtHdrParseError));
2002 assert!(Ipv6Packet::try_from_raw(partial).is_err());
2003
2004 let mut buf = [
2006 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,
2008 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
2010 ];
2011 let make_fixed_hdr = || {
2012 let mut fixed_hdr = new_fixed_hdr();
2013 fixed_hdr.next_hdr = IpProto::Tcp.into();
2014 fixed_hdr.payload_len = U16::new(10);
2015 fixed_hdr
2016 };
2017 let fixed_hdr = fixed_hdr_to_bytes(make_fixed_hdr());
2018 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr);
2019 let mut parsebuff = &buf[..];
2020 let partial = parsebuff.parse::<Ipv6PacketRaw<_>>().unwrap();
2021 let Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto } = &partial;
2022 assert_eq!(fixed_hdr.deref(), &make_fixed_hdr());
2023 assert_eq!(extension_hdrs.as_ref().complete().unwrap().deref(), []);
2024 let (body, proto) = body_proto.unwrap();
2025 assert_eq!(body.incomplete().unwrap(), &buf[IPV6_FIXED_HDR_LEN..]);
2026 assert_eq!(proto, IpProto::Tcp.into());
2027 assert!(Ipv6Packet::try_from_raw(partial).is_err());
2028 }
2029
2030 fn new_builder() -> Ipv6PacketBuilder {
2032 Ipv6PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, 64, IpProto::Tcp.into())
2033 }
2034
2035 #[test]
2036 fn test_serialize() {
2037 let mut builder = new_builder();
2038 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
2039 builder.flowlabel(0x10405);
2040 let mut buf = (&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2041 .into_serializer()
2042 .encapsulate(builder)
2043 .serialize_vec_outer()
2044 .unwrap();
2045 assert_eq!(
2047 buf.as_ref(),
2048 &[
2049 100, 177, 4, 5, 0, 10, 6, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
2050 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, 1, 2, 3, 4,
2051 5, 6, 7, 8, 9
2052 ][..],
2053 );
2054
2055 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2056 assert_eq!(packet.dscp_and_ecn().dscp(), 0x12);
2059 assert_eq!(packet.dscp_and_ecn().ecn(), 3);
2060 assert_eq!(packet.flowlabel(), 0x10405);
2061 }
2062
2063 #[test]
2064 fn test_serialize_zeroes() {
2065 let mut buf_0 = [0; IPV6_FIXED_HDR_LEN];
2068 let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], IPV6_FIXED_HDR_LEN..)
2069 .encapsulate(new_builder())
2070 .serialize_vec_outer()
2071 .unwrap()
2072 .unwrap_a();
2073 let mut buf_1 = [0xFF; IPV6_FIXED_HDR_LEN];
2074 let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], IPV6_FIXED_HDR_LEN..)
2075 .encapsulate(new_builder())
2076 .serialize_vec_outer()
2077 .unwrap()
2078 .unwrap_a();
2079 assert_eq!(&buf_0[..], &buf_1[..]);
2080 }
2081
2082 #[test]
2083 fn test_packet_builder_proto_not_next_header() {
2084 let mut buf = (&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2088 .into_serializer()
2089 .encapsulate(
2090 Ipv6PacketBuilderWithHbhOptions::new(
2091 new_builder(),
2092 &[HopByHopOption {
2093 action: ExtensionHeaderOptionAction::SkipAndContinue,
2094 mutable: false,
2095 data: HopByHopOptionData::RouterAlert { data: 0 },
2096 }],
2097 )
2098 .unwrap(),
2099 )
2100 .serialize_vec_outer()
2101 .unwrap();
2102 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2103 assert_eq!(packet.proto(), IpProto::Tcp.into());
2104 assert_eq!(packet.next_header(), Ipv6ExtHdrType::HopByHopOptions.into());
2105 }
2106
2107 #[test]
2108 #[should_panic(expected = "SizeLimitExceeded, Nested { inner: Buf { buf:")]
2109 fn test_serialize_panic_packet_length() {
2110 let _: Buf<&mut [u8]> = Buf::new(&mut [0; 1 << 16][..], ..)
2113 .encapsulate(new_builder())
2114 .serialize_vec_outer()
2115 .unwrap()
2116 .unwrap_a();
2117 }
2118
2119 #[test]
2120 #[should_panic(expected = "packet must have at least one extension header")]
2121 fn test_copy_header_bytes_for_fragment_without_ext_hdrs() {
2122 let mut buf = &fixed_hdr_to_bytes(new_fixed_hdr())[..];
2123 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2124 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2125 }
2126
2127 #[test]
2128 #[should_panic(expected = "exhausted all extension headers without finding fragment header")]
2129 fn test_copy_header_bytes_for_fragment_with_1_ext_hdr_no_fragment() {
2130 #[rustfmt::skip]
2131 let mut buf = [
2132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2135
2136 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2145 ];
2146 let mut fixed_hdr = new_fixed_hdr();
2147 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2148 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2149 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2150 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2151 let mut buf = &buf[..];
2152 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2153 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2154 }
2155
2156 #[test]
2157 #[should_panic(expected = "exhausted all extension headers without finding fragment header")]
2158 fn test_copy_header_bytes_for_fragment_with_2_ext_hdr_no_fragment() {
2159 #[rustfmt::skip]
2160 let mut buf = [
2161 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2163 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2164
2165 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,
2182 ];
2183 let mut fixed_hdr = new_fixed_hdr();
2184 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2185 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2186 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2187 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2188 let mut buf = &buf[..];
2189 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2190 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2191 }
2192
2193 #[test]
2194 fn test_copy_header_bytes_for_fragment() {
2195 #[rustfmt::skip]
2200 let mut bytes = [
2201 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2203 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2204
2205 IpProto::Tcp.into(), 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5,
2213 ];
2214 let mut fixed_hdr = new_fixed_hdr();
2215 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2216 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2217 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2218 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2219 let mut buf = &bytes[..];
2220 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2221 let copied_bytes = packet.copy_header_bytes_for_fragment();
2222 bytes[6] = IpProto::Tcp.into();
2223 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN]);
2224
2225 #[rustfmt::skip]
2230 let mut bytes = [
2231 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2233 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2234
2235 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,
2250 ];
2251 let mut fixed_hdr = new_fixed_hdr();
2252 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2253 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2254 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2255 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2256 let mut buf = &bytes[..];
2257 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2258 let copied_bytes = packet.copy_header_bytes_for_fragment();
2259 bytes[IPV6_FIXED_HDR_LEN] = IpProto::Tcp.into();
2260 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN + 8]);
2261
2262 #[rustfmt::skip]
2267 let mut bytes = [
2268 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2270 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2271
2272 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,
2295 ];
2296 let mut fixed_hdr = new_fixed_hdr();
2297 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2298 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2299 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2300 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2301 let mut buf = &bytes[..];
2302 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2303 let copied_bytes = packet.copy_header_bytes_for_fragment();
2304 bytes[IPV6_FIXED_HDR_LEN + 8] = IpProto::Tcp.into();
2305 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN + 24]);
2306
2307 #[rustfmt::skip]
2312 let mut bytes = [
2313 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2315 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2316
2317 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,
2333 ];
2334 let mut fixed_hdr = new_fixed_hdr();
2335 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2336 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2337 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2338 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2339 let mut buf = &bytes[..];
2340 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2341 let copied_bytes = packet.copy_header_bytes_for_fragment();
2342 let mut expected_bytes = Vec::new();
2343 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2344 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2345 expected_bytes[6] = Ipv6ExtHdrType::DestinationOptions.into();
2346 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2347
2348 #[rustfmt::skip]
2353 let mut bytes = [
2354 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2356 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2357
2358 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,
2380 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2381
2382 1, 2, 3, 4, 5,
2384 ];
2385 let mut fixed_hdr = new_fixed_hdr();
2386 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2387 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2388 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2389 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2390 let mut buf = &bytes[..];
2391 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2392 let copied_bytes = packet.copy_header_bytes_for_fragment();
2393 let mut expected_bytes = Vec::new();
2394 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2395 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2396 expected_bytes[6] = Ipv6ExtHdrType::DestinationOptions.into();
2397 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2398
2399 #[rustfmt::skip]
2404 let mut bytes = [
2405 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2407 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2408
2409 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,
2432 ];
2433 let mut fixed_hdr = new_fixed_hdr();
2434 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2435 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2436 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2437 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2438 let mut buf = &bytes[..];
2439 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2440 let copied_bytes = packet.copy_header_bytes_for_fragment();
2441 let mut expected_bytes = Vec::new();
2442 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN + 8]);
2443 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 16..bytes.len() - 5]);
2444 expected_bytes[IPV6_FIXED_HDR_LEN] = Ipv6ExtHdrType::DestinationOptions.into();
2445 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2446
2447 #[rustfmt::skip]
2452 let mut bytes = [
2453 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2455 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2456
2457 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,
2471 ];
2472 let mut fixed_hdr = new_fixed_hdr();
2473 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2474 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2475 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2476 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2477 let mut buf = &bytes[..];
2478 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2479 let copied_bytes = packet.copy_header_bytes_for_fragment();
2480 let mut expected_bytes = Vec::new();
2481 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2482 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2483 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2484 }
2485
2486 #[test]
2487 fn test_next_multiple_of_eight() {
2488 for x in 0usize..=IPV6_HBH_OPTIONS_MAX_LEN {
2489 let y = next_multiple_of_eight(x);
2490 assert_eq!(y % 8, 0);
2491 assert!(y >= x);
2492 if x % 8 == 0 {
2493 assert_eq!(x, y);
2494 } else {
2495 assert_eq!(x + (8 - x % 8), y);
2496 }
2497 }
2498 }
2499
2500 fn create_ipv4_and_ipv6_builders(
2501 proto_v4: Ipv4Proto,
2502 proto_v6: Ipv6Proto,
2503 ) -> (Ipv4PacketBuilder, Ipv6PacketBuilder) {
2504 const IP_DSCP_AND_ECN: DscpAndEcn = DscpAndEcn::new(0x12, 3);
2505 const IP_TTL: u8 = 64;
2506
2507 let mut ipv4_builder =
2508 Ipv4PacketBuilder::new(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP, IP_TTL, proto_v4);
2509 ipv4_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
2510 ipv4_builder.df_flag(false);
2511 ipv4_builder.mf_flag(false);
2512 ipv4_builder.fragment_offset(FragmentOffset::ZERO);
2513
2514 let mut ipv6_builder =
2515 Ipv6PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, IP_TTL, proto_v6);
2516 ipv6_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
2517 ipv6_builder.flowlabel(0x456);
2518
2519 (ipv4_builder, ipv6_builder)
2520 }
2521
2522 fn create_tcp_ipv4_and_ipv6_pkt(
2523 ) -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
2524 use crate::tcp::TcpSegmentBuilder;
2525 use core::num::NonZeroU16;
2526
2527 let tcp_src_port: NonZeroU16 = NonZeroU16::new(20).unwrap();
2528 let tcp_dst_port: NonZeroU16 = NonZeroU16::new(30).unwrap();
2529 const TCP_SEQ_NUM: u32 = 4321;
2530 const TCP_ACK_NUM: Option<u32> = Some(1234);
2531 const TCP_WINDOW_SIZE: u16 = 12345;
2532 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2533
2534 let (ipv4_builder, ipv6_builder) =
2535 create_ipv4_and_ipv6_builders(IpProto::Tcp.into(), IpProto::Tcp.into());
2536
2537 let tcp_builder = TcpSegmentBuilder::new(
2538 DEFAULT_V4_SRC_IP,
2539 DEFAULT_V4_DST_IP,
2540 tcp_src_port,
2541 tcp_dst_port,
2542 TCP_SEQ_NUM,
2543 TCP_ACK_NUM,
2544 TCP_WINDOW_SIZE,
2545 );
2546
2547 let v4_pkt_buf = (&PAYLOAD)
2548 .into_serializer()
2549 .encapsulate(tcp_builder)
2550 .encapsulate(ipv4_builder)
2551 .serialize_vec_outer()
2552 .expect("Failed to serialize to v4_pkt_buf");
2553
2554 let v6_tcp_builder = TcpSegmentBuilder::new(
2555 DEFAULT_SRC_IP,
2556 DEFAULT_DST_IP,
2557 tcp_src_port,
2558 tcp_dst_port,
2559 TCP_SEQ_NUM,
2560 TCP_ACK_NUM,
2561 TCP_WINDOW_SIZE,
2562 );
2563
2564 let v6_pkt_buf = (&PAYLOAD)
2565 .into_serializer()
2566 .encapsulate(v6_tcp_builder)
2567 .encapsulate(ipv6_builder)
2568 .serialize_vec_outer()
2569 .expect("Failed to serialize to v4_pkt_buf");
2570
2571 (v4_pkt_buf, v6_pkt_buf)
2572 }
2573
2574 #[test]
2575 fn test_nat64_translate_tcp() {
2576 let (expected_v4_pkt_buf, mut v6_pkt_buf) = create_tcp_ipv4_and_ipv6_pkt();
2577
2578 let parsed_v6_packet =
2579 v6_pkt_buf.parse::<Ipv6Packet<_>>().expect("Failed to parse v6_pkt_buf");
2580 let nat64_translation_result =
2581 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2582
2583 let serializable_pkt =
2584 assert_matches!(nat64_translation_result, Nat64TranslationResult::Forward(s) => s);
2585
2586 let translated_v4_pkt_buf = serializable_pkt
2587 .serialize_vec_outer()
2588 .expect("Failed to serialize to translated_v4_pkt_buf");
2589
2590 assert_eq!(
2591 expected_v4_pkt_buf.to_flattened_vec(),
2592 translated_v4_pkt_buf.to_flattened_vec()
2593 );
2594 }
2595
2596 fn create_udp_ipv4_and_ipv6_pkt(
2597 ) -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
2598 use crate::udp::UdpPacketBuilder;
2599 use core::num::NonZeroU16;
2600
2601 let udp_src_port: NonZeroU16 = NonZeroU16::new(35000).unwrap();
2602 let udp_dst_port: NonZeroU16 = NonZeroU16::new(53).unwrap();
2603 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2604
2605 let (ipv4_builder, ipv6_builder) =
2606 create_ipv4_and_ipv6_builders(IpProto::Udp.into(), IpProto::Udp.into());
2607
2608 let v4_udp_builder = UdpPacketBuilder::new(
2609 DEFAULT_V4_SRC_IP,
2610 DEFAULT_V4_DST_IP,
2611 Some(udp_src_port),
2612 udp_dst_port,
2613 );
2614
2615 let v4_pkt_buf = (&PAYLOAD)
2616 .into_serializer()
2617 .encapsulate(v4_udp_builder)
2618 .encapsulate(ipv4_builder)
2619 .serialize_vec_outer()
2620 .expect("Unable to serialize to v4_pkt_buf");
2621
2622 let v6_udp_builder =
2623 UdpPacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, Some(udp_src_port), udp_dst_port);
2624
2625 let v6_pkt_buf = (&PAYLOAD)
2626 .into_serializer()
2627 .encapsulate(v6_udp_builder)
2628 .encapsulate(ipv6_builder)
2629 .serialize_vec_outer()
2630 .expect("Unable to serialize to v6_pkt_buf");
2631
2632 (v4_pkt_buf, v6_pkt_buf)
2633 }
2634
2635 #[test]
2636 fn test_nat64_translate_udp() {
2637 let (expected_v4_pkt_buf, mut v6_pkt_buf) = create_udp_ipv4_and_ipv6_pkt();
2638
2639 let parsed_v6_packet =
2640 v6_pkt_buf.parse::<Ipv6Packet<_>>().expect("Unable to parse Ipv6Packet");
2641 let nat64_translation_result =
2642 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2643
2644 let serializable_pkt = assert_matches!(nat64_translation_result,
2645 Nat64TranslationResult::Forward(s) => s);
2646
2647 let translated_v4_pkt_buf = serializable_pkt
2648 .serialize_vec_outer()
2649 .expect("Unable to serialize to translated_v4_pkt_buf");
2650
2651 assert_eq!(
2652 expected_v4_pkt_buf.to_flattened_vec(),
2653 translated_v4_pkt_buf.to_flattened_vec()
2654 );
2655 }
2656
2657 #[test]
2658 fn test_nat64_translate_non_tcp_udp_icmp() {
2659 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2660
2661 let (ipv4_builder, ipv6_builder) =
2662 create_ipv4_and_ipv6_builders(Ipv4Proto::Other(59), Ipv6Proto::Other(59));
2663
2664 let expected_v4_pkt_buf = (&PAYLOAD)
2665 .into_serializer()
2666 .encapsulate(ipv4_builder)
2667 .serialize_vec_outer()
2668 .expect("Unable to serialize to expected_v4_pkt_buf");
2669
2670 let mut v6_pkt_buf = (&PAYLOAD)
2671 .into_serializer()
2672 .encapsulate(ipv6_builder)
2673 .serialize_vec_outer()
2674 .expect("Unable to serialize to v6_pkt_buf");
2675
2676 let translated_v4_pkt_buf = {
2677 let parsed_v6_packet = v6_pkt_buf
2678 .parse::<Ipv6Packet<_>>()
2679 .expect("Unable to serialize to translated_v4_pkt_buf");
2680
2681 let nat64_translation_result =
2682 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2683
2684 let serializable_pkt = assert_matches!(nat64_translation_result,
2685 Nat64TranslationResult::Forward(s) => s);
2686
2687 let translated_buf = serializable_pkt
2688 .serialize_vec_outer()
2689 .expect("Unable to serialize to translated_buf");
2690
2691 translated_buf
2692 };
2693
2694 assert_eq!(
2695 expected_v4_pkt_buf.to_flattened_vec(),
2696 translated_v4_pkt_buf.to_flattened_vec()
2697 );
2698 }
2699
2700 #[test_case(new_builder(), true; "fixed header more frags")]
2701 #[test_case(Ipv6PacketBuilderWithHbhOptions::new(
2702 new_builder(),
2703 &[HopByHopOption {
2704 action: ExtensionHeaderOptionAction::SkipAndContinue,
2705 mutable: false,
2706 data: HopByHopOptionData::RouterAlert { data: 0 },
2707 }]).unwrap(), false; "hbh last frag")]
2708 fn ipv6_packet_builder_with_fragment_header<
2709 B: Ipv6HeaderBuilder + Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>> + Debug,
2710 >(
2711 inner: B,
2712 more_fragments: bool,
2713 ) {
2714 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2715 let fragment_offset = FragmentOffset::new(13).unwrap();
2716 let identification = 0xABCDABCD;
2717 let builder = Ipv6PacketBuilderWithFragmentHeader::new(
2718 inner,
2719 fragment_offset,
2720 more_fragments,
2721 identification,
2722 );
2723 let mut serialized = PAYLOAD
2724 .into_serializer()
2725 .encapsulate(builder)
2726 .serialize_vec_outer()
2727 .unwrap()
2728 .unwrap_b();
2729 let packet = serialized.parse::<Ipv6Packet<_>>().unwrap();
2730 assert!(packet.fragment_header_present());
2731 assert_eq!(packet.proto(), Ipv6Proto::Proto(IpProto::Tcp));
2732 let fragment_data = packet
2733 .extension_hdrs
2734 .into_iter()
2735 .find_map(|ext_hdr| match ext_hdr.into_data() {
2736 Ipv6ExtensionHeaderData::Fragment { fragment_data } => Some(fragment_data),
2737 _ => None,
2738 })
2739 .unwrap();
2740 assert_eq!(fragment_data.fragment_offset(), fragment_offset);
2741 assert_eq!(fragment_data.identification(), identification);
2742 assert_eq!(fragment_data.m_flag(), more_fragments);
2743 }
2744
2745 #[test]
2748 fn extension_headers_take_from_max_body_size() {
2749 let builder = new_builder();
2750 assert_eq!(builder.constraints().max_body_len(), IPV6_MAX_PAYLOAD_LENGTH);
2751 let builder =
2752 Ipv6PacketBuilderWithFragmentHeader::new(builder, FragmentOffset::ZERO, false, 1234);
2753 assert_eq!(
2754 builder.constraints().max_body_len(),
2755 IPV6_MAX_PAYLOAD_LENGTH - IPV6_FRAGMENT_EXT_HDR_LEN
2756 );
2757 }
2758}