1use alloc::vec::Vec;
12use core::borrow::Borrow;
13use core::fmt::{self, Debug, Formatter};
14use core::ops::Range;
15
16use internet_checksum::Checksum;
17use log::debug;
18use net_types::ip::{GenericOverIp, IpAddress, Ipv4, Ipv4Addr, Ipv4SourceAddr, Ipv6Addr};
19use packet::records::RecordsIter;
20use packet::records::options::{OptionSequenceBuilder, OptionsRaw};
21use packet::{
22 BufferProvider, BufferView, BufferViewMut, EmptyBuf, FragmentedBytesMut, FromRaw,
23 GrowBufferMut, InnerPacketBuilder, LayoutBufferAlloc, MaybeParsed, NestablePacketBuilder,
24 NestableSerializer, NoOpSerializationContext, PacketBuilder, PacketConstraints, ParsablePacket,
25 ParseMetadata, PartialPacketBuilder, PartialSerializer, SerializeError, SerializeTarget,
26 Serializer,
27};
28use zerocopy::byteorder::network_endian::U16;
29use zerocopy::{
30 FromBytes, Immutable, IntoBytes, KnownLayout, Ref, SplitByteSlice, SplitByteSliceMut, Unaligned,
31};
32
33use crate::TRANSPORT_HEADER_MAX_SIZE;
34use crate::error::ParseError;
35use crate::ip::{
36 DscpAndEcn, FragmentOffset, IpEnvelope, IpExt, IpPacketBuilder, IpProto,
37 IpSerializationContext, Ipv4Proto, Ipv6Proto, Nat64Error, Nat64TranslationResult,
38};
39use crate::ipv6::Ipv6PacketBuilder;
40use crate::tcp::{TcpParseArgs, TcpSegment};
41use crate::udp::{UdpPacket, UdpParseArgs};
42
43pub(crate) use self::inner::IPV4_MIN_HDR_LEN;
44use self::options::{Ipv4Option, Ipv4OptionsImpl};
45
46pub const HDR_PREFIX_LEN: usize = 20;
48
49pub const MAX_HDR_LEN: usize = 60;
51
52pub const MAX_OPTIONS_LEN: usize = MAX_HDR_LEN - HDR_PREFIX_LEN;
54
55const IPV4_FRAGMENT_DATA_BYTE_RANGE: Range<usize> = 4..8;
57
58#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
60#[allow(missing_docs)]
61pub enum Ipv4FragmentType {
62 InitialFragment,
63 NonInitialFragment,
64}
65
66#[derive(KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned)]
69#[repr(C)]
70pub struct HeaderPrefix {
71 version_ihl: u8,
72 dscp_and_ecn: DscpAndEcn,
73 total_len: U16,
74 id: U16,
75 flags_frag_off: [u8; 2],
76 ttl: u8,
77 proto: u8,
78 hdr_checksum: [u8; 2],
79 src_ip: Ipv4Addr,
80 dst_ip: Ipv4Addr,
81}
82
83const IP_VERSION: u8 = 4;
84const VERSION_OFFSET: u8 = 4;
85const IHL_MASK: u8 = 0xF;
86const IHL_MAX: u8 = (1 << VERSION_OFFSET) - 1;
87const FLAGS_OFFSET: u8 = 13;
88const FLAGS_MAX: u8 = (1 << (16 - FLAGS_OFFSET)) - 1;
89const FRAG_OFF_MAX: u16 = (1 << FLAGS_OFFSET) - 1;
90
91impl HeaderPrefix {
92 #[allow(clippy::too_many_arguments)]
93 fn new(
94 ihl: u8,
95 dscp_and_ecn: DscpAndEcn,
96 total_len: u16,
97 id: u16,
98 flags: u8,
99 frag_off: u16,
100 ttl: u8,
101 proto: u8,
102 hdr_checksum: [u8; 2],
103 src_ip: Ipv4Addr,
104 dst_ip: Ipv4Addr,
105 ) -> HeaderPrefix {
106 debug_assert!(ihl <= IHL_MAX);
107 debug_assert!(flags <= FLAGS_MAX);
108 debug_assert!(frag_off <= FRAG_OFF_MAX);
109
110 HeaderPrefix {
111 version_ihl: (IP_VERSION << VERSION_OFFSET) | ihl,
112 dscp_and_ecn,
113 total_len: U16::new(total_len),
114 id: U16::new(id),
115 flags_frag_off: ((u16::from(flags) << FLAGS_OFFSET) | frag_off).to_be_bytes(),
116 ttl,
117 proto,
118 src_ip,
119 dst_ip,
120 hdr_checksum,
121 }
122 }
123
124 fn version(&self) -> u8 {
125 self.version_ihl >> VERSION_OFFSET
126 }
127
128 pub(crate) fn ihl(&self) -> u8 {
130 self.version_ihl & IHL_MASK
131 }
132
133 pub(crate) fn mf_flag(&self) -> bool {
135 self.flags_frag_off[0] & (1 << ((FLAGS_OFFSET - 8) + MF_FLAG_OFFSET)) > 0
140 }
141}
142
143pub trait Ipv4Header {
148 fn get_header_prefix(&self) -> &HeaderPrefix;
150
151 fn dscp_and_ecn(&self) -> DscpAndEcn {
153 self.get_header_prefix().dscp_and_ecn
154 }
155
156 fn id(&self) -> u16 {
158 self.get_header_prefix().id.get()
159 }
160
161 fn df_flag(&self) -> bool {
163 self.get_header_prefix().flags_frag_off[0] & (1 << (5 + DF_FLAG_OFFSET)) > 0
165 }
166
167 fn mf_flag(&self) -> bool {
169 self.get_header_prefix().mf_flag()
170 }
171
172 fn fragment_offset(&self) -> FragmentOffset {
174 FragmentOffset::new_with_lsb(U16::from_bytes(self.get_header_prefix().flags_frag_off).get())
175 }
176
177 fn fragment_type(&self) -> Ipv4FragmentType {
183 match self.fragment_offset().into_raw() {
184 0 => Ipv4FragmentType::InitialFragment,
185 _ => Ipv4FragmentType::NonInitialFragment,
186 }
187 }
188
189 fn ttl(&self) -> u8 {
191 self.get_header_prefix().ttl
192 }
193
194 fn proto(&self) -> Ipv4Proto {
198 Ipv4Proto::from(self.get_header_prefix().proto)
199 }
200
201 fn src_ip(&self) -> Ipv4Addr {
203 self.get_header_prefix().src_ip
204 }
205
206 fn dst_ip(&self) -> Ipv4Addr {
208 self.get_header_prefix().dst_ip
209 }
210
211 fn builder(&self) -> Ipv4PacketBuilder {
213 let mut s = Ipv4PacketBuilder {
214 id: self.id(),
215 dscp_and_ecn: self.dscp_and_ecn(),
216 flags: 0,
217 frag_off: self.fragment_offset().into_raw(),
218 ttl: self.ttl(),
219 proto: self.get_header_prefix().proto.into(),
220 src_ip: self.src_ip(),
221 dst_ip: self.dst_ip(),
222 };
223 s.df_flag(self.df_flag());
224 s.mf_flag(self.mf_flag());
225 s
226 }
227}
228
229impl Ipv4Header for HeaderPrefix {
230 fn get_header_prefix(&self) -> &HeaderPrefix {
231 self
232 }
233}
234
235pub struct Ipv4Packet<B> {
245 hdr_prefix: Ref<B, HeaderPrefix>,
246 options: Options<B>,
247 body: B,
248}
249
250impl<B: SplitByteSlice, I: IpExt> GenericOverIp<I> for Ipv4Packet<B> {
251 type Type = <I as IpExt>::Packet<B>;
252}
253
254impl<B: SplitByteSlice> Ipv4Header for Ipv4Packet<B> {
255 fn get_header_prefix(&self) -> &HeaderPrefix {
256 &self.hdr_prefix
257 }
258}
259
260impl<B: SplitByteSlice, C: IpSerializationContext<Ipv4>> PartialSerializer<C> for Ipv4Packet<B> {
261 fn partial_serialize_new_buf<BB: GrowBufferMut, A: LayoutBufferAlloc<BB>>(
266 &self,
267 _context: &mut C,
268 constraints: PacketConstraints,
269 alloc: A,
270 ) -> Result<(BB, usize), SerializeError<A::Error>> {
271 let hdr_prefix = Ref::bytes(&self.hdr_prefix);
274 let options = self.options.bytes();
275 let hdr_prefix_len = hdr_prefix.len();
276 let header_len = hdr_prefix_len + options.len();
277 let body_to_copy = self.body().len().min(TRANSPORT_HEADER_MAX_SIZE);
278 let outer_header_len = constraints.header_len();
279 let mut buffer = alloc.layout_alloc(outer_header_len + header_len, body_to_copy, 0)?;
280 buffer.with_parts_mut(|prefix, mut body, _suffix| {
281 let options_pos = outer_header_len + hdr_prefix_len;
282 prefix[outer_header_len..options_pos].copy_from_slice(hdr_prefix);
283 prefix[options_pos..].copy_from_slice(options);
284 body.copy_from_slice(&self.body()[..body_to_copy]);
285 });
286 buffer.grow_front(header_len);
287 let total_size = header_len + self.body.len();
288 Ok((buffer, total_size))
289 }
290}
291
292impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv4Packet<B> {
293 type Error = ParseError;
294
295 fn parse_metadata(&self) -> ParseMetadata {
296 ParseMetadata::from_packet(self.header_len(), self.body.len(), 0)
297 }
298
299 fn parse<BV: BufferView<B>>(buffer: BV, _args: ()) -> Result<Self, ParseError> {
300 Ipv4PacketRaw::<B>::parse(buffer, ()).and_then(Ipv4Packet::try_from_raw)
301 }
302}
303
304impl<B: SplitByteSlice> FromRaw<Ipv4PacketRaw<B>, ()> for Ipv4Packet<B> {
305 type Error = ParseError;
306
307 fn try_from_raw_with(raw: Ipv4PacketRaw<B>, _args: ()) -> Result<Self, Self::Error> {
308 let hdr_prefix = raw.hdr_prefix;
311 let hdr_bytes = (hdr_prefix.ihl() * 4) as usize;
312
313 if hdr_bytes < HDR_PREFIX_LEN {
314 return debug_err!(Err(ParseError::Format), "invalid IHL: {}", hdr_prefix.ihl());
315 }
316
317 let options = match raw.options {
318 MaybeParsed::Incomplete(_) => {
319 return debug_err!(Err(ParseError::Format), "Incomplete options");
320 }
321 MaybeParsed::Complete(unchecked) => Options::try_from_raw(unchecked)
322 .map_err(|e| debug_err!(e, "malformed options: {:?}", e))?,
323 };
324
325 if hdr_prefix.version() != 4 {
326 return debug_err!(
327 Err(ParseError::Format),
328 "unexpected IP version: {}",
329 hdr_prefix.version()
330 );
331 }
332
333 let body = match raw.body {
334 MaybeParsed::Incomplete(_) => {
335 if hdr_prefix.mf_flag() {
336 return debug_err!(
337 Err(ParseError::NotSupported),
338 "fragmentation not supported"
339 );
340 } else {
341 return debug_err!(Err(ParseError::Format), "Incomplete body");
342 }
343 }
344 MaybeParsed::Complete(bytes) => bytes,
345 };
346
347 let packet = Ipv4Packet { hdr_prefix, options, body };
348 if packet.compute_header_checksum() != [0, 0] {
349 return debug_err!(Err(ParseError::Checksum), "invalid checksum");
350 }
351 Ok(packet)
352 }
353}
354
355fn compute_header_checksum(hdr_prefix: &[u8], options: &[u8]) -> [u8; 2] {
356 let mut c = Checksum::new();
357 c.add_bytes(hdr_prefix);
358 c.add_bytes(options);
359 c.checksum()
360}
361
362impl<B: SplitByteSlice> Ipv4Packet<B> {
363 pub fn iter_options(&self) -> impl Iterator<Item = Ipv4Option<'_>> {
365 self.options.iter()
366 }
367
368 fn compute_header_checksum(&self) -> [u8; 2] {
370 compute_header_checksum(Ref::bytes(&self.hdr_prefix), self.options.bytes())
371 }
372
373 pub fn body(&self) -> &[u8] {
375 &self.body
376 }
377
378 pub fn header_len(&self) -> usize {
380 Ref::bytes(&self.hdr_prefix).len() + self.options.bytes().len()
381 }
382
383 pub fn src_ipv4(&self) -> Option<Ipv4SourceAddr> {
388 Ipv4SourceAddr::new(self.src_ip())
389 }
390
391 pub fn copy_header_bytes_for_fragment(&self) -> Vec<u8> {
397 let expected_bytes_len = self.header_len();
398 let mut bytes = Vec::with_capacity(expected_bytes_len);
399
400 bytes.extend_from_slice(Ref::bytes(&self.hdr_prefix));
401 bytes.extend_from_slice(self.options.bytes());
402
403 assert_eq!(bytes.len(), expected_bytes_len);
405
406 bytes[IPV4_FRAGMENT_DATA_BYTE_RANGE].copy_from_slice(&[0; 4][..]);
408
409 bytes
410 }
411
412 pub fn nat64_translate(
438 &self,
439 v6_src_addr: Ipv6Addr,
440 v6_dst_addr: Ipv6Addr,
441 ) -> Nat64TranslationResult<
442 impl Serializer<NoOpSerializationContext, Buffer = EmptyBuf> + Debug + '_,
443 Nat64Error,
444 > {
445 #[derive(Debug)]
448 enum Nat64Serializer<T, U, O> {
449 Tcp(T),
450 Udp(U),
451 Other(O),
452 }
453 impl<T, U, O> Serializer<NoOpSerializationContext> for Nat64Serializer<T, U, O>
454 where
455 T: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
456 U: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
457 O: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
458 {
459 type Buffer = EmptyBuf;
460 fn serialize<B, P>(
461 self,
462 context: &mut NoOpSerializationContext,
463 outer: PacketConstraints,
464 provider: P,
465 ) -> Result<B, (SerializeError<P::Error>, Self)>
466 where
467 B: GrowBufferMut,
468 P: BufferProvider<Self::Buffer, B>,
469 {
470 match self {
471 Nat64Serializer::Tcp(serializer) => serializer
472 .serialize(context, outer, provider)
473 .map_err(|(err, ser)| (err, Nat64Serializer::Tcp(ser))),
474 Nat64Serializer::Udp(serializer) => serializer
475 .serialize(context, outer, provider)
476 .map_err(|(err, ser)| (err, Nat64Serializer::Udp(ser))),
477 Nat64Serializer::Other(serializer) => serializer
478 .serialize(context, outer, provider)
479 .map_err(|(err, ser)| (err, Nat64Serializer::Other(ser))),
480 }
481 }
482
483 fn serialize_new_buf<B: GrowBufferMut, A: LayoutBufferAlloc<B>>(
484 &self,
485 context: &mut NoOpSerializationContext,
486 outer: PacketConstraints,
487 alloc: A,
488 ) -> Result<B, SerializeError<A::Error>> {
489 match self {
490 Nat64Serializer::Tcp(serializer) => {
491 serializer.serialize_new_buf(context, outer, alloc)
492 }
493 Nat64Serializer::Udp(serializer) => {
494 serializer.serialize_new_buf(context, outer, alloc)
495 }
496 Nat64Serializer::Other(serializer) => {
497 serializer.serialize_new_buf(context, outer, alloc)
498 }
499 }
500 }
501 }
502
503 impl<T, U, O> NestableSerializer for Nat64Serializer<T, U, O>
504 where
505 T: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
506 U: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
507 O: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
508 {
509 }
510
511 let v6_builder = |v6_proto| {
512 let mut builder =
513 Ipv6PacketBuilder::new(v6_src_addr, v6_dst_addr, self.ttl(), v6_proto);
514 builder.dscp_and_ecn(self.dscp_and_ecn());
515 builder.flowlabel(0);
516 builder
517 };
518
519 match self.proto() {
520 Ipv4Proto::Igmp => {
521 Nat64TranslationResult::Drop
523 }
524
525 Ipv4Proto::Proto(IpProto::Tcp) => {
526 let v6_pkt_builder = v6_builder(Ipv6Proto::Proto(IpProto::Tcp));
527 let args = TcpParseArgs::new(self.src_ip(), self.dst_ip());
528 match TcpSegment::parse(&mut self.body.as_bytes(), args) {
529 Ok(tcp) => {
530 let tcp_serializer =
534 Nat64Serializer::Tcp(tcp.into_serializer(v6_src_addr, v6_dst_addr));
535 Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(tcp_serializer))
536 }
537 Err(msg) => {
538 debug!("Parsing of TCP segment failed: {:?}", msg);
539
540 let common_serializer =
546 Nat64Serializer::Other(self.body().into_serializer());
547 Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(common_serializer))
548 }
549 }
550 }
551
552 Ipv4Proto::Proto(IpProto::Udp) => {
553 let v6_pkt_builder = v6_builder(Ipv6Proto::Proto(IpProto::Udp));
554 let args = UdpParseArgs::new(self.src_ip(), self.dst_ip());
555 match UdpPacket::parse(&mut self.body.as_bytes(), args) {
556 Ok(udp) => {
557 let udp_serializer =
561 Nat64Serializer::Udp(udp.into_serializer(v6_src_addr, v6_dst_addr));
562 Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(udp_serializer))
563 }
564 Err(msg) => {
565 debug!("Parsing of UDP packet failed: {:?}", msg);
566
567 let common_serializer =
573 Nat64Serializer::Other(self.body().into_serializer());
574 Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(common_serializer))
575 }
576 }
577 }
578
579 Ipv4Proto::Icmp => Nat64TranslationResult::Err(Nat64Error::NotImplemented),
580
581 Ipv4Proto::Other(val) => {
586 let v6_pkt_builder = v6_builder(Ipv6Proto::Other(val));
587 let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
588 Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(common_serializer))
589 }
590
591 Ipv4Proto::Proto(IpProto::Reserved) => Nat64TranslationResult::Drop,
594 }
595 }
596
597 pub fn to_vec(&self) -> Vec<u8> {
599 let Ipv4Packet { hdr_prefix, options, body } = self;
600 let mut buf = Vec::with_capacity(
601 Ref::bytes(&hdr_prefix).len() + options.bytes().len() + body.as_bytes().len(),
602 );
603 buf.extend(Ref::bytes(&hdr_prefix));
604 buf.extend(options.bytes());
605 buf.extend(body.as_bytes());
606 buf
607 }
608}
609
610impl<B: SplitByteSliceMut> Ipv4Packet<B> {
611 pub fn set_src_ip_and_update_checksum(&mut self, addr: Ipv4Addr) {
615 let old_bytes = self.hdr_prefix.src_ip.bytes();
616 self.hdr_prefix.hdr_checksum =
617 internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, addr.bytes());
618 self.hdr_prefix.src_ip = addr;
619 }
620
621 pub fn set_dst_ip_and_update_checksum(&mut self, addr: Ipv4Addr) {
625 let old_bytes = self.hdr_prefix.dst_ip.bytes();
626 self.hdr_prefix.hdr_checksum =
627 internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, addr.bytes());
628 self.hdr_prefix.dst_ip = addr;
629 }
630
631 pub fn set_ttl(&mut self, ttl: u8) {
635 let old_bytes = [self.hdr_prefix.ttl, self.hdr_prefix.proto];
639 let new_bytes = [ttl, self.hdr_prefix.proto];
640 self.hdr_prefix.hdr_checksum =
641 internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, &new_bytes);
642 self.hdr_prefix.ttl = ttl;
643 }
644
645 pub fn body_mut(&mut self) -> &mut [u8] {
647 &mut self.body
648 }
649
650 pub fn parts_with_body_mut(&mut self) -> (&HeaderPrefix, &Options<B>, &mut [u8]) {
653 (&self.hdr_prefix, &self.options, &mut self.body)
654 }
655}
656
657impl<B> Debug for Ipv4Packet<B>
658where
659 B: SplitByteSlice,
660{
661 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
662 f.debug_struct("Ipv4Packet")
663 .field("src_ip", &self.src_ip())
664 .field("dst_ip", &self.dst_ip())
665 .field("id", &self.id())
666 .field("ttl", &self.ttl())
667 .field("proto", &self.proto())
668 .field("frag_off", &self.fragment_offset())
669 .field("dscp", &self.dscp_and_ecn().dscp())
670 .field("ecn", &self.dscp_and_ecn().ecn())
671 .field("mf_flag", &self.mf_flag())
672 .field("df_flag", &self.df_flag())
673 .field("body", &alloc::format!("<{} bytes>", self.body.len()))
674 .finish()
675 }
676}
677
678pub struct Ipv4PacketRaw<B> {
688 hdr_prefix: Ref<B, HeaderPrefix>,
689 options: MaybeParsed<OptionsRaw<B, Ipv4OptionsImpl>, B>,
690 body: MaybeParsed<B, B>,
691}
692
693impl<B> Ipv4PacketRaw<B> {
694 pub fn body_mut(&mut self) -> &mut B {
698 match &mut self.body {
699 MaybeParsed::Complete(b) => b,
700 MaybeParsed::Incomplete(b) => b,
701 }
702 }
703}
704
705impl<B: SplitByteSlice> Ipv4Header for Ipv4PacketRaw<B> {
706 fn get_header_prefix(&self) -> &HeaderPrefix {
707 &self.hdr_prefix
708 }
709}
710
711impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv4PacketRaw<B> {
712 type Error = ParseError;
713
714 fn parse_metadata(&self) -> ParseMetadata {
715 let header_len = Ref::bytes(&self.hdr_prefix).len() + self.options.len();
716 ParseMetadata::from_packet(header_len, self.body.len(), 0)
717 }
718
719 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> Result<Self, ParseError> {
720 let hdr_prefix = buffer
721 .take_obj_front::<HeaderPrefix>()
722 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for header"))?;
723 let hdr_bytes = (hdr_prefix.ihl() * 4) as usize;
724
725 let options = MaybeParsed::take_from_buffer_with(
726 &mut buffer,
727 hdr_bytes.saturating_sub(HDR_PREFIX_LEN),
732 OptionsRaw::new,
733 );
734
735 let total_len: usize = hdr_prefix.total_len.get().into();
736 let body_len = total_len.saturating_sub(hdr_bytes);
737 if buffer.len() > body_len {
738 let _: B = buffer.take_back(buffer.len() - body_len).unwrap();
741 }
742
743 let body = MaybeParsed::new_with_min_len(buffer.into_rest(), body_len);
744
745 Ok(Self { hdr_prefix, options, body })
746 }
747}
748
749impl<B> Ipv4PacketRaw<B> {
750 pub fn options(&self) -> &MaybeParsed<OptionsRaw<B, Ipv4OptionsImpl>, B> {
752 &self.options
753 }
754}
755
756impl<B: SplitByteSlice> Ipv4PacketRaw<B> {
757 pub fn body(&self) -> MaybeParsed<&[u8], &[u8]> {
763 self.body.as_ref().map(|b| b.deref()).map_incomplete(|b| b.deref())
764 }
765
766 pub fn into_body(self) -> MaybeParsed<B, B> {
770 self.body
771 }
772}
773
774impl<B: SplitByteSliceMut> Ipv4PacketRaw<B> {
775 pub fn set_src_ip_and_update_checksum(&mut self, addr: Ipv4Addr) {
779 let old_bytes = self.hdr_prefix.src_ip.bytes();
780 self.hdr_prefix.hdr_checksum =
781 internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, addr.bytes());
782 self.hdr_prefix.src_ip = addr;
783 }
784
785 pub fn set_dst_ip_and_update_checksum(&mut self, addr: Ipv4Addr) {
789 let old_bytes = self.hdr_prefix.dst_ip.bytes();
790 self.hdr_prefix.hdr_checksum =
791 internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, addr.bytes());
792 self.hdr_prefix.dst_ip = addr;
793 }
794
795 pub fn set_total_len_and_update_checksum(&mut self, total_len: u16) {
797 let old_bytes = self.hdr_prefix.total_len.as_bytes();
798 let new_len = U16::new(total_len);
799 self.hdr_prefix.hdr_checksum =
800 internet_checksum::update(self.hdr_prefix.hdr_checksum, old_bytes, new_len.as_bytes());
801 self.hdr_prefix.total_len = new_len;
802 }
803}
804
805pub type Options<B> = packet::records::options::Options<B, Ipv4OptionsImpl>;
811
812#[derive(Debug)]
815pub struct Ipv4OptionsTooLongError;
816
817#[derive(Debug, Clone)]
819pub struct Ipv4PacketBuilderWithOptions<'a, I> {
820 prefix_builder: Ipv4PacketBuilder,
821 options: OptionSequenceBuilder<Ipv4Option<'a>, I>,
822}
823
824impl<'a, I> Ipv4PacketBuilderWithOptions<'a, I>
825where
826 I: Iterator + Clone,
827 I::Item: Borrow<Ipv4Option<'a>>,
828{
829 pub fn new<T: IntoIterator<IntoIter = I>>(
835 prefix_builder: Ipv4PacketBuilder,
836 options: T,
837 ) -> Result<Ipv4PacketBuilderWithOptions<'a, I>, Ipv4OptionsTooLongError> {
838 let options = OptionSequenceBuilder::new(options.into_iter());
839 if options.serialized_len() > MAX_OPTIONS_LEN {
840 return Err(Ipv4OptionsTooLongError);
841 }
842 Ok(Ipv4PacketBuilderWithOptions { prefix_builder, options })
843 }
844
845 fn aligned_options_len(&self) -> usize {
846 crate::utils::round_to_next_multiple_of_four(self.options.serialized_len())
848 }
849
850 pub fn prefix_builder(&self) -> &Ipv4PacketBuilder {
852 &self.prefix_builder
853 }
854
855 pub fn prefix_builder_mut(&mut self) -> &mut Ipv4PacketBuilder {
857 &mut self.prefix_builder
858 }
859
860 pub fn options(&self) -> &I {
862 self.options.records()
863 }
864
865 pub fn with_fragment_options(
871 self,
872 first_fragment: bool,
873 ) -> Ipv4PacketBuilderWithOptions<'a, impl Iterator<Item: Borrow<Ipv4Option<'a>>> + Clone> {
874 let Self { prefix_builder, options } = self;
875 Ipv4PacketBuilderWithOptions {
876 prefix_builder,
877 options: OptionSequenceBuilder::new(
880 options
881 .records()
882 .clone()
883 .filter(move |opt| first_fragment || opt.borrow().copied()),
884 ),
885 }
886 }
887}
888
889impl<'a, B> Ipv4PacketBuilderWithOptions<'a, RecordsIter<'a, B, Ipv4OptionsImpl>> {
890 pub fn new_with_records_iter(
893 prefix_builder: Ipv4PacketBuilder,
894 iter: RecordsIter<'a, B, Ipv4OptionsImpl>,
895 ) -> Self {
896 Self { prefix_builder, options: OptionSequenceBuilder::new(iter) }
897 }
898}
899
900impl<'a, I> NestablePacketBuilder for Ipv4PacketBuilderWithOptions<'a, I>
901where
902 I: Iterator + Clone,
903 I::Item: Borrow<Ipv4Option<'a>>,
904{
905 fn constraints(&self) -> PacketConstraints {
906 let header_len = IPV4_MIN_HDR_LEN + self.aligned_options_len();
907 assert_eq!(header_len % 4, 0);
908 PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
909 }
910}
911
912impl<'a, I, C: IpSerializationContext<Ipv4>> PacketBuilder<C>
913 for Ipv4PacketBuilderWithOptions<'a, I>
914where
915 I: Iterator + Clone,
916 I::Item: Borrow<Ipv4Option<'a>>,
917{
918 fn context_state(&self) -> C::ContextState {
919 C::envelope_to_state(IpEnvelope::new(true))
920 }
921
922 fn serialize(
923 &self,
924 context: &mut C,
925 target: &mut SerializeTarget<'_>,
926 body: FragmentedBytesMut<'_, '_>,
927 ) {
928 let opt_len = self.aligned_options_len();
929 let mut header = &mut &mut target.header[..];
935 let opts = header.take_back_zero(opt_len).expect("too few bytes for Ipv4 options");
936 let Ipv4PacketBuilderWithOptions { prefix_builder, options } = self;
937 options.serialize_into(opts);
938 prefix_builder.serialize(context, target, body);
939 }
940}
941
942impl<'a, I, C: IpSerializationContext<Ipv4>> PartialPacketBuilder<C>
943 for Ipv4PacketBuilderWithOptions<'a, I>
944where
945 I: Iterator + Clone,
946 I::Item: Borrow<Ipv4Option<'a>>,
947{
948 fn partial_serialize(&self, context: &mut C, body_len: usize, header: &mut [u8]) {
949 let Ipv4PacketBuilderWithOptions { prefix_builder, options } = self;
950 prefix_builder.partial_serialize(context, body_len, header);
951 let options_slice = &mut header[IPV4_MIN_HDR_LEN..];
952 assert_eq!(options_slice.len(), self.aligned_options_len());
953 options.serialize_into(options_slice);
954 }
955}
956
957impl<'a, C: IpSerializationContext<Ipv4>, I> IpPacketBuilder<C, Ipv4>
958 for Ipv4PacketBuilderWithOptions<'a, I>
959where
960 I: Default + Debug + Clone + Iterator<Item: Borrow<Ipv4Option<'a>>>,
961{
962 fn new(src_ip: Ipv4Addr, dst_ip: Ipv4Addr, ttl: u8, proto: Ipv4Proto) -> Self {
963 Ipv4PacketBuilderWithOptions::new(
964 Ipv4PacketBuilder::new(src_ip, dst_ip, ttl, proto),
965 I::default(),
966 )
967 .expect("packet builder with no options should be valid")
968 }
969
970 fn src_ip(&self) -> Ipv4Addr {
971 self.prefix_builder.src_ip
972 }
973
974 fn set_src_ip(&mut self, addr: Ipv4Addr) {
975 <Ipv4PacketBuilder as IpPacketBuilder<C, Ipv4>>::set_src_ip(&mut self.prefix_builder, addr)
976 }
977
978 fn dst_ip(&self) -> Ipv4Addr {
979 self.prefix_builder.dst_ip
980 }
981
982 fn set_dst_ip(&mut self, addr: Ipv4Addr) {
983 <Ipv4PacketBuilder as IpPacketBuilder<C, Ipv4>>::set_dst_ip(&mut self.prefix_builder, addr)
984 }
985
986 fn proto(&self) -> Ipv4Proto {
987 self.prefix_builder.proto
988 }
989
990 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
991 <Ipv4PacketBuilder as IpPacketBuilder<C, Ipv4>>::set_dscp_and_ecn(
992 &mut self.prefix_builder,
993 dscp_and_ecn,
994 )
995 }
996}
997
998#[derive(Debug, Clone, Eq, PartialEq)]
1000pub struct Ipv4PacketBuilder {
1001 id: u16,
1002 dscp_and_ecn: DscpAndEcn,
1003 flags: u8,
1004 frag_off: u16,
1005 ttl: u8,
1006 proto: Ipv4Proto,
1007 src_ip: Ipv4Addr,
1008 dst_ip: Ipv4Addr,
1009}
1010
1011impl Ipv4PacketBuilder {
1012 pub fn new<S: Into<Ipv4Addr>, D: Into<Ipv4Addr>>(
1014 src_ip: S,
1015 dst_ip: D,
1016 ttl: u8,
1017 proto: Ipv4Proto,
1018 ) -> Ipv4PacketBuilder {
1019 Ipv4PacketBuilder {
1020 id: 0,
1021 dscp_and_ecn: DscpAndEcn::default(),
1022 flags: 0,
1023 frag_off: 0,
1024 ttl,
1025 proto: proto,
1026 src_ip: src_ip.into(),
1027 dst_ip: dst_ip.into(),
1028 }
1029 }
1030
1031 pub fn dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1033 self.dscp_and_ecn = dscp_and_ecn;
1034 }
1035
1036 pub fn read_id(&self) -> u16 {
1038 self.id
1039 }
1040
1041 pub fn id(&mut self, id: u16) {
1043 self.id = id
1044 }
1045
1046 pub fn df_flag(&mut self, df: bool) {
1048 if df {
1049 self.flags |= 1 << DF_FLAG_OFFSET;
1050 } else {
1051 self.flags &= !(1 << DF_FLAG_OFFSET);
1052 }
1053 }
1054
1055 pub fn mf_flag(&mut self, mf: bool) {
1057 if mf {
1058 self.flags |= 1 << MF_FLAG_OFFSET;
1059 } else {
1060 self.flags &= !(1 << MF_FLAG_OFFSET);
1061 }
1062 }
1063
1064 pub fn fragment_offset(&mut self, fragment_offset: FragmentOffset) {
1066 self.frag_off = fragment_offset.into_raw();
1067 }
1068
1069 pub fn read_df_flag(&self) -> bool {
1071 (self.flags & (1 << DF_FLAG_OFFSET)) != 0
1072 }
1073
1074 fn get_header_prefix(&self, header_len: usize, total_len: usize) -> HeaderPrefix {
1075 assert_eq!(header_len % 4, 0);
1076 let ihl: u8 = u8::try_from(header_len / 4).expect("Header too large");
1077
1078 let id = if ((self.flags & (1 << DF_FLAG_OFFSET)) == 0)
1088 || ((self.flags & (1 << MF_FLAG_OFFSET)) == 1)
1089 || (self.frag_off > 0)
1090 {
1091 self.id
1092 } else {
1093 0
1094 };
1095
1096 HeaderPrefix::new(
1097 ihl,
1098 self.dscp_and_ecn,
1099 {
1100 debug_assert!(total_len <= u16::MAX as usize);
1106 total_len as u16
1107 },
1108 id,
1109 self.flags,
1110 self.frag_off,
1111 self.ttl,
1112 self.proto.into(),
1113 [0, 0], self.src_ip,
1115 self.dst_ip,
1116 )
1117 }
1118}
1119
1120impl NestablePacketBuilder for Ipv4PacketBuilder {
1121 fn constraints(&self) -> PacketConstraints {
1122 PacketConstraints::new(IPV4_MIN_HDR_LEN, 0, 0, (1 << 16) - 1 - IPV4_MIN_HDR_LEN)
1123 }
1124}
1125
1126impl<C: IpSerializationContext<Ipv4>> PacketBuilder<C> for Ipv4PacketBuilder {
1127 fn context_state(&self) -> C::ContextState {
1128 C::envelope_to_state(IpEnvelope::new(false))
1129 }
1130
1131 fn serialize(
1132 &self,
1133 _context: &mut C,
1134 target: &mut SerializeTarget<'_>,
1135 body: FragmentedBytesMut<'_, '_>,
1136 ) {
1137 let header_len = target.header.len();
1138 let total_len = header_len + body.len();
1139 let mut hdr_prefix = self.get_header_prefix(header_len, total_len);
1140 let options = &target.header[HDR_PREFIX_LEN..];
1141 let checksum = compute_header_checksum(hdr_prefix.as_bytes(), options);
1142 hdr_prefix.hdr_checksum = checksum;
1143 let mut header = &mut target.header;
1144 header.write_obj_front(&hdr_prefix).expect("too few bytes for IPv4 header prefix");
1145 }
1146}
1147
1148impl<C: IpSerializationContext<Ipv4>> PartialPacketBuilder<C> for Ipv4PacketBuilder {
1149 fn partial_serialize(&self, _context: &mut C, body_len: usize, mut header: &mut [u8]) {
1150 let total_len = header.len() + body_len;
1151 let hdr_prefix = self.get_header_prefix(header.len(), total_len);
1152 (&mut header).write_obj_front(&hdr_prefix).expect("too few bytes for IPv4 header prefix");
1153 }
1154}
1155
1156impl<C: IpSerializationContext<Ipv4>> IpPacketBuilder<C, Ipv4> for Ipv4PacketBuilder {
1157 fn new(src_ip: Ipv4Addr, dst_ip: Ipv4Addr, ttl: u8, proto: Ipv4Proto) -> Self {
1158 Ipv4PacketBuilder::new(src_ip, dst_ip, ttl, proto)
1159 }
1160
1161 fn src_ip(&self) -> Ipv4Addr {
1162 self.src_ip
1163 }
1164
1165 fn set_src_ip(&mut self, addr: Ipv4Addr) {
1166 self.src_ip = addr;
1167 }
1168
1169 fn dst_ip(&self) -> Ipv4Addr {
1170 self.dst_ip
1171 }
1172
1173 fn set_dst_ip(&mut self, addr: Ipv4Addr) {
1174 self.dst_ip = addr;
1175 }
1176
1177 fn proto(&self) -> Ipv4Proto {
1178 self.proto
1179 }
1180
1181 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1182 self.dscp_and_ecn = dscp_and_ecn;
1183 }
1184}
1185
1186const DF_FLAG_OFFSET: u8 = 1;
1188const MF_FLAG_OFFSET: u8 = 0;
1189
1190pub(crate) fn reassemble_fragmented_packet<
1196 'a,
1197 B: SplitByteSliceMut,
1198 BV: BufferViewMut<B>,
1199 I: Iterator<Item = &'a [u8]>,
1200>(
1201 mut buffer: BV,
1202 header: &[u8],
1203 body_fragments: I,
1204) -> Result<(), ParseError> {
1205 assert!(header.len() >= HDR_PREFIX_LEN);
1206
1207 let bytes = buffer.as_mut();
1208
1209 bytes[0..header.len()].copy_from_slice(header);
1211 let mut byte_count = header.len();
1212
1213 for p in body_fragments {
1215 bytes[byte_count..byte_count + p.len()].copy_from_slice(p);
1216 byte_count += p.len();
1217 }
1218
1219 if byte_count > usize::from(u16::MAX) {
1224 return debug_err!(
1225 Err(ParseError::Format),
1226 "fragmented packet length of {} bytes is too large",
1227 byte_count
1228 );
1229 }
1230
1231 let mut header_ref = Ref::<_, HeaderPrefix>::from_prefix(bytes).unwrap().0;
1234
1235 let options_bytes = &header[HDR_PREFIX_LEN..header.len()];
1236
1237 header_ref.total_len.set(u16::try_from(byte_count).unwrap());
1239
1240 header_ref.flags_frag_off = [0; 2];
1243
1244 header_ref.hdr_checksum = [0; 2];
1246 header_ref.hdr_checksum = compute_header_checksum(header_ref.as_bytes(), options_bytes);
1247
1248 Ok(())
1249}
1250
1251pub mod options {
1253 use byteorder::{ByteOrder, NetworkEndian};
1254 use packet::BufferViewMut;
1255 use packet::records::options::{
1256 OptionBuilder, OptionLayout, OptionParseErr, OptionParseLayout, OptionsImpl,
1257 };
1258 use zerocopy::byteorder::network_endian::U16;
1259
1260 const OPTION_KIND_EOL: u8 = 0;
1261 const OPTION_KIND_NOP: u8 = 1;
1262 const OPTION_KIND_RTRALRT: u8 = 148;
1263
1264 const OPTION_RTRALRT_LEN: usize = 2;
1265
1266 #[derive(PartialEq, Eq, Debug, Clone)]
1273 #[allow(missing_docs)]
1274 pub enum Ipv4Option<'a> {
1275 RouterAlert { data: u16 },
1281
1282 Unrecognized { kind: u8, data: &'a [u8] },
1294 }
1295
1296 impl<'a> Ipv4Option<'a> {
1297 pub fn copied(&self) -> bool {
1299 match self {
1300 Ipv4Option::RouterAlert { .. } => true,
1304 Ipv4Option::Unrecognized { kind, .. } => *kind & (1 << 7) != 0,
1305 }
1306 }
1307 }
1308
1309 #[derive(Debug, Clone)]
1311 pub struct Ipv4OptionsImpl;
1312
1313 impl OptionLayout for Ipv4OptionsImpl {
1314 type KindLenField = u8;
1315 }
1316
1317 impl OptionParseLayout for Ipv4OptionsImpl {
1318 type Error = OptionParseErr;
1319 const END_OF_OPTIONS: Option<u8> = Some(0);
1320 const NOP: Option<u8> = Some(1);
1321 }
1322
1323 impl OptionsImpl for Ipv4OptionsImpl {
1324 type Option<'a> = Ipv4Option<'a>;
1325
1326 fn parse<'a>(kind: u8, data: &'a [u8]) -> Result<Option<Ipv4Option<'a>>, OptionParseErr> {
1327 match kind {
1328 self::OPTION_KIND_EOL | self::OPTION_KIND_NOP => {
1329 unreachable!("records::options::Options promises to handle EOL and NOP")
1330 }
1331 self::OPTION_KIND_RTRALRT => {
1332 if data.len() == OPTION_RTRALRT_LEN {
1333 Ok(Some(Ipv4Option::RouterAlert { data: NetworkEndian::read_u16(data) }))
1334 } else {
1335 Err(OptionParseErr)
1336 }
1337 }
1338 kind => {
1339 if data.len() > 38 {
1340 Err(OptionParseErr)
1341 } else {
1342 Ok(Some(Ipv4Option::Unrecognized { kind, data }))
1343 }
1344 }
1345 }
1346 }
1347 }
1348
1349 impl<'a> OptionBuilder for Ipv4Option<'a> {
1350 type Layout = Ipv4OptionsImpl;
1351
1352 fn serialized_len(&self) -> usize {
1353 match self {
1354 Ipv4Option::RouterAlert { .. } => OPTION_RTRALRT_LEN,
1355 Ipv4Option::Unrecognized { data, .. } => data.len(),
1356 }
1357 }
1358
1359 fn option_kind(&self) -> u8 {
1360 match self {
1361 Ipv4Option::RouterAlert { .. } => OPTION_KIND_RTRALRT,
1362 Ipv4Option::Unrecognized { kind, .. } => *kind,
1363 }
1364 }
1365
1366 fn serialize_into(&self, mut buffer: &mut [u8]) {
1367 match self {
1368 Ipv4Option::Unrecognized { data, .. } => buffer.copy_from_slice(data),
1369 Ipv4Option::RouterAlert { data } => {
1370 (&mut buffer).write_obj_front(&U16::new(*data)).unwrap()
1371 }
1372 };
1373 }
1374 }
1375
1376 #[cfg(test)]
1377 mod test {
1378 use packet::records::RecordBuilder;
1379 use packet::records::options::Options;
1380
1381 use super::*;
1382
1383 #[test]
1384 fn test_serialize_router_alert() {
1385 let mut buffer = [0u8; 4];
1386 let option = Ipv4Option::RouterAlert { data: 0 };
1387 <Ipv4Option<'_> as RecordBuilder>::serialize_into(&option, &mut buffer);
1388 assert_eq!(buffer[0], 148);
1389 assert_eq!(buffer[1], 4);
1390 assert_eq!(buffer[2], 0);
1391 assert_eq!(buffer[3], 0);
1392 }
1393
1394 #[test]
1395 fn test_parse_router_alert() {
1396 let mut buffer: Vec<u8> = vec![148, 4, 0, 0];
1397 let options = Options::<_, Ipv4OptionsImpl>::parse(buffer.as_mut()).unwrap();
1398 let rtralt = options.iter().next().unwrap();
1399 assert_eq!(rtralt, Ipv4Option::RouterAlert { data: 0 });
1400 }
1401 }
1402}
1403
1404mod inner {
1405 pub const IPV4_MIN_HDR_LEN: usize = super::HDR_PREFIX_LEN;
1407}
1408
1409pub mod testutil {
1411 pub use super::inner::IPV4_MIN_HDR_LEN;
1412
1413 pub const IPV4_TTL_OFFSET: usize = 8;
1415
1416 pub const IPV4_CHECKSUM_OFFSET: usize = 10;
1418}
1419
1420#[cfg(test)]
1421mod tests {
1422 use assert_matches::assert_matches;
1423 use net_types::ethernet::Mac;
1424 use packet::{Buf, FragmentedBuffer, ParseBuffer, PartialSerializeResult};
1425
1426 use super::*;
1427 use crate::ethernet::{
1428 ETHERNET_MIN_BODY_LEN_NO_TAG, EtherType, EthernetFrame, EthernetFrameBuilder,
1429 EthernetFrameLengthCheck,
1430 };
1431 use crate::testutil::*;
1432
1433 const DEFAULT_SRC_MAC: Mac = Mac::new([1, 2, 3, 4, 5, 6]);
1434 const DEFAULT_DST_MAC: Mac = Mac::new([7, 8, 9, 0, 1, 2]);
1435 const DEFAULT_SRC_IP: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1436 const DEFAULT_DST_IP: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1437 const DEFAULT_V6_SRC_IP: Ipv6Addr = Ipv6Addr::new([0x2001, 0x0db8, 0, 0, 0, 0, 0, 1]);
1439 const DEFAULT_V6_DST_IP: Ipv6Addr = Ipv6Addr::new([0x2001, 0x0db8, 0, 0, 0, 0, 0, 2]);
1441
1442 #[test]
1443 fn test_parse_serialize_full_tcp() {
1444 use crate::testdata::tls_client_hello_v4::*;
1445
1446 let mut buf = ETHERNET_FRAME.bytes;
1447 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1448 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1449
1450 let mut body = frame.body();
1451 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1452 verify_ipv4_packet(&packet, IPV4_PACKET);
1453
1454 let buffer = packet
1456 .body()
1457 .into_serializer()
1458 .wrap_in(packet.builder())
1459 .wrap_in(frame.builder())
1460 .serialize_vec_outer(&mut NoOpSerializationContext)
1461 .unwrap();
1462 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1463
1464 assert_eq!(&packet.to_vec()[..], IPV4_PACKET.bytes);
1466 }
1467
1468 #[test]
1469 fn test_parse_serialize_full_udp() {
1470 use crate::testdata::dns_request_v4::*;
1471
1472 let mut buf = ETHERNET_FRAME.bytes;
1473 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1474 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1475
1476 let mut body = frame.body();
1477 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1478 verify_ipv4_packet(&packet, IPV4_PACKET);
1479
1480 let buffer = packet
1482 .body()
1483 .into_serializer()
1484 .wrap_in(packet.builder())
1485 .wrap_in(frame.builder())
1486 .serialize_vec_outer(&mut NoOpSerializationContext)
1487 .unwrap();
1488 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1489
1490 assert_eq!(&packet.to_vec()[..], IPV4_PACKET.bytes);
1492 }
1493
1494 #[test]
1495 fn test_parse_serialize_with_options() {
1496 use crate::testdata::igmpv2_membership::report::*;
1499
1500 let mut buf = IP_PACKET_BYTES;
1501 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1502 assert_eq!(packet.iter_options().count(), 1);
1503
1504 assert_eq!(&packet.to_vec()[..], IP_PACKET_BYTES);
1509 }
1510
1511 fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; 20] {
1512 zerocopy::transmute!(hdr_prefix)
1513 }
1514
1515 fn new_hdr_prefix() -> HeaderPrefix {
1518 HeaderPrefix::new(
1519 5,
1520 DscpAndEcn::default(),
1521 20,
1522 0x0102,
1523 0,
1524 0,
1525 0x03,
1526 IpProto::Tcp.into(),
1527 [0xa6, 0xcf],
1528 DEFAULT_SRC_IP,
1529 DEFAULT_DST_IP,
1530 )
1531 }
1532
1533 #[test]
1534 fn test_parse() {
1535 let mut bytes = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1536 let packet = bytes.parse::<Ipv4Packet<_>>().unwrap();
1537 assert_eq!(packet.id(), 0x0102);
1538 assert_eq!(packet.ttl(), 0x03);
1539 assert_eq!(packet.proto(), IpProto::Tcp.into());
1540 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1541 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1542 assert_eq!(packet.body(), []);
1543 }
1544
1545 #[test]
1546 fn test_parse_padding() {
1547 let mut buffer = Buf::new(Vec::new(), ..)
1549 .wrap_in(Ipv4PacketBuilder::new(DEFAULT_DST_IP, DEFAULT_DST_IP, 0, IpProto::Tcp.into()))
1550 .wrap_in(EthernetFrameBuilder::new(
1551 DEFAULT_SRC_MAC,
1552 DEFAULT_DST_MAC,
1553 EtherType::Ipv4,
1554 ETHERNET_MIN_BODY_LEN_NO_TAG,
1555 ))
1556 .serialize_vec_outer(&mut NoOpSerializationContext)
1557 .unwrap();
1558 let _: EthernetFrame<_> =
1559 buffer.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1560 assert_eq!(buffer.len(), 46);
1563 let packet = buffer.parse::<Ipv4Packet<_>>().unwrap();
1564 assert_eq!(packet.body().len(), 0);
1567 assert_eq!(buffer.len(), 0);
1571 }
1572
1573 #[test]
1574 fn test_parse_error() {
1575 let mut hdr_prefix = new_hdr_prefix();
1577 hdr_prefix.version_ihl = (5 << 4) | 5;
1578 assert_eq!(
1579 (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1580 ParseError::Format.into()
1581 );
1582
1583 let mut hdr_prefix = new_hdr_prefix();
1586 hdr_prefix.version_ihl = (4 << 4) | 4;
1587 assert_eq!(
1588 (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1589 ParseError::Format.into()
1590 );
1591
1592 let mut hdr_prefix = new_hdr_prefix();
1595 hdr_prefix.version_ihl = (4 << 4) | 6;
1596 assert_eq!(
1597 (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1598 ParseError::Format.into()
1599 );
1600 }
1601
1602 fn new_builder() -> Ipv4PacketBuilder {
1604 Ipv4PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, 64, IpProto::Tcp.into())
1605 }
1606
1607 #[test]
1608 fn test_fragment_type() {
1609 fn test_fragment_type_helper(fragment_offset: u16, expect_fragment_type: Ipv4FragmentType) {
1610 let mut builder = new_builder();
1611 builder.fragment_offset(FragmentOffset::new(fragment_offset).unwrap());
1612
1613 let mut buf = [0; IPV4_MIN_HDR_LEN]
1614 .into_serializer()
1615 .wrap_in(builder)
1616 .serialize_vec_outer(&mut NoOpSerializationContext)
1617 .unwrap();
1618
1619 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1620 assert_eq!(packet.fragment_type(), expect_fragment_type);
1621 }
1622
1623 test_fragment_type_helper(0x0000, Ipv4FragmentType::InitialFragment);
1624 test_fragment_type_helper(0x0008, Ipv4FragmentType::NonInitialFragment);
1625 }
1626
1627 #[test]
1628 fn test_serialize() {
1629 let mut builder = new_builder();
1630 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
1631 builder.id(0x0405);
1632 builder.df_flag(true);
1633 builder.mf_flag(true);
1634 builder.fragment_offset(FragmentOffset::new(0x0607).unwrap());
1635
1636 let mut buf = (&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9])
1637 .into_serializer()
1638 .wrap_in(builder)
1639 .serialize_vec_outer(&mut NoOpSerializationContext)
1640 .unwrap();
1641 assert_eq!(
1642 buf.as_ref(),
1643 [
1644 69, 75, 0, 30, 4, 5, 102, 7, 64, 6, 0, 112, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 3,
1645 4, 5, 7, 8, 9
1646 ]
1647 );
1648 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1649 assert_eq!(packet.dscp_and_ecn().dscp(), 0x12);
1650 assert_eq!(packet.dscp_and_ecn().ecn(), 3);
1651 assert_eq!(packet.id(), 0x0405);
1652 assert!(packet.df_flag());
1653 assert!(packet.mf_flag());
1654 assert_eq!(packet.fragment_offset().into_raw(), 0x0607);
1655 assert_eq!(packet.fragment_type(), Ipv4FragmentType::NonInitialFragment);
1656 }
1657
1658 #[test]
1659 fn test_partial_serialize() {
1660 let mut builder = new_builder();
1661 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
1662 builder.id(0x0405);
1663 builder.df_flag(true);
1664 builder.mf_flag(true);
1665 builder.fragment_offset(FragmentOffset::new(0x0607).unwrap());
1666 const BODY: &[u8] = &[0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1667 let packet = BODY.into_serializer().wrap_in(builder);
1668 const HEADER: &[u8] = &[69, 75, 0, 30, 4, 5, 102, 7, 64, 6, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8];
1669 const PACKET_LEN: usize = HEADER.len() + BODY.len();
1670
1671 let buf = assert_matches!(
1675 packet.partial_serialize(&mut NoOpSerializationContext, packet::new_buf_vec),
1676 Ok(PartialSerializeResult::NewBuffer { buffer, total_size: PACKET_LEN }) => buffer
1677 );
1678 assert_eq!(buf.as_ref(), HEADER);
1679 }
1680
1681 #[test]
1682 fn test_serialize_id_unset() {
1683 let mut builder = new_builder();
1684 builder.id(0x0405);
1685 builder.df_flag(true);
1686
1687 let mut buf = (&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9])
1688 .into_serializer()
1689 .wrap_in(builder)
1690 .serialize_vec_outer(&mut NoOpSerializationContext)
1691 .unwrap();
1692 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1693 assert_eq!(packet.id(), 0);
1694 assert!(packet.df_flag());
1695 assert_eq!(packet.mf_flag(), false);
1696 assert_eq!(packet.fragment_offset().into_raw(), 0);
1697 assert_eq!(packet.fragment_type(), Ipv4FragmentType::InitialFragment);
1698 }
1699
1700 #[test]
1701 fn test_serialize_zeroes() {
1702 let mut buf_0 = [0; IPV4_MIN_HDR_LEN];
1705 let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], IPV4_MIN_HDR_LEN..)
1706 .wrap_in(new_builder())
1707 .serialize_vec_outer(&mut NoOpSerializationContext)
1708 .unwrap()
1709 .unwrap_a();
1710 let mut buf_1 = [0xFF; IPV4_MIN_HDR_LEN];
1711 let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], IPV4_MIN_HDR_LEN..)
1712 .wrap_in(new_builder())
1713 .serialize_vec_outer(&mut NoOpSerializationContext)
1714 .unwrap()
1715 .unwrap_a();
1716 assert_eq!(buf_0, buf_1);
1717 }
1718
1719 #[test]
1720 #[should_panic(expected = "(SizeLimitExceeded, Nested { inner: Buf { buf:")]
1721 fn test_serialize_panic_packet_length() {
1722 let _: Buf<&mut [u8]> = Buf::new(&mut [0; (1 << 16) - IPV4_MIN_HDR_LEN][..], ..)
1724 .wrap_in(new_builder())
1725 .serialize_vec_outer(&mut NoOpSerializationContext)
1726 .unwrap()
1727 .unwrap_a();
1728 }
1729
1730 #[test]
1731 fn test_copy_header_bytes_for_fragment() {
1732 let hdr_prefix = new_hdr_prefix();
1733 let mut bytes = hdr_prefix_to_bytes(hdr_prefix);
1734 let mut buf = &bytes[..];
1735 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1736 let copied_bytes = packet.copy_header_bytes_for_fragment();
1737 bytes[IPV4_FRAGMENT_DATA_BYTE_RANGE].copy_from_slice(&[0; 4][..]);
1738 assert_eq!(&copied_bytes[..], &bytes[..]);
1739 }
1740
1741 #[test]
1742 fn test_partial_parsing() {
1743 use core::ops::Deref as _;
1744
1745 let mut hdr_prefix = new_hdr_prefix();
1748 hdr_prefix.total_len = U16::new(256);
1749 let mut bytes = hdr_prefix_to_bytes(hdr_prefix)[..].to_owned();
1750 const PAYLOAD: &[u8] = &[1, 2, 3, 4, 5];
1751 bytes.extend(PAYLOAD);
1752 let mut buf = &bytes[..];
1753 let packet = buf.parse::<Ipv4PacketRaw<_>>().unwrap();
1754 let Ipv4PacketRaw { hdr_prefix, options, body } = &packet;
1755 assert_eq!(Ref::bytes(&hdr_prefix), &bytes[0..20]);
1756 assert_eq!(options.as_ref().complete().unwrap().deref(), []);
1757 assert_eq!(body, &MaybeParsed::Incomplete(PAYLOAD));
1759 assert!(Ipv4Packet::try_from_raw(packet).is_err());
1761
1762 let mut hdr_prefix = new_hdr_prefix();
1764 hdr_prefix.version_ihl = (4 << 4) | 10;
1765 let bytes = hdr_prefix_to_bytes(hdr_prefix);
1766 let mut buf = &bytes[..];
1767 let packet = buf.parse::<Ipv4PacketRaw<_>>().unwrap();
1768 let Ipv4PacketRaw { hdr_prefix, options, body } = &packet;
1769 assert_eq!(Ref::bytes(&hdr_prefix), bytes);
1770 assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
1771 assert_eq!(body.complete().unwrap(), []);
1772 assert!(Ipv4Packet::try_from_raw(packet).is_err());
1774
1775 let hdr_prefix = new_hdr_prefix();
1777 let bytes = &hdr_prefix_to_bytes(hdr_prefix);
1778 let mut buf = &bytes[0..10];
1779 assert!(buf.parse::<Ipv4PacketRaw<_>>().is_err());
1780 }
1781
1782 fn create_ipv4_and_ipv6_builders(
1783 proto_v4: Ipv4Proto,
1784 proto_v6: Ipv6Proto,
1785 ) -> (Ipv4PacketBuilder, Ipv6PacketBuilder) {
1786 const IP_DSCP_AND_ECN: DscpAndEcn = DscpAndEcn::new(0x12, 3);
1787 const IP_TTL: u8 = 64;
1788
1789 let mut ipv4_builder =
1790 Ipv4PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, IP_TTL, proto_v4);
1791 ipv4_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
1792 ipv4_builder.id(0x0405);
1793 ipv4_builder.df_flag(true);
1794 ipv4_builder.mf_flag(false);
1795 ipv4_builder.fragment_offset(FragmentOffset::ZERO);
1796
1797 let mut ipv6_builder =
1798 Ipv6PacketBuilder::new(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP, IP_TTL, proto_v6);
1799 ipv6_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
1800 ipv6_builder.flowlabel(0);
1801
1802 (ipv4_builder, ipv6_builder)
1803 }
1804
1805 fn create_tcp_ipv4_and_ipv6_pkt()
1806 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
1807 use crate::tcp::TcpSegmentBuilder;
1808 use core::num::NonZeroU16;
1809
1810 let tcp_src_port: NonZeroU16 = NonZeroU16::new(20).unwrap();
1811 let tcp_dst_port: NonZeroU16 = NonZeroU16::new(30).unwrap();
1812 const TCP_SEQ_NUM: u32 = 4321;
1813 const TCP_ACK_NUM: Option<u32> = Some(1234);
1814 const TCP_WINDOW_SIZE: u16 = 12345;
1815 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1816
1817 let (ipv4_builder, ipv6_builder) =
1818 create_ipv4_and_ipv6_builders(IpProto::Tcp.into(), IpProto::Tcp.into());
1819
1820 let tcp_builder = TcpSegmentBuilder::new(
1821 DEFAULT_SRC_IP,
1822 DEFAULT_DST_IP,
1823 tcp_src_port,
1824 tcp_dst_port,
1825 TCP_SEQ_NUM,
1826 TCP_ACK_NUM,
1827 TCP_WINDOW_SIZE,
1828 );
1829
1830 let v4_pkt_buf = (&PAYLOAD)
1831 .into_serializer()
1832 .wrap_in(tcp_builder)
1833 .wrap_in(ipv4_builder)
1834 .serialize_vec_outer(&mut NoOpSerializationContext)
1835 .unwrap();
1836
1837 let v6_tcp_builder = TcpSegmentBuilder::new(
1838 DEFAULT_V6_SRC_IP,
1839 DEFAULT_V6_DST_IP,
1840 tcp_src_port,
1841 tcp_dst_port,
1842 TCP_SEQ_NUM,
1843 TCP_ACK_NUM,
1844 TCP_WINDOW_SIZE,
1845 );
1846
1847 let v6_pkt_buf = (&PAYLOAD)
1848 .into_serializer()
1849 .wrap_in(v6_tcp_builder)
1850 .wrap_in(ipv6_builder)
1851 .serialize_vec_outer(&mut NoOpSerializationContext)
1852 .unwrap();
1853
1854 (v4_pkt_buf, v6_pkt_buf)
1855 }
1856
1857 #[test]
1858 fn test_nat64_translate_tcp() {
1859 let (mut v4_pkt_buf, expected_v6_pkt_buf) = create_tcp_ipv4_and_ipv6_pkt();
1860
1861 let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1862 let nat64_translation_result =
1863 parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1864
1865 let serializable_pkt = match nat64_translation_result {
1866 Nat64TranslationResult::Forward(s) => s,
1867 _ => panic!("Nat64TranslationResult not of Forward type!"),
1868 };
1869
1870 let translated_v6_pkt_buf =
1871 serializable_pkt.serialize_vec_outer(&mut NoOpSerializationContext).unwrap();
1872
1873 assert_eq!(
1874 expected_v6_pkt_buf.to_flattened_vec(),
1875 translated_v6_pkt_buf.to_flattened_vec()
1876 );
1877 }
1878
1879 fn create_udp_ipv4_and_ipv6_pkt()
1880 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
1881 use crate::udp::UdpPacketBuilder;
1882 use core::num::NonZeroU16;
1883
1884 let udp_src_port: NonZeroU16 = NonZeroU16::new(35000).unwrap();
1885 let udp_dst_port: NonZeroU16 = NonZeroU16::new(53).unwrap();
1886 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1887
1888 let (ipv4_builder, ipv6_builder) =
1889 create_ipv4_and_ipv6_builders(IpProto::Udp.into(), IpProto::Udp.into());
1890
1891 let udp_builder =
1892 UdpPacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, Some(udp_src_port), udp_dst_port);
1893
1894 let v4_pkt_buf = (&PAYLOAD)
1895 .into_serializer()
1896 .wrap_in(udp_builder)
1897 .wrap_in(ipv4_builder)
1898 .serialize_vec_outer(&mut NoOpSerializationContext)
1899 .unwrap();
1900
1901 let v6_udp_builder = UdpPacketBuilder::new(
1902 DEFAULT_V6_SRC_IP,
1903 DEFAULT_V6_DST_IP,
1904 Some(udp_src_port),
1905 udp_dst_port,
1906 );
1907
1908 let v6_pkt_buf = (&PAYLOAD)
1909 .into_serializer()
1910 .wrap_in(v6_udp_builder)
1911 .wrap_in(ipv6_builder)
1912 .serialize_vec_outer(&mut NoOpSerializationContext)
1913 .unwrap();
1914
1915 (v4_pkt_buf, v6_pkt_buf)
1916 }
1917
1918 #[test]
1919 fn test_nat64_translate_udp() {
1920 let (mut v4_pkt_buf, expected_v6_pkt_buf) = create_udp_ipv4_and_ipv6_pkt();
1921
1922 let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1923 let nat64_translation_result =
1924 parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1925
1926 let serializable_pkt = match nat64_translation_result {
1927 Nat64TranslationResult::Forward(s) => s,
1928 _ => panic!(
1929 "Nat64TranslationResult not of Forward type: {:?} ",
1930 nat64_translation_result
1931 ),
1932 };
1933
1934 let translated_v6_pkt_buf =
1935 serializable_pkt.serialize_vec_outer(&mut NoOpSerializationContext).unwrap();
1936
1937 assert_eq!(
1938 expected_v6_pkt_buf.to_flattened_vec(),
1939 translated_v6_pkt_buf.to_flattened_vec()
1940 );
1941 }
1942
1943 #[test]
1944 fn test_nat64_translate_non_tcp_udp_icmp() {
1945 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1946
1947 let (ipv4_builder, ipv6_builder) =
1948 create_ipv4_and_ipv6_builders(Ipv4Proto::Other(50), Ipv6Proto::Other(50));
1949
1950 let mut v4_pkt_buf = (&PAYLOAD)
1951 .into_serializer()
1952 .wrap_in(ipv4_builder)
1953 .serialize_vec_outer(&mut NoOpSerializationContext)
1954 .unwrap();
1955
1956 let expected_v6_pkt_buf = (&PAYLOAD)
1957 .into_serializer()
1958 .wrap_in(ipv6_builder)
1959 .serialize_vec_outer(&mut NoOpSerializationContext)
1960 .unwrap();
1961
1962 let translated_v6_pkt_buf = {
1963 let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1964
1965 let nat64_translation_result =
1966 parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1967
1968 let serializable_pkt = match nat64_translation_result {
1969 Nat64TranslationResult::Forward(s) => s,
1970 _ => panic!(
1971 "Nat64TranslationResult not of Forward type: {:?} ",
1972 nat64_translation_result
1973 ),
1974 };
1975
1976 let translated_buf =
1977 serializable_pkt.serialize_vec_outer(&mut NoOpSerializationContext).unwrap();
1978
1979 translated_buf
1980 };
1981
1982 assert_eq!(
1983 expected_v6_pkt_buf.to_flattened_vec(),
1984 translated_v6_pkt_buf.to_flattened_vec()
1985 );
1986 }
1987
1988 #[test]
1989 fn test_partial_serialize_parsed() {
1990 const PACKET_BYTES: &[u8] = &[
1991 69, 75, 0, 30, 4, 5, 102, 7, 64, 6, 0, 112, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 3, 4,
1992 5, 7, 8, 9,
1993 ];
1994 const PACKET_LEN: usize = PACKET_BYTES.len();
1995 let mut packet_bytes_copy = Vec::from(PACKET_BYTES);
1996 let mut packet_bytes_ref: &mut [u8] = &mut packet_bytes_copy[..];
1997 let packet = packet_bytes_ref.parse::<Ipv4Packet<_>>().unwrap();
1998
1999 let buf = assert_matches!(
2000 packet.partial_serialize(&mut NoOpSerializationContext, packet::new_buf_vec),
2001 Ok(PartialSerializeResult::NewBuffer { buffer, total_size: PACKET_LEN }) => buffer
2002 );
2003 assert_eq!(buf.as_ref(), PACKET_BYTES);
2004 }
2005}