1pub mod opt;
97
98use std::fmt::{self, Formatter};
99use std::net::Ipv4Addr;
100use std::ops::Deref;
101
102use zerocopy::byteorder::{BigEndian, U16, U32};
103use zerocopy::{FromBytes, IntoBytes, Unaligned};
104
105use crate::packet::ipv4::opt::Ipv4OptionsIter;
106use crate::packet::protocol::IpProto;
107use crate::packet::{HeaderParser, PacketHeader};
108
109#[repr(C, packed)]
114#[derive(
115 FromBytes, IntoBytes, Unaligned, Debug, Clone, Copy, zerocopy::KnownLayout, zerocopy::Immutable,
116)]
117pub struct Ipv4Header {
118 ver_ihl: u8,
119 dscp_ecn: u8,
120 total_length: U16<BigEndian>,
121 identification: U16<BigEndian>,
122 flags_frag_offset: U16<BigEndian>,
123 ttl: u8,
124 protocol: IpProto,
125 checksum: U16<BigEndian>,
126 src_ip: U32<BigEndian>,
127 dst_ip: U32<BigEndian>,
128}
129
130impl Ipv4Header {
131 #[inline]
132 pub fn dscp(&self) -> u8 {
133 self.dscp_ecn >> 2
134 }
135
136 #[inline]
137 pub fn ecn(&self) -> u8 {
138 self.dscp_ecn & 0x03
139 }
140
141 #[inline]
142 pub fn version(&self) -> u8 {
143 self.ver_ihl >> 4
144 }
145
146 #[inline]
147 pub fn ihl(&self) -> u8 {
148 self.ver_ihl & 0x0F
149 }
150
151 const OFFSET_MASK: u16 = 0x1FFF;
152 const MF_FLAG_MASK: u16 = 0x2000;
153 const DF_FLAG_MASK: u16 = 0x4000;
154 const RS_FLAG_MASK: u16 = 0x8000;
155
156 #[inline]
157 pub fn flags(&self) -> u8 {
158 (self.flags_frag_offset.get() >> 13) as u8
159 }
160
161 #[inline]
162 pub fn fragment_offset(&self) -> u16 {
163 self.flags_frag_offset.get() & Self::OFFSET_MASK
164 }
165
166 #[inline]
167 pub fn has_dont_fragment(&self) -> bool {
168 (self.flags_frag_offset.get() & Self::DF_FLAG_MASK) != 0
170 }
171
172 #[inline]
173 pub fn has_more_fragment(&self) -> bool {
174 (self.flags_frag_offset.get() & Self::MF_FLAG_MASK) != 0
176 }
177
178 #[inline]
179 pub fn has_reserved_flag(&self) -> bool {
180 (self.flags_frag_offset.get() & Self::RS_FLAG_MASK) != 0
181 }
182
183 #[inline]
184 pub fn is_fragmenting(&self) -> bool {
185 (self.flags_frag_offset.get() & (Self::MF_FLAG_MASK | Self::OFFSET_MASK)) != 0
187 }
188
189 #[inline]
190 pub fn is_first_fragment(&self) -> bool {
191 let raw = self.flags_frag_offset.get();
193 (raw & Self::MF_FLAG_MASK) != 0 && (raw & Self::OFFSET_MASK) == 0
194 }
195
196 #[inline]
197 pub fn is_last_fragment(&self) -> bool {
198 let raw = self.flags_frag_offset.get();
200 (raw & Self::MF_FLAG_MASK) == 0 && (raw & Self::OFFSET_MASK) != 0
201 }
202
203 #[inline]
204 pub fn total_length(&self) -> usize {
205 self.total_length.get() as usize
206 }
207
208 #[inline]
209 pub fn ttl(&self) -> u8 {
210 self.ttl
211 }
212
213 #[inline]
214 pub fn protocol(&self) -> IpProto {
215 self.protocol
216 }
217
218 #[inline]
219 pub fn src_ip(&self) -> Ipv4Addr {
220 Ipv4Addr::from(self.src_ip.get())
221 }
222
223 #[inline]
224 pub fn dst_ip(&self) -> Ipv4Addr {
225 Ipv4Addr::from(self.dst_ip.get())
226 }
227
228 #[inline]
229 pub fn src_ip_raw(&self) -> [u8; 4] {
230 self.src_ip.get().to_be_bytes()
231 }
232
233 #[inline]
234 pub fn dst_ip_raw(&self) -> [u8; 4] {
235 self.dst_ip.get().to_be_bytes()
236 }
237
238 #[inline]
241 pub fn has_options(&self) -> bool {
242 self.ihl() > 5
243 }
244
245 #[inline]
246 pub fn id(&self) -> u16 {
247 self.identification.get()
248 }
249}
250
251#[derive(Debug, Clone)]
253pub struct Ipv4HeaderOpt<'a> {
254 pub header: &'a Ipv4Header,
255 pub raw_options: &'a [u8],
256}
257
258impl<'a> Ipv4HeaderOpt<'a> {
259 pub fn options(&'a self) -> Ipv4OptionsIter<'a> {
261 Ipv4OptionsIter::new(self.raw_options)
262 }
263}
264
265impl Deref for Ipv4HeaderOpt<'_> {
266 type Target = Ipv4Header;
267
268 #[inline]
269 fn deref(&self) -> &Self::Target {
270 self.header
271 }
272}
273
274impl PacketHeader for Ipv4Header {
275 const NAME: &'static str = "IPv4Header";
276 type InnerType = IpProto;
277
278 #[inline]
279 fn inner_type(&self) -> Self::InnerType {
280 self.protocol
281 }
282
283 #[inline]
284 fn total_len(&self, _buf: &[u8]) -> usize {
285 (self.ihl() as usize) * 4
286 }
287
288 #[inline]
289 fn is_valid(&self) -> bool {
290 self.version() == 4 && self.ihl() >= 5
291 }
292}
293
294impl HeaderParser for Ipv4Header {
295 type Output<'a> = Ipv4HeaderOpt<'a>;
296
297 #[inline]
298 fn into_view<'a>(header: &'a Self, raw_options: &'a [u8]) -> Self::Output<'a> {
299 Ipv4HeaderOpt {
300 header,
301 raw_options,
302 }
303 }
304}
305
306impl fmt::Display for Ipv4Header {
307 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
308 write!(
309 f,
310 "IPv4 {} -> {} proto={} ttl={} len={}",
311 self.src_ip(),
312 self.dst_ip(),
313 self.protocol(),
314 self.ttl(),
315 self.total_length()
316 )?;
317
318 if self.is_fragmenting() {
319 write!(f, " frag offset={}", self.fragment_offset())?;
320 }
321
322 if self.has_options() {
323 write!(f, " +opts")?;
324 }
325
326 Ok(())
327 }
328}
329
330impl fmt::Display for Ipv4HeaderOpt<'_> {
331 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
332 write!(f, "{}", self.header)?;
333
334 if !self.raw_options.is_empty() {
335 write!(f, " opts=[")?;
336 let mut first = true;
337 for opt in self.options().flatten() {
338 if !first {
339 write!(f, ",")?;
340 }
341 first = false;
342 write!(f, "{}", opt)?;
343 }
344 write!(f, "]")?;
345 }
346
347 Ok(())
348 }
349}
350
351mod tests {
352 use super::*;
353 #[test]
354 fn test_ipv4_header_size() {
355 assert_eq!(std::mem::size_of::<Ipv4Header>(), 20);
356 assert_eq!(Ipv4Header::FIXED_LEN, 20);
357 }
358
359 #[test]
360 fn test_ipv4_version_and_ihl() {
361 let header = create_test_header();
362 assert_eq!(header.version(), 4);
363 assert_eq!(header.ihl(), 5); assert!(header.is_valid());
365 }
366
367 #[test]
368 fn test_ipv4_dscp_ecn() {
369 let mut header = create_test_header();
370
371 header.dscp_ecn = 0xB9; assert_eq!(header.dscp(), 46);
374 assert_eq!(header.ecn(), 1);
375 }
376
377 #[test]
378 fn test_ipv4_total_length() {
379 let mut header = create_test_header();
380 header.total_length = U16::new(1500);
381 assert_eq!(header.total_length(), 1500);
382 }
383
384 #[test]
385 fn test_ipv4_fragmentation() {
386 let mut header = create_test_header();
387
388 header.flags_frag_offset = U16::new(0x4000); assert_eq!(header.flags(), 0x02);
391 assert_eq!(header.fragment_offset(), 0);
392 assert!(!header.is_fragmenting());
393
394 header.flags_frag_offset = U16::new(0x20B9);
396 assert_eq!(header.flags(), 0x01); assert_eq!(header.fragment_offset(), 185);
398 assert!(header.is_fragmenting());
399 }
400
401 #[test]
402 fn test_ipv4_addresses() {
403 let header = create_test_header();
404
405 let expected_src = Ipv4Addr::new(192, 168, 1, 100);
407 assert_eq!(header.src_ip(), expected_src);
408 assert_eq!(header.src_ip_raw(), [192, 168, 1, 100]);
409
410 let expected_dst = Ipv4Addr::new(10, 0, 0, 1);
412 assert_eq!(header.dst_ip(), expected_dst);
413 assert_eq!(header.dst_ip_raw(), [10, 0, 0, 1]);
414 }
415
416 #[test]
417 fn test_ipv4_protocol_ttl() {
418 let header = create_test_header();
419 assert_eq!(header.protocol(), IpProto::TCP);
420 assert_eq!(header.ttl(), 64);
421 }
422
423 #[test]
424 fn test_ipv4_parsing_basic() {
425 let packet = create_test_packet();
426
427 let result = Ipv4Header::from_bytes(&packet);
428 assert!(result.is_ok());
429
430 let (header_ext, payload) = result.unwrap();
431 assert_eq!(header_ext.version(), 4);
432 assert_eq!(header_ext.ihl(), 5);
433 assert_eq!(header_ext.protocol(), IpProto::TCP);
434 assert!(!header_ext.has_options());
435 assert_eq!(header_ext.raw_options.len(), 0);
436 assert_eq!(payload.len(), 0); }
438
439 #[test]
440 fn test_ipv4_parsing_invalid_version() {
441 let mut packet = create_test_packet();
442 packet[0] = 0x60; let result = Ipv4Header::from_bytes(&packet);
445 assert!(result.is_err());
446 }
447
448 #[test]
449 fn test_ipv4_parsing_invalid_ihl() {
450 let mut packet = create_test_packet();
451 packet[0] = 0x44; let result = Ipv4Header::from_bytes(&packet);
454 assert!(result.is_err());
455 }
456
457 #[test]
458 fn test_ipv4_parsing_too_small() {
459 let packet = vec![0u8; 19]; let result = Ipv4Header::from_bytes(&packet);
462 assert!(result.is_err());
463 }
464
465 #[test]
466 fn test_ipv4_total_len_no_options() {
467 let packet = create_test_packet();
468 let (header_ext, _) = Ipv4Header::from_bytes(&packet).unwrap();
469
470 assert_eq!(header_ext.total_len(&packet), 20);
472 assert_eq!(header_ext.raw_options.len(), 0);
473 }
474
475 #[test]
476 fn test_ipv4_with_options() {
477 let mut packet = create_test_packet();
478
479 packet[0] = 0x46; packet.extend_from_slice(&[0x01, 0x01, 0x01, 0x01]); let (header_ext, _) = Ipv4Header::from_bytes(&packet).unwrap();
486
487 assert_eq!(header_ext.ihl(), 6);
489 assert_eq!(header_ext.total_len(&packet), 24); assert!(header_ext.is_valid());
491 assert!(header_ext.has_options());
492 assert_eq!(header_ext.raw_options.len(), 4);
493
494 let opts: Vec<_> = header_ext.options().collect::<Result<Vec<_>, _>>().unwrap();
496 assert_eq!(opts.len(), 4); }
498
499 #[test]
500 fn test_ipv4_with_timestamp_option() {
501 let mut packet = create_test_packet();
502
503 packet[0] = 0x49; packet.push(0x44); packet.push(0x10); packet.push(0x05); packet.push(0x00); packet.extend_from_slice(&[0x00, 0x00, 0x00, 0x01]); packet.extend_from_slice(&[0x00, 0x00, 0x00, 0x02]); packet.extend_from_slice(&[0x00, 0x00, 0x00, 0x03]); let (header_ext, _) = Ipv4Header::from_bytes(&packet).unwrap();
518
519 assert_eq!(header_ext.ihl(), 9);
521 assert_eq!(header_ext.total_len(&packet), 36); assert!(header_ext.is_valid());
523 assert_eq!(header_ext.raw_options.len(), 16);
524
525 let opts: Vec<_> = header_ext.options().collect::<Result<Vec<_>, _>>().unwrap();
527 assert_eq!(opts.len(), 1);
528 }
529
530 #[test]
531 fn test_ipv4_with_record_route_option() {
532 let mut packet = create_test_packet();
533
534 packet[0] = 0x4A; packet.push(0x07); packet.push(0x13); packet.push(0x04); packet.extend_from_slice(&[192, 168, 1, 1]);
545 packet.extend_from_slice(&[192, 168, 1, 2]);
546 packet.extend_from_slice(&[192, 168, 1, 3]);
547 packet.extend_from_slice(&[192, 168, 1, 4]);
548
549 packet.push(0x01); let (header_ext, _) = Ipv4Header::from_bytes(&packet).unwrap();
553
554 assert_eq!(header_ext.ihl(), 10);
556 assert_eq!(header_ext.total_len(&packet), 40); assert!(header_ext.is_valid());
558 assert_eq!(header_ext.raw_options.len(), 20);
559
560 let opts: Vec<_> = header_ext.options().collect::<Result<Vec<_>, _>>().unwrap();
562 assert_eq!(opts.len(), 2); }
564
565 #[test]
566 fn test_ipv4_from_bytes_with_options_and_payload() {
567 let mut packet = create_test_packet();
568
569 packet[0] = 0x47; packet.push(0x01); packet.push(0x82); packet.push(0x06); packet.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]); packet.push(0x01); let payload_data = b"Test payload after IP options";
581 packet.extend_from_slice(payload_data);
582
583 let total_len = 28 + payload_data.len();
585 packet[2] = ((total_len >> 8) & 0xFF) as u8;
586 packet[3] = (total_len & 0xFF) as u8;
587
588 let result = Ipv4Header::from_bytes(&packet);
590 assert!(result.is_ok());
591
592 let (header_ext, payload) = result.unwrap();
593
594 assert_eq!(payload.len(), payload_data.len());
597 assert_eq!(payload, payload_data);
598
599 assert_eq!(header_ext.ihl(), 7);
601 assert_eq!(header_ext.total_len(&packet), 28);
602 assert_eq!(header_ext.total_length(), total_len);
603 assert_eq!(header_ext.raw_options.len(), 8);
604
605 let opts: Vec<_> = header_ext.options().collect::<Result<Vec<_>, _>>().unwrap();
607 assert_eq!(opts.len(), 3); }
609
610 #[test]
611 fn test_ipv4_total_len_includes_options() {
612 let mut packet = create_test_packet();
614
615 let (header_ext, _) = Ipv4Header::from_bytes(&packet).unwrap();
617 assert_eq!(header_ext.total_len(&packet), 20);
618 assert_eq!(header_ext.ihl(), 5);
619 assert_eq!(header_ext.raw_options.len(), 0);
620
621 packet = create_test_packet();
623 packet[0] = 0x46;
624 packet.extend_from_slice(&[0x01, 0x01, 0x01, 0x01]);
625 let (header_ext, _) = Ipv4Header::from_bytes(&packet).unwrap();
626 assert_eq!(header_ext.total_len(&packet), 24); assert_eq!(header_ext.ihl(), 6);
628 assert_eq!(header_ext.raw_options.len(), 4);
629
630 packet = create_test_packet();
632 packet[0] = 0x47;
633 packet.extend_from_slice(&[0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01]);
634 let (header_ext, _) = Ipv4Header::from_bytes(&packet).unwrap();
635 assert_eq!(header_ext.total_len(&packet), 28); assert_eq!(header_ext.ihl(), 7);
637 assert_eq!(header_ext.raw_options.len(), 8);
638
639 packet = create_test_packet();
641 packet[0] = 0x4F; let options = vec![0x01u8; 40]; packet.extend_from_slice(&options);
644 let (header_ext, _) = Ipv4Header::from_bytes(&packet).unwrap();
645 assert_eq!(header_ext.total_len(&packet), 60); assert_eq!(header_ext.ihl(), 15);
647 assert_eq!(header_ext.raw_options.len(), 40);
648 }
649
650 #[test]
651 fn test_ipv4_header_ext_with_options() {
652 let mut packet = create_test_packet();
653 packet[0] = 0x47; packet.extend_from_slice(&[148, 0x04, 0x00, 0x00]); packet.extend_from_slice(&[0x01, 0x01, 0x01, 0x01]);
660
661 let (header_ext, _) = Ipv4Header::from_bytes(&packet).unwrap();
662
663 assert_eq!(header_ext.raw_options.len(), 8);
664 assert!(header_ext.has_options());
665
666 let opts: Vec<_> = header_ext.options().collect::<Result<Vec<_>, _>>().unwrap();
668 assert_eq!(opts.len(), 5); assert_eq!(header_ext.version(), 4);
672 assert_eq!(header_ext.ihl(), 7);
673 assert_eq!(header_ext.protocol(), IpProto::TCP);
674 }
675
676 #[test]
677 fn test_ipv4_header_ext_deref() {
678 let packet = create_test_packet();
679 let (header_ext, _) = Ipv4Header::from_bytes(&packet).unwrap();
680
681 assert_eq!(header_ext.version(), 4);
683 assert_eq!(header_ext.ihl(), 5);
684 assert_eq!(header_ext.dscp(), 0);
685 assert_eq!(header_ext.ecn(), 0);
686 assert_eq!(header_ext.ttl(), 64);
687 assert_eq!(header_ext.protocol(), IpProto::TCP);
688 assert_eq!(
689 header_ext.src_ip(),
690 "192.168.1.100".parse::<Ipv4Addr>().unwrap()
691 );
692 assert_eq!(header_ext.dst_ip(), "10.0.0.1".parse::<Ipv4Addr>().unwrap());
693 }
694
695 #[test]
696 fn test_ipv4_options_integration_record_route() {
697 let mut packet = create_test_packet();
698 packet[0] = 0x48; packet.push(0x07); packet.push(0x0B); packet.push(0x04); packet.extend_from_slice(&[192, 168, 1, 1]); packet.extend_from_slice(&[192, 168, 1, 2]); packet.push(0x01);
709
710 let (header_ext, _) = Ipv4Header::from_bytes(&packet).unwrap();
711
712 assert_eq!(header_ext.raw_options.len(), 12);
713
714 let opts: Vec<_> = header_ext.options().collect::<Result<Vec<_>, _>>().unwrap();
716 assert_eq!(opts.len(), 2); use crate::packet::ipv4::opt::Ipv4OptionElement;
719 match &opts[0] {
720 Ipv4OptionElement::RecordRoute {
721 pointer,
722 route_data,
723 } => {
724 assert_eq!(*pointer, 4);
725 assert_eq!(route_data.len(), 8);
726 assert!(!opts[0].is_copied());
727 }
728 _ => panic!("Expected RecordRoute option"),
729 }
730 }
731
732 #[test]
733 fn test_ipv4_options_integration_timestamp() {
734 let mut packet = create_test_packet();
735 packet[0] = 0x47; packet.push(0x44); packet.push(0x08); packet.push(0x05); packet.push(0x00); packet.extend_from_slice(&[0x00, 0x00, 0x00, 0x01]); let (header_ext, _) = Ipv4Header::from_bytes(&packet).unwrap();
745
746 assert_eq!(header_ext.raw_options.len(), 8);
747
748 let opts: Vec<_> = header_ext.options().collect::<Result<Vec<_>, _>>().unwrap();
750 assert_eq!(opts.len(), 1);
751
752 use crate::packet::ipv4::opt::{Ipv4OptionElement, TimestampFlag};
753 match &opts[0] {
754 Ipv4OptionElement::Timestamp {
755 pointer,
756 overflow,
757 flags,
758 data,
759 } => {
760 assert_eq!(*pointer, 5);
761 assert_eq!(*overflow, 0);
762 assert_eq!(*flags, TimestampFlag::TimestampsOnly);
763 assert_eq!(data.len(), 4);
764 assert_eq!(opts[0].option_class(), 2);
765 }
766 _ => panic!("Expected Timestamp option"),
767 }
768 }
769
770 #[test]
771 fn test_ipv4_options_integration_security() {
772 let mut packet = create_test_packet();
773 packet[0] = 0x47; packet.push(0x82); packet.push(0x06); packet.extend_from_slice(&[0x00, 0xAB, 0x00, 0xCD]); packet.extend_from_slice(&[0x01, 0x01]); let (header_ext, _) = Ipv4Header::from_bytes(&packet).unwrap();
784
785 assert_eq!(header_ext.raw_options.len(), 8);
786
787 let opts: Vec<_> = header_ext.options().collect::<Result<Vec<_>, _>>().unwrap();
789 assert_eq!(opts.len(), 3); use crate::packet::ipv4::opt::Ipv4OptionElement;
792 match &opts[0] {
793 Ipv4OptionElement::Security {
794 classification,
795 protection_authority,
796 } => {
797 assert_eq!(*classification, 0x00AB);
798 assert_eq!(*protection_authority, 0x00CD);
799 assert!(opts[0].is_copied()); }
801 _ => panic!("Expected Security option"),
802 }
803 }
804
805 #[test]
806 fn test_ipv4_options_integration_multiple() {
807 let mut packet = create_test_packet();
808 packet[0] = 0x48; packet.push(0x01);
812
813 packet.extend_from_slice(&[136, 0x04, 0x12, 0x34]);
815
816 packet.extend_from_slice(&[148, 0x04, 0x00, 0x00]);
818
819 packet.extend_from_slice(&[0x01, 0x01, 0x01]);
821
822 let (header_ext, _) = Ipv4Header::from_bytes(&packet).unwrap();
823
824 assert_eq!(header_ext.raw_options.len(), 12);
825 assert!(header_ext.has_options());
826
827 let opts: Vec<_> = header_ext.options().collect::<Result<Vec<_>, _>>().unwrap();
829 assert_eq!(opts.len(), 6); use crate::packet::ipv4::opt::Ipv4OptionElement;
832 assert!(matches!(opts[0], Ipv4OptionElement::Nop));
833 assert!(matches!(opts[1], Ipv4OptionElement::StreamId(0x1234)));
834 assert!(matches!(opts[2], Ipv4OptionElement::RouterAlert(0)));
835 assert!(matches!(opts[3], Ipv4OptionElement::Nop));
836 }
837
838 fn create_test_header() -> Ipv4Header {
840 Ipv4Header {
841 ver_ihl: 0x45, dscp_ecn: 0x00,
843 total_length: U16::new(20),
844 identification: U16::new(0x1234),
845 flags_frag_offset: U16::new(0x4000), ttl: 64,
847 protocol: IpProto::TCP,
848 checksum: U16::new(0),
849 src_ip: U32::new(0xC0A80164), dst_ip: U32::new(0x0A000001), }
852 }
853
854 fn create_test_packet() -> Vec<u8> {
856 let mut packet = Vec::new();
857
858 packet.push(0x45);
860
861 packet.push(0x00);
863
864 packet.extend_from_slice(&[0x00, 0x14]);
866
867 packet.extend_from_slice(&[0x12, 0x34]);
869
870 packet.extend_from_slice(&[0x40, 0x00]);
872
873 packet.push(64);
875
876 packet.push(6);
878
879 packet.extend_from_slice(&[0x00, 0x00]);
881
882 packet.extend_from_slice(&[192, 168, 1, 100]);
884
885 packet.extend_from_slice(&[10, 0, 0, 1]);
887
888 packet
889 }
890}