1use alloc::vec::Vec;
12use core::borrow::Borrow;
13use core::convert::Infallible as Never;
14use core::fmt::{self, Debug, Formatter};
15use core::ops::Range;
16
17use internet_checksum::Checksum;
18use log::debug;
19use net_types::ip::{GenericOverIp, IpAddress, Ipv4, Ipv4Addr, Ipv4SourceAddr, Ipv6Addr};
20use packet::records::RecordsIter;
21use packet::records::options::{OptionSequenceBuilder, OptionsRaw};
22use packet::{
23 BufferProvider, BufferView, BufferViewMut, EmptyBuf, FragmentedBytesMut, FromRaw,
24 GrowBufferMut, InnerPacketBuilder, LayoutBufferAlloc, MaybeParsed, NestablePacketBuilder,
25 NestableSerializer, NoOpSerializationContext, PacketBuilder, PacketConstraints, ParsablePacket,
26 ParseMetadata, PartialPacketBuilder, PartialSerializeResult, PartialSerializer, SerializeError,
27 SerializeTarget, Serializer,
28};
29use zerocopy::byteorder::network_endian::U16;
30use zerocopy::{
31 FromBytes, Immutable, IntoBytes, KnownLayout, Ref, SplitByteSlice, SplitByteSliceMut, Unaligned,
32};
33
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(
262 &self,
263 _context: &mut C,
264 _constraints: PacketConstraints,
265 mut buffer: &mut [u8],
266 ) -> Result<PartialSerializeResult, SerializeError<Never>> {
267 let hdr_prefix = Ref::bytes(&self.hdr_prefix);
268 let options = self.options.bytes();
269
270 let mut buffer = &mut buffer;
271 let bytes_written = buffer.write_bytes_front_allow_partial(hdr_prefix)
272 + buffer.write_bytes_front_allow_partial(options)
273 + buffer.write_bytes_front_allow_partial(&self.body);
274 let total_size = hdr_prefix.len() + options.len() + self.body.len();
275
276 Ok(PartialSerializeResult { bytes_written, total_size })
277 }
278}
279
280impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv4Packet<B> {
281 type Error = ParseError;
282
283 fn parse_metadata(&self) -> ParseMetadata {
284 ParseMetadata::from_packet(self.header_len(), self.body.len(), 0)
285 }
286
287 fn parse<BV: BufferView<B>>(buffer: BV, _args: ()) -> Result<Self, ParseError> {
288 Ipv4PacketRaw::<B>::parse(buffer, ()).and_then(Ipv4Packet::try_from_raw)
289 }
290}
291
292impl<B: SplitByteSlice> FromRaw<Ipv4PacketRaw<B>, ()> for Ipv4Packet<B> {
293 type Error = ParseError;
294
295 fn try_from_raw_with(raw: Ipv4PacketRaw<B>, _args: ()) -> Result<Self, Self::Error> {
296 let hdr_prefix = raw.hdr_prefix;
299 let hdr_bytes = (hdr_prefix.ihl() * 4) as usize;
300
301 if hdr_bytes < HDR_PREFIX_LEN {
302 return debug_err!(Err(ParseError::Format), "invalid IHL: {}", hdr_prefix.ihl());
303 }
304
305 let options = match raw.options {
306 MaybeParsed::Incomplete(_) => {
307 return debug_err!(Err(ParseError::Format), "Incomplete options");
308 }
309 MaybeParsed::Complete(unchecked) => Options::try_from_raw(unchecked)
310 .map_err(|e| debug_err!(e, "malformed options: {:?}", e))?,
311 };
312
313 if hdr_prefix.version() != 4 {
314 return debug_err!(
315 Err(ParseError::Format),
316 "unexpected IP version: {}",
317 hdr_prefix.version()
318 );
319 }
320
321 let body = match raw.body {
322 MaybeParsed::Incomplete(_) => {
323 if hdr_prefix.mf_flag() {
324 return debug_err!(
325 Err(ParseError::NotSupported),
326 "fragmentation not supported"
327 );
328 } else {
329 return debug_err!(Err(ParseError::Format), "Incomplete body");
330 }
331 }
332 MaybeParsed::Complete(bytes) => bytes,
333 };
334
335 let packet = Ipv4Packet { hdr_prefix, options, body };
336 if packet.compute_header_checksum() != [0, 0] {
337 return debug_err!(Err(ParseError::Checksum), "invalid checksum");
338 }
339 Ok(packet)
340 }
341}
342
343fn compute_header_checksum(hdr_prefix: &[u8], options: &[u8]) -> [u8; 2] {
344 let mut c = Checksum::new();
345 c.add_bytes(hdr_prefix);
346 c.add_bytes(options);
347 c.checksum()
348}
349
350impl<B: SplitByteSlice> Ipv4Packet<B> {
351 pub fn iter_options(&self) -> impl Iterator<Item = Ipv4Option<'_>> {
353 self.options.iter()
354 }
355
356 fn compute_header_checksum(&self) -> [u8; 2] {
358 compute_header_checksum(Ref::bytes(&self.hdr_prefix), self.options.bytes())
359 }
360
361 pub fn body(&self) -> &[u8] {
363 &self.body
364 }
365
366 pub fn header_len(&self) -> usize {
368 Ref::bytes(&self.hdr_prefix).len() + self.options.bytes().len()
369 }
370
371 pub fn src_ipv4(&self) -> Option<Ipv4SourceAddr> {
376 Ipv4SourceAddr::new(self.src_ip())
377 }
378
379 pub fn copy_header_bytes_for_fragment(&self) -> Vec<u8> {
385 let expected_bytes_len = self.header_len();
386 let mut bytes = Vec::with_capacity(expected_bytes_len);
387
388 bytes.extend_from_slice(Ref::bytes(&self.hdr_prefix));
389 bytes.extend_from_slice(self.options.bytes());
390
391 assert_eq!(bytes.len(), expected_bytes_len);
393
394 bytes[IPV4_FRAGMENT_DATA_BYTE_RANGE].copy_from_slice(&[0; 4][..]);
396
397 bytes
398 }
399
400 pub fn nat64_translate(
426 &self,
427 v6_src_addr: Ipv6Addr,
428 v6_dst_addr: Ipv6Addr,
429 ) -> Nat64TranslationResult<
430 impl Serializer<NoOpSerializationContext, Buffer = EmptyBuf> + Debug + '_,
431 Nat64Error,
432 > {
433 #[derive(Debug)]
436 enum Nat64Serializer<T, U, O> {
437 Tcp(T),
438 Udp(U),
439 Other(O),
440 }
441 impl<T, U, O> Serializer<NoOpSerializationContext> for Nat64Serializer<T, U, O>
442 where
443 T: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
444 U: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
445 O: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
446 {
447 type Buffer = EmptyBuf;
448 fn serialize<B, P>(
449 self,
450 context: &mut NoOpSerializationContext,
451 outer: PacketConstraints,
452 provider: P,
453 ) -> Result<B, (SerializeError<P::Error>, Self)>
454 where
455 B: GrowBufferMut,
456 P: BufferProvider<Self::Buffer, B>,
457 {
458 match self {
459 Nat64Serializer::Tcp(serializer) => serializer
460 .serialize(context, outer, provider)
461 .map_err(|(err, ser)| (err, Nat64Serializer::Tcp(ser))),
462 Nat64Serializer::Udp(serializer) => serializer
463 .serialize(context, outer, provider)
464 .map_err(|(err, ser)| (err, Nat64Serializer::Udp(ser))),
465 Nat64Serializer::Other(serializer) => serializer
466 .serialize(context, outer, provider)
467 .map_err(|(err, ser)| (err, Nat64Serializer::Other(ser))),
468 }
469 }
470
471 fn serialize_new_buf<B: GrowBufferMut, A: LayoutBufferAlloc<B>>(
472 &self,
473 context: &mut NoOpSerializationContext,
474 outer: PacketConstraints,
475 alloc: A,
476 ) -> Result<B, SerializeError<A::Error>> {
477 match self {
478 Nat64Serializer::Tcp(serializer) => {
479 serializer.serialize_new_buf(context, outer, alloc)
480 }
481 Nat64Serializer::Udp(serializer) => {
482 serializer.serialize_new_buf(context, outer, alloc)
483 }
484 Nat64Serializer::Other(serializer) => {
485 serializer.serialize_new_buf(context, outer, alloc)
486 }
487 }
488 }
489 }
490
491 impl<T, U, O> NestableSerializer for Nat64Serializer<T, U, O>
492 where
493 T: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
494 U: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
495 O: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
496 {
497 }
498
499 let v6_builder = |v6_proto| {
500 let mut builder =
501 Ipv6PacketBuilder::new(v6_src_addr, v6_dst_addr, self.ttl(), v6_proto);
502 builder.dscp_and_ecn(self.dscp_and_ecn());
503 builder.flowlabel(0);
504 builder
505 };
506
507 match self.proto() {
508 Ipv4Proto::Igmp => {
509 Nat64TranslationResult::Drop
511 }
512
513 Ipv4Proto::Proto(IpProto::Tcp) => {
514 let v6_pkt_builder = v6_builder(Ipv6Proto::Proto(IpProto::Tcp));
515 let args = TcpParseArgs::new(self.src_ip(), self.dst_ip());
516 match TcpSegment::parse(&mut self.body.as_bytes(), args) {
517 Ok(tcp) => {
518 let tcp_serializer =
522 Nat64Serializer::Tcp(tcp.into_serializer(v6_src_addr, v6_dst_addr));
523 Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(tcp_serializer))
524 }
525 Err(msg) => {
526 debug!("Parsing of TCP segment failed: {:?}", msg);
527
528 let common_serializer =
534 Nat64Serializer::Other(self.body().into_serializer());
535 Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(common_serializer))
536 }
537 }
538 }
539
540 Ipv4Proto::Proto(IpProto::Udp) => {
541 let v6_pkt_builder = v6_builder(Ipv6Proto::Proto(IpProto::Udp));
542 let args = UdpParseArgs::new(self.src_ip(), self.dst_ip());
543 match UdpPacket::parse(&mut self.body.as_bytes(), args) {
544 Ok(udp) => {
545 let udp_serializer =
549 Nat64Serializer::Udp(udp.into_serializer(v6_src_addr, v6_dst_addr));
550 Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(udp_serializer))
551 }
552 Err(msg) => {
553 debug!("Parsing of UDP packet failed: {:?}", msg);
554
555 let common_serializer =
561 Nat64Serializer::Other(self.body().into_serializer());
562 Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(common_serializer))
563 }
564 }
565 }
566
567 Ipv4Proto::Icmp => Nat64TranslationResult::Err(Nat64Error::NotImplemented),
568
569 Ipv4Proto::Other(val) => {
574 let v6_pkt_builder = v6_builder(Ipv6Proto::Other(val));
575 let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
576 Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(common_serializer))
577 }
578
579 Ipv4Proto::Proto(IpProto::Reserved) => Nat64TranslationResult::Drop,
582 }
583 }
584
585 pub fn to_vec(&self) -> Vec<u8> {
587 let Ipv4Packet { hdr_prefix, options, body } = self;
588 let mut buf = Vec::with_capacity(
589 Ref::bytes(&hdr_prefix).len() + options.bytes().len() + body.as_bytes().len(),
590 );
591 buf.extend(Ref::bytes(&hdr_prefix));
592 buf.extend(options.bytes());
593 buf.extend(body.as_bytes());
594 buf
595 }
596}
597
598impl<B: SplitByteSliceMut> Ipv4Packet<B> {
599 pub fn set_src_ip_and_update_checksum(&mut self, addr: Ipv4Addr) {
603 let old_bytes = self.hdr_prefix.src_ip.bytes();
604 self.hdr_prefix.hdr_checksum =
605 internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, addr.bytes());
606 self.hdr_prefix.src_ip = addr;
607 }
608
609 pub fn set_dst_ip_and_update_checksum(&mut self, addr: Ipv4Addr) {
613 let old_bytes = self.hdr_prefix.dst_ip.bytes();
614 self.hdr_prefix.hdr_checksum =
615 internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, addr.bytes());
616 self.hdr_prefix.dst_ip = addr;
617 }
618
619 pub fn set_ttl(&mut self, ttl: u8) {
623 let old_bytes = [self.hdr_prefix.ttl, self.hdr_prefix.proto];
627 let new_bytes = [ttl, self.hdr_prefix.proto];
628 self.hdr_prefix.hdr_checksum =
629 internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, &new_bytes);
630 self.hdr_prefix.ttl = ttl;
631 }
632
633 pub fn body_mut(&mut self) -> &mut [u8] {
635 &mut self.body
636 }
637
638 pub fn parts_with_body_mut(&mut self) -> (&HeaderPrefix, &Options<B>, &mut [u8]) {
641 (&self.hdr_prefix, &self.options, &mut self.body)
642 }
643}
644
645impl<B> Debug for Ipv4Packet<B>
646where
647 B: SplitByteSlice,
648{
649 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
650 f.debug_struct("Ipv4Packet")
651 .field("src_ip", &self.src_ip())
652 .field("dst_ip", &self.dst_ip())
653 .field("id", &self.id())
654 .field("ttl", &self.ttl())
655 .field("proto", &self.proto())
656 .field("frag_off", &self.fragment_offset())
657 .field("dscp", &self.dscp_and_ecn().dscp())
658 .field("ecn", &self.dscp_and_ecn().ecn())
659 .field("mf_flag", &self.mf_flag())
660 .field("df_flag", &self.df_flag())
661 .field("body", &alloc::format!("<{} bytes>", self.body.len()))
662 .finish()
663 }
664}
665
666pub struct Ipv4PacketRaw<B> {
676 hdr_prefix: Ref<B, HeaderPrefix>,
677 options: MaybeParsed<OptionsRaw<B, Ipv4OptionsImpl>, B>,
678 body: MaybeParsed<B, B>,
679}
680
681impl<B> Ipv4PacketRaw<B> {
682 pub fn body_mut(&mut self) -> &mut B {
686 match &mut self.body {
687 MaybeParsed::Complete(b) => b,
688 MaybeParsed::Incomplete(b) => b,
689 }
690 }
691}
692
693impl<B: SplitByteSlice> Ipv4Header for Ipv4PacketRaw<B> {
694 fn get_header_prefix(&self) -> &HeaderPrefix {
695 &self.hdr_prefix
696 }
697}
698
699impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv4PacketRaw<B> {
700 type Error = ParseError;
701
702 fn parse_metadata(&self) -> ParseMetadata {
703 let header_len = Ref::bytes(&self.hdr_prefix).len() + self.options.len();
704 ParseMetadata::from_packet(header_len, self.body.len(), 0)
705 }
706
707 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> Result<Self, ParseError> {
708 let hdr_prefix = buffer
709 .take_obj_front::<HeaderPrefix>()
710 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for header"))?;
711 let hdr_bytes = (hdr_prefix.ihl() * 4) as usize;
712
713 let options = MaybeParsed::take_from_buffer_with(
714 &mut buffer,
715 hdr_bytes.saturating_sub(HDR_PREFIX_LEN),
720 OptionsRaw::new,
721 );
722
723 let total_len: usize = hdr_prefix.total_len.get().into();
724 let body_len = total_len.saturating_sub(hdr_bytes);
725 if buffer.len() > body_len {
726 let _: B = buffer.take_back(buffer.len() - body_len).unwrap();
729 }
730
731 let body = MaybeParsed::new_with_min_len(buffer.into_rest(), body_len);
732
733 Ok(Self { hdr_prefix, options, body })
734 }
735}
736
737impl<B> Ipv4PacketRaw<B> {
738 pub fn options(&self) -> &MaybeParsed<OptionsRaw<B, Ipv4OptionsImpl>, B> {
740 &self.options
741 }
742}
743
744impl<B: SplitByteSlice> Ipv4PacketRaw<B> {
745 pub fn body(&self) -> MaybeParsed<&[u8], &[u8]> {
751 self.body.as_ref().map(|b| b.deref()).map_incomplete(|b| b.deref())
752 }
753
754 pub fn into_body(self) -> MaybeParsed<B, B> {
758 self.body
759 }
760}
761
762impl<B: SplitByteSliceMut> Ipv4PacketRaw<B> {
763 pub fn set_src_ip_and_update_checksum(&mut self, addr: Ipv4Addr) {
767 let old_bytes = self.hdr_prefix.src_ip.bytes();
768 self.hdr_prefix.hdr_checksum =
769 internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, addr.bytes());
770 self.hdr_prefix.src_ip = addr;
771 }
772
773 pub fn set_dst_ip_and_update_checksum(&mut self, addr: Ipv4Addr) {
777 let old_bytes = self.hdr_prefix.dst_ip.bytes();
778 self.hdr_prefix.hdr_checksum =
779 internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, addr.bytes());
780 self.hdr_prefix.dst_ip = addr;
781 }
782}
783
784pub type Options<B> = packet::records::options::Options<B, Ipv4OptionsImpl>;
790
791#[derive(Debug)]
794pub struct Ipv4OptionsTooLongError;
795
796#[derive(Debug, Clone)]
798pub struct Ipv4PacketBuilderWithOptions<'a, I> {
799 prefix_builder: Ipv4PacketBuilder,
800 options: OptionSequenceBuilder<Ipv4Option<'a>, I>,
801}
802
803impl<'a, I> Ipv4PacketBuilderWithOptions<'a, I>
804where
805 I: Iterator + Clone,
806 I::Item: Borrow<Ipv4Option<'a>>,
807{
808 pub fn new<T: IntoIterator<IntoIter = I>>(
814 prefix_builder: Ipv4PacketBuilder,
815 options: T,
816 ) -> Result<Ipv4PacketBuilderWithOptions<'a, I>, Ipv4OptionsTooLongError> {
817 let options = OptionSequenceBuilder::new(options.into_iter());
818 if options.serialized_len() > MAX_OPTIONS_LEN {
819 return Err(Ipv4OptionsTooLongError);
820 }
821 Ok(Ipv4PacketBuilderWithOptions { prefix_builder, options })
822 }
823
824 fn aligned_options_len(&self) -> usize {
825 crate::utils::round_to_next_multiple_of_four(self.options.serialized_len())
827 }
828
829 pub fn prefix_builder(&self) -> &Ipv4PacketBuilder {
831 &self.prefix_builder
832 }
833
834 pub fn prefix_builder_mut(&mut self) -> &mut Ipv4PacketBuilder {
836 &mut self.prefix_builder
837 }
838
839 pub fn options(&self) -> &I {
841 self.options.records()
842 }
843
844 pub fn with_fragment_options(
850 self,
851 first_fragment: bool,
852 ) -> Ipv4PacketBuilderWithOptions<'a, impl Iterator<Item: Borrow<Ipv4Option<'a>>> + Clone> {
853 let Self { prefix_builder, options } = self;
854 Ipv4PacketBuilderWithOptions {
855 prefix_builder,
856 options: OptionSequenceBuilder::new(
859 options
860 .records()
861 .clone()
862 .filter(move |opt| first_fragment || opt.borrow().copied()),
863 ),
864 }
865 }
866}
867
868impl<'a, B> Ipv4PacketBuilderWithOptions<'a, RecordsIter<'a, B, Ipv4OptionsImpl>> {
869 pub fn new_with_records_iter(
872 prefix_builder: Ipv4PacketBuilder,
873 iter: RecordsIter<'a, B, Ipv4OptionsImpl>,
874 ) -> Self {
875 Self { prefix_builder, options: OptionSequenceBuilder::new(iter) }
876 }
877}
878
879impl<'a, I> NestablePacketBuilder for Ipv4PacketBuilderWithOptions<'a, I>
880where
881 I: Iterator + Clone,
882 I::Item: Borrow<Ipv4Option<'a>>,
883{
884 fn constraints(&self) -> PacketConstraints {
885 let header_len = IPV4_MIN_HDR_LEN + self.aligned_options_len();
886 assert_eq!(header_len % 4, 0);
887 PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
888 }
889}
890
891impl<'a, I, C: IpSerializationContext<Ipv4>> PacketBuilder<C>
892 for Ipv4PacketBuilderWithOptions<'a, I>
893where
894 I: Iterator + Clone,
895 I::Item: Borrow<Ipv4Option<'a>>,
896{
897 fn context_state(&self) -> C::ContextState {
898 C::envelope_to_state(IpEnvelope::new(true))
899 }
900
901 fn serialize(
902 &self,
903 context: &mut C,
904 target: &mut SerializeTarget<'_>,
905 body: FragmentedBytesMut<'_, '_>,
906 ) {
907 let opt_len = self.aligned_options_len();
908 let mut header = &mut &mut target.header[..];
914 let opts = header.take_back_zero(opt_len).expect("too few bytes for Ipv4 options");
915 let Ipv4PacketBuilderWithOptions { prefix_builder, options } = self;
916 options.serialize_into(opts);
917 prefix_builder.serialize(context, target, body);
918 }
919}
920
921impl<'a, I, C: IpSerializationContext<Ipv4>> PartialPacketBuilder<C>
922 for Ipv4PacketBuilderWithOptions<'a, I>
923where
924 I: Iterator + Clone,
925 I::Item: Borrow<Ipv4Option<'a>>,
926{
927 fn partial_serialize(&self, context: &mut C, body_len: usize, header: &mut [u8]) {
928 let Ipv4PacketBuilderWithOptions { prefix_builder, options } = self;
929 prefix_builder.partial_serialize(context, body_len, header);
930 let options_slice = &mut header[IPV4_MIN_HDR_LEN..];
931 assert_eq!(options_slice.len(), self.aligned_options_len());
932 options.serialize_into(options_slice);
933 }
934}
935
936impl<'a, C: IpSerializationContext<Ipv4>, I> IpPacketBuilder<C, Ipv4>
937 for Ipv4PacketBuilderWithOptions<'a, I>
938where
939 I: Default + Debug + Clone + Iterator<Item: Borrow<Ipv4Option<'a>>>,
940{
941 fn new(src_ip: Ipv4Addr, dst_ip: Ipv4Addr, ttl: u8, proto: Ipv4Proto) -> Self {
942 Ipv4PacketBuilderWithOptions::new(
943 Ipv4PacketBuilder::new(src_ip, dst_ip, ttl, proto),
944 I::default(),
945 )
946 .expect("packet builder with no options should be valid")
947 }
948
949 fn src_ip(&self) -> Ipv4Addr {
950 self.prefix_builder.src_ip
951 }
952
953 fn set_src_ip(&mut self, addr: Ipv4Addr) {
954 <Ipv4PacketBuilder as IpPacketBuilder<C, Ipv4>>::set_src_ip(&mut self.prefix_builder, addr)
955 }
956
957 fn dst_ip(&self) -> Ipv4Addr {
958 self.prefix_builder.dst_ip
959 }
960
961 fn set_dst_ip(&mut self, addr: Ipv4Addr) {
962 <Ipv4PacketBuilder as IpPacketBuilder<C, Ipv4>>::set_dst_ip(&mut self.prefix_builder, addr)
963 }
964
965 fn proto(&self) -> Ipv4Proto {
966 self.prefix_builder.proto
967 }
968
969 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
970 <Ipv4PacketBuilder as IpPacketBuilder<C, Ipv4>>::set_dscp_and_ecn(
971 &mut self.prefix_builder,
972 dscp_and_ecn,
973 )
974 }
975}
976
977#[derive(Debug, Clone, Eq, PartialEq)]
979pub struct Ipv4PacketBuilder {
980 id: u16,
981 dscp_and_ecn: DscpAndEcn,
982 flags: u8,
983 frag_off: u16,
984 ttl: u8,
985 proto: Ipv4Proto,
986 src_ip: Ipv4Addr,
987 dst_ip: Ipv4Addr,
988}
989
990impl Ipv4PacketBuilder {
991 pub fn new<S: Into<Ipv4Addr>, D: Into<Ipv4Addr>>(
993 src_ip: S,
994 dst_ip: D,
995 ttl: u8,
996 proto: Ipv4Proto,
997 ) -> Ipv4PacketBuilder {
998 Ipv4PacketBuilder {
999 id: 0,
1000 dscp_and_ecn: DscpAndEcn::default(),
1001 flags: 0,
1002 frag_off: 0,
1003 ttl,
1004 proto: proto,
1005 src_ip: src_ip.into(),
1006 dst_ip: dst_ip.into(),
1007 }
1008 }
1009
1010 pub fn dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1012 self.dscp_and_ecn = dscp_and_ecn;
1013 }
1014
1015 pub fn id(&mut self, id: u16) {
1017 self.id = id
1018 }
1019
1020 pub fn df_flag(&mut self, df: bool) {
1022 if df {
1023 self.flags |= 1 << DF_FLAG_OFFSET;
1024 } else {
1025 self.flags &= !(1 << DF_FLAG_OFFSET);
1026 }
1027 }
1028
1029 pub fn mf_flag(&mut self, mf: bool) {
1031 if mf {
1032 self.flags |= 1 << MF_FLAG_OFFSET;
1033 } else {
1034 self.flags &= !(1 << MF_FLAG_OFFSET);
1035 }
1036 }
1037
1038 pub fn fragment_offset(&mut self, fragment_offset: FragmentOffset) {
1040 self.frag_off = fragment_offset.into_raw();
1041 }
1042
1043 pub fn read_df_flag(&self) -> bool {
1045 (self.flags & (1 << DF_FLAG_OFFSET)) != 0
1046 }
1047
1048 fn get_header_prefix(&self, header_len: usize, total_len: usize) -> HeaderPrefix {
1049 assert_eq!(header_len % 4, 0);
1050 let ihl: u8 = u8::try_from(header_len / 4).expect("Header too large");
1051
1052 let id = if ((self.flags & (1 << DF_FLAG_OFFSET)) == 0)
1062 || ((self.flags & (1 << MF_FLAG_OFFSET)) == 1)
1063 || (self.frag_off > 0)
1064 {
1065 self.id
1066 } else {
1067 0
1068 };
1069
1070 HeaderPrefix::new(
1071 ihl,
1072 self.dscp_and_ecn,
1073 {
1074 debug_assert!(total_len <= core::u16::MAX as usize);
1080 total_len as u16
1081 },
1082 id,
1083 self.flags,
1084 self.frag_off,
1085 self.ttl,
1086 self.proto.into(),
1087 [0, 0], self.src_ip,
1089 self.dst_ip,
1090 )
1091 }
1092}
1093
1094impl NestablePacketBuilder for Ipv4PacketBuilder {
1095 fn constraints(&self) -> PacketConstraints {
1096 PacketConstraints::new(IPV4_MIN_HDR_LEN, 0, 0, (1 << 16) - 1 - IPV4_MIN_HDR_LEN)
1097 }
1098}
1099
1100impl<C: IpSerializationContext<Ipv4>> PacketBuilder<C> for Ipv4PacketBuilder {
1101 fn context_state(&self) -> C::ContextState {
1102 C::envelope_to_state(IpEnvelope::new(false))
1103 }
1104
1105 fn serialize(
1106 &self,
1107 _context: &mut C,
1108 target: &mut SerializeTarget<'_>,
1109 body: FragmentedBytesMut<'_, '_>,
1110 ) {
1111 let header_len = target.header.len();
1112 let total_len = header_len + body.len();
1113 let mut hdr_prefix = self.get_header_prefix(header_len, total_len);
1114 let options = &target.header[HDR_PREFIX_LEN..];
1115 let checksum = compute_header_checksum(hdr_prefix.as_bytes(), options);
1116 hdr_prefix.hdr_checksum = checksum;
1117 let mut header = &mut target.header;
1118 header.write_obj_front(&hdr_prefix).expect("too few bytes for IPv4 header prefix");
1119 }
1120}
1121
1122impl<C: IpSerializationContext<Ipv4>> PartialPacketBuilder<C> for Ipv4PacketBuilder {
1123 fn partial_serialize(&self, _context: &mut C, body_len: usize, mut header: &mut [u8]) {
1124 let total_len = header.len() + body_len;
1125 let hdr_prefix = self.get_header_prefix(header.len(), total_len);
1126 (&mut header).write_obj_front(&hdr_prefix).expect("too few bytes for IPv4 header prefix");
1127 }
1128}
1129
1130impl<C: IpSerializationContext<Ipv4>> IpPacketBuilder<C, Ipv4> for Ipv4PacketBuilder {
1131 fn new(src_ip: Ipv4Addr, dst_ip: Ipv4Addr, ttl: u8, proto: Ipv4Proto) -> Self {
1132 Ipv4PacketBuilder::new(src_ip, dst_ip, ttl, proto)
1133 }
1134
1135 fn src_ip(&self) -> Ipv4Addr {
1136 self.src_ip
1137 }
1138
1139 fn set_src_ip(&mut self, addr: Ipv4Addr) {
1140 self.src_ip = addr;
1141 }
1142
1143 fn dst_ip(&self) -> Ipv4Addr {
1144 self.dst_ip
1145 }
1146
1147 fn set_dst_ip(&mut self, addr: Ipv4Addr) {
1148 self.dst_ip = addr;
1149 }
1150
1151 fn proto(&self) -> Ipv4Proto {
1152 self.proto
1153 }
1154
1155 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1156 self.dscp_and_ecn = dscp_and_ecn;
1157 }
1158}
1159
1160const DF_FLAG_OFFSET: u8 = 1;
1162const MF_FLAG_OFFSET: u8 = 0;
1163
1164pub(crate) fn reassemble_fragmented_packet<
1170 B: SplitByteSliceMut,
1171 BV: BufferViewMut<B>,
1172 I: Iterator<Item = Vec<u8>>,
1173>(
1174 mut buffer: BV,
1175 header: Vec<u8>,
1176 body_fragments: I,
1177) -> Result<(), ParseError> {
1178 assert!(header.len() >= HDR_PREFIX_LEN);
1179
1180 let bytes = buffer.as_mut();
1181
1182 bytes[0..header.len()].copy_from_slice(&header[..]);
1184 let mut byte_count = header.len();
1185
1186 for p in body_fragments {
1188 bytes[byte_count..byte_count + p.len()].copy_from_slice(&p[..]);
1189 byte_count += p.len();
1190 }
1191
1192 if byte_count > usize::from(core::u16::MAX) {
1197 return debug_err!(
1198 Err(ParseError::Format),
1199 "fragmented packet length of {} bytes is too large",
1200 byte_count
1201 );
1202 }
1203
1204 let mut header_ref = Ref::<_, HeaderPrefix>::from_prefix(bytes).unwrap().0;
1207
1208 let options_bytes = &header[HDR_PREFIX_LEN..header.len()];
1209
1210 header_ref.total_len.set(u16::try_from(byte_count).unwrap());
1212
1213 header_ref.flags_frag_off = [0; 2];
1216
1217 header_ref.hdr_checksum = [0; 2];
1219 header_ref.hdr_checksum = compute_header_checksum(header_ref.as_bytes(), options_bytes);
1220
1221 Ok(())
1222}
1223
1224pub mod options {
1226 use byteorder::{ByteOrder, NetworkEndian};
1227 use packet::BufferViewMut;
1228 use packet::records::options::{
1229 OptionBuilder, OptionLayout, OptionParseErr, OptionParseLayout, OptionsImpl,
1230 };
1231 use zerocopy::byteorder::network_endian::U16;
1232
1233 const OPTION_KIND_EOL: u8 = 0;
1234 const OPTION_KIND_NOP: u8 = 1;
1235 const OPTION_KIND_RTRALRT: u8 = 148;
1236
1237 const OPTION_RTRALRT_LEN: usize = 2;
1238
1239 #[derive(PartialEq, Eq, Debug, Clone)]
1246 #[allow(missing_docs)]
1247 pub enum Ipv4Option<'a> {
1248 RouterAlert { data: u16 },
1254
1255 Unrecognized { kind: u8, data: &'a [u8] },
1267 }
1268
1269 impl<'a> Ipv4Option<'a> {
1270 pub fn copied(&self) -> bool {
1272 match self {
1273 Ipv4Option::RouterAlert { .. } => true,
1277 Ipv4Option::Unrecognized { kind, .. } => *kind & (1 << 7) != 0,
1278 }
1279 }
1280 }
1281
1282 #[derive(Debug, Clone)]
1284 pub struct Ipv4OptionsImpl;
1285
1286 impl OptionLayout for Ipv4OptionsImpl {
1287 type KindLenField = u8;
1288 }
1289
1290 impl OptionParseLayout for Ipv4OptionsImpl {
1291 type Error = OptionParseErr;
1292 const END_OF_OPTIONS: Option<u8> = Some(0);
1293 const NOP: Option<u8> = Some(1);
1294 }
1295
1296 impl OptionsImpl for Ipv4OptionsImpl {
1297 type Option<'a> = Ipv4Option<'a>;
1298
1299 fn parse<'a>(kind: u8, data: &'a [u8]) -> Result<Option<Ipv4Option<'a>>, OptionParseErr> {
1300 match kind {
1301 self::OPTION_KIND_EOL | self::OPTION_KIND_NOP => {
1302 unreachable!("records::options::Options promises to handle EOL and NOP")
1303 }
1304 self::OPTION_KIND_RTRALRT => {
1305 if data.len() == OPTION_RTRALRT_LEN {
1306 Ok(Some(Ipv4Option::RouterAlert { data: NetworkEndian::read_u16(data) }))
1307 } else {
1308 Err(OptionParseErr)
1309 }
1310 }
1311 kind => {
1312 if data.len() > 38 {
1313 Err(OptionParseErr)
1314 } else {
1315 Ok(Some(Ipv4Option::Unrecognized { kind, data }))
1316 }
1317 }
1318 }
1319 }
1320 }
1321
1322 impl<'a> OptionBuilder for Ipv4Option<'a> {
1323 type Layout = Ipv4OptionsImpl;
1324
1325 fn serialized_len(&self) -> usize {
1326 match self {
1327 Ipv4Option::RouterAlert { .. } => OPTION_RTRALRT_LEN,
1328 Ipv4Option::Unrecognized { data, .. } => data.len(),
1329 }
1330 }
1331
1332 fn option_kind(&self) -> u8 {
1333 match self {
1334 Ipv4Option::RouterAlert { .. } => OPTION_KIND_RTRALRT,
1335 Ipv4Option::Unrecognized { kind, .. } => *kind,
1336 }
1337 }
1338
1339 fn serialize_into(&self, mut buffer: &mut [u8]) {
1340 match self {
1341 Ipv4Option::Unrecognized { data, .. } => buffer.copy_from_slice(data),
1342 Ipv4Option::RouterAlert { data } => {
1343 (&mut buffer).write_obj_front(&U16::new(*data)).unwrap()
1344 }
1345 };
1346 }
1347 }
1348
1349 #[cfg(test)]
1350 mod test {
1351 use packet::records::RecordBuilder;
1352 use packet::records::options::Options;
1353
1354 use super::*;
1355
1356 #[test]
1357 fn test_serialize_router_alert() {
1358 let mut buffer = [0u8; 4];
1359 let option = Ipv4Option::RouterAlert { data: 0 };
1360 <Ipv4Option<'_> as RecordBuilder>::serialize_into(&option, &mut buffer);
1361 assert_eq!(buffer[0], 148);
1362 assert_eq!(buffer[1], 4);
1363 assert_eq!(buffer[2], 0);
1364 assert_eq!(buffer[3], 0);
1365 }
1366
1367 #[test]
1368 fn test_parse_router_alert() {
1369 let mut buffer: Vec<u8> = vec![148, 4, 0, 0];
1370 let options = Options::<_, Ipv4OptionsImpl>::parse(buffer.as_mut()).unwrap();
1371 let rtralt = options.iter().next().unwrap();
1372 assert_eq!(rtralt, Ipv4Option::RouterAlert { data: 0 });
1373 }
1374 }
1375}
1376
1377mod inner {
1378 pub const IPV4_MIN_HDR_LEN: usize = super::HDR_PREFIX_LEN;
1380}
1381
1382pub mod testutil {
1384 pub use super::inner::IPV4_MIN_HDR_LEN;
1385
1386 pub const IPV4_TTL_OFFSET: usize = 8;
1388
1389 pub const IPV4_CHECKSUM_OFFSET: usize = 10;
1391}
1392
1393#[cfg(test)]
1394mod tests {
1395 use net_types::ethernet::Mac;
1396 use packet::{Buf, FragmentedBuffer, NestableSerializer as _, ParseBuffer};
1397
1398 use super::*;
1399 use crate::ethernet::{
1400 ETHERNET_MIN_BODY_LEN_NO_TAG, EtherType, EthernetFrame, EthernetFrameBuilder,
1401 EthernetFrameLengthCheck,
1402 };
1403 use crate::testutil::*;
1404
1405 const DEFAULT_SRC_MAC: Mac = Mac::new([1, 2, 3, 4, 5, 6]);
1406 const DEFAULT_DST_MAC: Mac = Mac::new([7, 8, 9, 0, 1, 2]);
1407 const DEFAULT_SRC_IP: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1408 const DEFAULT_DST_IP: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1409 const DEFAULT_V6_SRC_IP: Ipv6Addr = Ipv6Addr::new([0x2001, 0x0db8, 0, 0, 0, 0, 0, 1]);
1411 const DEFAULT_V6_DST_IP: Ipv6Addr = Ipv6Addr::new([0x2001, 0x0db8, 0, 0, 0, 0, 0, 2]);
1413
1414 #[test]
1415 fn test_parse_serialize_full_tcp() {
1416 use crate::testdata::tls_client_hello_v4::*;
1417
1418 let mut buf = ETHERNET_FRAME.bytes;
1419 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1420 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1421
1422 let mut body = frame.body();
1423 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1424 verify_ipv4_packet(&packet, IPV4_PACKET);
1425
1426 let buffer = packet
1428 .body()
1429 .into_serializer()
1430 .wrap_in(packet.builder())
1431 .wrap_in(frame.builder())
1432 .serialize_vec_outer(&mut NoOpSerializationContext)
1433 .unwrap();
1434 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1435
1436 assert_eq!(&packet.to_vec()[..], IPV4_PACKET.bytes);
1438 }
1439
1440 #[test]
1441 fn test_parse_serialize_full_udp() {
1442 use crate::testdata::dns_request_v4::*;
1443
1444 let mut buf = ETHERNET_FRAME.bytes;
1445 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1446 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1447
1448 let mut body = frame.body();
1449 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1450 verify_ipv4_packet(&packet, IPV4_PACKET);
1451
1452 let buffer = packet
1454 .body()
1455 .into_serializer()
1456 .wrap_in(packet.builder())
1457 .wrap_in(frame.builder())
1458 .serialize_vec_outer(&mut NoOpSerializationContext)
1459 .unwrap();
1460 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1461
1462 assert_eq!(&packet.to_vec()[..], IPV4_PACKET.bytes);
1464 }
1465
1466 #[test]
1467 fn test_parse_serialize_with_options() {
1468 use crate::testdata::igmpv2_membership::report::*;
1471
1472 let mut buf = IP_PACKET_BYTES;
1473 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1474 assert_eq!(packet.iter_options().count(), 1);
1475
1476 assert_eq!(&packet.to_vec()[..], IP_PACKET_BYTES);
1481 }
1482
1483 fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; 20] {
1484 zerocopy::transmute!(hdr_prefix)
1485 }
1486
1487 fn new_hdr_prefix() -> HeaderPrefix {
1490 HeaderPrefix::new(
1491 5,
1492 DscpAndEcn::default(),
1493 20,
1494 0x0102,
1495 0,
1496 0,
1497 0x03,
1498 IpProto::Tcp.into(),
1499 [0xa6, 0xcf],
1500 DEFAULT_SRC_IP,
1501 DEFAULT_DST_IP,
1502 )
1503 }
1504
1505 #[test]
1506 fn test_parse() {
1507 let mut bytes = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1508 let packet = bytes.parse::<Ipv4Packet<_>>().unwrap();
1509 assert_eq!(packet.id(), 0x0102);
1510 assert_eq!(packet.ttl(), 0x03);
1511 assert_eq!(packet.proto(), IpProto::Tcp.into());
1512 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1513 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1514 assert_eq!(packet.body(), []);
1515 }
1516
1517 #[test]
1518 fn test_parse_padding() {
1519 let mut buffer = Buf::new(Vec::new(), ..)
1521 .wrap_in(Ipv4PacketBuilder::new(DEFAULT_DST_IP, DEFAULT_DST_IP, 0, IpProto::Tcp.into()))
1522 .wrap_in(EthernetFrameBuilder::new(
1523 DEFAULT_SRC_MAC,
1524 DEFAULT_DST_MAC,
1525 EtherType::Ipv4,
1526 ETHERNET_MIN_BODY_LEN_NO_TAG,
1527 ))
1528 .serialize_vec_outer(&mut NoOpSerializationContext)
1529 .unwrap();
1530 let _: EthernetFrame<_> =
1531 buffer.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1532 assert_eq!(buffer.len(), 46);
1535 let packet = buffer.parse::<Ipv4Packet<_>>().unwrap();
1536 assert_eq!(packet.body().len(), 0);
1539 assert_eq!(buffer.len(), 0);
1543 }
1544
1545 #[test]
1546 fn test_parse_error() {
1547 let mut hdr_prefix = new_hdr_prefix();
1549 hdr_prefix.version_ihl = (5 << 4) | 5;
1550 assert_eq!(
1551 (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1552 ParseError::Format.into()
1553 );
1554
1555 let mut hdr_prefix = new_hdr_prefix();
1558 hdr_prefix.version_ihl = (4 << 4) | 4;
1559 assert_eq!(
1560 (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1561 ParseError::Format.into()
1562 );
1563
1564 let mut hdr_prefix = new_hdr_prefix();
1567 hdr_prefix.version_ihl = (4 << 4) | 6;
1568 assert_eq!(
1569 (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1570 ParseError::Format.into()
1571 );
1572 }
1573
1574 fn new_builder() -> Ipv4PacketBuilder {
1576 Ipv4PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, 64, IpProto::Tcp.into())
1577 }
1578
1579 #[test]
1580 fn test_fragment_type() {
1581 fn test_fragment_type_helper(fragment_offset: u16, expect_fragment_type: Ipv4FragmentType) {
1582 let mut builder = new_builder();
1583 builder.fragment_offset(FragmentOffset::new(fragment_offset).unwrap());
1584
1585 let mut buf = [0; IPV4_MIN_HDR_LEN]
1586 .into_serializer()
1587 .wrap_in(builder)
1588 .serialize_vec_outer(&mut NoOpSerializationContext)
1589 .unwrap();
1590
1591 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1592 assert_eq!(packet.fragment_type(), expect_fragment_type);
1593 }
1594
1595 test_fragment_type_helper(0x0000, Ipv4FragmentType::InitialFragment);
1596 test_fragment_type_helper(0x0008, Ipv4FragmentType::NonInitialFragment);
1597 }
1598
1599 #[test]
1600 fn test_serialize() {
1601 let mut builder = new_builder();
1602 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
1603 builder.id(0x0405);
1604 builder.df_flag(true);
1605 builder.mf_flag(true);
1606 builder.fragment_offset(FragmentOffset::new(0x0607).unwrap());
1607
1608 let mut buf = (&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9])
1609 .into_serializer()
1610 .wrap_in(builder)
1611 .serialize_vec_outer(&mut NoOpSerializationContext)
1612 .unwrap();
1613 assert_eq!(
1614 buf.as_ref(),
1615 [
1616 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,
1617 4, 5, 7, 8, 9
1618 ]
1619 );
1620 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1621 assert_eq!(packet.dscp_and_ecn().dscp(), 0x12);
1622 assert_eq!(packet.dscp_and_ecn().ecn(), 3);
1623 assert_eq!(packet.id(), 0x0405);
1624 assert!(packet.df_flag());
1625 assert!(packet.mf_flag());
1626 assert_eq!(packet.fragment_offset().into_raw(), 0x0607);
1627 assert_eq!(packet.fragment_type(), Ipv4FragmentType::NonInitialFragment);
1628 }
1629
1630 #[test]
1631 fn test_partial_serialize() {
1632 let mut builder = new_builder();
1633 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
1634 builder.id(0x0405);
1635 builder.df_flag(true);
1636 builder.mf_flag(true);
1637 builder.fragment_offset(FragmentOffset::new(0x0607).unwrap());
1638 let body = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1639 let packet = (&body).into_serializer().wrap_in(builder);
1640 const HEADER_LEN: usize = 20;
1641
1642 const HEADER: [u8; HEADER_LEN] =
1645 [69, 75, 0, 30, 4, 5, 102, 7, 64, 6, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8];
1646 let mut expected_partial = HEADER.to_vec();
1647 expected_partial.resize(expected_partial.len() + body.len(), 0);
1648
1649 for i in 1..expected_partial.len() {
1650 let mut buf = vec![0u8; i];
1651 let result = packet.partial_serialize(
1652 &mut NoOpSerializationContext,
1653 PacketConstraints::UNCONSTRAINED,
1654 buf.as_mut_slice(),
1655 );
1656
1657 let bytes_written = if i >= HEADER_LEN { HEADER_LEN } else { 0 };
1660 assert_eq!(
1661 result,
1662 Ok(PartialSerializeResult { bytes_written, total_size: body.len() + HEADER_LEN })
1663 );
1664 if bytes_written > 0 {
1665 assert_eq!(buf, expected_partial[..i]);
1666 }
1667 }
1668 }
1669
1670 #[test]
1671 fn test_serialize_id_unset() {
1672 let mut builder = new_builder();
1673 builder.id(0x0405);
1674 builder.df_flag(true);
1675
1676 let mut buf = (&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9])
1677 .into_serializer()
1678 .wrap_in(builder)
1679 .serialize_vec_outer(&mut NoOpSerializationContext)
1680 .unwrap();
1681 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1682 assert_eq!(packet.id(), 0);
1683 assert!(packet.df_flag());
1684 assert_eq!(packet.mf_flag(), false);
1685 assert_eq!(packet.fragment_offset().into_raw(), 0);
1686 assert_eq!(packet.fragment_type(), Ipv4FragmentType::InitialFragment);
1687 }
1688
1689 #[test]
1690 fn test_serialize_zeroes() {
1691 let mut buf_0 = [0; IPV4_MIN_HDR_LEN];
1694 let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], IPV4_MIN_HDR_LEN..)
1695 .wrap_in(new_builder())
1696 .serialize_vec_outer(&mut NoOpSerializationContext)
1697 .unwrap()
1698 .unwrap_a();
1699 let mut buf_1 = [0xFF; IPV4_MIN_HDR_LEN];
1700 let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], IPV4_MIN_HDR_LEN..)
1701 .wrap_in(new_builder())
1702 .serialize_vec_outer(&mut NoOpSerializationContext)
1703 .unwrap()
1704 .unwrap_a();
1705 assert_eq!(buf_0, buf_1);
1706 }
1707
1708 #[test]
1709 #[should_panic(expected = "(SizeLimitExceeded, Nested { inner: Buf { buf:")]
1710 fn test_serialize_panic_packet_length() {
1711 let _: Buf<&mut [u8]> = Buf::new(&mut [0; (1 << 16) - IPV4_MIN_HDR_LEN][..], ..)
1713 .wrap_in(new_builder())
1714 .serialize_vec_outer(&mut NoOpSerializationContext)
1715 .unwrap()
1716 .unwrap_a();
1717 }
1718
1719 #[test]
1720 fn test_copy_header_bytes_for_fragment() {
1721 let hdr_prefix = new_hdr_prefix();
1722 let mut bytes = hdr_prefix_to_bytes(hdr_prefix);
1723 let mut buf = &bytes[..];
1724 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1725 let copied_bytes = packet.copy_header_bytes_for_fragment();
1726 bytes[IPV4_FRAGMENT_DATA_BYTE_RANGE].copy_from_slice(&[0; 4][..]);
1727 assert_eq!(&copied_bytes[..], &bytes[..]);
1728 }
1729
1730 #[test]
1731 fn test_partial_parsing() {
1732 use core::ops::Deref as _;
1733
1734 let mut hdr_prefix = new_hdr_prefix();
1737 hdr_prefix.total_len = U16::new(256);
1738 let mut bytes = hdr_prefix_to_bytes(hdr_prefix)[..].to_owned();
1739 const PAYLOAD: &[u8] = &[1, 2, 3, 4, 5];
1740 bytes.extend(PAYLOAD);
1741 let mut buf = &bytes[..];
1742 let packet = buf.parse::<Ipv4PacketRaw<_>>().unwrap();
1743 let Ipv4PacketRaw { hdr_prefix, options, body } = &packet;
1744 assert_eq!(Ref::bytes(&hdr_prefix), &bytes[0..20]);
1745 assert_eq!(options.as_ref().complete().unwrap().deref(), []);
1746 assert_eq!(body, &MaybeParsed::Incomplete(PAYLOAD));
1748 assert!(Ipv4Packet::try_from_raw(packet).is_err());
1750
1751 let mut hdr_prefix = new_hdr_prefix();
1753 hdr_prefix.version_ihl = (4 << 4) | 10;
1754 let bytes = hdr_prefix_to_bytes(hdr_prefix);
1755 let mut buf = &bytes[..];
1756 let packet = buf.parse::<Ipv4PacketRaw<_>>().unwrap();
1757 let Ipv4PacketRaw { hdr_prefix, options, body } = &packet;
1758 assert_eq!(Ref::bytes(&hdr_prefix), bytes);
1759 assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
1760 assert_eq!(body.complete().unwrap(), []);
1761 assert!(Ipv4Packet::try_from_raw(packet).is_err());
1763
1764 let hdr_prefix = new_hdr_prefix();
1766 let bytes = &hdr_prefix_to_bytes(hdr_prefix);
1767 let mut buf = &bytes[0..10];
1768 assert!(buf.parse::<Ipv4PacketRaw<_>>().is_err());
1769 }
1770
1771 fn create_ipv4_and_ipv6_builders(
1772 proto_v4: Ipv4Proto,
1773 proto_v6: Ipv6Proto,
1774 ) -> (Ipv4PacketBuilder, Ipv6PacketBuilder) {
1775 const IP_DSCP_AND_ECN: DscpAndEcn = DscpAndEcn::new(0x12, 3);
1776 const IP_TTL: u8 = 64;
1777
1778 let mut ipv4_builder =
1779 Ipv4PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, IP_TTL, proto_v4);
1780 ipv4_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
1781 ipv4_builder.id(0x0405);
1782 ipv4_builder.df_flag(true);
1783 ipv4_builder.mf_flag(false);
1784 ipv4_builder.fragment_offset(FragmentOffset::ZERO);
1785
1786 let mut ipv6_builder =
1787 Ipv6PacketBuilder::new(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP, IP_TTL, proto_v6);
1788 ipv6_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
1789 ipv6_builder.flowlabel(0);
1790
1791 (ipv4_builder, ipv6_builder)
1792 }
1793
1794 fn create_tcp_ipv4_and_ipv6_pkt()
1795 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
1796 use crate::tcp::TcpSegmentBuilder;
1797 use core::num::NonZeroU16;
1798
1799 let tcp_src_port: NonZeroU16 = NonZeroU16::new(20).unwrap();
1800 let tcp_dst_port: NonZeroU16 = NonZeroU16::new(30).unwrap();
1801 const TCP_SEQ_NUM: u32 = 4321;
1802 const TCP_ACK_NUM: Option<u32> = Some(1234);
1803 const TCP_WINDOW_SIZE: u16 = 12345;
1804 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1805
1806 let (ipv4_builder, ipv6_builder) =
1807 create_ipv4_and_ipv6_builders(IpProto::Tcp.into(), IpProto::Tcp.into());
1808
1809 let tcp_builder = TcpSegmentBuilder::new(
1810 DEFAULT_SRC_IP,
1811 DEFAULT_DST_IP,
1812 tcp_src_port,
1813 tcp_dst_port,
1814 TCP_SEQ_NUM,
1815 TCP_ACK_NUM,
1816 TCP_WINDOW_SIZE,
1817 );
1818
1819 let v4_pkt_buf = (&PAYLOAD)
1820 .into_serializer()
1821 .wrap_in(tcp_builder)
1822 .wrap_in(ipv4_builder)
1823 .serialize_vec_outer(&mut NoOpSerializationContext)
1824 .unwrap();
1825
1826 let v6_tcp_builder = TcpSegmentBuilder::new(
1827 DEFAULT_V6_SRC_IP,
1828 DEFAULT_V6_DST_IP,
1829 tcp_src_port,
1830 tcp_dst_port,
1831 TCP_SEQ_NUM,
1832 TCP_ACK_NUM,
1833 TCP_WINDOW_SIZE,
1834 );
1835
1836 let v6_pkt_buf = (&PAYLOAD)
1837 .into_serializer()
1838 .wrap_in(v6_tcp_builder)
1839 .wrap_in(ipv6_builder)
1840 .serialize_vec_outer(&mut NoOpSerializationContext)
1841 .unwrap();
1842
1843 (v4_pkt_buf, v6_pkt_buf)
1844 }
1845
1846 #[test]
1847 fn test_nat64_translate_tcp() {
1848 let (mut v4_pkt_buf, expected_v6_pkt_buf) = create_tcp_ipv4_and_ipv6_pkt();
1849
1850 let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1851 let nat64_translation_result =
1852 parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1853
1854 let serializable_pkt = match nat64_translation_result {
1855 Nat64TranslationResult::Forward(s) => s,
1856 _ => panic!("Nat64TranslationResult not of Forward type!"),
1857 };
1858
1859 let translated_v6_pkt_buf =
1860 serializable_pkt.serialize_vec_outer(&mut NoOpSerializationContext).unwrap();
1861
1862 assert_eq!(
1863 expected_v6_pkt_buf.to_flattened_vec(),
1864 translated_v6_pkt_buf.to_flattened_vec()
1865 );
1866 }
1867
1868 fn create_udp_ipv4_and_ipv6_pkt()
1869 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
1870 use crate::udp::UdpPacketBuilder;
1871 use core::num::NonZeroU16;
1872
1873 let udp_src_port: NonZeroU16 = NonZeroU16::new(35000).unwrap();
1874 let udp_dst_port: NonZeroU16 = NonZeroU16::new(53).unwrap();
1875 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1876
1877 let (ipv4_builder, ipv6_builder) =
1878 create_ipv4_and_ipv6_builders(IpProto::Udp.into(), IpProto::Udp.into());
1879
1880 let udp_builder =
1881 UdpPacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, Some(udp_src_port), udp_dst_port);
1882
1883 let v4_pkt_buf = (&PAYLOAD)
1884 .into_serializer()
1885 .wrap_in(udp_builder)
1886 .wrap_in(ipv4_builder)
1887 .serialize_vec_outer(&mut NoOpSerializationContext)
1888 .unwrap();
1889
1890 let v6_udp_builder = UdpPacketBuilder::new(
1891 DEFAULT_V6_SRC_IP,
1892 DEFAULT_V6_DST_IP,
1893 Some(udp_src_port),
1894 udp_dst_port,
1895 );
1896
1897 let v6_pkt_buf = (&PAYLOAD)
1898 .into_serializer()
1899 .wrap_in(v6_udp_builder)
1900 .wrap_in(ipv6_builder)
1901 .serialize_vec_outer(&mut NoOpSerializationContext)
1902 .unwrap();
1903
1904 (v4_pkt_buf, v6_pkt_buf)
1905 }
1906
1907 #[test]
1908 fn test_nat64_translate_udp() {
1909 let (mut v4_pkt_buf, expected_v6_pkt_buf) = create_udp_ipv4_and_ipv6_pkt();
1910
1911 let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1912 let nat64_translation_result =
1913 parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1914
1915 let serializable_pkt = match nat64_translation_result {
1916 Nat64TranslationResult::Forward(s) => s,
1917 _ => panic!(
1918 "Nat64TranslationResult not of Forward type: {:?} ",
1919 nat64_translation_result
1920 ),
1921 };
1922
1923 let translated_v6_pkt_buf =
1924 serializable_pkt.serialize_vec_outer(&mut NoOpSerializationContext).unwrap();
1925
1926 assert_eq!(
1927 expected_v6_pkt_buf.to_flattened_vec(),
1928 translated_v6_pkt_buf.to_flattened_vec()
1929 );
1930 }
1931
1932 #[test]
1933 fn test_nat64_translate_non_tcp_udp_icmp() {
1934 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1935
1936 let (ipv4_builder, ipv6_builder) =
1937 create_ipv4_and_ipv6_builders(Ipv4Proto::Other(50), Ipv6Proto::Other(50));
1938
1939 let mut v4_pkt_buf = (&PAYLOAD)
1940 .into_serializer()
1941 .wrap_in(ipv4_builder)
1942 .serialize_vec_outer(&mut NoOpSerializationContext)
1943 .unwrap();
1944
1945 let expected_v6_pkt_buf = (&PAYLOAD)
1946 .into_serializer()
1947 .wrap_in(ipv6_builder)
1948 .serialize_vec_outer(&mut NoOpSerializationContext)
1949 .unwrap();
1950
1951 let translated_v6_pkt_buf = {
1952 let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1953
1954 let nat64_translation_result =
1955 parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1956
1957 let serializable_pkt = match nat64_translation_result {
1958 Nat64TranslationResult::Forward(s) => s,
1959 _ => panic!(
1960 "Nat64TranslationResult not of Forward type: {:?} ",
1961 nat64_translation_result
1962 ),
1963 };
1964
1965 let translated_buf =
1966 serializable_pkt.serialize_vec_outer(&mut NoOpSerializationContext).unwrap();
1967
1968 translated_buf
1969 };
1970
1971 assert_eq!(
1972 expected_v6_pkt_buf.to_flattened_vec(),
1973 translated_v6_pkt_buf.to_flattened_vec()
1974 );
1975 }
1976
1977 #[test]
1978 fn test_partial_serialize_parsed() {
1979 let packet_bytes = [
1980 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,
1981 5, 7, 8, 9,
1982 ];
1983 let packet_len = packet_bytes.len();
1984 let mut packet_bytes_copy = packet_bytes;
1985 let mut packet_bytes_ref: &mut [u8] = &mut packet_bytes_copy[..];
1986 let packet = packet_bytes_ref.parse::<Ipv4Packet<_>>().unwrap();
1987
1988 for i in 1..(packet_len + 1) {
1989 let mut buf = vec![0u8; i];
1990 let result = packet.partial_serialize(
1991 &mut NoOpSerializationContext,
1992 PacketConstraints::UNCONSTRAINED,
1993 buf.as_mut_slice(),
1994 );
1995
1996 let bytes_written = if i >= packet_len { packet_len } else { i };
1997 assert_eq!(
1998 result,
1999 Ok(PartialSerializeResult { bytes_written, total_size: packet_len })
2000 );
2001 assert_eq!(buf[..bytes_written], packet_bytes[..bytes_written]);
2002 }
2003 }
2004}