Skip to content

Commit 8111765

Browse files
committed
Implement IPv4 checksum and update header fields
- Implement checksum calculation for IPv4 header. - Replace TOS header field with the new DSCP and ECN fields as directed in RFC 2474 and RFC 3168. Signed-off-by: Mohammad Aadil Shabier <[email protected]>
1 parent 73606b6 commit 8111765

File tree

1 file changed

+23
-8
lines changed

1 file changed

+23
-8
lines changed

src/layers/ipv4.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,10 @@ pub enum IPOption {
8585
pub struct IPv4 {
8686
version: u8,
8787
hdr_len: u8,
88-
tos: u8,
88+
#[serde(serialize_with = "crate::types::hex::serialize_lower_hex_u8")]
89+
dscp: u8,
90+
#[serde(serialize_with = "crate::types::hex::serialize_lower_hex_u8")]
91+
ecn: u8,
8992
len: u16,
9093
#[serde(serialize_with = "crate::types::hex::serialize_lower_hex_u16")]
9194
id: u16,
@@ -256,8 +259,16 @@ impl IPv4 {
256259
}
257260

258261
#[cfg(feature = "sculpting")]
259-
fn calculate_checksum(_bytes: &[u8]) -> u16 {
260-
0
262+
fn calculate_checksum(bytes: &[u8]) -> u16 {
263+
// 16 bit one's complement of one's complement sum of all 16 bit words
264+
let len = bytes.len();
265+
let mut csum = 0_u32;
266+
for i in 0..len/2 {
267+
let word = u16::from_be_bytes(bytes[2*i..2*(i+1)].try_into().unwrap());
268+
csum += word as u32;
269+
}
270+
csum = ((csum >> 16) + (csum & 0xffff)) as u32;
271+
(!csum & 0xffff) as u16
261272
}
262273
}
263274

@@ -279,7 +290,8 @@ impl Layer for IPv4 {
279290
data: hex::encode(bytes),
280291
});
281292
}
282-
self.tos = bytes[1];
293+
self.dscp = bytes[1] >> 2;
294+
self.ecn = bytes[1] & 0b11;
283295
self.len = u16::from_be_bytes(bytes[2..4].try_into().unwrap());
284296
self.id = u16::from_be_bytes(bytes[4..6].try_into().unwrap());
285297
let flags_offset = u16::from_be_bytes(bytes[6..8].try_into().unwrap());
@@ -337,9 +349,11 @@ impl Layer for IPv4 {
337349

338350
let mut result = Vec::with_capacity(self.len as usize);
339351

340-
let byte = (self.version << 4) | self.hdr_len;
352+
let mut byte = (self.version << 4) | self.hdr_len;
353+
result.push(byte);
354+
355+
byte = (self.dscp << 2) | self.ecn;
341356
result.push(byte);
342-
result.push(self.tos);
343357
result.extend(self.len.to_be_bytes());
344358
result.extend(self.id.to_be_bytes());
345359

@@ -357,10 +371,11 @@ impl Layer for IPv4 {
357371
todo!();
358372
}
359373

360-
result.extend(next_layer.unwrap_or_default());
361-
362374
let checksum = IPv4::calculate_checksum(&result);
363375
result[checksum_start..checksum_start + 2].copy_from_slice(&checksum.to_be_bytes());
376+
377+
result.extend(next_layer.unwrap_or_default());
378+
364379
Ok(result)
365380
}
366381
}

0 commit comments

Comments
 (0)