summaryrefslogtreecommitdiff
path: root/src/protocol/ipv4.rs
diff options
context:
space:
mode:
authorluwenpeng <[email protected]>2023-10-09 10:43:45 +0800
committerluwenpeng <[email protected]>2023-10-09 11:27:54 +0800
commita48db093e708f7aba47386a3de3f828ad2370e90 (patch)
tree2b66f9004942b8ef5035a56a5cd8bd7144abc008 /src/protocol/ipv4.rs
parente0c7dfa5bd9d424249b87ec07d377e94d49d139a (diff)
[feature] Support IPv4 Options Decodedev-lwp
Diffstat (limited to 'src/protocol/ipv4.rs')
-rw-r--r--src/protocol/ipv4.rs104
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)));