1use crate::ip::IpNextLevelProtocol;
4use crate::PrimitiveValues;
5
6use alloc::vec::Vec;
7
8use nex_macro::packet;
9use nex_macro_helper::types::*;
10
11use std::net::Ipv4Addr;
12
13#[cfg(feature = "serde")]
14use serde::{Deserialize, Serialize};
15
16pub const IPV4_HEADER_LEN: usize = MutableIpv4Packet::minimum_packet_size();
18pub const IPV4_HEADER_LENGTH_BYTE_UNITS: usize = 4;
20
21#[derive(Clone, Debug, PartialEq, Eq)]
23#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
24pub struct Ipv4OptionHeader {
25 pub copied: u1,
26 pub class: u2,
27 pub number: Ipv4OptionType,
28 pub length: Option<u8>,
29}
30
31#[derive(Clone, Debug, PartialEq, Eq)]
33#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
34pub struct Ipv4Header {
35 pub version: u4,
36 pub header_length: u4,
37 pub dscp: u6,
38 pub ecn: u2,
39 pub total_length: u16be,
40 pub identification: u16be,
41 pub flags: u3,
42 pub fragment_offset: u13be,
43 pub ttl: u8,
44 pub next_level_protocol: IpNextLevelProtocol,
45 pub checksum: u16be,
46 pub source: Ipv4Addr,
47 pub destination: Ipv4Addr,
48 pub options: Vec<Ipv4OptionHeader>,
49}
50
51impl Ipv4Header {
52 pub fn from_bytes(packet: &[u8]) -> Result<Ipv4Header, String> {
54 if packet.len() < IPV4_HEADER_LEN {
55 return Err("Packet is too small for IPv4 header".to_string());
56 }
57 match Ipv4Packet::new(packet) {
58 Some(ipv4_packet) => Ok(Ipv4Header {
59 version: ipv4_packet.get_version(),
60 header_length: ipv4_packet.get_header_length(),
61 dscp: ipv4_packet.get_dscp(),
62 ecn: ipv4_packet.get_ecn(),
63 total_length: ipv4_packet.get_total_length(),
64 identification: ipv4_packet.get_identification(),
65 flags: ipv4_packet.get_flags(),
66 fragment_offset: ipv4_packet.get_fragment_offset(),
67 ttl: ipv4_packet.get_ttl(),
68 next_level_protocol: ipv4_packet.get_next_level_protocol(),
69 checksum: ipv4_packet.get_checksum(),
70 source: ipv4_packet.get_source(),
71 destination: ipv4_packet.get_destination(),
72 options: ipv4_packet
73 .get_options_iter()
74 .map(|o| Ipv4OptionHeader {
75 copied: o.get_copied(),
76 class: o.get_class(),
77 number: o.get_number(),
78 length: o.get_length().first().cloned(),
79 })
80 .collect(),
81 }),
82 None => Err("Failed to parse IPv4 packet".to_string()),
83 }
84 }
85 pub(crate) fn from_packet(ipv4_packet: &Ipv4Packet) -> Ipv4Header {
87 Ipv4Header {
88 version: ipv4_packet.get_version(),
89 header_length: ipv4_packet.get_header_length(),
90 dscp: ipv4_packet.get_dscp(),
91 ecn: ipv4_packet.get_ecn(),
92 total_length: ipv4_packet.get_total_length(),
93 identification: ipv4_packet.get_identification(),
94 flags: ipv4_packet.get_flags(),
95 fragment_offset: ipv4_packet.get_fragment_offset(),
96 ttl: ipv4_packet.get_ttl(),
97 next_level_protocol: ipv4_packet.get_next_level_protocol(),
98 checksum: ipv4_packet.get_checksum(),
99 source: ipv4_packet.get_source(),
100 destination: ipv4_packet.get_destination(),
101 options: ipv4_packet
102 .get_options_iter()
103 .map(|o| Ipv4OptionHeader {
104 copied: o.get_copied(),
105 class: o.get_class(),
106 number: o.get_number(),
107 length: o.get_length().first().cloned(),
108 })
109 .collect(),
110 }
111 }
112}
113
114#[allow(non_snake_case)]
116#[allow(non_upper_case_globals)]
117pub mod Ipv4Flags {
118 use nex_macro_helper::types::*;
119
120 pub const DontFragment: u3 = 0b010;
122 pub const MoreFragments: u3 = 0b001;
124}
125
126#[repr(u8)]
129#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
130#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
131pub enum Ipv4OptionType {
132 EOL = 0,
134 NOP = 1,
136 SEC = 2,
138 LSR = 3,
140 TS = 4,
142 ESEC = 5,
144 CIPSO = 6,
146 RR = 7,
148 SID = 8,
150 SSR = 9,
152 ZSU = 10,
154 MTUP = 11,
156 MTUR = 12,
158 FINN = 13,
160 VISA = 14,
162 ENCODE = 15,
164 IMITD = 16,
166 EIP = 17,
168 TR = 18,
170 ADDEXT = 19,
172 RTRALT = 20,
174 SDB = 21,
176 Unassigned = 22,
178 DPS = 23,
180 UMP = 24,
182 QS = 25,
184 EXP = 30,
186 Unknown(u8),
188}
189
190impl Ipv4OptionType {
191 pub fn new(n: u8) -> Ipv4OptionType {
193 match n {
194 0 => Ipv4OptionType::EOL,
195 1 => Ipv4OptionType::NOP,
196 2 => Ipv4OptionType::SEC,
197 3 => Ipv4OptionType::LSR,
198 4 => Ipv4OptionType::TS,
199 5 => Ipv4OptionType::ESEC,
200 6 => Ipv4OptionType::CIPSO,
201 7 => Ipv4OptionType::RR,
202 8 => Ipv4OptionType::SID,
203 9 => Ipv4OptionType::SSR,
204 10 => Ipv4OptionType::ZSU,
205 11 => Ipv4OptionType::MTUP,
206 12 => Ipv4OptionType::MTUR,
207 13 => Ipv4OptionType::FINN,
208 14 => Ipv4OptionType::VISA,
209 15 => Ipv4OptionType::ENCODE,
210 16 => Ipv4OptionType::IMITD,
211 17 => Ipv4OptionType::EIP,
212 18 => Ipv4OptionType::TR,
213 19 => Ipv4OptionType::ADDEXT,
214 20 => Ipv4OptionType::RTRALT,
215 21 => Ipv4OptionType::SDB,
216 22 => Ipv4OptionType::Unassigned,
217 23 => Ipv4OptionType::DPS,
218 24 => Ipv4OptionType::UMP,
219 25 => Ipv4OptionType::QS,
220 30 => Ipv4OptionType::EXP,
221 _ => Ipv4OptionType::Unknown(n),
222 }
223 }
224}
225
226impl PrimitiveValues for Ipv4OptionType {
227 type T = (u8,);
228 fn to_primitive_values(&self) -> (u8,) {
229 match *self {
230 Ipv4OptionType::EOL => (0,),
231 Ipv4OptionType::NOP => (1,),
232 Ipv4OptionType::SEC => (2,),
233 Ipv4OptionType::LSR => (3,),
234 Ipv4OptionType::TS => (4,),
235 Ipv4OptionType::ESEC => (5,),
236 Ipv4OptionType::CIPSO => (6,),
237 Ipv4OptionType::RR => (7,),
238 Ipv4OptionType::SID => (8,),
239 Ipv4OptionType::SSR => (9,),
240 Ipv4OptionType::ZSU => (10,),
241 Ipv4OptionType::MTUP => (11,),
242 Ipv4OptionType::MTUR => (12,),
243 Ipv4OptionType::FINN => (13,),
244 Ipv4OptionType::VISA => (14,),
245 Ipv4OptionType::ENCODE => (15,),
246 Ipv4OptionType::IMITD => (16,),
247 Ipv4OptionType::EIP => (17,),
248 Ipv4OptionType::TR => (18,),
249 Ipv4OptionType::ADDEXT => (19,),
250 Ipv4OptionType::RTRALT => (20,),
251 Ipv4OptionType::SDB => (21,),
252 Ipv4OptionType::Unassigned => (22,),
253 Ipv4OptionType::DPS => (23,),
254 Ipv4OptionType::UMP => (24,),
255 Ipv4OptionType::QS => (25,),
256 Ipv4OptionType::EXP => (30,),
257 Ipv4OptionType::Unknown(n) => (n,),
258 }
259 }
260}
261
262#[packet]
264pub struct Ipv4 {
265 pub version: u4,
266 pub header_length: u4,
267 pub dscp: u6,
268 pub ecn: u2,
269 pub total_length: u16be,
270 pub identification: u16be,
271 pub flags: u3,
272 pub fragment_offset: u13be,
273 pub ttl: u8,
274 #[construct_with(u8)]
275 pub next_level_protocol: IpNextLevelProtocol,
276 pub checksum: u16be,
277 #[construct_with(u8, u8, u8, u8)]
278 pub source: Ipv4Addr,
279 #[construct_with(u8, u8, u8, u8)]
280 pub destination: Ipv4Addr,
281 #[length_fn = "ipv4_options_length"]
282 pub options: Vec<Ipv4Option>,
283 #[length_fn = "ipv4_payload_length"]
284 #[payload]
285 pub payload: Vec<u8>,
286}
287
288pub fn checksum(packet: &Ipv4Packet) -> u16be {
291 use crate::util;
292 use crate::Packet;
293
294 let min = Ipv4Packet::minimum_packet_size();
295 let max = packet.packet().len();
296 let header_length = match packet.get_header_length() as usize * 4 {
297 length if length < min => min,
298 length if length > max => max,
299 length => length,
300 };
301 let data = &packet.packet()[..header_length];
302 util::checksum(data, 5)
303}
304
305#[cfg(test)]
306mod checksum_tests {
307 use super::*;
308 use alloc::vec;
309
310 #[test]
311 fn checksum_zeros() {
312 let mut data = vec![0; 20];
313 let expected = 64255;
314 let mut pkg = MutableIpv4Packet::new(&mut data[..]).unwrap();
315 pkg.set_header_length(5);
316 assert_eq!(checksum(&pkg.to_immutable()), expected);
317 pkg.set_checksum(123);
318 assert_eq!(checksum(&pkg.to_immutable()), expected);
319 }
320
321 #[test]
322 fn checksum_nonzero() {
323 let mut data = vec![255; 20];
324 let expected = 2560;
325 let mut pkg = MutableIpv4Packet::new(&mut data[..]).unwrap();
326 pkg.set_header_length(5);
327 assert_eq!(checksum(&pkg.to_immutable()), expected);
328 pkg.set_checksum(123);
329 assert_eq!(checksum(&pkg.to_immutable()), expected);
330 }
331
332 #[test]
333 fn checksum_too_small_header_length() {
334 let mut data = vec![148; 20];
335 let expected = 51910;
336 let mut pkg = MutableIpv4Packet::new(&mut data[..]).unwrap();
337 pkg.set_header_length(0);
338 assert_eq!(checksum(&pkg.to_immutable()), expected);
339 }
340
341 #[test]
342 fn checksum_too_large_header_length() {
343 let mut data = vec![148; 20];
344 let expected = 51142;
345 let mut pkg = MutableIpv4Packet::new(&mut data[..]).unwrap();
346 pkg.set_header_length(99);
347 assert_eq!(checksum(&pkg.to_immutable()), expected);
348 }
349}
350
351fn ipv4_options_length(ipv4: &Ipv4Packet) -> usize {
352 (ipv4.get_header_length() as usize * 4).saturating_sub(20)
356}
357
358#[test]
359fn ipv4_options_length_test() {
360 let mut packet = [0u8; 20];
361 let mut ip_header = MutableIpv4Packet::new(&mut packet[..]).unwrap();
362 ip_header.set_header_length(5);
363 assert_eq!(ipv4_options_length(&ip_header.to_immutable()), 0);
364}
365
366fn ipv4_payload_length(ipv4: &Ipv4Packet) -> usize {
367 (ipv4.get_total_length() as usize).saturating_sub(ipv4.get_header_length() as usize * 4)
368}
369
370#[test]
371fn ipv4_payload_length_test() {
372 let mut packet = [0u8; 30];
373 let mut ip_header = MutableIpv4Packet::new(&mut packet[..]).unwrap();
374 ip_header.set_header_length(5);
375 ip_header.set_total_length(20);
376 assert_eq!(ipv4_payload_length(&ip_header.to_immutable()), 0);
377 ip_header.set_total_length(30);
380 assert_eq!(ipv4_payload_length(&ip_header.to_immutable()), 10);
381}
382
383#[packet]
385pub struct Ipv4Option {
386 copied: u1,
387 class: u2,
388 #[construct_with(u5)]
389 number: Ipv4OptionType,
390 #[length_fn = "ipv4_option_length"]
391 length: Vec<u8>,
394 #[length_fn = "ipv4_option_payload_length"]
395 #[payload]
396 data: Vec<u8>,
397}
398
399fn ipv4_option_length(option: &Ipv4OptionPacket) -> usize {
403 match option.get_number() {
404 Ipv4OptionType::EOL => 0,
405 Ipv4OptionType::NOP => 0,
406 _ => 1,
407 }
408}
409
410fn ipv4_option_payload_length(ipv4_option: &Ipv4OptionPacket) -> usize {
411 match ipv4_option.get_length().first() {
412 Some(len) => (*len as usize).saturating_sub(2),
413 None => 0,
414 }
415}
416
417#[test]
418fn ipv4_packet_test() {
419 use crate::ip::IpNextLevelProtocol;
420 use crate::Packet;
421 use crate::PacketSize;
422
423 let mut packet = [0u8; 200];
424 {
425 let mut ip_header = MutableIpv4Packet::new(&mut packet[..]).unwrap();
426 ip_header.set_version(4);
427 assert_eq!(ip_header.get_version(), 4);
428
429 ip_header.set_header_length(5);
430 assert_eq!(ip_header.get_header_length(), 5);
431
432 ip_header.set_dscp(4);
433 assert_eq!(ip_header.get_dscp(), 4);
434
435 ip_header.set_ecn(1);
436 assert_eq!(ip_header.get_ecn(), 1);
437
438 ip_header.set_total_length(115);
439 assert_eq!(ip_header.get_total_length(), 115);
440 assert_eq!(95, ip_header.payload().len());
441 assert_eq!(ip_header.get_total_length(), ip_header.packet_size() as u16);
442
443 ip_header.set_identification(257);
444 assert_eq!(ip_header.get_identification(), 257);
445
446 ip_header.set_flags(Ipv4Flags::DontFragment as u3);
447 assert_eq!(ip_header.get_flags(), 2);
448
449 ip_header.set_fragment_offset(257);
450 assert_eq!(ip_header.get_fragment_offset(), 257);
451
452 ip_header.set_ttl(64);
453 assert_eq!(ip_header.get_ttl(), 64);
454
455 ip_header.set_next_level_protocol(IpNextLevelProtocol::Udp);
456 assert_eq!(
457 ip_header.get_next_level_protocol(),
458 IpNextLevelProtocol::Udp
459 );
460
461 ip_header.set_source(Ipv4Addr::new(192, 168, 0, 1));
462 assert_eq!(ip_header.get_source(), Ipv4Addr::new(192, 168, 0, 1));
463
464 ip_header.set_destination(Ipv4Addr::new(192, 168, 0, 199));
465 assert_eq!(ip_header.get_destination(), Ipv4Addr::new(192, 168, 0, 199));
466
467 let imm_header = checksum(&ip_header.to_immutable());
468 ip_header.set_checksum(imm_header);
469 assert_eq!(ip_header.get_checksum(), 0xb64e);
470 }
471
472 let ref_packet = [
473 0x45, 0x11, 0x00, 0x73, 0x01, 0x01, 0x41, 0x01, 0x40, 0x11, 0xb6, 0x4e, 0xc0, 0xa8, 0x00, 0x01, 0xc0, 0xa8, 0x00, 0xc7, ];
484
485 assert_eq!(&ref_packet[..], &packet[..ref_packet.len()]);
486}
487
488#[test]
489fn ipv4_packet_option_test() {
490 use alloc::vec;
491
492 let mut packet = [0u8; 3];
493 {
494 let mut ipv4_options = MutableIpv4OptionPacket::new(&mut packet[..]).unwrap();
495
496 ipv4_options.set_copied(1);
497 assert_eq!(ipv4_options.get_copied(), 1);
498
499 ipv4_options.set_class(0);
500 assert_eq!(ipv4_options.get_class(), 0);
501
502 ipv4_options.set_number(Ipv4OptionType::new(3));
503 assert_eq!(ipv4_options.get_number(), Ipv4OptionType::LSR);
504
505 ipv4_options.set_length(&vec![3]);
506 assert_eq!(ipv4_options.get_length(), vec![3]);
507
508 ipv4_options.set_data(&vec![16]);
509 }
510
511 let ref_packet = [
512 0x83, 0x03, 0x10, ];
516
517 assert_eq!(&ref_packet[..], &packet[..]);
518}
519
520#[test]
521fn ipv4_packet_set_payload_test() {
522 use crate::Packet;
523
524 let mut packet = [0u8; 25]; let mut ip_packet = MutableIpv4Packet::new(&mut packet[..]).unwrap();
526 ip_packet.set_total_length(25);
527 ip_packet.set_header_length(5);
528 let payload = b"stuff"; ip_packet.set_payload(&payload[..]);
530 assert_eq!(ip_packet.payload(), payload);
531}
532
533#[test]
534#[should_panic(expected = "index 25 out of range for slice of length 24")]
535fn ipv4_packet_set_payload_test_panic() {
536 let mut packet = [0u8; 24]; let mut ip_packet = MutableIpv4Packet::new(&mut packet[..]).unwrap();
538 ip_packet.set_total_length(25);
539 ip_packet.set_header_length(5);
540 let payload = b"stuff"; ip_packet.set_payload(&payload[..]); }