1pub mod ext_hdrs;
12
13use alloc::vec::Vec;
14use core::borrow::Borrow;
15use core::convert::Infallible as Never;
16use core::fmt::{self, Debug, Formatter};
17use core::ops::Range;
18
19use log::debug;
20use net_types::ip::{GenericOverIp, Ipv4Addr, Ipv6, Ipv6Addr, Ipv6SourceAddr};
21use packet::records::{AlignedRecordSequenceBuilder, Records, RecordsRaw};
22use packet::{
23 BufferProvider, BufferView, BufferViewMut, EmptyBuf, FragmentedBytesMut, FromRaw,
24 GrowBufferMut, InnerPacketBuilder, LayoutBufferAlloc, MaybeParsed, NestablePacketBuilder,
25 NestableSerializer, NoOpSerializationContext, PacketBuilder, PacketConstraints, ParsablePacket,
26 ParseMetadata, PartialPacketBuilder, PartialSerializeResult, PartialSerializer, SerializeError,
27 SerializeTarget, Serializer,
28};
29use zerocopy::byteorder::network_endian::{U16, U32};
30use zerocopy::{
31 FromBytes, Immutable, IntoBytes, KnownLayout, Ref, SplitByteSlice, SplitByteSliceMut, Unaligned,
32};
33
34use crate::error::{IpParseErrorAction, IpParseResult, Ipv6ParseError, ParseError};
35use crate::icmp::Icmpv6ParameterProblemCode;
36use crate::ip::{
37 DscpAndEcn, FragmentOffset, IpEnvelope, IpExt, IpPacketBuilder, IpProto,
38 IpSerializationContext, Ipv4Proto, Ipv6ExtHdrType, Ipv6Proto, Nat64Error,
39 Nat64TranslationResult,
40};
41use crate::ipv4::{HDR_PREFIX_LEN, Ipv4PacketBuilder};
42use crate::tcp::{TcpParseArgs, TcpSegment};
43use crate::udp::{UdpPacket, UdpParseArgs};
44
45use ext_hdrs::{
46 ExtensionHeaderOptionAction, HopByHopOption, HopByHopOptionData, IPV6_FRAGMENT_EXT_HDR_LEN,
47 Ipv6ExtensionHeader, Ipv6ExtensionHeaderData, Ipv6ExtensionHeaderImpl,
48 Ipv6ExtensionHeaderParsingContext, Ipv6ExtensionHeaderParsingError, is_valid_next_header,
49 is_valid_next_header_upper_layer,
50};
51
52pub const IPV6_FIXED_HDR_LEN: usize = 40;
54
55pub const IPV6_PAYLOAD_LEN_BYTE_RANGE: Range<usize> = 4..6;
58
59const NEXT_HEADER_OFFSET: u8 = 6;
61
62const IPV6_HBH_OPTIONS_MAX_LEN: usize = (core::u8::MAX as usize) * 8 + 8;
66
67const IPV6_MAX_PAYLOAD_LENGTH: usize = core::u16::MAX as usize;
74
75fn ext_hdr_err_fn(hdr: &FixedHeader, err: Ipv6ExtensionHeaderParsingError) -> Ipv6ParseError {
78 match err {
97 Ipv6ExtensionHeaderParsingError::ErroneousHeaderField { pointer, must_send_icmp } => {
98 let (pointer, action) = match pointer.checked_add(IPV6_FIXED_HDR_LEN as u32) {
99 None => (0, IpParseErrorAction::DiscardPacket),
103 Some(p) => (p, IpParseErrorAction::DiscardPacketSendIcmpNoMulticast),
107 };
108
109 Ipv6ParseError::ParameterProblem {
110 src_ip: hdr.src_ip,
111 dst_ip: hdr.dst_ip,
112 code: Icmpv6ParameterProblemCode::ErroneousHeaderField,
113 pointer,
114 must_send_icmp,
115 action,
116 }
117 }
118 Ipv6ExtensionHeaderParsingError::UnrecognizedNextHeader { pointer, must_send_icmp } => {
119 let (pointer, action) = match pointer.checked_add(IPV6_FIXED_HDR_LEN as u32) {
120 None => (0, IpParseErrorAction::DiscardPacket),
121 Some(p) => (p, IpParseErrorAction::DiscardPacketSendIcmpNoMulticast),
122 };
123
124 Ipv6ParseError::ParameterProblem {
125 src_ip: hdr.src_ip,
126 dst_ip: hdr.dst_ip,
127 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
128 pointer,
129 must_send_icmp,
130 action,
131 }
132 }
133 Ipv6ExtensionHeaderParsingError::UnrecognizedOption { pointer, must_send_icmp, action } => {
134 let (pointer, action) = match pointer.checked_add(IPV6_FIXED_HDR_LEN as u32) {
135 None => (0, IpParseErrorAction::DiscardPacket),
136 Some(p) => {
137 let action = match action {
138 ExtensionHeaderOptionAction::SkipAndContinue => unreachable!(
139 "Should never end up here because this action should never result in an error"
140 ),
141 ExtensionHeaderOptionAction::DiscardPacket => {
142 IpParseErrorAction::DiscardPacket
143 }
144 ExtensionHeaderOptionAction::DiscardPacketSendIcmp => {
145 IpParseErrorAction::DiscardPacketSendIcmp
146 }
147 ExtensionHeaderOptionAction::DiscardPacketSendIcmpNoMulticast => {
148 IpParseErrorAction::DiscardPacketSendIcmpNoMulticast
149 }
150 };
151
152 (p, action)
153 }
154 };
155
156 Ipv6ParseError::ParameterProblem {
157 src_ip: hdr.src_ip,
158 dst_ip: hdr.dst_ip,
159 code: Icmpv6ParameterProblemCode::UnrecognizedIpv6Option,
160 pointer,
161 must_send_icmp,
162 action,
163 }
164 }
165 Ipv6ExtensionHeaderParsingError::BufferExhausted
166 | Ipv6ExtensionHeaderParsingError::MalformedData => {
167 Ipv6ParseError::Parse { error: ParseError::Format }
170 }
171 }
172}
173
174#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
176#[repr(C)]
177pub struct FixedHeader {
178 version_tc_flowlabel: [u8; 4],
179 payload_len: U16,
180 next_hdr: u8,
181 hop_limit: u8,
182 src_ip: Ipv6Addr,
183 dst_ip: Ipv6Addr,
184}
185
186const IP_VERSION: u8 = 6;
187const VERSION_OFFSET: u8 = 4;
188const FLOW_LABEL_MAX: u32 = (1 << 20) - 1;
189
190impl FixedHeader {
191 #[allow(clippy::too_many_arguments)]
192 fn new(
193 dscp_and_ecn: DscpAndEcn,
194 flow_label: u32,
195 payload_len: u16,
196 next_hdr: u8,
197 hop_limit: u8,
198 src_ip: Ipv6Addr,
199 dst_ip: Ipv6Addr,
200 ) -> FixedHeader {
201 debug_assert!(flow_label <= FLOW_LABEL_MAX);
202
203 let traffic_class = dscp_and_ecn.raw();
204 FixedHeader {
205 version_tc_flowlabel: [
206 IP_VERSION << VERSION_OFFSET | traffic_class >> 4,
207 (traffic_class << 4) | ((flow_label >> 16) as u8),
208 (flow_label >> 8) as u8,
209 flow_label as u8,
210 ],
211 payload_len: U16::new(payload_len),
212 next_hdr,
213 hop_limit,
214 src_ip,
215 dst_ip,
216 }
217 }
218
219 fn version(&self) -> u8 {
220 self.version_tc_flowlabel[0] >> 4
221 }
222
223 fn dscp_and_ecn(&self) -> DscpAndEcn {
224 ((self.version_tc_flowlabel[0] & 0xF) << 4 | self.version_tc_flowlabel[1] >> 4).into()
225 }
226
227 fn flowlabel(&self) -> u32 {
228 (u32::from(self.version_tc_flowlabel[1]) & 0xF) << 16
229 | u32::from(self.version_tc_flowlabel[2]) << 8
230 | u32::from(self.version_tc_flowlabel[3])
231 }
232}
233
234pub trait Ipv6Header {
239 fn get_fixed_header(&self) -> &FixedHeader;
241
242 fn hop_limit(&self) -> u8 {
244 self.get_fixed_header().hop_limit
245 }
246
247 fn next_header(&self) -> u8 {
249 self.get_fixed_header().next_hdr
250 }
251
252 fn src_ip(&self) -> Ipv6Addr {
254 self.get_fixed_header().src_ip
255 }
256
257 fn dst_ip(&self) -> Ipv6Addr {
259 self.get_fixed_header().dst_ip
260 }
261
262 fn dscp_and_ecn(&self) -> DscpAndEcn {
265 self.get_fixed_header().dscp_and_ecn()
266 }
267}
268
269impl Ipv6Header for FixedHeader {
270 fn get_fixed_header(&self) -> &FixedHeader {
271 self
272 }
273}
274
275pub struct Ipv6Packet<B> {
281 fixed_hdr: Ref<B, FixedHeader>,
282 extension_hdrs: Records<B, Ipv6ExtensionHeaderImpl>,
283 body: B,
284 proto: Ipv6Proto,
285}
286
287impl<B: SplitByteSlice, I: IpExt> GenericOverIp<I> for Ipv6Packet<B> {
288 type Type = <I as IpExt>::Packet<B>;
289}
290
291impl<B: SplitByteSlice> Ipv6Header for Ipv6Packet<B> {
292 fn get_fixed_header(&self) -> &FixedHeader {
293 &self.fixed_hdr
294 }
295}
296
297impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv6Packet<B> {
298 type Error = Ipv6ParseError;
299
300 fn parse_metadata(&self) -> ParseMetadata {
301 let header_len = Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.bytes().len();
302 ParseMetadata::from_packet(header_len, self.body.len(), 0)
303 }
304
305 fn parse<BV: BufferView<B>>(buffer: BV, _args: ()) -> Result<Self, Ipv6ParseError> {
306 Ipv6PacketRaw::parse(buffer, ()).and_then(Ipv6Packet::try_from_raw)
307 }
308}
309
310impl<B: SplitByteSlice> FromRaw<Ipv6PacketRaw<B>, ()> for Ipv6Packet<B> {
311 type Error = Ipv6ParseError;
312
313 fn try_from_raw_with(raw: Ipv6PacketRaw<B>, _args: ()) -> Result<Self, Self::Error> {
314 let fixed_hdr = raw.fixed_hdr;
315
316 if !is_valid_next_header(fixed_hdr.next_hdr, true) {
319 return debug_err!(
320 Err(Ipv6ParseError::ParameterProblem {
321 src_ip: fixed_hdr.src_ip,
322 dst_ip: fixed_hdr.dst_ip,
323 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
324 pointer: u32::from(NEXT_HEADER_OFFSET),
325 must_send_icmp: false,
326 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
327 }),
328 "Unrecognized next header value"
329 );
330 }
331
332 let extension_hdrs = match raw.extension_hdrs {
333 MaybeParsed::Complete(v) => {
334 Records::try_from_raw(v).map_err(|e| ext_hdr_err_fn(&fixed_hdr, e))?
335 }
336 MaybeParsed::Incomplete(_) => {
337 return debug_err!(
338 Err(ParseError::Format.into()),
339 "Incomplete IPv6 extension headers"
340 );
341 }
342 };
343
344 let (body, proto) =
348 raw.body_proto.expect("Unable to retrieve Ipv6Proto or MaybeParsed body from raw");
349 debug_assert!(is_valid_next_header_upper_layer(proto.into()));
350
351 let body = match body {
352 MaybeParsed::Complete(b) => b,
353 MaybeParsed::Incomplete(_b) => {
354 return debug_err!(Err(ParseError::Format.into()), "IPv6 body unretrievable.");
355 }
356 };
357
358 if extension_hdrs.bytes().len() + body.len() != usize::from(fixed_hdr.payload_len.get()) {
363 return debug_err!(
364 Err(ParseError::Format.into()),
365 "Payload len does not match body and extension headers"
366 );
367 }
368
369 if fixed_hdr.version() != 6 {
371 return debug_err!(
372 Err(ParseError::Format.into()),
373 "unexpected IP version: {}",
374 fixed_hdr.version()
375 );
376 }
377
378 Ok(Ipv6Packet { fixed_hdr, extension_hdrs, body, proto })
379 }
380}
381
382impl<B: SplitByteSlice, C: IpSerializationContext<Ipv6>> PartialSerializer<C> for Ipv6Packet<B> {
383 fn partial_serialize(
384 &self,
385 _context: &mut C,
386 _constraints: PacketConstraints,
387 mut buffer: &mut [u8],
388 ) -> Result<PartialSerializeResult, SerializeError<Never>> {
389 let fixed_hdr = Ref::bytes(&self.fixed_hdr);
390 let extension_hdrs = self.extension_hdrs.bytes();
391
392 let mut buffer = &mut buffer;
393 let bytes_written = buffer.write_bytes_front_allow_partial(Ref::bytes(&self.fixed_hdr))
394 + buffer.write_bytes_front_allow_partial(self.extension_hdrs.bytes())
395 + buffer.write_bytes_front_allow_partial(&self.body);
396 let total_size = fixed_hdr.len() + extension_hdrs.len() + self.body.len();
397
398 Ok(PartialSerializeResult { bytes_written, total_size })
399 }
400}
401
402impl<B: SplitByteSlice> Ipv6Packet<B> {
403 pub fn iter_extension_hdrs(&self) -> impl Iterator<Item = Ipv6ExtensionHeader<'_>> {
405 self.extension_hdrs.iter()
406 }
407
408 pub fn body(&self) -> &[u8] {
410 &self.body
411 }
412
413 pub fn dscp_and_ecn(&self) -> DscpAndEcn {
416 self.fixed_hdr.dscp_and_ecn()
417 }
418
419 pub fn flowlabel(&self) -> u32 {
421 self.fixed_hdr.flowlabel()
422 }
423
424 pub fn proto(&self) -> Ipv6Proto {
430 self.proto
431 }
432
433 pub fn src_ipv6(&self) -> Option<Ipv6SourceAddr> {
440 Ipv6SourceAddr::new(self.fixed_hdr.src_ip)
441 }
442
443 pub fn copy_header_bytes_for_fragment(&self) -> Vec<u8> {
454 let expected_bytes_len = self.header_len() - IPV6_FRAGMENT_EXT_HDR_LEN;
457 let mut bytes = Vec::with_capacity(expected_bytes_len);
458
459 bytes.extend_from_slice(Ref::bytes(&self.fixed_hdr));
460
461 let mut iter = self.extension_hdrs.iter();
465
466 let ext_hdr = iter.next().expect("packet must have at least one extension header");
470
471 if self.fixed_hdr.next_hdr == Ipv6ExtHdrType::Fragment.into() {
472 bytes[6] = ext_hdr.next_header;
478
479 bytes.extend_from_slice(&self.extension_hdrs.bytes()[IPV6_FRAGMENT_EXT_HDR_LEN..]);
481 } else {
482 let mut ext_hdr = ext_hdr;
483 let mut ext_hdr_start = 0;
484 let mut ext_hdr_end = iter.context().bytes_parsed;
485
486 loop {
492 let next_ext_hdr = iter
498 .next()
499 .expect("exhausted all extension headers without finding fragment header");
500
501 if let Ipv6ExtensionHeaderData::Fragment { .. } = next_ext_hdr.data() {
502 let fragment_hdr_end = ext_hdr_end + IPV6_FRAGMENT_EXT_HDR_LEN;
509 assert_eq!(fragment_hdr_end, iter.context().bytes_parsed);
510
511 let extension_hdr_bytes = self.extension_hdrs.bytes();
512
513 bytes.extend_from_slice(&extension_hdr_bytes[..ext_hdr_end]);
515
516 bytes.extend_from_slice(&extension_hdr_bytes[fragment_hdr_end..]);
518
519 match ext_hdr.data() {
522 Ipv6ExtensionHeaderData::HopByHopOptions { .. }
525 | Ipv6ExtensionHeaderData::DestinationOptions { .. }
526 | Ipv6ExtensionHeaderData::Routing { .. } => {
527 bytes[IPV6_FIXED_HDR_LEN + ext_hdr_start] = next_ext_hdr.next_header;
528 }
529 Ipv6ExtensionHeaderData::Fragment { .. } => unreachable!(
530 "If we had a fragment header before `ext_hdr`, we should have used that instead"
531 ),
532 }
533
534 break;
535 }
536
537 ext_hdr = next_ext_hdr;
538 ext_hdr_start = ext_hdr_end;
539 ext_hdr_end = iter.context().bytes_parsed;
540 }
541 }
542
543 assert_eq!(bytes.len(), expected_bytes_len);
545 bytes
546 }
547
548 fn header_len(&self) -> usize {
549 Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.bytes().len()
550 }
551
552 fn fragment_header_present(&self) -> bool {
553 for ext_hdr in self.extension_hdrs.iter() {
554 if matches!(ext_hdr.data(), Ipv6ExtensionHeaderData::Fragment { .. }) {
555 return true;
556 }
557 }
558 false
559 }
560
561 pub fn builder(&self) -> Ipv6PacketBuilder {
563 Ipv6PacketBuilder {
564 dscp_and_ecn: self.dscp_and_ecn(),
565 flowlabel: self.flowlabel(),
566 hop_limit: self.hop_limit(),
567 proto: self.proto(),
568 src_ip: self.src_ip(),
569 dst_ip: self.dst_ip(),
570 }
571 }
572
573 pub fn nat64_translate(
599 &self,
600 v4_src_addr: Ipv4Addr,
601 v4_dst_addr: Ipv4Addr,
602 ) -> Nat64TranslationResult<
603 impl Serializer<NoOpSerializationContext, Buffer = EmptyBuf> + Debug + '_,
604 Nat64Error,
605 > {
606 #[derive(Debug)]
609 enum Nat64Serializer<T, U, O> {
610 Tcp(T),
611 Udp(U),
612 Other(O),
613 }
614 impl<T, U, O> Serializer<NoOpSerializationContext> for Nat64Serializer<T, U, O>
615 where
616 T: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
617 U: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
618 O: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
619 {
620 type Buffer = EmptyBuf;
621 fn serialize<B, P>(
622 self,
623 context: &mut NoOpSerializationContext,
624 outer: PacketConstraints,
625 provider: P,
626 ) -> Result<B, (SerializeError<P::Error>, Self)>
627 where
628 B: GrowBufferMut,
629 P: BufferProvider<Self::Buffer, B>,
630 {
631 match self {
632 Nat64Serializer::Tcp(serializer) => serializer
633 .serialize(context, outer, provider)
634 .map_err(|(err, ser)| (err, Nat64Serializer::Tcp(ser))),
635 Nat64Serializer::Udp(serializer) => serializer
636 .serialize(context, outer, provider)
637 .map_err(|(err, ser)| (err, Nat64Serializer::Udp(ser))),
638 Nat64Serializer::Other(serializer) => serializer
639 .serialize(context, outer, provider)
640 .map_err(|(err, ser)| (err, Nat64Serializer::Other(ser))),
641 }
642 }
643
644 fn serialize_new_buf<B: GrowBufferMut, A: LayoutBufferAlloc<B>>(
645 &self,
646 context: &mut NoOpSerializationContext,
647 outer: PacketConstraints,
648 alloc: A,
649 ) -> Result<B, SerializeError<A::Error>> {
650 match self {
651 Nat64Serializer::Tcp(serializer) => {
652 serializer.serialize_new_buf(context, outer, alloc)
653 }
654 Nat64Serializer::Udp(serializer) => {
655 serializer.serialize_new_buf(context, outer, alloc)
656 }
657 Nat64Serializer::Other(serializer) => {
658 serializer.serialize_new_buf(context, outer, alloc)
659 }
660 }
661 }
662 }
663
664 impl<T, U, O> NestableSerializer for Nat64Serializer<T, U, O>
665 where
666 T: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
667 U: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
668 O: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
669 {
670 }
671
672 if self.fragment_header_present() {
675 return Nat64TranslationResult::Err(Nat64Error::NotImplemented);
676 }
677
678 let v4_builder = |v4_proto| {
679 let mut builder =
680 Ipv4PacketBuilder::new(v4_src_addr, v4_dst_addr, self.hop_limit(), v4_proto);
681 builder.dscp_and_ecn(self.dscp_and_ecn());
682
683 const IPV4_HEADER_LEN_BYTES: usize = HDR_PREFIX_LEN;
688
689 builder.df_flag(self.body().len() + IPV4_HEADER_LEN_BYTES > 1260);
695
696 builder.fragment_offset(FragmentOffset::ZERO);
699 builder.mf_flag(false);
700
701 builder
702 };
703
704 match self.proto() {
705 Ipv6Proto::Proto(IpProto::Tcp) => {
706 let v4_pkt_builder = v4_builder(Ipv4Proto::Proto(IpProto::Tcp));
707 let args = TcpParseArgs::new(self.src_ip(), self.dst_ip());
708 match TcpSegment::parse(&mut self.body.as_bytes(), args) {
713 Ok(tcp) => {
714 let tcp_serializer =
718 Nat64Serializer::Tcp(tcp.into_serializer(v4_src_addr, v4_dst_addr));
719 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(tcp_serializer))
720 }
721 Err(msg) => {
722 debug!("Parsing of TCP segment failed: {:?}", msg);
723
724 let common_serializer =
733 Nat64Serializer::Other(self.body().into_serializer());
734 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
735 }
736 }
737 }
738
739 Ipv6Proto::Proto(IpProto::Udp) => {
744 let v4_pkt_builder = v4_builder(Ipv4Proto::Proto(IpProto::Udp));
745 let args = UdpParseArgs::new(self.src_ip(), self.dst_ip());
746 match UdpPacket::parse(&mut self.body.as_bytes(), args) {
747 Ok(udp) => {
748 let udp_serializer =
752 Nat64Serializer::Udp(udp.into_serializer(v4_src_addr, v4_dst_addr));
753 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(udp_serializer))
754 }
755 Err(msg) => {
756 debug!("Parsing of UDP packet failed: {:?}", msg);
757
758 let common_serializer =
768 Nat64Serializer::Other(self.body().into_serializer());
769 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
770 }
771 }
772 }
773
774 Ipv6Proto::Icmpv6 => Nat64TranslationResult::Err(Nat64Error::NotImplemented),
777
778 Ipv6Proto::Other(val) => {
798 let v4_pkt_builder = v4_builder(Ipv4Proto::Other(val));
799 let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
800 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
801 }
802
803 Ipv6Proto::NoNextHeader => {
804 let v4_pkt_builder = v4_builder(Ipv4Proto::Other(Ipv6Proto::NoNextHeader.into()));
805 let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
806 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
807 }
808
809 Ipv6Proto::Proto(IpProto::Reserved) => Nat64TranslationResult::Drop,
812 }
813 }
814
815 pub fn to_vec(&self) -> Vec<u8> {
817 let Ipv6Packet { fixed_hdr, extension_hdrs, body, proto: _ } = self;
818 let mut buf = Vec::with_capacity(
819 Ref::bytes(&fixed_hdr).len() + extension_hdrs.bytes().len() + body.as_bytes().len(),
820 );
821 buf.extend(Ref::bytes(&fixed_hdr));
822 buf.extend(extension_hdrs.bytes());
823 buf.extend(body.as_bytes());
824 buf
825 }
826}
827
828impl<B: SplitByteSliceMut> Ipv6Packet<B> {
829 pub fn set_src_ip(&mut self, addr: Ipv6Addr) {
831 self.fixed_hdr.src_ip = addr;
832 }
833
834 pub fn set_dst_ip(&mut self, addr: Ipv6Addr) {
836 self.fixed_hdr.dst_ip = addr;
837 }
838
839 pub fn set_hop_limit(&mut self, hlim: u8) {
841 self.fixed_hdr.hop_limit = hlim;
842 }
843
844 pub fn body_mut(&mut self) -> &mut [u8] {
846 &mut self.body
847 }
848
849 pub fn parts_with_body_mut(&mut self) -> (&FixedHeader, ExtensionHeaders<'_>, &mut [u8]) {
852 (&self.fixed_hdr, ExtensionHeaders(self.extension_hdrs.as_ref()), &mut self.body)
853 }
854}
855
856impl<B: SplitByteSlice> Debug for Ipv6Packet<B> {
857 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
858 f.debug_struct("Ipv6Packet")
859 .field("src_ip", &self.src_ip())
860 .field("dst_ip", &self.dst_ip())
861 .field("hop_limit", &self.hop_limit())
862 .field("proto", &self.proto())
863 .field("dscp", &self.dscp_and_ecn().dscp())
864 .field("ecn", &self.dscp_and_ecn().ecn())
865 .field("flowlabel", &self.flowlabel())
866 .field("extension headers", &"TODO")
867 .field("body", &alloc::format!("<{} bytes>", self.body.len()))
868 .finish()
869 }
870}
871
872pub struct ExtensionHeaders<'a>(Records<&'a [u8], Ipv6ExtensionHeaderImpl>);
874
875impl<'a> ExtensionHeaders<'a> {
876 pub fn iter(&self) -> impl Iterator<Item = Ipv6ExtensionHeader<'_>> {
878 self.0.iter()
879 }
880
881 pub fn bytes(&self) -> &[u8] {
883 self.0.bytes()
884 }
885}
886
887#[derive(Copy, Clone, Debug, Eq, PartialEq)]
893pub struct ExtHdrParseError;
894
895pub struct Ipv6PacketRaw<B> {
905 fixed_hdr: Ref<B, FixedHeader>,
907 extension_hdrs: MaybeParsed<RecordsRaw<B, Ipv6ExtensionHeaderImpl>, B>,
913 body_proto: Result<(MaybeParsed<B, B>, Ipv6Proto), ExtHdrParseError>,
926}
927
928impl<B> Ipv6PacketRaw<B> {
929 pub fn body_mut(&mut self) -> Option<&mut B> {
933 match self.body_proto {
934 Ok(ref mut b) => match b {
935 (MaybeParsed::Complete(b), _) => Some(b),
936 (MaybeParsed::Incomplete(b), _) => Some(b),
937 },
938 Err(_) => None,
939 }
940 }
941}
942
943impl<B: SplitByteSlice> Ipv6Header for Ipv6PacketRaw<B> {
944 fn get_fixed_header(&self) -> &FixedHeader {
945 &self.fixed_hdr
946 }
947}
948
949impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv6PacketRaw<B> {
950 type Error = Ipv6ParseError;
951
952 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> Result<Self, Self::Error> {
953 let fixed_hdr = buffer
954 .take_obj_front::<FixedHeader>()
955 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for header"))?;
956 let payload_len = fixed_hdr.payload_len.get().into();
957 let _: Option<B> = buffer.len().checked_sub(payload_len).map(|padding| {
959 buffer.take_back(padding).unwrap_or_else(|| {
960 panic!("buffer.len()={} padding={}", buffer.len(), padding);
961 })
962 });
963
964 let mut extension_hdr_context = Ipv6ExtensionHeaderParsingContext::new(fixed_hdr.next_hdr);
965
966 let extension_hdrs =
967 RecordsRaw::parse_raw_with_mut_context(&mut buffer, &mut extension_hdr_context)
968 .map_incomplete(|(b, _)| b);
969
970 let body_proto = match &extension_hdrs {
971 MaybeParsed::Complete(r) => {
972 let _: &RecordsRaw<B, _> = r;
973 assert!(is_valid_next_header_upper_layer(extension_hdr_context.next_header));
994 let proto = Ipv6Proto::from(extension_hdr_context.next_header);
995 let body = MaybeParsed::new_with_min_len(
996 buffer.into_rest(),
997 payload_len.saturating_sub(extension_hdrs.len()),
998 );
999 Ok((body, proto))
1000 }
1001 MaybeParsed::Incomplete(b) => {
1002 let _: &B = b;
1003 Err(ExtHdrParseError)
1004 }
1005 };
1006
1007 Ok(Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto })
1008 }
1009
1010 fn parse_metadata(&self) -> ParseMetadata {
1011 let header_len = Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.len();
1012 let body_len = self.body_proto.as_ref().map(|(b, _p)| b.len()).unwrap_or(0);
1013 ParseMetadata::from_packet(header_len, body_len, 0)
1014 }
1015}
1016
1017impl<B: SplitByteSlice> Ipv6PacketRaw<B> {
1018 pub fn body_proto(&self) -> Result<(MaybeParsed<&[u8], &[u8]>, Ipv6Proto), ExtHdrParseError> {
1031 self.body_proto
1032 .as_ref()
1033 .map(|(mp, proto)| {
1034 (mp.as_ref().map(|b| b.deref()).map_incomplete(|b| b.deref()), *proto)
1035 })
1036 .map_err(|e| *e)
1037 }
1038
1039 pub fn body(&self) -> Result<MaybeParsed<&[u8], &[u8]>, ExtHdrParseError> {
1050 self.body_proto().map(|(body, _proto)| body)
1051 }
1052
1053 pub fn proto(&self) -> Result<Ipv6Proto, ExtHdrParseError> {
1060 self.body_proto().map(|(_body, proto)| proto)
1061 }
1062}
1063
1064impl<B: SplitByteSliceMut> Ipv6PacketRaw<B> {
1065 pub fn set_src_ip(&mut self, addr: Ipv6Addr) {
1067 self.fixed_hdr.src_ip = addr;
1068 }
1069
1070 pub fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1072 self.fixed_hdr.dst_ip = addr;
1073 }
1074}
1075
1076pub enum NextHeader {
1079 NextLayer(Ipv6Proto),
1081 Extension(Ipv6ExtHdrType),
1083}
1084
1085impl From<NextHeader> for u8 {
1086 fn from(next_hdr: NextHeader) -> Self {
1087 match next_hdr {
1088 NextHeader::NextLayer(n) => n.into(),
1089 NextHeader::Extension(e) => e.into(),
1090 }
1091 }
1092}
1093
1094mod sealed {
1095 use super::*;
1096 pub trait Ipv6HeaderBefore<T> {}
1104
1105 impl<'a, O, T> Ipv6HeaderBefore<T> for &'a O where O: Ipv6HeaderBefore<T> {}
1106
1107 pub trait Ipv6HeaderBuilder {
1109 fn fixed_header(&self) -> &Ipv6PacketBuilder;
1111
1112 fn extension_headers_len(&self) -> usize;
1115
1116 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1121 &self,
1122 buffer: &mut BV,
1123 next_header: NextHeader,
1124 payload_len: usize,
1125 );
1126 }
1127}
1128use sealed::{Ipv6HeaderBefore, Ipv6HeaderBuilder};
1129
1130impl<'a, O> Ipv6HeaderBuilder for &'a O
1131where
1132 O: Ipv6HeaderBuilder,
1133{
1134 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1135 O::fixed_header(self)
1136 }
1137
1138 fn extension_headers_len(&self) -> usize {
1139 O::extension_headers_len(self)
1140 }
1141
1142 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1143 &self,
1144 buffer: &mut BV,
1145 next_header: NextHeader,
1146 payload_len: usize,
1147 ) {
1148 O::serialize_header(self, buffer, next_header, payload_len)
1149 }
1150}
1151
1152macro_rules! impl_packet_builder_base {
1157 {} => {
1158 fn constraints(&self) -> PacketConstraints {
1159 let ext_headers = self.extension_headers_len();
1160 let header_len = IPV6_FIXED_HDR_LEN + ext_headers;
1161 let footer_len = 0;
1162 let min_body_len = 0;
1163 let max_body_len = IPV6_MAX_PAYLOAD_LENGTH - ext_headers;
1166 PacketConstraints::new(header_len, footer_len, min_body_len, max_body_len)
1167 }
1168 }
1169}
1170
1171macro_rules! impl_packet_builder {
1172 {} => {
1173 fn context_state(&self) -> C::ContextState {
1174 C::envelope_to_state(IpEnvelope::new(self.extension_headers_len() > 0))
1175 }
1176
1177 fn serialize(
1178 &self,
1179 _context: &mut C,
1180 target: &mut SerializeTarget<'_>,
1181 body: FragmentedBytesMut<'_, '_>,
1182 ) {
1183 let mut bv = &mut target.header;
1184 self.serialize_header(
1185 &mut bv,
1186 NextHeader::NextLayer(
1187 <Ipv6PacketBuilder as IpPacketBuilder<C, Ipv6>>::proto(self.fixed_header())
1188 ),
1189 body.len(),
1190 );
1191 }
1192 }
1193}
1194
1195macro_rules! impl_partial_packet_builder {
1196 {} => {
1197 fn partial_serialize(
1198 &self,
1199 _context: &mut C,
1200 body_len: usize,
1201 mut buffer: &mut [u8],
1202 ) {
1203 self.serialize_header(
1204 &mut &mut buffer,
1205 NextHeader::NextLayer(
1206 <Ipv6PacketBuilder as IpPacketBuilder<C, Ipv6>>::proto(self.fixed_header())
1207 ),
1208 body_len,
1209 );
1210 }
1211 }
1212}
1213#[derive(Debug, Clone, Eq, PartialEq)]
1215pub struct Ipv6PacketBuilder {
1216 dscp_and_ecn: DscpAndEcn,
1217 flowlabel: u32,
1218 hop_limit: u8,
1219 proto: Ipv6Proto,
1222 src_ip: Ipv6Addr,
1223 dst_ip: Ipv6Addr,
1224}
1225
1226impl Ipv6PacketBuilder {
1227 pub fn new<S: Into<Ipv6Addr>, D: Into<Ipv6Addr>>(
1233 src_ip: S,
1234 dst_ip: D,
1235 hop_limit: u8,
1236 proto: Ipv6Proto,
1237 ) -> Ipv6PacketBuilder {
1238 Ipv6PacketBuilder {
1239 dscp_and_ecn: DscpAndEcn::default(),
1240 flowlabel: 0,
1241 hop_limit,
1242 proto,
1243 src_ip: src_ip.into(),
1244 dst_ip: dst_ip.into(),
1245 }
1246 }
1247
1248 pub fn dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1251 self.dscp_and_ecn = dscp_and_ecn;
1252 }
1253
1254 pub fn flowlabel(&mut self, flowlabel: u32) {
1260 assert!(flowlabel <= 1 << 20, "invalid flowlabel: {:x}", flowlabel);
1261 self.flowlabel = flowlabel;
1262 }
1263}
1264
1265impl Ipv6HeaderBuilder for Ipv6PacketBuilder {
1266 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1267 self
1268 }
1269
1270 fn extension_headers_len(&self) -> usize {
1271 0
1272 }
1273
1274 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1275 &self,
1276 buffer: &mut BV,
1277 next_header: NextHeader,
1278 payload_len: usize,
1279 ) {
1280 buffer
1281 .write_obj_front(&FixedHeader::new(
1282 self.dscp_and_ecn,
1283 self.flowlabel,
1284 {
1285 debug_assert!(payload_len <= core::u16::MAX as usize);
1292 payload_len as u16
1293 },
1294 next_header.into(),
1295 self.hop_limit,
1296 self.src_ip,
1297 self.dst_ip,
1298 ))
1299 .expect("not enough bytes for IPv6 fixed header");
1300 }
1301}
1302
1303impl NestablePacketBuilder for Ipv6PacketBuilder {
1304 impl_packet_builder_base! {}
1305}
1306
1307impl<C: IpSerializationContext<Ipv6>> PacketBuilder<C> for Ipv6PacketBuilder {
1308 impl_packet_builder! {}
1309}
1310
1311impl<C: IpSerializationContext<Ipv6>> PartialPacketBuilder<C> for Ipv6PacketBuilder {
1312 impl_partial_packet_builder! {}
1313}
1314
1315#[derive(Debug, Clone)]
1317pub struct Ipv6PacketBuilderWithHbhOptions<'a, I> {
1318 prefix_builder: Ipv6PacketBuilder,
1319 hbh_options: AlignedRecordSequenceBuilder<HopByHopOption<'a>, I>,
1320}
1321
1322impl<'a, I> Ipv6PacketBuilderWithHbhOptions<'a, I>
1323where
1324 I: Iterator + Clone,
1325 I::Item: Borrow<HopByHopOption<'a>>,
1326{
1327 pub fn new<T: IntoIterator<Item = I::Item, IntoIter = I>>(
1329 prefix_builder: Ipv6PacketBuilder,
1330 options: T,
1331 ) -> Option<Ipv6PacketBuilderWithHbhOptions<'a, I>> {
1332 let iter = options.into_iter();
1333 if iter
1336 .clone()
1337 .filter(|r| matches!(r.borrow().data, HopByHopOptionData::RouterAlert { .. }))
1338 .count()
1339 > 1
1340 {
1341 return None;
1342 }
1343 let hbh_options = AlignedRecordSequenceBuilder::new(2, iter);
1344 if next_multiple_of_eight(2 + hbh_options.serialized_len()) > IPV6_HBH_OPTIONS_MAX_LEN {
1346 return None;
1347 }
1348 Some(Ipv6PacketBuilderWithHbhOptions { prefix_builder, hbh_options })
1349 }
1350
1351 fn aligned_hbh_len(&self) -> usize {
1352 let opt_len = self.hbh_options.serialized_len();
1353 let hbh_len = opt_len + 2;
1354 next_multiple_of_eight(hbh_len)
1355 }
1356}
1357
1358fn next_multiple_of_eight(x: usize) -> usize {
1359 (x + 7) & (!7)
1360}
1361
1362impl<C: IpSerializationContext<Ipv6>> IpPacketBuilder<C, Ipv6> for Ipv6PacketBuilder {
1363 fn new(src_ip: Ipv6Addr, dst_ip: Ipv6Addr, ttl: u8, proto: Ipv6Proto) -> Self {
1364 Ipv6PacketBuilder::new(src_ip, dst_ip, ttl, proto)
1365 }
1366
1367 fn src_ip(&self) -> Ipv6Addr {
1368 self.src_ip
1369 }
1370
1371 fn set_src_ip(&mut self, addr: Ipv6Addr) {
1372 self.src_ip = addr;
1373 }
1374
1375 fn dst_ip(&self) -> Ipv6Addr {
1376 self.dst_ip
1377 }
1378
1379 fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1380 self.dst_ip = addr;
1381 }
1382
1383 fn proto(&self) -> Ipv6Proto {
1384 self.proto
1385 }
1386
1387 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1388 self.dscp_and_ecn = dscp_and_ecn;
1389 }
1390}
1391
1392impl<'a, I> Ipv6HeaderBuilder for Ipv6PacketBuilderWithHbhOptions<'a, I>
1393where
1394 I: Iterator + Clone,
1395 I::Item: Borrow<HopByHopOption<'a>>,
1396{
1397 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1398 &self.prefix_builder
1399 }
1400
1401 fn extension_headers_len(&self) -> usize {
1402 self.prefix_builder.extension_headers_len() + self.aligned_hbh_len()
1403 }
1404
1405 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1406 &self,
1407 buffer: &mut BV,
1408 next_header: NextHeader,
1409 payload_len: usize,
1410 ) {
1411 let aligned_hbh_len = self.aligned_hbh_len();
1412 self.prefix_builder.serialize_header(
1414 buffer,
1415 NextHeader::Extension(Ipv6ExtHdrType::HopByHopOptions),
1416 payload_len + aligned_hbh_len,
1417 );
1418 let mut hbh_header = buffer.take_front(aligned_hbh_len).unwrap();
1420 let hbh_header = hbh_header.as_mut();
1421 hbh_header[0] = next_header.into();
1422 hbh_header[1] = u8::try_from((aligned_hbh_len - 8) / 8).expect("extension header too big");
1423 self.hbh_options.serialize_into(&mut hbh_header[2..]);
1424 }
1425}
1426
1427impl<'a, I> NestablePacketBuilder for Ipv6PacketBuilderWithHbhOptions<'a, I>
1428where
1429 I: Iterator + Clone,
1430 I::Item: Borrow<HopByHopOption<'a>>,
1431{
1432 impl_packet_builder_base! {}
1433}
1434
1435impl<'a, I, C: IpSerializationContext<Ipv6>> PacketBuilder<C>
1436 for Ipv6PacketBuilderWithHbhOptions<'a, I>
1437where
1438 I: Iterator + Clone,
1439 I::Item: Borrow<HopByHopOption<'a>>,
1440{
1441 impl_packet_builder! {}
1442}
1443
1444impl<'a, I, C: IpSerializationContext<Ipv6>> PartialPacketBuilder<C>
1445 for Ipv6PacketBuilderWithHbhOptions<'a, I>
1446where
1447 I: Iterator + Clone,
1448 I::Item: Borrow<HopByHopOption<'a>>,
1449{
1450 impl_partial_packet_builder! {}
1451}
1452
1453impl<'a, C: IpSerializationContext<Ipv6>, I> IpPacketBuilder<C, Ipv6>
1454 for Ipv6PacketBuilderWithHbhOptions<'a, I>
1455where
1456 I: Iterator<Item: Borrow<HopByHopOption<'a>>> + Debug + Default + Clone,
1457{
1458 fn new(src_ip: Ipv6Addr, dst_ip: Ipv6Addr, ttl: u8, proto: Ipv6Proto) -> Self {
1459 Ipv6PacketBuilderWithHbhOptions::new(
1460 Ipv6PacketBuilder::new(src_ip, dst_ip, ttl, proto),
1461 I::default(),
1462 )
1463 .expect("packet builder with no options should be valid")
1464 }
1465
1466 fn src_ip(&self) -> Ipv6Addr {
1467 self.prefix_builder.src_ip
1468 }
1469
1470 fn set_src_ip(&mut self, addr: Ipv6Addr) {
1471 self.prefix_builder.src_ip = addr;
1472 }
1473
1474 fn dst_ip(&self) -> Ipv6Addr {
1475 self.prefix_builder.dst_ip
1476 }
1477
1478 fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1479 self.prefix_builder.dst_ip = addr;
1480 }
1481
1482 fn proto(&self) -> Ipv6Proto {
1483 self.prefix_builder.proto
1484 }
1485
1486 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1487 <Ipv6PacketBuilder as IpPacketBuilder<C, Ipv6>>::set_dscp_and_ecn(
1488 &mut self.prefix_builder,
1489 dscp_and_ecn,
1490 )
1491 }
1492}
1493
1494#[derive(Debug, Eq, PartialEq)]
1503pub struct Ipv6PacketBuilderWithFragmentHeader<B> {
1504 header_builder: B,
1505 fragment_offset: FragmentOffset,
1506 more_fragments: bool,
1507 identification: u32,
1508}
1509
1510impl<B: Ipv6HeaderBefore<Self>> Ipv6PacketBuilderWithFragmentHeader<B> {
1511 pub fn new(
1513 header_builder: B,
1514 fragment_offset: FragmentOffset,
1515 more_fragments: bool,
1516 identification: u32,
1517 ) -> Self {
1518 Self { header_builder, fragment_offset, more_fragments, identification }
1519 }
1520}
1521
1522impl<B> Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>> for Ipv6PacketBuilder {}
1523impl<B, I> Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>>
1524 for Ipv6PacketBuilderWithHbhOptions<'_, I>
1525{
1526}
1527
1528pub trait Ipv6PacketBuilderBeforeFragment:
1531 Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<Self>> + Ipv6HeaderBuilder + Sized
1532{
1533}
1534impl<B> Ipv6PacketBuilderBeforeFragment for B where
1535 B: Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<Self>> + Ipv6HeaderBuilder + Sized
1536{
1537}
1538
1539impl<B: Ipv6HeaderBuilder> Ipv6HeaderBuilder for Ipv6PacketBuilderWithFragmentHeader<B> {
1540 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1541 self.header_builder.fixed_header()
1542 }
1543
1544 fn extension_headers_len(&self) -> usize {
1545 self.header_builder.extension_headers_len() + IPV6_FRAGMENT_EXT_HDR_LEN
1546 }
1547
1548 fn serialize_header<BB: SplitByteSliceMut, BV: BufferViewMut<BB>>(
1549 &self,
1550 buffer: &mut BV,
1551 next_header: NextHeader,
1552 payload_len: usize,
1553 ) {
1554 let Self { header_builder, fragment_offset, more_fragments, identification } = self;
1555 let payload_len = payload_len + IPV6_FRAGMENT_EXT_HDR_LEN;
1556 header_builder.serialize_header(
1557 buffer,
1558 NextHeader::Extension(Ipv6ExtHdrType::Fragment),
1559 payload_len,
1560 );
1561 buffer.write_obj_front(&u8::from(next_header)).unwrap();
1562 let _: BB = buffer.take_front_zero(1).unwrap();
1564 let more_fragments = u16::from(*more_fragments);
1565 buffer
1566 .write_obj_front(&U16::new(fragment_offset.into_raw() << 3 | more_fragments))
1567 .unwrap();
1568 buffer.write_obj_front(&U32::new(*identification)).unwrap();
1569 }
1570}
1571
1572impl<B: Ipv6HeaderBuilder> NestablePacketBuilder for Ipv6PacketBuilderWithFragmentHeader<B> {
1573 impl_packet_builder_base! {}
1574}
1575
1576impl<B: Ipv6HeaderBuilder, C: IpSerializationContext<Ipv6>> PacketBuilder<C>
1577 for Ipv6PacketBuilderWithFragmentHeader<B>
1578{
1579 impl_packet_builder! {}
1580}
1581
1582impl<B: Ipv6HeaderBuilder, C: IpSerializationContext<Ipv6>> PartialPacketBuilder<C>
1583 for Ipv6PacketBuilderWithFragmentHeader<B>
1584{
1585 impl_partial_packet_builder! {}
1586}
1587
1588pub(crate) fn reassemble_fragmented_packet<
1594 B: SplitByteSliceMut,
1595 BV: BufferViewMut<B>,
1596 I: Iterator<Item = Vec<u8>>,
1597>(
1598 mut buffer: BV,
1599 header: Vec<u8>,
1600 body_fragments: I,
1601) -> IpParseResult<Ipv6, ()> {
1602 assert!(header.len() >= IPV6_FIXED_HDR_LEN);
1603
1604 let bytes = buffer.as_mut();
1605
1606 bytes[0..header.len()].copy_from_slice(&header[..]);
1608 let mut byte_count = header.len();
1609
1610 for p in body_fragments {
1612 bytes[byte_count..byte_count + p.len()].copy_from_slice(&p[..]);
1613 byte_count += p.len();
1614 }
1615
1616 let payload_length = byte_count - IPV6_FIXED_HDR_LEN;
1628
1629 if payload_length > usize::from(core::u16::MAX) {
1632 return debug_err!(
1633 Err(ParseError::Format.into()),
1634 "fragmented packet payload length of {} bytes is too large",
1635 payload_length
1636 );
1637 }
1638
1639 let mut header = Ref::<_, FixedHeader>::from_prefix(bytes).unwrap().0;
1642
1643 header.payload_len.set(u16::try_from(payload_length).unwrap());
1645
1646 Ok(())
1647}
1648
1649#[cfg(test)]
1650mod tests {
1651 use assert_matches::assert_matches;
1652 use packet::{Buf, FragmentedBuffer, ParseBuffer};
1653 use test_case::test_case;
1654
1655 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1656 use crate::testutil::*;
1657
1658 use super::ext_hdrs::*;
1659 use super::*;
1660
1661 const DEFAULT_SRC_IP: Ipv6Addr =
1662 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1663 const DEFAULT_DST_IP: Ipv6Addr =
1664 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1665
1666 const DEFAULT_V4_SRC_IP: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1667 const DEFAULT_V4_DST_IP: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1668
1669 #[test]
1670 fn test_parse_serialize_full_tcp() {
1671 use crate::testdata::syn_v6::*;
1672
1673 let mut buf = ETHERNET_FRAME.bytes;
1674 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1675 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1676
1677 let mut body = frame.body();
1678 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1679 verify_ipv6_packet(&packet, IPV6_PACKET);
1680
1681 let buffer = packet
1683 .body()
1684 .into_serializer()
1685 .wrap_in(packet.builder())
1686 .wrap_in(frame.builder())
1687 .serialize_vec_outer(&mut NoOpSerializationContext)
1688 .unwrap();
1689 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1690
1691 assert_eq!(&packet.to_vec()[..], IPV6_PACKET.bytes);
1693 }
1694
1695 #[test]
1696 fn test_parse_serialize_full_udp() {
1697 use crate::testdata::dns_request_v6::*;
1698
1699 let mut buf = ETHERNET_FRAME.bytes;
1700 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1701 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1702
1703 let mut body = frame.body();
1704 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1705 verify_ipv6_packet(&packet, IPV6_PACKET);
1706
1707 let buffer = packet
1709 .body()
1710 .into_serializer()
1711 .wrap_in(packet.builder())
1712 .wrap_in(frame.builder())
1713 .serialize_vec_outer(&mut NoOpSerializationContext)
1714 .unwrap();
1715 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1716
1717 assert_eq!(&packet.to_vec()[..], IPV6_PACKET.bytes);
1719 }
1720
1721 #[test]
1722 fn test_parse_serialize_with_extension_headers() {
1723 use crate::testdata::mld_router_report::*;
1726
1727 let mut buf = REPORT;
1728 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1729 assert_eq!(packet.iter_extension_hdrs().count(), 1);
1730
1731 assert_eq!(&packet.to_vec()[..], REPORT);
1736 }
1737
1738 fn fixed_hdr_to_bytes(fixed_hdr: FixedHeader) -> [u8; IPV6_FIXED_HDR_LEN] {
1739 zerocopy::transmute!(fixed_hdr)
1740 }
1741
1742 fn new_fixed_hdr() -> FixedHeader {
1744 FixedHeader::new(
1745 DscpAndEcn::new(0, 2),
1746 0x77,
1747 0,
1748 IpProto::Tcp.into(),
1749 64,
1750 DEFAULT_SRC_IP,
1751 DEFAULT_DST_IP,
1752 )
1753 }
1754
1755 #[test]
1756 fn test_parse() {
1757 let mut buf = &fixed_hdr_to_bytes(new_fixed_hdr())[..];
1758 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1759 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1760 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1761 assert_eq!(packet.flowlabel(), 0x77);
1762 assert_eq!(packet.hop_limit(), 64);
1763 assert_eq!(packet.fixed_hdr.next_hdr, IpProto::Tcp.into());
1764 assert_eq!(packet.proto(), IpProto::Tcp.into());
1765 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1766 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1767 assert_eq!(packet.body(), []);
1768 }
1769
1770 #[test]
1771 fn test_parse_with_ext_hdrs() {
1772 #[rustfmt::skip]
1773 let mut buf = [
1774 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1776 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1777
1778 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,
1793 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1794
1795 IpProto::Tcp.into(), 1, 0, 1, 0, 1, 1, 0, 1, 6, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
1805 ];
1806 let mut fixed_hdr = new_fixed_hdr();
1807 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
1808 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1809 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1810 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1811 let mut buf = &buf[..];
1812 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1813 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1814 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1815 assert_eq!(packet.flowlabel(), 0x77);
1816 assert_eq!(packet.hop_limit(), 64);
1817 assert_eq!(packet.fixed_hdr.next_hdr, Ipv6ExtHdrType::HopByHopOptions.into());
1818 assert_eq!(packet.proto(), IpProto::Tcp.into());
1819 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1820 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1821 assert_eq!(packet.body(), [1, 2, 3, 4, 5]);
1822 let ext_hdrs: Vec<Ipv6ExtensionHeader<'_>> = packet.iter_extension_hdrs().collect();
1823 assert_eq!(ext_hdrs.len(), 3);
1824 assert_eq!(ext_hdrs[0].next_header, Ipv6ExtHdrType::Routing.into());
1826 if let Ipv6ExtensionHeaderData::HopByHopOptions { options } = ext_hdrs[0].data() {
1827 assert_eq!(options.iter().count(), 0);
1829 } else {
1830 panic!("Should have matched HopByHopOptions!");
1831 }
1832
1833 assert_eq!(ext_hdrs[1].next_header, Ipv6ExtHdrType::DestinationOptions.into());
1835 if let Ipv6ExtensionHeaderData::Routing { routing_data } = ext_hdrs[1].data() {
1836 assert_eq!(routing_data.routing_type(), Err(RoutingTypeParseError::UnsupportedType(0)));
1837 assert_eq!(routing_data.segments_left(), 0);
1838 } else {
1839 panic!("Should have matched RoutingExtensionHeader: {:?}", ext_hdrs[1].data());
1840 }
1841
1842 assert_eq!(ext_hdrs[2].next_header, IpProto::Tcp.into());
1844 if let Ipv6ExtensionHeaderData::DestinationOptions { options } = ext_hdrs[2].data() {
1845 assert_eq!(options.iter().count(), 0);
1847 } else {
1848 panic!("Should have matched DestinationOptions!");
1849 }
1850
1851 #[rustfmt::skip]
1853 let mut buf = [
1854 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1856 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1857
1858 Ipv6Proto::NoNextHeader.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
1867 ];
1868 let mut fixed_hdr = new_fixed_hdr();
1869 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
1870 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1871 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1872 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1873 let mut buf = &buf[..];
1874 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1875 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1876 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1877 assert_eq!(packet.flowlabel(), 0x77);
1878 assert_eq!(packet.hop_limit(), 64);
1879 assert_eq!(packet.fixed_hdr.next_hdr, Ipv6ExtHdrType::HopByHopOptions.into());
1880 assert_eq!(packet.proto(), Ipv6Proto::NoNextHeader);
1881 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1882 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1883 assert_eq!(packet.body(), [1, 2, 3, 4, 5]);
1884 let ext_hdrs: Vec<Ipv6ExtensionHeader<'_>> = packet.iter_extension_hdrs().collect();
1885 assert_eq!(ext_hdrs.len(), 1);
1886 assert_eq!(ext_hdrs[0].next_header, Ipv6Proto::NoNextHeader.into());
1888 if let Ipv6ExtensionHeaderData::HopByHopOptions { options } = ext_hdrs[0].data() {
1889 assert_eq!(options.iter().count(), 0);
1891 } else {
1892 panic!("Should have matched HopByHopOptions!");
1893 }
1894 }
1895
1896 #[test]
1897 fn test_parse_error() {
1898 let mut fixed_hdr = new_fixed_hdr();
1900 fixed_hdr.version_tc_flowlabel[0] = 0x50;
1901 assert_eq!(
1902 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1903 ParseError::Format.into()
1904 );
1905
1906 let mut fixed_hdr = new_fixed_hdr();
1908 fixed_hdr.payload_len = U16::new(2);
1909 assert_eq!(
1910 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1911 ParseError::Format.into()
1912 );
1913
1914 let mut fixed_hdr = new_fixed_hdr();
1916 fixed_hdr.next_hdr = 255;
1917 assert_eq!(
1918 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1919 Ipv6ParseError::ParameterProblem {
1920 src_ip: DEFAULT_SRC_IP,
1921 dst_ip: DEFAULT_DST_IP,
1922 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1923 pointer: u32::from(NEXT_HEADER_OFFSET),
1924 must_send_icmp: false,
1925 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1926 }
1927 );
1928
1929 let mut fixed_hdr = new_fixed_hdr();
1931 fixed_hdr.next_hdr = Ipv4Proto::Icmp.into();
1932 assert_eq!(
1933 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1934 Ipv6ParseError::ParameterProblem {
1935 src_ip: DEFAULT_SRC_IP,
1936 dst_ip: DEFAULT_DST_IP,
1937 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1938 pointer: u32::from(NEXT_HEADER_OFFSET),
1939 must_send_icmp: false,
1940 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1941 }
1942 );
1943
1944 #[rustfmt::skip]
1946 let mut buf = [
1947 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1949 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1950
1951 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,
1959 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1960
1961 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
1970 ];
1971 let mut fixed_hdr = new_fixed_hdr();
1972 fixed_hdr.next_hdr = Ipv6ExtHdrType::Routing.into();
1973 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1974 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1975 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1976 let mut buf = &buf[..];
1977 assert_eq!(
1978 buf.parse::<Ipv6Packet<_>>().unwrap_err(),
1979 Ipv6ParseError::ParameterProblem {
1980 src_ip: DEFAULT_SRC_IP,
1981 dst_ip: DEFAULT_DST_IP,
1982 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1983 pointer: IPV6_FIXED_HDR_LEN as u32,
1984 must_send_icmp: false,
1985 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1986 }
1987 );
1988
1989 #[rustfmt::skip]
1991 let mut buf = [
1992 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1994 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1995
1996 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,
2004 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2005
2006 1, 2, 3, 4, 5,
2008 ];
2009 let mut fixed_hdr = new_fixed_hdr();
2010 fixed_hdr.next_hdr = Ipv6ExtHdrType::Routing.into();
2011 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2012 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2013 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2014 let mut buf = &buf[..];
2015 assert_eq!(
2016 buf.parse::<Ipv6Packet<_>>().unwrap_err(),
2017 Ipv6ParseError::ParameterProblem {
2018 src_ip: DEFAULT_SRC_IP,
2019 dst_ip: DEFAULT_DST_IP,
2020 code: Icmpv6ParameterProblemCode::ErroneousHeaderField,
2021 pointer: (IPV6_FIXED_HDR_LEN as u32) + 2,
2022 must_send_icmp: true,
2023 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2024 }
2025 );
2026 }
2027
2028 #[test]
2029 fn test_parse_all_next_header_values() {
2030 let mut buf = [
2036 0x81, 0x13, 0x27, 0xeb, 0x75, 0x92, 0x33, 0x89, 0x01, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
2037 0x03, 0x70, 0x00, 0x22, 0xf7, 0x30, 0x2c, 0x06, 0xfe, 0xc9, 0x00, 0x2d, 0x3b, 0xeb,
2038 0xad, 0x3e, 0x5c, 0x41, 0xc8, 0x70, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x11, 0x00,
2039 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x4f, 0x4f, 0x6f, 0x4f, 0x4f, 0x4f, 0x4f,
2040 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x19, 0x19,
2041 0x19, 0x19, 0x19, 0x4f, 0x4f, 0x4f, 0x4f, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2042 0x00, 0x4f, 0x4f, 0x5a, 0x5a, 0x5a, 0xc9, 0x5a, 0x46, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
2043 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0xe4, 0x5a, 0x5a, 0x5a, 0x5a,
2044 ];
2045
2046 assert_matches!(
2049 (&buf[..]).parse::<Ipv6Packet<_>>(),
2050 Err(Ipv6ParseError::ParameterProblem {
2051 src_ip: _,
2052 dst_ip: _,
2053 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2054 pointer: 0,
2055 must_send_icmp: false,
2056 action: IpParseErrorAction::DiscardPacket,
2057 })
2058 );
2059
2060 for b in 0u8..=255 {
2063 buf[6] = b;
2065 let _: Result<_, _> = (&buf[..]).parse::<Ipv6Packet<_>>();
2066 }
2067 }
2068
2069 #[test]
2070 fn test_partial_parse() {
2071 use core::convert::TryInto as _;
2072 use core::ops::Deref as _;
2073
2074 #[rustfmt::skip]
2076 let mut buf = [
2077 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2079 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2080
2081 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2090 ];
2091 let len = buf.len() - IPV6_FIXED_HDR_LEN;
2092 let len = len.try_into().unwrap();
2093 let make_fixed_hdr = || {
2094 let mut fixed_hdr = new_fixed_hdr();
2095 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2096 fixed_hdr.payload_len = U16::new(len);
2097 fixed_hdr
2098 };
2099 const MALFORMED_BYTE: u8 = 10;
2101 buf[IPV6_FIXED_HDR_LEN + 1] = MALFORMED_BYTE;
2102 let fixed_hdr = fixed_hdr_to_bytes(make_fixed_hdr());
2103 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr);
2104 let mut buf = &buf[..];
2105 let partial = buf.parse::<Ipv6PacketRaw<_>>().unwrap();
2106 let Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto } = &partial;
2107 assert_eq!(fixed_hdr.deref(), &make_fixed_hdr());
2108 assert_eq!(
2109 *extension_hdrs.as_ref().incomplete().unwrap(),
2110 [IpProto::Tcp.into(), MALFORMED_BYTE]
2111 );
2112 assert_eq!(body_proto, &Err(ExtHdrParseError));
2113 assert!(Ipv6Packet::try_from_raw(partial).is_err());
2114
2115 let mut buf = [
2117 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,
2119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
2121 ];
2122 let make_fixed_hdr = || {
2123 let mut fixed_hdr = new_fixed_hdr();
2124 fixed_hdr.next_hdr = IpProto::Tcp.into();
2125 fixed_hdr.payload_len = U16::new(10);
2126 fixed_hdr
2127 };
2128 let fixed_hdr = fixed_hdr_to_bytes(make_fixed_hdr());
2129 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr);
2130 let mut parsebuff = &buf[..];
2131 let partial = parsebuff.parse::<Ipv6PacketRaw<_>>().unwrap();
2132 let Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto } = &partial;
2133 assert_eq!(fixed_hdr.deref(), &make_fixed_hdr());
2134 assert_eq!(extension_hdrs.as_ref().complete().unwrap().deref(), []);
2135 let (body, proto) = body_proto.unwrap();
2136 assert_eq!(body.incomplete().unwrap(), &buf[IPV6_FIXED_HDR_LEN..]);
2137 assert_eq!(proto, IpProto::Tcp.into());
2138 assert!(Ipv6Packet::try_from_raw(partial).is_err());
2139 }
2140
2141 fn new_builder() -> Ipv6PacketBuilder {
2143 Ipv6PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, 64, IpProto::Tcp.into())
2144 }
2145
2146 #[test]
2147 fn test_serialize() {
2148 let mut builder = new_builder();
2149 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
2150 builder.flowlabel(0x10405);
2151 let mut buf = (&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2152 .into_serializer()
2153 .wrap_in(builder)
2154 .serialize_vec_outer(&mut NoOpSerializationContext)
2155 .unwrap();
2156 assert_eq!(
2158 buf.as_ref(),
2159 &[
2160 100, 177, 4, 5, 0, 10, 6, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
2161 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, 1, 2, 3, 4,
2162 5, 6, 7, 8, 9
2163 ][..],
2164 );
2165
2166 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2167 assert_eq!(packet.dscp_and_ecn().dscp(), 0x12);
2170 assert_eq!(packet.dscp_and_ecn().ecn(), 3);
2171 assert_eq!(packet.flowlabel(), 0x10405);
2172 }
2173
2174 #[test]
2175 fn test_partial_serialize() {
2176 let mut builder = new_builder();
2177 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
2178 builder.flowlabel(0x10405);
2179 let body = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2180 let packet = (&body).into_serializer().wrap_in(builder);
2181
2182 const HEADER_LEN: usize = 40;
2185 const HEADER: [u8; HEADER_LEN] = [
2186 100, 177, 4, 5, 0, 10, 6, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
2187 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
2188 ];
2189 let mut expected_partial = HEADER.to_vec();
2190 expected_partial.resize(expected_partial.len() + body.len(), 0);
2191
2192 for i in 1..expected_partial.len() {
2193 let mut buf = vec![0u8; i];
2194 let result = packet.partial_serialize(
2195 &mut NoOpSerializationContext,
2196 PacketConstraints::UNCONSTRAINED,
2197 buf.as_mut_slice(),
2198 );
2199
2200 let bytes_written = if i >= HEADER_LEN { HEADER_LEN } else { 0 };
2203 assert_eq!(
2204 result,
2205 Ok(PartialSerializeResult { bytes_written, total_size: body.len() + HEADER_LEN })
2206 );
2207 if bytes_written > 0 {
2208 assert_eq!(buf, expected_partial[..i]);
2209 }
2210 }
2211 }
2212
2213 #[test]
2214 fn test_serialize_zeroes() {
2215 let mut buf_0 = [0; IPV6_FIXED_HDR_LEN];
2218 let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], IPV6_FIXED_HDR_LEN..)
2219 .wrap_in(new_builder())
2220 .serialize_vec_outer(&mut NoOpSerializationContext)
2221 .unwrap()
2222 .unwrap_a();
2223 let mut buf_1 = [0xFF; IPV6_FIXED_HDR_LEN];
2224 let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], IPV6_FIXED_HDR_LEN..)
2225 .wrap_in(new_builder())
2226 .serialize_vec_outer(&mut NoOpSerializationContext)
2227 .unwrap()
2228 .unwrap_a();
2229 assert_eq!(&buf_0[..], &buf_1[..]);
2230 }
2231
2232 #[test]
2233 fn test_packet_builder_proto_not_next_header() {
2234 let mut buf = (&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2238 .into_serializer()
2239 .wrap_in(
2240 Ipv6PacketBuilderWithHbhOptions::new(
2241 new_builder(),
2242 &[HopByHopOption {
2243 action: ExtensionHeaderOptionAction::SkipAndContinue,
2244 mutable: false,
2245 data: HopByHopOptionData::RouterAlert { data: 0 },
2246 }],
2247 )
2248 .unwrap(),
2249 )
2250 .serialize_vec_outer(&mut NoOpSerializationContext)
2251 .unwrap();
2252 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2253 assert_eq!(packet.proto(), IpProto::Tcp.into());
2254 assert_eq!(packet.next_header(), Ipv6ExtHdrType::HopByHopOptions.into());
2255 }
2256
2257 #[test]
2258 #[should_panic(expected = "SizeLimitExceeded, Nested { inner: Buf { buf:")]
2259 fn test_serialize_panic_packet_length() {
2260 let _: Buf<&mut [u8]> = Buf::new(&mut [0; 1 << 16][..], ..)
2263 .wrap_in(new_builder())
2264 .serialize_vec_outer(&mut NoOpSerializationContext)
2265 .unwrap()
2266 .unwrap_a();
2267 }
2268
2269 #[test]
2270 #[should_panic(expected = "packet must have at least one extension header")]
2271 fn test_copy_header_bytes_for_fragment_without_ext_hdrs() {
2272 let mut buf = &fixed_hdr_to_bytes(new_fixed_hdr())[..];
2273 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2274 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2275 }
2276
2277 #[test]
2278 #[should_panic(expected = "exhausted all extension headers without finding fragment header")]
2279 fn test_copy_header_bytes_for_fragment_with_1_ext_hdr_no_fragment() {
2280 #[rustfmt::skip]
2281 let mut buf = [
2282 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2284 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2285
2286 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2295 ];
2296 let mut fixed_hdr = new_fixed_hdr();
2297 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2298 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2299 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2300 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2301 let mut buf = &buf[..];
2302 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2303 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2304 }
2305
2306 #[test]
2307 #[should_panic(expected = "exhausted all extension headers without finding fragment header")]
2308 fn test_copy_header_bytes_for_fragment_with_2_ext_hdr_no_fragment() {
2309 #[rustfmt::skip]
2310 let mut buf = [
2311 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2313 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2314
2315 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,
2332 ];
2333 let mut fixed_hdr = new_fixed_hdr();
2334 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2335 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2336 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2337 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2338 let mut buf = &buf[..];
2339 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2340 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2341 }
2342
2343 #[test]
2344 fn test_copy_header_bytes_for_fragment() {
2345 #[rustfmt::skip]
2350 let mut bytes = [
2351 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2353 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2354
2355 IpProto::Tcp.into(), 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5,
2363 ];
2364 let mut fixed_hdr = new_fixed_hdr();
2365 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2366 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2367 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2368 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2369 let mut buf = &bytes[..];
2370 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2371 let copied_bytes = packet.copy_header_bytes_for_fragment();
2372 bytes[6] = IpProto::Tcp.into();
2373 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN]);
2374
2375 #[rustfmt::skip]
2380 let mut bytes = [
2381 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2383 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2384
2385 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,
2400 ];
2401 let mut fixed_hdr = new_fixed_hdr();
2402 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2403 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2404 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2405 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2406 let mut buf = &bytes[..];
2407 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2408 let copied_bytes = packet.copy_header_bytes_for_fragment();
2409 bytes[IPV6_FIXED_HDR_LEN] = IpProto::Tcp.into();
2410 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN + 8]);
2411
2412 #[rustfmt::skip]
2417 let mut bytes = [
2418 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2420 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2421
2422 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,
2445 ];
2446 let mut fixed_hdr = new_fixed_hdr();
2447 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2448 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2449 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2450 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2451 let mut buf = &bytes[..];
2452 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2453 let copied_bytes = packet.copy_header_bytes_for_fragment();
2454 bytes[IPV6_FIXED_HDR_LEN + 8] = IpProto::Tcp.into();
2455 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN + 24]);
2456
2457 #[rustfmt::skip]
2462 let mut bytes = [
2463 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2465 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2466
2467 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,
2483 ];
2484 let mut fixed_hdr = new_fixed_hdr();
2485 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2486 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2487 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2488 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2489 let mut buf = &bytes[..];
2490 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2491 let copied_bytes = packet.copy_header_bytes_for_fragment();
2492 let mut expected_bytes = Vec::new();
2493 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2494 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2495 expected_bytes[6] = Ipv6ExtHdrType::DestinationOptions.into();
2496 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2497
2498 #[rustfmt::skip]
2503 let mut bytes = [
2504 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2506 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2507
2508 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,
2530 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2531
2532 1, 2, 3, 4, 5,
2534 ];
2535 let mut fixed_hdr = new_fixed_hdr();
2536 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2537 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2538 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2539 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2540 let mut buf = &bytes[..];
2541 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2542 let copied_bytes = packet.copy_header_bytes_for_fragment();
2543 let mut expected_bytes = Vec::new();
2544 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2545 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2546 expected_bytes[6] = Ipv6ExtHdrType::DestinationOptions.into();
2547 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2548
2549 #[rustfmt::skip]
2554 let mut bytes = [
2555 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2557 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2558
2559 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,
2582 ];
2583 let mut fixed_hdr = new_fixed_hdr();
2584 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2585 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2586 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2587 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2588 let mut buf = &bytes[..];
2589 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2590 let copied_bytes = packet.copy_header_bytes_for_fragment();
2591 let mut expected_bytes = Vec::new();
2592 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN + 8]);
2593 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 16..bytes.len() - 5]);
2594 expected_bytes[IPV6_FIXED_HDR_LEN] = Ipv6ExtHdrType::DestinationOptions.into();
2595 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2596
2597 #[rustfmt::skip]
2602 let mut bytes = [
2603 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2605 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2606
2607 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,
2621 ];
2622 let mut fixed_hdr = new_fixed_hdr();
2623 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2624 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2625 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2626 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2627 let mut buf = &bytes[..];
2628 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2629 let copied_bytes = packet.copy_header_bytes_for_fragment();
2630 let mut expected_bytes = Vec::new();
2631 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2632 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2633 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2634
2635 #[rustfmt::skip]
2641 let mut bytes = [
2642 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2644 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2645
2646 Ipv6ExtHdrType::Routing.into(), 0, 0, 1, 0, 1, 1, 0, Ipv6ExtHdrType::Fragment.into(), 4, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
2661 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2662
2663 IpProto::Tcp.into(), 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5,
2671 ];
2672 let mut fixed_hdr = new_fixed_hdr();
2673 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2674 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2675 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2676 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2677 let mut buf = &bytes[..];
2678 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2679 let copied_bytes = packet.copy_header_bytes_for_fragment();
2680 let mut expected_bytes = Vec::new();
2681 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN + 48]);
2683 expected_bytes[IPV6_FIXED_HDR_LEN + 8] = IpProto::Tcp.into();
2684 assert_eq!(copied_bytes, expected_bytes);
2685 }
2686
2687 #[test]
2688 fn test_next_multiple_of_eight() {
2689 for x in 0usize..=IPV6_HBH_OPTIONS_MAX_LEN {
2690 let y = next_multiple_of_eight(x);
2691 assert_eq!(y % 8, 0);
2692 assert!(y >= x);
2693 if x % 8 == 0 {
2694 assert_eq!(x, y);
2695 } else {
2696 assert_eq!(x + (8 - x % 8), y);
2697 }
2698 }
2699 }
2700
2701 fn create_ipv4_and_ipv6_builders(
2702 proto_v4: Ipv4Proto,
2703 proto_v6: Ipv6Proto,
2704 ) -> (Ipv4PacketBuilder, Ipv6PacketBuilder) {
2705 const IP_DSCP_AND_ECN: DscpAndEcn = DscpAndEcn::new(0x12, 3);
2706 const IP_TTL: u8 = 64;
2707
2708 let mut ipv4_builder =
2709 Ipv4PacketBuilder::new(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP, IP_TTL, proto_v4);
2710 ipv4_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
2711 ipv4_builder.df_flag(false);
2712 ipv4_builder.mf_flag(false);
2713 ipv4_builder.fragment_offset(FragmentOffset::ZERO);
2714
2715 let mut ipv6_builder =
2716 Ipv6PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, IP_TTL, proto_v6);
2717 ipv6_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
2718 ipv6_builder.flowlabel(0x456);
2719
2720 (ipv4_builder, ipv6_builder)
2721 }
2722
2723 fn create_tcp_ipv4_and_ipv6_pkt()
2724 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
2725 use crate::tcp::TcpSegmentBuilder;
2726 use core::num::NonZeroU16;
2727
2728 let tcp_src_port: NonZeroU16 = NonZeroU16::new(20).unwrap();
2729 let tcp_dst_port: NonZeroU16 = NonZeroU16::new(30).unwrap();
2730 const TCP_SEQ_NUM: u32 = 4321;
2731 const TCP_ACK_NUM: Option<u32> = Some(1234);
2732 const TCP_WINDOW_SIZE: u16 = 12345;
2733 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2734
2735 let (ipv4_builder, ipv6_builder) =
2736 create_ipv4_and_ipv6_builders(IpProto::Tcp.into(), IpProto::Tcp.into());
2737
2738 let tcp_builder = TcpSegmentBuilder::new(
2739 DEFAULT_V4_SRC_IP,
2740 DEFAULT_V4_DST_IP,
2741 tcp_src_port,
2742 tcp_dst_port,
2743 TCP_SEQ_NUM,
2744 TCP_ACK_NUM,
2745 TCP_WINDOW_SIZE,
2746 );
2747
2748 let v4_pkt_buf = (&PAYLOAD)
2749 .into_serializer()
2750 .wrap_in(tcp_builder)
2751 .wrap_in(ipv4_builder)
2752 .serialize_vec_outer(&mut NoOpSerializationContext)
2753 .expect("Failed to serialize to v4_pkt_buf");
2754
2755 let v6_tcp_builder = TcpSegmentBuilder::new(
2756 DEFAULT_SRC_IP,
2757 DEFAULT_DST_IP,
2758 tcp_src_port,
2759 tcp_dst_port,
2760 TCP_SEQ_NUM,
2761 TCP_ACK_NUM,
2762 TCP_WINDOW_SIZE,
2763 );
2764
2765 let v6_pkt_buf = (&PAYLOAD)
2766 .into_serializer()
2767 .wrap_in(v6_tcp_builder)
2768 .wrap_in(ipv6_builder)
2769 .serialize_vec_outer(&mut NoOpSerializationContext)
2770 .expect("Failed to serialize to v4_pkt_buf");
2771
2772 (v4_pkt_buf, v6_pkt_buf)
2773 }
2774
2775 #[test]
2776 fn test_nat64_translate_tcp() {
2777 let (expected_v4_pkt_buf, mut v6_pkt_buf) = create_tcp_ipv4_and_ipv6_pkt();
2778
2779 let parsed_v6_packet =
2780 v6_pkt_buf.parse::<Ipv6Packet<_>>().expect("Failed to parse v6_pkt_buf");
2781 let nat64_translation_result =
2782 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2783
2784 let serializable_pkt =
2785 assert_matches!(nat64_translation_result, Nat64TranslationResult::Forward(s) => s);
2786
2787 let translated_v4_pkt_buf = serializable_pkt
2788 .serialize_vec_outer(&mut NoOpSerializationContext)
2789 .expect("Failed to serialize to translated_v4_pkt_buf");
2790
2791 assert_eq!(
2792 expected_v4_pkt_buf.to_flattened_vec(),
2793 translated_v4_pkt_buf.to_flattened_vec()
2794 );
2795 }
2796
2797 fn create_udp_ipv4_and_ipv6_pkt()
2798 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
2799 use crate::udp::UdpPacketBuilder;
2800 use core::num::NonZeroU16;
2801
2802 let udp_src_port: NonZeroU16 = NonZeroU16::new(35000).unwrap();
2803 let udp_dst_port: NonZeroU16 = NonZeroU16::new(53).unwrap();
2804 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2805
2806 let (ipv4_builder, ipv6_builder) =
2807 create_ipv4_and_ipv6_builders(IpProto::Udp.into(), IpProto::Udp.into());
2808
2809 let v4_udp_builder = UdpPacketBuilder::new(
2810 DEFAULT_V4_SRC_IP,
2811 DEFAULT_V4_DST_IP,
2812 Some(udp_src_port),
2813 udp_dst_port,
2814 );
2815
2816 let v4_pkt_buf = (&PAYLOAD)
2817 .into_serializer()
2818 .wrap_in(v4_udp_builder)
2819 .wrap_in(ipv4_builder)
2820 .serialize_vec_outer(&mut NoOpSerializationContext)
2821 .expect("Unable to serialize to v4_pkt_buf");
2822
2823 let v6_udp_builder =
2824 UdpPacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, Some(udp_src_port), udp_dst_port);
2825
2826 let v6_pkt_buf = (&PAYLOAD)
2827 .into_serializer()
2828 .wrap_in(v6_udp_builder)
2829 .wrap_in(ipv6_builder)
2830 .serialize_vec_outer(&mut NoOpSerializationContext)
2831 .expect("Unable to serialize to v6_pkt_buf");
2832
2833 (v4_pkt_buf, v6_pkt_buf)
2834 }
2835
2836 #[test]
2837 fn test_nat64_translate_udp() {
2838 let (expected_v4_pkt_buf, mut v6_pkt_buf) = create_udp_ipv4_and_ipv6_pkt();
2839
2840 let parsed_v6_packet =
2841 v6_pkt_buf.parse::<Ipv6Packet<_>>().expect("Unable to parse Ipv6Packet");
2842 let nat64_translation_result =
2843 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2844
2845 let serializable_pkt = assert_matches!(nat64_translation_result,
2846 Nat64TranslationResult::Forward(s) => s);
2847
2848 let translated_v4_pkt_buf = serializable_pkt
2849 .serialize_vec_outer(&mut NoOpSerializationContext)
2850 .expect("Unable to serialize to translated_v4_pkt_buf");
2851
2852 assert_eq!(
2853 expected_v4_pkt_buf.to_flattened_vec(),
2854 translated_v4_pkt_buf.to_flattened_vec()
2855 );
2856 }
2857
2858 #[test]
2859 fn test_nat64_translate_non_tcp_udp_icmp() {
2860 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2861
2862 let (ipv4_builder, ipv6_builder) =
2863 create_ipv4_and_ipv6_builders(Ipv4Proto::Other(59), Ipv6Proto::Other(59));
2864
2865 let expected_v4_pkt_buf = (&PAYLOAD)
2866 .into_serializer()
2867 .wrap_in(ipv4_builder)
2868 .serialize_vec_outer(&mut NoOpSerializationContext)
2869 .expect("Unable to serialize to expected_v4_pkt_buf");
2870
2871 let mut v6_pkt_buf = (&PAYLOAD)
2872 .into_serializer()
2873 .wrap_in(ipv6_builder)
2874 .serialize_vec_outer(&mut NoOpSerializationContext)
2875 .expect("Unable to serialize to v6_pkt_buf");
2876
2877 let translated_v4_pkt_buf = {
2878 let parsed_v6_packet = v6_pkt_buf
2879 .parse::<Ipv6Packet<_>>()
2880 .expect("Unable to serialize to translated_v4_pkt_buf");
2881
2882 let nat64_translation_result =
2883 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2884
2885 let serializable_pkt = assert_matches!(nat64_translation_result,
2886 Nat64TranslationResult::Forward(s) => s);
2887
2888 let translated_buf = serializable_pkt
2889 .serialize_vec_outer(&mut NoOpSerializationContext)
2890 .expect("Unable to serialize to translated_buf");
2891
2892 translated_buf
2893 };
2894
2895 assert_eq!(
2896 expected_v4_pkt_buf.to_flattened_vec(),
2897 translated_v4_pkt_buf.to_flattened_vec()
2898 );
2899 }
2900
2901 #[test_case(new_builder(), true; "fixed header more frags")]
2902 #[test_case(Ipv6PacketBuilderWithHbhOptions::new(
2903 new_builder(),
2904 &[HopByHopOption {
2905 action: ExtensionHeaderOptionAction::SkipAndContinue,
2906 mutable: false,
2907 data: HopByHopOptionData::RouterAlert { data: 0 },
2908 }]).unwrap(), false; "hbh last frag")]
2909 fn ipv6_packet_builder_with_fragment_header<
2910 B: Ipv6HeaderBuilder + Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>> + Debug,
2911 >(
2912 inner: B,
2913 more_fragments: bool,
2914 ) {
2915 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2916 let fragment_offset = FragmentOffset::new(13).unwrap();
2917 let identification = 0xABCDABCD;
2918 let builder = Ipv6PacketBuilderWithFragmentHeader::new(
2919 inner,
2920 fragment_offset,
2921 more_fragments,
2922 identification,
2923 );
2924 let mut serialized = builder
2925 .wrap_body(PAYLOAD.into_serializer())
2926 .serialize_vec_outer(&mut NoOpSerializationContext)
2927 .unwrap()
2928 .unwrap_b();
2929 let packet = serialized.parse::<Ipv6Packet<_>>().unwrap();
2930 assert!(packet.fragment_header_present());
2931 assert_eq!(packet.proto(), Ipv6Proto::Proto(IpProto::Tcp));
2932 let fragment_data = packet
2933 .extension_hdrs
2934 .into_iter()
2935 .find_map(|ext_hdr| match ext_hdr.into_data() {
2936 Ipv6ExtensionHeaderData::Fragment { fragment_data } => Some(fragment_data),
2937 _ => None,
2938 })
2939 .unwrap();
2940 assert_eq!(fragment_data.fragment_offset(), fragment_offset);
2941 assert_eq!(fragment_data.identification(), identification);
2942 assert_eq!(fragment_data.m_flag(), more_fragments);
2943 }
2944
2945 #[test]
2948 fn extension_headers_take_from_max_body_size() {
2949 let builder = new_builder();
2950 assert_eq!(builder.constraints().max_body_len(), IPV6_MAX_PAYLOAD_LENGTH);
2951 let builder =
2952 Ipv6PacketBuilderWithFragmentHeader::new(builder, FragmentOffset::ZERO, false, 1234);
2953 assert_eq!(
2954 builder.constraints().max_body_len(),
2955 IPV6_MAX_PAYLOAD_LENGTH - IPV6_FRAGMENT_EXT_HDR_LEN
2956 );
2957 }
2958
2959 #[test]
2960 fn test_partial_serialize_parsed() {
2961 let packet_bytes = [
2962 100, 177, 4, 5, 0, 10, 6, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
2963 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, 1, 2, 3, 4, 5, 6, 7,
2964 8, 9,
2965 ];
2966 let packet_len = packet_bytes.len();
2967 let mut packet_bytes_copy = packet_bytes;
2968 let mut packet_bytes_ref: &mut [u8] = &mut packet_bytes_copy[..];
2969 let packet = packet_bytes_ref.parse::<Ipv6Packet<_>>().unwrap();
2970
2971 for i in 1..(packet_len + 1) {
2972 let mut buf = vec![0u8; i];
2973 let result = packet.partial_serialize(
2974 &mut NoOpSerializationContext,
2975 PacketConstraints::UNCONSTRAINED,
2976 buf.as_mut_slice(),
2977 );
2978
2979 let bytes_written = if i >= packet_len { packet_len } else { i };
2980 assert_eq!(
2981 result,
2982 Ok(PartialSerializeResult { bytes_written, total_size: packet_len })
2983 );
2984 assert_eq!(buf[..bytes_written], packet_bytes[..bytes_written]);
2985 }
2986 }
2987}