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, PartialPacketBuilder, ReusableBuffer, SerializeError,
25 SerializeTarget, Serializer,
26};
27use zerocopy::byteorder::network_endian::{U16, U32};
28use zerocopy::{
29 FromBytes, Immutable, IntoBytes, KnownLayout, Ref, SplitByteSlice, SplitByteSliceMut, Unaligned,
30};
31
32use crate::error::{IpParseError, IpParseErrorAction, IpParseResult, ParseError};
33use crate::icmp::Icmpv6ParameterProblemCode;
34use crate::ip::{
35 DscpAndEcn, FragmentOffset, IpExt, IpPacketBuilder, IpProto, Ipv4Proto, Ipv6ExtHdrType,
36 Ipv6Proto, Nat64Error, Nat64TranslationResult,
37};
38use crate::ipv4::{Ipv4PacketBuilder, HDR_PREFIX_LEN};
39use crate::tcp::{TcpParseArgs, TcpSegment};
40use crate::udp::{UdpPacket, UdpParseArgs};
41
42use ext_hdrs::{
43 is_valid_next_header, is_valid_next_header_upper_layer, ExtensionHeaderOptionAction,
44 HopByHopOption, HopByHopOptionData, Ipv6ExtensionHeader, Ipv6ExtensionHeaderData,
45 Ipv6ExtensionHeaderImpl, Ipv6ExtensionHeaderParsingContext, Ipv6ExtensionHeaderParsingError,
46 IPV6_FRAGMENT_EXT_HDR_LEN,
47};
48
49pub const IPV6_FIXED_HDR_LEN: usize = 40;
51
52pub const IPV6_PAYLOAD_LEN_BYTE_RANGE: Range<usize> = 4..6;
55
56const NEXT_HEADER_OFFSET: u8 = 6;
58
59const IPV6_HBH_OPTIONS_MAX_LEN: usize = (core::u8::MAX as usize) * 8 + 8;
63
64const IPV6_MAX_PAYLOAD_LENGTH: usize = core::u16::MAX as usize;
71
72fn ext_hdr_err_fn(hdr: &FixedHeader, err: Ipv6ExtensionHeaderParsingError) -> IpParseError<Ipv6> {
75 match err {
94 Ipv6ExtensionHeaderParsingError::ErroneousHeaderField {
95 pointer,
96 must_send_icmp,
97 header_len: _,
98 } => {
99 let (pointer, action) = match pointer.checked_add(IPV6_FIXED_HDR_LEN as u32) {
100 None => (0, IpParseErrorAction::DiscardPacket),
104 Some(p) => (p, IpParseErrorAction::DiscardPacketSendIcmpNoMulticast),
108 };
109
110 IpParseError::ParameterProblem {
111 src_ip: hdr.src_ip,
112 dst_ip: hdr.dst_ip,
113 code: Icmpv6ParameterProblemCode::ErroneousHeaderField,
114 pointer,
115 must_send_icmp,
116 header_len: (),
117 action,
118 }
119 }
120 Ipv6ExtensionHeaderParsingError::UnrecognizedNextHeader {
121 pointer,
122 must_send_icmp,
123 header_len: _,
124 } => {
125 let (pointer, action) = match pointer.checked_add(IPV6_FIXED_HDR_LEN as u32) {
126 None => (0, IpParseErrorAction::DiscardPacket),
127 Some(p) => (p, IpParseErrorAction::DiscardPacketSendIcmpNoMulticast),
128 };
129
130 IpParseError::ParameterProblem {
131 src_ip: hdr.src_ip,
132 dst_ip: hdr.dst_ip,
133 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
134 pointer,
135 must_send_icmp,
136 header_len: (),
137 action,
138 }
139 }
140 Ipv6ExtensionHeaderParsingError::UnrecognizedOption {
141 pointer,
142 must_send_icmp,
143 header_len: _,
144 action,
145 } => {
146 let (pointer, action) = match pointer.checked_add(IPV6_FIXED_HDR_LEN as u32) {
147 None => (0, IpParseErrorAction::DiscardPacket),
148 Some(p) => {
149 let action = match action {
150 ExtensionHeaderOptionAction::SkipAndContinue => unreachable!(
151 "Should never end up here because this action should never result in an error"
152 ),
153 ExtensionHeaderOptionAction::DiscardPacket => IpParseErrorAction::DiscardPacket,
154 ExtensionHeaderOptionAction::DiscardPacketSendIcmp => {
155 IpParseErrorAction::DiscardPacketSendIcmp
156 }
157 ExtensionHeaderOptionAction::DiscardPacketSendIcmpNoMulticast => {
158 IpParseErrorAction::DiscardPacketSendIcmpNoMulticast
159 }
160 };
161
162 (p, action)
163 }
164 };
165
166 IpParseError::ParameterProblem {
167 src_ip: hdr.src_ip,
168 dst_ip: hdr.dst_ip,
169 code: Icmpv6ParameterProblemCode::UnrecognizedIpv6Option,
170 pointer,
171 must_send_icmp,
172 header_len: (),
173 action,
174 }
175 }
176 Ipv6ExtensionHeaderParsingError::BufferExhausted
177 | Ipv6ExtensionHeaderParsingError::MalformedData => {
178 IpParseError::Parse { error: ParseError::Format }
181 }
182 }
183}
184
185#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
187#[repr(C)]
188pub struct FixedHeader {
189 version_tc_flowlabel: [u8; 4],
190 payload_len: U16,
191 next_hdr: u8,
192 hop_limit: u8,
193 src_ip: Ipv6Addr,
194 dst_ip: Ipv6Addr,
195}
196
197const IP_VERSION: u8 = 6;
198const VERSION_OFFSET: u8 = 4;
199const FLOW_LABEL_MAX: u32 = (1 << 20) - 1;
200
201impl FixedHeader {
202 #[allow(clippy::too_many_arguments)]
203 fn new(
204 dscp_and_ecn: DscpAndEcn,
205 flow_label: u32,
206 payload_len: u16,
207 next_hdr: u8,
208 hop_limit: u8,
209 src_ip: Ipv6Addr,
210 dst_ip: Ipv6Addr,
211 ) -> FixedHeader {
212 debug_assert!(flow_label <= FLOW_LABEL_MAX);
213
214 let traffic_class = dscp_and_ecn.raw();
215 FixedHeader {
216 version_tc_flowlabel: [
217 IP_VERSION << VERSION_OFFSET | traffic_class >> 4,
218 (traffic_class << 4) | ((flow_label >> 16) as u8),
219 (flow_label >> 8) as u8,
220 flow_label as u8,
221 ],
222 payload_len: U16::new(payload_len),
223 next_hdr,
224 hop_limit,
225 src_ip,
226 dst_ip,
227 }
228 }
229
230 fn version(&self) -> u8 {
231 self.version_tc_flowlabel[0] >> 4
232 }
233
234 fn dscp_and_ecn(&self) -> DscpAndEcn {
235 ((self.version_tc_flowlabel[0] & 0xF) << 4 | self.version_tc_flowlabel[1] >> 4).into()
236 }
237
238 fn flowlabel(&self) -> u32 {
239 (u32::from(self.version_tc_flowlabel[1]) & 0xF) << 16
240 | u32::from(self.version_tc_flowlabel[2]) << 8
241 | u32::from(self.version_tc_flowlabel[3])
242 }
243}
244
245pub trait Ipv6Header {
250 fn get_fixed_header(&self) -> &FixedHeader;
252
253 fn hop_limit(&self) -> u8 {
255 self.get_fixed_header().hop_limit
256 }
257
258 fn next_header(&self) -> u8 {
260 self.get_fixed_header().next_hdr
261 }
262
263 fn src_ip(&self) -> Ipv6Addr {
265 self.get_fixed_header().src_ip
266 }
267
268 fn dst_ip(&self) -> Ipv6Addr {
270 self.get_fixed_header().dst_ip
271 }
272
273 fn dscp_and_ecn(&self) -> DscpAndEcn {
276 self.get_fixed_header().dscp_and_ecn()
277 }
278}
279
280impl Ipv6Header for FixedHeader {
281 fn get_fixed_header(&self) -> &FixedHeader {
282 self
283 }
284}
285
286pub struct Ipv6Packet<B> {
292 fixed_hdr: Ref<B, FixedHeader>,
293 extension_hdrs: Records<B, Ipv6ExtensionHeaderImpl>,
294 body: B,
295 proto: Ipv6Proto,
296}
297
298impl<B: SplitByteSlice, I: IpExt> GenericOverIp<I> for Ipv6Packet<B> {
299 type Type = <I as IpExt>::Packet<B>;
300}
301
302impl<B: SplitByteSlice> Ipv6Header for Ipv6Packet<B> {
303 fn get_fixed_header(&self) -> &FixedHeader {
304 &self.fixed_hdr
305 }
306}
307
308impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv6Packet<B> {
309 type Error = IpParseError<Ipv6>;
310
311 fn parse_metadata(&self) -> ParseMetadata {
312 let header_len = Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.bytes().len();
313 ParseMetadata::from_packet(header_len, self.body.len(), 0)
314 }
315
316 fn parse<BV: BufferView<B>>(buffer: BV, _args: ()) -> IpParseResult<Ipv6, Self> {
317 Ipv6PacketRaw::parse(buffer, ()).and_then(Ipv6Packet::try_from_raw)
318 }
319}
320
321impl<B: SplitByteSlice> FromRaw<Ipv6PacketRaw<B>, ()> for Ipv6Packet<B> {
322 type Error = IpParseError<Ipv6>;
323
324 fn try_from_raw_with(raw: Ipv6PacketRaw<B>, _args: ()) -> Result<Self, Self::Error> {
325 let fixed_hdr = raw.fixed_hdr;
326
327 if !is_valid_next_header(fixed_hdr.next_hdr, true) {
330 return debug_err!(
331 Err(IpParseError::ParameterProblem {
332 src_ip: fixed_hdr.src_ip,
333 dst_ip: fixed_hdr.dst_ip,
334 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
335 pointer: u32::from(NEXT_HEADER_OFFSET),
336 must_send_icmp: false,
337 header_len: (),
338 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
339 }),
340 "Unrecognized next header value"
341 );
342 }
343
344 let extension_hdrs = match raw.extension_hdrs {
345 MaybeParsed::Complete(v) => {
346 Records::try_from_raw(v).map_err(|e| ext_hdr_err_fn(&fixed_hdr, e))?
347 }
348 MaybeParsed::Incomplete(_) => {
349 return debug_err!(
350 Err(ParseError::Format.into()),
351 "Incomplete IPv6 extension headers"
352 );
353 }
354 };
355
356 let (body, proto) =
360 raw.body_proto.expect("Unable to retrieve Ipv6Proto or MaybeParsed body from raw");
361 debug_assert!(is_valid_next_header_upper_layer(proto.into()));
362
363 let body = match body {
364 MaybeParsed::Complete(b) => b,
365 MaybeParsed::Incomplete(_b) => {
366 return debug_err!(Err(ParseError::Format.into()), "IPv6 body unretrievable.");
367 }
368 };
369
370 if extension_hdrs.bytes().len() + body.len() != usize::from(fixed_hdr.payload_len.get()) {
375 return debug_err!(
376 Err(ParseError::Format.into()),
377 "Payload len does not match body and extension headers"
378 );
379 }
380
381 if fixed_hdr.version() != 6 {
383 return debug_err!(
384 Err(ParseError::Format.into()),
385 "unexpected IP version: {}",
386 fixed_hdr.version()
387 );
388 }
389
390 Ok(Ipv6Packet { fixed_hdr, extension_hdrs, body, proto })
391 }
392}
393
394impl<B: SplitByteSlice> Ipv6Packet<B> {
395 pub fn iter_extension_hdrs(&self) -> impl Iterator<Item = Ipv6ExtensionHeader<'_>> {
397 self.extension_hdrs.iter()
398 }
399
400 pub fn body(&self) -> &[u8] {
402 &self.body
403 }
404
405 pub fn dscp_and_ecn(&self) -> DscpAndEcn {
408 self.fixed_hdr.dscp_and_ecn()
409 }
410
411 pub fn flowlabel(&self) -> u32 {
413 self.fixed_hdr.flowlabel()
414 }
415
416 pub fn proto(&self) -> Ipv6Proto {
422 self.proto
423 }
424
425 pub fn src_ipv6(&self) -> Option<Ipv6SourceAddr> {
432 Ipv6SourceAddr::new(self.fixed_hdr.src_ip)
433 }
434
435 pub fn copy_header_bytes_for_fragment(&self) -> Vec<u8> {
446 let expected_bytes_len = self.header_len() - IPV6_FRAGMENT_EXT_HDR_LEN;
449 let mut bytes = Vec::with_capacity(expected_bytes_len);
450
451 bytes.extend_from_slice(Ref::bytes(&self.fixed_hdr));
452
453 let mut iter = self.extension_hdrs.iter();
457
458 let ext_hdr = iter.next().expect("packet must have at least one extension header");
462
463 if self.fixed_hdr.next_hdr == Ipv6ExtHdrType::Fragment.into() {
464 bytes[6] = ext_hdr.next_header;
470
471 bytes.extend_from_slice(&self.extension_hdrs.bytes()[IPV6_FRAGMENT_EXT_HDR_LEN..]);
473 } else {
474 let mut ext_hdr = ext_hdr;
475 let mut ext_hdr_start = 0;
476 let mut ext_hdr_end = iter.context().bytes_parsed;
477
478 loop {
484 let next_ext_hdr = iter
490 .next()
491 .expect("exhausted all extension headers without finding fragment header");
492
493 if let Ipv6ExtensionHeaderData::Fragment { .. } = next_ext_hdr.data() {
494 let fragment_hdr_end = ext_hdr_end + IPV6_FRAGMENT_EXT_HDR_LEN;
501 assert_eq!(fragment_hdr_end, iter.context().bytes_parsed);
502
503 let extension_hdr_bytes = self.extension_hdrs.bytes();
504
505 bytes.extend_from_slice(&extension_hdr_bytes[..ext_hdr_end]);
507
508 bytes.extend_from_slice(&extension_hdr_bytes[fragment_hdr_end..]);
510
511 match ext_hdr.data() {
514 Ipv6ExtensionHeaderData::HopByHopOptions { .. }
517 | Ipv6ExtensionHeaderData::DestinationOptions { .. } => {
518 bytes[IPV6_FIXED_HDR_LEN+ext_hdr_start] = next_ext_hdr.next_header;
519 }
520 Ipv6ExtensionHeaderData::Fragment { .. } => unreachable!("If we had a fragment header before `ext_hdr`, we should have used that instead"),
521 }
522
523 break;
524 }
525
526 ext_hdr = next_ext_hdr;
527 ext_hdr_start = ext_hdr_end;
528 ext_hdr_end = iter.context().bytes_parsed;
529 }
530 }
531
532 assert_eq!(bytes.len(), expected_bytes_len);
534 bytes
535 }
536
537 fn header_len(&self) -> usize {
538 Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.bytes().len()
539 }
540
541 fn fragment_header_present(&self) -> bool {
542 for ext_hdr in self.extension_hdrs.iter() {
543 if matches!(ext_hdr.data(), Ipv6ExtensionHeaderData::Fragment { .. }) {
544 return true;
545 }
546 }
547 false
548 }
549
550 pub fn builder(&self) -> Ipv6PacketBuilder {
552 Ipv6PacketBuilder {
553 dscp_and_ecn: self.dscp_and_ecn(),
554 flowlabel: self.flowlabel(),
555 hop_limit: self.hop_limit(),
556 proto: self.proto(),
557 src_ip: self.src_ip(),
558 dst_ip: self.dst_ip(),
559 }
560 }
561
562 pub fn nat64_translate(
588 &self,
589 v4_src_addr: Ipv4Addr,
590 v4_dst_addr: Ipv4Addr,
591 ) -> Nat64TranslationResult<impl Serializer<Buffer = EmptyBuf> + Debug + '_, Nat64Error> {
592 #[derive(Debug)]
595 enum Nat64Serializer<T, U, O> {
596 Tcp(T),
597 Udp(U),
598 Other(O),
599 }
600
601 impl<T, U, O> Serializer for Nat64Serializer<T, U, O>
602 where
603 T: Serializer<Buffer = EmptyBuf>,
604 U: Serializer<Buffer = EmptyBuf>,
605 O: Serializer<Buffer = EmptyBuf>,
606 {
607 type Buffer = EmptyBuf;
608 fn serialize<B, P>(
609 self,
610 outer: PacketConstraints,
611 provider: P,
612 ) -> Result<B, (SerializeError<P::Error>, Self)>
613 where
614 B: GrowBufferMut,
615 P: BufferProvider<Self::Buffer, B>,
616 {
617 match self {
618 Nat64Serializer::Tcp(serializer) => serializer
619 .serialize(outer, provider)
620 .map_err(|(err, ser)| (err, Nat64Serializer::Tcp(ser))),
621 Nat64Serializer::Udp(serializer) => serializer
622 .serialize(outer, provider)
623 .map_err(|(err, ser)| (err, Nat64Serializer::Udp(ser))),
624 Nat64Serializer::Other(serializer) => serializer
625 .serialize(outer, provider)
626 .map_err(|(err, ser)| (err, Nat64Serializer::Other(ser))),
627 }
628 }
629
630 fn serialize_new_buf<B: ReusableBuffer, A: BufferAlloc<B>>(
631 &self,
632 outer: PacketConstraints,
633 alloc: A,
634 ) -> Result<B, SerializeError<A::Error>> {
635 match self {
636 Nat64Serializer::Tcp(serializer) => serializer.serialize_new_buf(outer, alloc),
637 Nat64Serializer::Udp(serializer) => serializer.serialize_new_buf(outer, alloc),
638 Nat64Serializer::Other(serializer) => {
639 serializer.serialize_new_buf(outer, alloc)
640 }
641 }
642 }
643 }
644
645 if self.fragment_header_present() {
648 return Nat64TranslationResult::Err(Nat64Error::NotImplemented);
649 }
650
651 let v4_builder = |v4_proto| {
652 let mut builder =
653 Ipv4PacketBuilder::new(v4_src_addr, v4_dst_addr, self.hop_limit(), v4_proto);
654 builder.dscp_and_ecn(self.dscp_and_ecn());
655
656 const IPV4_HEADER_LEN_BYTES: usize = HDR_PREFIX_LEN;
661
662 builder.df_flag(self.body().len() + IPV4_HEADER_LEN_BYTES > 1260);
668
669 builder.fragment_offset(FragmentOffset::ZERO);
672 builder.mf_flag(false);
673
674 builder
675 };
676
677 match self.proto() {
678 Ipv6Proto::Proto(IpProto::Tcp) => {
679 let v4_pkt_builder = v4_builder(Ipv4Proto::Proto(IpProto::Tcp));
680 let args = TcpParseArgs::new(self.src_ip(), self.dst_ip());
681 match TcpSegment::parse(&mut self.body.as_bytes(), args) {
686 Ok(tcp) => {
687 let tcp_serializer =
691 Nat64Serializer::Tcp(tcp.into_serializer(v4_src_addr, v4_dst_addr));
692 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(tcp_serializer))
693 }
694 Err(msg) => {
695 debug!("Parsing of TCP segment failed: {:?}", msg);
696
697 let common_serializer =
706 Nat64Serializer::Other(self.body().into_serializer());
707 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
708 }
709 }
710 }
711
712 Ipv6Proto::Proto(IpProto::Udp) => {
717 let v4_pkt_builder = v4_builder(Ipv4Proto::Proto(IpProto::Udp));
718 let args = UdpParseArgs::new(self.src_ip(), self.dst_ip());
719 match UdpPacket::parse(&mut self.body.as_bytes(), args) {
720 Ok(udp) => {
721 let udp_serializer =
725 Nat64Serializer::Udp(udp.into_serializer(v4_src_addr, v4_dst_addr));
726 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(udp_serializer))
727 }
728 Err(msg) => {
729 debug!("Parsing of UDP packet failed: {:?}", msg);
730
731 let common_serializer =
741 Nat64Serializer::Other(self.body().into_serializer());
742 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
743 }
744 }
745 }
746
747 Ipv6Proto::Icmpv6 => Nat64TranslationResult::Err(Nat64Error::NotImplemented),
750
751 Ipv6Proto::Other(val) => {
771 let v4_pkt_builder = v4_builder(Ipv4Proto::Other(val));
772 let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
773 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
774 }
775
776 Ipv6Proto::NoNextHeader => {
777 let v4_pkt_builder = v4_builder(Ipv4Proto::Other(Ipv6Proto::NoNextHeader.into()));
778 let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
779 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
780 }
781
782 Ipv6Proto::Proto(IpProto::Reserved) => Nat64TranslationResult::Drop,
785 }
786 }
787
788 pub fn to_vec(&self) -> Vec<u8> {
790 let Ipv6Packet { fixed_hdr, extension_hdrs, body, proto: _ } = self;
791 let mut buf = Vec::with_capacity(
792 Ref::bytes(&fixed_hdr).len() + extension_hdrs.bytes().len() + body.as_bytes().len(),
793 );
794 buf.extend(Ref::bytes(&fixed_hdr));
795 buf.extend(extension_hdrs.bytes());
796 buf.extend(body.as_bytes());
797 buf
798 }
799}
800
801impl<B: SplitByteSliceMut> Ipv6Packet<B> {
802 pub fn set_src_ip(&mut self, addr: Ipv6Addr) {
804 self.fixed_hdr.src_ip = addr;
805 }
806
807 pub fn set_dst_ip(&mut self, addr: Ipv6Addr) {
809 self.fixed_hdr.dst_ip = addr;
810 }
811
812 pub fn set_hop_limit(&mut self, hlim: u8) {
814 self.fixed_hdr.hop_limit = hlim;
815 }
816
817 pub fn body_mut(&mut self) -> &mut [u8] {
819 &mut self.body
820 }
821
822 pub fn parts_with_body_mut(&mut self) -> (&FixedHeader, ExtensionHeaders<'_>, &mut [u8]) {
825 (&self.fixed_hdr, ExtensionHeaders(self.extension_hdrs.as_ref()), &mut self.body)
826 }
827}
828
829impl<B: SplitByteSlice> Debug for Ipv6Packet<B> {
830 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
831 f.debug_struct("Ipv6Packet")
832 .field("src_ip", &self.src_ip())
833 .field("dst_ip", &self.dst_ip())
834 .field("hop_limit", &self.hop_limit())
835 .field("proto", &self.proto())
836 .field("dscp", &self.dscp_and_ecn().dscp())
837 .field("ecn", &self.dscp_and_ecn().ecn())
838 .field("flowlabel", &self.flowlabel())
839 .field("extension headers", &"TODO")
840 .field("body", &alloc::format!("<{} bytes>", self.body.len()))
841 .finish()
842 }
843}
844
845pub struct ExtensionHeaders<'a>(Records<&'a [u8], Ipv6ExtensionHeaderImpl>);
847
848impl<'a> ExtensionHeaders<'a> {
849 pub fn iter(&self) -> impl Iterator<Item = Ipv6ExtensionHeader<'_>> {
851 self.0.iter()
852 }
853
854 pub fn bytes(&self) -> &[u8] {
856 self.0.bytes()
857 }
858}
859
860#[derive(Copy, Clone, Debug, Eq, PartialEq)]
866pub struct ExtHdrParseError;
867
868pub struct Ipv6PacketRaw<B> {
878 fixed_hdr: Ref<B, FixedHeader>,
880 extension_hdrs: MaybeParsed<RecordsRaw<B, Ipv6ExtensionHeaderImpl>, B>,
886 body_proto: Result<(MaybeParsed<B, B>, Ipv6Proto), ExtHdrParseError>,
899}
900
901impl<B> Ipv6PacketRaw<B> {
902 pub fn body_mut(&mut self) -> Option<&mut B> {
906 match self.body_proto {
907 Ok(ref mut b) => match b {
908 (MaybeParsed::Complete(ref mut b), _) => Some(b),
909 (MaybeParsed::Incomplete(ref mut b), _) => Some(b),
910 },
911 Err(_) => None,
912 }
913 }
914}
915
916impl<B: SplitByteSlice> Ipv6Header for Ipv6PacketRaw<B> {
917 fn get_fixed_header(&self) -> &FixedHeader {
918 &self.fixed_hdr
919 }
920}
921
922impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv6PacketRaw<B> {
923 type Error = IpParseError<Ipv6>;
924
925 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> Result<Self, Self::Error> {
926 let fixed_hdr = buffer
927 .take_obj_front::<FixedHeader>()
928 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for header"))?;
929 let payload_len = fixed_hdr.payload_len.get().into();
930 let _: Option<B> = buffer.len().checked_sub(payload_len).map(|padding| {
932 buffer.take_back(padding).unwrap_or_else(|| {
933 panic!("buffer.len()={} padding={}", buffer.len(), padding);
934 })
935 });
936
937 let mut extension_hdr_context = Ipv6ExtensionHeaderParsingContext::new(fixed_hdr.next_hdr);
938
939 let extension_hdrs =
940 RecordsRaw::parse_raw_with_mut_context(&mut buffer, &mut extension_hdr_context)
941 .map_incomplete(|(b, _)| b);
942
943 let body_proto = match &extension_hdrs {
944 MaybeParsed::Complete(r) => {
945 let _: &RecordsRaw<B, _> = r;
946 assert!(is_valid_next_header_upper_layer(extension_hdr_context.next_header));
967 let proto = Ipv6Proto::from(extension_hdr_context.next_header);
968 let body = MaybeParsed::new_with_min_len(
969 buffer.into_rest(),
970 payload_len.saturating_sub(extension_hdrs.len()),
971 );
972 Ok((body, proto))
973 }
974 MaybeParsed::Incomplete(b) => {
975 let _: &B = b;
976 Err(ExtHdrParseError)
977 }
978 };
979
980 Ok(Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto })
981 }
982
983 fn parse_metadata(&self) -> ParseMetadata {
984 let header_len = Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.len();
985 let body_len = self.body_proto.as_ref().map(|(b, _p)| b.len()).unwrap_or(0);
986 ParseMetadata::from_packet(header_len, body_len, 0)
987 }
988}
989
990impl<B: SplitByteSlice> Ipv6PacketRaw<B> {
991 pub fn body_proto(&self) -> Result<(MaybeParsed<&[u8], &[u8]>, Ipv6Proto), ExtHdrParseError> {
1004 self.body_proto
1005 .as_ref()
1006 .map(|(mp, proto)| {
1007 (mp.as_ref().map(|b| b.deref()).map_incomplete(|b| b.deref()), *proto)
1008 })
1009 .map_err(|e| *e)
1010 }
1011
1012 pub fn body(&self) -> Result<MaybeParsed<&[u8], &[u8]>, ExtHdrParseError> {
1023 self.body_proto().map(|(body, _proto)| body)
1024 }
1025
1026 pub fn proto(&self) -> Result<Ipv6Proto, ExtHdrParseError> {
1033 self.body_proto().map(|(_body, proto)| proto)
1034 }
1035}
1036
1037impl<B: SplitByteSliceMut> Ipv6PacketRaw<B> {
1038 pub fn set_src_ip(&mut self, addr: Ipv6Addr) {
1040 self.fixed_hdr.src_ip = addr;
1041 }
1042
1043 pub fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1045 self.fixed_hdr.dst_ip = addr;
1046 }
1047}
1048
1049pub enum NextHeader {
1052 NextLayer(Ipv6Proto),
1054 Extension(Ipv6ExtHdrType),
1056}
1057
1058impl From<NextHeader> for u8 {
1059 fn from(next_hdr: NextHeader) -> Self {
1060 match next_hdr {
1061 NextHeader::NextLayer(n) => n.into(),
1062 NextHeader::Extension(e) => e.into(),
1063 }
1064 }
1065}
1066
1067mod sealed {
1068 use super::*;
1069 pub trait Ipv6HeaderBefore<T> {}
1077
1078 impl<'a, O, T> Ipv6HeaderBefore<T> for &'a O where O: Ipv6HeaderBefore<T> {}
1079
1080 pub trait Ipv6HeaderBuilder {
1082 fn fixed_header(&self) -> &Ipv6PacketBuilder;
1084
1085 fn extension_headers_len(&self) -> usize;
1088
1089 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1094 &self,
1095 buffer: &mut BV,
1096 next_header: NextHeader,
1097 payload_len: usize,
1098 );
1099 }
1100}
1101use sealed::{Ipv6HeaderBefore, Ipv6HeaderBuilder};
1102
1103impl<'a, O> Ipv6HeaderBuilder for &'a O
1104where
1105 O: Ipv6HeaderBuilder,
1106{
1107 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1108 O::fixed_header(self)
1109 }
1110
1111 fn extension_headers_len(&self) -> usize {
1112 O::extension_headers_len(self)
1113 }
1114
1115 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1116 &self,
1117 buffer: &mut BV,
1118 next_header: NextHeader,
1119 payload_len: usize,
1120 ) {
1121 O::serialize_header(self, buffer, next_header, payload_len)
1122 }
1123}
1124
1125macro_rules! impl_packet_builder {
1130 {} => {
1131 fn constraints(&self) -> PacketConstraints {
1132 let ext_headers = self.extension_headers_len();
1133 let header_len = IPV6_FIXED_HDR_LEN + ext_headers;
1134 let footer_len = 0;
1135 let min_body_len = 0;
1136 let max_body_len = IPV6_MAX_PAYLOAD_LENGTH - ext_headers;
1139 PacketConstraints::new(header_len, footer_len, min_body_len, max_body_len)
1140 }
1141
1142 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
1143 let mut bv = &mut target.header;
1144 self.serialize_header(
1145 &mut bv,
1146 NextHeader::NextLayer(self.fixed_header().proto()),
1147 body.len(),
1148 );
1149 }
1150 }
1151}
1152
1153macro_rules! impl_partial_packet_builder {
1154 {} => {
1155 fn partial_serialize(&self, body_len: usize, mut buffer: &mut [u8]) {
1156 self.serialize_header(
1157 &mut &mut buffer,
1158 NextHeader::NextLayer(self.fixed_header().proto()),
1159 body_len,
1160 );
1161 }
1162 }
1163}
1164#[derive(Debug, Clone, Eq, PartialEq)]
1166pub struct Ipv6PacketBuilder {
1167 dscp_and_ecn: DscpAndEcn,
1168 flowlabel: u32,
1169 hop_limit: u8,
1170 proto: Ipv6Proto,
1173 src_ip: Ipv6Addr,
1174 dst_ip: Ipv6Addr,
1175}
1176
1177impl Ipv6PacketBuilder {
1178 pub fn new<S: Into<Ipv6Addr>, D: Into<Ipv6Addr>>(
1184 src_ip: S,
1185 dst_ip: D,
1186 hop_limit: u8,
1187 proto: Ipv6Proto,
1188 ) -> Ipv6PacketBuilder {
1189 Ipv6PacketBuilder {
1190 dscp_and_ecn: DscpAndEcn::default(),
1191 flowlabel: 0,
1192 hop_limit,
1193 proto,
1194 src_ip: src_ip.into(),
1195 dst_ip: dst_ip.into(),
1196 }
1197 }
1198
1199 pub fn dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1202 self.dscp_and_ecn = dscp_and_ecn;
1203 }
1204
1205 pub fn flowlabel(&mut self, flowlabel: u32) {
1211 assert!(flowlabel <= 1 << 20, "invalid flowlabel: {:x}", flowlabel);
1212 self.flowlabel = flowlabel;
1213 }
1214}
1215
1216impl Ipv6HeaderBuilder for Ipv6PacketBuilder {
1217 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1218 self
1219 }
1220
1221 fn extension_headers_len(&self) -> usize {
1222 0
1223 }
1224
1225 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1226 &self,
1227 buffer: &mut BV,
1228 next_header: NextHeader,
1229 payload_len: usize,
1230 ) {
1231 buffer
1232 .write_obj_front(&FixedHeader::new(
1233 self.dscp_and_ecn,
1234 self.flowlabel,
1235 {
1236 debug_assert!(payload_len <= core::u16::MAX as usize);
1243 payload_len as u16
1244 },
1245 next_header.into(),
1246 self.hop_limit,
1247 self.src_ip,
1248 self.dst_ip,
1249 ))
1250 .expect("not enough bytes for IPv6 fixed header");
1251 }
1252}
1253
1254impl PacketBuilder for Ipv6PacketBuilder {
1255 impl_packet_builder! {}
1256}
1257
1258impl PartialPacketBuilder for Ipv6PacketBuilder {
1259 impl_partial_packet_builder! {}
1260}
1261
1262#[derive(Debug, Clone)]
1264pub struct Ipv6PacketBuilderWithHbhOptions<'a, I> {
1265 prefix_builder: Ipv6PacketBuilder,
1266 hbh_options: AlignedRecordSequenceBuilder<HopByHopOption<'a>, I>,
1267}
1268
1269impl<'a, I> Ipv6PacketBuilderWithHbhOptions<'a, I>
1270where
1271 I: Iterator + Clone,
1272 I::Item: Borrow<HopByHopOption<'a>>,
1273{
1274 pub fn new<T: IntoIterator<Item = I::Item, IntoIter = I>>(
1276 prefix_builder: Ipv6PacketBuilder,
1277 options: T,
1278 ) -> Option<Ipv6PacketBuilderWithHbhOptions<'a, I>> {
1279 let iter = options.into_iter();
1280 if iter
1283 .clone()
1284 .filter(|r| matches!(r.borrow().data, HopByHopOptionData::RouterAlert { .. }))
1285 .count()
1286 > 1
1287 {
1288 return None;
1289 }
1290 let hbh_options = AlignedRecordSequenceBuilder::new(2, iter);
1291 if next_multiple_of_eight(2 + hbh_options.serialized_len()) > IPV6_HBH_OPTIONS_MAX_LEN {
1293 return None;
1294 }
1295 Some(Ipv6PacketBuilderWithHbhOptions { prefix_builder, hbh_options })
1296 }
1297
1298 fn aligned_hbh_len(&self) -> usize {
1299 let opt_len = self.hbh_options.serialized_len();
1300 let hbh_len = opt_len + 2;
1301 next_multiple_of_eight(hbh_len)
1302 }
1303}
1304
1305fn next_multiple_of_eight(x: usize) -> usize {
1306 (x + 7) & (!7)
1307}
1308
1309impl IpPacketBuilder<Ipv6> for Ipv6PacketBuilder {
1310 fn new(src_ip: Ipv6Addr, dst_ip: Ipv6Addr, ttl: u8, proto: Ipv6Proto) -> Self {
1311 Ipv6PacketBuilder::new(src_ip, dst_ip, ttl, proto)
1312 }
1313
1314 fn src_ip(&self) -> Ipv6Addr {
1315 self.src_ip
1316 }
1317
1318 fn set_src_ip(&mut self, addr: Ipv6Addr) {
1319 self.src_ip = addr;
1320 }
1321
1322 fn dst_ip(&self) -> Ipv6Addr {
1323 self.dst_ip
1324 }
1325
1326 fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1327 self.dst_ip = addr;
1328 }
1329
1330 fn proto(&self) -> Ipv6Proto {
1331 self.proto
1332 }
1333
1334 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1335 self.dscp_and_ecn = dscp_and_ecn;
1336 }
1337}
1338
1339impl<'a, I> Ipv6HeaderBuilder for Ipv6PacketBuilderWithHbhOptions<'a, I>
1340where
1341 I: Iterator + Clone,
1342 I::Item: Borrow<HopByHopOption<'a>>,
1343{
1344 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1345 &self.prefix_builder
1346 }
1347
1348 fn extension_headers_len(&self) -> usize {
1349 self.prefix_builder.extension_headers_len() + self.aligned_hbh_len()
1350 }
1351
1352 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1353 &self,
1354 buffer: &mut BV,
1355 next_header: NextHeader,
1356 payload_len: usize,
1357 ) {
1358 let aligned_hbh_len = self.aligned_hbh_len();
1359 self.prefix_builder.serialize_header(
1361 buffer,
1362 NextHeader::Extension(Ipv6ExtHdrType::HopByHopOptions),
1363 payload_len + aligned_hbh_len,
1364 );
1365 let mut hbh_header = buffer.take_front(aligned_hbh_len).unwrap();
1367 let hbh_header = hbh_header.as_mut();
1368 hbh_header[0] = next_header.into();
1369 hbh_header[1] = u8::try_from((aligned_hbh_len - 8) / 8).expect("extension header too big");
1370 self.hbh_options.serialize_into(&mut hbh_header[2..]);
1371 }
1372}
1373
1374impl<'a, I> PacketBuilder for Ipv6PacketBuilderWithHbhOptions<'a, I>
1375where
1376 I: Iterator + Clone,
1377 I::Item: Borrow<HopByHopOption<'a>>,
1378{
1379 impl_packet_builder! {}
1380}
1381
1382impl<'a, I> PartialPacketBuilder for Ipv6PacketBuilderWithHbhOptions<'a, I>
1383where
1384 I: Iterator + Clone,
1385 I::Item: Borrow<HopByHopOption<'a>>,
1386{
1387 impl_partial_packet_builder! {}
1388}
1389
1390impl<'a, I> IpPacketBuilder<Ipv6> for Ipv6PacketBuilderWithHbhOptions<'a, I>
1391where
1392 I: Iterator<Item: Borrow<HopByHopOption<'a>>> + Debug + Default + Clone,
1393{
1394 fn new(src_ip: Ipv6Addr, dst_ip: Ipv6Addr, ttl: u8, proto: Ipv6Proto) -> Self {
1395 Ipv6PacketBuilderWithHbhOptions::new(
1396 Ipv6PacketBuilder::new(src_ip, dst_ip, ttl, proto),
1397 I::default(),
1398 )
1399 .expect("packet builder with no options should be valid")
1400 }
1401
1402 fn src_ip(&self) -> Ipv6Addr {
1403 self.prefix_builder.src_ip
1404 }
1405
1406 fn set_src_ip(&mut self, addr: Ipv6Addr) {
1407 self.prefix_builder.src_ip = addr;
1408 }
1409
1410 fn dst_ip(&self) -> Ipv6Addr {
1411 self.prefix_builder.dst_ip
1412 }
1413
1414 fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1415 self.prefix_builder.dst_ip = addr;
1416 }
1417
1418 fn proto(&self) -> Ipv6Proto {
1419 self.prefix_builder.proto
1420 }
1421
1422 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1423 self.prefix_builder.set_dscp_and_ecn(dscp_and_ecn)
1424 }
1425}
1426
1427#[derive(Debug, Eq, PartialEq)]
1436pub struct Ipv6PacketBuilderWithFragmentHeader<B> {
1437 header_builder: B,
1438 fragment_offset: FragmentOffset,
1439 more_fragments: bool,
1440 identification: u32,
1441}
1442
1443impl<B: Ipv6HeaderBefore<Self>> Ipv6PacketBuilderWithFragmentHeader<B> {
1444 pub fn new(
1446 header_builder: B,
1447 fragment_offset: FragmentOffset,
1448 more_fragments: bool,
1449 identification: u32,
1450 ) -> Self {
1451 Self { header_builder, fragment_offset, more_fragments, identification }
1452 }
1453}
1454
1455impl<B> Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>> for Ipv6PacketBuilder {}
1456impl<B, I> Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>>
1457 for Ipv6PacketBuilderWithHbhOptions<'_, I>
1458{
1459}
1460
1461pub trait Ipv6PacketBuilderBeforeFragment:
1464 Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<Self>> + Ipv6HeaderBuilder + Sized
1465{
1466}
1467impl<B> Ipv6PacketBuilderBeforeFragment for B where
1468 B: Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<Self>> + Ipv6HeaderBuilder + Sized
1469{
1470}
1471
1472impl<B: Ipv6HeaderBuilder> Ipv6HeaderBuilder for Ipv6PacketBuilderWithFragmentHeader<B> {
1473 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1474 self.header_builder.fixed_header()
1475 }
1476
1477 fn extension_headers_len(&self) -> usize {
1478 self.header_builder.extension_headers_len() + IPV6_FRAGMENT_EXT_HDR_LEN
1479 }
1480
1481 fn serialize_header<BB: SplitByteSliceMut, BV: BufferViewMut<BB>>(
1482 &self,
1483 buffer: &mut BV,
1484 next_header: NextHeader,
1485 payload_len: usize,
1486 ) {
1487 let Self { header_builder, fragment_offset, more_fragments, identification } = self;
1488 let payload_len = payload_len + IPV6_FRAGMENT_EXT_HDR_LEN;
1489 header_builder.serialize_header(
1490 buffer,
1491 NextHeader::Extension(Ipv6ExtHdrType::Fragment),
1492 payload_len,
1493 );
1494 buffer.write_obj_front(&u8::from(next_header)).unwrap();
1495 let _: BB = buffer.take_front_zero(1).unwrap();
1497 let more_fragments = u16::from(*more_fragments);
1498 buffer
1499 .write_obj_front(&U16::new(fragment_offset.into_raw() << 3 | more_fragments))
1500 .unwrap();
1501 buffer.write_obj_front(&U32::new(*identification)).unwrap();
1502 }
1503}
1504
1505impl<B: Ipv6HeaderBuilder> PacketBuilder for Ipv6PacketBuilderWithFragmentHeader<B> {
1506 impl_packet_builder! {}
1507}
1508
1509impl<B: Ipv6HeaderBuilder> PartialPacketBuilder for Ipv6PacketBuilderWithFragmentHeader<B> {
1510 impl_partial_packet_builder! {}
1511}
1512
1513pub(crate) fn reassemble_fragmented_packet<
1515 B: SplitByteSliceMut,
1516 BV: BufferViewMut<B>,
1517 I: Iterator<Item = Vec<u8>>,
1518>(
1519 mut buffer: BV,
1520 header: Vec<u8>,
1521 body_fragments: I,
1522) -> IpParseResult<Ipv6, ()> {
1523 let bytes = buffer.as_mut();
1524
1525 bytes[0..header.len()].copy_from_slice(&header[..]);
1527 let mut byte_count = header.len();
1528
1529 for p in body_fragments {
1531 bytes[byte_count..byte_count + p.len()].copy_from_slice(&p[..]);
1532 byte_count += p.len();
1533 }
1534
1535 let payload_length = byte_count - IPV6_FIXED_HDR_LEN;
1547
1548 if payload_length > usize::from(core::u16::MAX) {
1551 return debug_err!(
1552 Err(ParseError::Format.into()),
1553 "fragmented packet payload length of {} bytes is too large",
1554 payload_length
1555 );
1556 }
1557
1558 let mut header = Ref::<_, FixedHeader>::from_prefix(bytes).unwrap().0;
1561
1562 header.payload_len.set(u16::try_from(payload_length).unwrap());
1564
1565 Ok(())
1566}
1567
1568#[cfg(test)]
1569mod tests {
1570 use assert_matches::assert_matches;
1571 use packet::{Buf, FragmentedBuffer, ParseBuffer};
1572 use test_case::test_case;
1573
1574 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1575 use crate::testutil::*;
1576
1577 use super::ext_hdrs::*;
1578 use super::*;
1579
1580 const DEFAULT_SRC_IP: Ipv6Addr =
1581 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1582 const DEFAULT_DST_IP: Ipv6Addr =
1583 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1584
1585 const DEFAULT_V4_SRC_IP: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1586 const DEFAULT_V4_DST_IP: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1587
1588 #[test]
1589 fn test_parse_serialize_full_tcp() {
1590 use crate::testdata::syn_v6::*;
1591
1592 let mut buf = ETHERNET_FRAME.bytes;
1593 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1594 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1595
1596 let mut body = frame.body();
1597 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1598 verify_ipv6_packet(&packet, IPV6_PACKET);
1599
1600 let buffer = packet
1602 .body()
1603 .into_serializer()
1604 .wrap_in(packet.builder())
1605 .wrap_in(frame.builder())
1606 .serialize_vec_outer()
1607 .unwrap();
1608 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1609
1610 assert_eq!(&packet.to_vec()[..], IPV6_PACKET.bytes);
1612 }
1613
1614 #[test]
1615 fn test_parse_serialize_full_udp() {
1616 use crate::testdata::dns_request_v6::*;
1617
1618 let mut buf = ETHERNET_FRAME.bytes;
1619 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1620 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1621
1622 let mut body = frame.body();
1623 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1624 verify_ipv6_packet(&packet, IPV6_PACKET);
1625
1626 let buffer = packet
1628 .body()
1629 .into_serializer()
1630 .wrap_in(packet.builder())
1631 .wrap_in(frame.builder())
1632 .serialize_vec_outer()
1633 .unwrap();
1634 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1635
1636 assert_eq!(&packet.to_vec()[..], IPV6_PACKET.bytes);
1638 }
1639
1640 #[test]
1641 fn test_parse_serialize_with_extension_headers() {
1642 use crate::testdata::mld_router_report::*;
1645
1646 let mut buf = REPORT;
1647 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1648 assert_eq!(packet.iter_extension_hdrs().count(), 1);
1649
1650 assert_eq!(&packet.to_vec()[..], REPORT);
1655 }
1656
1657 fn fixed_hdr_to_bytes(fixed_hdr: FixedHeader) -> [u8; IPV6_FIXED_HDR_LEN] {
1658 zerocopy::transmute!(fixed_hdr)
1659 }
1660
1661 fn new_fixed_hdr() -> FixedHeader {
1663 FixedHeader::new(
1664 DscpAndEcn::new(0, 2),
1665 0x77,
1666 0,
1667 IpProto::Tcp.into(),
1668 64,
1669 DEFAULT_SRC_IP,
1670 DEFAULT_DST_IP,
1671 )
1672 }
1673
1674 #[test]
1675 fn test_parse() {
1676 let mut buf = &fixed_hdr_to_bytes(new_fixed_hdr())[..];
1677 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1678 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1679 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1680 assert_eq!(packet.flowlabel(), 0x77);
1681 assert_eq!(packet.hop_limit(), 64);
1682 assert_eq!(packet.fixed_hdr.next_hdr, IpProto::Tcp.into());
1683 assert_eq!(packet.proto(), IpProto::Tcp.into());
1684 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1685 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1686 assert_eq!(packet.body(), []);
1687 }
1688
1689 #[test]
1690 fn test_parse_with_ext_hdrs() {
1691 #[rustfmt::skip]
1692 let mut buf = [
1693 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1695 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1696
1697 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,
1712 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1713
1714 IpProto::Tcp.into(), 1, 0, 1, 0, 1, 1, 0, 1, 6, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
1724 ];
1725 let mut fixed_hdr = new_fixed_hdr();
1726 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
1727 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1728 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1729 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1730 let mut buf = &buf[..];
1731 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1732 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1733 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1734 assert_eq!(packet.flowlabel(), 0x77);
1735 assert_eq!(packet.hop_limit(), 64);
1736 assert_eq!(packet.fixed_hdr.next_hdr, Ipv6ExtHdrType::HopByHopOptions.into());
1737 assert_eq!(packet.proto(), IpProto::Tcp.into());
1738 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1739 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1740 assert_eq!(packet.body(), [1, 2, 3, 4, 5]);
1741 let ext_hdrs: Vec<Ipv6ExtensionHeader<'_>> = packet.iter_extension_hdrs().collect();
1742 assert_eq!(ext_hdrs.len(), 2);
1743 assert_eq!(ext_hdrs[0].next_header, Ipv6ExtHdrType::Routing.into());
1745 if let Ipv6ExtensionHeaderData::HopByHopOptions { options } = ext_hdrs[0].data() {
1746 assert_eq!(options.iter().count(), 0);
1748 } else {
1749 panic!("Should have matched HopByHopOptions!");
1750 }
1751
1752 assert_eq!(ext_hdrs[1].next_header, IpProto::Tcp.into());
1757 if let Ipv6ExtensionHeaderData::DestinationOptions { options } = ext_hdrs[1].data() {
1758 assert_eq!(options.iter().count(), 0);
1760 } else {
1761 panic!("Should have matched DestinationOptions!");
1762 }
1763
1764 #[rustfmt::skip]
1766 let mut buf = [
1767 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1769 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1770
1771 Ipv6Proto::NoNextHeader.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
1780 ];
1781 let mut fixed_hdr = new_fixed_hdr();
1782 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
1783 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1784 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1785 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1786 let mut buf = &buf[..];
1787 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1788 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1789 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1790 assert_eq!(packet.flowlabel(), 0x77);
1791 assert_eq!(packet.hop_limit(), 64);
1792 assert_eq!(packet.fixed_hdr.next_hdr, Ipv6ExtHdrType::HopByHopOptions.into());
1793 assert_eq!(packet.proto(), Ipv6Proto::NoNextHeader);
1794 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1795 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1796 assert_eq!(packet.body(), [1, 2, 3, 4, 5]);
1797 let ext_hdrs: Vec<Ipv6ExtensionHeader<'_>> = packet.iter_extension_hdrs().collect();
1798 assert_eq!(ext_hdrs.len(), 1);
1799 assert_eq!(ext_hdrs[0].next_header, Ipv6Proto::NoNextHeader.into());
1801 if let Ipv6ExtensionHeaderData::HopByHopOptions { options } = ext_hdrs[0].data() {
1802 assert_eq!(options.iter().count(), 0);
1804 } else {
1805 panic!("Should have matched HopByHopOptions!");
1806 }
1807 }
1808
1809 #[test]
1810 fn test_parse_error() {
1811 let mut fixed_hdr = new_fixed_hdr();
1813 fixed_hdr.version_tc_flowlabel[0] = 0x50;
1814 assert_eq!(
1815 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1816 ParseError::Format.into()
1817 );
1818
1819 let mut fixed_hdr = new_fixed_hdr();
1821 fixed_hdr.payload_len = U16::new(2);
1822 assert_eq!(
1823 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1824 ParseError::Format.into()
1825 );
1826
1827 let mut fixed_hdr = new_fixed_hdr();
1829 fixed_hdr.next_hdr = 255;
1830 assert_eq!(
1831 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1832 IpParseError::ParameterProblem {
1833 src_ip: DEFAULT_SRC_IP,
1834 dst_ip: DEFAULT_DST_IP,
1835 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1836 pointer: u32::from(NEXT_HEADER_OFFSET),
1837 must_send_icmp: false,
1838 header_len: (),
1839 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1840 }
1841 );
1842
1843 let mut fixed_hdr = new_fixed_hdr();
1845 fixed_hdr.next_hdr = Ipv4Proto::Icmp.into();
1846 assert_eq!(
1847 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1848 IpParseError::ParameterProblem {
1849 src_ip: DEFAULT_SRC_IP,
1850 dst_ip: DEFAULT_DST_IP,
1851 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1852 pointer: u32::from(NEXT_HEADER_OFFSET),
1853 must_send_icmp: false,
1854 header_len: (),
1855 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1856 }
1857 );
1858
1859 #[rustfmt::skip]
1861 let mut buf = [
1862 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1864 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1865
1866 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,
1874 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1875
1876 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
1885 ];
1886 let mut fixed_hdr = new_fixed_hdr();
1887 fixed_hdr.next_hdr = Ipv6ExtHdrType::Routing.into();
1888 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1889 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1890 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1891 let mut buf = &buf[..];
1892 assert_eq!(
1893 buf.parse::<Ipv6Packet<_>>().unwrap_err(),
1894 IpParseError::ParameterProblem {
1895 src_ip: DEFAULT_SRC_IP,
1896 dst_ip: DEFAULT_DST_IP,
1897 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1898 pointer: IPV6_FIXED_HDR_LEN as u32,
1899 must_send_icmp: false,
1900 header_len: (),
1901 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1902 }
1903 );
1904
1905 #[rustfmt::skip]
1907 let mut buf = [
1908 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1910 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1911
1912 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,
1920 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1921
1922 1, 2, 3, 4, 5,
1924 ];
1925 let mut fixed_hdr = new_fixed_hdr();
1926 fixed_hdr.next_hdr = Ipv6ExtHdrType::Routing.into();
1927 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1928 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1929 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1930 let mut buf = &buf[..];
1931 assert_eq!(
1932 buf.parse::<Ipv6Packet<_>>().unwrap_err(),
1933 IpParseError::ParameterProblem {
1934 src_ip: DEFAULT_SRC_IP,
1935 dst_ip: DEFAULT_DST_IP,
1936 code: Icmpv6ParameterProblemCode::ErroneousHeaderField,
1937 pointer: (IPV6_FIXED_HDR_LEN as u32) + 2,
1938 must_send_icmp: true,
1939 header_len: (),
1940 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1941 }
1942 );
1943 }
1944
1945 #[test]
1946 fn test_parse_all_next_header_values() {
1947 let mut buf = [
1953 0x81, 0x13, 0x27, 0xeb, 0x75, 0x92, 0x33, 0x89, 0x01, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
1954 0x03, 0x70, 0x00, 0x22, 0xf7, 0x30, 0x2c, 0x06, 0xfe, 0xc9, 0x00, 0x2d, 0x3b, 0xeb,
1955 0xad, 0x3e, 0x5c, 0x41, 0xc8, 0x70, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x11, 0x00,
1956 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x4f, 0x4f, 0x6f, 0x4f, 0x4f, 0x4f, 0x4f,
1957 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x19, 0x19,
1958 0x19, 0x19, 0x19, 0x4f, 0x4f, 0x4f, 0x4f, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1959 0x00, 0x4f, 0x4f, 0x5a, 0x5a, 0x5a, 0xc9, 0x5a, 0x46, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
1960 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0xe4, 0x5a, 0x5a, 0x5a, 0x5a,
1961 ];
1962
1963 assert_matches!(
1966 (&buf[..]).parse::<Ipv6Packet<_>>(),
1967 Err(IpParseError::ParameterProblem {
1968 src_ip: _,
1969 dst_ip: _,
1970 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1971 pointer: 0,
1972 must_send_icmp: false,
1973 header_len: (),
1974 action: IpParseErrorAction::DiscardPacket,
1975 })
1976 );
1977
1978 for b in 0u8..=255 {
1981 buf[6] = b;
1983 let _: Result<_, _> = (&buf[..]).parse::<Ipv6Packet<_>>();
1984 }
1985 }
1986
1987 #[test]
1988 fn test_partial_parse() {
1989 use core::convert::TryInto as _;
1990 use core::ops::Deref as _;
1991
1992 #[rustfmt::skip]
1994 let mut buf = [
1995 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1997 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1998
1999 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2008 ];
2009 let len = buf.len() - IPV6_FIXED_HDR_LEN;
2010 let len = len.try_into().unwrap();
2011 let make_fixed_hdr = || {
2012 let mut fixed_hdr = new_fixed_hdr();
2013 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2014 fixed_hdr.payload_len = U16::new(len);
2015 fixed_hdr
2016 };
2017 const MALFORMED_BYTE: u8 = 10;
2019 buf[IPV6_FIXED_HDR_LEN + 1] = MALFORMED_BYTE;
2020 let fixed_hdr = fixed_hdr_to_bytes(make_fixed_hdr());
2021 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr);
2022 let mut buf = &buf[..];
2023 let partial = buf.parse::<Ipv6PacketRaw<_>>().unwrap();
2024 let Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto } = &partial;
2025 assert_eq!(fixed_hdr.deref(), &make_fixed_hdr());
2026 assert_eq!(
2027 *extension_hdrs.as_ref().incomplete().unwrap(),
2028 [IpProto::Tcp.into(), MALFORMED_BYTE]
2029 );
2030 assert_eq!(body_proto, &Err(ExtHdrParseError));
2031 assert!(Ipv6Packet::try_from_raw(partial).is_err());
2032
2033 let mut buf = [
2035 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,
2037 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
2039 ];
2040 let make_fixed_hdr = || {
2041 let mut fixed_hdr = new_fixed_hdr();
2042 fixed_hdr.next_hdr = IpProto::Tcp.into();
2043 fixed_hdr.payload_len = U16::new(10);
2044 fixed_hdr
2045 };
2046 let fixed_hdr = fixed_hdr_to_bytes(make_fixed_hdr());
2047 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr);
2048 let mut parsebuff = &buf[..];
2049 let partial = parsebuff.parse::<Ipv6PacketRaw<_>>().unwrap();
2050 let Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto } = &partial;
2051 assert_eq!(fixed_hdr.deref(), &make_fixed_hdr());
2052 assert_eq!(extension_hdrs.as_ref().complete().unwrap().deref(), []);
2053 let (body, proto) = body_proto.unwrap();
2054 assert_eq!(body.incomplete().unwrap(), &buf[IPV6_FIXED_HDR_LEN..]);
2055 assert_eq!(proto, IpProto::Tcp.into());
2056 assert!(Ipv6Packet::try_from_raw(partial).is_err());
2057 }
2058
2059 fn new_builder() -> Ipv6PacketBuilder {
2061 Ipv6PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, 64, IpProto::Tcp.into())
2062 }
2063
2064 #[test]
2065 fn test_serialize() {
2066 let mut builder = new_builder();
2067 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
2068 builder.flowlabel(0x10405);
2069 let mut buf = (&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2070 .into_serializer()
2071 .wrap_in(builder)
2072 .serialize_vec_outer()
2073 .unwrap();
2074 assert_eq!(
2076 buf.as_ref(),
2077 &[
2078 100, 177, 4, 5, 0, 10, 6, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
2079 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, 1, 2, 3, 4,
2080 5, 6, 7, 8, 9
2081 ][..],
2082 );
2083
2084 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2085 assert_eq!(packet.dscp_and_ecn().dscp(), 0x12);
2088 assert_eq!(packet.dscp_and_ecn().ecn(), 3);
2089 assert_eq!(packet.flowlabel(), 0x10405);
2090 }
2091
2092 #[test]
2093 fn test_serialize_zeroes() {
2094 let mut buf_0 = [0; IPV6_FIXED_HDR_LEN];
2097 let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], IPV6_FIXED_HDR_LEN..)
2098 .wrap_in(new_builder())
2099 .serialize_vec_outer()
2100 .unwrap()
2101 .unwrap_a();
2102 let mut buf_1 = [0xFF; IPV6_FIXED_HDR_LEN];
2103 let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], IPV6_FIXED_HDR_LEN..)
2104 .wrap_in(new_builder())
2105 .serialize_vec_outer()
2106 .unwrap()
2107 .unwrap_a();
2108 assert_eq!(&buf_0[..], &buf_1[..]);
2109 }
2110
2111 #[test]
2112 fn test_packet_builder_proto_not_next_header() {
2113 let mut buf = (&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2117 .into_serializer()
2118 .wrap_in(
2119 Ipv6PacketBuilderWithHbhOptions::new(
2120 new_builder(),
2121 &[HopByHopOption {
2122 action: ExtensionHeaderOptionAction::SkipAndContinue,
2123 mutable: false,
2124 data: HopByHopOptionData::RouterAlert { data: 0 },
2125 }],
2126 )
2127 .unwrap(),
2128 )
2129 .serialize_vec_outer()
2130 .unwrap();
2131 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2132 assert_eq!(packet.proto(), IpProto::Tcp.into());
2133 assert_eq!(packet.next_header(), Ipv6ExtHdrType::HopByHopOptions.into());
2134 }
2135
2136 #[test]
2137 #[should_panic(expected = "SizeLimitExceeded, Nested { inner: Buf { buf:")]
2138 fn test_serialize_panic_packet_length() {
2139 let _: Buf<&mut [u8]> = Buf::new(&mut [0; 1 << 16][..], ..)
2142 .wrap_in(new_builder())
2143 .serialize_vec_outer()
2144 .unwrap()
2145 .unwrap_a();
2146 }
2147
2148 #[test]
2149 #[should_panic(expected = "packet must have at least one extension header")]
2150 fn test_copy_header_bytes_for_fragment_without_ext_hdrs() {
2151 let mut buf = &fixed_hdr_to_bytes(new_fixed_hdr())[..];
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_1_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 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2174 ];
2175 let mut fixed_hdr = new_fixed_hdr();
2176 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2177 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2178 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2179 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2180 let mut buf = &buf[..];
2181 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2182 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2183 }
2184
2185 #[test]
2186 #[should_panic(expected = "exhausted all extension headers without finding fragment header")]
2187 fn test_copy_header_bytes_for_fragment_with_2_ext_hdr_no_fragment() {
2188 #[rustfmt::skip]
2189 let mut buf = [
2190 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2192 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2193
2194 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,
2211 ];
2212 let mut fixed_hdr = new_fixed_hdr();
2213 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2214 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2215 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2216 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2217 let mut buf = &buf[..];
2218 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2219 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2220 }
2221
2222 #[test]
2223 fn test_copy_header_bytes_for_fragment() {
2224 #[rustfmt::skip]
2229 let mut bytes = [
2230 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2232 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2233
2234 IpProto::Tcp.into(), 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5,
2242 ];
2243 let mut fixed_hdr = new_fixed_hdr();
2244 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2245 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2246 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2247 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2248 let mut buf = &bytes[..];
2249 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2250 let copied_bytes = packet.copy_header_bytes_for_fragment();
2251 bytes[6] = IpProto::Tcp.into();
2252 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN]);
2253
2254 #[rustfmt::skip]
2259 let mut bytes = [
2260 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2262 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2263
2264 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,
2279 ];
2280 let mut fixed_hdr = new_fixed_hdr();
2281 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2282 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2283 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2284 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2285 let mut buf = &bytes[..];
2286 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2287 let copied_bytes = packet.copy_header_bytes_for_fragment();
2288 bytes[IPV6_FIXED_HDR_LEN] = IpProto::Tcp.into();
2289 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN + 8]);
2290
2291 #[rustfmt::skip]
2296 let mut bytes = [
2297 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2299 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2300
2301 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,
2324 ];
2325 let mut fixed_hdr = new_fixed_hdr();
2326 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2327 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2328 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2329 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2330 let mut buf = &bytes[..];
2331 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2332 let copied_bytes = packet.copy_header_bytes_for_fragment();
2333 bytes[IPV6_FIXED_HDR_LEN + 8] = IpProto::Tcp.into();
2334 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN + 24]);
2335
2336 #[rustfmt::skip]
2341 let mut bytes = [
2342 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2344 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2345
2346 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,
2362 ];
2363 let mut fixed_hdr = new_fixed_hdr();
2364 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2365 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2366 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2367 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2368 let mut buf = &bytes[..];
2369 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2370 let copied_bytes = packet.copy_header_bytes_for_fragment();
2371 let mut expected_bytes = Vec::new();
2372 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2373 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2374 expected_bytes[6] = Ipv6ExtHdrType::DestinationOptions.into();
2375 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2376
2377 #[rustfmt::skip]
2382 let mut bytes = [
2383 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2385 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2386
2387 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,
2409 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2410
2411 1, 2, 3, 4, 5,
2413 ];
2414 let mut fixed_hdr = new_fixed_hdr();
2415 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2416 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2417 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2418 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2419 let mut buf = &bytes[..];
2420 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2421 let copied_bytes = packet.copy_header_bytes_for_fragment();
2422 let mut expected_bytes = Vec::new();
2423 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2424 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2425 expected_bytes[6] = Ipv6ExtHdrType::DestinationOptions.into();
2426 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2427
2428 #[rustfmt::skip]
2433 let mut bytes = [
2434 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2436 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2437
2438 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,
2461 ];
2462 let mut fixed_hdr = new_fixed_hdr();
2463 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2464 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2465 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2466 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2467 let mut buf = &bytes[..];
2468 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2469 let copied_bytes = packet.copy_header_bytes_for_fragment();
2470 let mut expected_bytes = Vec::new();
2471 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN + 8]);
2472 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 16..bytes.len() - 5]);
2473 expected_bytes[IPV6_FIXED_HDR_LEN] = Ipv6ExtHdrType::DestinationOptions.into();
2474 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2475
2476 #[rustfmt::skip]
2481 let mut bytes = [
2482 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2484 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2485
2486 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,
2500 ];
2501 let mut fixed_hdr = new_fixed_hdr();
2502 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2503 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2504 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2505 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2506 let mut buf = &bytes[..];
2507 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2508 let copied_bytes = packet.copy_header_bytes_for_fragment();
2509 let mut expected_bytes = Vec::new();
2510 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2511 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2512 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2513 }
2514
2515 #[test]
2516 fn test_next_multiple_of_eight() {
2517 for x in 0usize..=IPV6_HBH_OPTIONS_MAX_LEN {
2518 let y = next_multiple_of_eight(x);
2519 assert_eq!(y % 8, 0);
2520 assert!(y >= x);
2521 if x % 8 == 0 {
2522 assert_eq!(x, y);
2523 } else {
2524 assert_eq!(x + (8 - x % 8), y);
2525 }
2526 }
2527 }
2528
2529 fn create_ipv4_and_ipv6_builders(
2530 proto_v4: Ipv4Proto,
2531 proto_v6: Ipv6Proto,
2532 ) -> (Ipv4PacketBuilder, Ipv6PacketBuilder) {
2533 const IP_DSCP_AND_ECN: DscpAndEcn = DscpAndEcn::new(0x12, 3);
2534 const IP_TTL: u8 = 64;
2535
2536 let mut ipv4_builder =
2537 Ipv4PacketBuilder::new(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP, IP_TTL, proto_v4);
2538 ipv4_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
2539 ipv4_builder.df_flag(false);
2540 ipv4_builder.mf_flag(false);
2541 ipv4_builder.fragment_offset(FragmentOffset::ZERO);
2542
2543 let mut ipv6_builder =
2544 Ipv6PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, IP_TTL, proto_v6);
2545 ipv6_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
2546 ipv6_builder.flowlabel(0x456);
2547
2548 (ipv4_builder, ipv6_builder)
2549 }
2550
2551 fn create_tcp_ipv4_and_ipv6_pkt(
2552 ) -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
2553 use crate::tcp::TcpSegmentBuilder;
2554 use core::num::NonZeroU16;
2555
2556 let tcp_src_port: NonZeroU16 = NonZeroU16::new(20).unwrap();
2557 let tcp_dst_port: NonZeroU16 = NonZeroU16::new(30).unwrap();
2558 const TCP_SEQ_NUM: u32 = 4321;
2559 const TCP_ACK_NUM: Option<u32> = Some(1234);
2560 const TCP_WINDOW_SIZE: u16 = 12345;
2561 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2562
2563 let (ipv4_builder, ipv6_builder) =
2564 create_ipv4_and_ipv6_builders(IpProto::Tcp.into(), IpProto::Tcp.into());
2565
2566 let tcp_builder = TcpSegmentBuilder::new(
2567 DEFAULT_V4_SRC_IP,
2568 DEFAULT_V4_DST_IP,
2569 tcp_src_port,
2570 tcp_dst_port,
2571 TCP_SEQ_NUM,
2572 TCP_ACK_NUM,
2573 TCP_WINDOW_SIZE,
2574 );
2575
2576 let v4_pkt_buf = (&PAYLOAD)
2577 .into_serializer()
2578 .wrap_in(tcp_builder)
2579 .wrap_in(ipv4_builder)
2580 .serialize_vec_outer()
2581 .expect("Failed to serialize to v4_pkt_buf");
2582
2583 let v6_tcp_builder = TcpSegmentBuilder::new(
2584 DEFAULT_SRC_IP,
2585 DEFAULT_DST_IP,
2586 tcp_src_port,
2587 tcp_dst_port,
2588 TCP_SEQ_NUM,
2589 TCP_ACK_NUM,
2590 TCP_WINDOW_SIZE,
2591 );
2592
2593 let v6_pkt_buf = (&PAYLOAD)
2594 .into_serializer()
2595 .wrap_in(v6_tcp_builder)
2596 .wrap_in(ipv6_builder)
2597 .serialize_vec_outer()
2598 .expect("Failed to serialize to v4_pkt_buf");
2599
2600 (v4_pkt_buf, v6_pkt_buf)
2601 }
2602
2603 #[test]
2604 fn test_nat64_translate_tcp() {
2605 let (expected_v4_pkt_buf, mut v6_pkt_buf) = create_tcp_ipv4_and_ipv6_pkt();
2606
2607 let parsed_v6_packet =
2608 v6_pkt_buf.parse::<Ipv6Packet<_>>().expect("Failed to parse v6_pkt_buf");
2609 let nat64_translation_result =
2610 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2611
2612 let serializable_pkt =
2613 assert_matches!(nat64_translation_result, Nat64TranslationResult::Forward(s) => s);
2614
2615 let translated_v4_pkt_buf = serializable_pkt
2616 .serialize_vec_outer()
2617 .expect("Failed to serialize to translated_v4_pkt_buf");
2618
2619 assert_eq!(
2620 expected_v4_pkt_buf.to_flattened_vec(),
2621 translated_v4_pkt_buf.to_flattened_vec()
2622 );
2623 }
2624
2625 fn create_udp_ipv4_and_ipv6_pkt(
2626 ) -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
2627 use crate::udp::UdpPacketBuilder;
2628 use core::num::NonZeroU16;
2629
2630 let udp_src_port: NonZeroU16 = NonZeroU16::new(35000).unwrap();
2631 let udp_dst_port: NonZeroU16 = NonZeroU16::new(53).unwrap();
2632 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2633
2634 let (ipv4_builder, ipv6_builder) =
2635 create_ipv4_and_ipv6_builders(IpProto::Udp.into(), IpProto::Udp.into());
2636
2637 let v4_udp_builder = UdpPacketBuilder::new(
2638 DEFAULT_V4_SRC_IP,
2639 DEFAULT_V4_DST_IP,
2640 Some(udp_src_port),
2641 udp_dst_port,
2642 );
2643
2644 let v4_pkt_buf = (&PAYLOAD)
2645 .into_serializer()
2646 .wrap_in(v4_udp_builder)
2647 .wrap_in(ipv4_builder)
2648 .serialize_vec_outer()
2649 .expect("Unable to serialize to v4_pkt_buf");
2650
2651 let v6_udp_builder =
2652 UdpPacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, Some(udp_src_port), udp_dst_port);
2653
2654 let v6_pkt_buf = (&PAYLOAD)
2655 .into_serializer()
2656 .wrap_in(v6_udp_builder)
2657 .wrap_in(ipv6_builder)
2658 .serialize_vec_outer()
2659 .expect("Unable to serialize to v6_pkt_buf");
2660
2661 (v4_pkt_buf, v6_pkt_buf)
2662 }
2663
2664 #[test]
2665 fn test_nat64_translate_udp() {
2666 let (expected_v4_pkt_buf, mut v6_pkt_buf) = create_udp_ipv4_and_ipv6_pkt();
2667
2668 let parsed_v6_packet =
2669 v6_pkt_buf.parse::<Ipv6Packet<_>>().expect("Unable to parse Ipv6Packet");
2670 let nat64_translation_result =
2671 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2672
2673 let serializable_pkt = assert_matches!(nat64_translation_result,
2674 Nat64TranslationResult::Forward(s) => s);
2675
2676 let translated_v4_pkt_buf = serializable_pkt
2677 .serialize_vec_outer()
2678 .expect("Unable to serialize to translated_v4_pkt_buf");
2679
2680 assert_eq!(
2681 expected_v4_pkt_buf.to_flattened_vec(),
2682 translated_v4_pkt_buf.to_flattened_vec()
2683 );
2684 }
2685
2686 #[test]
2687 fn test_nat64_translate_non_tcp_udp_icmp() {
2688 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2689
2690 let (ipv4_builder, ipv6_builder) =
2691 create_ipv4_and_ipv6_builders(Ipv4Proto::Other(59), Ipv6Proto::Other(59));
2692
2693 let expected_v4_pkt_buf = (&PAYLOAD)
2694 .into_serializer()
2695 .wrap_in(ipv4_builder)
2696 .serialize_vec_outer()
2697 .expect("Unable to serialize to expected_v4_pkt_buf");
2698
2699 let mut v6_pkt_buf = (&PAYLOAD)
2700 .into_serializer()
2701 .wrap_in(ipv6_builder)
2702 .serialize_vec_outer()
2703 .expect("Unable to serialize to v6_pkt_buf");
2704
2705 let translated_v4_pkt_buf = {
2706 let parsed_v6_packet = v6_pkt_buf
2707 .parse::<Ipv6Packet<_>>()
2708 .expect("Unable to serialize to translated_v4_pkt_buf");
2709
2710 let nat64_translation_result =
2711 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2712
2713 let serializable_pkt = assert_matches!(nat64_translation_result,
2714 Nat64TranslationResult::Forward(s) => s);
2715
2716 let translated_buf = serializable_pkt
2717 .serialize_vec_outer()
2718 .expect("Unable to serialize to translated_buf");
2719
2720 translated_buf
2721 };
2722
2723 assert_eq!(
2724 expected_v4_pkt_buf.to_flattened_vec(),
2725 translated_v4_pkt_buf.to_flattened_vec()
2726 );
2727 }
2728
2729 #[test_case(new_builder(), true; "fixed header more frags")]
2730 #[test_case(Ipv6PacketBuilderWithHbhOptions::new(
2731 new_builder(),
2732 &[HopByHopOption {
2733 action: ExtensionHeaderOptionAction::SkipAndContinue,
2734 mutable: false,
2735 data: HopByHopOptionData::RouterAlert { data: 0 },
2736 }]).unwrap(), false; "hbh last frag")]
2737 fn ipv6_packet_builder_with_fragment_header<
2738 B: Ipv6HeaderBuilder + Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>> + Debug,
2739 >(
2740 inner: B,
2741 more_fragments: bool,
2742 ) {
2743 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2744 let fragment_offset = FragmentOffset::new(13).unwrap();
2745 let identification = 0xABCDABCD;
2746 let builder = Ipv6PacketBuilderWithFragmentHeader::new(
2747 inner,
2748 fragment_offset,
2749 more_fragments,
2750 identification,
2751 );
2752 let mut serialized =
2753 builder.wrap_body(PAYLOAD.into_serializer()).serialize_vec_outer().unwrap().unwrap_b();
2754 let packet = serialized.parse::<Ipv6Packet<_>>().unwrap();
2755 assert!(packet.fragment_header_present());
2756 assert_eq!(packet.proto(), Ipv6Proto::Proto(IpProto::Tcp));
2757 let fragment_data = packet
2758 .extension_hdrs
2759 .into_iter()
2760 .find_map(|ext_hdr| match ext_hdr.into_data() {
2761 Ipv6ExtensionHeaderData::Fragment { fragment_data } => Some(fragment_data),
2762 _ => None,
2763 })
2764 .unwrap();
2765 assert_eq!(fragment_data.fragment_offset(), fragment_offset);
2766 assert_eq!(fragment_data.identification(), identification);
2767 assert_eq!(fragment_data.m_flag(), more_fragments);
2768 }
2769
2770 #[test]
2773 fn extension_headers_take_from_max_body_size() {
2774 let builder = new_builder();
2775 assert_eq!(builder.constraints().max_body_len(), IPV6_MAX_PAYLOAD_LENGTH);
2776 let builder =
2777 Ipv6PacketBuilderWithFragmentHeader::new(builder, FragmentOffset::ZERO, false, 1234);
2778 assert_eq!(
2779 builder.constraints().max_body_len(),
2780 IPV6_MAX_PAYLOAD_LENGTH - IPV6_FRAGMENT_EXT_HDR_LEN
2781 );
2782 }
2783}