1use crate::ip::IpNextHeaderProtocol;
12use crate::{types::*, util, Packet, PrimitiveValues};
13use std::net::Ipv4Addr;
14
15#[allow(non_snake_case)]
17#[allow(non_upper_case_globals)]
18pub mod Ipv4Flags {
19 use crate::types::*;
20
21 pub const DontFragment: u3 = 0b010;
23 pub const MoreFragments: u3 = 0b001;
25}
26
27#[allow(non_snake_case)]
30#[allow(non_upper_case_globals)]
31pub mod Ipv4OptionNumbers {
32 use super::Ipv4OptionNumber;
33
34 pub const EOL: Ipv4OptionNumber = Ipv4OptionNumber(0);
36
37 pub const NOP: Ipv4OptionNumber = Ipv4OptionNumber(1);
39
40 pub const SEC: Ipv4OptionNumber = Ipv4OptionNumber(2);
42
43 pub const LSR: Ipv4OptionNumber = Ipv4OptionNumber(3);
45
46 pub const TS: Ipv4OptionNumber = Ipv4OptionNumber(4);
48
49 pub const ESEC: Ipv4OptionNumber = Ipv4OptionNumber(5);
51
52 pub const CIPSO: Ipv4OptionNumber = Ipv4OptionNumber(6);
54
55 pub const RR: Ipv4OptionNumber = Ipv4OptionNumber(7);
57
58 pub const SID: Ipv4OptionNumber = Ipv4OptionNumber(8);
60
61 pub const SSR: Ipv4OptionNumber = Ipv4OptionNumber(9);
63
64 pub const ZSU: Ipv4OptionNumber = Ipv4OptionNumber(10);
66
67 pub const MTUP: Ipv4OptionNumber = Ipv4OptionNumber(11);
69
70 pub const MTUR: Ipv4OptionNumber = Ipv4OptionNumber(12);
72
73 pub const FINN: Ipv4OptionNumber = Ipv4OptionNumber(13);
75
76 pub const VISA: Ipv4OptionNumber = Ipv4OptionNumber(14);
78
79 pub const ENCODE: Ipv4OptionNumber = Ipv4OptionNumber(15);
81
82 pub const IMITD: Ipv4OptionNumber = Ipv4OptionNumber(16);
84
85 pub const EIP: Ipv4OptionNumber = Ipv4OptionNumber(17);
87
88 pub const TR: Ipv4OptionNumber = Ipv4OptionNumber(18);
90
91 pub const ADDEXT: Ipv4OptionNumber = Ipv4OptionNumber(19);
93
94 pub const RTRALT: Ipv4OptionNumber = Ipv4OptionNumber(20);
96
97 pub const SDB: Ipv4OptionNumber = Ipv4OptionNumber(21);
99
100 pub const DPS: Ipv4OptionNumber = Ipv4OptionNumber(23);
102
103 pub const UMP: Ipv4OptionNumber = Ipv4OptionNumber(24);
105
106 pub const QS: Ipv4OptionNumber = Ipv4OptionNumber(25);
108
109 pub const EXP: Ipv4OptionNumber = Ipv4OptionNumber(30);
111}
112
113#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
115pub struct Ipv4OptionNumber(pub u8);
116
117impl Ipv4OptionNumber {
118 pub fn new(value: u8) -> Ipv4OptionNumber {
120 Ipv4OptionNumber(value)
121 }
122}
123
124impl PrimitiveValues for Ipv4OptionNumber {
125 type T = (u8,);
126 fn to_primitive_values(&self) -> (u8,) {
127 (self.0,)
128 }
129}
130
131#[derive(Debug, Packet)]
133pub struct Ipv4 {
134 pub version: u4,
135 pub header_length: u4,
136 pub dscp: u6,
137 pub ecn: u2,
138 pub total_length: u16be,
139 pub identification: u16be,
140 pub flags: u3,
141 pub fragment_offset: u13be,
142 pub ttl: u8,
143 #[construct_with(u8)]
144 pub next_level_protocol: IpNextHeaderProtocol,
145 pub checksum: u16be,
146 #[construct_with(u8, u8, u8, u8)]
147 pub source: Ipv4Addr,
148 #[construct_with(u8, u8, u8, u8)]
149 pub destination: Ipv4Addr,
150 #[length = "ipv4_options_length(header_length)"]
151 pub options: Vec<Ipv4Option>,
152 #[length = "ipv4_payload_length(total_length, header_length)"]
153 #[payload]
154 pub payload: Vec<u8>,
155}
156
157pub fn checksum(packet: &Ipv4Packet) -> u16be {
160 let min = Ipv4Packet::minimum_packet_size();
161 let max = packet.packet().len();
162 let header_length = match packet.get_header_length() as usize * 4 {
163 length if length < min => min,
164 length if length > max => max,
165 length => length,
166 };
167 let data = &packet.packet()[..header_length];
168 util::checksum(data, 5)
169}
170
171#[cfg(test)]
172mod checksum_tests {
173 use super::*;
174
175 #[test]
176 fn checksum_zeros() {
177 let mut data = vec![0; 20];
178 let expected = 64255;
179 let mut pkg = MutableIpv4Packet::new(&mut data[..]).unwrap();
180 pkg.set_header_length(5);
181 assert_eq!(checksum(&pkg.to_immutable()), expected);
182 pkg.set_checksum(123);
183 assert_eq!(checksum(&pkg.to_immutable()), expected);
184 }
185
186 #[test]
187 fn checksum_nonzero() {
188 let mut data = vec![255; 20];
189 let expected = 2560;
190 let mut pkg = MutableIpv4Packet::new(&mut data[..]).unwrap();
191 pkg.set_header_length(5);
192 assert_eq!(checksum(&pkg.to_immutable()), expected);
193 pkg.set_checksum(123);
194 assert_eq!(checksum(&pkg.to_immutable()), expected);
195 }
196
197 #[test]
198 fn checksum_too_small_header_length() {
199 let mut data = vec![148; 20];
200 let expected = 51910;
201 let mut pkg = MutableIpv4Packet::new(&mut data[..]).unwrap();
202 pkg.set_header_length(0);
203 assert_eq!(checksum(&pkg.to_immutable()), expected);
204 }
205
206 #[test]
207 fn checksum_too_large_header_length() {
208 let mut data = vec![148; 20];
209 let expected = 51142;
210 let mut pkg = MutableIpv4Packet::new(&mut data[..]).unwrap();
211 pkg.set_header_length(99);
212 assert_eq!(checksum(&pkg.to_immutable()), expected);
213 }
214}
215
216fn ipv4_options_length(header_length: u8) -> usize {
217 (header_length as usize * 4).saturating_sub(20)
221}
222
223#[test]
224fn ipv4_options_length_test() {
225 assert_eq!(ipv4_options_length(5), 0);
226}
227
228fn ipv4_payload_length(total_length: u16, header_length: u8) -> usize {
229 (total_length as usize).saturating_sub(header_length as usize * 4)
230}
231
232#[test]
233fn ipv4_payload_length_test() {
234 assert_eq!(ipv4_payload_length(20, 5), 0);
235 assert_eq!(ipv4_payload_length(30, 5), 10);
238}
239
240#[derive(Debug, Packet)]
242pub struct Ipv4Option {
243 copied: u1,
244 class: u2,
245 #[construct_with(u5)]
246 number: Ipv4OptionNumber,
247 #[length = "ipv4_option_length(number)"]
248 length: Vec<u8>,
251 #[length = "ipv4_option_payload_length(&length)"]
252 #[payload]
253 data: Vec<u8>,
254}
255
256fn ipv4_option_length(number: Ipv4OptionNumber) -> usize {
260 match number {
261 Ipv4OptionNumbers::EOL => 0,
262 Ipv4OptionNumbers::NOP => 0,
263 _ => 1,
264 }
265}
266
267fn ipv4_option_payload_length(length: &[u8]) -> usize {
268 match length.first() {
269 Some(len) => (*len as usize).saturating_sub(2),
270 None => 0,
271 }
272}
273
274#[test]
275fn ipv4_packet_test() {
276 use crate::ip::IpNextHeaderProtocols;
277 use crate::{Packet, PacketSize};
278
279 let mut packet = [0u8; 200];
280 {
281 let mut ip_header = MutableIpv4Packet::new(&mut packet[..]).unwrap();
282 ip_header.set_version(4);
283 assert_eq!(ip_header.get_version(), 4);
284
285 ip_header.set_header_length(5);
286 assert_eq!(ip_header.get_header_length(), 5);
287
288 ip_header.set_dscp(4);
289 assert_eq!(ip_header.get_dscp(), 4);
290
291 ip_header.set_ecn(1);
292 assert_eq!(ip_header.get_ecn(), 1);
293
294 ip_header.set_total_length(115);
295 assert_eq!(ip_header.get_total_length(), 115);
296 assert_eq!(95, ip_header.payload().len());
297 assert_eq!(ip_header.get_total_length(), ip_header.packet_size() as u16);
298
299 ip_header.set_identification(257);
300 assert_eq!(ip_header.get_identification(), 257);
301
302 ip_header.set_flags(Ipv4Flags::DontFragment);
303 assert_eq!(ip_header.get_flags(), 2);
304
305 ip_header.set_fragment_offset(257);
306 assert_eq!(ip_header.get_fragment_offset(), 257);
307
308 ip_header.set_ttl(64);
309 assert_eq!(ip_header.get_ttl(), 64);
310
311 ip_header.set_next_level_protocol(IpNextHeaderProtocols::Udp);
312 assert_eq!(
313 ip_header.get_next_level_protocol(),
314 IpNextHeaderProtocols::Udp
315 );
316
317 ip_header.set_source(Ipv4Addr::new(192, 168, 0, 1));
318 assert_eq!(ip_header.get_source(), Ipv4Addr::new(192, 168, 0, 1));
319
320 ip_header.set_destination(Ipv4Addr::new(192, 168, 0, 199));
321 assert_eq!(ip_header.get_destination(), Ipv4Addr::new(192, 168, 0, 199));
322
323 let imm_header = checksum(&ip_header.to_immutable());
324 ip_header.set_checksum(imm_header);
325 assert_eq!(ip_header.get_checksum(), 0xb64e);
326 }
327
328 let ref_packet = [
329 0x45, 0x11, 0x00, 0x73, 0x01, 0x01, 0x41, 0x01, 0x40, 0x11, 0xb6, 0x4e, 0xc0, 0xa8, 0x00, 0x01, 0xc0, 0xa8, 0x00, 0xc7, ];
340
341 assert_eq!(&ref_packet[..], &packet[..ref_packet.len()]);
342}
343
344#[test]
345fn ipv4_packet_option_test() {
346 let mut packet = [0u8; 3];
347 {
348 let mut ipv4_options = MutableIpv4OptionPacket::new(&mut packet[..]).unwrap();
349
350 ipv4_options.set_copied(1);
351 assert_eq!(ipv4_options.get_copied(), 1);
352
353 ipv4_options.set_class(0);
354 assert_eq!(ipv4_options.get_class(), 0);
355
356 ipv4_options.set_number(Ipv4OptionNumber(3));
357 assert_eq!(ipv4_options.get_number(), Ipv4OptionNumbers::LSR);
358
359 ipv4_options.set_length(&vec![3]);
360 assert_eq!(ipv4_options.get_length(), vec![3]);
361
362 ipv4_options.set_data(&vec![16]);
363 }
364
365 let ref_packet = [
366 0x83, 0x03, 0x10, ];
370
371 assert_eq!(&ref_packet[..], &packet[..]);
372}
373
374#[test]
375fn ipv4_packet_set_payload_test() {
376 use Packet;
377
378 let mut packet = [0u8; 25]; let mut ip_packet = MutableIpv4Packet::new(&mut packet[..]).unwrap();
380 ip_packet.set_total_length(25);
381 ip_packet.set_header_length(5);
382 let payload = b"stuff"; ip_packet.set_payload(&payload[..]);
384 assert_eq!(ip_packet.payload(), payload);
385}
386
387#[test]
388#[should_panic(expected = "index 25 out of range for slice of length 24")]
389fn ipv4_packet_set_payload_test_panic() {
390 let mut packet = [0u8; 24]; let mut ip_packet = MutableIpv4Packet::new(&mut packet[..]).unwrap();
392 ip_packet.set_total_length(25);
393 ip_packet.set_header_length(5);
394 let payload = b"stuff"; ip_packet.set_payload(&payload[..]); }