diff options
| author | luwenpeng <[email protected]> | 2023-10-09 10:43:45 +0800 |
|---|---|---|
| committer | luwenpeng <[email protected]> | 2023-10-09 11:27:54 +0800 |
| commit | a48db093e708f7aba47386a3de3f828ad2370e90 (patch) | |
| tree | 2b66f9004942b8ef5035a56a5cd8bd7144abc008 /src/protocol/ipv4.rs | |
| parent | e0c7dfa5bd9d424249b87ec07d377e94d49d139a (diff) | |
[feature] Support IPv4 Options Decodedev-lwp
Diffstat (limited to 'src/protocol/ipv4.rs')
| -rw-r--r-- | src/protocol/ipv4.rs | 104 |
1 files changed, 101 insertions, 3 deletions
diff --git a/src/protocol/ipv4.rs b/src/protocol/ipv4.rs index 2297196..f2fc19b 100644 --- a/src/protocol/ipv4.rs +++ b/src/protocol/ipv4.rs @@ -45,6 +45,7 @@ pub struct IPv4Header { pub checksum: u16, pub source_address: Ipv4Addr, pub dest_address: Ipv4Addr, + pub options: Option<Vec<u8>>, } /****************************************************************************** @@ -84,8 +85,11 @@ impl Decode for IPv4Header { let (input, checksum) = number::streaming::be_u16(input)?; let (input, source_address) = address_v4_decode(input)?; let (input, dest_address) = address_v4_decode(input)?; - - // TODO IPv4 Options Decode + let (input, options) = match verihl.1 > 5 { + true => nom::bytes::streaming::take((verihl.1 - 5) * 4)(input) + .map(|(i, l)| (i, Some(l.to_vec())))?, + false => (input, None), + }; Ok(( input, @@ -102,6 +106,7 @@ impl Decode for IPv4Header { checksum, source_address, dest_address, + options, }, )) } @@ -121,7 +126,8 @@ mod tests { const LAST_SLICE: &'static [u8] = &[0xff]; #[test] - fn ipv4_header_decode() { + // Without Options + fn ipv4_header_decode1() { /* * Internet Protocol Version 4, Src: 192.168.0.101, Dst: 121.14.154.93 * 0100 .... = Version: 4 @@ -173,6 +179,98 @@ mod tests { checksum: 0xc352, source_address: Ipv4Addr::new(192, 168, 0, 101), dest_address: Ipv4Addr::new(121, 14, 154, 93), + options: None, + }; + + assert_eq!(IPv4Header::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = IPv4Header::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } + } + + // assert_eq!(1, 0); + } + + #[test] + // With Options + fn ipv4_header_decode2() { + /* + * Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1 + * 0100 .... = Version: 4 + * .... 1111 = Header Length: 60 bytes (15) + * Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) + * 0000 00.. = Differentiated Services Codepoint: Default (0) + * .... ..00 = Explicit Congestion Notification: Not ECN-Capable Transport (0) + * Total Length: 124 + * Identification: 0x0000 (0) + * 010. .... = Flags: 0x2, Don't fragment + * 0... .... = Reserved bit: Not set + * .1.. .... = Don't fragment: Set + * ..0. .... = More fragments: Not set + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 64 + * Protocol: ICMP (1) + * Header Checksum: 0xfd30 [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0xfd30] + * Source Address: 127.0.0.1 + * Destination Address: 127.0.0.1 + * Options: (40 bytes), Commercial Security + * IP Option - Commercial Security (40 bytes) + * Type: 134 + * 1... .... = Copy on fragmentation: Yes + * .00. .... = Class: Control (0) + * ...0 0110 = Number: Commercial IP security option (6) + * Length: 40 + * DOI: 1 + * Tag Type: Restrictive Category Bitmap (1) + * Sensitivity Level: 1 + * Categories: 0,2,4,5,6,239 + */ + + let bytes = [ + 0x4f, /* Version and Header length */ + 0x00, /* Differentiated Services Field */ + 0x00, 0x7c, /* Total Length */ + 0x00, 0x00, /* Identification */ + 0x40, 0x00, /* Flags and Fragment Offset */ + 0x40, /* Time to Live */ + 0x01, /* Protocol */ + 0xfd, 0x30, /* Header Checksum */ + 0x7f, 0x00, 0x00, 0x01, /* Source Address */ + 0x7f, 0x00, 0x00, 0x01, /* Destination Address */ + 0x86, 0x28, 0x00, 0x00, 0x00, 0x01, 0x01, 0x22, 0x00, 0x01, 0xae, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, /* Options */ + 0xff, /* Payload */ + ]; + + let expectation = IPv4Header { + version: 4, + ihl: 60, + tos: 0, + length: 124, + id: 0x0000, + flags: 0x2, + frag_offset: 0, + ttl: 64, + protocol: IPProtocol::ICMP, + checksum: 0xfd30, + source_address: Ipv4Addr::new(127, 0, 0, 1), + dest_address: Ipv4Addr::new(127, 0, 0, 1), + options: Some(vec![ + 0x86, 0x28, 0x00, 0x00, 0x00, 0x01, 0x01, 0x22, 0x00, 0x01, 0xae, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + ]), }; assert_eq!(IPv4Header::decode(&bytes), Ok((LAST_SLICE, expectation))); |
