1
+ use crate :: tcp:: TcpHeader ;
2
+ use crate :: utils:: calculate_ip_checksum;
3
+ use std:: net:: Ipv4Addr ;
4
+ use std:: str:: FromStr ;
5
+
1
6
/// Represents the IP header structure with its fields.
7
+ ///
8
+ /// This struct follows the IP header format.
9
+ /// Reference: https://github.com/wiseaidev/dark-web-rust/tree/main/chapter-1#13-the-ip-header-struct
10
+ #[ repr( C , packed) ]
2
11
#[ derive( Debug ) ]
3
12
pub struct IpHeader {
4
13
/// Version and Internet Header Length (IHL) combined field.
5
14
pub version_ihl : u8 ,
15
+ /// Type of Service (TOS) field.
16
+ pub tos : u8 ,
17
+ /// Length field.
18
+ pub len : u16 ,
19
+ /// Identification field.
20
+ pub id : u16 ,
21
+ /// Fragment Offset field.
22
+ pub offset : u16 ,
6
23
/// Time To Live (TTL) field.
7
24
pub ttl : u8 ,
8
- /// Source IP address field.
9
- pub source_ip : u32 ,
10
- /// Destination IP address field.
11
- pub dest_ip : u32 ,
12
25
/// Protocol field.
13
26
pub protocol : u8 ,
14
- /// Length field.
15
- pub len : u16 ,
27
+ /// Header Checksum field.
28
+ pub sum : u16 ,
29
+ /// Source IP address field.
30
+ pub src : u32 ,
31
+ /// Destination IP address field.
32
+ pub dst : u32 ,
16
33
}
17
34
/// Implements methods for the IpHeader struct.
18
35
impl IpHeader {
36
+ /// Constructs an IP header with the given source IP and computes the length and checksum.
37
+ ///
38
+ /// # Arguments
39
+ ///
40
+ /// * `source_ip` - The source IP address.
41
+ /// * `dest_ip` - The target ip.
42
+ ///
43
+ /// # Returns
44
+ ///
45
+ /// (`IpHeader`): The IP header with calculated length and checksum.
46
+ ///
47
+ /// # Examples
48
+ ///
49
+ /// ```
50
+ /// use rping::utils::{generate_random_ip, calculate_tcp_checksum};
51
+ /// use rping::ip::IpHeader;
52
+ ///
53
+ /// let source_ip = generate_random_ip();
54
+ /// let ip_header = IpHeader::new(source_ip, "192.168.1.10");
55
+ /// // Ensure that relevant fields have been initialized properly.
56
+ /// assert_eq!(ip_header.version_ihl, (4 << 4) | 5);
57
+ /// assert_eq!(ip_header.protocol, 6);
58
+ /// ```
59
+ pub fn new ( source_ip : u32 , dest_ip : & str ) -> Self {
60
+ let mut ip_header = Self {
61
+ version_ihl : 69 ,
62
+ tos : 0 ,
63
+ len : 0 ,
64
+ id : 0 ,
65
+ offset : 0 ,
66
+ ttl : 50 ,
67
+ protocol : 6 ,
68
+ sum : 0 ,
69
+ src : source_ip. to_be ( ) ,
70
+ dst : Ipv4Addr :: from_str ( dest_ip) . unwrap ( ) . into ( ) ,
71
+ } ;
72
+
73
+ // Convert destination IP to big-endian
74
+ ip_header. dst = ip_header. dst . to_be ( ) ;
75
+
76
+ // Calculate the total length (IP header + TCP header)
77
+ let total_length =
78
+ ( std:: mem:: size_of :: < IpHeader > ( ) + std:: mem:: size_of :: < TcpHeader > ( ) ) as u16 ;
79
+
80
+ // Set the total length in the IP header
81
+ ip_header. len = total_length. to_be ( ) ;
82
+
83
+ // Calculate the checksum without TCP header
84
+ ip_header. sum = calculate_ip_checksum ( & ip_header) ;
85
+
86
+ // Convert length and checksum to network byte order (big-endian)
87
+ ip_header. len = ip_header. len . to_be ( ) ;
88
+ ip_header. sum = ip_header. sum . to_be ( ) ;
89
+
90
+ ip_header
91
+ }
92
+
19
93
/// Returns a byte slice representing the binary data of the IpHeader.
20
94
///
21
95
/// # Examples
@@ -24,14 +98,21 @@ impl IpHeader {
24
98
///
25
99
/// let ip_header = IpHeader {
26
100
/// version_ihl: 0x45,
101
+ /// tos: 0,
102
+ /// len: 20,
103
+ /// id: 0,
104
+ /// offset: 0,
27
105
/// ttl: 64,
28
- /// source_ip: 0xC0A80001, // 192.168.0.1
29
- /// dest_ip: 0xC0A80002, // 192.168.0.2
30
106
/// protocol: 6,
31
- /// len: 0,
107
+ /// sum: 127,
108
+ /// src: 0xC0A80001, // 192.168.0.1
109
+ /// dst: 0xC0A80002, // 192.168.0.2
32
110
/// };
33
111
///
34
- /// assert_eq!(ip_header.as_bytes(), &[1, 0, 168, 192, 2, 0, 168, 192, 0, 0, 69, 64, 6, 127, 0, 0]);
112
+ /// assert_eq!(
113
+ /// ip_header.as_bytes(),
114
+ /// &[69, 0, 20, 0, 0, 0, 0, 0, 64, 6, 127, 0, 1, 0, 168, 192, 2, 0, 168, 192]
115
+ /// );
35
116
/// ```
36
117
/// Returns a byte slice representing the binary data of the IpHeader.
37
118
pub fn as_bytes ( & self ) -> & [ u8 ] {
@@ -52,16 +133,20 @@ mod tests {
52
133
fn test_ip_header_as_bytes ( ) {
53
134
let ip_header = IpHeader {
54
135
version_ihl : 0x45 ,
136
+ tos : 0 ,
137
+ len : 20 ,
138
+ id : 0 ,
139
+ offset : 0 ,
55
140
ttl : 64 ,
56
- source_ip : 0xC0A80001 , // 192.168.0.1
57
- dest_ip : 0xC0A80002 , // 192.168.0.2
58
141
protocol : 6 ,
59
- len : 0 ,
142
+ sum : 0 ,
143
+ src : 0xC0A80001 , // 192.168.0.1
144
+ dst : 0xC0A80002 , // 192.168.0.2
60
145
} ;
61
146
62
147
assert_eq ! (
63
148
ip_header. as_bytes( ) ,
64
- & [ 1 , 0 , 168 , 192 , 2 , 0 , 168 , 192 , 0 , 0 , 69 , 64 , 6 , 0 , 0 , 0 ]
149
+ & [ 69 , 0 , 20 , 0 , 0 , 0 , 0 , 0 , 64 , 6 , 0 , 0 , 1 , 0 , 168 , 192 , 2 , 0 , 168 , 192 ]
65
150
) ;
66
151
}
67
152
}
0 commit comments