1pub mod ext_hdrs;
12
13use alloc::vec::Vec;
14use core::borrow::Borrow;
15use core::fmt::{self, Debug, Formatter};
16use core::ops::Range;
17
18use log::debug;
19use net_types::ip::{GenericOverIp, Ipv4Addr, Ipv6, Ipv6Addr, Ipv6SourceAddr};
20use packet::records::{AlignedRecordSequenceBuilder, Records, RecordsRaw};
21use packet::{
22 BufferProvider, BufferView, BufferViewMut, EmptyBuf, FragmentedBytesMut, FromRaw,
23 GrowBufferMut, InnerPacketBuilder, LayoutBufferAlloc, MaybeParsed, PacketBuilder,
24 PacketConstraints, ParsablePacket, ParseMetadata, PartialPacketBuilder, 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::{HDR_PREFIX_LEN, Ipv4PacketBuilder};
39use crate::tcp::{TcpParseArgs, TcpSegment};
40use crate::udp::{UdpPacket, UdpParseArgs};
41
42use ext_hdrs::{
43 ExtensionHeaderOptionAction, HopByHopOption, HopByHopOptionData, IPV6_FRAGMENT_EXT_HDR_LEN,
44 Ipv6ExtensionHeader, Ipv6ExtensionHeaderData, Ipv6ExtensionHeaderImpl,
45 Ipv6ExtensionHeaderParsingContext, Ipv6ExtensionHeaderParsingError, is_valid_next_header,
46 is_valid_next_header_upper_layer,
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 => {
154 IpParseErrorAction::DiscardPacket
155 }
156 ExtensionHeaderOptionAction::DiscardPacketSendIcmp => {
157 IpParseErrorAction::DiscardPacketSendIcmp
158 }
159 ExtensionHeaderOptionAction::DiscardPacketSendIcmpNoMulticast => {
160 IpParseErrorAction::DiscardPacketSendIcmpNoMulticast
161 }
162 };
163
164 (p, action)
165 }
166 };
167
168 IpParseError::ParameterProblem {
169 src_ip: hdr.src_ip,
170 dst_ip: hdr.dst_ip,
171 code: Icmpv6ParameterProblemCode::UnrecognizedIpv6Option,
172 pointer,
173 must_send_icmp,
174 header_len: (),
175 action,
176 }
177 }
178 Ipv6ExtensionHeaderParsingError::BufferExhausted
179 | Ipv6ExtensionHeaderParsingError::MalformedData => {
180 IpParseError::Parse { error: ParseError::Format }
183 }
184 }
185}
186
187#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
189#[repr(C)]
190pub struct FixedHeader {
191 version_tc_flowlabel: [u8; 4],
192 payload_len: U16,
193 next_hdr: u8,
194 hop_limit: u8,
195 src_ip: Ipv6Addr,
196 dst_ip: Ipv6Addr,
197}
198
199const IP_VERSION: u8 = 6;
200const VERSION_OFFSET: u8 = 4;
201const FLOW_LABEL_MAX: u32 = (1 << 20) - 1;
202
203impl FixedHeader {
204 #[allow(clippy::too_many_arguments)]
205 fn new(
206 dscp_and_ecn: DscpAndEcn,
207 flow_label: u32,
208 payload_len: u16,
209 next_hdr: u8,
210 hop_limit: u8,
211 src_ip: Ipv6Addr,
212 dst_ip: Ipv6Addr,
213 ) -> FixedHeader {
214 debug_assert!(flow_label <= FLOW_LABEL_MAX);
215
216 let traffic_class = dscp_and_ecn.raw();
217 FixedHeader {
218 version_tc_flowlabel: [
219 IP_VERSION << VERSION_OFFSET | traffic_class >> 4,
220 (traffic_class << 4) | ((flow_label >> 16) as u8),
221 (flow_label >> 8) as u8,
222 flow_label as u8,
223 ],
224 payload_len: U16::new(payload_len),
225 next_hdr,
226 hop_limit,
227 src_ip,
228 dst_ip,
229 }
230 }
231
232 fn version(&self) -> u8 {
233 self.version_tc_flowlabel[0] >> 4
234 }
235
236 fn dscp_and_ecn(&self) -> DscpAndEcn {
237 ((self.version_tc_flowlabel[0] & 0xF) << 4 | self.version_tc_flowlabel[1] >> 4).into()
238 }
239
240 fn flowlabel(&self) -> u32 {
241 (u32::from(self.version_tc_flowlabel[1]) & 0xF) << 16
242 | u32::from(self.version_tc_flowlabel[2]) << 8
243 | u32::from(self.version_tc_flowlabel[3])
244 }
245}
246
247pub trait Ipv6Header {
252 fn get_fixed_header(&self) -> &FixedHeader;
254
255 fn hop_limit(&self) -> u8 {
257 self.get_fixed_header().hop_limit
258 }
259
260 fn next_header(&self) -> u8 {
262 self.get_fixed_header().next_hdr
263 }
264
265 fn src_ip(&self) -> Ipv6Addr {
267 self.get_fixed_header().src_ip
268 }
269
270 fn dst_ip(&self) -> Ipv6Addr {
272 self.get_fixed_header().dst_ip
273 }
274
275 fn dscp_and_ecn(&self) -> DscpAndEcn {
278 self.get_fixed_header().dscp_and_ecn()
279 }
280}
281
282impl Ipv6Header for FixedHeader {
283 fn get_fixed_header(&self) -> &FixedHeader {
284 self
285 }
286}
287
288pub struct Ipv6Packet<B> {
294 fixed_hdr: Ref<B, FixedHeader>,
295 extension_hdrs: Records<B, Ipv6ExtensionHeaderImpl>,
296 body: B,
297 proto: Ipv6Proto,
298}
299
300impl<B: SplitByteSlice, I: IpExt> GenericOverIp<I> for Ipv6Packet<B> {
301 type Type = <I as IpExt>::Packet<B>;
302}
303
304impl<B: SplitByteSlice> Ipv6Header for Ipv6Packet<B> {
305 fn get_fixed_header(&self) -> &FixedHeader {
306 &self.fixed_hdr
307 }
308}
309
310impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv6Packet<B> {
311 type Error = IpParseError<Ipv6>;
312
313 fn parse_metadata(&self) -> ParseMetadata {
314 let header_len = Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.bytes().len();
315 ParseMetadata::from_packet(header_len, self.body.len(), 0)
316 }
317
318 fn parse<BV: BufferView<B>>(buffer: BV, _args: ()) -> IpParseResult<Ipv6, Self> {
319 Ipv6PacketRaw::parse(buffer, ()).and_then(Ipv6Packet::try_from_raw)
320 }
321}
322
323impl<B: SplitByteSlice> FromRaw<Ipv6PacketRaw<B>, ()> for Ipv6Packet<B> {
324 type Error = IpParseError<Ipv6>;
325
326 fn try_from_raw_with(raw: Ipv6PacketRaw<B>, _args: ()) -> Result<Self, Self::Error> {
327 let fixed_hdr = raw.fixed_hdr;
328
329 if !is_valid_next_header(fixed_hdr.next_hdr, true) {
332 return debug_err!(
333 Err(IpParseError::ParameterProblem {
334 src_ip: fixed_hdr.src_ip,
335 dst_ip: fixed_hdr.dst_ip,
336 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
337 pointer: u32::from(NEXT_HEADER_OFFSET),
338 must_send_icmp: false,
339 header_len: (),
340 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
341 }),
342 "Unrecognized next header value"
343 );
344 }
345
346 let extension_hdrs = match raw.extension_hdrs {
347 MaybeParsed::Complete(v) => {
348 Records::try_from_raw(v).map_err(|e| ext_hdr_err_fn(&fixed_hdr, e))?
349 }
350 MaybeParsed::Incomplete(_) => {
351 return debug_err!(
352 Err(ParseError::Format.into()),
353 "Incomplete IPv6 extension headers"
354 );
355 }
356 };
357
358 let (body, proto) =
362 raw.body_proto.expect("Unable to retrieve Ipv6Proto or MaybeParsed body from raw");
363 debug_assert!(is_valid_next_header_upper_layer(proto.into()));
364
365 let body = match body {
366 MaybeParsed::Complete(b) => b,
367 MaybeParsed::Incomplete(_b) => {
368 return debug_err!(Err(ParseError::Format.into()), "IPv6 body unretrievable.");
369 }
370 };
371
372 if extension_hdrs.bytes().len() + body.len() != usize::from(fixed_hdr.payload_len.get()) {
377 return debug_err!(
378 Err(ParseError::Format.into()),
379 "Payload len does not match body and extension headers"
380 );
381 }
382
383 if fixed_hdr.version() != 6 {
385 return debug_err!(
386 Err(ParseError::Format.into()),
387 "unexpected IP version: {}",
388 fixed_hdr.version()
389 );
390 }
391
392 Ok(Ipv6Packet { fixed_hdr, extension_hdrs, body, proto })
393 }
394}
395
396impl<B: SplitByteSlice> Ipv6Packet<B> {
397 pub fn iter_extension_hdrs(&self) -> impl Iterator<Item = Ipv6ExtensionHeader<'_>> {
399 self.extension_hdrs.iter()
400 }
401
402 pub fn body(&self) -> &[u8] {
404 &self.body
405 }
406
407 pub fn dscp_and_ecn(&self) -> DscpAndEcn {
410 self.fixed_hdr.dscp_and_ecn()
411 }
412
413 pub fn flowlabel(&self) -> u32 {
415 self.fixed_hdr.flowlabel()
416 }
417
418 pub fn proto(&self) -> Ipv6Proto {
424 self.proto
425 }
426
427 pub fn src_ipv6(&self) -> Option<Ipv6SourceAddr> {
434 Ipv6SourceAddr::new(self.fixed_hdr.src_ip)
435 }
436
437 pub fn copy_header_bytes_for_fragment(&self) -> Vec<u8> {
448 let expected_bytes_len = self.header_len() - IPV6_FRAGMENT_EXT_HDR_LEN;
451 let mut bytes = Vec::with_capacity(expected_bytes_len);
452
453 bytes.extend_from_slice(Ref::bytes(&self.fixed_hdr));
454
455 let mut iter = self.extension_hdrs.iter();
459
460 let ext_hdr = iter.next().expect("packet must have at least one extension header");
464
465 if self.fixed_hdr.next_hdr == Ipv6ExtHdrType::Fragment.into() {
466 bytes[6] = ext_hdr.next_header;
472
473 bytes.extend_from_slice(&self.extension_hdrs.bytes()[IPV6_FRAGMENT_EXT_HDR_LEN..]);
475 } else {
476 let mut ext_hdr = ext_hdr;
477 let mut ext_hdr_start = 0;
478 let mut ext_hdr_end = iter.context().bytes_parsed;
479
480 loop {
486 let next_ext_hdr = iter
492 .next()
493 .expect("exhausted all extension headers without finding fragment header");
494
495 if let Ipv6ExtensionHeaderData::Fragment { .. } = next_ext_hdr.data() {
496 let fragment_hdr_end = ext_hdr_end + IPV6_FRAGMENT_EXT_HDR_LEN;
503 assert_eq!(fragment_hdr_end, iter.context().bytes_parsed);
504
505 let extension_hdr_bytes = self.extension_hdrs.bytes();
506
507 bytes.extend_from_slice(&extension_hdr_bytes[..ext_hdr_end]);
509
510 bytes.extend_from_slice(&extension_hdr_bytes[fragment_hdr_end..]);
512
513 match ext_hdr.data() {
516 Ipv6ExtensionHeaderData::HopByHopOptions { .. }
519 | Ipv6ExtensionHeaderData::DestinationOptions { .. } => {
520 bytes[IPV6_FIXED_HDR_LEN + ext_hdr_start] = next_ext_hdr.next_header;
521 }
522 Ipv6ExtensionHeaderData::Fragment { .. } => unreachable!(
523 "If we had a fragment header before `ext_hdr`, we should have used that instead"
524 ),
525 }
526
527 break;
528 }
529
530 ext_hdr = next_ext_hdr;
531 ext_hdr_start = ext_hdr_end;
532 ext_hdr_end = iter.context().bytes_parsed;
533 }
534 }
535
536 assert_eq!(bytes.len(), expected_bytes_len);
538 bytes
539 }
540
541 fn header_len(&self) -> usize {
542 Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.bytes().len()
543 }
544
545 fn fragment_header_present(&self) -> bool {
546 for ext_hdr in self.extension_hdrs.iter() {
547 if matches!(ext_hdr.data(), Ipv6ExtensionHeaderData::Fragment { .. }) {
548 return true;
549 }
550 }
551 false
552 }
553
554 pub fn builder(&self) -> Ipv6PacketBuilder {
556 Ipv6PacketBuilder {
557 dscp_and_ecn: self.dscp_and_ecn(),
558 flowlabel: self.flowlabel(),
559 hop_limit: self.hop_limit(),
560 proto: self.proto(),
561 src_ip: self.src_ip(),
562 dst_ip: self.dst_ip(),
563 }
564 }
565
566 pub fn nat64_translate(
592 &self,
593 v4_src_addr: Ipv4Addr,
594 v4_dst_addr: Ipv4Addr,
595 ) -> Nat64TranslationResult<impl Serializer<Buffer = EmptyBuf> + Debug + '_, Nat64Error> {
596 #[derive(Debug)]
599 enum Nat64Serializer<T, U, O> {
600 Tcp(T),
601 Udp(U),
602 Other(O),
603 }
604
605 impl<T, U, O> Serializer for Nat64Serializer<T, U, O>
606 where
607 T: Serializer<Buffer = EmptyBuf>,
608 U: Serializer<Buffer = EmptyBuf>,
609 O: Serializer<Buffer = EmptyBuf>,
610 {
611 type Buffer = EmptyBuf;
612 fn serialize<B, P>(
613 self,
614 outer: PacketConstraints,
615 provider: P,
616 ) -> Result<B, (SerializeError<P::Error>, Self)>
617 where
618 B: GrowBufferMut,
619 P: BufferProvider<Self::Buffer, B>,
620 {
621 match self {
622 Nat64Serializer::Tcp(serializer) => serializer
623 .serialize(outer, provider)
624 .map_err(|(err, ser)| (err, Nat64Serializer::Tcp(ser))),
625 Nat64Serializer::Udp(serializer) => serializer
626 .serialize(outer, provider)
627 .map_err(|(err, ser)| (err, Nat64Serializer::Udp(ser))),
628 Nat64Serializer::Other(serializer) => serializer
629 .serialize(outer, provider)
630 .map_err(|(err, ser)| (err, Nat64Serializer::Other(ser))),
631 }
632 }
633
634 fn serialize_new_buf<B: GrowBufferMut, A: LayoutBufferAlloc<B>>(
635 &self,
636 outer: PacketConstraints,
637 alloc: A,
638 ) -> Result<B, SerializeError<A::Error>> {
639 match self {
640 Nat64Serializer::Tcp(serializer) => serializer.serialize_new_buf(outer, alloc),
641 Nat64Serializer::Udp(serializer) => serializer.serialize_new_buf(outer, alloc),
642 Nat64Serializer::Other(serializer) => {
643 serializer.serialize_new_buf(outer, alloc)
644 }
645 }
646 }
647 }
648
649 if self.fragment_header_present() {
652 return Nat64TranslationResult::Err(Nat64Error::NotImplemented);
653 }
654
655 let v4_builder = |v4_proto| {
656 let mut builder =
657 Ipv4PacketBuilder::new(v4_src_addr, v4_dst_addr, self.hop_limit(), v4_proto);
658 builder.dscp_and_ecn(self.dscp_and_ecn());
659
660 const IPV4_HEADER_LEN_BYTES: usize = HDR_PREFIX_LEN;
665
666 builder.df_flag(self.body().len() + IPV4_HEADER_LEN_BYTES > 1260);
672
673 builder.fragment_offset(FragmentOffset::ZERO);
676 builder.mf_flag(false);
677
678 builder
679 };
680
681 match self.proto() {
682 Ipv6Proto::Proto(IpProto::Tcp) => {
683 let v4_pkt_builder = v4_builder(Ipv4Proto::Proto(IpProto::Tcp));
684 let args = TcpParseArgs::new(self.src_ip(), self.dst_ip());
685 match TcpSegment::parse(&mut self.body.as_bytes(), args) {
690 Ok(tcp) => {
691 let tcp_serializer =
695 Nat64Serializer::Tcp(tcp.into_serializer(v4_src_addr, v4_dst_addr));
696 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(tcp_serializer))
697 }
698 Err(msg) => {
699 debug!("Parsing of TCP segment failed: {:?}", msg);
700
701 let common_serializer =
710 Nat64Serializer::Other(self.body().into_serializer());
711 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
712 }
713 }
714 }
715
716 Ipv6Proto::Proto(IpProto::Udp) => {
721 let v4_pkt_builder = v4_builder(Ipv4Proto::Proto(IpProto::Udp));
722 let args = UdpParseArgs::new(self.src_ip(), self.dst_ip());
723 match UdpPacket::parse(&mut self.body.as_bytes(), args) {
724 Ok(udp) => {
725 let udp_serializer =
729 Nat64Serializer::Udp(udp.into_serializer(v4_src_addr, v4_dst_addr));
730 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(udp_serializer))
731 }
732 Err(msg) => {
733 debug!("Parsing of UDP packet failed: {:?}", msg);
734
735 let common_serializer =
745 Nat64Serializer::Other(self.body().into_serializer());
746 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
747 }
748 }
749 }
750
751 Ipv6Proto::Icmpv6 => Nat64TranslationResult::Err(Nat64Error::NotImplemented),
754
755 Ipv6Proto::Other(val) => {
775 let v4_pkt_builder = v4_builder(Ipv4Proto::Other(val));
776 let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
777 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
778 }
779
780 Ipv6Proto::NoNextHeader => {
781 let v4_pkt_builder = v4_builder(Ipv4Proto::Other(Ipv6Proto::NoNextHeader.into()));
782 let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
783 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
784 }
785
786 Ipv6Proto::Proto(IpProto::Reserved) => Nat64TranslationResult::Drop,
789 }
790 }
791
792 pub fn to_vec(&self) -> Vec<u8> {
794 let Ipv6Packet { fixed_hdr, extension_hdrs, body, proto: _ } = self;
795 let mut buf = Vec::with_capacity(
796 Ref::bytes(&fixed_hdr).len() + extension_hdrs.bytes().len() + body.as_bytes().len(),
797 );
798 buf.extend(Ref::bytes(&fixed_hdr));
799 buf.extend(extension_hdrs.bytes());
800 buf.extend(body.as_bytes());
801 buf
802 }
803}
804
805impl<B: SplitByteSliceMut> Ipv6Packet<B> {
806 pub fn set_src_ip(&mut self, addr: Ipv6Addr) {
808 self.fixed_hdr.src_ip = addr;
809 }
810
811 pub fn set_dst_ip(&mut self, addr: Ipv6Addr) {
813 self.fixed_hdr.dst_ip = addr;
814 }
815
816 pub fn set_hop_limit(&mut self, hlim: u8) {
818 self.fixed_hdr.hop_limit = hlim;
819 }
820
821 pub fn body_mut(&mut self) -> &mut [u8] {
823 &mut self.body
824 }
825
826 pub fn parts_with_body_mut(&mut self) -> (&FixedHeader, ExtensionHeaders<'_>, &mut [u8]) {
829 (&self.fixed_hdr, ExtensionHeaders(self.extension_hdrs.as_ref()), &mut self.body)
830 }
831}
832
833impl<B: SplitByteSlice> Debug for Ipv6Packet<B> {
834 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
835 f.debug_struct("Ipv6Packet")
836 .field("src_ip", &self.src_ip())
837 .field("dst_ip", &self.dst_ip())
838 .field("hop_limit", &self.hop_limit())
839 .field("proto", &self.proto())
840 .field("dscp", &self.dscp_and_ecn().dscp())
841 .field("ecn", &self.dscp_and_ecn().ecn())
842 .field("flowlabel", &self.flowlabel())
843 .field("extension headers", &"TODO")
844 .field("body", &alloc::format!("<{} bytes>", self.body.len()))
845 .finish()
846 }
847}
848
849pub struct ExtensionHeaders<'a>(Records<&'a [u8], Ipv6ExtensionHeaderImpl>);
851
852impl<'a> ExtensionHeaders<'a> {
853 pub fn iter(&self) -> impl Iterator<Item = Ipv6ExtensionHeader<'_>> {
855 self.0.iter()
856 }
857
858 pub fn bytes(&self) -> &[u8] {
860 self.0.bytes()
861 }
862}
863
864#[derive(Copy, Clone, Debug, Eq, PartialEq)]
870pub struct ExtHdrParseError;
871
872pub struct Ipv6PacketRaw<B> {
882 fixed_hdr: Ref<B, FixedHeader>,
884 extension_hdrs: MaybeParsed<RecordsRaw<B, Ipv6ExtensionHeaderImpl>, B>,
890 body_proto: Result<(MaybeParsed<B, B>, Ipv6Proto), ExtHdrParseError>,
903}
904
905impl<B> Ipv6PacketRaw<B> {
906 pub fn body_mut(&mut self) -> Option<&mut B> {
910 match self.body_proto {
911 Ok(ref mut b) => match b {
912 (MaybeParsed::Complete(ref mut b), _) => Some(b),
913 (MaybeParsed::Incomplete(ref mut b), _) => Some(b),
914 },
915 Err(_) => None,
916 }
917 }
918}
919
920impl<B: SplitByteSlice> Ipv6Header for Ipv6PacketRaw<B> {
921 fn get_fixed_header(&self) -> &FixedHeader {
922 &self.fixed_hdr
923 }
924}
925
926impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv6PacketRaw<B> {
927 type Error = IpParseError<Ipv6>;
928
929 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> Result<Self, Self::Error> {
930 let fixed_hdr = buffer
931 .take_obj_front::<FixedHeader>()
932 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for header"))?;
933 let payload_len = fixed_hdr.payload_len.get().into();
934 let _: Option<B> = buffer.len().checked_sub(payload_len).map(|padding| {
936 buffer.take_back(padding).unwrap_or_else(|| {
937 panic!("buffer.len()={} padding={}", buffer.len(), padding);
938 })
939 });
940
941 let mut extension_hdr_context = Ipv6ExtensionHeaderParsingContext::new(fixed_hdr.next_hdr);
942
943 let extension_hdrs =
944 RecordsRaw::parse_raw_with_mut_context(&mut buffer, &mut extension_hdr_context)
945 .map_incomplete(|(b, _)| b);
946
947 let body_proto = match &extension_hdrs {
948 MaybeParsed::Complete(r) => {
949 let _: &RecordsRaw<B, _> = r;
950 assert!(is_valid_next_header_upper_layer(extension_hdr_context.next_header));
971 let proto = Ipv6Proto::from(extension_hdr_context.next_header);
972 let body = MaybeParsed::new_with_min_len(
973 buffer.into_rest(),
974 payload_len.saturating_sub(extension_hdrs.len()),
975 );
976 Ok((body, proto))
977 }
978 MaybeParsed::Incomplete(b) => {
979 let _: &B = b;
980 Err(ExtHdrParseError)
981 }
982 };
983
984 Ok(Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto })
985 }
986
987 fn parse_metadata(&self) -> ParseMetadata {
988 let header_len = Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.len();
989 let body_len = self.body_proto.as_ref().map(|(b, _p)| b.len()).unwrap_or(0);
990 ParseMetadata::from_packet(header_len, body_len, 0)
991 }
992}
993
994impl<B: SplitByteSlice> Ipv6PacketRaw<B> {
995 pub fn body_proto(&self) -> Result<(MaybeParsed<&[u8], &[u8]>, Ipv6Proto), ExtHdrParseError> {
1008 self.body_proto
1009 .as_ref()
1010 .map(|(mp, proto)| {
1011 (mp.as_ref().map(|b| b.deref()).map_incomplete(|b| b.deref()), *proto)
1012 })
1013 .map_err(|e| *e)
1014 }
1015
1016 pub fn body(&self) -> Result<MaybeParsed<&[u8], &[u8]>, ExtHdrParseError> {
1027 self.body_proto().map(|(body, _proto)| body)
1028 }
1029
1030 pub fn proto(&self) -> Result<Ipv6Proto, ExtHdrParseError> {
1037 self.body_proto().map(|(_body, proto)| proto)
1038 }
1039}
1040
1041impl<B: SplitByteSliceMut> Ipv6PacketRaw<B> {
1042 pub fn set_src_ip(&mut self, addr: Ipv6Addr) {
1044 self.fixed_hdr.src_ip = addr;
1045 }
1046
1047 pub fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1049 self.fixed_hdr.dst_ip = addr;
1050 }
1051}
1052
1053pub enum NextHeader {
1056 NextLayer(Ipv6Proto),
1058 Extension(Ipv6ExtHdrType),
1060}
1061
1062impl From<NextHeader> for u8 {
1063 fn from(next_hdr: NextHeader) -> Self {
1064 match next_hdr {
1065 NextHeader::NextLayer(n) => n.into(),
1066 NextHeader::Extension(e) => e.into(),
1067 }
1068 }
1069}
1070
1071mod sealed {
1072 use super::*;
1073 pub trait Ipv6HeaderBefore<T> {}
1081
1082 impl<'a, O, T> Ipv6HeaderBefore<T> for &'a O where O: Ipv6HeaderBefore<T> {}
1083
1084 pub trait Ipv6HeaderBuilder {
1086 fn fixed_header(&self) -> &Ipv6PacketBuilder;
1088
1089 fn extension_headers_len(&self) -> usize;
1092
1093 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1098 &self,
1099 buffer: &mut BV,
1100 next_header: NextHeader,
1101 payload_len: usize,
1102 );
1103 }
1104}
1105use sealed::{Ipv6HeaderBefore, Ipv6HeaderBuilder};
1106
1107impl<'a, O> Ipv6HeaderBuilder for &'a O
1108where
1109 O: Ipv6HeaderBuilder,
1110{
1111 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1112 O::fixed_header(self)
1113 }
1114
1115 fn extension_headers_len(&self) -> usize {
1116 O::extension_headers_len(self)
1117 }
1118
1119 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1120 &self,
1121 buffer: &mut BV,
1122 next_header: NextHeader,
1123 payload_len: usize,
1124 ) {
1125 O::serialize_header(self, buffer, next_header, payload_len)
1126 }
1127}
1128
1129macro_rules! impl_packet_builder {
1134 {} => {
1135 fn constraints(&self) -> PacketConstraints {
1136 let ext_headers = self.extension_headers_len();
1137 let header_len = IPV6_FIXED_HDR_LEN + ext_headers;
1138 let footer_len = 0;
1139 let min_body_len = 0;
1140 let max_body_len = IPV6_MAX_PAYLOAD_LENGTH - ext_headers;
1143 PacketConstraints::new(header_len, footer_len, min_body_len, max_body_len)
1144 }
1145
1146 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
1147 let mut bv = &mut target.header;
1148 self.serialize_header(
1149 &mut bv,
1150 NextHeader::NextLayer(self.fixed_header().proto()),
1151 body.len(),
1152 );
1153 }
1154 }
1155}
1156
1157macro_rules! impl_partial_packet_builder {
1158 {} => {
1159 fn partial_serialize(&self, body_len: usize, mut buffer: &mut [u8]) {
1160 self.serialize_header(
1161 &mut &mut buffer,
1162 NextHeader::NextLayer(self.fixed_header().proto()),
1163 body_len,
1164 );
1165 }
1166 }
1167}
1168#[derive(Debug, Clone, Eq, PartialEq)]
1170pub struct Ipv6PacketBuilder {
1171 dscp_and_ecn: DscpAndEcn,
1172 flowlabel: u32,
1173 hop_limit: u8,
1174 proto: Ipv6Proto,
1177 src_ip: Ipv6Addr,
1178 dst_ip: Ipv6Addr,
1179}
1180
1181impl Ipv6PacketBuilder {
1182 pub fn new<S: Into<Ipv6Addr>, D: Into<Ipv6Addr>>(
1188 src_ip: S,
1189 dst_ip: D,
1190 hop_limit: u8,
1191 proto: Ipv6Proto,
1192 ) -> Ipv6PacketBuilder {
1193 Ipv6PacketBuilder {
1194 dscp_and_ecn: DscpAndEcn::default(),
1195 flowlabel: 0,
1196 hop_limit,
1197 proto,
1198 src_ip: src_ip.into(),
1199 dst_ip: dst_ip.into(),
1200 }
1201 }
1202
1203 pub fn dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1206 self.dscp_and_ecn = dscp_and_ecn;
1207 }
1208
1209 pub fn flowlabel(&mut self, flowlabel: u32) {
1215 assert!(flowlabel <= 1 << 20, "invalid flowlabel: {:x}", flowlabel);
1216 self.flowlabel = flowlabel;
1217 }
1218}
1219
1220impl Ipv6HeaderBuilder for Ipv6PacketBuilder {
1221 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1222 self
1223 }
1224
1225 fn extension_headers_len(&self) -> usize {
1226 0
1227 }
1228
1229 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1230 &self,
1231 buffer: &mut BV,
1232 next_header: NextHeader,
1233 payload_len: usize,
1234 ) {
1235 buffer
1236 .write_obj_front(&FixedHeader::new(
1237 self.dscp_and_ecn,
1238 self.flowlabel,
1239 {
1240 debug_assert!(payload_len <= core::u16::MAX as usize);
1247 payload_len as u16
1248 },
1249 next_header.into(),
1250 self.hop_limit,
1251 self.src_ip,
1252 self.dst_ip,
1253 ))
1254 .expect("not enough bytes for IPv6 fixed header");
1255 }
1256}
1257
1258impl PacketBuilder for Ipv6PacketBuilder {
1259 impl_packet_builder! {}
1260}
1261
1262impl PartialPacketBuilder for Ipv6PacketBuilder {
1263 impl_partial_packet_builder! {}
1264}
1265
1266#[derive(Debug, Clone)]
1268pub struct Ipv6PacketBuilderWithHbhOptions<'a, I> {
1269 prefix_builder: Ipv6PacketBuilder,
1270 hbh_options: AlignedRecordSequenceBuilder<HopByHopOption<'a>, I>,
1271}
1272
1273impl<'a, I> Ipv6PacketBuilderWithHbhOptions<'a, I>
1274where
1275 I: Iterator + Clone,
1276 I::Item: Borrow<HopByHopOption<'a>>,
1277{
1278 pub fn new<T: IntoIterator<Item = I::Item, IntoIter = I>>(
1280 prefix_builder: Ipv6PacketBuilder,
1281 options: T,
1282 ) -> Option<Ipv6PacketBuilderWithHbhOptions<'a, I>> {
1283 let iter = options.into_iter();
1284 if iter
1287 .clone()
1288 .filter(|r| matches!(r.borrow().data, HopByHopOptionData::RouterAlert { .. }))
1289 .count()
1290 > 1
1291 {
1292 return None;
1293 }
1294 let hbh_options = AlignedRecordSequenceBuilder::new(2, iter);
1295 if next_multiple_of_eight(2 + hbh_options.serialized_len()) > IPV6_HBH_OPTIONS_MAX_LEN {
1297 return None;
1298 }
1299 Some(Ipv6PacketBuilderWithHbhOptions { prefix_builder, hbh_options })
1300 }
1301
1302 fn aligned_hbh_len(&self) -> usize {
1303 let opt_len = self.hbh_options.serialized_len();
1304 let hbh_len = opt_len + 2;
1305 next_multiple_of_eight(hbh_len)
1306 }
1307}
1308
1309fn next_multiple_of_eight(x: usize) -> usize {
1310 (x + 7) & (!7)
1311}
1312
1313impl IpPacketBuilder<Ipv6> for Ipv6PacketBuilder {
1314 fn new(src_ip: Ipv6Addr, dst_ip: Ipv6Addr, ttl: u8, proto: Ipv6Proto) -> Self {
1315 Ipv6PacketBuilder::new(src_ip, dst_ip, ttl, proto)
1316 }
1317
1318 fn src_ip(&self) -> Ipv6Addr {
1319 self.src_ip
1320 }
1321
1322 fn set_src_ip(&mut self, addr: Ipv6Addr) {
1323 self.src_ip = addr;
1324 }
1325
1326 fn dst_ip(&self) -> Ipv6Addr {
1327 self.dst_ip
1328 }
1329
1330 fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1331 self.dst_ip = addr;
1332 }
1333
1334 fn proto(&self) -> Ipv6Proto {
1335 self.proto
1336 }
1337
1338 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1339 self.dscp_and_ecn = dscp_and_ecn;
1340 }
1341}
1342
1343impl<'a, I> Ipv6HeaderBuilder for Ipv6PacketBuilderWithHbhOptions<'a, I>
1344where
1345 I: Iterator + Clone,
1346 I::Item: Borrow<HopByHopOption<'a>>,
1347{
1348 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1349 &self.prefix_builder
1350 }
1351
1352 fn extension_headers_len(&self) -> usize {
1353 self.prefix_builder.extension_headers_len() + self.aligned_hbh_len()
1354 }
1355
1356 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1357 &self,
1358 buffer: &mut BV,
1359 next_header: NextHeader,
1360 payload_len: usize,
1361 ) {
1362 let aligned_hbh_len = self.aligned_hbh_len();
1363 self.prefix_builder.serialize_header(
1365 buffer,
1366 NextHeader::Extension(Ipv6ExtHdrType::HopByHopOptions),
1367 payload_len + aligned_hbh_len,
1368 );
1369 let mut hbh_header = buffer.take_front(aligned_hbh_len).unwrap();
1371 let hbh_header = hbh_header.as_mut();
1372 hbh_header[0] = next_header.into();
1373 hbh_header[1] = u8::try_from((aligned_hbh_len - 8) / 8).expect("extension header too big");
1374 self.hbh_options.serialize_into(&mut hbh_header[2..]);
1375 }
1376}
1377
1378impl<'a, I> PacketBuilder for Ipv6PacketBuilderWithHbhOptions<'a, I>
1379where
1380 I: Iterator + Clone,
1381 I::Item: Borrow<HopByHopOption<'a>>,
1382{
1383 impl_packet_builder! {}
1384}
1385
1386impl<'a, I> PartialPacketBuilder for Ipv6PacketBuilderWithHbhOptions<'a, I>
1387where
1388 I: Iterator + Clone,
1389 I::Item: Borrow<HopByHopOption<'a>>,
1390{
1391 impl_partial_packet_builder! {}
1392}
1393
1394impl<'a, I> IpPacketBuilder<Ipv6> for Ipv6PacketBuilderWithHbhOptions<'a, I>
1395where
1396 I: Iterator<Item: Borrow<HopByHopOption<'a>>> + Debug + Default + Clone,
1397{
1398 fn new(src_ip: Ipv6Addr, dst_ip: Ipv6Addr, ttl: u8, proto: Ipv6Proto) -> Self {
1399 Ipv6PacketBuilderWithHbhOptions::new(
1400 Ipv6PacketBuilder::new(src_ip, dst_ip, ttl, proto),
1401 I::default(),
1402 )
1403 .expect("packet builder with no options should be valid")
1404 }
1405
1406 fn src_ip(&self) -> Ipv6Addr {
1407 self.prefix_builder.src_ip
1408 }
1409
1410 fn set_src_ip(&mut self, addr: Ipv6Addr) {
1411 self.prefix_builder.src_ip = addr;
1412 }
1413
1414 fn dst_ip(&self) -> Ipv6Addr {
1415 self.prefix_builder.dst_ip
1416 }
1417
1418 fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1419 self.prefix_builder.dst_ip = addr;
1420 }
1421
1422 fn proto(&self) -> Ipv6Proto {
1423 self.prefix_builder.proto
1424 }
1425
1426 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1427 self.prefix_builder.set_dscp_and_ecn(dscp_and_ecn)
1428 }
1429}
1430
1431#[derive(Debug, Eq, PartialEq)]
1440pub struct Ipv6PacketBuilderWithFragmentHeader<B> {
1441 header_builder: B,
1442 fragment_offset: FragmentOffset,
1443 more_fragments: bool,
1444 identification: u32,
1445}
1446
1447impl<B: Ipv6HeaderBefore<Self>> Ipv6PacketBuilderWithFragmentHeader<B> {
1448 pub fn new(
1450 header_builder: B,
1451 fragment_offset: FragmentOffset,
1452 more_fragments: bool,
1453 identification: u32,
1454 ) -> Self {
1455 Self { header_builder, fragment_offset, more_fragments, identification }
1456 }
1457}
1458
1459impl<B> Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>> for Ipv6PacketBuilder {}
1460impl<B, I> Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>>
1461 for Ipv6PacketBuilderWithHbhOptions<'_, I>
1462{
1463}
1464
1465pub trait Ipv6PacketBuilderBeforeFragment:
1468 Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<Self>> + Ipv6HeaderBuilder + Sized
1469{
1470}
1471impl<B> Ipv6PacketBuilderBeforeFragment for B where
1472 B: Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<Self>> + Ipv6HeaderBuilder + Sized
1473{
1474}
1475
1476impl<B: Ipv6HeaderBuilder> Ipv6HeaderBuilder for Ipv6PacketBuilderWithFragmentHeader<B> {
1477 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1478 self.header_builder.fixed_header()
1479 }
1480
1481 fn extension_headers_len(&self) -> usize {
1482 self.header_builder.extension_headers_len() + IPV6_FRAGMENT_EXT_HDR_LEN
1483 }
1484
1485 fn serialize_header<BB: SplitByteSliceMut, BV: BufferViewMut<BB>>(
1486 &self,
1487 buffer: &mut BV,
1488 next_header: NextHeader,
1489 payload_len: usize,
1490 ) {
1491 let Self { header_builder, fragment_offset, more_fragments, identification } = self;
1492 let payload_len = payload_len + IPV6_FRAGMENT_EXT_HDR_LEN;
1493 header_builder.serialize_header(
1494 buffer,
1495 NextHeader::Extension(Ipv6ExtHdrType::Fragment),
1496 payload_len,
1497 );
1498 buffer.write_obj_front(&u8::from(next_header)).unwrap();
1499 let _: BB = buffer.take_front_zero(1).unwrap();
1501 let more_fragments = u16::from(*more_fragments);
1502 buffer
1503 .write_obj_front(&U16::new(fragment_offset.into_raw() << 3 | more_fragments))
1504 .unwrap();
1505 buffer.write_obj_front(&U32::new(*identification)).unwrap();
1506 }
1507}
1508
1509impl<B: Ipv6HeaderBuilder> PacketBuilder for Ipv6PacketBuilderWithFragmentHeader<B> {
1510 impl_packet_builder! {}
1511}
1512
1513impl<B: Ipv6HeaderBuilder> PartialPacketBuilder for Ipv6PacketBuilderWithFragmentHeader<B> {
1514 impl_partial_packet_builder! {}
1515}
1516
1517pub(crate) fn reassemble_fragmented_packet<
1519 B: SplitByteSliceMut,
1520 BV: BufferViewMut<B>,
1521 I: Iterator<Item = Vec<u8>>,
1522>(
1523 mut buffer: BV,
1524 header: Vec<u8>,
1525 body_fragments: I,
1526) -> IpParseResult<Ipv6, ()> {
1527 let bytes = buffer.as_mut();
1528
1529 bytes[0..header.len()].copy_from_slice(&header[..]);
1531 let mut byte_count = header.len();
1532
1533 for p in body_fragments {
1535 bytes[byte_count..byte_count + p.len()].copy_from_slice(&p[..]);
1536 byte_count += p.len();
1537 }
1538
1539 let payload_length = byte_count - IPV6_FIXED_HDR_LEN;
1551
1552 if payload_length > usize::from(core::u16::MAX) {
1555 return debug_err!(
1556 Err(ParseError::Format.into()),
1557 "fragmented packet payload length of {} bytes is too large",
1558 payload_length
1559 );
1560 }
1561
1562 let mut header = Ref::<_, FixedHeader>::from_prefix(bytes).unwrap().0;
1565
1566 header.payload_len.set(u16::try_from(payload_length).unwrap());
1568
1569 Ok(())
1570}
1571
1572#[cfg(test)]
1573mod tests {
1574 use assert_matches::assert_matches;
1575 use packet::{Buf, FragmentedBuffer, ParseBuffer};
1576 use test_case::test_case;
1577
1578 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1579 use crate::testutil::*;
1580
1581 use super::ext_hdrs::*;
1582 use super::*;
1583
1584 const DEFAULT_SRC_IP: Ipv6Addr =
1585 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1586 const DEFAULT_DST_IP: Ipv6Addr =
1587 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1588
1589 const DEFAULT_V4_SRC_IP: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1590 const DEFAULT_V4_DST_IP: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1591
1592 #[test]
1593 fn test_parse_serialize_full_tcp() {
1594 use crate::testdata::syn_v6::*;
1595
1596 let mut buf = ETHERNET_FRAME.bytes;
1597 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1598 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1599
1600 let mut body = frame.body();
1601 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1602 verify_ipv6_packet(&packet, IPV6_PACKET);
1603
1604 let buffer = packet
1606 .body()
1607 .into_serializer()
1608 .wrap_in(packet.builder())
1609 .wrap_in(frame.builder())
1610 .serialize_vec_outer()
1611 .unwrap();
1612 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1613
1614 assert_eq!(&packet.to_vec()[..], IPV6_PACKET.bytes);
1616 }
1617
1618 #[test]
1619 fn test_parse_serialize_full_udp() {
1620 use crate::testdata::dns_request_v6::*;
1621
1622 let mut buf = ETHERNET_FRAME.bytes;
1623 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1624 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1625
1626 let mut body = frame.body();
1627 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1628 verify_ipv6_packet(&packet, IPV6_PACKET);
1629
1630 let buffer = packet
1632 .body()
1633 .into_serializer()
1634 .wrap_in(packet.builder())
1635 .wrap_in(frame.builder())
1636 .serialize_vec_outer()
1637 .unwrap();
1638 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1639
1640 assert_eq!(&packet.to_vec()[..], IPV6_PACKET.bytes);
1642 }
1643
1644 #[test]
1645 fn test_parse_serialize_with_extension_headers() {
1646 use crate::testdata::mld_router_report::*;
1649
1650 let mut buf = REPORT;
1651 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1652 assert_eq!(packet.iter_extension_hdrs().count(), 1);
1653
1654 assert_eq!(&packet.to_vec()[..], REPORT);
1659 }
1660
1661 fn fixed_hdr_to_bytes(fixed_hdr: FixedHeader) -> [u8; IPV6_FIXED_HDR_LEN] {
1662 zerocopy::transmute!(fixed_hdr)
1663 }
1664
1665 fn new_fixed_hdr() -> FixedHeader {
1667 FixedHeader::new(
1668 DscpAndEcn::new(0, 2),
1669 0x77,
1670 0,
1671 IpProto::Tcp.into(),
1672 64,
1673 DEFAULT_SRC_IP,
1674 DEFAULT_DST_IP,
1675 )
1676 }
1677
1678 #[test]
1679 fn test_parse() {
1680 let mut buf = &fixed_hdr_to_bytes(new_fixed_hdr())[..];
1681 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1682 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1683 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1684 assert_eq!(packet.flowlabel(), 0x77);
1685 assert_eq!(packet.hop_limit(), 64);
1686 assert_eq!(packet.fixed_hdr.next_hdr, IpProto::Tcp.into());
1687 assert_eq!(packet.proto(), IpProto::Tcp.into());
1688 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1689 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1690 assert_eq!(packet.body(), []);
1691 }
1692
1693 #[test]
1694 fn test_parse_with_ext_hdrs() {
1695 #[rustfmt::skip]
1696 let mut buf = [
1697 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1699 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1700
1701 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,
1716 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1717
1718 IpProto::Tcp.into(), 1, 0, 1, 0, 1, 1, 0, 1, 6, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
1728 ];
1729 let mut fixed_hdr = new_fixed_hdr();
1730 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
1731 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1732 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1733 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1734 let mut buf = &buf[..];
1735 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1736 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1737 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1738 assert_eq!(packet.flowlabel(), 0x77);
1739 assert_eq!(packet.hop_limit(), 64);
1740 assert_eq!(packet.fixed_hdr.next_hdr, Ipv6ExtHdrType::HopByHopOptions.into());
1741 assert_eq!(packet.proto(), IpProto::Tcp.into());
1742 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1743 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1744 assert_eq!(packet.body(), [1, 2, 3, 4, 5]);
1745 let ext_hdrs: Vec<Ipv6ExtensionHeader<'_>> = packet.iter_extension_hdrs().collect();
1746 assert_eq!(ext_hdrs.len(), 2);
1747 assert_eq!(ext_hdrs[0].next_header, Ipv6ExtHdrType::Routing.into());
1749 if let Ipv6ExtensionHeaderData::HopByHopOptions { options } = ext_hdrs[0].data() {
1750 assert_eq!(options.iter().count(), 0);
1752 } else {
1753 panic!("Should have matched HopByHopOptions!");
1754 }
1755
1756 assert_eq!(ext_hdrs[1].next_header, IpProto::Tcp.into());
1761 if let Ipv6ExtensionHeaderData::DestinationOptions { options } = ext_hdrs[1].data() {
1762 assert_eq!(options.iter().count(), 0);
1764 } else {
1765 panic!("Should have matched DestinationOptions!");
1766 }
1767
1768 #[rustfmt::skip]
1770 let mut buf = [
1771 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1773 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1774
1775 Ipv6Proto::NoNextHeader.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
1784 ];
1785 let mut fixed_hdr = new_fixed_hdr();
1786 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
1787 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1788 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1789 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1790 let mut buf = &buf[..];
1791 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1792 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1793 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1794 assert_eq!(packet.flowlabel(), 0x77);
1795 assert_eq!(packet.hop_limit(), 64);
1796 assert_eq!(packet.fixed_hdr.next_hdr, Ipv6ExtHdrType::HopByHopOptions.into());
1797 assert_eq!(packet.proto(), Ipv6Proto::NoNextHeader);
1798 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1799 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1800 assert_eq!(packet.body(), [1, 2, 3, 4, 5]);
1801 let ext_hdrs: Vec<Ipv6ExtensionHeader<'_>> = packet.iter_extension_hdrs().collect();
1802 assert_eq!(ext_hdrs.len(), 1);
1803 assert_eq!(ext_hdrs[0].next_header, Ipv6Proto::NoNextHeader.into());
1805 if let Ipv6ExtensionHeaderData::HopByHopOptions { options } = ext_hdrs[0].data() {
1806 assert_eq!(options.iter().count(), 0);
1808 } else {
1809 panic!("Should have matched HopByHopOptions!");
1810 }
1811 }
1812
1813 #[test]
1814 fn test_parse_error() {
1815 let mut fixed_hdr = new_fixed_hdr();
1817 fixed_hdr.version_tc_flowlabel[0] = 0x50;
1818 assert_eq!(
1819 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1820 ParseError::Format.into()
1821 );
1822
1823 let mut fixed_hdr = new_fixed_hdr();
1825 fixed_hdr.payload_len = U16::new(2);
1826 assert_eq!(
1827 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1828 ParseError::Format.into()
1829 );
1830
1831 let mut fixed_hdr = new_fixed_hdr();
1833 fixed_hdr.next_hdr = 255;
1834 assert_eq!(
1835 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1836 IpParseError::ParameterProblem {
1837 src_ip: DEFAULT_SRC_IP,
1838 dst_ip: DEFAULT_DST_IP,
1839 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1840 pointer: u32::from(NEXT_HEADER_OFFSET),
1841 must_send_icmp: false,
1842 header_len: (),
1843 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1844 }
1845 );
1846
1847 let mut fixed_hdr = new_fixed_hdr();
1849 fixed_hdr.next_hdr = Ipv4Proto::Icmp.into();
1850 assert_eq!(
1851 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1852 IpParseError::ParameterProblem {
1853 src_ip: DEFAULT_SRC_IP,
1854 dst_ip: DEFAULT_DST_IP,
1855 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1856 pointer: u32::from(NEXT_HEADER_OFFSET),
1857 must_send_icmp: false,
1858 header_len: (),
1859 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1860 }
1861 );
1862
1863 #[rustfmt::skip]
1865 let mut buf = [
1866 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1868 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1869
1870 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,
1878 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1879
1880 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
1889 ];
1890 let mut fixed_hdr = new_fixed_hdr();
1891 fixed_hdr.next_hdr = Ipv6ExtHdrType::Routing.into();
1892 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1893 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1894 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1895 let mut buf = &buf[..];
1896 assert_eq!(
1897 buf.parse::<Ipv6Packet<_>>().unwrap_err(),
1898 IpParseError::ParameterProblem {
1899 src_ip: DEFAULT_SRC_IP,
1900 dst_ip: DEFAULT_DST_IP,
1901 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1902 pointer: IPV6_FIXED_HDR_LEN as u32,
1903 must_send_icmp: false,
1904 header_len: (),
1905 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1906 }
1907 );
1908
1909 #[rustfmt::skip]
1911 let mut buf = [
1912 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1914 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1915
1916 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,
1924 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1925
1926 1, 2, 3, 4, 5,
1928 ];
1929 let mut fixed_hdr = new_fixed_hdr();
1930 fixed_hdr.next_hdr = Ipv6ExtHdrType::Routing.into();
1931 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1932 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1933 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1934 let mut buf = &buf[..];
1935 assert_eq!(
1936 buf.parse::<Ipv6Packet<_>>().unwrap_err(),
1937 IpParseError::ParameterProblem {
1938 src_ip: DEFAULT_SRC_IP,
1939 dst_ip: DEFAULT_DST_IP,
1940 code: Icmpv6ParameterProblemCode::ErroneousHeaderField,
1941 pointer: (IPV6_FIXED_HDR_LEN as u32) + 2,
1942 must_send_icmp: true,
1943 header_len: (),
1944 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1945 }
1946 );
1947 }
1948
1949 #[test]
1950 fn test_parse_all_next_header_values() {
1951 let mut buf = [
1957 0x81, 0x13, 0x27, 0xeb, 0x75, 0x92, 0x33, 0x89, 0x01, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
1958 0x03, 0x70, 0x00, 0x22, 0xf7, 0x30, 0x2c, 0x06, 0xfe, 0xc9, 0x00, 0x2d, 0x3b, 0xeb,
1959 0xad, 0x3e, 0x5c, 0x41, 0xc8, 0x70, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x11, 0x00,
1960 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x4f, 0x4f, 0x6f, 0x4f, 0x4f, 0x4f, 0x4f,
1961 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x19, 0x19,
1962 0x19, 0x19, 0x19, 0x4f, 0x4f, 0x4f, 0x4f, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1963 0x00, 0x4f, 0x4f, 0x5a, 0x5a, 0x5a, 0xc9, 0x5a, 0x46, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
1964 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0xe4, 0x5a, 0x5a, 0x5a, 0x5a,
1965 ];
1966
1967 assert_matches!(
1970 (&buf[..]).parse::<Ipv6Packet<_>>(),
1971 Err(IpParseError::ParameterProblem {
1972 src_ip: _,
1973 dst_ip: _,
1974 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1975 pointer: 0,
1976 must_send_icmp: false,
1977 header_len: (),
1978 action: IpParseErrorAction::DiscardPacket,
1979 })
1980 );
1981
1982 for b in 0u8..=255 {
1985 buf[6] = b;
1987 let _: Result<_, _> = (&buf[..]).parse::<Ipv6Packet<_>>();
1988 }
1989 }
1990
1991 #[test]
1992 fn test_partial_parse() {
1993 use core::convert::TryInto as _;
1994 use core::ops::Deref as _;
1995
1996 #[rustfmt::skip]
1998 let mut buf = [
1999 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2001 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2002
2003 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2012 ];
2013 let len = buf.len() - IPV6_FIXED_HDR_LEN;
2014 let len = len.try_into().unwrap();
2015 let make_fixed_hdr = || {
2016 let mut fixed_hdr = new_fixed_hdr();
2017 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2018 fixed_hdr.payload_len = U16::new(len);
2019 fixed_hdr
2020 };
2021 const MALFORMED_BYTE: u8 = 10;
2023 buf[IPV6_FIXED_HDR_LEN + 1] = MALFORMED_BYTE;
2024 let fixed_hdr = fixed_hdr_to_bytes(make_fixed_hdr());
2025 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr);
2026 let mut buf = &buf[..];
2027 let partial = buf.parse::<Ipv6PacketRaw<_>>().unwrap();
2028 let Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto } = &partial;
2029 assert_eq!(fixed_hdr.deref(), &make_fixed_hdr());
2030 assert_eq!(
2031 *extension_hdrs.as_ref().incomplete().unwrap(),
2032 [IpProto::Tcp.into(), MALFORMED_BYTE]
2033 );
2034 assert_eq!(body_proto, &Err(ExtHdrParseError));
2035 assert!(Ipv6Packet::try_from_raw(partial).is_err());
2036
2037 let mut buf = [
2039 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,
2041 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
2043 ];
2044 let make_fixed_hdr = || {
2045 let mut fixed_hdr = new_fixed_hdr();
2046 fixed_hdr.next_hdr = IpProto::Tcp.into();
2047 fixed_hdr.payload_len = U16::new(10);
2048 fixed_hdr
2049 };
2050 let fixed_hdr = fixed_hdr_to_bytes(make_fixed_hdr());
2051 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr);
2052 let mut parsebuff = &buf[..];
2053 let partial = parsebuff.parse::<Ipv6PacketRaw<_>>().unwrap();
2054 let Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto } = &partial;
2055 assert_eq!(fixed_hdr.deref(), &make_fixed_hdr());
2056 assert_eq!(extension_hdrs.as_ref().complete().unwrap().deref(), []);
2057 let (body, proto) = body_proto.unwrap();
2058 assert_eq!(body.incomplete().unwrap(), &buf[IPV6_FIXED_HDR_LEN..]);
2059 assert_eq!(proto, IpProto::Tcp.into());
2060 assert!(Ipv6Packet::try_from_raw(partial).is_err());
2061 }
2062
2063 fn new_builder() -> Ipv6PacketBuilder {
2065 Ipv6PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, 64, IpProto::Tcp.into())
2066 }
2067
2068 #[test]
2069 fn test_serialize() {
2070 let mut builder = new_builder();
2071 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
2072 builder.flowlabel(0x10405);
2073 let mut buf = (&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2074 .into_serializer()
2075 .wrap_in(builder)
2076 .serialize_vec_outer()
2077 .unwrap();
2078 assert_eq!(
2080 buf.as_ref(),
2081 &[
2082 100, 177, 4, 5, 0, 10, 6, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
2083 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, 1, 2, 3, 4,
2084 5, 6, 7, 8, 9
2085 ][..],
2086 );
2087
2088 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2089 assert_eq!(packet.dscp_and_ecn().dscp(), 0x12);
2092 assert_eq!(packet.dscp_and_ecn().ecn(), 3);
2093 assert_eq!(packet.flowlabel(), 0x10405);
2094 }
2095
2096 #[test]
2097 fn test_serialize_zeroes() {
2098 let mut buf_0 = [0; IPV6_FIXED_HDR_LEN];
2101 let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], IPV6_FIXED_HDR_LEN..)
2102 .wrap_in(new_builder())
2103 .serialize_vec_outer()
2104 .unwrap()
2105 .unwrap_a();
2106 let mut buf_1 = [0xFF; IPV6_FIXED_HDR_LEN];
2107 let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], IPV6_FIXED_HDR_LEN..)
2108 .wrap_in(new_builder())
2109 .serialize_vec_outer()
2110 .unwrap()
2111 .unwrap_a();
2112 assert_eq!(&buf_0[..], &buf_1[..]);
2113 }
2114
2115 #[test]
2116 fn test_packet_builder_proto_not_next_header() {
2117 let mut buf = (&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2121 .into_serializer()
2122 .wrap_in(
2123 Ipv6PacketBuilderWithHbhOptions::new(
2124 new_builder(),
2125 &[HopByHopOption {
2126 action: ExtensionHeaderOptionAction::SkipAndContinue,
2127 mutable: false,
2128 data: HopByHopOptionData::RouterAlert { data: 0 },
2129 }],
2130 )
2131 .unwrap(),
2132 )
2133 .serialize_vec_outer()
2134 .unwrap();
2135 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2136 assert_eq!(packet.proto(), IpProto::Tcp.into());
2137 assert_eq!(packet.next_header(), Ipv6ExtHdrType::HopByHopOptions.into());
2138 }
2139
2140 #[test]
2141 #[should_panic(expected = "SizeLimitExceeded, Nested { inner: Buf { buf:")]
2142 fn test_serialize_panic_packet_length() {
2143 let _: Buf<&mut [u8]> = Buf::new(&mut [0; 1 << 16][..], ..)
2146 .wrap_in(new_builder())
2147 .serialize_vec_outer()
2148 .unwrap()
2149 .unwrap_a();
2150 }
2151
2152 #[test]
2153 #[should_panic(expected = "packet must have at least one extension header")]
2154 fn test_copy_header_bytes_for_fragment_without_ext_hdrs() {
2155 let mut buf = &fixed_hdr_to_bytes(new_fixed_hdr())[..];
2156 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2157 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2158 }
2159
2160 #[test]
2161 #[should_panic(expected = "exhausted all extension headers without finding fragment header")]
2162 fn test_copy_header_bytes_for_fragment_with_1_ext_hdr_no_fragment() {
2163 #[rustfmt::skip]
2164 let mut buf = [
2165 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2167 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2168
2169 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2178 ];
2179 let mut fixed_hdr = new_fixed_hdr();
2180 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2181 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2182 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2183 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2184 let mut buf = &buf[..];
2185 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2186 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2187 }
2188
2189 #[test]
2190 #[should_panic(expected = "exhausted all extension headers without finding fragment header")]
2191 fn test_copy_header_bytes_for_fragment_with_2_ext_hdr_no_fragment() {
2192 #[rustfmt::skip]
2193 let mut buf = [
2194 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2196 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2197
2198 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,
2215 ];
2216 let mut fixed_hdr = new_fixed_hdr();
2217 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2218 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2219 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2220 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2221 let mut buf = &buf[..];
2222 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2223 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2224 }
2225
2226 #[test]
2227 fn test_copy_header_bytes_for_fragment() {
2228 #[rustfmt::skip]
2233 let mut bytes = [
2234 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2236 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2237
2238 IpProto::Tcp.into(), 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5,
2246 ];
2247 let mut fixed_hdr = new_fixed_hdr();
2248 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2249 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2250 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2251 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2252 let mut buf = &bytes[..];
2253 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2254 let copied_bytes = packet.copy_header_bytes_for_fragment();
2255 bytes[6] = IpProto::Tcp.into();
2256 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN]);
2257
2258 #[rustfmt::skip]
2263 let mut bytes = [
2264 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2266 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2267
2268 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,
2283 ];
2284 let mut fixed_hdr = new_fixed_hdr();
2285 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2286 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2287 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2288 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2289 let mut buf = &bytes[..];
2290 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2291 let copied_bytes = packet.copy_header_bytes_for_fragment();
2292 bytes[IPV6_FIXED_HDR_LEN] = IpProto::Tcp.into();
2293 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN + 8]);
2294
2295 #[rustfmt::skip]
2300 let mut bytes = [
2301 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2303 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2304
2305 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,
2328 ];
2329 let mut fixed_hdr = new_fixed_hdr();
2330 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2331 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2332 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2333 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2334 let mut buf = &bytes[..];
2335 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2336 let copied_bytes = packet.copy_header_bytes_for_fragment();
2337 bytes[IPV6_FIXED_HDR_LEN + 8] = IpProto::Tcp.into();
2338 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN + 24]);
2339
2340 #[rustfmt::skip]
2345 let mut bytes = [
2346 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2348 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2349
2350 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,
2366 ];
2367 let mut fixed_hdr = new_fixed_hdr();
2368 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2369 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2370 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2371 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2372 let mut buf = &bytes[..];
2373 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2374 let copied_bytes = packet.copy_header_bytes_for_fragment();
2375 let mut expected_bytes = Vec::new();
2376 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2377 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2378 expected_bytes[6] = Ipv6ExtHdrType::DestinationOptions.into();
2379 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2380
2381 #[rustfmt::skip]
2386 let mut bytes = [
2387 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2389 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2390
2391 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,
2413 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2414
2415 1, 2, 3, 4, 5,
2417 ];
2418 let mut fixed_hdr = new_fixed_hdr();
2419 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.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]);
2428 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2429 expected_bytes[6] = 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, 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,
2465 ];
2466 let mut fixed_hdr = new_fixed_hdr();
2467 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2468 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2469 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2470 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2471 let mut buf = &bytes[..];
2472 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2473 let copied_bytes = packet.copy_header_bytes_for_fragment();
2474 let mut expected_bytes = Vec::new();
2475 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN + 8]);
2476 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 16..bytes.len() - 5]);
2477 expected_bytes[IPV6_FIXED_HDR_LEN] = Ipv6ExtHdrType::DestinationOptions.into();
2478 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2479
2480 #[rustfmt::skip]
2485 let mut bytes = [
2486 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2488 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2489
2490 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,
2504 ];
2505 let mut fixed_hdr = new_fixed_hdr();
2506 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2507 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2508 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2509 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2510 let mut buf = &bytes[..];
2511 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2512 let copied_bytes = packet.copy_header_bytes_for_fragment();
2513 let mut expected_bytes = Vec::new();
2514 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2515 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2516 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2517 }
2518
2519 #[test]
2520 fn test_next_multiple_of_eight() {
2521 for x in 0usize..=IPV6_HBH_OPTIONS_MAX_LEN {
2522 let y = next_multiple_of_eight(x);
2523 assert_eq!(y % 8, 0);
2524 assert!(y >= x);
2525 if x % 8 == 0 {
2526 assert_eq!(x, y);
2527 } else {
2528 assert_eq!(x + (8 - x % 8), y);
2529 }
2530 }
2531 }
2532
2533 fn create_ipv4_and_ipv6_builders(
2534 proto_v4: Ipv4Proto,
2535 proto_v6: Ipv6Proto,
2536 ) -> (Ipv4PacketBuilder, Ipv6PacketBuilder) {
2537 const IP_DSCP_AND_ECN: DscpAndEcn = DscpAndEcn::new(0x12, 3);
2538 const IP_TTL: u8 = 64;
2539
2540 let mut ipv4_builder =
2541 Ipv4PacketBuilder::new(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP, IP_TTL, proto_v4);
2542 ipv4_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
2543 ipv4_builder.df_flag(false);
2544 ipv4_builder.mf_flag(false);
2545 ipv4_builder.fragment_offset(FragmentOffset::ZERO);
2546
2547 let mut ipv6_builder =
2548 Ipv6PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, IP_TTL, proto_v6);
2549 ipv6_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
2550 ipv6_builder.flowlabel(0x456);
2551
2552 (ipv4_builder, ipv6_builder)
2553 }
2554
2555 fn create_tcp_ipv4_and_ipv6_pkt()
2556 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
2557 use crate::tcp::TcpSegmentBuilder;
2558 use core::num::NonZeroU16;
2559
2560 let tcp_src_port: NonZeroU16 = NonZeroU16::new(20).unwrap();
2561 let tcp_dst_port: NonZeroU16 = NonZeroU16::new(30).unwrap();
2562 const TCP_SEQ_NUM: u32 = 4321;
2563 const TCP_ACK_NUM: Option<u32> = Some(1234);
2564 const TCP_WINDOW_SIZE: u16 = 12345;
2565 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2566
2567 let (ipv4_builder, ipv6_builder) =
2568 create_ipv4_and_ipv6_builders(IpProto::Tcp.into(), IpProto::Tcp.into());
2569
2570 let tcp_builder = TcpSegmentBuilder::new(
2571 DEFAULT_V4_SRC_IP,
2572 DEFAULT_V4_DST_IP,
2573 tcp_src_port,
2574 tcp_dst_port,
2575 TCP_SEQ_NUM,
2576 TCP_ACK_NUM,
2577 TCP_WINDOW_SIZE,
2578 );
2579
2580 let v4_pkt_buf = (&PAYLOAD)
2581 .into_serializer()
2582 .wrap_in(tcp_builder)
2583 .wrap_in(ipv4_builder)
2584 .serialize_vec_outer()
2585 .expect("Failed to serialize to v4_pkt_buf");
2586
2587 let v6_tcp_builder = TcpSegmentBuilder::new(
2588 DEFAULT_SRC_IP,
2589 DEFAULT_DST_IP,
2590 tcp_src_port,
2591 tcp_dst_port,
2592 TCP_SEQ_NUM,
2593 TCP_ACK_NUM,
2594 TCP_WINDOW_SIZE,
2595 );
2596
2597 let v6_pkt_buf = (&PAYLOAD)
2598 .into_serializer()
2599 .wrap_in(v6_tcp_builder)
2600 .wrap_in(ipv6_builder)
2601 .serialize_vec_outer()
2602 .expect("Failed to serialize to v4_pkt_buf");
2603
2604 (v4_pkt_buf, v6_pkt_buf)
2605 }
2606
2607 #[test]
2608 fn test_nat64_translate_tcp() {
2609 let (expected_v4_pkt_buf, mut v6_pkt_buf) = create_tcp_ipv4_and_ipv6_pkt();
2610
2611 let parsed_v6_packet =
2612 v6_pkt_buf.parse::<Ipv6Packet<_>>().expect("Failed to parse v6_pkt_buf");
2613 let nat64_translation_result =
2614 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2615
2616 let serializable_pkt =
2617 assert_matches!(nat64_translation_result, Nat64TranslationResult::Forward(s) => s);
2618
2619 let translated_v4_pkt_buf = serializable_pkt
2620 .serialize_vec_outer()
2621 .expect("Failed to serialize to translated_v4_pkt_buf");
2622
2623 assert_eq!(
2624 expected_v4_pkt_buf.to_flattened_vec(),
2625 translated_v4_pkt_buf.to_flattened_vec()
2626 );
2627 }
2628
2629 fn create_udp_ipv4_and_ipv6_pkt()
2630 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
2631 use crate::udp::UdpPacketBuilder;
2632 use core::num::NonZeroU16;
2633
2634 let udp_src_port: NonZeroU16 = NonZeroU16::new(35000).unwrap();
2635 let udp_dst_port: NonZeroU16 = NonZeroU16::new(53).unwrap();
2636 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2637
2638 let (ipv4_builder, ipv6_builder) =
2639 create_ipv4_and_ipv6_builders(IpProto::Udp.into(), IpProto::Udp.into());
2640
2641 let v4_udp_builder = UdpPacketBuilder::new(
2642 DEFAULT_V4_SRC_IP,
2643 DEFAULT_V4_DST_IP,
2644 Some(udp_src_port),
2645 udp_dst_port,
2646 );
2647
2648 let v4_pkt_buf = (&PAYLOAD)
2649 .into_serializer()
2650 .wrap_in(v4_udp_builder)
2651 .wrap_in(ipv4_builder)
2652 .serialize_vec_outer()
2653 .expect("Unable to serialize to v4_pkt_buf");
2654
2655 let v6_udp_builder =
2656 UdpPacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, Some(udp_src_port), udp_dst_port);
2657
2658 let v6_pkt_buf = (&PAYLOAD)
2659 .into_serializer()
2660 .wrap_in(v6_udp_builder)
2661 .wrap_in(ipv6_builder)
2662 .serialize_vec_outer()
2663 .expect("Unable to serialize to v6_pkt_buf");
2664
2665 (v4_pkt_buf, v6_pkt_buf)
2666 }
2667
2668 #[test]
2669 fn test_nat64_translate_udp() {
2670 let (expected_v4_pkt_buf, mut v6_pkt_buf) = create_udp_ipv4_and_ipv6_pkt();
2671
2672 let parsed_v6_packet =
2673 v6_pkt_buf.parse::<Ipv6Packet<_>>().expect("Unable to parse Ipv6Packet");
2674 let nat64_translation_result =
2675 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2676
2677 let serializable_pkt = assert_matches!(nat64_translation_result,
2678 Nat64TranslationResult::Forward(s) => s);
2679
2680 let translated_v4_pkt_buf = serializable_pkt
2681 .serialize_vec_outer()
2682 .expect("Unable to serialize to translated_v4_pkt_buf");
2683
2684 assert_eq!(
2685 expected_v4_pkt_buf.to_flattened_vec(),
2686 translated_v4_pkt_buf.to_flattened_vec()
2687 );
2688 }
2689
2690 #[test]
2691 fn test_nat64_translate_non_tcp_udp_icmp() {
2692 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2693
2694 let (ipv4_builder, ipv6_builder) =
2695 create_ipv4_and_ipv6_builders(Ipv4Proto::Other(59), Ipv6Proto::Other(59));
2696
2697 let expected_v4_pkt_buf = (&PAYLOAD)
2698 .into_serializer()
2699 .wrap_in(ipv4_builder)
2700 .serialize_vec_outer()
2701 .expect("Unable to serialize to expected_v4_pkt_buf");
2702
2703 let mut v6_pkt_buf = (&PAYLOAD)
2704 .into_serializer()
2705 .wrap_in(ipv6_builder)
2706 .serialize_vec_outer()
2707 .expect("Unable to serialize to v6_pkt_buf");
2708
2709 let translated_v4_pkt_buf = {
2710 let parsed_v6_packet = v6_pkt_buf
2711 .parse::<Ipv6Packet<_>>()
2712 .expect("Unable to serialize to translated_v4_pkt_buf");
2713
2714 let nat64_translation_result =
2715 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2716
2717 let serializable_pkt = assert_matches!(nat64_translation_result,
2718 Nat64TranslationResult::Forward(s) => s);
2719
2720 let translated_buf = serializable_pkt
2721 .serialize_vec_outer()
2722 .expect("Unable to serialize to translated_buf");
2723
2724 translated_buf
2725 };
2726
2727 assert_eq!(
2728 expected_v4_pkt_buf.to_flattened_vec(),
2729 translated_v4_pkt_buf.to_flattened_vec()
2730 );
2731 }
2732
2733 #[test_case(new_builder(), true; "fixed header more frags")]
2734 #[test_case(Ipv6PacketBuilderWithHbhOptions::new(
2735 new_builder(),
2736 &[HopByHopOption {
2737 action: ExtensionHeaderOptionAction::SkipAndContinue,
2738 mutable: false,
2739 data: HopByHopOptionData::RouterAlert { data: 0 },
2740 }]).unwrap(), false; "hbh last frag")]
2741 fn ipv6_packet_builder_with_fragment_header<
2742 B: Ipv6HeaderBuilder + Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>> + Debug,
2743 >(
2744 inner: B,
2745 more_fragments: bool,
2746 ) {
2747 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2748 let fragment_offset = FragmentOffset::new(13).unwrap();
2749 let identification = 0xABCDABCD;
2750 let builder = Ipv6PacketBuilderWithFragmentHeader::new(
2751 inner,
2752 fragment_offset,
2753 more_fragments,
2754 identification,
2755 );
2756 let mut serialized =
2757 builder.wrap_body(PAYLOAD.into_serializer()).serialize_vec_outer().unwrap().unwrap_b();
2758 let packet = serialized.parse::<Ipv6Packet<_>>().unwrap();
2759 assert!(packet.fragment_header_present());
2760 assert_eq!(packet.proto(), Ipv6Proto::Proto(IpProto::Tcp));
2761 let fragment_data = packet
2762 .extension_hdrs
2763 .into_iter()
2764 .find_map(|ext_hdr| match ext_hdr.into_data() {
2765 Ipv6ExtensionHeaderData::Fragment { fragment_data } => Some(fragment_data),
2766 _ => None,
2767 })
2768 .unwrap();
2769 assert_eq!(fragment_data.fragment_offset(), fragment_offset);
2770 assert_eq!(fragment_data.identification(), identification);
2771 assert_eq!(fragment_data.m_flag(), more_fragments);
2772 }
2773
2774 #[test]
2777 fn extension_headers_take_from_max_body_size() {
2778 let builder = new_builder();
2779 assert_eq!(builder.constraints().max_body_len(), IPV6_MAX_PAYLOAD_LENGTH);
2780 let builder =
2781 Ipv6PacketBuilderWithFragmentHeader::new(builder, FragmentOffset::ZERO, false, 1234);
2782 assert_eq!(
2783 builder.constraints().max_body_len(),
2784 IPV6_MAX_PAYLOAD_LENGTH - IPV6_FRAGMENT_EXT_HDR_LEN
2785 );
2786 }
2787}