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
796pub type Options<B> = packet::records::options::Options<B, Ipv4OptionsImpl>;
802
803#[derive(Debug)]
806pub struct Ipv4OptionsTooLongError;
807
808#[derive(Debug, Clone)]
810pub struct Ipv4PacketBuilderWithOptions<'a, I> {
811 prefix_builder: Ipv4PacketBuilder,
812 options: OptionSequenceBuilder<Ipv4Option<'a>, I>,
813}
814
815impl<'a, I> Ipv4PacketBuilderWithOptions<'a, I>
816where
817 I: Iterator + Clone,
818 I::Item: Borrow<Ipv4Option<'a>>,
819{
820 pub fn new<T: IntoIterator<IntoIter = I>>(
826 prefix_builder: Ipv4PacketBuilder,
827 options: T,
828 ) -> Result<Ipv4PacketBuilderWithOptions<'a, I>, Ipv4OptionsTooLongError> {
829 let options = OptionSequenceBuilder::new(options.into_iter());
830 if options.serialized_len() > MAX_OPTIONS_LEN {
831 return Err(Ipv4OptionsTooLongError);
832 }
833 Ok(Ipv4PacketBuilderWithOptions { prefix_builder, options })
834 }
835
836 fn aligned_options_len(&self) -> usize {
837 crate::utils::round_to_next_multiple_of_four(self.options.serialized_len())
839 }
840
841 pub fn prefix_builder(&self) -> &Ipv4PacketBuilder {
843 &self.prefix_builder
844 }
845
846 pub fn prefix_builder_mut(&mut self) -> &mut Ipv4PacketBuilder {
848 &mut self.prefix_builder
849 }
850
851 pub fn options(&self) -> &I {
853 self.options.records()
854 }
855
856 pub fn with_fragment_options(
862 self,
863 first_fragment: bool,
864 ) -> Ipv4PacketBuilderWithOptions<'a, impl Iterator<Item: Borrow<Ipv4Option<'a>>> + Clone> {
865 let Self { prefix_builder, options } = self;
866 Ipv4PacketBuilderWithOptions {
867 prefix_builder,
868 options: OptionSequenceBuilder::new(
871 options
872 .records()
873 .clone()
874 .filter(move |opt| first_fragment || opt.borrow().copied()),
875 ),
876 }
877 }
878}
879
880impl<'a, B> Ipv4PacketBuilderWithOptions<'a, RecordsIter<'a, B, Ipv4OptionsImpl>> {
881 pub fn new_with_records_iter(
884 prefix_builder: Ipv4PacketBuilder,
885 iter: RecordsIter<'a, B, Ipv4OptionsImpl>,
886 ) -> Self {
887 Self { prefix_builder, options: OptionSequenceBuilder::new(iter) }
888 }
889}
890
891impl<'a, I> NestablePacketBuilder for Ipv4PacketBuilderWithOptions<'a, I>
892where
893 I: Iterator + Clone,
894 I::Item: Borrow<Ipv4Option<'a>>,
895{
896 fn constraints(&self) -> PacketConstraints {
897 let header_len = IPV4_MIN_HDR_LEN + self.aligned_options_len();
898 assert_eq!(header_len % 4, 0);
899 PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
900 }
901}
902
903impl<'a, I, C: IpSerializationContext<Ipv4>> PacketBuilder<C>
904 for Ipv4PacketBuilderWithOptions<'a, I>
905where
906 I: Iterator + Clone,
907 I::Item: Borrow<Ipv4Option<'a>>,
908{
909 fn context_state(&self) -> C::ContextState {
910 C::envelope_to_state(IpEnvelope::new(true))
911 }
912
913 fn serialize(
914 &self,
915 context: &mut C,
916 target: &mut SerializeTarget<'_>,
917 body: FragmentedBytesMut<'_, '_>,
918 ) {
919 let opt_len = self.aligned_options_len();
920 let mut header = &mut &mut target.header[..];
926 let opts = header.take_back_zero(opt_len).expect("too few bytes for Ipv4 options");
927 let Ipv4PacketBuilderWithOptions { prefix_builder, options } = self;
928 options.serialize_into(opts);
929 prefix_builder.serialize(context, target, body);
930 }
931}
932
933impl<'a, I, C: IpSerializationContext<Ipv4>> PartialPacketBuilder<C>
934 for Ipv4PacketBuilderWithOptions<'a, I>
935where
936 I: Iterator + Clone,
937 I::Item: Borrow<Ipv4Option<'a>>,
938{
939 fn partial_serialize(&self, context: &mut C, body_len: usize, header: &mut [u8]) {
940 let Ipv4PacketBuilderWithOptions { prefix_builder, options } = self;
941 prefix_builder.partial_serialize(context, body_len, header);
942 let options_slice = &mut header[IPV4_MIN_HDR_LEN..];
943 assert_eq!(options_slice.len(), self.aligned_options_len());
944 options.serialize_into(options_slice);
945 }
946}
947
948impl<'a, C: IpSerializationContext<Ipv4>, I> IpPacketBuilder<C, Ipv4>
949 for Ipv4PacketBuilderWithOptions<'a, I>
950where
951 I: Default + Debug + Clone + Iterator<Item: Borrow<Ipv4Option<'a>>>,
952{
953 fn new(src_ip: Ipv4Addr, dst_ip: Ipv4Addr, ttl: u8, proto: Ipv4Proto) -> Self {
954 Ipv4PacketBuilderWithOptions::new(
955 Ipv4PacketBuilder::new(src_ip, dst_ip, ttl, proto),
956 I::default(),
957 )
958 .expect("packet builder with no options should be valid")
959 }
960
961 fn src_ip(&self) -> Ipv4Addr {
962 self.prefix_builder.src_ip
963 }
964
965 fn set_src_ip(&mut self, addr: Ipv4Addr) {
966 <Ipv4PacketBuilder as IpPacketBuilder<C, Ipv4>>::set_src_ip(&mut self.prefix_builder, addr)
967 }
968
969 fn dst_ip(&self) -> Ipv4Addr {
970 self.prefix_builder.dst_ip
971 }
972
973 fn set_dst_ip(&mut self, addr: Ipv4Addr) {
974 <Ipv4PacketBuilder as IpPacketBuilder<C, Ipv4>>::set_dst_ip(&mut self.prefix_builder, addr)
975 }
976
977 fn proto(&self) -> Ipv4Proto {
978 self.prefix_builder.proto
979 }
980
981 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
982 <Ipv4PacketBuilder as IpPacketBuilder<C, Ipv4>>::set_dscp_and_ecn(
983 &mut self.prefix_builder,
984 dscp_and_ecn,
985 )
986 }
987}
988
989#[derive(Debug, Clone, Eq, PartialEq)]
991pub struct Ipv4PacketBuilder {
992 id: u16,
993 dscp_and_ecn: DscpAndEcn,
994 flags: u8,
995 frag_off: u16,
996 ttl: u8,
997 proto: Ipv4Proto,
998 src_ip: Ipv4Addr,
999 dst_ip: Ipv4Addr,
1000}
1001
1002impl Ipv4PacketBuilder {
1003 pub fn new<S: Into<Ipv4Addr>, D: Into<Ipv4Addr>>(
1005 src_ip: S,
1006 dst_ip: D,
1007 ttl: u8,
1008 proto: Ipv4Proto,
1009 ) -> Ipv4PacketBuilder {
1010 Ipv4PacketBuilder {
1011 id: 0,
1012 dscp_and_ecn: DscpAndEcn::default(),
1013 flags: 0,
1014 frag_off: 0,
1015 ttl,
1016 proto: proto,
1017 src_ip: src_ip.into(),
1018 dst_ip: dst_ip.into(),
1019 }
1020 }
1021
1022 pub fn dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1024 self.dscp_and_ecn = dscp_and_ecn;
1025 }
1026
1027 pub fn id(&mut self, id: u16) {
1029 self.id = id
1030 }
1031
1032 pub fn df_flag(&mut self, df: bool) {
1034 if df {
1035 self.flags |= 1 << DF_FLAG_OFFSET;
1036 } else {
1037 self.flags &= !(1 << DF_FLAG_OFFSET);
1038 }
1039 }
1040
1041 pub fn mf_flag(&mut self, mf: bool) {
1043 if mf {
1044 self.flags |= 1 << MF_FLAG_OFFSET;
1045 } else {
1046 self.flags &= !(1 << MF_FLAG_OFFSET);
1047 }
1048 }
1049
1050 pub fn fragment_offset(&mut self, fragment_offset: FragmentOffset) {
1052 self.frag_off = fragment_offset.into_raw();
1053 }
1054
1055 pub fn read_df_flag(&self) -> bool {
1057 (self.flags & (1 << DF_FLAG_OFFSET)) != 0
1058 }
1059
1060 fn get_header_prefix(&self, header_len: usize, total_len: usize) -> HeaderPrefix {
1061 assert_eq!(header_len % 4, 0);
1062 let ihl: u8 = u8::try_from(header_len / 4).expect("Header too large");
1063
1064 let id = if ((self.flags & (1 << DF_FLAG_OFFSET)) == 0)
1074 || ((self.flags & (1 << MF_FLAG_OFFSET)) == 1)
1075 || (self.frag_off > 0)
1076 {
1077 self.id
1078 } else {
1079 0
1080 };
1081
1082 HeaderPrefix::new(
1083 ihl,
1084 self.dscp_and_ecn,
1085 {
1086 debug_assert!(total_len <= u16::MAX as usize);
1092 total_len as u16
1093 },
1094 id,
1095 self.flags,
1096 self.frag_off,
1097 self.ttl,
1098 self.proto.into(),
1099 [0, 0], self.src_ip,
1101 self.dst_ip,
1102 )
1103 }
1104}
1105
1106impl NestablePacketBuilder for Ipv4PacketBuilder {
1107 fn constraints(&self) -> PacketConstraints {
1108 PacketConstraints::new(IPV4_MIN_HDR_LEN, 0, 0, (1 << 16) - 1 - IPV4_MIN_HDR_LEN)
1109 }
1110}
1111
1112impl<C: IpSerializationContext<Ipv4>> PacketBuilder<C> for Ipv4PacketBuilder {
1113 fn context_state(&self) -> C::ContextState {
1114 C::envelope_to_state(IpEnvelope::new(false))
1115 }
1116
1117 fn serialize(
1118 &self,
1119 _context: &mut C,
1120 target: &mut SerializeTarget<'_>,
1121 body: FragmentedBytesMut<'_, '_>,
1122 ) {
1123 let header_len = target.header.len();
1124 let total_len = header_len + body.len();
1125 let mut hdr_prefix = self.get_header_prefix(header_len, total_len);
1126 let options = &target.header[HDR_PREFIX_LEN..];
1127 let checksum = compute_header_checksum(hdr_prefix.as_bytes(), options);
1128 hdr_prefix.hdr_checksum = checksum;
1129 let mut header = &mut target.header;
1130 header.write_obj_front(&hdr_prefix).expect("too few bytes for IPv4 header prefix");
1131 }
1132}
1133
1134impl<C: IpSerializationContext<Ipv4>> PartialPacketBuilder<C> for Ipv4PacketBuilder {
1135 fn partial_serialize(&self, _context: &mut C, body_len: usize, mut header: &mut [u8]) {
1136 let total_len = header.len() + body_len;
1137 let hdr_prefix = self.get_header_prefix(header.len(), total_len);
1138 (&mut header).write_obj_front(&hdr_prefix).expect("too few bytes for IPv4 header prefix");
1139 }
1140}
1141
1142impl<C: IpSerializationContext<Ipv4>> IpPacketBuilder<C, Ipv4> for Ipv4PacketBuilder {
1143 fn new(src_ip: Ipv4Addr, dst_ip: Ipv4Addr, ttl: u8, proto: Ipv4Proto) -> Self {
1144 Ipv4PacketBuilder::new(src_ip, dst_ip, ttl, proto)
1145 }
1146
1147 fn src_ip(&self) -> Ipv4Addr {
1148 self.src_ip
1149 }
1150
1151 fn set_src_ip(&mut self, addr: Ipv4Addr) {
1152 self.src_ip = addr;
1153 }
1154
1155 fn dst_ip(&self) -> Ipv4Addr {
1156 self.dst_ip
1157 }
1158
1159 fn set_dst_ip(&mut self, addr: Ipv4Addr) {
1160 self.dst_ip = addr;
1161 }
1162
1163 fn proto(&self) -> Ipv4Proto {
1164 self.proto
1165 }
1166
1167 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1168 self.dscp_and_ecn = dscp_and_ecn;
1169 }
1170}
1171
1172const DF_FLAG_OFFSET: u8 = 1;
1174const MF_FLAG_OFFSET: u8 = 0;
1175
1176pub(crate) fn reassemble_fragmented_packet<
1182 'a,
1183 B: SplitByteSliceMut,
1184 BV: BufferViewMut<B>,
1185 I: Iterator<Item = &'a [u8]>,
1186>(
1187 mut buffer: BV,
1188 header: &[u8],
1189 body_fragments: I,
1190) -> Result<(), ParseError> {
1191 assert!(header.len() >= HDR_PREFIX_LEN);
1192
1193 let bytes = buffer.as_mut();
1194
1195 bytes[0..header.len()].copy_from_slice(header);
1197 let mut byte_count = header.len();
1198
1199 for p in body_fragments {
1201 bytes[byte_count..byte_count + p.len()].copy_from_slice(p);
1202 byte_count += p.len();
1203 }
1204
1205 if byte_count > usize::from(u16::MAX) {
1210 return debug_err!(
1211 Err(ParseError::Format),
1212 "fragmented packet length of {} bytes is too large",
1213 byte_count
1214 );
1215 }
1216
1217 let mut header_ref = Ref::<_, HeaderPrefix>::from_prefix(bytes).unwrap().0;
1220
1221 let options_bytes = &header[HDR_PREFIX_LEN..header.len()];
1222
1223 header_ref.total_len.set(u16::try_from(byte_count).unwrap());
1225
1226 header_ref.flags_frag_off = [0; 2];
1229
1230 header_ref.hdr_checksum = [0; 2];
1232 header_ref.hdr_checksum = compute_header_checksum(header_ref.as_bytes(), options_bytes);
1233
1234 Ok(())
1235}
1236
1237pub mod options {
1239 use byteorder::{ByteOrder, NetworkEndian};
1240 use packet::BufferViewMut;
1241 use packet::records::options::{
1242 OptionBuilder, OptionLayout, OptionParseErr, OptionParseLayout, OptionsImpl,
1243 };
1244 use zerocopy::byteorder::network_endian::U16;
1245
1246 const OPTION_KIND_EOL: u8 = 0;
1247 const OPTION_KIND_NOP: u8 = 1;
1248 const OPTION_KIND_RTRALRT: u8 = 148;
1249
1250 const OPTION_RTRALRT_LEN: usize = 2;
1251
1252 #[derive(PartialEq, Eq, Debug, Clone)]
1259 #[allow(missing_docs)]
1260 pub enum Ipv4Option<'a> {
1261 RouterAlert { data: u16 },
1267
1268 Unrecognized { kind: u8, data: &'a [u8] },
1280 }
1281
1282 impl<'a> Ipv4Option<'a> {
1283 pub fn copied(&self) -> bool {
1285 match self {
1286 Ipv4Option::RouterAlert { .. } => true,
1290 Ipv4Option::Unrecognized { kind, .. } => *kind & (1 << 7) != 0,
1291 }
1292 }
1293 }
1294
1295 #[derive(Debug, Clone)]
1297 pub struct Ipv4OptionsImpl;
1298
1299 impl OptionLayout for Ipv4OptionsImpl {
1300 type KindLenField = u8;
1301 }
1302
1303 impl OptionParseLayout for Ipv4OptionsImpl {
1304 type Error = OptionParseErr;
1305 const END_OF_OPTIONS: Option<u8> = Some(0);
1306 const NOP: Option<u8> = Some(1);
1307 }
1308
1309 impl OptionsImpl for Ipv4OptionsImpl {
1310 type Option<'a> = Ipv4Option<'a>;
1311
1312 fn parse<'a>(kind: u8, data: &'a [u8]) -> Result<Option<Ipv4Option<'a>>, OptionParseErr> {
1313 match kind {
1314 self::OPTION_KIND_EOL | self::OPTION_KIND_NOP => {
1315 unreachable!("records::options::Options promises to handle EOL and NOP")
1316 }
1317 self::OPTION_KIND_RTRALRT => {
1318 if data.len() == OPTION_RTRALRT_LEN {
1319 Ok(Some(Ipv4Option::RouterAlert { data: NetworkEndian::read_u16(data) }))
1320 } else {
1321 Err(OptionParseErr)
1322 }
1323 }
1324 kind => {
1325 if data.len() > 38 {
1326 Err(OptionParseErr)
1327 } else {
1328 Ok(Some(Ipv4Option::Unrecognized { kind, data }))
1329 }
1330 }
1331 }
1332 }
1333 }
1334
1335 impl<'a> OptionBuilder for Ipv4Option<'a> {
1336 type Layout = Ipv4OptionsImpl;
1337
1338 fn serialized_len(&self) -> usize {
1339 match self {
1340 Ipv4Option::RouterAlert { .. } => OPTION_RTRALRT_LEN,
1341 Ipv4Option::Unrecognized { data, .. } => data.len(),
1342 }
1343 }
1344
1345 fn option_kind(&self) -> u8 {
1346 match self {
1347 Ipv4Option::RouterAlert { .. } => OPTION_KIND_RTRALRT,
1348 Ipv4Option::Unrecognized { kind, .. } => *kind,
1349 }
1350 }
1351
1352 fn serialize_into(&self, mut buffer: &mut [u8]) {
1353 match self {
1354 Ipv4Option::Unrecognized { data, .. } => buffer.copy_from_slice(data),
1355 Ipv4Option::RouterAlert { data } => {
1356 (&mut buffer).write_obj_front(&U16::new(*data)).unwrap()
1357 }
1358 };
1359 }
1360 }
1361
1362 #[cfg(test)]
1363 mod test {
1364 use packet::records::RecordBuilder;
1365 use packet::records::options::Options;
1366
1367 use super::*;
1368
1369 #[test]
1370 fn test_serialize_router_alert() {
1371 let mut buffer = [0u8; 4];
1372 let option = Ipv4Option::RouterAlert { data: 0 };
1373 <Ipv4Option<'_> as RecordBuilder>::serialize_into(&option, &mut buffer);
1374 assert_eq!(buffer[0], 148);
1375 assert_eq!(buffer[1], 4);
1376 assert_eq!(buffer[2], 0);
1377 assert_eq!(buffer[3], 0);
1378 }
1379
1380 #[test]
1381 fn test_parse_router_alert() {
1382 let mut buffer: Vec<u8> = vec![148, 4, 0, 0];
1383 let options = Options::<_, Ipv4OptionsImpl>::parse(buffer.as_mut()).unwrap();
1384 let rtralt = options.iter().next().unwrap();
1385 assert_eq!(rtralt, Ipv4Option::RouterAlert { data: 0 });
1386 }
1387 }
1388}
1389
1390mod inner {
1391 pub const IPV4_MIN_HDR_LEN: usize = super::HDR_PREFIX_LEN;
1393}
1394
1395pub mod testutil {
1397 pub use super::inner::IPV4_MIN_HDR_LEN;
1398
1399 pub const IPV4_TTL_OFFSET: usize = 8;
1401
1402 pub const IPV4_CHECKSUM_OFFSET: usize = 10;
1404}
1405
1406#[cfg(test)]
1407mod tests {
1408 use assert_matches::assert_matches;
1409 use net_types::ethernet::Mac;
1410 use packet::{Buf, FragmentedBuffer, ParseBuffer, PartialSerializeResult};
1411
1412 use super::*;
1413 use crate::ethernet::{
1414 ETHERNET_MIN_BODY_LEN_NO_TAG, EtherType, EthernetFrame, EthernetFrameBuilder,
1415 EthernetFrameLengthCheck,
1416 };
1417 use crate::testutil::*;
1418
1419 const DEFAULT_SRC_MAC: Mac = Mac::new([1, 2, 3, 4, 5, 6]);
1420 const DEFAULT_DST_MAC: Mac = Mac::new([7, 8, 9, 0, 1, 2]);
1421 const DEFAULT_SRC_IP: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1422 const DEFAULT_DST_IP: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1423 const DEFAULT_V6_SRC_IP: Ipv6Addr = Ipv6Addr::new([0x2001, 0x0db8, 0, 0, 0, 0, 0, 1]);
1425 const DEFAULT_V6_DST_IP: Ipv6Addr = Ipv6Addr::new([0x2001, 0x0db8, 0, 0, 0, 0, 0, 2]);
1427
1428 #[test]
1429 fn test_parse_serialize_full_tcp() {
1430 use crate::testdata::tls_client_hello_v4::*;
1431
1432 let mut buf = ETHERNET_FRAME.bytes;
1433 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1434 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1435
1436 let mut body = frame.body();
1437 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1438 verify_ipv4_packet(&packet, IPV4_PACKET);
1439
1440 let buffer = packet
1442 .body()
1443 .into_serializer()
1444 .wrap_in(packet.builder())
1445 .wrap_in(frame.builder())
1446 .serialize_vec_outer(&mut NoOpSerializationContext)
1447 .unwrap();
1448 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1449
1450 assert_eq!(&packet.to_vec()[..], IPV4_PACKET.bytes);
1452 }
1453
1454 #[test]
1455 fn test_parse_serialize_full_udp() {
1456 use crate::testdata::dns_request_v4::*;
1457
1458 let mut buf = ETHERNET_FRAME.bytes;
1459 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1460 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1461
1462 let mut body = frame.body();
1463 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1464 verify_ipv4_packet(&packet, IPV4_PACKET);
1465
1466 let buffer = packet
1468 .body()
1469 .into_serializer()
1470 .wrap_in(packet.builder())
1471 .wrap_in(frame.builder())
1472 .serialize_vec_outer(&mut NoOpSerializationContext)
1473 .unwrap();
1474 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1475
1476 assert_eq!(&packet.to_vec()[..], IPV4_PACKET.bytes);
1478 }
1479
1480 #[test]
1481 fn test_parse_serialize_with_options() {
1482 use crate::testdata::igmpv2_membership::report::*;
1485
1486 let mut buf = IP_PACKET_BYTES;
1487 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1488 assert_eq!(packet.iter_options().count(), 1);
1489
1490 assert_eq!(&packet.to_vec()[..], IP_PACKET_BYTES);
1495 }
1496
1497 fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; 20] {
1498 zerocopy::transmute!(hdr_prefix)
1499 }
1500
1501 fn new_hdr_prefix() -> HeaderPrefix {
1504 HeaderPrefix::new(
1505 5,
1506 DscpAndEcn::default(),
1507 20,
1508 0x0102,
1509 0,
1510 0,
1511 0x03,
1512 IpProto::Tcp.into(),
1513 [0xa6, 0xcf],
1514 DEFAULT_SRC_IP,
1515 DEFAULT_DST_IP,
1516 )
1517 }
1518
1519 #[test]
1520 fn test_parse() {
1521 let mut bytes = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1522 let packet = bytes.parse::<Ipv4Packet<_>>().unwrap();
1523 assert_eq!(packet.id(), 0x0102);
1524 assert_eq!(packet.ttl(), 0x03);
1525 assert_eq!(packet.proto(), IpProto::Tcp.into());
1526 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1527 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1528 assert_eq!(packet.body(), []);
1529 }
1530
1531 #[test]
1532 fn test_parse_padding() {
1533 let mut buffer = Buf::new(Vec::new(), ..)
1535 .wrap_in(Ipv4PacketBuilder::new(DEFAULT_DST_IP, DEFAULT_DST_IP, 0, IpProto::Tcp.into()))
1536 .wrap_in(EthernetFrameBuilder::new(
1537 DEFAULT_SRC_MAC,
1538 DEFAULT_DST_MAC,
1539 EtherType::Ipv4,
1540 ETHERNET_MIN_BODY_LEN_NO_TAG,
1541 ))
1542 .serialize_vec_outer(&mut NoOpSerializationContext)
1543 .unwrap();
1544 let _: EthernetFrame<_> =
1545 buffer.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1546 assert_eq!(buffer.len(), 46);
1549 let packet = buffer.parse::<Ipv4Packet<_>>().unwrap();
1550 assert_eq!(packet.body().len(), 0);
1553 assert_eq!(buffer.len(), 0);
1557 }
1558
1559 #[test]
1560 fn test_parse_error() {
1561 let mut hdr_prefix = new_hdr_prefix();
1563 hdr_prefix.version_ihl = (5 << 4) | 5;
1564 assert_eq!(
1565 (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1566 ParseError::Format.into()
1567 );
1568
1569 let mut hdr_prefix = new_hdr_prefix();
1572 hdr_prefix.version_ihl = (4 << 4) | 4;
1573 assert_eq!(
1574 (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1575 ParseError::Format.into()
1576 );
1577
1578 let mut hdr_prefix = new_hdr_prefix();
1581 hdr_prefix.version_ihl = (4 << 4) | 6;
1582 assert_eq!(
1583 (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1584 ParseError::Format.into()
1585 );
1586 }
1587
1588 fn new_builder() -> Ipv4PacketBuilder {
1590 Ipv4PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, 64, IpProto::Tcp.into())
1591 }
1592
1593 #[test]
1594 fn test_fragment_type() {
1595 fn test_fragment_type_helper(fragment_offset: u16, expect_fragment_type: Ipv4FragmentType) {
1596 let mut builder = new_builder();
1597 builder.fragment_offset(FragmentOffset::new(fragment_offset).unwrap());
1598
1599 let mut buf = [0; IPV4_MIN_HDR_LEN]
1600 .into_serializer()
1601 .wrap_in(builder)
1602 .serialize_vec_outer(&mut NoOpSerializationContext)
1603 .unwrap();
1604
1605 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1606 assert_eq!(packet.fragment_type(), expect_fragment_type);
1607 }
1608
1609 test_fragment_type_helper(0x0000, Ipv4FragmentType::InitialFragment);
1610 test_fragment_type_helper(0x0008, Ipv4FragmentType::NonInitialFragment);
1611 }
1612
1613 #[test]
1614 fn test_serialize() {
1615 let mut builder = new_builder();
1616 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
1617 builder.id(0x0405);
1618 builder.df_flag(true);
1619 builder.mf_flag(true);
1620 builder.fragment_offset(FragmentOffset::new(0x0607).unwrap());
1621
1622 let mut buf = (&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9])
1623 .into_serializer()
1624 .wrap_in(builder)
1625 .serialize_vec_outer(&mut NoOpSerializationContext)
1626 .unwrap();
1627 assert_eq!(
1628 buf.as_ref(),
1629 [
1630 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,
1631 4, 5, 7, 8, 9
1632 ]
1633 );
1634 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1635 assert_eq!(packet.dscp_and_ecn().dscp(), 0x12);
1636 assert_eq!(packet.dscp_and_ecn().ecn(), 3);
1637 assert_eq!(packet.id(), 0x0405);
1638 assert!(packet.df_flag());
1639 assert!(packet.mf_flag());
1640 assert_eq!(packet.fragment_offset().into_raw(), 0x0607);
1641 assert_eq!(packet.fragment_type(), Ipv4FragmentType::NonInitialFragment);
1642 }
1643
1644 #[test]
1645 fn test_partial_serialize() {
1646 let mut builder = new_builder();
1647 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
1648 builder.id(0x0405);
1649 builder.df_flag(true);
1650 builder.mf_flag(true);
1651 builder.fragment_offset(FragmentOffset::new(0x0607).unwrap());
1652 const BODY: &[u8] = &[0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1653 let packet = BODY.into_serializer().wrap_in(builder);
1654 const HEADER: &[u8] = &[69, 75, 0, 30, 4, 5, 102, 7, 64, 6, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8];
1655 const PACKET_LEN: usize = HEADER.len() + BODY.len();
1656
1657 let buf = assert_matches!(
1661 packet.partial_serialize(&mut NoOpSerializationContext, packet::new_buf_vec),
1662 Ok(PartialSerializeResult::NewBuffer { buffer, total_size: PACKET_LEN }) => buffer
1663 );
1664 assert_eq!(buf.as_ref(), HEADER);
1665 }
1666
1667 #[test]
1668 fn test_serialize_id_unset() {
1669 let mut builder = new_builder();
1670 builder.id(0x0405);
1671 builder.df_flag(true);
1672
1673 let mut buf = (&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9])
1674 .into_serializer()
1675 .wrap_in(builder)
1676 .serialize_vec_outer(&mut NoOpSerializationContext)
1677 .unwrap();
1678 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1679 assert_eq!(packet.id(), 0);
1680 assert!(packet.df_flag());
1681 assert_eq!(packet.mf_flag(), false);
1682 assert_eq!(packet.fragment_offset().into_raw(), 0);
1683 assert_eq!(packet.fragment_type(), Ipv4FragmentType::InitialFragment);
1684 }
1685
1686 #[test]
1687 fn test_serialize_zeroes() {
1688 let mut buf_0 = [0; IPV4_MIN_HDR_LEN];
1691 let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], IPV4_MIN_HDR_LEN..)
1692 .wrap_in(new_builder())
1693 .serialize_vec_outer(&mut NoOpSerializationContext)
1694 .unwrap()
1695 .unwrap_a();
1696 let mut buf_1 = [0xFF; IPV4_MIN_HDR_LEN];
1697 let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], IPV4_MIN_HDR_LEN..)
1698 .wrap_in(new_builder())
1699 .serialize_vec_outer(&mut NoOpSerializationContext)
1700 .unwrap()
1701 .unwrap_a();
1702 assert_eq!(buf_0, buf_1);
1703 }
1704
1705 #[test]
1706 #[should_panic(expected = "(SizeLimitExceeded, Nested { inner: Buf { buf:")]
1707 fn test_serialize_panic_packet_length() {
1708 let _: Buf<&mut [u8]> = Buf::new(&mut [0; (1 << 16) - IPV4_MIN_HDR_LEN][..], ..)
1710 .wrap_in(new_builder())
1711 .serialize_vec_outer(&mut NoOpSerializationContext)
1712 .unwrap()
1713 .unwrap_a();
1714 }
1715
1716 #[test]
1717 fn test_copy_header_bytes_for_fragment() {
1718 let hdr_prefix = new_hdr_prefix();
1719 let mut bytes = hdr_prefix_to_bytes(hdr_prefix);
1720 let mut buf = &bytes[..];
1721 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1722 let copied_bytes = packet.copy_header_bytes_for_fragment();
1723 bytes[IPV4_FRAGMENT_DATA_BYTE_RANGE].copy_from_slice(&[0; 4][..]);
1724 assert_eq!(&copied_bytes[..], &bytes[..]);
1725 }
1726
1727 #[test]
1728 fn test_partial_parsing() {
1729 use core::ops::Deref as _;
1730
1731 let mut hdr_prefix = new_hdr_prefix();
1734 hdr_prefix.total_len = U16::new(256);
1735 let mut bytes = hdr_prefix_to_bytes(hdr_prefix)[..].to_owned();
1736 const PAYLOAD: &[u8] = &[1, 2, 3, 4, 5];
1737 bytes.extend(PAYLOAD);
1738 let mut buf = &bytes[..];
1739 let packet = buf.parse::<Ipv4PacketRaw<_>>().unwrap();
1740 let Ipv4PacketRaw { hdr_prefix, options, body } = &packet;
1741 assert_eq!(Ref::bytes(&hdr_prefix), &bytes[0..20]);
1742 assert_eq!(options.as_ref().complete().unwrap().deref(), []);
1743 assert_eq!(body, &MaybeParsed::Incomplete(PAYLOAD));
1745 assert!(Ipv4Packet::try_from_raw(packet).is_err());
1747
1748 let mut hdr_prefix = new_hdr_prefix();
1750 hdr_prefix.version_ihl = (4 << 4) | 10;
1751 let bytes = hdr_prefix_to_bytes(hdr_prefix);
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);
1756 assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
1757 assert_eq!(body.complete().unwrap(), []);
1758 assert!(Ipv4Packet::try_from_raw(packet).is_err());
1760
1761 let hdr_prefix = new_hdr_prefix();
1763 let bytes = &hdr_prefix_to_bytes(hdr_prefix);
1764 let mut buf = &bytes[0..10];
1765 assert!(buf.parse::<Ipv4PacketRaw<_>>().is_err());
1766 }
1767
1768 fn create_ipv4_and_ipv6_builders(
1769 proto_v4: Ipv4Proto,
1770 proto_v6: Ipv6Proto,
1771 ) -> (Ipv4PacketBuilder, Ipv6PacketBuilder) {
1772 const IP_DSCP_AND_ECN: DscpAndEcn = DscpAndEcn::new(0x12, 3);
1773 const IP_TTL: u8 = 64;
1774
1775 let mut ipv4_builder =
1776 Ipv4PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, IP_TTL, proto_v4);
1777 ipv4_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
1778 ipv4_builder.id(0x0405);
1779 ipv4_builder.df_flag(true);
1780 ipv4_builder.mf_flag(false);
1781 ipv4_builder.fragment_offset(FragmentOffset::ZERO);
1782
1783 let mut ipv6_builder =
1784 Ipv6PacketBuilder::new(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP, IP_TTL, proto_v6);
1785 ipv6_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
1786 ipv6_builder.flowlabel(0);
1787
1788 (ipv4_builder, ipv6_builder)
1789 }
1790
1791 fn create_tcp_ipv4_and_ipv6_pkt()
1792 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
1793 use crate::tcp::TcpSegmentBuilder;
1794 use core::num::NonZeroU16;
1795
1796 let tcp_src_port: NonZeroU16 = NonZeroU16::new(20).unwrap();
1797 let tcp_dst_port: NonZeroU16 = NonZeroU16::new(30).unwrap();
1798 const TCP_SEQ_NUM: u32 = 4321;
1799 const TCP_ACK_NUM: Option<u32> = Some(1234);
1800 const TCP_WINDOW_SIZE: u16 = 12345;
1801 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1802
1803 let (ipv4_builder, ipv6_builder) =
1804 create_ipv4_and_ipv6_builders(IpProto::Tcp.into(), IpProto::Tcp.into());
1805
1806 let tcp_builder = TcpSegmentBuilder::new(
1807 DEFAULT_SRC_IP,
1808 DEFAULT_DST_IP,
1809 tcp_src_port,
1810 tcp_dst_port,
1811 TCP_SEQ_NUM,
1812 TCP_ACK_NUM,
1813 TCP_WINDOW_SIZE,
1814 );
1815
1816 let v4_pkt_buf = (&PAYLOAD)
1817 .into_serializer()
1818 .wrap_in(tcp_builder)
1819 .wrap_in(ipv4_builder)
1820 .serialize_vec_outer(&mut NoOpSerializationContext)
1821 .unwrap();
1822
1823 let v6_tcp_builder = TcpSegmentBuilder::new(
1824 DEFAULT_V6_SRC_IP,
1825 DEFAULT_V6_DST_IP,
1826 tcp_src_port,
1827 tcp_dst_port,
1828 TCP_SEQ_NUM,
1829 TCP_ACK_NUM,
1830 TCP_WINDOW_SIZE,
1831 );
1832
1833 let v6_pkt_buf = (&PAYLOAD)
1834 .into_serializer()
1835 .wrap_in(v6_tcp_builder)
1836 .wrap_in(ipv6_builder)
1837 .serialize_vec_outer(&mut NoOpSerializationContext)
1838 .unwrap();
1839
1840 (v4_pkt_buf, v6_pkt_buf)
1841 }
1842
1843 #[test]
1844 fn test_nat64_translate_tcp() {
1845 let (mut v4_pkt_buf, expected_v6_pkt_buf) = create_tcp_ipv4_and_ipv6_pkt();
1846
1847 let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1848 let nat64_translation_result =
1849 parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1850
1851 let serializable_pkt = match nat64_translation_result {
1852 Nat64TranslationResult::Forward(s) => s,
1853 _ => panic!("Nat64TranslationResult not of Forward type!"),
1854 };
1855
1856 let translated_v6_pkt_buf =
1857 serializable_pkt.serialize_vec_outer(&mut NoOpSerializationContext).unwrap();
1858
1859 assert_eq!(
1860 expected_v6_pkt_buf.to_flattened_vec(),
1861 translated_v6_pkt_buf.to_flattened_vec()
1862 );
1863 }
1864
1865 fn create_udp_ipv4_and_ipv6_pkt()
1866 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
1867 use crate::udp::UdpPacketBuilder;
1868 use core::num::NonZeroU16;
1869
1870 let udp_src_port: NonZeroU16 = NonZeroU16::new(35000).unwrap();
1871 let udp_dst_port: NonZeroU16 = NonZeroU16::new(53).unwrap();
1872 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1873
1874 let (ipv4_builder, ipv6_builder) =
1875 create_ipv4_and_ipv6_builders(IpProto::Udp.into(), IpProto::Udp.into());
1876
1877 let udp_builder =
1878 UdpPacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, Some(udp_src_port), udp_dst_port);
1879
1880 let v4_pkt_buf = (&PAYLOAD)
1881 .into_serializer()
1882 .wrap_in(udp_builder)
1883 .wrap_in(ipv4_builder)
1884 .serialize_vec_outer(&mut NoOpSerializationContext)
1885 .unwrap();
1886
1887 let v6_udp_builder = UdpPacketBuilder::new(
1888 DEFAULT_V6_SRC_IP,
1889 DEFAULT_V6_DST_IP,
1890 Some(udp_src_port),
1891 udp_dst_port,
1892 );
1893
1894 let v6_pkt_buf = (&PAYLOAD)
1895 .into_serializer()
1896 .wrap_in(v6_udp_builder)
1897 .wrap_in(ipv6_builder)
1898 .serialize_vec_outer(&mut NoOpSerializationContext)
1899 .unwrap();
1900
1901 (v4_pkt_buf, v6_pkt_buf)
1902 }
1903
1904 #[test]
1905 fn test_nat64_translate_udp() {
1906 let (mut v4_pkt_buf, expected_v6_pkt_buf) = create_udp_ipv4_and_ipv6_pkt();
1907
1908 let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1909 let nat64_translation_result =
1910 parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1911
1912 let serializable_pkt = match nat64_translation_result {
1913 Nat64TranslationResult::Forward(s) => s,
1914 _ => panic!(
1915 "Nat64TranslationResult not of Forward type: {:?} ",
1916 nat64_translation_result
1917 ),
1918 };
1919
1920 let translated_v6_pkt_buf =
1921 serializable_pkt.serialize_vec_outer(&mut NoOpSerializationContext).unwrap();
1922
1923 assert_eq!(
1924 expected_v6_pkt_buf.to_flattened_vec(),
1925 translated_v6_pkt_buf.to_flattened_vec()
1926 );
1927 }
1928
1929 #[test]
1930 fn test_nat64_translate_non_tcp_udp_icmp() {
1931 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1932
1933 let (ipv4_builder, ipv6_builder) =
1934 create_ipv4_and_ipv6_builders(Ipv4Proto::Other(50), Ipv6Proto::Other(50));
1935
1936 let mut v4_pkt_buf = (&PAYLOAD)
1937 .into_serializer()
1938 .wrap_in(ipv4_builder)
1939 .serialize_vec_outer(&mut NoOpSerializationContext)
1940 .unwrap();
1941
1942 let expected_v6_pkt_buf = (&PAYLOAD)
1943 .into_serializer()
1944 .wrap_in(ipv6_builder)
1945 .serialize_vec_outer(&mut NoOpSerializationContext)
1946 .unwrap();
1947
1948 let translated_v6_pkt_buf = {
1949 let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1950
1951 let nat64_translation_result =
1952 parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1953
1954 let serializable_pkt = match nat64_translation_result {
1955 Nat64TranslationResult::Forward(s) => s,
1956 _ => panic!(
1957 "Nat64TranslationResult not of Forward type: {:?} ",
1958 nat64_translation_result
1959 ),
1960 };
1961
1962 let translated_buf =
1963 serializable_pkt.serialize_vec_outer(&mut NoOpSerializationContext).unwrap();
1964
1965 translated_buf
1966 };
1967
1968 assert_eq!(
1969 expected_v6_pkt_buf.to_flattened_vec(),
1970 translated_v6_pkt_buf.to_flattened_vec()
1971 );
1972 }
1973
1974 #[test]
1975 fn test_partial_serialize_parsed() {
1976 const PACKET_BYTES: &[u8] = &[
1977 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,
1978 5, 7, 8, 9,
1979 ];
1980 const PACKET_LEN: usize = PACKET_BYTES.len();
1981 let mut packet_bytes_copy = Vec::from(PACKET_BYTES);
1982 let mut packet_bytes_ref: &mut [u8] = &mut packet_bytes_copy[..];
1983 let packet = packet_bytes_ref.parse::<Ipv4Packet<_>>().unwrap();
1984
1985 let buf = assert_matches!(
1986 packet.partial_serialize(&mut NoOpSerializationContext, packet::new_buf_vec),
1987 Ok(PartialSerializeResult::NewBuffer { buffer, total_size: PACKET_LEN }) => buffer
1988 );
1989 assert_eq!(buf.as_ref(), PACKET_BYTES);
1990 }
1991}