1use core::mem;
2
3use crate::{getter_be, setter_be};
4
5#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
7pub enum IpHdr {
8 V4(Ipv4Hdr),
9 V6(Ipv6Hdr),
10}
11
12#[repr(C)]
14#[derive(Debug, Copy, Clone)]
15#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
16pub struct Ipv4Hdr {
17 pub vihl: u8,
18 pub tos: u8,
19 pub tot_len: [u8; 2],
20 pub id: [u8; 2],
21 pub frags: [u8; 2],
22 pub ttl: u8,
23 pub proto: IpProto,
24 pub check: [u8; 2],
25 pub src_addr: [u8; 4],
26 pub dst_addr: [u8; 4],
27}
28
29impl Ipv4Hdr {
30 pub const LEN: usize = mem::size_of::<Ipv4Hdr>();
31
32 #[inline]
34 pub fn version(&self) -> u8 {
35 (self.vihl >> 4) & 0xF
36 }
37
38 #[inline]
40 pub fn ihl(&self) -> u8 {
41 (self.vihl & 0xF) << 2
42 }
43
44 #[inline]
46 pub fn set_vihl(&mut self, version: u8, ihl_in_bytes: u8) {
47 let ihl_in_words = ihl_in_bytes / 4;
48 self.vihl = ((version & 0xF) << 4) | (ihl_in_words & 0xF);
49 }
50
51 #[inline]
53 pub fn dscp(&self) -> u8 {
54 (self.tos >> 2) & 0x3F
55 }
56
57 #[inline]
59 pub fn ecn(&self) -> u8 {
60 self.tos & 0x3
61 }
62
63 #[inline]
65 pub fn set_tos(&mut self, dscp: u8, ecn: u8) {
66 self.tos = ((dscp & 0x3F) << 2) | (ecn & 0x3);
67 }
68
69 #[inline]
71 pub fn tot_len(&self) -> u16 {
72 unsafe { getter_be!(self, tot_len, u16) }
74 }
75
76 #[inline]
78 pub fn set_tot_len(&mut self, len: u16) {
79 unsafe { setter_be!(self, tot_len, len) }
81 }
82
83 #[inline]
85 pub fn id(&self) -> u16 {
86 unsafe { getter_be!(self, id, u16) }
88 }
89
90 #[inline]
92 pub fn set_id(&mut self, id: u16) {
93 unsafe { setter_be!(self, id, id) }
95 }
96
97 #[inline]
98 fn frags(&self) -> u16 {
99 unsafe { getter_be!(self, frags, u16) }
101 }
102
103 #[inline]
105 pub fn frag_flags(&self) -> u8 {
106 (self.frags() >> 13) as u8
107 }
108
109 #[inline]
111 pub fn frag_offset(&self) -> u16 {
112 self.frags() & 0x1FFF
113 }
114
115 #[inline]
117 pub fn set_frags(&mut self, flags: u8, offset: u16) {
118 let value = ((flags as u16 & 0x7) << 13) | (offset & 0x1FFF);
119 unsafe { setter_be!(self, frags, value) }
121 }
122
123 #[inline]
125 pub fn checksum(&self) -> u16 {
126 unsafe { getter_be!(self, check, u16) }
128 }
129
130 #[inline]
132 pub fn set_checksum(&mut self, checksum: u16) {
133 unsafe { setter_be!(self, check, checksum) }
135 }
136
137 #[inline]
139 pub fn src_addr(&self) -> core::net::Ipv4Addr {
140 core::net::Ipv4Addr::from(self.src_addr)
141 }
142
143 #[inline]
145 pub fn dst_addr(&self) -> core::net::Ipv4Addr {
146 core::net::Ipv4Addr::from(self.dst_addr)
147 }
148
149 #[inline]
151 pub fn set_src_addr(&mut self, src: core::net::Ipv4Addr) {
152 self.src_addr = src.octets();
153 }
154
155 #[inline]
157 pub fn set_dst_addr(&mut self, dst: core::net::Ipv4Addr) {
158 self.dst_addr = dst.octets();
159 }
160}
161
162#[repr(C)]
164#[derive(Debug, Copy, Clone)]
165#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
166pub struct Ipv6Hdr {
167 pub vcf: [u8; 4],
169 pub payload_len: [u8; 2],
171 pub next_hdr: IpProto,
173 pub hop_limit: u8,
175 pub src_addr: [u8; 16],
177 pub dst_addr: [u8; 16],
179}
180
181impl Ipv6Hdr {
182 pub const LEN: usize = mem::size_of::<Ipv6Hdr>();
183
184 #[inline]
186 pub fn version(&self) -> u8 {
187 (self.vcf[0] >> 4) & 0xF
188 }
189
190 #[inline]
192 pub fn set_version(&mut self, version: u8) {
193 self.vcf[0] = (self.vcf[0] & 0x0F) | ((version & 0xF) << 4);
194 }
195
196 #[inline]
198 pub fn dscp(&self) -> u8 {
199 ((self.vcf[0] & 0x0F) << 2) | ((self.vcf[1] >> 6) & 0x03)
200 }
201
202 #[inline]
204 pub fn ecn(&self) -> u8 {
205 (self.vcf[1] >> 4) & 0x03
206 }
207
208 #[inline]
210 pub fn flow_label(&self) -> u32 {
211 ((self.vcf[1] as u32 & 0x0F) << 16) | ((self.vcf[2] as u32) << 8) | (self.vcf[3] as u32)
212 }
213
214 #[inline]
216 pub fn set_dscp_ecn(&mut self, dscp: u8, ecn: u8) {
217 self.vcf[0] = (self.vcf[0] & 0xF0) | ((dscp >> 2) & 0x0F);
219
220 self.vcf[1] = (self.vcf[1] & 0x0F) | (((dscp & 0x03) << 6) | ((ecn & 0x03) << 4));
222 }
223
224 #[inline]
226 pub fn set_flow_label(&mut self, flow_label: u32) {
227 self.vcf[1] = (self.vcf[1] & 0xF0) | ((flow_label >> 16) as u8 & 0x0F);
228 self.vcf[2] = ((flow_label >> 8) & 0xFF) as u8;
229 self.vcf[3] = (flow_label & 0xFF) as u8;
230 }
231
232 #[inline]
234 pub fn set_vcf(&mut self, version: u8, dscp: u8, ecn: u8, flow_label: u32) {
235 self.vcf[0] = ((version & 0x0F) << 4) | ((dscp >> 2) & 0x0F);
236 self.vcf[1] =
237 ((dscp & 0x03) << 6) | ((ecn & 0x03) << 4) | ((flow_label >> 16) as u8 & 0x0F);
238 self.vcf[2] = ((flow_label >> 8) & 0xFF) as u8;
239 self.vcf[3] = (flow_label & 0xFF) as u8;
240 }
241
242 #[inline]
244 pub fn payload_len(&self) -> u16 {
245 unsafe { getter_be!(self, payload_len, u16) }
247 }
248
249 #[inline]
251 pub fn set_payload_len(&mut self, len: u16) {
252 unsafe { setter_be!(self, payload_len, len) }
254 }
255
256 #[inline]
258 pub fn src_addr(&self) -> core::net::Ipv6Addr {
259 core::net::Ipv6Addr::from(self.src_addr)
260 }
261
262 #[inline]
264 pub fn dst_addr(&self) -> core::net::Ipv6Addr {
265 core::net::Ipv6Addr::from(self.dst_addr)
266 }
267
268 #[inline]
270 pub fn set_src_addr(&mut self, src: core::net::Ipv6Addr) {
271 self.src_addr = src.octets();
272 }
273
274 #[inline]
276 pub fn set_dst_addr(&mut self, dst: core::net::Ipv6Addr) {
277 self.dst_addr = dst.octets();
278 }
279}
280
281#[repr(u8)]
284#[derive(PartialEq, Eq, Debug, Copy, Clone)]
285#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
286pub enum IpProto {
287 HopOpt = 0,
289 Icmp = 1,
291 Igmp = 2,
293 Ggp = 3,
295 Ipv4 = 4,
297 Stream = 5,
299 Tcp = 6,
301 Cbt = 7,
303 Egp = 8,
305 Igp = 9,
307 BbnRccMon = 10,
309 NvpII = 11,
311 Pup = 12,
313 Argus = 13,
315 Emcon = 14,
317 Xnet = 15,
319 Chaos = 16,
321 Udp = 17,
323 Mux = 18,
325 DcnMeas = 19,
327 Hmp = 20,
329 Prm = 21,
331 Idp = 22,
333 Trunk1 = 23,
335 Trunk2 = 24,
337 Leaf1 = 25,
339 Leaf2 = 26,
341 Rdp = 27,
343 Irtp = 28,
345 Tp4 = 29,
347 Netblt = 30,
349 MfeNsp = 31,
351 MeritInp = 32,
353 Dccp = 33,
355 ThirdPartyConnect = 34,
357 Idpr = 35,
359 Xtp = 36,
361 Ddp = 37,
363 IdprCmtp = 38,
365 TpPlusPlus = 39,
367 Il = 40,
369 Ipv6 = 41,
371 Sdrp = 42,
373 Ipv6Route = 43,
375 Ipv6Frag = 44,
377 Idrp = 45,
379 Rsvp = 46,
381 Gre = 47,
383 Dsr = 48,
385 Bna = 49,
387 Esp = 50,
389 Ah = 51,
391 Inlsp = 52,
393 Swipe = 53,
395 Narp = 54,
397 Mobile = 55,
399 Tlsp = 56,
401 Skip = 57,
403 Ipv6Icmp = 58,
405 Ipv6NoNxt = 59,
407 Ipv6Opts = 60,
409 AnyHostInternal = 61,
411 Cftp = 62,
413 AnyLocalNetwork = 63,
415 SatExpak = 64,
417 Kryptolan = 65,
419 Rvd = 66,
421 Ippc = 67,
423 AnyDistributedFileSystem = 68,
425 SatMon = 69,
427 Visa = 70,
429 Ipcv = 71,
431 Cpnx = 72,
433 Cphb = 73,
435 Wsn = 74,
437 Pvp = 75,
439 BrSatMon = 76,
441 SunNd = 77,
443 WbMon = 78,
445 WbExpak = 79,
447 IsoIp = 80,
449 Vmtp = 81,
451 SecureVmtp = 82,
453 Vines = 83,
455 Ttp = 84,
457 NsfnetIgp = 85,
459 Dgp = 86,
461 Tcf = 87,
463 Eigrp = 88,
465 Ospfigp = 89,
467 SpriteRpc = 90,
469 Larp = 91,
471 Mtp = 92,
473 Ax25 = 93,
475 Ipip = 94,
477 Micp = 95,
479 SccSp = 96,
481 Etherip = 97,
483 Encap = 98,
485 AnyPrivateEncryptionScheme = 99,
487 Gmtp = 100,
489 Ifmp = 101,
491 Pnni = 102,
493 Pim = 103,
495 Aris = 104,
497 Scps = 105,
499 Qnx = 106,
501 ActiveNetworks = 107,
503 IpComp = 108,
505 Snp = 109,
507 CompaqPeer = 110,
509 IpxInIp = 111,
511 Vrrp = 112,
513 Pgm = 113,
515 AnyZeroHopProtocol = 114,
517 L2tp = 115,
519 Ddx = 116,
521 Iatp = 117,
523 Stp = 118,
525 Srp = 119,
527 Uti = 120,
529 Smp = 121,
531 Sm = 122,
533 Ptp = 123,
535 IsisOverIpv4 = 124,
537 Fire = 125,
539 Crtp = 126,
541 Crudp = 127,
543 Sscopmce = 128,
545 Iplt = 129,
547 Sps = 130,
549 Pipe = 131,
551 Sctp = 132,
553 Fc = 133,
555 RsvpE2eIgnore = 134,
557 MobilityHeader = 135,
559 UdpLite = 136,
561 Mpls = 137,
563 Manet = 138,
565 Hip = 139,
567 Shim6 = 140,
569 Wesp = 141,
571 Rohc = 142,
573 EthernetInIpv4 = 143,
575 Aggfrag = 144,
577 Test1 = 253,
579 Test2 = 254,
581 Reserved = 255,
583}
584
585#[cfg(test)]
586mod tests {
587 use super::*;
588 use core::net::{Ipv4Addr, Ipv6Addr};
589
590 fn default_ipv4_hdr() -> Ipv4Hdr {
592 Ipv4Hdr {
593 vihl: 0,
594 tos: 0,
595 tot_len: [0; 2],
596 id: [0; 2],
597 frags: [0; 2],
598 ttl: 0,
599 proto: IpProto::Tcp,
600 check: [0; 2],
601 src_addr: [0; 4],
602 dst_addr: [0; 4],
603 }
604 }
605
606 fn default_ipv6_hdr() -> Ipv6Hdr {
608 Ipv6Hdr {
609 vcf: [0; 4],
610 payload_len: [0; 2],
611 next_hdr: IpProto::Tcp,
612 hop_limit: 0,
613 src_addr: [0; 16],
614 dst_addr: [0; 16],
615 }
616 }
617
618 #[test]
619 fn test_ipv4_vihl() {
620 let mut hdr = default_ipv4_hdr();
621 hdr.set_vihl(4, 20); assert_eq!(hdr.version(), 4);
623 assert_eq!(hdr.ihl(), 20);
624
625 hdr.set_vihl(4, 24); assert_eq!(hdr.version(), 4);
627 assert_eq!(hdr.ihl(), 24);
628 }
629
630 #[test]
631 fn test_ipv4_tos() {
632 let mut hdr = default_ipv4_hdr();
633 hdr.set_tos(0b001010, 0b01); assert_eq!(hdr.dscp(), 0b001010);
635 assert_eq!(hdr.ecn(), 0b01);
636
637 hdr.set_tos(0b110011, 0b10); assert_eq!(hdr.dscp(), 0b110011);
639 assert_eq!(hdr.ecn(), 0b10);
640 }
641
642 #[test]
643 fn test_ipv4_tot_len() {
644 let mut hdr = default_ipv4_hdr();
645 hdr.set_tot_len(1500);
646 assert_eq!(hdr.tot_len(), 1500);
647 }
648
649 #[test]
650 fn test_ipv4_id() {
651 let mut hdr = default_ipv4_hdr();
652 hdr.set_id(0xABCD);
653 assert_eq!(hdr.id(), 0xABCD);
654 }
655
656 #[test]
657 fn test_ipv4_frags() {
658 let mut hdr = default_ipv4_hdr();
659 hdr.set_frags(0b010, 100);
661 assert_eq!(hdr.frag_flags(), 0b010);
662 assert_eq!(hdr.frag_offset(), 100);
663
664 hdr.set_frags(0b001, 0x1ABC);
666 assert_eq!(hdr.frag_flags(), 0b001);
667 assert_eq!(hdr.frag_offset(), 0x1ABC);
668 }
669
670 #[test]
671 fn test_ipv4_checksum() {
672 let mut hdr = default_ipv4_hdr();
673 hdr.set_checksum(0x1234);
674 assert_eq!(hdr.checksum(), 0x1234);
675 }
676
677 #[test]
678 fn test_ipv4_addrs() {
679 let mut hdr = default_ipv4_hdr();
680 let src = Ipv4Addr::new(192, 168, 1, 1);
681 let dst = Ipv4Addr::new(10, 0, 0, 1);
682 hdr.set_src_addr(src);
683 hdr.set_dst_addr(dst);
684 assert_eq!(hdr.src_addr(), src);
685 assert_eq!(hdr.dst_addr(), dst);
686 }
687
688 #[test]
689 fn test_ipv6_version() {
690 let mut hdr = default_ipv6_hdr();
691 hdr.set_version(6);
692 assert_eq!(hdr.version(), 6);
693 }
694
695 #[test]
696 fn test_ipv6_dscp_ecn() {
697 let mut hdr = default_ipv6_hdr();
698 hdr.set_dscp_ecn(0b001010, 0b01);
700 assert_eq!(hdr.dscp(), 0b001010);
701 assert_eq!(hdr.ecn(), 0b01);
702
703 hdr.set_version(6);
707 hdr.set_flow_label(0xFFFFF); hdr.set_dscp_ecn(0b110011, 0b10);
709 assert_eq!(hdr.version(), 6); assert_eq!(hdr.dscp(), 0b110011);
711 assert_eq!(hdr.ecn(), 0b10);
712 assert_eq!(hdr.flow_label(), 0xFFFFF); }
714
715 #[test]
716 fn test_ipv6_flow_label() {
717 let mut hdr = default_ipv6_hdr();
718 hdr.set_flow_label(0x12345); assert_eq!(hdr.flow_label(), 0x12345);
720
721 hdr.set_version(6);
724 hdr.set_dscp_ecn(0b001010, 0b01);
725 hdr.set_flow_label(0xABCDE);
726 assert_eq!(hdr.version(), 6);
727 assert_eq!(hdr.dscp(), 0b001010);
728 assert_eq!(hdr.ecn(), 0b01);
729 assert_eq!(hdr.flow_label(), 0xABCDE);
730 }
731
732 #[test]
733 fn test_ipv6_set_vcf() {
734 let mut hdr = default_ipv6_hdr();
735 let version = 6;
736 let dscp = 0b001111; let ecn = 0b11; let flow_label = 0xFEDCB; hdr.set_vcf(version, dscp, ecn, flow_label);
741 assert_eq!(hdr.version(), version);
742 assert_eq!(hdr.dscp(), dscp);
743 assert_eq!(hdr.ecn(), ecn);
744 assert_eq!(hdr.flow_label(), flow_label);
745 }
746
747 #[test]
748 fn test_ipv6_payload_len() {
749 let mut hdr = default_ipv6_hdr();
750 hdr.set_payload_len(3000);
751 assert_eq!(hdr.payload_len(), 3000);
752 }
753
754 #[test]
755 fn test_ipv6_addrs() {
756 let mut hdr = default_ipv6_hdr();
757 let src = Ipv6Addr::new(0x2001, 0x0db8, 0, 0, 0, 0, 0, 0x0001);
758 let dst = Ipv6Addr::new(0x2001, 0x0db8, 0, 0, 0, 0, 0, 0x0002);
759 hdr.set_src_addr(src);
760 hdr.set_dst_addr(dst);
761 assert_eq!(hdr.src_addr(), src);
762 assert_eq!(hdr.dst_addr(), dst);
763 }
764
765 #[test]
766 fn test_ip_proto_variants() {
767 assert_eq!(IpProto::Tcp as u8, 6);
768 assert_eq!(IpProto::Udp as u8, 17);
769 assert_eq!(IpProto::Icmp as u8, 1);
770 assert_eq!(IpProto::Ipv6Icmp as u8, 58);
771 }
772
773 #[test]
774 fn test_iphdr_enum() {
775 let ipv4_hdr = default_ipv4_hdr();
776 let ip_hdr_v4 = IpHdr::V4(ipv4_hdr);
777 if let IpHdr::V4(hdr) = ip_hdr_v4 {
778 assert_eq!(hdr.vihl, ipv4_hdr.vihl); } else {
780 panic!("Expected IpHdr::V4");
781 }
782
783 let ipv6_hdr = default_ipv6_hdr();
784 let ip_hdr_v6 = IpHdr::V6(ipv6_hdr);
785 if let IpHdr::V6(hdr) = ip_hdr_v6 {
786 assert_eq!(hdr.vcf, ipv6_hdr.vcf); } else {
788 panic!("Expected IpHdr::V6");
789 }
790 }
791}