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: SplitByteSlice> Ipv6Header for Ipv6PacketRaw<B> {
900 fn get_fixed_header(&self) -> &FixedHeader {
901 &self.fixed_hdr
902 }
903}
904
905impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv6PacketRaw<B> {
906 type Error = IpParseError<Ipv6>;
907
908 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> Result<Self, Self::Error> {
909 let fixed_hdr = buffer
910 .take_obj_front::<FixedHeader>()
911 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for header"))?;
912 let payload_len = fixed_hdr.payload_len.get().into();
913 let _: Option<B> = buffer.len().checked_sub(payload_len).map(|padding| {
915 buffer.take_back(padding).unwrap_or_else(|| {
916 panic!("buffer.len()={} padding={}", buffer.len(), padding);
917 })
918 });
919
920 let mut extension_hdr_context = Ipv6ExtensionHeaderParsingContext::new(fixed_hdr.next_hdr);
921
922 let extension_hdrs =
923 RecordsRaw::parse_raw_with_mut_context(&mut buffer, &mut extension_hdr_context)
924 .map_incomplete(|(b, _)| b);
925
926 let body_proto = match &extension_hdrs {
927 MaybeParsed::Complete(r) => {
928 let _: &RecordsRaw<B, _> = r;
929 assert!(is_valid_next_header_upper_layer(extension_hdr_context.next_header));
950 let proto = Ipv6Proto::from(extension_hdr_context.next_header);
951 let body = MaybeParsed::new_with_min_len(
952 buffer.into_rest(),
953 payload_len.saturating_sub(extension_hdrs.len()),
954 );
955 Ok((body, proto))
956 }
957 MaybeParsed::Incomplete(b) => {
958 let _: &B = b;
959 Err(ExtHdrParseError)
960 }
961 };
962
963 Ok(Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto })
964 }
965
966 fn parse_metadata(&self) -> ParseMetadata {
967 let header_len = Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.len();
968 let body_len = self.body_proto.as_ref().map(|(b, _p)| b.len()).unwrap_or(0);
969 ParseMetadata::from_packet(header_len, body_len, 0)
970 }
971}
972
973impl<B: SplitByteSlice> Ipv6PacketRaw<B> {
974 pub fn body_proto(&self) -> Result<(MaybeParsed<&[u8], &[u8]>, Ipv6Proto), ExtHdrParseError> {
987 self.body_proto
988 .as_ref()
989 .map(|(mp, proto)| {
990 (mp.as_ref().map(|b| b.deref()).map_incomplete(|b| b.deref()), *proto)
991 })
992 .map_err(|e| *e)
993 }
994
995 pub fn body(&self) -> Result<MaybeParsed<&[u8], &[u8]>, ExtHdrParseError> {
1006 self.body_proto().map(|(body, _proto)| body)
1007 }
1008
1009 pub fn proto(&self) -> Result<Ipv6Proto, ExtHdrParseError> {
1016 self.body_proto().map(|(_body, proto)| proto)
1017 }
1018}
1019
1020impl<B: SplitByteSliceMut> Ipv6PacketRaw<B> {
1021 pub fn set_src_ip(&mut self, addr: Ipv6Addr) {
1023 self.fixed_hdr.src_ip = addr;
1024 }
1025
1026 pub fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1028 self.fixed_hdr.dst_ip = addr;
1029 }
1030}
1031
1032pub enum NextHeader {
1035 NextLayer(Ipv6Proto),
1037 Extension(Ipv6ExtHdrType),
1039}
1040
1041impl From<NextHeader> for u8 {
1042 fn from(next_hdr: NextHeader) -> Self {
1043 match next_hdr {
1044 NextHeader::NextLayer(n) => n.into(),
1045 NextHeader::Extension(e) => e.into(),
1046 }
1047 }
1048}
1049
1050mod sealed {
1051 use super::*;
1052 pub trait Ipv6HeaderBefore<T> {}
1060
1061 impl<'a, O, T> Ipv6HeaderBefore<T> for &'a O where O: Ipv6HeaderBefore<T> {}
1062
1063 pub trait Ipv6HeaderBuilder {
1065 fn fixed_header(&self) -> &Ipv6PacketBuilder;
1067
1068 fn extension_headers_len(&self) -> usize;
1071
1072 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1077 &self,
1078 buffer: &mut BV,
1079 next_header: NextHeader,
1080 payload_len: usize,
1081 );
1082 }
1083}
1084use sealed::{Ipv6HeaderBefore, Ipv6HeaderBuilder};
1085
1086impl<'a, O> Ipv6HeaderBuilder for &'a O
1087where
1088 O: Ipv6HeaderBuilder,
1089{
1090 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1091 O::fixed_header(self)
1092 }
1093
1094 fn extension_headers_len(&self) -> usize {
1095 O::extension_headers_len(self)
1096 }
1097
1098 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1099 &self,
1100 buffer: &mut BV,
1101 next_header: NextHeader,
1102 payload_len: usize,
1103 ) {
1104 O::serialize_header(self, buffer, next_header, payload_len)
1105 }
1106}
1107
1108macro_rules! impl_packet_builder {
1113 {} => {
1114 fn constraints(&self) -> PacketConstraints {
1115 let ext_headers = self.extension_headers_len();
1116 let header_len = IPV6_FIXED_HDR_LEN + ext_headers;
1117 let footer_len = 0;
1118 let min_body_len = 0;
1119 let max_body_len = IPV6_MAX_PAYLOAD_LENGTH - ext_headers;
1122 PacketConstraints::new(header_len, footer_len, min_body_len, max_body_len)
1123 }
1124
1125 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
1126 let mut bv = &mut target.header;
1127 self.serialize_header(
1128 &mut bv,
1129 NextHeader::NextLayer(self.fixed_header().proto()),
1130 body.len(),
1131 );
1132 }
1133 }
1134}
1135
1136#[derive(Debug, Clone, Eq, PartialEq)]
1138pub struct Ipv6PacketBuilder {
1139 dscp_and_ecn: DscpAndEcn,
1140 flowlabel: u32,
1141 hop_limit: u8,
1142 proto: Ipv6Proto,
1145 src_ip: Ipv6Addr,
1146 dst_ip: Ipv6Addr,
1147}
1148
1149impl Ipv6PacketBuilder {
1150 pub fn new<S: Into<Ipv6Addr>, D: Into<Ipv6Addr>>(
1156 src_ip: S,
1157 dst_ip: D,
1158 hop_limit: u8,
1159 proto: Ipv6Proto,
1160 ) -> Ipv6PacketBuilder {
1161 Ipv6PacketBuilder {
1162 dscp_and_ecn: DscpAndEcn::default(),
1163 flowlabel: 0,
1164 hop_limit,
1165 proto,
1166 src_ip: src_ip.into(),
1167 dst_ip: dst_ip.into(),
1168 }
1169 }
1170
1171 pub fn dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1174 self.dscp_and_ecn = dscp_and_ecn;
1175 }
1176
1177 pub fn flowlabel(&mut self, flowlabel: u32) {
1183 assert!(flowlabel <= 1 << 20, "invalid flowlabel: {:x}", flowlabel);
1184 self.flowlabel = flowlabel;
1185 }
1186}
1187
1188impl Ipv6HeaderBuilder for Ipv6PacketBuilder {
1189 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1190 self
1191 }
1192
1193 fn extension_headers_len(&self) -> usize {
1194 0
1195 }
1196
1197 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1198 &self,
1199 buffer: &mut BV,
1200 next_header: NextHeader,
1201 payload_len: usize,
1202 ) {
1203 buffer
1204 .write_obj_front(&FixedHeader::new(
1205 self.dscp_and_ecn,
1206 self.flowlabel,
1207 {
1208 debug_assert!(payload_len <= core::u16::MAX as usize);
1215 payload_len as u16
1216 },
1217 next_header.into(),
1218 self.hop_limit,
1219 self.src_ip,
1220 self.dst_ip,
1221 ))
1222 .expect("not enough bytes for IPv6 fixed header");
1223 }
1224}
1225
1226impl PacketBuilder for Ipv6PacketBuilder {
1227 impl_packet_builder! {}
1228}
1229
1230#[derive(Debug, Clone)]
1232pub struct Ipv6PacketBuilderWithHbhOptions<'a, I> {
1233 prefix_builder: Ipv6PacketBuilder,
1234 hbh_options: AlignedRecordSequenceBuilder<HopByHopOption<'a>, I>,
1235}
1236
1237impl<'a, I> Ipv6PacketBuilderWithHbhOptions<'a, I>
1238where
1239 I: Iterator + Clone,
1240 I::Item: Borrow<HopByHopOption<'a>>,
1241{
1242 pub fn new<T: IntoIterator<Item = I::Item, IntoIter = I>>(
1244 prefix_builder: Ipv6PacketBuilder,
1245 options: T,
1246 ) -> Option<Ipv6PacketBuilderWithHbhOptions<'a, I>> {
1247 let iter = options.into_iter();
1248 if iter
1251 .clone()
1252 .filter(|r| matches!(r.borrow().data, HopByHopOptionData::RouterAlert { .. }))
1253 .count()
1254 > 1
1255 {
1256 return None;
1257 }
1258 let hbh_options = AlignedRecordSequenceBuilder::new(2, iter);
1259 if next_multiple_of_eight(2 + hbh_options.serialized_len()) > IPV6_HBH_OPTIONS_MAX_LEN {
1261 return None;
1262 }
1263 Some(Ipv6PacketBuilderWithHbhOptions { prefix_builder, hbh_options })
1264 }
1265
1266 fn aligned_hbh_len(&self) -> usize {
1267 let opt_len = self.hbh_options.serialized_len();
1268 let hbh_len = opt_len + 2;
1269 next_multiple_of_eight(hbh_len)
1270 }
1271}
1272
1273fn next_multiple_of_eight(x: usize) -> usize {
1274 (x + 7) & (!7)
1275}
1276
1277impl IpPacketBuilder<Ipv6> for Ipv6PacketBuilder {
1278 fn new(src_ip: Ipv6Addr, dst_ip: Ipv6Addr, ttl: u8, proto: Ipv6Proto) -> Self {
1279 Ipv6PacketBuilder::new(src_ip, dst_ip, ttl, proto)
1280 }
1281
1282 fn src_ip(&self) -> Ipv6Addr {
1283 self.src_ip
1284 }
1285
1286 fn set_src_ip(&mut self, addr: Ipv6Addr) {
1287 self.src_ip = addr;
1288 }
1289
1290 fn dst_ip(&self) -> Ipv6Addr {
1291 self.dst_ip
1292 }
1293
1294 fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1295 self.dst_ip = addr;
1296 }
1297
1298 fn proto(&self) -> Ipv6Proto {
1299 self.proto
1300 }
1301
1302 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1303 self.dscp_and_ecn = dscp_and_ecn;
1304 }
1305}
1306
1307impl<'a, I> Ipv6HeaderBuilder for Ipv6PacketBuilderWithHbhOptions<'a, I>
1308where
1309 I: Iterator + Clone,
1310 I::Item: Borrow<HopByHopOption<'a>>,
1311{
1312 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1313 &self.prefix_builder
1314 }
1315
1316 fn extension_headers_len(&self) -> usize {
1317 self.prefix_builder.extension_headers_len() + self.aligned_hbh_len()
1318 }
1319
1320 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1321 &self,
1322 buffer: &mut BV,
1323 next_header: NextHeader,
1324 payload_len: usize,
1325 ) {
1326 let aligned_hbh_len = self.aligned_hbh_len();
1327 self.prefix_builder.serialize_header(
1329 buffer,
1330 NextHeader::Extension(Ipv6ExtHdrType::HopByHopOptions),
1331 payload_len + aligned_hbh_len,
1332 );
1333 let mut hbh_header = buffer.take_front(aligned_hbh_len).unwrap();
1335 let hbh_header = hbh_header.as_mut();
1336 hbh_header[0] = next_header.into();
1337 hbh_header[1] = u8::try_from((aligned_hbh_len - 8) / 8).expect("extension header too big");
1338 self.hbh_options.serialize_into(&mut hbh_header[2..]);
1339 }
1340}
1341
1342impl<'a, I> PacketBuilder for Ipv6PacketBuilderWithHbhOptions<'a, I>
1343where
1344 I: Iterator + Clone,
1345 I::Item: Borrow<HopByHopOption<'a>>,
1346{
1347 impl_packet_builder! {}
1348}
1349
1350impl<'a, I> IpPacketBuilder<Ipv6> for Ipv6PacketBuilderWithHbhOptions<'a, I>
1351where
1352 I: Iterator<Item: Borrow<HopByHopOption<'a>>> + Debug + Default + Clone,
1353{
1354 fn new(src_ip: Ipv6Addr, dst_ip: Ipv6Addr, ttl: u8, proto: Ipv6Proto) -> Self {
1355 Ipv6PacketBuilderWithHbhOptions::new(
1356 Ipv6PacketBuilder::new(src_ip, dst_ip, ttl, proto),
1357 I::default(),
1358 )
1359 .expect("packet builder with no options should be valid")
1360 }
1361
1362 fn src_ip(&self) -> Ipv6Addr {
1363 self.prefix_builder.src_ip
1364 }
1365
1366 fn set_src_ip(&mut self, addr: Ipv6Addr) {
1367 self.prefix_builder.src_ip = addr;
1368 }
1369
1370 fn dst_ip(&self) -> Ipv6Addr {
1371 self.prefix_builder.dst_ip
1372 }
1373
1374 fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1375 self.prefix_builder.dst_ip = addr;
1376 }
1377
1378 fn proto(&self) -> Ipv6Proto {
1379 self.prefix_builder.proto
1380 }
1381
1382 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1383 self.prefix_builder.set_dscp_and_ecn(dscp_and_ecn)
1384 }
1385}
1386
1387#[derive(Debug, Eq, PartialEq)]
1396pub struct Ipv6PacketBuilderWithFragmentHeader<B> {
1397 header_builder: B,
1398 fragment_offset: FragmentOffset,
1399 more_fragments: bool,
1400 identification: u32,
1401}
1402
1403impl<B: Ipv6HeaderBefore<Self>> Ipv6PacketBuilderWithFragmentHeader<B> {
1404 pub fn new(
1406 header_builder: B,
1407 fragment_offset: FragmentOffset,
1408 more_fragments: bool,
1409 identification: u32,
1410 ) -> Self {
1411 Self { header_builder, fragment_offset, more_fragments, identification }
1412 }
1413}
1414
1415impl<B> Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>> for Ipv6PacketBuilder {}
1416impl<B, I> Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>>
1417 for Ipv6PacketBuilderWithHbhOptions<'_, I>
1418{
1419}
1420
1421pub trait Ipv6PacketBuilderBeforeFragment:
1424 Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<Self>> + Ipv6HeaderBuilder + Sized
1425{
1426}
1427impl<B> Ipv6PacketBuilderBeforeFragment for B where
1428 B: Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<Self>> + Ipv6HeaderBuilder + Sized
1429{
1430}
1431
1432impl<B: Ipv6HeaderBuilder> Ipv6HeaderBuilder for Ipv6PacketBuilderWithFragmentHeader<B> {
1433 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1434 self.header_builder.fixed_header()
1435 }
1436
1437 fn extension_headers_len(&self) -> usize {
1438 self.header_builder.extension_headers_len() + IPV6_FRAGMENT_EXT_HDR_LEN
1439 }
1440
1441 fn serialize_header<BB: SplitByteSliceMut, BV: BufferViewMut<BB>>(
1442 &self,
1443 buffer: &mut BV,
1444 next_header: NextHeader,
1445 payload_len: usize,
1446 ) {
1447 let Self { header_builder, fragment_offset, more_fragments, identification } = self;
1448 let payload_len = payload_len + IPV6_FRAGMENT_EXT_HDR_LEN;
1449 header_builder.serialize_header(
1450 buffer,
1451 NextHeader::Extension(Ipv6ExtHdrType::Fragment),
1452 payload_len,
1453 );
1454 buffer.write_obj_front(&u8::from(next_header)).unwrap();
1455 let _: BB = buffer.take_front_zero(1).unwrap();
1457 let more_fragments = u16::from(*more_fragments);
1458 buffer
1459 .write_obj_front(&U16::new(fragment_offset.into_raw() << 3 | more_fragments))
1460 .unwrap();
1461 buffer.write_obj_front(&U32::new(*identification)).unwrap();
1462 }
1463}
1464
1465impl<B: Ipv6HeaderBuilder> PacketBuilder for Ipv6PacketBuilderWithFragmentHeader<B> {
1466 impl_packet_builder! {}
1467}
1468
1469pub(crate) fn reassemble_fragmented_packet<
1471 B: SplitByteSliceMut,
1472 BV: BufferViewMut<B>,
1473 I: Iterator<Item = Vec<u8>>,
1474>(
1475 mut buffer: BV,
1476 header: Vec<u8>,
1477 body_fragments: I,
1478) -> IpParseResult<Ipv6, ()> {
1479 let bytes = buffer.as_mut();
1480
1481 bytes[0..header.len()].copy_from_slice(&header[..]);
1483 let mut byte_count = header.len();
1484
1485 for p in body_fragments {
1487 bytes[byte_count..byte_count + p.len()].copy_from_slice(&p[..]);
1488 byte_count += p.len();
1489 }
1490
1491 let payload_length = byte_count - IPV6_FIXED_HDR_LEN;
1503
1504 if payload_length > usize::from(core::u16::MAX) {
1507 return debug_err!(
1508 Err(ParseError::Format.into()),
1509 "fragmented packet payload length of {} bytes is too large",
1510 payload_length
1511 );
1512 }
1513
1514 let mut header = Ref::<_, FixedHeader>::from_prefix(bytes).unwrap().0;
1517
1518 header.payload_len.set(u16::try_from(payload_length).unwrap());
1520
1521 Ok(())
1522}
1523
1524#[cfg(test)]
1525mod tests {
1526 use assert_matches::assert_matches;
1527 use packet::{Buf, FragmentedBuffer, ParseBuffer};
1528 use test_case::test_case;
1529
1530 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1531 use crate::testutil::*;
1532
1533 use super::ext_hdrs::*;
1534 use super::*;
1535
1536 const DEFAULT_SRC_IP: Ipv6Addr =
1537 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1538 const DEFAULT_DST_IP: Ipv6Addr =
1539 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1540
1541 const DEFAULT_V4_SRC_IP: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1542 const DEFAULT_V4_DST_IP: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1543
1544 #[test]
1545 fn test_parse_serialize_full_tcp() {
1546 use crate::testdata::syn_v6::*;
1547
1548 let mut buf = ETHERNET_FRAME.bytes;
1549 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1550 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1551
1552 let mut body = frame.body();
1553 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1554 verify_ipv6_packet(&packet, IPV6_PACKET);
1555
1556 let buffer = packet
1558 .body()
1559 .into_serializer()
1560 .encapsulate(packet.builder())
1561 .encapsulate(frame.builder())
1562 .serialize_vec_outer()
1563 .unwrap();
1564 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1565
1566 assert_eq!(&packet.to_vec()[..], IPV6_PACKET.bytes);
1568 }
1569
1570 #[test]
1571 fn test_parse_serialize_full_udp() {
1572 use crate::testdata::dns_request_v6::*;
1573
1574 let mut buf = ETHERNET_FRAME.bytes;
1575 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1576 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1577
1578 let mut body = frame.body();
1579 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1580 verify_ipv6_packet(&packet, IPV6_PACKET);
1581
1582 let buffer = packet
1584 .body()
1585 .into_serializer()
1586 .encapsulate(packet.builder())
1587 .encapsulate(frame.builder())
1588 .serialize_vec_outer()
1589 .unwrap();
1590 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1591
1592 assert_eq!(&packet.to_vec()[..], IPV6_PACKET.bytes);
1594 }
1595
1596 #[test]
1597 fn test_parse_serialize_with_extension_headers() {
1598 use crate::testdata::mld_router_report::*;
1601
1602 let mut buf = REPORT;
1603 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1604 assert_eq!(packet.iter_extension_hdrs().count(), 1);
1605
1606 assert_eq!(&packet.to_vec()[..], REPORT);
1611 }
1612
1613 fn fixed_hdr_to_bytes(fixed_hdr: FixedHeader) -> [u8; IPV6_FIXED_HDR_LEN] {
1614 zerocopy::transmute!(fixed_hdr)
1615 }
1616
1617 fn new_fixed_hdr() -> FixedHeader {
1619 FixedHeader::new(
1620 DscpAndEcn::new(0, 2),
1621 0x77,
1622 0,
1623 IpProto::Tcp.into(),
1624 64,
1625 DEFAULT_SRC_IP,
1626 DEFAULT_DST_IP,
1627 )
1628 }
1629
1630 #[test]
1631 fn test_parse() {
1632 let mut buf = &fixed_hdr_to_bytes(new_fixed_hdr())[..];
1633 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1634 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1635 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1636 assert_eq!(packet.flowlabel(), 0x77);
1637 assert_eq!(packet.hop_limit(), 64);
1638 assert_eq!(packet.fixed_hdr.next_hdr, IpProto::Tcp.into());
1639 assert_eq!(packet.proto(), IpProto::Tcp.into());
1640 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1641 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1642 assert_eq!(packet.body(), []);
1643 }
1644
1645 #[test]
1646 fn test_parse_with_ext_hdrs() {
1647 #[rustfmt::skip]
1648 let mut buf = [
1649 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1651 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1652
1653 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,
1668 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1669
1670 IpProto::Tcp.into(), 1, 0, 1, 0, 1, 1, 0, 1, 6, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
1680 ];
1681 let mut fixed_hdr = new_fixed_hdr();
1682 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
1683 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1684 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1685 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1686 let mut buf = &buf[..];
1687 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1688 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1689 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1690 assert_eq!(packet.flowlabel(), 0x77);
1691 assert_eq!(packet.hop_limit(), 64);
1692 assert_eq!(packet.fixed_hdr.next_hdr, Ipv6ExtHdrType::HopByHopOptions.into());
1693 assert_eq!(packet.proto(), IpProto::Tcp.into());
1694 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1695 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1696 assert_eq!(packet.body(), [1, 2, 3, 4, 5]);
1697 let ext_hdrs: Vec<Ipv6ExtensionHeader<'_>> = packet.iter_extension_hdrs().collect();
1698 assert_eq!(ext_hdrs.len(), 2);
1699 assert_eq!(ext_hdrs[0].next_header, Ipv6ExtHdrType::Routing.into());
1701 if let Ipv6ExtensionHeaderData::HopByHopOptions { options } = ext_hdrs[0].data() {
1702 assert_eq!(options.iter().count(), 0);
1704 } else {
1705 panic!("Should have matched HopByHopOptions!");
1706 }
1707
1708 assert_eq!(ext_hdrs[1].next_header, IpProto::Tcp.into());
1713 if let Ipv6ExtensionHeaderData::DestinationOptions { options } = ext_hdrs[1].data() {
1714 assert_eq!(options.iter().count(), 0);
1716 } else {
1717 panic!("Should have matched DestinationOptions!");
1718 }
1719
1720 #[rustfmt::skip]
1722 let mut buf = [
1723 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1725 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1726
1727 Ipv6Proto::NoNextHeader.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
1736 ];
1737 let mut fixed_hdr = new_fixed_hdr();
1738 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
1739 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1740 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1741 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1742 let mut buf = &buf[..];
1743 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1744 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1745 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1746 assert_eq!(packet.flowlabel(), 0x77);
1747 assert_eq!(packet.hop_limit(), 64);
1748 assert_eq!(packet.fixed_hdr.next_hdr, Ipv6ExtHdrType::HopByHopOptions.into());
1749 assert_eq!(packet.proto(), Ipv6Proto::NoNextHeader);
1750 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1751 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1752 assert_eq!(packet.body(), [1, 2, 3, 4, 5]);
1753 let ext_hdrs: Vec<Ipv6ExtensionHeader<'_>> = packet.iter_extension_hdrs().collect();
1754 assert_eq!(ext_hdrs.len(), 1);
1755 assert_eq!(ext_hdrs[0].next_header, Ipv6Proto::NoNextHeader.into());
1757 if let Ipv6ExtensionHeaderData::HopByHopOptions { options } = ext_hdrs[0].data() {
1758 assert_eq!(options.iter().count(), 0);
1760 } else {
1761 panic!("Should have matched HopByHopOptions!");
1762 }
1763 }
1764
1765 #[test]
1766 fn test_parse_error() {
1767 let mut fixed_hdr = new_fixed_hdr();
1769 fixed_hdr.version_tc_flowlabel[0] = 0x50;
1770 assert_eq!(
1771 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1772 ParseError::Format.into()
1773 );
1774
1775 let mut fixed_hdr = new_fixed_hdr();
1777 fixed_hdr.payload_len = U16::new(2);
1778 assert_eq!(
1779 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1780 ParseError::Format.into()
1781 );
1782
1783 let mut fixed_hdr = new_fixed_hdr();
1785 fixed_hdr.next_hdr = 255;
1786 assert_eq!(
1787 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1788 IpParseError::ParameterProblem {
1789 src_ip: DEFAULT_SRC_IP,
1790 dst_ip: DEFAULT_DST_IP,
1791 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1792 pointer: u32::from(NEXT_HEADER_OFFSET),
1793 must_send_icmp: false,
1794 header_len: (),
1795 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1796 }
1797 );
1798
1799 let mut fixed_hdr = new_fixed_hdr();
1801 fixed_hdr.next_hdr = Ipv4Proto::Icmp.into();
1802 assert_eq!(
1803 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1804 IpParseError::ParameterProblem {
1805 src_ip: DEFAULT_SRC_IP,
1806 dst_ip: DEFAULT_DST_IP,
1807 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1808 pointer: u32::from(NEXT_HEADER_OFFSET),
1809 must_send_icmp: false,
1810 header_len: (),
1811 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1812 }
1813 );
1814
1815 #[rustfmt::skip]
1817 let mut buf = [
1818 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1820 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1821
1822 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,
1830 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1831
1832 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
1841 ];
1842 let mut fixed_hdr = new_fixed_hdr();
1843 fixed_hdr.next_hdr = Ipv6ExtHdrType::Routing.into();
1844 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1845 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1846 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1847 let mut buf = &buf[..];
1848 assert_eq!(
1849 buf.parse::<Ipv6Packet<_>>().unwrap_err(),
1850 IpParseError::ParameterProblem {
1851 src_ip: DEFAULT_SRC_IP,
1852 dst_ip: DEFAULT_DST_IP,
1853 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1854 pointer: IPV6_FIXED_HDR_LEN as u32,
1855 must_send_icmp: false,
1856 header_len: (),
1857 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1858 }
1859 );
1860
1861 #[rustfmt::skip]
1863 let mut buf = [
1864 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1866 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1867
1868 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,
1876 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1877
1878 1, 2, 3, 4, 5,
1880 ];
1881 let mut fixed_hdr = new_fixed_hdr();
1882 fixed_hdr.next_hdr = Ipv6ExtHdrType::Routing.into();
1883 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1884 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1885 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1886 let mut buf = &buf[..];
1887 assert_eq!(
1888 buf.parse::<Ipv6Packet<_>>().unwrap_err(),
1889 IpParseError::ParameterProblem {
1890 src_ip: DEFAULT_SRC_IP,
1891 dst_ip: DEFAULT_DST_IP,
1892 code: Icmpv6ParameterProblemCode::ErroneousHeaderField,
1893 pointer: (IPV6_FIXED_HDR_LEN as u32) + 2,
1894 must_send_icmp: true,
1895 header_len: (),
1896 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1897 }
1898 );
1899 }
1900
1901 #[test]
1902 fn test_parse_all_next_header_values() {
1903 let mut buf = [
1909 0x81, 0x13, 0x27, 0xeb, 0x75, 0x92, 0x33, 0x89, 0x01, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
1910 0x03, 0x70, 0x00, 0x22, 0xf7, 0x30, 0x2c, 0x06, 0xfe, 0xc9, 0x00, 0x2d, 0x3b, 0xeb,
1911 0xad, 0x3e, 0x5c, 0x41, 0xc8, 0x70, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x11, 0x00,
1912 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x4f, 0x4f, 0x6f, 0x4f, 0x4f, 0x4f, 0x4f,
1913 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x19, 0x19,
1914 0x19, 0x19, 0x19, 0x4f, 0x4f, 0x4f, 0x4f, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1915 0x00, 0x4f, 0x4f, 0x5a, 0x5a, 0x5a, 0xc9, 0x5a, 0x46, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
1916 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0xe4, 0x5a, 0x5a, 0x5a, 0x5a,
1917 ];
1918
1919 assert_matches!(
1922 (&buf[..]).parse::<Ipv6Packet<_>>(),
1923 Err(IpParseError::ParameterProblem {
1924 src_ip: _,
1925 dst_ip: _,
1926 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1927 pointer: 0,
1928 must_send_icmp: false,
1929 header_len: (),
1930 action: IpParseErrorAction::DiscardPacket,
1931 })
1932 );
1933
1934 for b in 0u8..=255 {
1937 buf[6] = b;
1939 let _: Result<_, _> = (&buf[..]).parse::<Ipv6Packet<_>>();
1940 }
1941 }
1942
1943 #[test]
1944 fn test_partial_parse() {
1945 use core::convert::TryInto as _;
1946 use core::ops::Deref as _;
1947
1948 #[rustfmt::skip]
1950 let mut buf = [
1951 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1953 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1954
1955 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
1964 ];
1965 let len = buf.len() - IPV6_FIXED_HDR_LEN;
1966 let len = len.try_into().unwrap();
1967 let make_fixed_hdr = || {
1968 let mut fixed_hdr = new_fixed_hdr();
1969 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
1970 fixed_hdr.payload_len = U16::new(len);
1971 fixed_hdr
1972 };
1973 const MALFORMED_BYTE: u8 = 10;
1975 buf[IPV6_FIXED_HDR_LEN + 1] = MALFORMED_BYTE;
1976 let fixed_hdr = fixed_hdr_to_bytes(make_fixed_hdr());
1977 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr);
1978 let mut buf = &buf[..];
1979 let partial = buf.parse::<Ipv6PacketRaw<_>>().unwrap();
1980 let Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto } = &partial;
1981 assert_eq!(fixed_hdr.deref(), &make_fixed_hdr());
1982 assert_eq!(
1983 *extension_hdrs.as_ref().incomplete().unwrap(),
1984 [IpProto::Tcp.into(), MALFORMED_BYTE]
1985 );
1986 assert_eq!(body_proto, &Err(ExtHdrParseError));
1987 assert!(Ipv6Packet::try_from_raw(partial).is_err());
1988
1989 let mut buf = [
1991 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,
1993 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
1995 ];
1996 let make_fixed_hdr = || {
1997 let mut fixed_hdr = new_fixed_hdr();
1998 fixed_hdr.next_hdr = IpProto::Tcp.into();
1999 fixed_hdr.payload_len = U16::new(10);
2000 fixed_hdr
2001 };
2002 let fixed_hdr = fixed_hdr_to_bytes(make_fixed_hdr());
2003 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr);
2004 let mut parsebuff = &buf[..];
2005 let partial = parsebuff.parse::<Ipv6PacketRaw<_>>().unwrap();
2006 let Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto } = &partial;
2007 assert_eq!(fixed_hdr.deref(), &make_fixed_hdr());
2008 assert_eq!(extension_hdrs.as_ref().complete().unwrap().deref(), []);
2009 let (body, proto) = body_proto.unwrap();
2010 assert_eq!(body.incomplete().unwrap(), &buf[IPV6_FIXED_HDR_LEN..]);
2011 assert_eq!(proto, IpProto::Tcp.into());
2012 assert!(Ipv6Packet::try_from_raw(partial).is_err());
2013 }
2014
2015 fn new_builder() -> Ipv6PacketBuilder {
2017 Ipv6PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, 64, IpProto::Tcp.into())
2018 }
2019
2020 #[test]
2021 fn test_serialize() {
2022 let mut builder = new_builder();
2023 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
2024 builder.flowlabel(0x10405);
2025 let mut buf = (&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2026 .into_serializer()
2027 .encapsulate(builder)
2028 .serialize_vec_outer()
2029 .unwrap();
2030 assert_eq!(
2032 buf.as_ref(),
2033 &[
2034 100, 177, 4, 5, 0, 10, 6, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
2035 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, 1, 2, 3, 4,
2036 5, 6, 7, 8, 9
2037 ][..],
2038 );
2039
2040 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2041 assert_eq!(packet.dscp_and_ecn().dscp(), 0x12);
2044 assert_eq!(packet.dscp_and_ecn().ecn(), 3);
2045 assert_eq!(packet.flowlabel(), 0x10405);
2046 }
2047
2048 #[test]
2049 fn test_serialize_zeroes() {
2050 let mut buf_0 = [0; IPV6_FIXED_HDR_LEN];
2053 let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], IPV6_FIXED_HDR_LEN..)
2054 .encapsulate(new_builder())
2055 .serialize_vec_outer()
2056 .unwrap()
2057 .unwrap_a();
2058 let mut buf_1 = [0xFF; IPV6_FIXED_HDR_LEN];
2059 let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], IPV6_FIXED_HDR_LEN..)
2060 .encapsulate(new_builder())
2061 .serialize_vec_outer()
2062 .unwrap()
2063 .unwrap_a();
2064 assert_eq!(&buf_0[..], &buf_1[..]);
2065 }
2066
2067 #[test]
2068 fn test_packet_builder_proto_not_next_header() {
2069 let mut buf = (&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2073 .into_serializer()
2074 .encapsulate(
2075 Ipv6PacketBuilderWithHbhOptions::new(
2076 new_builder(),
2077 &[HopByHopOption {
2078 action: ExtensionHeaderOptionAction::SkipAndContinue,
2079 mutable: false,
2080 data: HopByHopOptionData::RouterAlert { data: 0 },
2081 }],
2082 )
2083 .unwrap(),
2084 )
2085 .serialize_vec_outer()
2086 .unwrap();
2087 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2088 assert_eq!(packet.proto(), IpProto::Tcp.into());
2089 assert_eq!(packet.next_header(), Ipv6ExtHdrType::HopByHopOptions.into());
2090 }
2091
2092 #[test]
2093 #[should_panic(expected = "SizeLimitExceeded, Nested { inner: Buf { buf:")]
2094 fn test_serialize_panic_packet_length() {
2095 let _: Buf<&mut [u8]> = Buf::new(&mut [0; 1 << 16][..], ..)
2098 .encapsulate(new_builder())
2099 .serialize_vec_outer()
2100 .unwrap()
2101 .unwrap_a();
2102 }
2103
2104 #[test]
2105 #[should_panic(expected = "packet must have at least one extension header")]
2106 fn test_copy_header_bytes_for_fragment_without_ext_hdrs() {
2107 let mut buf = &fixed_hdr_to_bytes(new_fixed_hdr())[..];
2108 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2109 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2110 }
2111
2112 #[test]
2113 #[should_panic(expected = "exhausted all extension headers without finding fragment header")]
2114 fn test_copy_header_bytes_for_fragment_with_1_ext_hdr_no_fragment() {
2115 #[rustfmt::skip]
2116 let mut buf = [
2117 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2120
2121 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2130 ];
2131 let mut fixed_hdr = new_fixed_hdr();
2132 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2133 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2134 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2135 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2136 let mut buf = &buf[..];
2137 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2138 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2139 }
2140
2141 #[test]
2142 #[should_panic(expected = "exhausted all extension headers without finding fragment header")]
2143 fn test_copy_header_bytes_for_fragment_with_2_ext_hdr_no_fragment() {
2144 #[rustfmt::skip]
2145 let mut buf = [
2146 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2148 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2149
2150 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,
2167 ];
2168 let mut fixed_hdr = new_fixed_hdr();
2169 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2170 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2171 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2172 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2173 let mut buf = &buf[..];
2174 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2175 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2176 }
2177
2178 #[test]
2179 fn test_copy_header_bytes_for_fragment() {
2180 #[rustfmt::skip]
2185 let mut bytes = [
2186 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2188 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2189
2190 IpProto::Tcp.into(), 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5,
2198 ];
2199 let mut fixed_hdr = new_fixed_hdr();
2200 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2201 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2202 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2203 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2204 let mut buf = &bytes[..];
2205 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2206 let copied_bytes = packet.copy_header_bytes_for_fragment();
2207 bytes[6] = IpProto::Tcp.into();
2208 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN]);
2209
2210 #[rustfmt::skip]
2215 let mut bytes = [
2216 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2218 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2219
2220 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,
2235 ];
2236 let mut fixed_hdr = new_fixed_hdr();
2237 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2238 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2239 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2240 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2241 let mut buf = &bytes[..];
2242 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2243 let copied_bytes = packet.copy_header_bytes_for_fragment();
2244 bytes[IPV6_FIXED_HDR_LEN] = IpProto::Tcp.into();
2245 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN + 8]);
2246
2247 #[rustfmt::skip]
2252 let mut bytes = [
2253 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2255 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2256
2257 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,
2280 ];
2281 let mut fixed_hdr = new_fixed_hdr();
2282 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2283 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2284 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2285 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2286 let mut buf = &bytes[..];
2287 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2288 let copied_bytes = packet.copy_header_bytes_for_fragment();
2289 bytes[IPV6_FIXED_HDR_LEN + 8] = IpProto::Tcp.into();
2290 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN + 24]);
2291
2292 #[rustfmt::skip]
2297 let mut bytes = [
2298 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2300 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2301
2302 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,
2318 ];
2319 let mut fixed_hdr = new_fixed_hdr();
2320 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2321 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2322 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2323 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2324 let mut buf = &bytes[..];
2325 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2326 let copied_bytes = packet.copy_header_bytes_for_fragment();
2327 let mut expected_bytes = Vec::new();
2328 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2329 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2330 expected_bytes[6] = Ipv6ExtHdrType::DestinationOptions.into();
2331 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2332
2333 #[rustfmt::skip]
2338 let mut bytes = [
2339 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2341 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2342
2343 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,
2365 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2366
2367 1, 2, 3, 4, 5,
2369 ];
2370 let mut fixed_hdr = new_fixed_hdr();
2371 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2372 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2373 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2374 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2375 let mut buf = &bytes[..];
2376 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2377 let copied_bytes = packet.copy_header_bytes_for_fragment();
2378 let mut expected_bytes = Vec::new();
2379 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2380 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2381 expected_bytes[6] = Ipv6ExtHdrType::DestinationOptions.into();
2382 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2383
2384 #[rustfmt::skip]
2389 let mut bytes = [
2390 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2392 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2393
2394 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,
2417 ];
2418 let mut fixed_hdr = new_fixed_hdr();
2419 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2420 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2421 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2422 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2423 let mut buf = &bytes[..];
2424 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2425 let copied_bytes = packet.copy_header_bytes_for_fragment();
2426 let mut expected_bytes = Vec::new();
2427 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN + 8]);
2428 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 16..bytes.len() - 5]);
2429 expected_bytes[IPV6_FIXED_HDR_LEN] = Ipv6ExtHdrType::DestinationOptions.into();
2430 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2431
2432 #[rustfmt::skip]
2437 let mut bytes = [
2438 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2440 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2441
2442 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,
2456 ];
2457 let mut fixed_hdr = new_fixed_hdr();
2458 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2459 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2460 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2461 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2462 let mut buf = &bytes[..];
2463 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2464 let copied_bytes = packet.copy_header_bytes_for_fragment();
2465 let mut expected_bytes = Vec::new();
2466 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2467 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2468 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2469 }
2470
2471 #[test]
2472 fn test_next_multiple_of_eight() {
2473 for x in 0usize..=IPV6_HBH_OPTIONS_MAX_LEN {
2474 let y = next_multiple_of_eight(x);
2475 assert_eq!(y % 8, 0);
2476 assert!(y >= x);
2477 if x % 8 == 0 {
2478 assert_eq!(x, y);
2479 } else {
2480 assert_eq!(x + (8 - x % 8), y);
2481 }
2482 }
2483 }
2484
2485 fn create_ipv4_and_ipv6_builders(
2486 proto_v4: Ipv4Proto,
2487 proto_v6: Ipv6Proto,
2488 ) -> (Ipv4PacketBuilder, Ipv6PacketBuilder) {
2489 const IP_DSCP_AND_ECN: DscpAndEcn = DscpAndEcn::new(0x12, 3);
2490 const IP_TTL: u8 = 64;
2491
2492 let mut ipv4_builder =
2493 Ipv4PacketBuilder::new(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP, IP_TTL, proto_v4);
2494 ipv4_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
2495 ipv4_builder.df_flag(false);
2496 ipv4_builder.mf_flag(false);
2497 ipv4_builder.fragment_offset(FragmentOffset::ZERO);
2498
2499 let mut ipv6_builder =
2500 Ipv6PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, IP_TTL, proto_v6);
2501 ipv6_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
2502 ipv6_builder.flowlabel(0x456);
2503
2504 (ipv4_builder, ipv6_builder)
2505 }
2506
2507 fn create_tcp_ipv4_and_ipv6_pkt(
2508 ) -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
2509 use crate::tcp::TcpSegmentBuilder;
2510 use core::num::NonZeroU16;
2511
2512 let tcp_src_port: NonZeroU16 = NonZeroU16::new(20).unwrap();
2513 let tcp_dst_port: NonZeroU16 = NonZeroU16::new(30).unwrap();
2514 const TCP_SEQ_NUM: u32 = 4321;
2515 const TCP_ACK_NUM: Option<u32> = Some(1234);
2516 const TCP_WINDOW_SIZE: u16 = 12345;
2517 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2518
2519 let (ipv4_builder, ipv6_builder) =
2520 create_ipv4_and_ipv6_builders(IpProto::Tcp.into(), IpProto::Tcp.into());
2521
2522 let tcp_builder = TcpSegmentBuilder::new(
2523 DEFAULT_V4_SRC_IP,
2524 DEFAULT_V4_DST_IP,
2525 tcp_src_port,
2526 tcp_dst_port,
2527 TCP_SEQ_NUM,
2528 TCP_ACK_NUM,
2529 TCP_WINDOW_SIZE,
2530 );
2531
2532 let v4_pkt_buf = (&PAYLOAD)
2533 .into_serializer()
2534 .encapsulate(tcp_builder)
2535 .encapsulate(ipv4_builder)
2536 .serialize_vec_outer()
2537 .expect("Failed to serialize to v4_pkt_buf");
2538
2539 let v6_tcp_builder = TcpSegmentBuilder::new(
2540 DEFAULT_SRC_IP,
2541 DEFAULT_DST_IP,
2542 tcp_src_port,
2543 tcp_dst_port,
2544 TCP_SEQ_NUM,
2545 TCP_ACK_NUM,
2546 TCP_WINDOW_SIZE,
2547 );
2548
2549 let v6_pkt_buf = (&PAYLOAD)
2550 .into_serializer()
2551 .encapsulate(v6_tcp_builder)
2552 .encapsulate(ipv6_builder)
2553 .serialize_vec_outer()
2554 .expect("Failed to serialize to v4_pkt_buf");
2555
2556 (v4_pkt_buf, v6_pkt_buf)
2557 }
2558
2559 #[test]
2560 fn test_nat64_translate_tcp() {
2561 let (expected_v4_pkt_buf, mut v6_pkt_buf) = create_tcp_ipv4_and_ipv6_pkt();
2562
2563 let parsed_v6_packet =
2564 v6_pkt_buf.parse::<Ipv6Packet<_>>().expect("Failed to parse v6_pkt_buf");
2565 let nat64_translation_result =
2566 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2567
2568 let serializable_pkt =
2569 assert_matches!(nat64_translation_result, Nat64TranslationResult::Forward(s) => s);
2570
2571 let translated_v4_pkt_buf = serializable_pkt
2572 .serialize_vec_outer()
2573 .expect("Failed to serialize to translated_v4_pkt_buf");
2574
2575 assert_eq!(
2576 expected_v4_pkt_buf.to_flattened_vec(),
2577 translated_v4_pkt_buf.to_flattened_vec()
2578 );
2579 }
2580
2581 fn create_udp_ipv4_and_ipv6_pkt(
2582 ) -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
2583 use crate::udp::UdpPacketBuilder;
2584 use core::num::NonZeroU16;
2585
2586 let udp_src_port: NonZeroU16 = NonZeroU16::new(35000).unwrap();
2587 let udp_dst_port: NonZeroU16 = NonZeroU16::new(53).unwrap();
2588 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2589
2590 let (ipv4_builder, ipv6_builder) =
2591 create_ipv4_and_ipv6_builders(IpProto::Udp.into(), IpProto::Udp.into());
2592
2593 let v4_udp_builder = UdpPacketBuilder::new(
2594 DEFAULT_V4_SRC_IP,
2595 DEFAULT_V4_DST_IP,
2596 Some(udp_src_port),
2597 udp_dst_port,
2598 );
2599
2600 let v4_pkt_buf = (&PAYLOAD)
2601 .into_serializer()
2602 .encapsulate(v4_udp_builder)
2603 .encapsulate(ipv4_builder)
2604 .serialize_vec_outer()
2605 .expect("Unable to serialize to v4_pkt_buf");
2606
2607 let v6_udp_builder =
2608 UdpPacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, Some(udp_src_port), udp_dst_port);
2609
2610 let v6_pkt_buf = (&PAYLOAD)
2611 .into_serializer()
2612 .encapsulate(v6_udp_builder)
2613 .encapsulate(ipv6_builder)
2614 .serialize_vec_outer()
2615 .expect("Unable to serialize to v6_pkt_buf");
2616
2617 (v4_pkt_buf, v6_pkt_buf)
2618 }
2619
2620 #[test]
2621 fn test_nat64_translate_udp() {
2622 let (expected_v4_pkt_buf, mut v6_pkt_buf) = create_udp_ipv4_and_ipv6_pkt();
2623
2624 let parsed_v6_packet =
2625 v6_pkt_buf.parse::<Ipv6Packet<_>>().expect("Unable to parse Ipv6Packet");
2626 let nat64_translation_result =
2627 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2628
2629 let serializable_pkt = assert_matches!(nat64_translation_result,
2630 Nat64TranslationResult::Forward(s) => s);
2631
2632 let translated_v4_pkt_buf = serializable_pkt
2633 .serialize_vec_outer()
2634 .expect("Unable to serialize to translated_v4_pkt_buf");
2635
2636 assert_eq!(
2637 expected_v4_pkt_buf.to_flattened_vec(),
2638 translated_v4_pkt_buf.to_flattened_vec()
2639 );
2640 }
2641
2642 #[test]
2643 fn test_nat64_translate_non_tcp_udp_icmp() {
2644 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2645
2646 let (ipv4_builder, ipv6_builder) =
2647 create_ipv4_and_ipv6_builders(Ipv4Proto::Other(59), Ipv6Proto::Other(59));
2648
2649 let expected_v4_pkt_buf = (&PAYLOAD)
2650 .into_serializer()
2651 .encapsulate(ipv4_builder)
2652 .serialize_vec_outer()
2653 .expect("Unable to serialize to expected_v4_pkt_buf");
2654
2655 let mut v6_pkt_buf = (&PAYLOAD)
2656 .into_serializer()
2657 .encapsulate(ipv6_builder)
2658 .serialize_vec_outer()
2659 .expect("Unable to serialize to v6_pkt_buf");
2660
2661 let translated_v4_pkt_buf = {
2662 let parsed_v6_packet = v6_pkt_buf
2663 .parse::<Ipv6Packet<_>>()
2664 .expect("Unable to serialize to translated_v4_pkt_buf");
2665
2666 let nat64_translation_result =
2667 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2668
2669 let serializable_pkt = assert_matches!(nat64_translation_result,
2670 Nat64TranslationResult::Forward(s) => s);
2671
2672 let translated_buf = serializable_pkt
2673 .serialize_vec_outer()
2674 .expect("Unable to serialize to translated_buf");
2675
2676 translated_buf
2677 };
2678
2679 assert_eq!(
2680 expected_v4_pkt_buf.to_flattened_vec(),
2681 translated_v4_pkt_buf.to_flattened_vec()
2682 );
2683 }
2684
2685 #[test_case(new_builder(), true; "fixed header more frags")]
2686 #[test_case(Ipv6PacketBuilderWithHbhOptions::new(
2687 new_builder(),
2688 &[HopByHopOption {
2689 action: ExtensionHeaderOptionAction::SkipAndContinue,
2690 mutable: false,
2691 data: HopByHopOptionData::RouterAlert { data: 0 },
2692 }]).unwrap(), false; "hbh last frag")]
2693 fn ipv6_packet_builder_with_fragment_header<
2694 B: Ipv6HeaderBuilder + Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>> + Debug,
2695 >(
2696 inner: B,
2697 more_fragments: bool,
2698 ) {
2699 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2700 let fragment_offset = FragmentOffset::new(13).unwrap();
2701 let identification = 0xABCDABCD;
2702 let builder = Ipv6PacketBuilderWithFragmentHeader::new(
2703 inner,
2704 fragment_offset,
2705 more_fragments,
2706 identification,
2707 );
2708 let mut serialized = PAYLOAD
2709 .into_serializer()
2710 .encapsulate(builder)
2711 .serialize_vec_outer()
2712 .unwrap()
2713 .unwrap_b();
2714 let packet = serialized.parse::<Ipv6Packet<_>>().unwrap();
2715 assert!(packet.fragment_header_present());
2716 assert_eq!(packet.proto(), Ipv6Proto::Proto(IpProto::Tcp));
2717 let fragment_data = packet
2718 .extension_hdrs
2719 .into_iter()
2720 .find_map(|ext_hdr| match ext_hdr.into_data() {
2721 Ipv6ExtensionHeaderData::Fragment { fragment_data } => Some(fragment_data),
2722 _ => None,
2723 })
2724 .unwrap();
2725 assert_eq!(fragment_data.fragment_offset(), fragment_offset);
2726 assert_eq!(fragment_data.identification(), identification);
2727 assert_eq!(fragment_data.m_flag(), more_fragments);
2728 }
2729
2730 #[test]
2733 fn extension_headers_take_from_max_body_size() {
2734 let builder = new_builder();
2735 assert_eq!(builder.constraints().max_body_len(), IPV6_MAX_PAYLOAD_LENGTH);
2736 let builder =
2737 Ipv6PacketBuilderWithFragmentHeader::new(builder, FragmentOffset::ZERO, false, 1234);
2738 assert_eq!(
2739 builder.constraints().max_body_len(),
2740 IPV6_MAX_PAYLOAD_LENGTH - IPV6_FRAGMENT_EXT_HDR_LEN
2741 );
2742 }
2743}