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