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::{IpParseError, IpParseResult, 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 Ipv4OnlyMeta {
236 pub id: u16,
238 pub fragment_type: Ipv4FragmentType,
240}
241
242pub struct Ipv4Packet<B> {
252 hdr_prefix: Ref<B, HeaderPrefix>,
253 options: Options<B>,
254 body: B,
255}
256
257impl<B: SplitByteSlice, I: IpExt> GenericOverIp<I> for Ipv4Packet<B> {
258 type Type = <I as IpExt>::Packet<B>;
259}
260
261impl<B: SplitByteSlice> Ipv4Header for Ipv4Packet<B> {
262 fn get_header_prefix(&self) -> &HeaderPrefix {
263 &self.hdr_prefix
264 }
265}
266
267impl<B: SplitByteSlice> PartialSerializer for Ipv4Packet<B> {
268 fn partial_serialize(
269 &self,
270 _outer: PacketConstraints,
271 mut buffer: &mut [u8],
272 ) -> Result<PartialSerializeResult, SerializeError<Never>> {
273 let hdr_prefix = Ref::bytes(&self.hdr_prefix);
274 let options = self.options.bytes();
275
276 let mut buffer = &mut buffer;
277 let bytes_written = buffer.write_bytes_front_allow_partial(hdr_prefix)
278 + buffer.write_bytes_front_allow_partial(options)
279 + buffer.write_bytes_front_allow_partial(&self.body);
280 let total_size = hdr_prefix.len() + options.len() + self.body.len();
281
282 Ok(PartialSerializeResult { bytes_written, total_size })
283 }
284}
285
286impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv4Packet<B> {
287 type Error = IpParseError<Ipv4>;
288
289 fn parse_metadata(&self) -> ParseMetadata {
290 ParseMetadata::from_packet(self.header_len(), self.body.len(), 0)
291 }
292
293 fn parse<BV: BufferView<B>>(buffer: BV, _args: ()) -> IpParseResult<Ipv4, Self> {
294 Ipv4PacketRaw::<B>::parse(buffer, ()).and_then(Ipv4Packet::try_from_raw)
295 }
296}
297
298impl<B: SplitByteSlice> FromRaw<Ipv4PacketRaw<B>, ()> for Ipv4Packet<B> {
299 type Error = IpParseError<Ipv4>;
300
301 fn try_from_raw_with(raw: Ipv4PacketRaw<B>, _args: ()) -> Result<Self, Self::Error> {
302 let hdr_prefix = raw.hdr_prefix;
305 let hdr_bytes = (hdr_prefix.ihl() * 4) as usize;
306
307 if hdr_bytes < HDR_PREFIX_LEN {
308 return debug_err!(Err(ParseError::Format.into()), "invalid IHL: {}", hdr_prefix.ihl());
309 }
310
311 let options = match raw.options {
312 MaybeParsed::Incomplete(_) => {
313 return debug_err!(Err(ParseError::Format.into()), "Incomplete options");
314 }
315 MaybeParsed::Complete(unchecked) => Options::try_from_raw(unchecked)
316 .map_err(|e| debug_err!(e, "malformed options: {:?}", e))?,
317 };
318
319 if hdr_prefix.version() != 4 {
320 return debug_err!(
321 Err(ParseError::Format.into()),
322 "unexpected IP version: {}",
323 hdr_prefix.version()
324 );
325 }
326
327 let body = match raw.body {
328 MaybeParsed::Incomplete(_) => {
329 if hdr_prefix.mf_flag() {
330 return debug_err!(
331 Err(ParseError::NotSupported.into()),
332 "fragmentation not supported"
333 );
334 } else {
335 return debug_err!(Err(ParseError::Format.into()), "Incomplete body");
336 }
337 }
338 MaybeParsed::Complete(bytes) => bytes,
339 };
340
341 let packet = Ipv4Packet { hdr_prefix, options, body };
342 if packet.compute_header_checksum() != [0, 0] {
343 return debug_err!(Err(ParseError::Checksum.into()), "invalid checksum");
344 }
345 Ok(packet)
346 }
347}
348
349fn compute_header_checksum(hdr_prefix: &[u8], options: &[u8]) -> [u8; 2] {
350 let mut c = Checksum::new();
351 c.add_bytes(hdr_prefix);
352 c.add_bytes(options);
353 c.checksum()
354}
355
356impl<B: SplitByteSlice> Ipv4Packet<B> {
357 pub fn iter_options(&self) -> impl Iterator<Item = Ipv4Option<'_>> {
359 self.options.iter()
360 }
361
362 fn compute_header_checksum(&self) -> [u8; 2] {
364 compute_header_checksum(Ref::bytes(&self.hdr_prefix), self.options.bytes())
365 }
366
367 pub fn body(&self) -> &[u8] {
369 &self.body
370 }
371
372 pub fn header_len(&self) -> usize {
374 Ref::bytes(&self.hdr_prefix).len() + self.options.bytes().len()
375 }
376
377 pub fn src_ipv4(&self) -> Option<Ipv4SourceAddr> {
382 Ipv4SourceAddr::new(self.src_ip())
383 }
384
385 pub fn copy_header_bytes_for_fragment(&self) -> Vec<u8> {
391 let expected_bytes_len = self.header_len();
392 let mut bytes = Vec::with_capacity(expected_bytes_len);
393
394 bytes.extend_from_slice(Ref::bytes(&self.hdr_prefix));
395 bytes.extend_from_slice(self.options.bytes());
396
397 assert_eq!(bytes.len(), expected_bytes_len);
399
400 bytes[IPV4_FRAGMENT_DATA_BYTE_RANGE].copy_from_slice(&[0; 4][..]);
402
403 bytes
404 }
405
406 pub fn nat64_translate(
432 &self,
433 v6_src_addr: Ipv6Addr,
434 v6_dst_addr: Ipv6Addr,
435 ) -> Nat64TranslationResult<impl Serializer<Buffer = EmptyBuf> + Debug + '_, Nat64Error> {
436 #[derive(Debug)]
439 enum Nat64Serializer<T, U, O> {
440 Tcp(T),
441 Udp(U),
442 Other(O),
443 }
444
445 impl<T, U, O> Serializer for Nat64Serializer<T, U, O>
446 where
447 T: Serializer<Buffer = EmptyBuf>,
448 U: Serializer<Buffer = EmptyBuf>,
449 O: Serializer<Buffer = EmptyBuf>,
450 {
451 type Buffer = EmptyBuf;
452 fn serialize<B, P>(
453 self,
454 outer: PacketConstraints,
455 provider: P,
456 ) -> Result<B, (SerializeError<P::Error>, Self)>
457 where
458 B: GrowBufferMut,
459 P: BufferProvider<Self::Buffer, B>,
460 {
461 match self {
462 Nat64Serializer::Tcp(serializer) => serializer
463 .serialize(outer, provider)
464 .map_err(|(err, ser)| (err, Nat64Serializer::Tcp(ser))),
465 Nat64Serializer::Udp(serializer) => serializer
466 .serialize(outer, provider)
467 .map_err(|(err, ser)| (err, Nat64Serializer::Udp(ser))),
468 Nat64Serializer::Other(serializer) => serializer
469 .serialize(outer, provider)
470 .map_err(|(err, ser)| (err, Nat64Serializer::Other(ser))),
471 }
472 }
473
474 fn serialize_new_buf<B: GrowBufferMut, A: LayoutBufferAlloc<B>>(
475 &self,
476 outer: PacketConstraints,
477 alloc: A,
478 ) -> Result<B, SerializeError<A::Error>> {
479 match self {
480 Nat64Serializer::Tcp(serializer) => serializer.serialize_new_buf(outer, alloc),
481 Nat64Serializer::Udp(serializer) => serializer.serialize_new_buf(outer, alloc),
482 Nat64Serializer::Other(serializer) => {
483 serializer.serialize_new_buf(outer, alloc)
484 }
485 }
486 }
487 }
488
489 let v6_builder = |v6_proto| {
490 let mut builder =
491 Ipv6PacketBuilder::new(v6_src_addr, v6_dst_addr, self.ttl(), v6_proto);
492 builder.dscp_and_ecn(self.dscp_and_ecn());
493 builder.flowlabel(0);
494 builder
495 };
496
497 match self.proto() {
498 Ipv4Proto::Igmp => {
499 Nat64TranslationResult::Drop
501 }
502
503 Ipv4Proto::Proto(IpProto::Tcp) => {
504 let v6_pkt_builder = v6_builder(Ipv6Proto::Proto(IpProto::Tcp));
505 let args = TcpParseArgs::new(self.src_ip(), self.dst_ip());
506 match TcpSegment::parse(&mut self.body.as_bytes(), args) {
507 Ok(tcp) => {
508 let tcp_serializer =
512 Nat64Serializer::Tcp(tcp.into_serializer(v6_src_addr, v6_dst_addr));
513 Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(tcp_serializer))
514 }
515 Err(msg) => {
516 debug!("Parsing of TCP segment failed: {:?}", msg);
517
518 let common_serializer =
524 Nat64Serializer::Other(self.body().into_serializer());
525 Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(common_serializer))
526 }
527 }
528 }
529
530 Ipv4Proto::Proto(IpProto::Udp) => {
531 let v6_pkt_builder = v6_builder(Ipv6Proto::Proto(IpProto::Udp));
532 let args = UdpParseArgs::new(self.src_ip(), self.dst_ip());
533 match UdpPacket::parse(&mut self.body.as_bytes(), args) {
534 Ok(udp) => {
535 let udp_serializer =
539 Nat64Serializer::Udp(udp.into_serializer(v6_src_addr, v6_dst_addr));
540 Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(udp_serializer))
541 }
542 Err(msg) => {
543 debug!("Parsing of UDP packet failed: {:?}", msg);
544
545 let common_serializer =
551 Nat64Serializer::Other(self.body().into_serializer());
552 Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(common_serializer))
553 }
554 }
555 }
556
557 Ipv4Proto::Icmp => Nat64TranslationResult::Err(Nat64Error::NotImplemented),
558
559 Ipv4Proto::Other(val) => {
564 let v6_pkt_builder = v6_builder(Ipv6Proto::Other(val));
565 let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
566 Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(common_serializer))
567 }
568
569 Ipv4Proto::Proto(IpProto::Reserved) => Nat64TranslationResult::Drop,
572 }
573 }
574
575 pub fn to_vec(&self) -> Vec<u8> {
577 let Ipv4Packet { hdr_prefix, options, body } = self;
578 let mut buf = Vec::with_capacity(
579 Ref::bytes(&hdr_prefix).len() + options.bytes().len() + body.as_bytes().len(),
580 );
581 buf.extend(Ref::bytes(&hdr_prefix));
582 buf.extend(options.bytes());
583 buf.extend(body.as_bytes());
584 buf
585 }
586}
587
588impl<B: SplitByteSliceMut> Ipv4Packet<B> {
589 pub fn set_src_ip_and_update_checksum(&mut self, addr: Ipv4Addr) {
593 let old_bytes = self.hdr_prefix.src_ip.bytes();
594 self.hdr_prefix.hdr_checksum =
595 internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, addr.bytes());
596 self.hdr_prefix.src_ip = addr;
597 }
598
599 pub fn set_dst_ip_and_update_checksum(&mut self, addr: Ipv4Addr) {
603 let old_bytes = self.hdr_prefix.dst_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.dst_ip = addr;
607 }
608
609 pub fn set_ttl(&mut self, ttl: u8) {
613 let old_bytes = [self.hdr_prefix.ttl, self.hdr_prefix.proto];
617 let new_bytes = [ttl, self.hdr_prefix.proto];
618 self.hdr_prefix.hdr_checksum =
619 internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, &new_bytes);
620 self.hdr_prefix.ttl = ttl;
621 }
622
623 pub fn body_mut(&mut self) -> &mut [u8] {
625 &mut self.body
626 }
627
628 pub fn parts_with_body_mut(&mut self) -> (&HeaderPrefix, &Options<B>, &mut [u8]) {
631 (&self.hdr_prefix, &self.options, &mut self.body)
632 }
633}
634
635impl<B> Debug for Ipv4Packet<B>
636where
637 B: SplitByteSlice,
638{
639 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
640 f.debug_struct("Ipv4Packet")
641 .field("src_ip", &self.src_ip())
642 .field("dst_ip", &self.dst_ip())
643 .field("id", &self.id())
644 .field("ttl", &self.ttl())
645 .field("proto", &self.proto())
646 .field("frag_off", &self.fragment_offset())
647 .field("dscp", &self.dscp_and_ecn().dscp())
648 .field("ecn", &self.dscp_and_ecn().ecn())
649 .field("mf_flag", &self.mf_flag())
650 .field("df_flag", &self.df_flag())
651 .field("body", &alloc::format!("<{} bytes>", self.body.len()))
652 .finish()
653 }
654}
655
656pub struct Ipv4PacketRaw<B> {
666 hdr_prefix: Ref<B, HeaderPrefix>,
667 options: MaybeParsed<OptionsRaw<B, Ipv4OptionsImpl>, B>,
668 body: MaybeParsed<B, B>,
669}
670
671impl<B> Ipv4PacketRaw<B> {
672 pub fn body_mut(&mut self) -> &mut B {
676 match &mut self.body {
677 MaybeParsed::Complete(b) => b,
678 MaybeParsed::Incomplete(b) => b,
679 }
680 }
681}
682
683impl<B: SplitByteSlice> Ipv4Header for Ipv4PacketRaw<B> {
684 fn get_header_prefix(&self) -> &HeaderPrefix {
685 &self.hdr_prefix
686 }
687}
688
689impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv4PacketRaw<B> {
690 type Error = IpParseError<Ipv4>;
691
692 fn parse_metadata(&self) -> ParseMetadata {
693 let header_len = Ref::bytes(&self.hdr_prefix).len() + self.options.len();
694 ParseMetadata::from_packet(header_len, self.body.len(), 0)
695 }
696
697 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> IpParseResult<Ipv4, Self> {
698 let hdr_prefix = buffer
699 .take_obj_front::<HeaderPrefix>()
700 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for header"))?;
701 let hdr_bytes = (hdr_prefix.ihl() * 4) as usize;
702
703 let options = MaybeParsed::take_from_buffer_with(
704 &mut buffer,
705 hdr_bytes.saturating_sub(HDR_PREFIX_LEN),
710 OptionsRaw::new,
711 );
712
713 let total_len: usize = hdr_prefix.total_len.get().into();
714 let body_len = total_len.saturating_sub(hdr_bytes);
715 if buffer.len() > body_len {
716 let _: B = buffer.take_back(buffer.len() - body_len).unwrap();
719 }
720
721 let body = MaybeParsed::new_with_min_len(buffer.into_rest(), body_len);
722
723 Ok(Self { hdr_prefix, options, body })
724 }
725}
726
727impl<B> Ipv4PacketRaw<B> {
728 pub fn options(&self) -> &MaybeParsed<OptionsRaw<B, Ipv4OptionsImpl>, B> {
730 &self.options
731 }
732}
733
734impl<B: SplitByteSlice> Ipv4PacketRaw<B> {
735 pub fn body(&self) -> MaybeParsed<&[u8], &[u8]> {
741 self.body.as_ref().map(|b| b.deref()).map_incomplete(|b| b.deref())
742 }
743
744 pub fn into_body(self) -> MaybeParsed<B, B> {
748 self.body
749 }
750}
751
752impl<B: SplitByteSliceMut> Ipv4PacketRaw<B> {
753 pub fn set_src_ip_and_update_checksum(&mut self, addr: Ipv4Addr) {
757 let old_bytes = self.hdr_prefix.src_ip.bytes();
758 self.hdr_prefix.hdr_checksum =
759 internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, addr.bytes());
760 self.hdr_prefix.src_ip = addr;
761 }
762
763 pub fn set_dst_ip_and_update_checksum(&mut self, addr: Ipv4Addr) {
767 let old_bytes = self.hdr_prefix.dst_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.dst_ip = addr;
771 }
772}
773
774pub type Options<B> = packet::records::options::Options<B, Ipv4OptionsImpl>;
780
781#[derive(Debug)]
784pub struct Ipv4OptionsTooLongError;
785
786#[derive(Debug, Clone)]
788pub struct Ipv4PacketBuilderWithOptions<'a, I> {
789 prefix_builder: Ipv4PacketBuilder,
790 options: OptionSequenceBuilder<Ipv4Option<'a>, I>,
791}
792
793impl<'a, I> Ipv4PacketBuilderWithOptions<'a, I>
794where
795 I: Iterator + Clone,
796 I::Item: Borrow<Ipv4Option<'a>>,
797{
798 pub fn new<T: IntoIterator<IntoIter = I>>(
804 prefix_builder: Ipv4PacketBuilder,
805 options: T,
806 ) -> Result<Ipv4PacketBuilderWithOptions<'a, I>, Ipv4OptionsTooLongError> {
807 let options = OptionSequenceBuilder::new(options.into_iter());
808 if options.serialized_len() > MAX_OPTIONS_LEN {
809 return Err(Ipv4OptionsTooLongError);
810 }
811 Ok(Ipv4PacketBuilderWithOptions { prefix_builder, options })
812 }
813
814 fn aligned_options_len(&self) -> usize {
815 crate::utils::round_to_next_multiple_of_four(self.options.serialized_len())
817 }
818
819 pub fn prefix_builder(&self) -> &Ipv4PacketBuilder {
821 &self.prefix_builder
822 }
823
824 pub fn prefix_builder_mut(&mut self) -> &mut Ipv4PacketBuilder {
826 &mut self.prefix_builder
827 }
828
829 pub fn options(&self) -> &I {
831 self.options.records()
832 }
833
834 pub fn with_fragment_options(
840 self,
841 first_fragment: bool,
842 ) -> Ipv4PacketBuilderWithOptions<'a, impl Iterator<Item: Borrow<Ipv4Option<'a>>> + Clone> {
843 let Self { prefix_builder, options } = self;
844 Ipv4PacketBuilderWithOptions {
845 prefix_builder,
846 options: OptionSequenceBuilder::new(
849 options
850 .records()
851 .clone()
852 .filter(move |opt| first_fragment || opt.borrow().copied()),
853 ),
854 }
855 }
856}
857
858impl<'a, B> Ipv4PacketBuilderWithOptions<'a, RecordsIter<'a, B, Ipv4OptionsImpl>> {
859 pub fn new_with_records_iter(
862 prefix_builder: Ipv4PacketBuilder,
863 iter: RecordsIter<'a, B, Ipv4OptionsImpl>,
864 ) -> Self {
865 Self { prefix_builder, options: OptionSequenceBuilder::new(iter) }
866 }
867}
868
869impl<'a, I> PacketBuilder for Ipv4PacketBuilderWithOptions<'a, I>
870where
871 I: Iterator + Clone,
872 I::Item: Borrow<Ipv4Option<'a>>,
873{
874 fn constraints(&self) -> PacketConstraints {
875 let header_len = IPV4_MIN_HDR_LEN + self.aligned_options_len();
876 assert_eq!(header_len % 4, 0);
877 PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
878 }
879
880 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
881 let opt_len = self.aligned_options_len();
882 let mut header = &mut &mut target.header[..];
888 let opts = header.take_back_zero(opt_len).expect("too few bytes for Ipv4 options");
889 let Ipv4PacketBuilderWithOptions { prefix_builder, options } = self;
890 options.serialize_into(opts);
891 prefix_builder.serialize(target, body);
892 }
893}
894
895impl<'a, I> PartialPacketBuilder for Ipv4PacketBuilderWithOptions<'a, I>
896where
897 I: Iterator + Clone,
898 I::Item: Borrow<Ipv4Option<'a>>,
899{
900 fn partial_serialize(&self, body_len: usize, header: &mut [u8]) {
901 let Ipv4PacketBuilderWithOptions { prefix_builder, options } = self;
902 prefix_builder.partial_serialize(body_len, header);
903 let options_slice = &mut header[IPV4_MIN_HDR_LEN..];
904 assert_eq!(options_slice.len(), self.aligned_options_len());
905 options.serialize_into(options_slice);
906 }
907}
908
909impl<'a, I> IpPacketBuilder<Ipv4> for Ipv4PacketBuilderWithOptions<'a, I>
910where
911 I: Default + Debug + Clone + Iterator<Item: Borrow<Ipv4Option<'a>>>,
912{
913 fn new(src_ip: Ipv4Addr, dst_ip: Ipv4Addr, ttl: u8, proto: Ipv4Proto) -> Self {
914 Ipv4PacketBuilderWithOptions::new(
915 Ipv4PacketBuilder::new(src_ip, dst_ip, ttl, proto),
916 I::default(),
917 )
918 .expect("packet builder with no options should be valid")
919 }
920
921 fn src_ip(&self) -> Ipv4Addr {
922 self.prefix_builder.src_ip
923 }
924
925 fn set_src_ip(&mut self, addr: Ipv4Addr) {
926 self.prefix_builder.set_src_ip(addr);
927 }
928
929 fn dst_ip(&self) -> Ipv4Addr {
930 self.prefix_builder.dst_ip
931 }
932
933 fn set_dst_ip(&mut self, addr: Ipv4Addr) {
934 self.prefix_builder.set_dst_ip(addr);
935 }
936
937 fn proto(&self) -> Ipv4Proto {
938 self.prefix_builder.proto
939 }
940
941 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
942 self.prefix_builder.set_dscp_and_ecn(dscp_and_ecn)
943 }
944}
945
946#[derive(Debug, Clone, Eq, PartialEq)]
948pub struct Ipv4PacketBuilder {
949 id: u16,
950 dscp_and_ecn: DscpAndEcn,
951 flags: u8,
952 frag_off: u16,
953 ttl: u8,
954 proto: Ipv4Proto,
955 src_ip: Ipv4Addr,
956 dst_ip: Ipv4Addr,
957}
958
959impl Ipv4PacketBuilder {
960 pub fn new<S: Into<Ipv4Addr>, D: Into<Ipv4Addr>>(
962 src_ip: S,
963 dst_ip: D,
964 ttl: u8,
965 proto: Ipv4Proto,
966 ) -> Ipv4PacketBuilder {
967 Ipv4PacketBuilder {
968 id: 0,
969 dscp_and_ecn: DscpAndEcn::default(),
970 flags: 0,
971 frag_off: 0,
972 ttl,
973 proto: proto,
974 src_ip: src_ip.into(),
975 dst_ip: dst_ip.into(),
976 }
977 }
978
979 pub fn dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
981 self.dscp_and_ecn = dscp_and_ecn;
982 }
983
984 pub fn id(&mut self, id: u16) {
986 self.id = id
987 }
988
989 pub fn df_flag(&mut self, df: bool) {
991 if df {
992 self.flags |= 1 << DF_FLAG_OFFSET;
993 } else {
994 self.flags &= !(1 << DF_FLAG_OFFSET);
995 }
996 }
997
998 pub fn mf_flag(&mut self, mf: bool) {
1000 if mf {
1001 self.flags |= 1 << MF_FLAG_OFFSET;
1002 } else {
1003 self.flags &= !(1 << MF_FLAG_OFFSET);
1004 }
1005 }
1006
1007 pub fn fragment_offset(&mut self, fragment_offset: FragmentOffset) {
1009 self.frag_off = fragment_offset.into_raw();
1010 }
1011
1012 pub fn read_df_flag(&self) -> bool {
1014 (self.flags & (1 << DF_FLAG_OFFSET)) != 0
1015 }
1016
1017 fn get_header_prefix(&self, header_len: usize, total_len: usize) -> HeaderPrefix {
1018 assert_eq!(header_len % 4, 0);
1019 let ihl: u8 = u8::try_from(header_len / 4).expect("Header too large");
1020
1021 let id = if ((self.flags & (1 << DF_FLAG_OFFSET)) == 0)
1031 || ((self.flags & (1 << MF_FLAG_OFFSET)) == 1)
1032 || (self.frag_off > 0)
1033 {
1034 self.id
1035 } else {
1036 0
1037 };
1038
1039 HeaderPrefix::new(
1040 ihl,
1041 self.dscp_and_ecn,
1042 {
1043 debug_assert!(total_len <= core::u16::MAX as usize);
1049 total_len as u16
1050 },
1051 id,
1052 self.flags,
1053 self.frag_off,
1054 self.ttl,
1055 self.proto.into(),
1056 [0, 0], self.src_ip,
1058 self.dst_ip,
1059 )
1060 }
1061}
1062
1063impl PacketBuilder for Ipv4PacketBuilder {
1064 fn constraints(&self) -> PacketConstraints {
1065 PacketConstraints::new(IPV4_MIN_HDR_LEN, 0, 0, (1 << 16) - 1 - IPV4_MIN_HDR_LEN)
1066 }
1067
1068 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
1069 let header_len = target.header.len();
1070 let total_len = header_len + body.len();
1071 let mut hdr_prefix = self.get_header_prefix(header_len, total_len);
1072 let options = &target.header[HDR_PREFIX_LEN..];
1073 let checksum = compute_header_checksum(hdr_prefix.as_bytes(), options);
1074 hdr_prefix.hdr_checksum = checksum;
1075 let mut header = &mut target.header;
1076 header.write_obj_front(&hdr_prefix).expect("too few bytes for IPv4 header prefix");
1077 }
1078}
1079
1080impl PartialPacketBuilder for Ipv4PacketBuilder {
1081 fn partial_serialize(&self, body_len: usize, mut header: &mut [u8]) {
1082 let total_len = header.len() + body_len;
1083 let hdr_prefix = self.get_header_prefix(header.len(), total_len);
1084 (&mut header).write_obj_front(&hdr_prefix).expect("too few bytes for IPv4 header prefix");
1085 }
1086}
1087
1088impl IpPacketBuilder<Ipv4> for Ipv4PacketBuilder {
1089 fn new(src_ip: Ipv4Addr, dst_ip: Ipv4Addr, ttl: u8, proto: Ipv4Proto) -> Self {
1090 Ipv4PacketBuilder::new(src_ip, dst_ip, ttl, proto)
1091 }
1092
1093 fn src_ip(&self) -> Ipv4Addr {
1094 self.src_ip
1095 }
1096
1097 fn set_src_ip(&mut self, addr: Ipv4Addr) {
1098 self.src_ip = addr;
1099 }
1100
1101 fn dst_ip(&self) -> Ipv4Addr {
1102 self.dst_ip
1103 }
1104
1105 fn set_dst_ip(&mut self, addr: Ipv4Addr) {
1106 self.dst_ip = addr;
1107 }
1108
1109 fn proto(&self) -> Ipv4Proto {
1110 self.proto
1111 }
1112
1113 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1114 self.dscp_and_ecn = dscp_and_ecn;
1115 }
1116}
1117
1118const DF_FLAG_OFFSET: u8 = 1;
1120const MF_FLAG_OFFSET: u8 = 0;
1121
1122pub(crate) fn reassemble_fragmented_packet<
1124 B: SplitByteSliceMut,
1125 BV: BufferViewMut<B>,
1126 I: Iterator<Item = Vec<u8>>,
1127>(
1128 mut buffer: BV,
1129 header: Vec<u8>,
1130 body_fragments: I,
1131) -> IpParseResult<Ipv4, ()> {
1132 let bytes = buffer.as_mut();
1133
1134 bytes[0..header.len()].copy_from_slice(&header[..]);
1136 let mut byte_count = header.len();
1137
1138 for p in body_fragments {
1140 bytes[byte_count..byte_count + p.len()].copy_from_slice(&p[..]);
1141 byte_count += p.len();
1142 }
1143
1144 if byte_count > usize::from(core::u16::MAX) {
1149 return debug_err!(
1150 Err(ParseError::Format.into()),
1151 "fragmented packet length of {} bytes is too large",
1152 byte_count
1153 );
1154 }
1155
1156 let mut header = Ref::<_, HeaderPrefix>::from_prefix(bytes).unwrap().0;
1159
1160 header.total_len.set(u16::try_from(byte_count).unwrap());
1162
1163 header.flags_frag_off = [0; 2];
1166
1167 header.hdr_checksum = [0; 2];
1169 header.hdr_checksum = compute_header_checksum(header.as_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}