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, PacketBuilder,
25 PacketConstraints, ParsablePacket, ParseMetadata, PartialPacketBuilder, PartialSerializeResult,
26 PartialSerializer, SerializeError, SerializeTarget, Serializer,
27};
28use zerocopy::byteorder::network_endian::U16;
29use zerocopy::{
30 FromBytes, Immutable, IntoBytes, KnownLayout, Ref, SplitByteSlice, SplitByteSliceMut, Unaligned,
31};
32
33use crate::error::ParseError;
34use crate::ip::{
35 DscpAndEcn, FragmentOffset, IpExt, IpPacketBuilder, IpProto, Ipv4Proto, Ipv6Proto, Nat64Error,
36 Nat64TranslationResult,
37};
38use crate::ipv6::Ipv6PacketBuilder;
39use crate::tcp::{TcpParseArgs, TcpSegment};
40use crate::udp::{UdpPacket, UdpParseArgs};
41
42pub(crate) use self::inner::IPV4_MIN_HDR_LEN;
43use self::options::{Ipv4Option, Ipv4OptionsImpl};
44
45pub const HDR_PREFIX_LEN: usize = 20;
47
48pub const MAX_HDR_LEN: usize = 60;
50
51pub const MAX_OPTIONS_LEN: usize = MAX_HDR_LEN - HDR_PREFIX_LEN;
53
54const IPV4_FRAGMENT_DATA_BYTE_RANGE: Range<usize> = 4..8;
56
57#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
59#[allow(missing_docs)]
60pub enum Ipv4FragmentType {
61 InitialFragment,
62 NonInitialFragment,
63}
64
65#[derive(KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned)]
68#[repr(C)]
69pub struct HeaderPrefix {
70 version_ihl: u8,
71 dscp_and_ecn: DscpAndEcn,
72 total_len: U16,
73 id: U16,
74 flags_frag_off: [u8; 2],
75 ttl: u8,
76 proto: u8,
77 hdr_checksum: [u8; 2],
78 src_ip: Ipv4Addr,
79 dst_ip: Ipv4Addr,
80}
81
82const IP_VERSION: u8 = 4;
83const VERSION_OFFSET: u8 = 4;
84const IHL_MASK: u8 = 0xF;
85const IHL_MAX: u8 = (1 << VERSION_OFFSET) - 1;
86const FLAGS_OFFSET: u8 = 13;
87const FLAGS_MAX: u8 = (1 << (16 - FLAGS_OFFSET)) - 1;
88const FRAG_OFF_MAX: u16 = (1 << FLAGS_OFFSET) - 1;
89
90impl HeaderPrefix {
91 #[allow(clippy::too_many_arguments)]
92 fn new(
93 ihl: u8,
94 dscp_and_ecn: DscpAndEcn,
95 total_len: u16,
96 id: u16,
97 flags: u8,
98 frag_off: u16,
99 ttl: u8,
100 proto: u8,
101 hdr_checksum: [u8; 2],
102 src_ip: Ipv4Addr,
103 dst_ip: Ipv4Addr,
104 ) -> HeaderPrefix {
105 debug_assert!(ihl <= IHL_MAX);
106 debug_assert!(flags <= FLAGS_MAX);
107 debug_assert!(frag_off <= FRAG_OFF_MAX);
108
109 HeaderPrefix {
110 version_ihl: (IP_VERSION << VERSION_OFFSET) | ihl,
111 dscp_and_ecn,
112 total_len: U16::new(total_len),
113 id: U16::new(id),
114 flags_frag_off: ((u16::from(flags) << FLAGS_OFFSET) | frag_off).to_be_bytes(),
115 ttl,
116 proto,
117 src_ip,
118 dst_ip,
119 hdr_checksum,
120 }
121 }
122
123 fn version(&self) -> u8 {
124 self.version_ihl >> VERSION_OFFSET
125 }
126
127 pub(crate) fn ihl(&self) -> u8 {
129 self.version_ihl & IHL_MASK
130 }
131
132 pub(crate) fn mf_flag(&self) -> bool {
134 self.flags_frag_off[0] & (1 << ((FLAGS_OFFSET - 8) + MF_FLAG_OFFSET)) > 0
139 }
140}
141
142pub trait Ipv4Header {
147 fn get_header_prefix(&self) -> &HeaderPrefix;
149
150 fn dscp_and_ecn(&self) -> DscpAndEcn {
152 self.get_header_prefix().dscp_and_ecn
153 }
154
155 fn id(&self) -> u16 {
157 self.get_header_prefix().id.get()
158 }
159
160 fn df_flag(&self) -> bool {
162 self.get_header_prefix().flags_frag_off[0] & (1 << (5 + DF_FLAG_OFFSET)) > 0
164 }
165
166 fn mf_flag(&self) -> bool {
168 self.get_header_prefix().mf_flag()
169 }
170
171 fn fragment_offset(&self) -> FragmentOffset {
173 FragmentOffset::new_with_lsb(U16::from_bytes(self.get_header_prefix().flags_frag_off).get())
174 }
175
176 fn fragment_type(&self) -> Ipv4FragmentType {
182 match self.fragment_offset().into_raw() {
183 0 => Ipv4FragmentType::InitialFragment,
184 _ => Ipv4FragmentType::NonInitialFragment,
185 }
186 }
187
188 fn ttl(&self) -> u8 {
190 self.get_header_prefix().ttl
191 }
192
193 fn proto(&self) -> Ipv4Proto {
197 Ipv4Proto::from(self.get_header_prefix().proto)
198 }
199
200 fn src_ip(&self) -> Ipv4Addr {
202 self.get_header_prefix().src_ip
203 }
204
205 fn dst_ip(&self) -> Ipv4Addr {
207 self.get_header_prefix().dst_ip
208 }
209
210 fn builder(&self) -> Ipv4PacketBuilder {
212 let mut s = Ipv4PacketBuilder {
213 id: self.id(),
214 dscp_and_ecn: self.dscp_and_ecn(),
215 flags: 0,
216 frag_off: self.fragment_offset().into_raw(),
217 ttl: self.ttl(),
218 proto: self.get_header_prefix().proto.into(),
219 src_ip: self.src_ip(),
220 dst_ip: self.dst_ip(),
221 };
222 s.df_flag(self.df_flag());
223 s.mf_flag(self.mf_flag());
224 s
225 }
226}
227
228impl Ipv4Header for HeaderPrefix {
229 fn get_header_prefix(&self) -> &HeaderPrefix {
230 self
231 }
232}
233
234pub struct Ipv4Packet<B> {
244 hdr_prefix: Ref<B, HeaderPrefix>,
245 options: Options<B>,
246 body: B,
247}
248
249impl<B: SplitByteSlice, I: IpExt> GenericOverIp<I> for Ipv4Packet<B> {
250 type Type = <I as IpExt>::Packet<B>;
251}
252
253impl<B: SplitByteSlice> Ipv4Header for Ipv4Packet<B> {
254 fn get_header_prefix(&self) -> &HeaderPrefix {
255 &self.hdr_prefix
256 }
257}
258
259impl<B: SplitByteSlice> PartialSerializer for Ipv4Packet<B> {
260 fn partial_serialize(
261 &self,
262 _outer: PacketConstraints,
263 mut buffer: &mut [u8],
264 ) -> Result<PartialSerializeResult, SerializeError<Never>> {
265 let hdr_prefix = Ref::bytes(&self.hdr_prefix);
266 let options = self.options.bytes();
267
268 let mut buffer = &mut buffer;
269 let bytes_written = buffer.write_bytes_front_allow_partial(hdr_prefix)
270 + buffer.write_bytes_front_allow_partial(options)
271 + buffer.write_bytes_front_allow_partial(&self.body);
272 let total_size = hdr_prefix.len() + options.len() + self.body.len();
273
274 Ok(PartialSerializeResult { bytes_written, total_size })
275 }
276}
277
278impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv4Packet<B> {
279 type Error = ParseError;
280
281 fn parse_metadata(&self) -> ParseMetadata {
282 ParseMetadata::from_packet(self.header_len(), self.body.len(), 0)
283 }
284
285 fn parse<BV: BufferView<B>>(buffer: BV, _args: ()) -> Result<Self, ParseError> {
286 Ipv4PacketRaw::<B>::parse(buffer, ()).and_then(Ipv4Packet::try_from_raw)
287 }
288}
289
290impl<B: SplitByteSlice> FromRaw<Ipv4PacketRaw<B>, ()> for Ipv4Packet<B> {
291 type Error = ParseError;
292
293 fn try_from_raw_with(raw: Ipv4PacketRaw<B>, _args: ()) -> Result<Self, Self::Error> {
294 let hdr_prefix = raw.hdr_prefix;
297 let hdr_bytes = (hdr_prefix.ihl() * 4) as usize;
298
299 if hdr_bytes < HDR_PREFIX_LEN {
300 return debug_err!(Err(ParseError::Format), "invalid IHL: {}", hdr_prefix.ihl());
301 }
302
303 let options = match raw.options {
304 MaybeParsed::Incomplete(_) => {
305 return debug_err!(Err(ParseError::Format), "Incomplete options");
306 }
307 MaybeParsed::Complete(unchecked) => Options::try_from_raw(unchecked)
308 .map_err(|e| debug_err!(e, "malformed options: {:?}", e))?,
309 };
310
311 if hdr_prefix.version() != 4 {
312 return debug_err!(
313 Err(ParseError::Format),
314 "unexpected IP version: {}",
315 hdr_prefix.version()
316 );
317 }
318
319 let body = match raw.body {
320 MaybeParsed::Incomplete(_) => {
321 if hdr_prefix.mf_flag() {
322 return debug_err!(
323 Err(ParseError::NotSupported),
324 "fragmentation not supported"
325 );
326 } else {
327 return debug_err!(Err(ParseError::Format), "Incomplete body");
328 }
329 }
330 MaybeParsed::Complete(bytes) => bytes,
331 };
332
333 let packet = Ipv4Packet { hdr_prefix, options, body };
334 if packet.compute_header_checksum() != [0, 0] {
335 return debug_err!(Err(ParseError::Checksum), "invalid checksum");
336 }
337 Ok(packet)
338 }
339}
340
341fn compute_header_checksum(hdr_prefix: &[u8], options: &[u8]) -> [u8; 2] {
342 let mut c = Checksum::new();
343 c.add_bytes(hdr_prefix);
344 c.add_bytes(options);
345 c.checksum()
346}
347
348impl<B: SplitByteSlice> Ipv4Packet<B> {
349 pub fn iter_options(&self) -> impl Iterator<Item = Ipv4Option<'_>> {
351 self.options.iter()
352 }
353
354 fn compute_header_checksum(&self) -> [u8; 2] {
356 compute_header_checksum(Ref::bytes(&self.hdr_prefix), self.options.bytes())
357 }
358
359 pub fn body(&self) -> &[u8] {
361 &self.body
362 }
363
364 pub fn header_len(&self) -> usize {
366 Ref::bytes(&self.hdr_prefix).len() + self.options.bytes().len()
367 }
368
369 pub fn src_ipv4(&self) -> Option<Ipv4SourceAddr> {
374 Ipv4SourceAddr::new(self.src_ip())
375 }
376
377 pub fn copy_header_bytes_for_fragment(&self) -> Vec<u8> {
383 let expected_bytes_len = self.header_len();
384 let mut bytes = Vec::with_capacity(expected_bytes_len);
385
386 bytes.extend_from_slice(Ref::bytes(&self.hdr_prefix));
387 bytes.extend_from_slice(self.options.bytes());
388
389 assert_eq!(bytes.len(), expected_bytes_len);
391
392 bytes[IPV4_FRAGMENT_DATA_BYTE_RANGE].copy_from_slice(&[0; 4][..]);
394
395 bytes
396 }
397
398 pub fn nat64_translate(
424 &self,
425 v6_src_addr: Ipv6Addr,
426 v6_dst_addr: Ipv6Addr,
427 ) -> Nat64TranslationResult<impl Serializer<Buffer = EmptyBuf> + Debug + '_, Nat64Error> {
428 #[derive(Debug)]
431 enum Nat64Serializer<T, U, O> {
432 Tcp(T),
433 Udp(U),
434 Other(O),
435 }
436
437 impl<T, U, O> Serializer for Nat64Serializer<T, U, O>
438 where
439 T: Serializer<Buffer = EmptyBuf>,
440 U: Serializer<Buffer = EmptyBuf>,
441 O: Serializer<Buffer = EmptyBuf>,
442 {
443 type Buffer = EmptyBuf;
444 fn serialize<B, P>(
445 self,
446 outer: PacketConstraints,
447 provider: P,
448 ) -> Result<B, (SerializeError<P::Error>, Self)>
449 where
450 B: GrowBufferMut,
451 P: BufferProvider<Self::Buffer, B>,
452 {
453 match self {
454 Nat64Serializer::Tcp(serializer) => serializer
455 .serialize(outer, provider)
456 .map_err(|(err, ser)| (err, Nat64Serializer::Tcp(ser))),
457 Nat64Serializer::Udp(serializer) => serializer
458 .serialize(outer, provider)
459 .map_err(|(err, ser)| (err, Nat64Serializer::Udp(ser))),
460 Nat64Serializer::Other(serializer) => serializer
461 .serialize(outer, provider)
462 .map_err(|(err, ser)| (err, Nat64Serializer::Other(ser))),
463 }
464 }
465
466 fn serialize_new_buf<B: GrowBufferMut, A: LayoutBufferAlloc<B>>(
467 &self,
468 outer: PacketConstraints,
469 alloc: A,
470 ) -> Result<B, SerializeError<A::Error>> {
471 match self {
472 Nat64Serializer::Tcp(serializer) => serializer.serialize_new_buf(outer, alloc),
473 Nat64Serializer::Udp(serializer) => serializer.serialize_new_buf(outer, alloc),
474 Nat64Serializer::Other(serializer) => {
475 serializer.serialize_new_buf(outer, alloc)
476 }
477 }
478 }
479 }
480
481 let v6_builder = |v6_proto| {
482 let mut builder =
483 Ipv6PacketBuilder::new(v6_src_addr, v6_dst_addr, self.ttl(), v6_proto);
484 builder.dscp_and_ecn(self.dscp_and_ecn());
485 builder.flowlabel(0);
486 builder
487 };
488
489 match self.proto() {
490 Ipv4Proto::Igmp => {
491 Nat64TranslationResult::Drop
493 }
494
495 Ipv4Proto::Proto(IpProto::Tcp) => {
496 let v6_pkt_builder = v6_builder(Ipv6Proto::Proto(IpProto::Tcp));
497 let args = TcpParseArgs::new(self.src_ip(), self.dst_ip());
498 match TcpSegment::parse(&mut self.body.as_bytes(), args) {
499 Ok(tcp) => {
500 let tcp_serializer =
504 Nat64Serializer::Tcp(tcp.into_serializer(v6_src_addr, v6_dst_addr));
505 Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(tcp_serializer))
506 }
507 Err(msg) => {
508 debug!("Parsing of TCP segment failed: {:?}", msg);
509
510 let common_serializer =
516 Nat64Serializer::Other(self.body().into_serializer());
517 Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(common_serializer))
518 }
519 }
520 }
521
522 Ipv4Proto::Proto(IpProto::Udp) => {
523 let v6_pkt_builder = v6_builder(Ipv6Proto::Proto(IpProto::Udp));
524 let args = UdpParseArgs::new(self.src_ip(), self.dst_ip());
525 match UdpPacket::parse(&mut self.body.as_bytes(), args) {
526 Ok(udp) => {
527 let udp_serializer =
531 Nat64Serializer::Udp(udp.into_serializer(v6_src_addr, v6_dst_addr));
532 Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(udp_serializer))
533 }
534 Err(msg) => {
535 debug!("Parsing of UDP packet failed: {:?}", msg);
536
537 let common_serializer =
543 Nat64Serializer::Other(self.body().into_serializer());
544 Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(common_serializer))
545 }
546 }
547 }
548
549 Ipv4Proto::Icmp => Nat64TranslationResult::Err(Nat64Error::NotImplemented),
550
551 Ipv4Proto::Other(val) => {
556 let v6_pkt_builder = v6_builder(Ipv6Proto::Other(val));
557 let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
558 Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(common_serializer))
559 }
560
561 Ipv4Proto::Proto(IpProto::Reserved) => Nat64TranslationResult::Drop,
564 }
565 }
566
567 pub fn to_vec(&self) -> Vec<u8> {
569 let Ipv4Packet { hdr_prefix, options, body } = self;
570 let mut buf = Vec::with_capacity(
571 Ref::bytes(&hdr_prefix).len() + options.bytes().len() + body.as_bytes().len(),
572 );
573 buf.extend(Ref::bytes(&hdr_prefix));
574 buf.extend(options.bytes());
575 buf.extend(body.as_bytes());
576 buf
577 }
578}
579
580impl<B: SplitByteSliceMut> Ipv4Packet<B> {
581 pub fn set_src_ip_and_update_checksum(&mut self, addr: Ipv4Addr) {
585 let old_bytes = self.hdr_prefix.src_ip.bytes();
586 self.hdr_prefix.hdr_checksum =
587 internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, addr.bytes());
588 self.hdr_prefix.src_ip = addr;
589 }
590
591 pub fn set_dst_ip_and_update_checksum(&mut self, addr: Ipv4Addr) {
595 let old_bytes = self.hdr_prefix.dst_ip.bytes();
596 self.hdr_prefix.hdr_checksum =
597 internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, addr.bytes());
598 self.hdr_prefix.dst_ip = addr;
599 }
600
601 pub fn set_ttl(&mut self, ttl: u8) {
605 let old_bytes = [self.hdr_prefix.ttl, self.hdr_prefix.proto];
609 let new_bytes = [ttl, self.hdr_prefix.proto];
610 self.hdr_prefix.hdr_checksum =
611 internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, &new_bytes);
612 self.hdr_prefix.ttl = ttl;
613 }
614
615 pub fn body_mut(&mut self) -> &mut [u8] {
617 &mut self.body
618 }
619
620 pub fn parts_with_body_mut(&mut self) -> (&HeaderPrefix, &Options<B>, &mut [u8]) {
623 (&self.hdr_prefix, &self.options, &mut self.body)
624 }
625}
626
627impl<B> Debug for Ipv4Packet<B>
628where
629 B: SplitByteSlice,
630{
631 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
632 f.debug_struct("Ipv4Packet")
633 .field("src_ip", &self.src_ip())
634 .field("dst_ip", &self.dst_ip())
635 .field("id", &self.id())
636 .field("ttl", &self.ttl())
637 .field("proto", &self.proto())
638 .field("frag_off", &self.fragment_offset())
639 .field("dscp", &self.dscp_and_ecn().dscp())
640 .field("ecn", &self.dscp_and_ecn().ecn())
641 .field("mf_flag", &self.mf_flag())
642 .field("df_flag", &self.df_flag())
643 .field("body", &alloc::format!("<{} bytes>", self.body.len()))
644 .finish()
645 }
646}
647
648pub struct Ipv4PacketRaw<B> {
658 hdr_prefix: Ref<B, HeaderPrefix>,
659 options: MaybeParsed<OptionsRaw<B, Ipv4OptionsImpl>, B>,
660 body: MaybeParsed<B, B>,
661}
662
663impl<B> Ipv4PacketRaw<B> {
664 pub fn body_mut(&mut self) -> &mut B {
668 match &mut self.body {
669 MaybeParsed::Complete(b) => b,
670 MaybeParsed::Incomplete(b) => b,
671 }
672 }
673}
674
675impl<B: SplitByteSlice> Ipv4Header for Ipv4PacketRaw<B> {
676 fn get_header_prefix(&self) -> &HeaderPrefix {
677 &self.hdr_prefix
678 }
679}
680
681impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv4PacketRaw<B> {
682 type Error = ParseError;
683
684 fn parse_metadata(&self) -> ParseMetadata {
685 let header_len = Ref::bytes(&self.hdr_prefix).len() + self.options.len();
686 ParseMetadata::from_packet(header_len, self.body.len(), 0)
687 }
688
689 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> Result<Self, ParseError> {
690 let hdr_prefix = buffer
691 .take_obj_front::<HeaderPrefix>()
692 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for header"))?;
693 let hdr_bytes = (hdr_prefix.ihl() * 4) as usize;
694
695 let options = MaybeParsed::take_from_buffer_with(
696 &mut buffer,
697 hdr_bytes.saturating_sub(HDR_PREFIX_LEN),
702 OptionsRaw::new,
703 );
704
705 let total_len: usize = hdr_prefix.total_len.get().into();
706 let body_len = total_len.saturating_sub(hdr_bytes);
707 if buffer.len() > body_len {
708 let _: B = buffer.take_back(buffer.len() - body_len).unwrap();
711 }
712
713 let body = MaybeParsed::new_with_min_len(buffer.into_rest(), body_len);
714
715 Ok(Self { hdr_prefix, options, body })
716 }
717}
718
719impl<B> Ipv4PacketRaw<B> {
720 pub fn options(&self) -> &MaybeParsed<OptionsRaw<B, Ipv4OptionsImpl>, B> {
722 &self.options
723 }
724}
725
726impl<B: SplitByteSlice> Ipv4PacketRaw<B> {
727 pub fn body(&self) -> MaybeParsed<&[u8], &[u8]> {
733 self.body.as_ref().map(|b| b.deref()).map_incomplete(|b| b.deref())
734 }
735
736 pub fn into_body(self) -> MaybeParsed<B, B> {
740 self.body
741 }
742}
743
744impl<B: SplitByteSliceMut> Ipv4PacketRaw<B> {
745 pub fn set_src_ip_and_update_checksum(&mut self, addr: Ipv4Addr) {
749 let old_bytes = self.hdr_prefix.src_ip.bytes();
750 self.hdr_prefix.hdr_checksum =
751 internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, addr.bytes());
752 self.hdr_prefix.src_ip = addr;
753 }
754
755 pub fn set_dst_ip_and_update_checksum(&mut self, addr: Ipv4Addr) {
759 let old_bytes = self.hdr_prefix.dst_ip.bytes();
760 self.hdr_prefix.hdr_checksum =
761 internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, addr.bytes());
762 self.hdr_prefix.dst_ip = addr;
763 }
764}
765
766pub type Options<B> = packet::records::options::Options<B, Ipv4OptionsImpl>;
772
773#[derive(Debug)]
776pub struct Ipv4OptionsTooLongError;
777
778#[derive(Debug, Clone)]
780pub struct Ipv4PacketBuilderWithOptions<'a, I> {
781 prefix_builder: Ipv4PacketBuilder,
782 options: OptionSequenceBuilder<Ipv4Option<'a>, I>,
783}
784
785impl<'a, I> Ipv4PacketBuilderWithOptions<'a, I>
786where
787 I: Iterator + Clone,
788 I::Item: Borrow<Ipv4Option<'a>>,
789{
790 pub fn new<T: IntoIterator<IntoIter = I>>(
796 prefix_builder: Ipv4PacketBuilder,
797 options: T,
798 ) -> Result<Ipv4PacketBuilderWithOptions<'a, I>, Ipv4OptionsTooLongError> {
799 let options = OptionSequenceBuilder::new(options.into_iter());
800 if options.serialized_len() > MAX_OPTIONS_LEN {
801 return Err(Ipv4OptionsTooLongError);
802 }
803 Ok(Ipv4PacketBuilderWithOptions { prefix_builder, options })
804 }
805
806 fn aligned_options_len(&self) -> usize {
807 crate::utils::round_to_next_multiple_of_four(self.options.serialized_len())
809 }
810
811 pub fn prefix_builder(&self) -> &Ipv4PacketBuilder {
813 &self.prefix_builder
814 }
815
816 pub fn prefix_builder_mut(&mut self) -> &mut Ipv4PacketBuilder {
818 &mut self.prefix_builder
819 }
820
821 pub fn options(&self) -> &I {
823 self.options.records()
824 }
825
826 pub fn with_fragment_options(
832 self,
833 first_fragment: bool,
834 ) -> Ipv4PacketBuilderWithOptions<'a, impl Iterator<Item: Borrow<Ipv4Option<'a>>> + Clone> {
835 let Self { prefix_builder, options } = self;
836 Ipv4PacketBuilderWithOptions {
837 prefix_builder,
838 options: OptionSequenceBuilder::new(
841 options
842 .records()
843 .clone()
844 .filter(move |opt| first_fragment || opt.borrow().copied()),
845 ),
846 }
847 }
848}
849
850impl<'a, B> Ipv4PacketBuilderWithOptions<'a, RecordsIter<'a, B, Ipv4OptionsImpl>> {
851 pub fn new_with_records_iter(
854 prefix_builder: Ipv4PacketBuilder,
855 iter: RecordsIter<'a, B, Ipv4OptionsImpl>,
856 ) -> Self {
857 Self { prefix_builder, options: OptionSequenceBuilder::new(iter) }
858 }
859}
860
861impl<'a, I> PacketBuilder for Ipv4PacketBuilderWithOptions<'a, I>
862where
863 I: Iterator + Clone,
864 I::Item: Borrow<Ipv4Option<'a>>,
865{
866 fn constraints(&self) -> PacketConstraints {
867 let header_len = IPV4_MIN_HDR_LEN + self.aligned_options_len();
868 assert_eq!(header_len % 4, 0);
869 PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
870 }
871
872 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
873 let opt_len = self.aligned_options_len();
874 let mut header = &mut &mut target.header[..];
880 let opts = header.take_back_zero(opt_len).expect("too few bytes for Ipv4 options");
881 let Ipv4PacketBuilderWithOptions { prefix_builder, options } = self;
882 options.serialize_into(opts);
883 prefix_builder.serialize(target, body);
884 }
885}
886
887impl<'a, I> PartialPacketBuilder for Ipv4PacketBuilderWithOptions<'a, I>
888where
889 I: Iterator + Clone,
890 I::Item: Borrow<Ipv4Option<'a>>,
891{
892 fn partial_serialize(&self, body_len: usize, header: &mut [u8]) {
893 let Ipv4PacketBuilderWithOptions { prefix_builder, options } = self;
894 prefix_builder.partial_serialize(body_len, header);
895 let options_slice = &mut header[IPV4_MIN_HDR_LEN..];
896 assert_eq!(options_slice.len(), self.aligned_options_len());
897 options.serialize_into(options_slice);
898 }
899}
900
901impl<'a, I> IpPacketBuilder<Ipv4> for Ipv4PacketBuilderWithOptions<'a, I>
902where
903 I: Default + Debug + Clone + Iterator<Item: Borrow<Ipv4Option<'a>>>,
904{
905 fn new(src_ip: Ipv4Addr, dst_ip: Ipv4Addr, ttl: u8, proto: Ipv4Proto) -> Self {
906 Ipv4PacketBuilderWithOptions::new(
907 Ipv4PacketBuilder::new(src_ip, dst_ip, ttl, proto),
908 I::default(),
909 )
910 .expect("packet builder with no options should be valid")
911 }
912
913 fn src_ip(&self) -> Ipv4Addr {
914 self.prefix_builder.src_ip
915 }
916
917 fn set_src_ip(&mut self, addr: Ipv4Addr) {
918 self.prefix_builder.set_src_ip(addr);
919 }
920
921 fn dst_ip(&self) -> Ipv4Addr {
922 self.prefix_builder.dst_ip
923 }
924
925 fn set_dst_ip(&mut self, addr: Ipv4Addr) {
926 self.prefix_builder.set_dst_ip(addr);
927 }
928
929 fn proto(&self) -> Ipv4Proto {
930 self.prefix_builder.proto
931 }
932
933 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
934 self.prefix_builder.set_dscp_and_ecn(dscp_and_ecn)
935 }
936}
937
938#[derive(Debug, Clone, Eq, PartialEq)]
940pub struct Ipv4PacketBuilder {
941 id: u16,
942 dscp_and_ecn: DscpAndEcn,
943 flags: u8,
944 frag_off: u16,
945 ttl: u8,
946 proto: Ipv4Proto,
947 src_ip: Ipv4Addr,
948 dst_ip: Ipv4Addr,
949}
950
951impl Ipv4PacketBuilder {
952 pub fn new<S: Into<Ipv4Addr>, D: Into<Ipv4Addr>>(
954 src_ip: S,
955 dst_ip: D,
956 ttl: u8,
957 proto: Ipv4Proto,
958 ) -> Ipv4PacketBuilder {
959 Ipv4PacketBuilder {
960 id: 0,
961 dscp_and_ecn: DscpAndEcn::default(),
962 flags: 0,
963 frag_off: 0,
964 ttl,
965 proto: proto,
966 src_ip: src_ip.into(),
967 dst_ip: dst_ip.into(),
968 }
969 }
970
971 pub fn dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
973 self.dscp_and_ecn = dscp_and_ecn;
974 }
975
976 pub fn id(&mut self, id: u16) {
978 self.id = id
979 }
980
981 pub fn df_flag(&mut self, df: bool) {
983 if df {
984 self.flags |= 1 << DF_FLAG_OFFSET;
985 } else {
986 self.flags &= !(1 << DF_FLAG_OFFSET);
987 }
988 }
989
990 pub fn mf_flag(&mut self, mf: bool) {
992 if mf {
993 self.flags |= 1 << MF_FLAG_OFFSET;
994 } else {
995 self.flags &= !(1 << MF_FLAG_OFFSET);
996 }
997 }
998
999 pub fn fragment_offset(&mut self, fragment_offset: FragmentOffset) {
1001 self.frag_off = fragment_offset.into_raw();
1002 }
1003
1004 pub fn read_df_flag(&self) -> bool {
1006 (self.flags & (1 << DF_FLAG_OFFSET)) != 0
1007 }
1008
1009 fn get_header_prefix(&self, header_len: usize, total_len: usize) -> HeaderPrefix {
1010 assert_eq!(header_len % 4, 0);
1011 let ihl: u8 = u8::try_from(header_len / 4).expect("Header too large");
1012
1013 let id = if ((self.flags & (1 << DF_FLAG_OFFSET)) == 0)
1023 || ((self.flags & (1 << MF_FLAG_OFFSET)) == 1)
1024 || (self.frag_off > 0)
1025 {
1026 self.id
1027 } else {
1028 0
1029 };
1030
1031 HeaderPrefix::new(
1032 ihl,
1033 self.dscp_and_ecn,
1034 {
1035 debug_assert!(total_len <= core::u16::MAX as usize);
1041 total_len as u16
1042 },
1043 id,
1044 self.flags,
1045 self.frag_off,
1046 self.ttl,
1047 self.proto.into(),
1048 [0, 0], self.src_ip,
1050 self.dst_ip,
1051 )
1052 }
1053}
1054
1055impl PacketBuilder for Ipv4PacketBuilder {
1056 fn constraints(&self) -> PacketConstraints {
1057 PacketConstraints::new(IPV4_MIN_HDR_LEN, 0, 0, (1 << 16) - 1 - IPV4_MIN_HDR_LEN)
1058 }
1059
1060 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
1061 let header_len = target.header.len();
1062 let total_len = header_len + body.len();
1063 let mut hdr_prefix = self.get_header_prefix(header_len, total_len);
1064 let options = &target.header[HDR_PREFIX_LEN..];
1065 let checksum = compute_header_checksum(hdr_prefix.as_bytes(), options);
1066 hdr_prefix.hdr_checksum = checksum;
1067 let mut header = &mut target.header;
1068 header.write_obj_front(&hdr_prefix).expect("too few bytes for IPv4 header prefix");
1069 }
1070}
1071
1072impl PartialPacketBuilder for Ipv4PacketBuilder {
1073 fn partial_serialize(&self, body_len: usize, mut header: &mut [u8]) {
1074 let total_len = header.len() + body_len;
1075 let hdr_prefix = self.get_header_prefix(header.len(), total_len);
1076 (&mut header).write_obj_front(&hdr_prefix).expect("too few bytes for IPv4 header prefix");
1077 }
1078}
1079
1080impl IpPacketBuilder<Ipv4> for Ipv4PacketBuilder {
1081 fn new(src_ip: Ipv4Addr, dst_ip: Ipv4Addr, ttl: u8, proto: Ipv4Proto) -> Self {
1082 Ipv4PacketBuilder::new(src_ip, dst_ip, ttl, proto)
1083 }
1084
1085 fn src_ip(&self) -> Ipv4Addr {
1086 self.src_ip
1087 }
1088
1089 fn set_src_ip(&mut self, addr: Ipv4Addr) {
1090 self.src_ip = addr;
1091 }
1092
1093 fn dst_ip(&self) -> Ipv4Addr {
1094 self.dst_ip
1095 }
1096
1097 fn set_dst_ip(&mut self, addr: Ipv4Addr) {
1098 self.dst_ip = addr;
1099 }
1100
1101 fn proto(&self) -> Ipv4Proto {
1102 self.proto
1103 }
1104
1105 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1106 self.dscp_and_ecn = dscp_and_ecn;
1107 }
1108}
1109
1110const DF_FLAG_OFFSET: u8 = 1;
1112const MF_FLAG_OFFSET: u8 = 0;
1113
1114pub(crate) fn reassemble_fragmented_packet<
1120 B: SplitByteSliceMut,
1121 BV: BufferViewMut<B>,
1122 I: Iterator<Item = Vec<u8>>,
1123>(
1124 mut buffer: BV,
1125 header: Vec<u8>,
1126 body_fragments: I,
1127) -> Result<(), ParseError> {
1128 assert!(header.len() >= HDR_PREFIX_LEN);
1129
1130 let bytes = buffer.as_mut();
1131
1132 bytes[0..header.len()].copy_from_slice(&header[..]);
1134 let mut byte_count = header.len();
1135
1136 for p in body_fragments {
1138 bytes[byte_count..byte_count + p.len()].copy_from_slice(&p[..]);
1139 byte_count += p.len();
1140 }
1141
1142 if byte_count > usize::from(core::u16::MAX) {
1147 return debug_err!(
1148 Err(ParseError::Format),
1149 "fragmented packet length of {} bytes is too large",
1150 byte_count
1151 );
1152 }
1153
1154 let mut header_ref = Ref::<_, HeaderPrefix>::from_prefix(bytes).unwrap().0;
1157
1158 let options_bytes = &header[HDR_PREFIX_LEN..header.len()];
1159
1160 header_ref.total_len.set(u16::try_from(byte_count).unwrap());
1162
1163 header_ref.flags_frag_off = [0; 2];
1166
1167 header_ref.hdr_checksum = [0; 2];
1169 header_ref.hdr_checksum = compute_header_checksum(header_ref.as_bytes(), options_bytes);
1170
1171 Ok(())
1172}
1173
1174pub mod options {
1176 use byteorder::{ByteOrder, NetworkEndian};
1177 use packet::BufferViewMut;
1178 use packet::records::options::{
1179 OptionBuilder, OptionLayout, OptionParseErr, OptionParseLayout, OptionsImpl,
1180 };
1181 use zerocopy::byteorder::network_endian::U16;
1182
1183 const OPTION_KIND_EOL: u8 = 0;
1184 const OPTION_KIND_NOP: u8 = 1;
1185 const OPTION_KIND_RTRALRT: u8 = 148;
1186
1187 const OPTION_RTRALRT_LEN: usize = 2;
1188
1189 #[derive(PartialEq, Eq, Debug, Clone)]
1196 #[allow(missing_docs)]
1197 pub enum Ipv4Option<'a> {
1198 RouterAlert { data: u16 },
1204
1205 Unrecognized { kind: u8, data: &'a [u8] },
1217 }
1218
1219 impl<'a> Ipv4Option<'a> {
1220 pub fn copied(&self) -> bool {
1222 match self {
1223 Ipv4Option::RouterAlert { .. } => true,
1227 Ipv4Option::Unrecognized { kind, .. } => *kind & (1 << 7) != 0,
1228 }
1229 }
1230 }
1231
1232 #[derive(Debug, Clone)]
1234 pub struct Ipv4OptionsImpl;
1235
1236 impl OptionLayout for Ipv4OptionsImpl {
1237 type KindLenField = u8;
1238 }
1239
1240 impl OptionParseLayout for Ipv4OptionsImpl {
1241 type Error = OptionParseErr;
1242 const END_OF_OPTIONS: Option<u8> = Some(0);
1243 const NOP: Option<u8> = Some(1);
1244 }
1245
1246 impl OptionsImpl for Ipv4OptionsImpl {
1247 type Option<'a> = Ipv4Option<'a>;
1248
1249 fn parse<'a>(kind: u8, data: &'a [u8]) -> Result<Option<Ipv4Option<'a>>, OptionParseErr> {
1250 match kind {
1251 self::OPTION_KIND_EOL | self::OPTION_KIND_NOP => {
1252 unreachable!("records::options::Options promises to handle EOL and NOP")
1253 }
1254 self::OPTION_KIND_RTRALRT => {
1255 if data.len() == OPTION_RTRALRT_LEN {
1256 Ok(Some(Ipv4Option::RouterAlert { data: NetworkEndian::read_u16(data) }))
1257 } else {
1258 Err(OptionParseErr)
1259 }
1260 }
1261 kind => {
1262 if data.len() > 38 {
1263 Err(OptionParseErr)
1264 } else {
1265 Ok(Some(Ipv4Option::Unrecognized { kind, data }))
1266 }
1267 }
1268 }
1269 }
1270 }
1271
1272 impl<'a> OptionBuilder for Ipv4Option<'a> {
1273 type Layout = Ipv4OptionsImpl;
1274
1275 fn serialized_len(&self) -> usize {
1276 match self {
1277 Ipv4Option::RouterAlert { .. } => OPTION_RTRALRT_LEN,
1278 Ipv4Option::Unrecognized { data, .. } => data.len(),
1279 }
1280 }
1281
1282 fn option_kind(&self) -> u8 {
1283 match self {
1284 Ipv4Option::RouterAlert { .. } => OPTION_KIND_RTRALRT,
1285 Ipv4Option::Unrecognized { kind, .. } => *kind,
1286 }
1287 }
1288
1289 fn serialize_into(&self, mut buffer: &mut [u8]) {
1290 match self {
1291 Ipv4Option::Unrecognized { data, .. } => buffer.copy_from_slice(data),
1292 Ipv4Option::RouterAlert { data } => {
1293 (&mut buffer).write_obj_front(&U16::new(*data)).unwrap()
1294 }
1295 };
1296 }
1297 }
1298
1299 #[cfg(test)]
1300 mod test {
1301 use packet::records::RecordBuilder;
1302 use packet::records::options::Options;
1303
1304 use super::*;
1305
1306 #[test]
1307 fn test_serialize_router_alert() {
1308 let mut buffer = [0u8; 4];
1309 let option = Ipv4Option::RouterAlert { data: 0 };
1310 <Ipv4Option<'_> as RecordBuilder>::serialize_into(&option, &mut buffer);
1311 assert_eq!(buffer[0], 148);
1312 assert_eq!(buffer[1], 4);
1313 assert_eq!(buffer[2], 0);
1314 assert_eq!(buffer[3], 0);
1315 }
1316
1317 #[test]
1318 fn test_parse_router_alert() {
1319 let mut buffer: Vec<u8> = vec![148, 4, 0, 0];
1320 let options = Options::<_, Ipv4OptionsImpl>::parse(buffer.as_mut()).unwrap();
1321 let rtralt = options.iter().next().unwrap();
1322 assert_eq!(rtralt, Ipv4Option::RouterAlert { data: 0 });
1323 }
1324 }
1325}
1326
1327mod inner {
1328 pub const IPV4_MIN_HDR_LEN: usize = super::HDR_PREFIX_LEN;
1330}
1331
1332pub mod testutil {
1334 pub use super::inner::IPV4_MIN_HDR_LEN;
1335
1336 pub const IPV4_TTL_OFFSET: usize = 8;
1338
1339 pub const IPV4_CHECKSUM_OFFSET: usize = 10;
1341}
1342
1343#[cfg(test)]
1344mod tests {
1345 use net_types::ethernet::Mac;
1346 use packet::{Buf, FragmentedBuffer, ParseBuffer};
1347
1348 use super::*;
1349 use crate::ethernet::{
1350 ETHERNET_MIN_BODY_LEN_NO_TAG, EtherType, EthernetFrame, EthernetFrameBuilder,
1351 EthernetFrameLengthCheck,
1352 };
1353 use crate::testutil::*;
1354
1355 const DEFAULT_SRC_MAC: Mac = Mac::new([1, 2, 3, 4, 5, 6]);
1356 const DEFAULT_DST_MAC: Mac = Mac::new([7, 8, 9, 0, 1, 2]);
1357 const DEFAULT_SRC_IP: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1358 const DEFAULT_DST_IP: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1359 const DEFAULT_V6_SRC_IP: Ipv6Addr = Ipv6Addr::new([0x2001, 0x0db8, 0, 0, 0, 0, 0, 1]);
1361 const DEFAULT_V6_DST_IP: Ipv6Addr = Ipv6Addr::new([0x2001, 0x0db8, 0, 0, 0, 0, 0, 2]);
1363
1364 #[test]
1365 fn test_parse_serialize_full_tcp() {
1366 use crate::testdata::tls_client_hello_v4::*;
1367
1368 let mut buf = ETHERNET_FRAME.bytes;
1369 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1370 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1371
1372 let mut body = frame.body();
1373 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1374 verify_ipv4_packet(&packet, IPV4_PACKET);
1375
1376 let buffer = packet
1378 .body()
1379 .into_serializer()
1380 .wrap_in(packet.builder())
1381 .wrap_in(frame.builder())
1382 .serialize_vec_outer()
1383 .unwrap();
1384 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1385
1386 assert_eq!(&packet.to_vec()[..], IPV4_PACKET.bytes);
1388 }
1389
1390 #[test]
1391 fn test_parse_serialize_full_udp() {
1392 use crate::testdata::dns_request_v4::*;
1393
1394 let mut buf = ETHERNET_FRAME.bytes;
1395 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1396 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1397
1398 let mut body = frame.body();
1399 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1400 verify_ipv4_packet(&packet, IPV4_PACKET);
1401
1402 let buffer = packet
1404 .body()
1405 .into_serializer()
1406 .wrap_in(packet.builder())
1407 .wrap_in(frame.builder())
1408 .serialize_vec_outer()
1409 .unwrap();
1410 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1411
1412 assert_eq!(&packet.to_vec()[..], IPV4_PACKET.bytes);
1414 }
1415
1416 #[test]
1417 fn test_parse_serialize_with_options() {
1418 use crate::testdata::igmpv2_membership::report::*;
1421
1422 let mut buf = IP_PACKET_BYTES;
1423 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1424 assert_eq!(packet.iter_options().count(), 1);
1425
1426 assert_eq!(&packet.to_vec()[..], IP_PACKET_BYTES);
1431 }
1432
1433 fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; 20] {
1434 zerocopy::transmute!(hdr_prefix)
1435 }
1436
1437 fn new_hdr_prefix() -> HeaderPrefix {
1440 HeaderPrefix::new(
1441 5,
1442 DscpAndEcn::default(),
1443 20,
1444 0x0102,
1445 0,
1446 0,
1447 0x03,
1448 IpProto::Tcp.into(),
1449 [0xa6, 0xcf],
1450 DEFAULT_SRC_IP,
1451 DEFAULT_DST_IP,
1452 )
1453 }
1454
1455 #[test]
1456 fn test_parse() {
1457 let mut bytes = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1458 let packet = bytes.parse::<Ipv4Packet<_>>().unwrap();
1459 assert_eq!(packet.id(), 0x0102);
1460 assert_eq!(packet.ttl(), 0x03);
1461 assert_eq!(packet.proto(), IpProto::Tcp.into());
1462 assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1463 assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1464 assert_eq!(packet.body(), []);
1465 }
1466
1467 #[test]
1468 fn test_parse_padding() {
1469 let mut buffer = Buf::new(Vec::new(), ..)
1471 .wrap_in(Ipv4PacketBuilder::new(DEFAULT_DST_IP, DEFAULT_DST_IP, 0, IpProto::Tcp.into()))
1472 .wrap_in(EthernetFrameBuilder::new(
1473 DEFAULT_SRC_MAC,
1474 DEFAULT_DST_MAC,
1475 EtherType::Ipv4,
1476 ETHERNET_MIN_BODY_LEN_NO_TAG,
1477 ))
1478 .serialize_vec_outer()
1479 .unwrap();
1480 let _: EthernetFrame<_> =
1481 buffer.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1482 assert_eq!(buffer.len(), 46);
1485 let packet = buffer.parse::<Ipv4Packet<_>>().unwrap();
1486 assert_eq!(packet.body().len(), 0);
1489 assert_eq!(buffer.len(), 0);
1493 }
1494
1495 #[test]
1496 fn test_parse_error() {
1497 let mut hdr_prefix = new_hdr_prefix();
1499 hdr_prefix.version_ihl = (5 << 4) | 5;
1500 assert_eq!(
1501 (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1502 ParseError::Format.into()
1503 );
1504
1505 let mut hdr_prefix = new_hdr_prefix();
1508 hdr_prefix.version_ihl = (4 << 4) | 4;
1509 assert_eq!(
1510 (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1511 ParseError::Format.into()
1512 );
1513
1514 let mut hdr_prefix = new_hdr_prefix();
1517 hdr_prefix.version_ihl = (4 << 4) | 6;
1518 assert_eq!(
1519 (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1520 ParseError::Format.into()
1521 );
1522 }
1523
1524 fn new_builder() -> Ipv4PacketBuilder {
1526 Ipv4PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, 64, IpProto::Tcp.into())
1527 }
1528
1529 #[test]
1530 fn test_fragment_type() {
1531 fn test_fragment_type_helper(fragment_offset: u16, expect_fragment_type: Ipv4FragmentType) {
1532 let mut builder = new_builder();
1533 builder.fragment_offset(FragmentOffset::new(fragment_offset).unwrap());
1534
1535 let mut buf = [0; IPV4_MIN_HDR_LEN]
1536 .into_serializer()
1537 .wrap_in(builder)
1538 .serialize_vec_outer()
1539 .unwrap();
1540
1541 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1542 assert_eq!(packet.fragment_type(), expect_fragment_type);
1543 }
1544
1545 test_fragment_type_helper(0x0000, Ipv4FragmentType::InitialFragment);
1546 test_fragment_type_helper(0x0008, Ipv4FragmentType::NonInitialFragment);
1547 }
1548
1549 #[test]
1550 fn test_serialize() {
1551 let mut builder = new_builder();
1552 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
1553 builder.id(0x0405);
1554 builder.df_flag(true);
1555 builder.mf_flag(true);
1556 builder.fragment_offset(FragmentOffset::new(0x0607).unwrap());
1557
1558 let mut buf = (&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9])
1559 .into_serializer()
1560 .wrap_in(builder)
1561 .serialize_vec_outer()
1562 .unwrap();
1563 assert_eq!(
1564 buf.as_ref(),
1565 [
1566 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,
1567 4, 5, 7, 8, 9
1568 ]
1569 );
1570 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1571 assert_eq!(packet.dscp_and_ecn().dscp(), 0x12);
1572 assert_eq!(packet.dscp_and_ecn().ecn(), 3);
1573 assert_eq!(packet.id(), 0x0405);
1574 assert!(packet.df_flag());
1575 assert!(packet.mf_flag());
1576 assert_eq!(packet.fragment_offset().into_raw(), 0x0607);
1577 assert_eq!(packet.fragment_type(), Ipv4FragmentType::NonInitialFragment);
1578 }
1579
1580 #[test]
1581 fn test_partial_serialize() {
1582 let mut builder = new_builder();
1583 builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
1584 builder.id(0x0405);
1585 builder.df_flag(true);
1586 builder.mf_flag(true);
1587 builder.fragment_offset(FragmentOffset::new(0x0607).unwrap());
1588 let body = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1589 let packet = (&body).into_serializer().wrap_in(builder);
1590 const HEADER_LEN: usize = 20;
1591
1592 const HEADER: [u8; HEADER_LEN] =
1595 [69, 75, 0, 30, 4, 5, 102, 7, 64, 6, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8];
1596 let mut expected_partial = HEADER.to_vec();
1597 expected_partial.resize(expected_partial.len() + body.len(), 0);
1598
1599 for i in 1..expected_partial.len() {
1600 let mut buf = vec![0u8; i];
1601 let result =
1602 packet.partial_serialize(PacketConstraints::UNCONSTRAINED, buf.as_mut_slice());
1603
1604 let bytes_written = if i >= HEADER_LEN { HEADER_LEN } else { 0 };
1607 assert_eq!(
1608 result,
1609 Ok(PartialSerializeResult { bytes_written, total_size: body.len() + HEADER_LEN })
1610 );
1611 if bytes_written > 0 {
1612 assert_eq!(buf, expected_partial[..i]);
1613 }
1614 }
1615 }
1616
1617 #[test]
1618 fn test_serialize_id_unset() {
1619 let mut builder = new_builder();
1620 builder.id(0x0405);
1621 builder.df_flag(true);
1622
1623 let mut buf = (&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9])
1624 .into_serializer()
1625 .wrap_in(builder)
1626 .serialize_vec_outer()
1627 .unwrap();
1628 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1629 assert_eq!(packet.id(), 0);
1630 assert!(packet.df_flag());
1631 assert_eq!(packet.mf_flag(), false);
1632 assert_eq!(packet.fragment_offset().into_raw(), 0);
1633 assert_eq!(packet.fragment_type(), Ipv4FragmentType::InitialFragment);
1634 }
1635
1636 #[test]
1637 fn test_serialize_zeroes() {
1638 let mut buf_0 = [0; IPV4_MIN_HDR_LEN];
1641 let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], IPV4_MIN_HDR_LEN..)
1642 .wrap_in(new_builder())
1643 .serialize_vec_outer()
1644 .unwrap()
1645 .unwrap_a();
1646 let mut buf_1 = [0xFF; IPV4_MIN_HDR_LEN];
1647 let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], IPV4_MIN_HDR_LEN..)
1648 .wrap_in(new_builder())
1649 .serialize_vec_outer()
1650 .unwrap()
1651 .unwrap_a();
1652 assert_eq!(buf_0, buf_1);
1653 }
1654
1655 #[test]
1656 #[should_panic(expected = "(SizeLimitExceeded, Nested { inner: Buf { buf:")]
1657 fn test_serialize_panic_packet_length() {
1658 let _: Buf<&mut [u8]> = Buf::new(&mut [0; (1 << 16) - IPV4_MIN_HDR_LEN][..], ..)
1660 .wrap_in(new_builder())
1661 .serialize_vec_outer()
1662 .unwrap()
1663 .unwrap_a();
1664 }
1665
1666 #[test]
1667 fn test_copy_header_bytes_for_fragment() {
1668 let hdr_prefix = new_hdr_prefix();
1669 let mut bytes = hdr_prefix_to_bytes(hdr_prefix);
1670 let mut buf = &bytes[..];
1671 let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1672 let copied_bytes = packet.copy_header_bytes_for_fragment();
1673 bytes[IPV4_FRAGMENT_DATA_BYTE_RANGE].copy_from_slice(&[0; 4][..]);
1674 assert_eq!(&copied_bytes[..], &bytes[..]);
1675 }
1676
1677 #[test]
1678 fn test_partial_parsing() {
1679 use core::ops::Deref as _;
1680
1681 let mut hdr_prefix = new_hdr_prefix();
1684 hdr_prefix.total_len = U16::new(256);
1685 let mut bytes = hdr_prefix_to_bytes(hdr_prefix)[..].to_owned();
1686 const PAYLOAD: &[u8] = &[1, 2, 3, 4, 5];
1687 bytes.extend(PAYLOAD);
1688 let mut buf = &bytes[..];
1689 let packet = buf.parse::<Ipv4PacketRaw<_>>().unwrap();
1690 let Ipv4PacketRaw { hdr_prefix, options, body } = &packet;
1691 assert_eq!(Ref::bytes(&hdr_prefix), &bytes[0..20]);
1692 assert_eq!(options.as_ref().complete().unwrap().deref(), []);
1693 assert_eq!(body, &MaybeParsed::Incomplete(PAYLOAD));
1695 assert!(Ipv4Packet::try_from_raw(packet).is_err());
1697
1698 let mut hdr_prefix = new_hdr_prefix();
1700 hdr_prefix.version_ihl = (4 << 4) | 10;
1701 let bytes = hdr_prefix_to_bytes(hdr_prefix);
1702 let mut buf = &bytes[..];
1703 let packet = buf.parse::<Ipv4PacketRaw<_>>().unwrap();
1704 let Ipv4PacketRaw { hdr_prefix, options, body } = &packet;
1705 assert_eq!(Ref::bytes(&hdr_prefix), bytes);
1706 assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
1707 assert_eq!(body.complete().unwrap(), []);
1708 assert!(Ipv4Packet::try_from_raw(packet).is_err());
1710
1711 let hdr_prefix = new_hdr_prefix();
1713 let bytes = &hdr_prefix_to_bytes(hdr_prefix);
1714 let mut buf = &bytes[0..10];
1715 assert!(buf.parse::<Ipv4PacketRaw<_>>().is_err());
1716 }
1717
1718 fn create_ipv4_and_ipv6_builders(
1719 proto_v4: Ipv4Proto,
1720 proto_v6: Ipv6Proto,
1721 ) -> (Ipv4PacketBuilder, Ipv6PacketBuilder) {
1722 const IP_DSCP_AND_ECN: DscpAndEcn = DscpAndEcn::new(0x12, 3);
1723 const IP_TTL: u8 = 64;
1724
1725 let mut ipv4_builder =
1726 Ipv4PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, IP_TTL, proto_v4);
1727 ipv4_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
1728 ipv4_builder.id(0x0405);
1729 ipv4_builder.df_flag(true);
1730 ipv4_builder.mf_flag(false);
1731 ipv4_builder.fragment_offset(FragmentOffset::ZERO);
1732
1733 let mut ipv6_builder =
1734 Ipv6PacketBuilder::new(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP, IP_TTL, proto_v6);
1735 ipv6_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
1736 ipv6_builder.flowlabel(0);
1737
1738 (ipv4_builder, ipv6_builder)
1739 }
1740
1741 fn create_tcp_ipv4_and_ipv6_pkt()
1742 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
1743 use crate::tcp::TcpSegmentBuilder;
1744 use core::num::NonZeroU16;
1745
1746 let tcp_src_port: NonZeroU16 = NonZeroU16::new(20).unwrap();
1747 let tcp_dst_port: NonZeroU16 = NonZeroU16::new(30).unwrap();
1748 const TCP_SEQ_NUM: u32 = 4321;
1749 const TCP_ACK_NUM: Option<u32> = Some(1234);
1750 const TCP_WINDOW_SIZE: u16 = 12345;
1751 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1752
1753 let (ipv4_builder, ipv6_builder) =
1754 create_ipv4_and_ipv6_builders(IpProto::Tcp.into(), IpProto::Tcp.into());
1755
1756 let tcp_builder = TcpSegmentBuilder::new(
1757 DEFAULT_SRC_IP,
1758 DEFAULT_DST_IP,
1759 tcp_src_port,
1760 tcp_dst_port,
1761 TCP_SEQ_NUM,
1762 TCP_ACK_NUM,
1763 TCP_WINDOW_SIZE,
1764 );
1765
1766 let v4_pkt_buf = (&PAYLOAD)
1767 .into_serializer()
1768 .wrap_in(tcp_builder)
1769 .wrap_in(ipv4_builder)
1770 .serialize_vec_outer()
1771 .unwrap();
1772
1773 let v6_tcp_builder = TcpSegmentBuilder::new(
1774 DEFAULT_V6_SRC_IP,
1775 DEFAULT_V6_DST_IP,
1776 tcp_src_port,
1777 tcp_dst_port,
1778 TCP_SEQ_NUM,
1779 TCP_ACK_NUM,
1780 TCP_WINDOW_SIZE,
1781 );
1782
1783 let v6_pkt_buf = (&PAYLOAD)
1784 .into_serializer()
1785 .wrap_in(v6_tcp_builder)
1786 .wrap_in(ipv6_builder)
1787 .serialize_vec_outer()
1788 .unwrap();
1789
1790 (v4_pkt_buf, v6_pkt_buf)
1791 }
1792
1793 #[test]
1794 fn test_nat64_translate_tcp() {
1795 let (mut v4_pkt_buf, expected_v6_pkt_buf) = create_tcp_ipv4_and_ipv6_pkt();
1796
1797 let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1798 let nat64_translation_result =
1799 parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1800
1801 let serializable_pkt = match nat64_translation_result {
1802 Nat64TranslationResult::Forward(s) => s,
1803 _ => panic!("Nat64TranslationResult not of Forward type!"),
1804 };
1805
1806 let translated_v6_pkt_buf = serializable_pkt.serialize_vec_outer().unwrap();
1807
1808 assert_eq!(
1809 expected_v6_pkt_buf.to_flattened_vec(),
1810 translated_v6_pkt_buf.to_flattened_vec()
1811 );
1812 }
1813
1814 fn create_udp_ipv4_and_ipv6_pkt()
1815 -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
1816 use crate::udp::UdpPacketBuilder;
1817 use core::num::NonZeroU16;
1818
1819 let udp_src_port: NonZeroU16 = NonZeroU16::new(35000).unwrap();
1820 let udp_dst_port: NonZeroU16 = NonZeroU16::new(53).unwrap();
1821 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1822
1823 let (ipv4_builder, ipv6_builder) =
1824 create_ipv4_and_ipv6_builders(IpProto::Udp.into(), IpProto::Udp.into());
1825
1826 let udp_builder =
1827 UdpPacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, Some(udp_src_port), udp_dst_port);
1828
1829 let v4_pkt_buf = (&PAYLOAD)
1830 .into_serializer()
1831 .wrap_in(udp_builder)
1832 .wrap_in(ipv4_builder)
1833 .serialize_vec_outer()
1834 .unwrap();
1835
1836 let v6_udp_builder = UdpPacketBuilder::new(
1837 DEFAULT_V6_SRC_IP,
1838 DEFAULT_V6_DST_IP,
1839 Some(udp_src_port),
1840 udp_dst_port,
1841 );
1842
1843 let v6_pkt_buf = (&PAYLOAD)
1844 .into_serializer()
1845 .wrap_in(v6_udp_builder)
1846 .wrap_in(ipv6_builder)
1847 .serialize_vec_outer()
1848 .unwrap();
1849
1850 (v4_pkt_buf, v6_pkt_buf)
1851 }
1852
1853 #[test]
1854 fn test_nat64_translate_udp() {
1855 let (mut v4_pkt_buf, expected_v6_pkt_buf) = create_udp_ipv4_and_ipv6_pkt();
1856
1857 let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1858 let nat64_translation_result =
1859 parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1860
1861 let serializable_pkt = match nat64_translation_result {
1862 Nat64TranslationResult::Forward(s) => s,
1863 _ => panic!(
1864 "Nat64TranslationResult not of Forward type: {:?} ",
1865 nat64_translation_result
1866 ),
1867 };
1868
1869 let translated_v6_pkt_buf = serializable_pkt.serialize_vec_outer().unwrap();
1870
1871 assert_eq!(
1872 expected_v6_pkt_buf.to_flattened_vec(),
1873 translated_v6_pkt_buf.to_flattened_vec()
1874 );
1875 }
1876
1877 #[test]
1878 fn test_nat64_translate_non_tcp_udp_icmp() {
1879 const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1880
1881 let (ipv4_builder, ipv6_builder) =
1882 create_ipv4_and_ipv6_builders(Ipv4Proto::Other(50), Ipv6Proto::Other(50));
1883
1884 let mut v4_pkt_buf =
1885 (&PAYLOAD).into_serializer().wrap_in(ipv4_builder).serialize_vec_outer().unwrap();
1886
1887 let expected_v6_pkt_buf =
1888 (&PAYLOAD).into_serializer().wrap_in(ipv6_builder).serialize_vec_outer().unwrap();
1889
1890 let translated_v6_pkt_buf = {
1891 let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1892
1893 let nat64_translation_result =
1894 parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1895
1896 let serializable_pkt = match nat64_translation_result {
1897 Nat64TranslationResult::Forward(s) => s,
1898 _ => panic!(
1899 "Nat64TranslationResult not of Forward type: {:?} ",
1900 nat64_translation_result
1901 ),
1902 };
1903
1904 let translated_buf = serializable_pkt.serialize_vec_outer().unwrap();
1905
1906 translated_buf
1907 };
1908
1909 assert_eq!(
1910 expected_v6_pkt_buf.to_flattened_vec(),
1911 translated_v6_pkt_buf.to_flattened_vec()
1912 );
1913 }
1914
1915 #[test]
1916 fn test_partial_serialize_parsed() {
1917 let packet_bytes = [
1918 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,
1919 5, 7, 8, 9,
1920 ];
1921 let packet_len = packet_bytes.len();
1922 let mut packet_bytes_copy = packet_bytes;
1923 let mut packet_bytes_ref: &mut [u8] = &mut packet_bytes_copy[..];
1924 let packet = packet_bytes_ref.parse::<Ipv4Packet<_>>().unwrap();
1925
1926 for i in 1..(packet_len + 1) {
1927 let mut buf = vec![0u8; i];
1928 let result =
1929 packet.partial_serialize(PacketConstraints::UNCONSTRAINED, buf.as_mut_slice());
1930
1931 let bytes_written = if i >= packet_len { packet_len } else { i };
1932 assert_eq!(
1933 result,
1934 Ok(PartialSerializeResult { bytes_written, total_size: packet_len })
1935 );
1936 assert_eq!(buf[..bytes_written], packet_bytes[..bytes_written]);
1937 }
1938 }
1939}