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 _outer: 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 bytes[IPV6_FIXED_HDR_LEN + ext_hdr_start] = next_ext_hdr.next_header;
527 }
528 Ipv6ExtensionHeaderData::Fragment { .. } => unreachable!(
529 "If we had a fragment header before `ext_hdr`, we should have used that instead"
530 ),
531 }
532
533 break;
534 }
535
536 ext_hdr = next_ext_hdr;
537 ext_hdr_start = ext_hdr_end;
538 ext_hdr_end = iter.context().bytes_parsed;
539 }
540 }
541
542 assert_eq!(bytes.len(), expected_bytes_len);
544 bytes
545 }
546
547 fn header_len(&self) -> usize {
548 Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.bytes().len()
549 }
550
551 fn fragment_header_present(&self) -> bool {
552 for ext_hdr in self.extension_hdrs.iter() {
553 if matches!(ext_hdr.data(), Ipv6ExtensionHeaderData::Fragment { .. }) {
554 return true;
555 }
556 }
557 false
558 }
559
560 pub fn builder(&self) -> Ipv6PacketBuilder {
562 Ipv6PacketBuilder {
563 dscp_and_ecn: self.dscp_and_ecn(),
564 flowlabel: self.flowlabel(),
565 hop_limit: self.hop_limit(),
566 proto: self.proto(),
567 src_ip: self.src_ip(),
568 dst_ip: self.dst_ip(),
569 }
570 }
571
572 pub fn nat64_translate(
598 &self,
599 v4_src_addr: Ipv4Addr,
600 v4_dst_addr: Ipv4Addr,
601 ) -> Nat64TranslationResult<
602 impl Serializer<NoOpSerializationContext, Buffer = EmptyBuf> + Debug + '_,
603 Nat64Error,
604 > {
605 #[derive(Debug)]
608 enum Nat64Serializer<T, U, O> {
609 Tcp(T),
610 Udp(U),
611 Other(O),
612 }
613 impl<T, U, O> Serializer<NoOpSerializationContext> for Nat64Serializer<T, U, O>
614 where
615 T: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
616 U: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
617 O: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
618 {
619 type Buffer = EmptyBuf;
620 fn serialize<B, P>(
621 self,
622 context: &mut NoOpSerializationContext,
623 outer: PacketConstraints,
624 provider: P,
625 ) -> Result<B, (SerializeError<P::Error>, Self)>
626 where
627 B: GrowBufferMut,
628 P: BufferProvider<Self::Buffer, B>,
629 {
630 match self {
631 Nat64Serializer::Tcp(serializer) => serializer
632 .serialize(context, outer, provider)
633 .map_err(|(err, ser)| (err, Nat64Serializer::Tcp(ser))),
634 Nat64Serializer::Udp(serializer) => serializer
635 .serialize(context, outer, provider)
636 .map_err(|(err, ser)| (err, Nat64Serializer::Udp(ser))),
637 Nat64Serializer::Other(serializer) => serializer
638 .serialize(context, outer, provider)
639 .map_err(|(err, ser)| (err, Nat64Serializer::Other(ser))),
640 }
641 }
642
643 fn serialize_new_buf<B: GrowBufferMut, A: LayoutBufferAlloc<B>>(
644 &self,
645 context: &mut NoOpSerializationContext,
646 outer: PacketConstraints,
647 alloc: A,
648 ) -> Result<B, SerializeError<A::Error>> {
649 match self {
650 Nat64Serializer::Tcp(serializer) => {
651 serializer.serialize_new_buf(context, outer, alloc)
652 }
653 Nat64Serializer::Udp(serializer) => {
654 serializer.serialize_new_buf(context, outer, alloc)
655 }
656 Nat64Serializer::Other(serializer) => {
657 serializer.serialize_new_buf(context, outer, alloc)
658 }
659 }
660 }
661 }
662
663 impl<T, U, O> NestableSerializer for Nat64Serializer<T, U, O>
664 where
665 T: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
666 U: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
667 O: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
668 {
669 }
670
671 if self.fragment_header_present() {
674 return Nat64TranslationResult::Err(Nat64Error::NotImplemented);
675 }
676
677 let v4_builder = |v4_proto| {
678 let mut builder =
679 Ipv4PacketBuilder::new(v4_src_addr, v4_dst_addr, self.hop_limit(), v4_proto);
680 builder.dscp_and_ecn(self.dscp_and_ecn());
681
682 const IPV4_HEADER_LEN_BYTES: usize = HDR_PREFIX_LEN;
687
688 builder.df_flag(self.body().len() + IPV4_HEADER_LEN_BYTES > 1260);
694
695 builder.fragment_offset(FragmentOffset::ZERO);
698 builder.mf_flag(false);
699
700 builder
701 };
702
703 match self.proto() {
704 Ipv6Proto::Proto(IpProto::Tcp) => {
705 let v4_pkt_builder = v4_builder(Ipv4Proto::Proto(IpProto::Tcp));
706 let args = TcpParseArgs::new(self.src_ip(), self.dst_ip());
707 match TcpSegment::parse(&mut self.body.as_bytes(), args) {
712 Ok(tcp) => {
713 let tcp_serializer =
717 Nat64Serializer::Tcp(tcp.into_serializer(v4_src_addr, v4_dst_addr));
718 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(tcp_serializer))
719 }
720 Err(msg) => {
721 debug!("Parsing of TCP segment failed: {:?}", msg);
722
723 let common_serializer =
732 Nat64Serializer::Other(self.body().into_serializer());
733 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
734 }
735 }
736 }
737
738 Ipv6Proto::Proto(IpProto::Udp) => {
743 let v4_pkt_builder = v4_builder(Ipv4Proto::Proto(IpProto::Udp));
744 let args = UdpParseArgs::new(self.src_ip(), self.dst_ip());
745 match UdpPacket::parse(&mut self.body.as_bytes(), args) {
746 Ok(udp) => {
747 let udp_serializer =
751 Nat64Serializer::Udp(udp.into_serializer(v4_src_addr, v4_dst_addr));
752 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(udp_serializer))
753 }
754 Err(msg) => {
755 debug!("Parsing of UDP packet failed: {:?}", msg);
756
757 let common_serializer =
767 Nat64Serializer::Other(self.body().into_serializer());
768 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
769 }
770 }
771 }
772
773 Ipv6Proto::Icmpv6 => Nat64TranslationResult::Err(Nat64Error::NotImplemented),
776
777 Ipv6Proto::Other(val) => {
797 let v4_pkt_builder = v4_builder(Ipv4Proto::Other(val));
798 let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
799 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
800 }
801
802 Ipv6Proto::NoNextHeader => {
803 let v4_pkt_builder = v4_builder(Ipv4Proto::Other(Ipv6Proto::NoNextHeader.into()));
804 let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
805 Nat64TranslationResult::Forward(v4_pkt_builder.wrap_body(common_serializer))
806 }
807
808 Ipv6Proto::Proto(IpProto::Reserved) => Nat64TranslationResult::Drop,
811 }
812 }
813
814 pub fn to_vec(&self) -> Vec<u8> {
816 let Ipv6Packet { fixed_hdr, extension_hdrs, body, proto: _ } = self;
817 let mut buf = Vec::with_capacity(
818 Ref::bytes(&fixed_hdr).len() + extension_hdrs.bytes().len() + body.as_bytes().len(),
819 );
820 buf.extend(Ref::bytes(&fixed_hdr));
821 buf.extend(extension_hdrs.bytes());
822 buf.extend(body.as_bytes());
823 buf
824 }
825}
826
827impl<B: SplitByteSliceMut> Ipv6Packet<B> {
828 pub fn set_src_ip(&mut self, addr: Ipv6Addr) {
830 self.fixed_hdr.src_ip = addr;
831 }
832
833 pub fn set_dst_ip(&mut self, addr: Ipv6Addr) {
835 self.fixed_hdr.dst_ip = addr;
836 }
837
838 pub fn set_hop_limit(&mut self, hlim: u8) {
840 self.fixed_hdr.hop_limit = hlim;
841 }
842
843 pub fn body_mut(&mut self) -> &mut [u8] {
845 &mut self.body
846 }
847
848 pub fn parts_with_body_mut(&mut self) -> (&FixedHeader, ExtensionHeaders<'_>, &mut [u8]) {
851 (&self.fixed_hdr, ExtensionHeaders(self.extension_hdrs.as_ref()), &mut self.body)
852 }
853}
854
855impl<B: SplitByteSlice> Debug for Ipv6Packet<B> {
856 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
857 f.debug_struct("Ipv6Packet")
858 .field("src_ip", &self.src_ip())
859 .field("dst_ip", &self.dst_ip())
860 .field("hop_limit", &self.hop_limit())
861 .field("proto", &self.proto())
862 .field("dscp", &self.dscp_and_ecn().dscp())
863 .field("ecn", &self.dscp_and_ecn().ecn())
864 .field("flowlabel", &self.flowlabel())
865 .field("extension headers", &"TODO")
866 .field("body", &alloc::format!("<{} bytes>", self.body.len()))
867 .finish()
868 }
869}
870
871pub struct ExtensionHeaders<'a>(Records<&'a [u8], Ipv6ExtensionHeaderImpl>);
873
874impl<'a> ExtensionHeaders<'a> {
875 pub fn iter(&self) -> impl Iterator<Item = Ipv6ExtensionHeader<'_>> {
877 self.0.iter()
878 }
879
880 pub fn bytes(&self) -> &[u8] {
882 self.0.bytes()
883 }
884}
885
886#[derive(Copy, Clone, Debug, Eq, PartialEq)]
892pub struct ExtHdrParseError;
893
894pub struct Ipv6PacketRaw<B> {
904 fixed_hdr: Ref<B, FixedHeader>,
906 extension_hdrs: MaybeParsed<RecordsRaw<B, Ipv6ExtensionHeaderImpl>, B>,
912 body_proto: Result<(MaybeParsed<B, B>, Ipv6Proto), ExtHdrParseError>,
925}
926
927impl<B> Ipv6PacketRaw<B> {
928 pub fn body_mut(&mut self) -> Option<&mut B> {
932 match self.body_proto {
933 Ok(ref mut b) => match b {
934 (MaybeParsed::Complete(b), _) => Some(b),
935 (MaybeParsed::Incomplete(b), _) => Some(b),
936 },
937 Err(_) => None,
938 }
939 }
940}
941
942impl<B: SplitByteSlice> Ipv6Header for Ipv6PacketRaw<B> {
943 fn get_fixed_header(&self) -> &FixedHeader {
944 &self.fixed_hdr
945 }
946}
947
948impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv6PacketRaw<B> {
949 type Error = Ipv6ParseError;
950
951 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> Result<Self, Self::Error> {
952 let fixed_hdr = buffer
953 .take_obj_front::<FixedHeader>()
954 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for header"))?;
955 let payload_len = fixed_hdr.payload_len.get().into();
956 let _: Option<B> = buffer.len().checked_sub(payload_len).map(|padding| {
958 buffer.take_back(padding).unwrap_or_else(|| {
959 panic!("buffer.len()={} padding={}", buffer.len(), padding);
960 })
961 });
962
963 let mut extension_hdr_context = Ipv6ExtensionHeaderParsingContext::new(fixed_hdr.next_hdr);
964
965 let extension_hdrs =
966 RecordsRaw::parse_raw_with_mut_context(&mut buffer, &mut extension_hdr_context)
967 .map_incomplete(|(b, _)| b);
968
969 let body_proto = match &extension_hdrs {
970 MaybeParsed::Complete(r) => {
971 let _: &RecordsRaw<B, _> = r;
972 assert!(is_valid_next_header_upper_layer(extension_hdr_context.next_header));
993 let proto = Ipv6Proto::from(extension_hdr_context.next_header);
994 let body = MaybeParsed::new_with_min_len(
995 buffer.into_rest(),
996 payload_len.saturating_sub(extension_hdrs.len()),
997 );
998 Ok((body, proto))
999 }
1000 MaybeParsed::Incomplete(b) => {
1001 let _: &B = b;
1002 Err(ExtHdrParseError)
1003 }
1004 };
1005
1006 Ok(Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto })
1007 }
1008
1009 fn parse_metadata(&self) -> ParseMetadata {
1010 let header_len = Ref::bytes(&self.fixed_hdr).len() + self.extension_hdrs.len();
1011 let body_len = self.body_proto.as_ref().map(|(b, _p)| b.len()).unwrap_or(0);
1012 ParseMetadata::from_packet(header_len, body_len, 0)
1013 }
1014}
1015
1016impl<B: SplitByteSlice> Ipv6PacketRaw<B> {
1017 pub fn body_proto(&self) -> Result<(MaybeParsed<&[u8], &[u8]>, Ipv6Proto), ExtHdrParseError> {
1030 self.body_proto
1031 .as_ref()
1032 .map(|(mp, proto)| {
1033 (mp.as_ref().map(|b| b.deref()).map_incomplete(|b| b.deref()), *proto)
1034 })
1035 .map_err(|e| *e)
1036 }
1037
1038 pub fn body(&self) -> Result<MaybeParsed<&[u8], &[u8]>, ExtHdrParseError> {
1049 self.body_proto().map(|(body, _proto)| body)
1050 }
1051
1052 pub fn proto(&self) -> Result<Ipv6Proto, ExtHdrParseError> {
1059 self.body_proto().map(|(_body, proto)| proto)
1060 }
1061}
1062
1063impl<B: SplitByteSliceMut> Ipv6PacketRaw<B> {
1064 pub fn set_src_ip(&mut self, addr: Ipv6Addr) {
1066 self.fixed_hdr.src_ip = addr;
1067 }
1068
1069 pub fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1071 self.fixed_hdr.dst_ip = addr;
1072 }
1073}
1074
1075pub enum NextHeader {
1078 NextLayer(Ipv6Proto),
1080 Extension(Ipv6ExtHdrType),
1082}
1083
1084impl From<NextHeader> for u8 {
1085 fn from(next_hdr: NextHeader) -> Self {
1086 match next_hdr {
1087 NextHeader::NextLayer(n) => n.into(),
1088 NextHeader::Extension(e) => e.into(),
1089 }
1090 }
1091}
1092
1093mod sealed {
1094 use super::*;
1095 pub trait Ipv6HeaderBefore<T> {}
1103
1104 impl<'a, O, T> Ipv6HeaderBefore<T> for &'a O where O: Ipv6HeaderBefore<T> {}
1105
1106 pub trait Ipv6HeaderBuilder {
1108 fn fixed_header(&self) -> &Ipv6PacketBuilder;
1110
1111 fn extension_headers_len(&self) -> usize;
1114
1115 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1120 &self,
1121 buffer: &mut BV,
1122 next_header: NextHeader,
1123 payload_len: usize,
1124 );
1125 }
1126}
1127use sealed::{Ipv6HeaderBefore, Ipv6HeaderBuilder};
1128
1129impl<'a, O> Ipv6HeaderBuilder for &'a O
1130where
1131 O: Ipv6HeaderBuilder,
1132{
1133 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1134 O::fixed_header(self)
1135 }
1136
1137 fn extension_headers_len(&self) -> usize {
1138 O::extension_headers_len(self)
1139 }
1140
1141 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1142 &self,
1143 buffer: &mut BV,
1144 next_header: NextHeader,
1145 payload_len: usize,
1146 ) {
1147 O::serialize_header(self, buffer, next_header, payload_len)
1148 }
1149}
1150
1151macro_rules! impl_packet_builder_base {
1156 {} => {
1157 fn constraints(&self) -> PacketConstraints {
1158 let ext_headers = self.extension_headers_len();
1159 let header_len = IPV6_FIXED_HDR_LEN + ext_headers;
1160 let footer_len = 0;
1161 let min_body_len = 0;
1162 let max_body_len = IPV6_MAX_PAYLOAD_LENGTH - ext_headers;
1165 PacketConstraints::new(header_len, footer_len, min_body_len, max_body_len)
1166 }
1167 }
1168}
1169
1170macro_rules! impl_packet_builder {
1171 {} => {
1172 fn context_state(&self) -> C::ContextState {
1173 C::envelope_to_state(IpEnvelope::new())
1174 }
1175
1176 fn serialize(
1177 &self,
1178 _context: &mut C,
1179 target: &mut SerializeTarget<'_>,
1180 body: FragmentedBytesMut<'_, '_>,
1181 ) {
1182 let mut bv = &mut target.header;
1183 self.serialize_header(
1184 &mut bv,
1185 NextHeader::NextLayer(
1186 <Ipv6PacketBuilder as IpPacketBuilder<C, Ipv6>>::proto(self.fixed_header())
1187 ),
1188 body.len(),
1189 );
1190 }
1191 }
1192}
1193
1194macro_rules! impl_partial_packet_builder {
1195 {} => {
1196 fn partial_serialize(
1197 &self,
1198 _context: &mut C,
1199 body_len: usize,
1200 mut buffer: &mut [u8],
1201 ) {
1202 self.serialize_header(
1203 &mut &mut buffer,
1204 NextHeader::NextLayer(
1205 <Ipv6PacketBuilder as IpPacketBuilder<C, Ipv6>>::proto(self.fixed_header())
1206 ),
1207 body_len,
1208 );
1209 }
1210 }
1211}
1212#[derive(Debug, Clone, Eq, PartialEq)]
1214pub struct Ipv6PacketBuilder {
1215 dscp_and_ecn: DscpAndEcn,
1216 flowlabel: u32,
1217 hop_limit: u8,
1218 proto: Ipv6Proto,
1221 src_ip: Ipv6Addr,
1222 dst_ip: Ipv6Addr,
1223}
1224
1225impl Ipv6PacketBuilder {
1226 pub fn new<S: Into<Ipv6Addr>, D: Into<Ipv6Addr>>(
1232 src_ip: S,
1233 dst_ip: D,
1234 hop_limit: u8,
1235 proto: Ipv6Proto,
1236 ) -> Ipv6PacketBuilder {
1237 Ipv6PacketBuilder {
1238 dscp_and_ecn: DscpAndEcn::default(),
1239 flowlabel: 0,
1240 hop_limit,
1241 proto,
1242 src_ip: src_ip.into(),
1243 dst_ip: dst_ip.into(),
1244 }
1245 }
1246
1247 pub fn dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1250 self.dscp_and_ecn = dscp_and_ecn;
1251 }
1252
1253 pub fn flowlabel(&mut self, flowlabel: u32) {
1259 assert!(flowlabel <= 1 << 20, "invalid flowlabel: {:x}", flowlabel);
1260 self.flowlabel = flowlabel;
1261 }
1262}
1263
1264impl Ipv6HeaderBuilder for Ipv6PacketBuilder {
1265 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1266 self
1267 }
1268
1269 fn extension_headers_len(&self) -> usize {
1270 0
1271 }
1272
1273 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1274 &self,
1275 buffer: &mut BV,
1276 next_header: NextHeader,
1277 payload_len: usize,
1278 ) {
1279 buffer
1280 .write_obj_front(&FixedHeader::new(
1281 self.dscp_and_ecn,
1282 self.flowlabel,
1283 {
1284 debug_assert!(payload_len <= core::u16::MAX as usize);
1291 payload_len as u16
1292 },
1293 next_header.into(),
1294 self.hop_limit,
1295 self.src_ip,
1296 self.dst_ip,
1297 ))
1298 .expect("not enough bytes for IPv6 fixed header");
1299 }
1300}
1301
1302impl NestablePacketBuilder for Ipv6PacketBuilder {
1303 impl_packet_builder_base! {}
1304}
1305
1306impl<C: IpSerializationContext<Ipv6>> PacketBuilder<C> for Ipv6PacketBuilder {
1307 impl_packet_builder! {}
1308}
1309
1310impl<C: IpSerializationContext<Ipv6>> PartialPacketBuilder<C> for Ipv6PacketBuilder {
1311 impl_partial_packet_builder! {}
1312}
1313
1314#[derive(Debug, Clone)]
1316pub struct Ipv6PacketBuilderWithHbhOptions<'a, I> {
1317 prefix_builder: Ipv6PacketBuilder,
1318 hbh_options: AlignedRecordSequenceBuilder<HopByHopOption<'a>, I>,
1319}
1320
1321impl<'a, I> Ipv6PacketBuilderWithHbhOptions<'a, I>
1322where
1323 I: Iterator + Clone,
1324 I::Item: Borrow<HopByHopOption<'a>>,
1325{
1326 pub fn new<T: IntoIterator<Item = I::Item, IntoIter = I>>(
1328 prefix_builder: Ipv6PacketBuilder,
1329 options: T,
1330 ) -> Option<Ipv6PacketBuilderWithHbhOptions<'a, I>> {
1331 let iter = options.into_iter();
1332 if iter
1335 .clone()
1336 .filter(|r| matches!(r.borrow().data, HopByHopOptionData::RouterAlert { .. }))
1337 .count()
1338 > 1
1339 {
1340 return None;
1341 }
1342 let hbh_options = AlignedRecordSequenceBuilder::new(2, iter);
1343 if next_multiple_of_eight(2 + hbh_options.serialized_len()) > IPV6_HBH_OPTIONS_MAX_LEN {
1345 return None;
1346 }
1347 Some(Ipv6PacketBuilderWithHbhOptions { prefix_builder, hbh_options })
1348 }
1349
1350 fn aligned_hbh_len(&self) -> usize {
1351 let opt_len = self.hbh_options.serialized_len();
1352 let hbh_len = opt_len + 2;
1353 next_multiple_of_eight(hbh_len)
1354 }
1355}
1356
1357fn next_multiple_of_eight(x: usize) -> usize {
1358 (x + 7) & (!7)
1359}
1360
1361impl<C: IpSerializationContext<Ipv6>> IpPacketBuilder<C, Ipv6> for Ipv6PacketBuilder {
1362 fn new(src_ip: Ipv6Addr, dst_ip: Ipv6Addr, ttl: u8, proto: Ipv6Proto) -> Self {
1363 Ipv6PacketBuilder::new(src_ip, dst_ip, ttl, proto)
1364 }
1365
1366 fn src_ip(&self) -> Ipv6Addr {
1367 self.src_ip
1368 }
1369
1370 fn set_src_ip(&mut self, addr: Ipv6Addr) {
1371 self.src_ip = addr;
1372 }
1373
1374 fn dst_ip(&self) -> Ipv6Addr {
1375 self.dst_ip
1376 }
1377
1378 fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1379 self.dst_ip = addr;
1380 }
1381
1382 fn proto(&self) -> Ipv6Proto {
1383 self.proto
1384 }
1385
1386 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1387 self.dscp_and_ecn = dscp_and_ecn;
1388 }
1389}
1390
1391impl<'a, I> Ipv6HeaderBuilder for Ipv6PacketBuilderWithHbhOptions<'a, I>
1392where
1393 I: Iterator + Clone,
1394 I::Item: Borrow<HopByHopOption<'a>>,
1395{
1396 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1397 &self.prefix_builder
1398 }
1399
1400 fn extension_headers_len(&self) -> usize {
1401 self.prefix_builder.extension_headers_len() + self.aligned_hbh_len()
1402 }
1403
1404 fn serialize_header<B: SplitByteSliceMut, BV: BufferViewMut<B>>(
1405 &self,
1406 buffer: &mut BV,
1407 next_header: NextHeader,
1408 payload_len: usize,
1409 ) {
1410 let aligned_hbh_len = self.aligned_hbh_len();
1411 self.prefix_builder.serialize_header(
1413 buffer,
1414 NextHeader::Extension(Ipv6ExtHdrType::HopByHopOptions),
1415 payload_len + aligned_hbh_len,
1416 );
1417 let mut hbh_header = buffer.take_front(aligned_hbh_len).unwrap();
1419 let hbh_header = hbh_header.as_mut();
1420 hbh_header[0] = next_header.into();
1421 hbh_header[1] = u8::try_from((aligned_hbh_len - 8) / 8).expect("extension header too big");
1422 self.hbh_options.serialize_into(&mut hbh_header[2..]);
1423 }
1424}
1425
1426impl<'a, I> NestablePacketBuilder for Ipv6PacketBuilderWithHbhOptions<'a, I>
1427where
1428 I: Iterator + Clone,
1429 I::Item: Borrow<HopByHopOption<'a>>,
1430{
1431 impl_packet_builder_base! {}
1432}
1433
1434impl<'a, I, C: IpSerializationContext<Ipv6>> PacketBuilder<C>
1435 for Ipv6PacketBuilderWithHbhOptions<'a, I>
1436where
1437 I: Iterator + Clone,
1438 I::Item: Borrow<HopByHopOption<'a>>,
1439{
1440 impl_packet_builder! {}
1441}
1442
1443impl<'a, I, C: IpSerializationContext<Ipv6>> PartialPacketBuilder<C>
1444 for Ipv6PacketBuilderWithHbhOptions<'a, I>
1445where
1446 I: Iterator + Clone,
1447 I::Item: Borrow<HopByHopOption<'a>>,
1448{
1449 impl_partial_packet_builder! {}
1450}
1451
1452impl<'a, C: IpSerializationContext<Ipv6>, I> IpPacketBuilder<C, Ipv6>
1453 for Ipv6PacketBuilderWithHbhOptions<'a, I>
1454where
1455 I: Iterator<Item: Borrow<HopByHopOption<'a>>> + Debug + Default + Clone,
1456{
1457 fn new(src_ip: Ipv6Addr, dst_ip: Ipv6Addr, ttl: u8, proto: Ipv6Proto) -> Self {
1458 Ipv6PacketBuilderWithHbhOptions::new(
1459 Ipv6PacketBuilder::new(src_ip, dst_ip, ttl, proto),
1460 I::default(),
1461 )
1462 .expect("packet builder with no options should be valid")
1463 }
1464
1465 fn src_ip(&self) -> Ipv6Addr {
1466 self.prefix_builder.src_ip
1467 }
1468
1469 fn set_src_ip(&mut self, addr: Ipv6Addr) {
1470 self.prefix_builder.src_ip = addr;
1471 }
1472
1473 fn dst_ip(&self) -> Ipv6Addr {
1474 self.prefix_builder.dst_ip
1475 }
1476
1477 fn set_dst_ip(&mut self, addr: Ipv6Addr) {
1478 self.prefix_builder.dst_ip = addr;
1479 }
1480
1481 fn proto(&self) -> Ipv6Proto {
1482 self.prefix_builder.proto
1483 }
1484
1485 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1486 <Ipv6PacketBuilder as IpPacketBuilder<C, Ipv6>>::set_dscp_and_ecn(
1487 &mut self.prefix_builder,
1488 dscp_and_ecn,
1489 )
1490 }
1491}
1492
1493#[derive(Debug, Eq, PartialEq)]
1502pub struct Ipv6PacketBuilderWithFragmentHeader<B> {
1503 header_builder: B,
1504 fragment_offset: FragmentOffset,
1505 more_fragments: bool,
1506 identification: u32,
1507}
1508
1509impl<B: Ipv6HeaderBefore<Self>> Ipv6PacketBuilderWithFragmentHeader<B> {
1510 pub fn new(
1512 header_builder: B,
1513 fragment_offset: FragmentOffset,
1514 more_fragments: bool,
1515 identification: u32,
1516 ) -> Self {
1517 Self { header_builder, fragment_offset, more_fragments, identification }
1518 }
1519}
1520
1521impl<B> Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>> for Ipv6PacketBuilder {}
1522impl<B, I> Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>>
1523 for Ipv6PacketBuilderWithHbhOptions<'_, I>
1524{
1525}
1526
1527pub trait Ipv6PacketBuilderBeforeFragment:
1530 Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<Self>> + Ipv6HeaderBuilder + Sized
1531{
1532}
1533impl<B> Ipv6PacketBuilderBeforeFragment for B where
1534 B: Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<Self>> + Ipv6HeaderBuilder + Sized
1535{
1536}
1537
1538impl<B: Ipv6HeaderBuilder> Ipv6HeaderBuilder for Ipv6PacketBuilderWithFragmentHeader<B> {
1539 fn fixed_header(&self) -> &Ipv6PacketBuilder {
1540 self.header_builder.fixed_header()
1541 }
1542
1543 fn extension_headers_len(&self) -> usize {
1544 self.header_builder.extension_headers_len() + IPV6_FRAGMENT_EXT_HDR_LEN
1545 }
1546
1547 fn serialize_header<BB: SplitByteSliceMut, BV: BufferViewMut<BB>>(
1548 &self,
1549 buffer: &mut BV,
1550 next_header: NextHeader,
1551 payload_len: usize,
1552 ) {
1553 let Self { header_builder, fragment_offset, more_fragments, identification } = self;
1554 let payload_len = payload_len + IPV6_FRAGMENT_EXT_HDR_LEN;
1555 header_builder.serialize_header(
1556 buffer,
1557 NextHeader::Extension(Ipv6ExtHdrType::Fragment),
1558 payload_len,
1559 );
1560 buffer.write_obj_front(&u8::from(next_header)).unwrap();
1561 let _: BB = buffer.take_front_zero(1).unwrap();
1563 let more_fragments = u16::from(*more_fragments);
1564 buffer
1565 .write_obj_front(&U16::new(fragment_offset.into_raw() << 3 | more_fragments))
1566 .unwrap();
1567 buffer.write_obj_front(&U32::new(*identification)).unwrap();
1568 }
1569}
1570
1571impl<B: Ipv6HeaderBuilder> NestablePacketBuilder for Ipv6PacketBuilderWithFragmentHeader<B> {
1572 impl_packet_builder_base! {}
1573}
1574
1575impl<B: Ipv6HeaderBuilder, C: IpSerializationContext<Ipv6>> PacketBuilder<C>
1576 for Ipv6PacketBuilderWithFragmentHeader<B>
1577{
1578 impl_packet_builder! {}
1579}
1580
1581impl<B: Ipv6HeaderBuilder, C: IpSerializationContext<Ipv6>> PartialPacketBuilder<C>
1582 for Ipv6PacketBuilderWithFragmentHeader<B>
1583{
1584 impl_partial_packet_builder! {}
1585}
1586
1587pub(crate) fn reassemble_fragmented_packet<
1593 B: SplitByteSliceMut,
1594 BV: BufferViewMut<B>,
1595 I: Iterator<Item = Vec<u8>>,
1596>(
1597 mut buffer: BV,
1598 header: Vec<u8>,
1599 body_fragments: I,
1600) -> IpParseResult<Ipv6, ()> {
1601 assert!(header.len() >= IPV6_FIXED_HDR_LEN);
1602
1603 let bytes = buffer.as_mut();
1604
1605 bytes[0..header.len()].copy_from_slice(&header[..]);
1607 let mut byte_count = header.len();
1608
1609 for p in body_fragments {
1611 bytes[byte_count..byte_count + p.len()].copy_from_slice(&p[..]);
1612 byte_count += p.len();
1613 }
1614
1615 let payload_length = byte_count - IPV6_FIXED_HDR_LEN;
1627
1628 if payload_length > usize::from(core::u16::MAX) {
1631 return debug_err!(
1632 Err(ParseError::Format.into()),
1633 "fragmented packet payload length of {} bytes is too large",
1634 payload_length
1635 );
1636 }
1637
1638 let mut header = Ref::<_, FixedHeader>::from_prefix(bytes).unwrap().0;
1641
1642 header.payload_len.set(u16::try_from(payload_length).unwrap());
1644
1645 Ok(())
1646}
1647
1648#[cfg(test)]
1649mod tests {
1650 use assert_matches::assert_matches;
1651 use packet::{Buf, FragmentedBuffer, NestableSerializer as _, ParseBuffer};
1652 use test_case::test_case;
1653
1654 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1655 use crate::testutil::*;
1656
1657 use super::ext_hdrs::*;
1658 use super::*;
1659
1660 const DEFAULT_SRC_IP: Ipv6Addr =
1661 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1662 const DEFAULT_DST_IP: Ipv6Addr =
1663 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1664
1665 const DEFAULT_V4_SRC_IP: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1666 const DEFAULT_V4_DST_IP: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1667
1668 #[test]
1669 fn test_parse_serialize_full_tcp() {
1670 use crate::testdata::syn_v6::*;
1671
1672 let mut buf = ETHERNET_FRAME.bytes;
1673 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1674 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1675
1676 let mut body = frame.body();
1677 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1678 verify_ipv6_packet(&packet, IPV6_PACKET);
1679
1680 let buffer = packet
1682 .body()
1683 .into_serializer()
1684 .wrap_in(packet.builder())
1685 .wrap_in(frame.builder())
1686 .serialize_vec_outer(&mut NoOpSerializationContext)
1687 .unwrap();
1688 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1689
1690 assert_eq!(&packet.to_vec()[..], IPV6_PACKET.bytes);
1692 }
1693
1694 #[test]
1695 fn test_parse_serialize_full_udp() {
1696 use crate::testdata::dns_request_v6::*;
1697
1698 let mut buf = ETHERNET_FRAME.bytes;
1699 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1700 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1701
1702 let mut body = frame.body();
1703 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1704 verify_ipv6_packet(&packet, IPV6_PACKET);
1705
1706 let buffer = packet
1708 .body()
1709 .into_serializer()
1710 .wrap_in(packet.builder())
1711 .wrap_in(frame.builder())
1712 .serialize_vec_outer(&mut NoOpSerializationContext)
1713 .unwrap();
1714 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1715
1716 assert_eq!(&packet.to_vec()[..], IPV6_PACKET.bytes);
1718 }
1719
1720 #[test]
1721 fn test_parse_serialize_with_extension_headers() {
1722 use crate::testdata::mld_router_report::*;
1725
1726 let mut buf = REPORT;
1727 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1728 assert_eq!(packet.iter_extension_hdrs().count(), 1);
1729
1730 assert_eq!(&packet.to_vec()[..], REPORT);
1735 }
1736
1737 fn fixed_hdr_to_bytes(fixed_hdr: FixedHeader) -> [u8; IPV6_FIXED_HDR_LEN] {
1738 zerocopy::transmute!(fixed_hdr)
1739 }
1740
1741 fn new_fixed_hdr() -> FixedHeader {
1743 FixedHeader::new(
1744 DscpAndEcn::new(0, 2),
1745 0x77,
1746 0,
1747 IpProto::Tcp.into(),
1748 64,
1749 DEFAULT_SRC_IP,
1750 DEFAULT_DST_IP,
1751 )
1752 }
1753
1754 #[test]
1755 fn test_parse() {
1756 let mut buf = &fixed_hdr_to_bytes(new_fixed_hdr())[..];
1757 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1758 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1759 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1760 assert_eq!(packet.flowlabel(), 0x77);
1761 assert_eq!(packet.hop_limit(), 64);
1762 assert_eq!(packet.fixed_hdr.next_hdr, IpProto::Tcp.into());
1763 assert_eq!(packet.proto(), IpProto::Tcp.into());
1764 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1765 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1766 assert_eq!(packet.body(), []);
1767 }
1768
1769 #[test]
1770 fn test_parse_with_ext_hdrs() {
1771 #[rustfmt::skip]
1772 let mut buf = [
1773 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1775 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1776
1777 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,
1792 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1793
1794 IpProto::Tcp.into(), 1, 0, 1, 0, 1, 1, 0, 1, 6, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
1804 ];
1805 let mut fixed_hdr = new_fixed_hdr();
1806 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
1807 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1808 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1809 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1810 let mut buf = &buf[..];
1811 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1812 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1813 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1814 assert_eq!(packet.flowlabel(), 0x77);
1815 assert_eq!(packet.hop_limit(), 64);
1816 assert_eq!(packet.fixed_hdr.next_hdr, Ipv6ExtHdrType::HopByHopOptions.into());
1817 assert_eq!(packet.proto(), IpProto::Tcp.into());
1818 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1819 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1820 assert_eq!(packet.body(), [1, 2, 3, 4, 5]);
1821 let ext_hdrs: Vec<Ipv6ExtensionHeader<'_>> = packet.iter_extension_hdrs().collect();
1822 assert_eq!(ext_hdrs.len(), 2);
1823 assert_eq!(ext_hdrs[0].next_header, Ipv6ExtHdrType::Routing.into());
1825 if let Ipv6ExtensionHeaderData::HopByHopOptions { options } = ext_hdrs[0].data() {
1826 assert_eq!(options.iter().count(), 0);
1828 } else {
1829 panic!("Should have matched HopByHopOptions!");
1830 }
1831
1832 assert_eq!(ext_hdrs[1].next_header, IpProto::Tcp.into());
1837 if let Ipv6ExtensionHeaderData::DestinationOptions { options } = ext_hdrs[1].data() {
1838 assert_eq!(options.iter().count(), 0);
1840 } else {
1841 panic!("Should have matched DestinationOptions!");
1842 }
1843
1844 #[rustfmt::skip]
1846 let mut buf = [
1847 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1849 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1850
1851 Ipv6Proto::NoNextHeader.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
1860 ];
1861 let mut fixed_hdr = new_fixed_hdr();
1862 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
1863 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1864 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1865 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1866 let mut buf = &buf[..];
1867 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
1868 assert_eq!(packet.dscp_and_ecn().dscp(), 0);
1869 assert_eq!(packet.dscp_and_ecn().ecn(), 2);
1870 assert_eq!(packet.flowlabel(), 0x77);
1871 assert_eq!(packet.hop_limit(), 64);
1872 assert_eq!(packet.fixed_hdr.next_hdr, Ipv6ExtHdrType::HopByHopOptions.into());
1873 assert_eq!(packet.proto(), Ipv6Proto::NoNextHeader);
1874 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1875 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1876 assert_eq!(packet.body(), [1, 2, 3, 4, 5]);
1877 let ext_hdrs: Vec<Ipv6ExtensionHeader<'_>> = packet.iter_extension_hdrs().collect();
1878 assert_eq!(ext_hdrs.len(), 1);
1879 assert_eq!(ext_hdrs[0].next_header, Ipv6Proto::NoNextHeader.into());
1881 if let Ipv6ExtensionHeaderData::HopByHopOptions { options } = ext_hdrs[0].data() {
1882 assert_eq!(options.iter().count(), 0);
1884 } else {
1885 panic!("Should have matched HopByHopOptions!");
1886 }
1887 }
1888
1889 #[test]
1890 fn test_parse_error() {
1891 let mut fixed_hdr = new_fixed_hdr();
1893 fixed_hdr.version_tc_flowlabel[0] = 0x50;
1894 assert_eq!(
1895 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1896 ParseError::Format.into()
1897 );
1898
1899 let mut fixed_hdr = new_fixed_hdr();
1901 fixed_hdr.payload_len = U16::new(2);
1902 assert_eq!(
1903 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1904 ParseError::Format.into()
1905 );
1906
1907 let mut fixed_hdr = new_fixed_hdr();
1909 fixed_hdr.next_hdr = 255;
1910 assert_eq!(
1911 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1912 Ipv6ParseError::ParameterProblem {
1913 src_ip: DEFAULT_SRC_IP,
1914 dst_ip: DEFAULT_DST_IP,
1915 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1916 pointer: u32::from(NEXT_HEADER_OFFSET),
1917 must_send_icmp: false,
1918 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1919 }
1920 );
1921
1922 let mut fixed_hdr = new_fixed_hdr();
1924 fixed_hdr.next_hdr = Ipv4Proto::Icmp.into();
1925 assert_eq!(
1926 (&fixed_hdr_to_bytes(fixed_hdr)[..]).parse::<Ipv6Packet<_>>().unwrap_err(),
1927 Ipv6ParseError::ParameterProblem {
1928 src_ip: DEFAULT_SRC_IP,
1929 dst_ip: DEFAULT_DST_IP,
1930 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1931 pointer: u32::from(NEXT_HEADER_OFFSET),
1932 must_send_icmp: false,
1933 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1934 }
1935 );
1936
1937 #[rustfmt::skip]
1939 let mut buf = [
1940 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1942 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1943
1944 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,
1952 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1953
1954 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
1963 ];
1964 let mut fixed_hdr = new_fixed_hdr();
1965 fixed_hdr.next_hdr = Ipv6ExtHdrType::Routing.into();
1966 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
1967 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
1968 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
1969 let mut buf = &buf[..];
1970 assert_eq!(
1971 buf.parse::<Ipv6Packet<_>>().unwrap_err(),
1972 Ipv6ParseError::ParameterProblem {
1973 src_ip: DEFAULT_SRC_IP,
1974 dst_ip: DEFAULT_DST_IP,
1975 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
1976 pointer: IPV6_FIXED_HDR_LEN as u32,
1977 must_send_icmp: false,
1978 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
1979 }
1980 );
1981
1982 #[rustfmt::skip]
1984 let mut buf = [
1985 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1987 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1988
1989 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,
1997 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1998
1999 1, 2, 3, 4, 5,
2001 ];
2002 let mut fixed_hdr = new_fixed_hdr();
2003 fixed_hdr.next_hdr = Ipv6ExtHdrType::Routing.into();
2004 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2005 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2006 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2007 let mut buf = &buf[..];
2008 assert_eq!(
2009 buf.parse::<Ipv6Packet<_>>().unwrap_err(),
2010 Ipv6ParseError::ParameterProblem {
2011 src_ip: DEFAULT_SRC_IP,
2012 dst_ip: DEFAULT_DST_IP,
2013 code: Icmpv6ParameterProblemCode::ErroneousHeaderField,
2014 pointer: (IPV6_FIXED_HDR_LEN as u32) + 2,
2015 must_send_icmp: true,
2016 action: IpParseErrorAction::DiscardPacketSendIcmpNoMulticast,
2017 }
2018 );
2019 }
2020
2021 #[test]
2022 fn test_parse_all_next_header_values() {
2023 let mut buf = [
2029 0x81, 0x13, 0x27, 0xeb, 0x75, 0x92, 0x33, 0x89, 0x01, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
2030 0x03, 0x70, 0x00, 0x22, 0xf7, 0x30, 0x2c, 0x06, 0xfe, 0xc9, 0x00, 0x2d, 0x3b, 0xeb,
2031 0xad, 0x3e, 0x5c, 0x41, 0xc8, 0x70, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x11, 0x00,
2032 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x4f, 0x4f, 0x6f, 0x4f, 0x4f, 0x4f, 0x4f,
2033 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x19, 0x19,
2034 0x19, 0x19, 0x19, 0x4f, 0x4f, 0x4f, 0x4f, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2035 0x00, 0x4f, 0x4f, 0x5a, 0x5a, 0x5a, 0xc9, 0x5a, 0x46, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
2036 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0xe4, 0x5a, 0x5a, 0x5a, 0x5a,
2037 ];
2038
2039 assert_matches!(
2042 (&buf[..]).parse::<Ipv6Packet<_>>(),
2043 Err(Ipv6ParseError::ParameterProblem {
2044 src_ip: _,
2045 dst_ip: _,
2046 code: Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2047 pointer: 0,
2048 must_send_icmp: false,
2049 action: IpParseErrorAction::DiscardPacket,
2050 })
2051 );
2052
2053 for b in 0u8..=255 {
2056 buf[6] = b;
2058 let _: Result<_, _> = (&buf[..]).parse::<Ipv6Packet<_>>();
2059 }
2060 }
2061
2062 #[test]
2063 fn test_partial_parse() {
2064 use core::convert::TryInto as _;
2065 use core::ops::Deref as _;
2066
2067 #[rustfmt::skip]
2069 let mut buf = [
2070 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2072 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2073
2074 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2083 ];
2084 let len = buf.len() - IPV6_FIXED_HDR_LEN;
2085 let len = len.try_into().unwrap();
2086 let make_fixed_hdr = || {
2087 let mut fixed_hdr = new_fixed_hdr();
2088 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2089 fixed_hdr.payload_len = U16::new(len);
2090 fixed_hdr
2091 };
2092 const MALFORMED_BYTE: u8 = 10;
2094 buf[IPV6_FIXED_HDR_LEN + 1] = MALFORMED_BYTE;
2095 let fixed_hdr = fixed_hdr_to_bytes(make_fixed_hdr());
2096 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr);
2097 let mut buf = &buf[..];
2098 let partial = buf.parse::<Ipv6PacketRaw<_>>().unwrap();
2099 let Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto } = &partial;
2100 assert_eq!(fixed_hdr.deref(), &make_fixed_hdr());
2101 assert_eq!(
2102 *extension_hdrs.as_ref().incomplete().unwrap(),
2103 [IpProto::Tcp.into(), MALFORMED_BYTE]
2104 );
2105 assert_eq!(body_proto, &Err(ExtHdrParseError));
2106 assert!(Ipv6Packet::try_from_raw(partial).is_err());
2107
2108 let mut buf = [
2110 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,
2112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
2114 ];
2115 let make_fixed_hdr = || {
2116 let mut fixed_hdr = new_fixed_hdr();
2117 fixed_hdr.next_hdr = IpProto::Tcp.into();
2118 fixed_hdr.payload_len = U16::new(10);
2119 fixed_hdr
2120 };
2121 let fixed_hdr = fixed_hdr_to_bytes(make_fixed_hdr());
2122 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr);
2123 let mut parsebuff = &buf[..];
2124 let partial = parsebuff.parse::<Ipv6PacketRaw<_>>().unwrap();
2125 let Ipv6PacketRaw { fixed_hdr, extension_hdrs, body_proto } = &partial;
2126 assert_eq!(fixed_hdr.deref(), &make_fixed_hdr());
2127 assert_eq!(extension_hdrs.as_ref().complete().unwrap().deref(), []);
2128 let (body, proto) = body_proto.unwrap();
2129 assert_eq!(body.incomplete().unwrap(), &buf[IPV6_FIXED_HDR_LEN..]);
2130 assert_eq!(proto, IpProto::Tcp.into());
2131 assert!(Ipv6Packet::try_from_raw(partial).is_err());
2132 }
2133
2134 fn new_builder() -> Ipv6PacketBuilder {
2136 Ipv6PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, 64, IpProto::Tcp.into())
2137 }
2138
2139 #[test]
2140 fn test_serialize() {
2141 let mut builder = new_builder();
2142 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
2143 builder.flowlabel(0x10405);
2144 let mut buf = (&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2145 .into_serializer()
2146 .wrap_in(builder)
2147 .serialize_vec_outer(&mut NoOpSerializationContext)
2148 .unwrap();
2149 assert_eq!(
2151 buf.as_ref(),
2152 &[
2153 100, 177, 4, 5, 0, 10, 6, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
2154 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, 1, 2, 3, 4,
2155 5, 6, 7, 8, 9
2156 ][..],
2157 );
2158
2159 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2160 assert_eq!(packet.dscp_and_ecn().dscp(), 0x12);
2163 assert_eq!(packet.dscp_and_ecn().ecn(), 3);
2164 assert_eq!(packet.flowlabel(), 0x10405);
2165 }
2166
2167 #[test]
2168 fn test_partial_serialize() {
2169 let mut builder = new_builder();
2170 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
2171 builder.flowlabel(0x10405);
2172 let body = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2173 let packet = (&body).into_serializer().wrap_in(builder);
2174
2175 const HEADER_LEN: usize = 40;
2178 const HEADER: [u8; HEADER_LEN] = [
2179 100, 177, 4, 5, 0, 10, 6, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
2180 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
2181 ];
2182 let mut expected_partial = HEADER.to_vec();
2183 expected_partial.resize(expected_partial.len() + body.len(), 0);
2184
2185 for i in 1..expected_partial.len() {
2186 let mut buf = vec![0u8; i];
2187 let result = packet.partial_serialize(
2188 &mut NoOpSerializationContext,
2189 PacketConstraints::UNCONSTRAINED,
2190 buf.as_mut_slice(),
2191 );
2192
2193 let bytes_written = if i >= HEADER_LEN { HEADER_LEN } else { 0 };
2196 assert_eq!(
2197 result,
2198 Ok(PartialSerializeResult { bytes_written, total_size: body.len() + HEADER_LEN })
2199 );
2200 if bytes_written > 0 {
2201 assert_eq!(buf, expected_partial[..i]);
2202 }
2203 }
2204 }
2205
2206 #[test]
2207 fn test_serialize_zeroes() {
2208 let mut buf_0 = [0; IPV6_FIXED_HDR_LEN];
2211 let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], IPV6_FIXED_HDR_LEN..)
2212 .wrap_in(new_builder())
2213 .serialize_vec_outer(&mut NoOpSerializationContext)
2214 .unwrap()
2215 .unwrap_a();
2216 let mut buf_1 = [0xFF; IPV6_FIXED_HDR_LEN];
2217 let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], IPV6_FIXED_HDR_LEN..)
2218 .wrap_in(new_builder())
2219 .serialize_vec_outer(&mut NoOpSerializationContext)
2220 .unwrap()
2221 .unwrap_a();
2222 assert_eq!(&buf_0[..], &buf_1[..]);
2223 }
2224
2225 #[test]
2226 fn test_packet_builder_proto_not_next_header() {
2227 let mut buf = (&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2231 .into_serializer()
2232 .wrap_in(
2233 Ipv6PacketBuilderWithHbhOptions::new(
2234 new_builder(),
2235 &[HopByHopOption {
2236 action: ExtensionHeaderOptionAction::SkipAndContinue,
2237 mutable: false,
2238 data: HopByHopOptionData::RouterAlert { data: 0 },
2239 }],
2240 )
2241 .unwrap(),
2242 )
2243 .serialize_vec_outer(&mut NoOpSerializationContext)
2244 .unwrap();
2245 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2246 assert_eq!(packet.proto(), IpProto::Tcp.into());
2247 assert_eq!(packet.next_header(), Ipv6ExtHdrType::HopByHopOptions.into());
2248 }
2249
2250 #[test]
2251 #[should_panic(expected = "SizeLimitExceeded, Nested { inner: Buf { buf:")]
2252 fn test_serialize_panic_packet_length() {
2253 let _: Buf<&mut [u8]> = Buf::new(&mut [0; 1 << 16][..], ..)
2256 .wrap_in(new_builder())
2257 .serialize_vec_outer(&mut NoOpSerializationContext)
2258 .unwrap()
2259 .unwrap_a();
2260 }
2261
2262 #[test]
2263 #[should_panic(expected = "packet must have at least one extension header")]
2264 fn test_copy_header_bytes_for_fragment_without_ext_hdrs() {
2265 let mut buf = &fixed_hdr_to_bytes(new_fixed_hdr())[..];
2266 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2267 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2268 }
2269
2270 #[test]
2271 #[should_panic(expected = "exhausted all extension headers without finding fragment header")]
2272 fn test_copy_header_bytes_for_fragment_with_1_ext_hdr_no_fragment() {
2273 #[rustfmt::skip]
2274 let mut buf = [
2275 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2277 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2278
2279 IpProto::Tcp.into(), 0, 0, 1, 0, 1, 1, 0, 1, 2, 3, 4, 5,
2288 ];
2289 let mut fixed_hdr = new_fixed_hdr();
2290 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2291 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2292 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2293 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2294 let mut buf = &buf[..];
2295 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2296 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2297 }
2298
2299 #[test]
2300 #[should_panic(expected = "exhausted all extension headers without finding fragment header")]
2301 fn test_copy_header_bytes_for_fragment_with_2_ext_hdr_no_fragment() {
2302 #[rustfmt::skip]
2303 let mut buf = [
2304 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2306 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2307
2308 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,
2325 ];
2326 let mut fixed_hdr = new_fixed_hdr();
2327 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2328 fixed_hdr.payload_len = U16::new((buf.len() - IPV6_FIXED_HDR_LEN) as u16);
2329 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2330 buf[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2331 let mut buf = &buf[..];
2332 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2333 let _: Vec<_> = packet.copy_header_bytes_for_fragment();
2334 }
2335
2336 #[test]
2337 fn test_copy_header_bytes_for_fragment() {
2338 #[rustfmt::skip]
2343 let mut bytes = [
2344 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2346 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2347
2348 IpProto::Tcp.into(), 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5,
2356 ];
2357 let mut fixed_hdr = new_fixed_hdr();
2358 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2359 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2360 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2361 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2362 let mut buf = &bytes[..];
2363 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2364 let copied_bytes = packet.copy_header_bytes_for_fragment();
2365 bytes[6] = IpProto::Tcp.into();
2366 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN]);
2367
2368 #[rustfmt::skip]
2373 let mut bytes = [
2374 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2376 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2377
2378 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,
2393 ];
2394 let mut fixed_hdr = new_fixed_hdr();
2395 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2396 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2397 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2398 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2399 let mut buf = &bytes[..];
2400 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2401 let copied_bytes = packet.copy_header_bytes_for_fragment();
2402 bytes[IPV6_FIXED_HDR_LEN] = IpProto::Tcp.into();
2403 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN + 8]);
2404
2405 #[rustfmt::skip]
2410 let mut bytes = [
2411 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2413 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2414
2415 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,
2438 ];
2439 let mut fixed_hdr = new_fixed_hdr();
2440 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2441 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2442 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2443 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2444 let mut buf = &bytes[..];
2445 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2446 let copied_bytes = packet.copy_header_bytes_for_fragment();
2447 bytes[IPV6_FIXED_HDR_LEN + 8] = IpProto::Tcp.into();
2448 assert_eq!(&copied_bytes[..], &bytes[..IPV6_FIXED_HDR_LEN + 24]);
2449
2450 #[rustfmt::skip]
2455 let mut bytes = [
2456 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2458 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2459
2460 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,
2476 ];
2477 let mut fixed_hdr = new_fixed_hdr();
2478 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2479 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2480 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2481 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2482 let mut buf = &bytes[..];
2483 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2484 let copied_bytes = packet.copy_header_bytes_for_fragment();
2485 let mut expected_bytes = Vec::new();
2486 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2487 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2488 expected_bytes[6] = Ipv6ExtHdrType::DestinationOptions.into();
2489 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2490
2491 #[rustfmt::skip]
2496 let mut bytes = [
2497 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2499 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2500
2501 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,
2523 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2524
2525 1, 2, 3, 4, 5,
2527 ];
2528 let mut fixed_hdr = new_fixed_hdr();
2529 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2530 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2531 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2532 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2533 let mut buf = &bytes[..];
2534 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2535 let copied_bytes = packet.copy_header_bytes_for_fragment();
2536 let mut expected_bytes = Vec::new();
2537 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2538 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2539 expected_bytes[6] = Ipv6ExtHdrType::DestinationOptions.into();
2540 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2541
2542 #[rustfmt::skip]
2547 let mut bytes = [
2548 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2550 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2551
2552 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,
2575 ];
2576 let mut fixed_hdr = new_fixed_hdr();
2577 fixed_hdr.next_hdr = Ipv6ExtHdrType::HopByHopOptions.into();
2578 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2579 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2580 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2581 let mut buf = &bytes[..];
2582 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2583 let copied_bytes = packet.copy_header_bytes_for_fragment();
2584 let mut expected_bytes = Vec::new();
2585 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN + 8]);
2586 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 16..bytes.len() - 5]);
2587 expected_bytes[IPV6_FIXED_HDR_LEN] = Ipv6ExtHdrType::DestinationOptions.into();
2588 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2589
2590 #[rustfmt::skip]
2595 let mut bytes = [
2596 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2598 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2599
2600 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,
2614 ];
2615 let mut fixed_hdr = new_fixed_hdr();
2616 fixed_hdr.next_hdr = Ipv6ExtHdrType::Fragment.into();
2617 fixed_hdr.payload_len = U16::new((bytes.len() - IPV6_FIXED_HDR_LEN) as u16);
2618 let fixed_hdr_buf = fixed_hdr_to_bytes(fixed_hdr);
2619 bytes[..IPV6_FIXED_HDR_LEN].copy_from_slice(&fixed_hdr_buf);
2620 let mut buf = &bytes[..];
2621 let packet = buf.parse::<Ipv6Packet<_>>().unwrap();
2622 let copied_bytes = packet.copy_header_bytes_for_fragment();
2623 let mut expected_bytes = Vec::new();
2624 expected_bytes.extend_from_slice(&bytes[..IPV6_FIXED_HDR_LEN]);
2625 expected_bytes.extend_from_slice(&bytes[IPV6_FIXED_HDR_LEN + 8..bytes.len() - 5]);
2626 assert_eq!(&copied_bytes[..], &expected_bytes[..]);
2627 }
2628
2629 #[test]
2630 fn test_next_multiple_of_eight() {
2631 for x in 0usize..=IPV6_HBH_OPTIONS_MAX_LEN {
2632 let y = next_multiple_of_eight(x);
2633 assert_eq!(y % 8, 0);
2634 assert!(y >= x);
2635 if x % 8 == 0 {
2636 assert_eq!(x, y);
2637 } else {
2638 assert_eq!(x + (8 - x % 8), y);
2639 }
2640 }
2641 }
2642
2643 fn create_ipv4_and_ipv6_builders(
2644 proto_v4: Ipv4Proto,
2645 proto_v6: Ipv6Proto,
2646 ) -> (Ipv4PacketBuilder, Ipv6PacketBuilder) {
2647 const IP_DSCP_AND_ECN: DscpAndEcn = DscpAndEcn::new(0x12, 3);
2648 const IP_TTL: u8 = 64;
2649
2650 let mut ipv4_builder =
2651 Ipv4PacketBuilder::new(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP, IP_TTL, proto_v4);
2652 ipv4_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
2653 ipv4_builder.df_flag(false);
2654 ipv4_builder.mf_flag(false);
2655 ipv4_builder.fragment_offset(FragmentOffset::ZERO);
2656
2657 let mut ipv6_builder =
2658 Ipv6PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, IP_TTL, proto_v6);
2659 ipv6_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
2660 ipv6_builder.flowlabel(0x456);
2661
2662 (ipv4_builder, ipv6_builder)
2663 }
2664
2665 fn create_tcp_ipv4_and_ipv6_pkt()
2666 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
2667 use crate::tcp::TcpSegmentBuilder;
2668 use core::num::NonZeroU16;
2669
2670 let tcp_src_port: NonZeroU16 = NonZeroU16::new(20).unwrap();
2671 let tcp_dst_port: NonZeroU16 = NonZeroU16::new(30).unwrap();
2672 const TCP_SEQ_NUM: u32 = 4321;
2673 const TCP_ACK_NUM: Option<u32> = Some(1234);
2674 const TCP_WINDOW_SIZE: u16 = 12345;
2675 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2676
2677 let (ipv4_builder, ipv6_builder) =
2678 create_ipv4_and_ipv6_builders(IpProto::Tcp.into(), IpProto::Tcp.into());
2679
2680 let tcp_builder = TcpSegmentBuilder::new(
2681 DEFAULT_V4_SRC_IP,
2682 DEFAULT_V4_DST_IP,
2683 tcp_src_port,
2684 tcp_dst_port,
2685 TCP_SEQ_NUM,
2686 TCP_ACK_NUM,
2687 TCP_WINDOW_SIZE,
2688 );
2689
2690 let v4_pkt_buf = (&PAYLOAD)
2691 .into_serializer()
2692 .wrap_in(tcp_builder)
2693 .wrap_in(ipv4_builder)
2694 .serialize_vec_outer(&mut NoOpSerializationContext)
2695 .expect("Failed to serialize to v4_pkt_buf");
2696
2697 let v6_tcp_builder = TcpSegmentBuilder::new(
2698 DEFAULT_SRC_IP,
2699 DEFAULT_DST_IP,
2700 tcp_src_port,
2701 tcp_dst_port,
2702 TCP_SEQ_NUM,
2703 TCP_ACK_NUM,
2704 TCP_WINDOW_SIZE,
2705 );
2706
2707 let v6_pkt_buf = (&PAYLOAD)
2708 .into_serializer()
2709 .wrap_in(v6_tcp_builder)
2710 .wrap_in(ipv6_builder)
2711 .serialize_vec_outer(&mut NoOpSerializationContext)
2712 .expect("Failed to serialize to v4_pkt_buf");
2713
2714 (v4_pkt_buf, v6_pkt_buf)
2715 }
2716
2717 #[test]
2718 fn test_nat64_translate_tcp() {
2719 let (expected_v4_pkt_buf, mut v6_pkt_buf) = create_tcp_ipv4_and_ipv6_pkt();
2720
2721 let parsed_v6_packet =
2722 v6_pkt_buf.parse::<Ipv6Packet<_>>().expect("Failed to parse v6_pkt_buf");
2723 let nat64_translation_result =
2724 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2725
2726 let serializable_pkt =
2727 assert_matches!(nat64_translation_result, Nat64TranslationResult::Forward(s) => s);
2728
2729 let translated_v4_pkt_buf = serializable_pkt
2730 .serialize_vec_outer(&mut NoOpSerializationContext)
2731 .expect("Failed to serialize to translated_v4_pkt_buf");
2732
2733 assert_eq!(
2734 expected_v4_pkt_buf.to_flattened_vec(),
2735 translated_v4_pkt_buf.to_flattened_vec()
2736 );
2737 }
2738
2739 fn create_udp_ipv4_and_ipv6_pkt()
2740 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
2741 use crate::udp::UdpPacketBuilder;
2742 use core::num::NonZeroU16;
2743
2744 let udp_src_port: NonZeroU16 = NonZeroU16::new(35000).unwrap();
2745 let udp_dst_port: NonZeroU16 = NonZeroU16::new(53).unwrap();
2746 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2747
2748 let (ipv4_builder, ipv6_builder) =
2749 create_ipv4_and_ipv6_builders(IpProto::Udp.into(), IpProto::Udp.into());
2750
2751 let v4_udp_builder = UdpPacketBuilder::new(
2752 DEFAULT_V4_SRC_IP,
2753 DEFAULT_V4_DST_IP,
2754 Some(udp_src_port),
2755 udp_dst_port,
2756 );
2757
2758 let v4_pkt_buf = (&PAYLOAD)
2759 .into_serializer()
2760 .wrap_in(v4_udp_builder)
2761 .wrap_in(ipv4_builder)
2762 .serialize_vec_outer(&mut NoOpSerializationContext)
2763 .expect("Unable to serialize to v4_pkt_buf");
2764
2765 let v6_udp_builder =
2766 UdpPacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, Some(udp_src_port), udp_dst_port);
2767
2768 let v6_pkt_buf = (&PAYLOAD)
2769 .into_serializer()
2770 .wrap_in(v6_udp_builder)
2771 .wrap_in(ipv6_builder)
2772 .serialize_vec_outer(&mut NoOpSerializationContext)
2773 .expect("Unable to serialize to v6_pkt_buf");
2774
2775 (v4_pkt_buf, v6_pkt_buf)
2776 }
2777
2778 #[test]
2779 fn test_nat64_translate_udp() {
2780 let (expected_v4_pkt_buf, mut v6_pkt_buf) = create_udp_ipv4_and_ipv6_pkt();
2781
2782 let parsed_v6_packet =
2783 v6_pkt_buf.parse::<Ipv6Packet<_>>().expect("Unable to parse Ipv6Packet");
2784 let nat64_translation_result =
2785 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2786
2787 let serializable_pkt = assert_matches!(nat64_translation_result,
2788 Nat64TranslationResult::Forward(s) => s);
2789
2790 let translated_v4_pkt_buf = serializable_pkt
2791 .serialize_vec_outer(&mut NoOpSerializationContext)
2792 .expect("Unable to serialize to translated_v4_pkt_buf");
2793
2794 assert_eq!(
2795 expected_v4_pkt_buf.to_flattened_vec(),
2796 translated_v4_pkt_buf.to_flattened_vec()
2797 );
2798 }
2799
2800 #[test]
2801 fn test_nat64_translate_non_tcp_udp_icmp() {
2802 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2803
2804 let (ipv4_builder, ipv6_builder) =
2805 create_ipv4_and_ipv6_builders(Ipv4Proto::Other(59), Ipv6Proto::Other(59));
2806
2807 let expected_v4_pkt_buf = (&PAYLOAD)
2808 .into_serializer()
2809 .wrap_in(ipv4_builder)
2810 .serialize_vec_outer(&mut NoOpSerializationContext)
2811 .expect("Unable to serialize to expected_v4_pkt_buf");
2812
2813 let mut v6_pkt_buf = (&PAYLOAD)
2814 .into_serializer()
2815 .wrap_in(ipv6_builder)
2816 .serialize_vec_outer(&mut NoOpSerializationContext)
2817 .expect("Unable to serialize to v6_pkt_buf");
2818
2819 let translated_v4_pkt_buf = {
2820 let parsed_v6_packet = v6_pkt_buf
2821 .parse::<Ipv6Packet<_>>()
2822 .expect("Unable to serialize to translated_v4_pkt_buf");
2823
2824 let nat64_translation_result =
2825 parsed_v6_packet.nat64_translate(DEFAULT_V4_SRC_IP, DEFAULT_V4_DST_IP);
2826
2827 let serializable_pkt = assert_matches!(nat64_translation_result,
2828 Nat64TranslationResult::Forward(s) => s);
2829
2830 let translated_buf = serializable_pkt
2831 .serialize_vec_outer(&mut NoOpSerializationContext)
2832 .expect("Unable to serialize to translated_buf");
2833
2834 translated_buf
2835 };
2836
2837 assert_eq!(
2838 expected_v4_pkt_buf.to_flattened_vec(),
2839 translated_v4_pkt_buf.to_flattened_vec()
2840 );
2841 }
2842
2843 #[test_case(new_builder(), true; "fixed header more frags")]
2844 #[test_case(Ipv6PacketBuilderWithHbhOptions::new(
2845 new_builder(),
2846 &[HopByHopOption {
2847 action: ExtensionHeaderOptionAction::SkipAndContinue,
2848 mutable: false,
2849 data: HopByHopOptionData::RouterAlert { data: 0 },
2850 }]).unwrap(), false; "hbh last frag")]
2851 fn ipv6_packet_builder_with_fragment_header<
2852 B: Ipv6HeaderBuilder + Ipv6HeaderBefore<Ipv6PacketBuilderWithFragmentHeader<B>> + Debug,
2853 >(
2854 inner: B,
2855 more_fragments: bool,
2856 ) {
2857 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
2858 let fragment_offset = FragmentOffset::new(13).unwrap();
2859 let identification = 0xABCDABCD;
2860 let builder = Ipv6PacketBuilderWithFragmentHeader::new(
2861 inner,
2862 fragment_offset,
2863 more_fragments,
2864 identification,
2865 );
2866 let mut serialized = builder
2867 .wrap_body(PAYLOAD.into_serializer())
2868 .serialize_vec_outer(&mut NoOpSerializationContext)
2869 .unwrap()
2870 .unwrap_b();
2871 let packet = serialized.parse::<Ipv6Packet<_>>().unwrap();
2872 assert!(packet.fragment_header_present());
2873 assert_eq!(packet.proto(), Ipv6Proto::Proto(IpProto::Tcp));
2874 let fragment_data = packet
2875 .extension_hdrs
2876 .into_iter()
2877 .find_map(|ext_hdr| match ext_hdr.into_data() {
2878 Ipv6ExtensionHeaderData::Fragment { fragment_data } => Some(fragment_data),
2879 _ => None,
2880 })
2881 .unwrap();
2882 assert_eq!(fragment_data.fragment_offset(), fragment_offset);
2883 assert_eq!(fragment_data.identification(), identification);
2884 assert_eq!(fragment_data.m_flag(), more_fragments);
2885 }
2886
2887 #[test]
2890 fn extension_headers_take_from_max_body_size() {
2891 let builder = new_builder();
2892 assert_eq!(builder.constraints().max_body_len(), IPV6_MAX_PAYLOAD_LENGTH);
2893 let builder =
2894 Ipv6PacketBuilderWithFragmentHeader::new(builder, FragmentOffset::ZERO, false, 1234);
2895 assert_eq!(
2896 builder.constraints().max_body_len(),
2897 IPV6_MAX_PAYLOAD_LENGTH - IPV6_FRAGMENT_EXT_HDR_LEN
2898 );
2899 }
2900
2901 #[test]
2902 fn test_partial_serialize_parsed() {
2903 let packet_bytes = [
2904 100, 177, 4, 5, 0, 10, 6, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
2905 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, 1, 2, 3, 4, 5, 6, 7,
2906 8, 9,
2907 ];
2908 let packet_len = packet_bytes.len();
2909 let mut packet_bytes_copy = packet_bytes;
2910 let mut packet_bytes_ref: &mut [u8] = &mut packet_bytes_copy[..];
2911 let packet = packet_bytes_ref.parse::<Ipv6Packet<_>>().unwrap();
2912
2913 for i in 1..(packet_len + 1) {
2914 let mut buf = vec![0u8; i];
2915 let result = packet.partial_serialize(
2916 &mut NoOpSerializationContext,
2917 PacketConstraints::UNCONSTRAINED,
2918 buf.as_mut_slice(),
2919 );
2920
2921 let bytes_written = if i >= packet_len { packet_len } else { i };
2922 assert_eq!(
2923 result,
2924 Ok(PartialSerializeResult { bytes_written, total_size: packet_len })
2925 );
2926 assert_eq!(buf[..bytes_written], packet_bytes[..bytes_written]);
2927 }
2928 }
2929}