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 <= core::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 B: SplitByteSliceMut,
1183 BV: BufferViewMut<B>,
1184 I: Iterator<Item = Vec<u8>>,
1185>(
1186 mut buffer: BV,
1187 header: Vec<u8>,
1188 body_fragments: I,
1189) -> Result<(), ParseError> {
1190 assert!(header.len() >= HDR_PREFIX_LEN);
1191
1192 let bytes = buffer.as_mut();
1193
1194 bytes[0..header.len()].copy_from_slice(&header[..]);
1196 let mut byte_count = header.len();
1197
1198 for p in body_fragments {
1200 bytes[byte_count..byte_count + p.len()].copy_from_slice(&p[..]);
1201 byte_count += p.len();
1202 }
1203
1204 if byte_count > usize::from(core::u16::MAX) {
1209 return debug_err!(
1210 Err(ParseError::Format),
1211 "fragmented packet length of {} bytes is too large",
1212 byte_count
1213 );
1214 }
1215
1216 let mut header_ref = Ref::<_, HeaderPrefix>::from_prefix(bytes).unwrap().0;
1219
1220 let options_bytes = &header[HDR_PREFIX_LEN..header.len()];
1221
1222 header_ref.total_len.set(u16::try_from(byte_count).unwrap());
1224
1225 header_ref.flags_frag_off = [0; 2];
1228
1229 header_ref.hdr_checksum = [0; 2];
1231 header_ref.hdr_checksum = compute_header_checksum(header_ref.as_bytes(), options_bytes);
1232
1233 Ok(())
1234}
1235
1236pub mod options {
1238 use byteorder::{ByteOrder, NetworkEndian};
1239 use packet::BufferViewMut;
1240 use packet::records::options::{
1241 OptionBuilder, OptionLayout, OptionParseErr, OptionParseLayout, OptionsImpl,
1242 };
1243 use zerocopy::byteorder::network_endian::U16;
1244
1245 const OPTION_KIND_EOL: u8 = 0;
1246 const OPTION_KIND_NOP: u8 = 1;
1247 const OPTION_KIND_RTRALRT: u8 = 148;
1248
1249 const OPTION_RTRALRT_LEN: usize = 2;
1250
1251 #[derive(PartialEq, Eq, Debug, Clone)]
1258 #[allow(missing_docs)]
1259 pub enum Ipv4Option<'a> {
1260 RouterAlert { data: u16 },
1266
1267 Unrecognized { kind: u8, data: &'a [u8] },
1279 }
1280
1281 impl<'a> Ipv4Option<'a> {
1282 pub fn copied(&self) -> bool {
1284 match self {
1285 Ipv4Option::RouterAlert { .. } => true,
1289 Ipv4Option::Unrecognized { kind, .. } => *kind & (1 << 7) != 0,
1290 }
1291 }
1292 }
1293
1294 #[derive(Debug, Clone)]
1296 pub struct Ipv4OptionsImpl;
1297
1298 impl OptionLayout for Ipv4OptionsImpl {
1299 type KindLenField = u8;
1300 }
1301
1302 impl OptionParseLayout for Ipv4OptionsImpl {
1303 type Error = OptionParseErr;
1304 const END_OF_OPTIONS: Option<u8> = Some(0);
1305 const NOP: Option<u8> = Some(1);
1306 }
1307
1308 impl OptionsImpl for Ipv4OptionsImpl {
1309 type Option<'a> = Ipv4Option<'a>;
1310
1311 fn parse<'a>(kind: u8, data: &'a [u8]) -> Result<Option<Ipv4Option<'a>>, OptionParseErr> {
1312 match kind {
1313 self::OPTION_KIND_EOL | self::OPTION_KIND_NOP => {
1314 unreachable!("records::options::Options promises to handle EOL and NOP")
1315 }
1316 self::OPTION_KIND_RTRALRT => {
1317 if data.len() == OPTION_RTRALRT_LEN {
1318 Ok(Some(Ipv4Option::RouterAlert { data: NetworkEndian::read_u16(data) }))
1319 } else {
1320 Err(OptionParseErr)
1321 }
1322 }
1323 kind => {
1324 if data.len() > 38 {
1325 Err(OptionParseErr)
1326 } else {
1327 Ok(Some(Ipv4Option::Unrecognized { kind, data }))
1328 }
1329 }
1330 }
1331 }
1332 }
1333
1334 impl<'a> OptionBuilder for Ipv4Option<'a> {
1335 type Layout = Ipv4OptionsImpl;
1336
1337 fn serialized_len(&self) -> usize {
1338 match self {
1339 Ipv4Option::RouterAlert { .. } => OPTION_RTRALRT_LEN,
1340 Ipv4Option::Unrecognized { data, .. } => data.len(),
1341 }
1342 }
1343
1344 fn option_kind(&self) -> u8 {
1345 match self {
1346 Ipv4Option::RouterAlert { .. } => OPTION_KIND_RTRALRT,
1347 Ipv4Option::Unrecognized { kind, .. } => *kind,
1348 }
1349 }
1350
1351 fn serialize_into(&self, mut buffer: &mut [u8]) {
1352 match self {
1353 Ipv4Option::Unrecognized { data, .. } => buffer.copy_from_slice(data),
1354 Ipv4Option::RouterAlert { data } => {
1355 (&mut buffer).write_obj_front(&U16::new(*data)).unwrap()
1356 }
1357 };
1358 }
1359 }
1360
1361 #[cfg(test)]
1362 mod test {
1363 use packet::records::RecordBuilder;
1364 use packet::records::options::Options;
1365
1366 use super::*;
1367
1368 #[test]
1369 fn test_serialize_router_alert() {
1370 let mut buffer = [0u8; 4];
1371 let option = Ipv4Option::RouterAlert { data: 0 };
1372 <Ipv4Option<'_> as RecordBuilder>::serialize_into(&option, &mut buffer);
1373 assert_eq!(buffer[0], 148);
1374 assert_eq!(buffer[1], 4);
1375 assert_eq!(buffer[2], 0);
1376 assert_eq!(buffer[3], 0);
1377 }
1378
1379 #[test]
1380 fn test_parse_router_alert() {
1381 let mut buffer: Vec<u8> = vec![148, 4, 0, 0];
1382 let options = Options::<_, Ipv4OptionsImpl>::parse(buffer.as_mut()).unwrap();
1383 let rtralt = options.iter().next().unwrap();
1384 assert_eq!(rtralt, Ipv4Option::RouterAlert { data: 0 });
1385 }
1386 }
1387}
1388
1389mod inner {
1390 pub const IPV4_MIN_HDR_LEN: usize = super::HDR_PREFIX_LEN;
1392}
1393
1394pub mod testutil {
1396 pub use super::inner::IPV4_MIN_HDR_LEN;
1397
1398 pub const IPV4_TTL_OFFSET: usize = 8;
1400
1401 pub const IPV4_CHECKSUM_OFFSET: usize = 10;
1403}
1404
1405#[cfg(test)]
1406mod tests {
1407 use assert_matches::assert_matches;
1408 use net_types::ethernet::Mac;
1409 use packet::{Buf, FragmentedBuffer, ParseBuffer, PartialSerializeResult};
1410
1411 use super::*;
1412 use crate::ethernet::{
1413 ETHERNET_MIN_BODY_LEN_NO_TAG, EtherType, EthernetFrame, EthernetFrameBuilder,
1414 EthernetFrameLengthCheck,
1415 };
1416 use crate::testutil::*;
1417
1418 const DEFAULT_SRC_MAC: Mac = Mac::new([1, 2, 3, 4, 5, 6]);
1419 const DEFAULT_DST_MAC: Mac = Mac::new([7, 8, 9, 0, 1, 2]);
1420 const DEFAULT_SRC_IP: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1421 const DEFAULT_DST_IP: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1422 const DEFAULT_V6_SRC_IP: Ipv6Addr = Ipv6Addr::new([0x2001, 0x0db8, 0, 0, 0, 0, 0, 1]);
1424 const DEFAULT_V6_DST_IP: Ipv6Addr = Ipv6Addr::new([0x2001, 0x0db8, 0, 0, 0, 0, 0, 2]);
1426
1427 #[test]
1428 fn test_parse_serialize_full_tcp() {
1429 use crate::testdata::tls_client_hello_v4::*;
1430
1431 let mut buf = ETHERNET_FRAME.bytes;
1432 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1433 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1434
1435 let mut body = frame.body();
1436 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1437 verify_ipv4_packet(&packet, IPV4_PACKET);
1438
1439 let buffer = packet
1441 .body()
1442 .into_serializer()
1443 .wrap_in(packet.builder())
1444 .wrap_in(frame.builder())
1445 .serialize_vec_outer(&mut NoOpSerializationContext)
1446 .unwrap();
1447 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1448
1449 assert_eq!(&packet.to_vec()[..], IPV4_PACKET.bytes);
1451 }
1452
1453 #[test]
1454 fn test_parse_serialize_full_udp() {
1455 use crate::testdata::dns_request_v4::*;
1456
1457 let mut buf = ETHERNET_FRAME.bytes;
1458 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1459 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1460
1461 let mut body = frame.body();
1462 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1463 verify_ipv4_packet(&packet, IPV4_PACKET);
1464
1465 let buffer = packet
1467 .body()
1468 .into_serializer()
1469 .wrap_in(packet.builder())
1470 .wrap_in(frame.builder())
1471 .serialize_vec_outer(&mut NoOpSerializationContext)
1472 .unwrap();
1473 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1474
1475 assert_eq!(&packet.to_vec()[..], IPV4_PACKET.bytes);
1477 }
1478
1479 #[test]
1480 fn test_parse_serialize_with_options() {
1481 use crate::testdata::igmpv2_membership::report::*;
1484
1485 let mut buf = IP_PACKET_BYTES;
1486 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1487 assert_eq!(packet.iter_options().count(), 1);
1488
1489 assert_eq!(&packet.to_vec()[..], IP_PACKET_BYTES);
1494 }
1495
1496 fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; 20] {
1497 zerocopy::transmute!(hdr_prefix)
1498 }
1499
1500 fn new_hdr_prefix() -> HeaderPrefix {
1503 HeaderPrefix::new(
1504 5,
1505 DscpAndEcn::default(),
1506 20,
1507 0x0102,
1508 0,
1509 0,
1510 0x03,
1511 IpProto::Tcp.into(),
1512 [0xa6, 0xcf],
1513 DEFAULT_SRC_IP,
1514 DEFAULT_DST_IP,
1515 )
1516 }
1517
1518 #[test]
1519 fn test_parse() {
1520 let mut bytes = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1521 let packet = bytes.parse::<Ipv4Packet<_>>().unwrap();
1522 assert_eq!(packet.id(), 0x0102);
1523 assert_eq!(packet.ttl(), 0x03);
1524 assert_eq!(packet.proto(), IpProto::Tcp.into());
1525 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1526 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1527 assert_eq!(packet.body(), []);
1528 }
1529
1530 #[test]
1531 fn test_parse_padding() {
1532 let mut buffer = Buf::new(Vec::new(), ..)
1534 .wrap_in(Ipv4PacketBuilder::new(DEFAULT_DST_IP, DEFAULT_DST_IP, 0, IpProto::Tcp.into()))
1535 .wrap_in(EthernetFrameBuilder::new(
1536 DEFAULT_SRC_MAC,
1537 DEFAULT_DST_MAC,
1538 EtherType::Ipv4,
1539 ETHERNET_MIN_BODY_LEN_NO_TAG,
1540 ))
1541 .serialize_vec_outer(&mut NoOpSerializationContext)
1542 .unwrap();
1543 let _: EthernetFrame<_> =
1544 buffer.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1545 assert_eq!(buffer.len(), 46);
1548 let packet = buffer.parse::<Ipv4Packet<_>>().unwrap();
1549 assert_eq!(packet.body().len(), 0);
1552 assert_eq!(buffer.len(), 0);
1556 }
1557
1558 #[test]
1559 fn test_parse_error() {
1560 let mut hdr_prefix = new_hdr_prefix();
1562 hdr_prefix.version_ihl = (5 << 4) | 5;
1563 assert_eq!(
1564 (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1565 ParseError::Format.into()
1566 );
1567
1568 let mut hdr_prefix = new_hdr_prefix();
1571 hdr_prefix.version_ihl = (4 << 4) | 4;
1572 assert_eq!(
1573 (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1574 ParseError::Format.into()
1575 );
1576
1577 let mut hdr_prefix = new_hdr_prefix();
1580 hdr_prefix.version_ihl = (4 << 4) | 6;
1581 assert_eq!(
1582 (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1583 ParseError::Format.into()
1584 );
1585 }
1586
1587 fn new_builder() -> Ipv4PacketBuilder {
1589 Ipv4PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, 64, IpProto::Tcp.into())
1590 }
1591
1592 #[test]
1593 fn test_fragment_type() {
1594 fn test_fragment_type_helper(fragment_offset: u16, expect_fragment_type: Ipv4FragmentType) {
1595 let mut builder = new_builder();
1596 builder.fragment_offset(FragmentOffset::new(fragment_offset).unwrap());
1597
1598 let mut buf = [0; IPV4_MIN_HDR_LEN]
1599 .into_serializer()
1600 .wrap_in(builder)
1601 .serialize_vec_outer(&mut NoOpSerializationContext)
1602 .unwrap();
1603
1604 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1605 assert_eq!(packet.fragment_type(), expect_fragment_type);
1606 }
1607
1608 test_fragment_type_helper(0x0000, Ipv4FragmentType::InitialFragment);
1609 test_fragment_type_helper(0x0008, Ipv4FragmentType::NonInitialFragment);
1610 }
1611
1612 #[test]
1613 fn test_serialize() {
1614 let mut builder = new_builder();
1615 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
1616 builder.id(0x0405);
1617 builder.df_flag(true);
1618 builder.mf_flag(true);
1619 builder.fragment_offset(FragmentOffset::new(0x0607).unwrap());
1620
1621 let mut buf = (&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9])
1622 .into_serializer()
1623 .wrap_in(builder)
1624 .serialize_vec_outer(&mut NoOpSerializationContext)
1625 .unwrap();
1626 assert_eq!(
1627 buf.as_ref(),
1628 [
1629 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,
1630 4, 5, 7, 8, 9
1631 ]
1632 );
1633 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1634 assert_eq!(packet.dscp_and_ecn().dscp(), 0x12);
1635 assert_eq!(packet.dscp_and_ecn().ecn(), 3);
1636 assert_eq!(packet.id(), 0x0405);
1637 assert!(packet.df_flag());
1638 assert!(packet.mf_flag());
1639 assert_eq!(packet.fragment_offset().into_raw(), 0x0607);
1640 assert_eq!(packet.fragment_type(), Ipv4FragmentType::NonInitialFragment);
1641 }
1642
1643 #[test]
1644 fn test_partial_serialize() {
1645 let mut builder = new_builder();
1646 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
1647 builder.id(0x0405);
1648 builder.df_flag(true);
1649 builder.mf_flag(true);
1650 builder.fragment_offset(FragmentOffset::new(0x0607).unwrap());
1651 const BODY: &[u8] = &[0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1652 let packet = BODY.into_serializer().wrap_in(builder);
1653 const HEADER: &[u8] = &[69, 75, 0, 30, 4, 5, 102, 7, 64, 6, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8];
1654 const PACKET_LEN: usize = HEADER.len() + BODY.len();
1655
1656 let buf = assert_matches!(
1660 packet.partial_serialize(&mut NoOpSerializationContext, packet::new_buf_vec),
1661 Ok(PartialSerializeResult::NewBuffer { buffer, total_size: PACKET_LEN }) => buffer
1662 );
1663 assert_eq!(buf.as_ref(), HEADER);
1664 }
1665
1666 #[test]
1667 fn test_serialize_id_unset() {
1668 let mut builder = new_builder();
1669 builder.id(0x0405);
1670 builder.df_flag(true);
1671
1672 let mut buf = (&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9])
1673 .into_serializer()
1674 .wrap_in(builder)
1675 .serialize_vec_outer(&mut NoOpSerializationContext)
1676 .unwrap();
1677 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1678 assert_eq!(packet.id(), 0);
1679 assert!(packet.df_flag());
1680 assert_eq!(packet.mf_flag(), false);
1681 assert_eq!(packet.fragment_offset().into_raw(), 0);
1682 assert_eq!(packet.fragment_type(), Ipv4FragmentType::InitialFragment);
1683 }
1684
1685 #[test]
1686 fn test_serialize_zeroes() {
1687 let mut buf_0 = [0; IPV4_MIN_HDR_LEN];
1690 let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], IPV4_MIN_HDR_LEN..)
1691 .wrap_in(new_builder())
1692 .serialize_vec_outer(&mut NoOpSerializationContext)
1693 .unwrap()
1694 .unwrap_a();
1695 let mut buf_1 = [0xFF; IPV4_MIN_HDR_LEN];
1696 let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], IPV4_MIN_HDR_LEN..)
1697 .wrap_in(new_builder())
1698 .serialize_vec_outer(&mut NoOpSerializationContext)
1699 .unwrap()
1700 .unwrap_a();
1701 assert_eq!(buf_0, buf_1);
1702 }
1703
1704 #[test]
1705 #[should_panic(expected = "(SizeLimitExceeded, Nested { inner: Buf { buf:")]
1706 fn test_serialize_panic_packet_length() {
1707 let _: Buf<&mut [u8]> = Buf::new(&mut [0; (1 << 16) - IPV4_MIN_HDR_LEN][..], ..)
1709 .wrap_in(new_builder())
1710 .serialize_vec_outer(&mut NoOpSerializationContext)
1711 .unwrap()
1712 .unwrap_a();
1713 }
1714
1715 #[test]
1716 fn test_copy_header_bytes_for_fragment() {
1717 let hdr_prefix = new_hdr_prefix();
1718 let mut bytes = hdr_prefix_to_bytes(hdr_prefix);
1719 let mut buf = &bytes[..];
1720 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1721 let copied_bytes = packet.copy_header_bytes_for_fragment();
1722 bytes[IPV4_FRAGMENT_DATA_BYTE_RANGE].copy_from_slice(&[0; 4][..]);
1723 assert_eq!(&copied_bytes[..], &bytes[..]);
1724 }
1725
1726 #[test]
1727 fn test_partial_parsing() {
1728 use core::ops::Deref as _;
1729
1730 let mut hdr_prefix = new_hdr_prefix();
1733 hdr_prefix.total_len = U16::new(256);
1734 let mut bytes = hdr_prefix_to_bytes(hdr_prefix)[..].to_owned();
1735 const PAYLOAD: &[u8] = &[1, 2, 3, 4, 5];
1736 bytes.extend(PAYLOAD);
1737 let mut buf = &bytes[..];
1738 let packet = buf.parse::<Ipv4PacketRaw<_>>().unwrap();
1739 let Ipv4PacketRaw { hdr_prefix, options, body } = &packet;
1740 assert_eq!(Ref::bytes(&hdr_prefix), &bytes[0..20]);
1741 assert_eq!(options.as_ref().complete().unwrap().deref(), []);
1742 assert_eq!(body, &MaybeParsed::Incomplete(PAYLOAD));
1744 assert!(Ipv4Packet::try_from_raw(packet).is_err());
1746
1747 let mut hdr_prefix = new_hdr_prefix();
1749 hdr_prefix.version_ihl = (4 << 4) | 10;
1750 let bytes = hdr_prefix_to_bytes(hdr_prefix);
1751 let mut buf = &bytes[..];
1752 let packet = buf.parse::<Ipv4PacketRaw<_>>().unwrap();
1753 let Ipv4PacketRaw { hdr_prefix, options, body } = &packet;
1754 assert_eq!(Ref::bytes(&hdr_prefix), bytes);
1755 assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
1756 assert_eq!(body.complete().unwrap(), []);
1757 assert!(Ipv4Packet::try_from_raw(packet).is_err());
1759
1760 let hdr_prefix = new_hdr_prefix();
1762 let bytes = &hdr_prefix_to_bytes(hdr_prefix);
1763 let mut buf = &bytes[0..10];
1764 assert!(buf.parse::<Ipv4PacketRaw<_>>().is_err());
1765 }
1766
1767 fn create_ipv4_and_ipv6_builders(
1768 proto_v4: Ipv4Proto,
1769 proto_v6: Ipv6Proto,
1770 ) -> (Ipv4PacketBuilder, Ipv6PacketBuilder) {
1771 const IP_DSCP_AND_ECN: DscpAndEcn = DscpAndEcn::new(0x12, 3);
1772 const IP_TTL: u8 = 64;
1773
1774 let mut ipv4_builder =
1775 Ipv4PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, IP_TTL, proto_v4);
1776 ipv4_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
1777 ipv4_builder.id(0x0405);
1778 ipv4_builder.df_flag(true);
1779 ipv4_builder.mf_flag(false);
1780 ipv4_builder.fragment_offset(FragmentOffset::ZERO);
1781
1782 let mut ipv6_builder =
1783 Ipv6PacketBuilder::new(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP, IP_TTL, proto_v6);
1784 ipv6_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
1785 ipv6_builder.flowlabel(0);
1786
1787 (ipv4_builder, ipv6_builder)
1788 }
1789
1790 fn create_tcp_ipv4_and_ipv6_pkt()
1791 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
1792 use crate::tcp::TcpSegmentBuilder;
1793 use core::num::NonZeroU16;
1794
1795 let tcp_src_port: NonZeroU16 = NonZeroU16::new(20).unwrap();
1796 let tcp_dst_port: NonZeroU16 = NonZeroU16::new(30).unwrap();
1797 const TCP_SEQ_NUM: u32 = 4321;
1798 const TCP_ACK_NUM: Option<u32> = Some(1234);
1799 const TCP_WINDOW_SIZE: u16 = 12345;
1800 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1801
1802 let (ipv4_builder, ipv6_builder) =
1803 create_ipv4_and_ipv6_builders(IpProto::Tcp.into(), IpProto::Tcp.into());
1804
1805 let tcp_builder = TcpSegmentBuilder::new(
1806 DEFAULT_SRC_IP,
1807 DEFAULT_DST_IP,
1808 tcp_src_port,
1809 tcp_dst_port,
1810 TCP_SEQ_NUM,
1811 TCP_ACK_NUM,
1812 TCP_WINDOW_SIZE,
1813 );
1814
1815 let v4_pkt_buf = (&PAYLOAD)
1816 .into_serializer()
1817 .wrap_in(tcp_builder)
1818 .wrap_in(ipv4_builder)
1819 .serialize_vec_outer(&mut NoOpSerializationContext)
1820 .unwrap();
1821
1822 let v6_tcp_builder = TcpSegmentBuilder::new(
1823 DEFAULT_V6_SRC_IP,
1824 DEFAULT_V6_DST_IP,
1825 tcp_src_port,
1826 tcp_dst_port,
1827 TCP_SEQ_NUM,
1828 TCP_ACK_NUM,
1829 TCP_WINDOW_SIZE,
1830 );
1831
1832 let v6_pkt_buf = (&PAYLOAD)
1833 .into_serializer()
1834 .wrap_in(v6_tcp_builder)
1835 .wrap_in(ipv6_builder)
1836 .serialize_vec_outer(&mut NoOpSerializationContext)
1837 .unwrap();
1838
1839 (v4_pkt_buf, v6_pkt_buf)
1840 }
1841
1842 #[test]
1843 fn test_nat64_translate_tcp() {
1844 let (mut v4_pkt_buf, expected_v6_pkt_buf) = create_tcp_ipv4_and_ipv6_pkt();
1845
1846 let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1847 let nat64_translation_result =
1848 parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1849
1850 let serializable_pkt = match nat64_translation_result {
1851 Nat64TranslationResult::Forward(s) => s,
1852 _ => panic!("Nat64TranslationResult not of Forward type!"),
1853 };
1854
1855 let translated_v6_pkt_buf =
1856 serializable_pkt.serialize_vec_outer(&mut NoOpSerializationContext).unwrap();
1857
1858 assert_eq!(
1859 expected_v6_pkt_buf.to_flattened_vec(),
1860 translated_v6_pkt_buf.to_flattened_vec()
1861 );
1862 }
1863
1864 fn create_udp_ipv4_and_ipv6_pkt()
1865 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
1866 use crate::udp::UdpPacketBuilder;
1867 use core::num::NonZeroU16;
1868
1869 let udp_src_port: NonZeroU16 = NonZeroU16::new(35000).unwrap();
1870 let udp_dst_port: NonZeroU16 = NonZeroU16::new(53).unwrap();
1871 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1872
1873 let (ipv4_builder, ipv6_builder) =
1874 create_ipv4_and_ipv6_builders(IpProto::Udp.into(), IpProto::Udp.into());
1875
1876 let udp_builder =
1877 UdpPacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, Some(udp_src_port), udp_dst_port);
1878
1879 let v4_pkt_buf = (&PAYLOAD)
1880 .into_serializer()
1881 .wrap_in(udp_builder)
1882 .wrap_in(ipv4_builder)
1883 .serialize_vec_outer(&mut NoOpSerializationContext)
1884 .unwrap();
1885
1886 let v6_udp_builder = UdpPacketBuilder::new(
1887 DEFAULT_V6_SRC_IP,
1888 DEFAULT_V6_DST_IP,
1889 Some(udp_src_port),
1890 udp_dst_port,
1891 );
1892
1893 let v6_pkt_buf = (&PAYLOAD)
1894 .into_serializer()
1895 .wrap_in(v6_udp_builder)
1896 .wrap_in(ipv6_builder)
1897 .serialize_vec_outer(&mut NoOpSerializationContext)
1898 .unwrap();
1899
1900 (v4_pkt_buf, v6_pkt_buf)
1901 }
1902
1903 #[test]
1904 fn test_nat64_translate_udp() {
1905 let (mut v4_pkt_buf, expected_v6_pkt_buf) = create_udp_ipv4_and_ipv6_pkt();
1906
1907 let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1908 let nat64_translation_result =
1909 parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1910
1911 let serializable_pkt = match nat64_translation_result {
1912 Nat64TranslationResult::Forward(s) => s,
1913 _ => panic!(
1914 "Nat64TranslationResult not of Forward type: {:?} ",
1915 nat64_translation_result
1916 ),
1917 };
1918
1919 let translated_v6_pkt_buf =
1920 serializable_pkt.serialize_vec_outer(&mut NoOpSerializationContext).unwrap();
1921
1922 assert_eq!(
1923 expected_v6_pkt_buf.to_flattened_vec(),
1924 translated_v6_pkt_buf.to_flattened_vec()
1925 );
1926 }
1927
1928 #[test]
1929 fn test_nat64_translate_non_tcp_udp_icmp() {
1930 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1931
1932 let (ipv4_builder, ipv6_builder) =
1933 create_ipv4_and_ipv6_builders(Ipv4Proto::Other(50), Ipv6Proto::Other(50));
1934
1935 let mut v4_pkt_buf = (&PAYLOAD)
1936 .into_serializer()
1937 .wrap_in(ipv4_builder)
1938 .serialize_vec_outer(&mut NoOpSerializationContext)
1939 .unwrap();
1940
1941 let expected_v6_pkt_buf = (&PAYLOAD)
1942 .into_serializer()
1943 .wrap_in(ipv6_builder)
1944 .serialize_vec_outer(&mut NoOpSerializationContext)
1945 .unwrap();
1946
1947 let translated_v6_pkt_buf = {
1948 let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1949
1950 let nat64_translation_result =
1951 parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1952
1953 let serializable_pkt = match nat64_translation_result {
1954 Nat64TranslationResult::Forward(s) => s,
1955 _ => panic!(
1956 "Nat64TranslationResult not of Forward type: {:?} ",
1957 nat64_translation_result
1958 ),
1959 };
1960
1961 let translated_buf =
1962 serializable_pkt.serialize_vec_outer(&mut NoOpSerializationContext).unwrap();
1963
1964 translated_buf
1965 };
1966
1967 assert_eq!(
1968 expected_v6_pkt_buf.to_flattened_vec(),
1969 translated_v6_pkt_buf.to_flattened_vec()
1970 );
1971 }
1972
1973 #[test]
1974 fn test_partial_serialize_parsed() {
1975 const PACKET_BYTES: &[u8] = &[
1976 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,
1977 5, 7, 8, 9,
1978 ];
1979 const PACKET_LEN: usize = PACKET_BYTES.len();
1980 let mut packet_bytes_copy = Vec::from(PACKET_BYTES);
1981 let mut packet_bytes_ref: &mut [u8] = &mut packet_bytes_copy[..];
1982 let packet = packet_bytes_ref.parse::<Ipv4Packet<_>>().unwrap();
1983
1984 let buf = assert_matches!(
1985 packet.partial_serialize(&mut NoOpSerializationContext, packet::new_buf_vec),
1986 Ok(PartialSerializeResult::NewBuffer { buffer, total_size: PACKET_LEN }) => buffer
1987 );
1988 assert_eq!(buf.as_ref(), PACKET_BYTES);
1989 }
1990}