diff options
| author | luwenpeng <[email protected]> | 2023-07-28 14:02:23 +0800 |
|---|---|---|
| committer | luwenpeng <[email protected]> | 2023-08-01 11:44:26 +0800 |
| commit | 7749538385eff149da2a7de73f485cdd00baa129 (patch) | |
| tree | 8866ef8aa830a5e456dd323e71330253dddb6b31 | |
| parent | 9dd56a85f858f73fbc03079349f4c4b9b3295b79 (diff) | |
[feature] Support UDP Decode
| -rw-r--r-- | src/protocol/mod.rs | 3 | ||||
| -rw-r--r-- | src/protocol/udp.rs | 106 |
2 files changed, 108 insertions, 1 deletions
diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 7a3bb05..2591e5b 100644 --- a/src/protocol/mod.rs +++ b/src/protocol/mod.rs @@ -1,4 +1,5 @@ pub mod ethernet; pub mod ip; pub mod ipv4; -pub mod ipv6;
\ No newline at end of file +pub mod ipv6; +pub mod udp;
\ No newline at end of file diff --git a/src/protocol/udp.rs b/src/protocol/udp.rs new file mode 100644 index 0000000..c5fab65 --- /dev/null +++ b/src/protocol/udp.rs @@ -0,0 +1,106 @@ +use nom::number; +use nom::IResult; + +/****************************************************************************** + * Struct + ******************************************************************************/ + +/* + * User Datagram Header Format + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Source Port | Destination Port | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Length | Checksum | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Data | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct UdpHeader { + pub source_port: u16, + pub dest_port: u16, + pub length: u16, + pub checksum: u16, +} + +/****************************************************************************** + * API + ******************************************************************************/ + +impl UdpHeader { + pub fn decode(input: &[u8]) -> IResult<&[u8], UdpHeader> { + let (input, source_port) = number::streaming::be_u16(input)?; + let (input, dest_port) = number::streaming::be_u16(input)?; + let (input, length) = number::streaming::be_u16(input)?; + let (input, checksum) = number::streaming::be_u16(input)?; + + Ok(( + input, + UdpHeader { + source_port, + dest_port, + length, + checksum, + }, + )) + } +} + +/****************************************************************************** + * TEST + ******************************************************************************/ + +#[cfg(test)] +mod tests { + use super::UdpHeader; + + const LAST_SLICE: &'static [u8] = &[0xff]; + + #[test] + fn udp_header_decode() { + /* + * User Datagram Protocol, Src Port: 9993, Dst Port: 9993 + * Source Port: 9993 + * Destination Port: 9993 + * Length: 145 + * Checksum: 0x57d3 [correct] + * [Calculated Checksum: 0x57d3] + * [Checksum Status: Good] + * [Stream index: 3] + * [Timestamps] + * [Time since first frame: 0.000000000 seconds] + * [Time since previous frame: 0.000000000 seconds] + * UDP payload (137 bytes) + * Data (137 bytes) + */ + + let bytes = [ + 0x27, 0x09, /* Source Port */ + 0x27, 0x09, /* Destination Port */ + 0x00, 0x91, /* Length */ + 0x57, 0xd3, /* Checksum */ + 0xff, /* Payload */ + ]; + + let expectation = UdpHeader { + source_port: 9993, + dest_port: 9993, + length: 145, + checksum: 0x57d3, + }; + + assert_eq!(UdpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = UdpHeader::decode(&bytes); + if let Ok((payload, header)) = result { + println!("return: {:?}, payload: {}", header, payload.len()); + } else { + println!("return: Incomplete data"); + } + } +} |
