summaryrefslogtreecommitdiff
path: root/src/protocol
diff options
context:
space:
mode:
authorluwenpeng <[email protected]>2023-09-08 15:16:17 +0800
committerluwenpeng <[email protected]>2023-09-08 15:24:43 +0800
commit3c6fc844b5e15ae85e08f8bee18e54c30f33d988 (patch)
treea25d85e25a08b3f9b2309549400ea473dd6442c7 /src/protocol
parent16066bd3dc9f38e21cf8247b4b913c5bcc59d57e (diff)
[feature] Support ICMPv6 Decode
Diffstat (limited to 'src/protocol')
-rw-r--r--src/protocol/icmp.rs12
-rw-r--r--src/protocol/icmpv6.rs181
-rw-r--r--src/protocol/mod.rs3
-rw-r--r--src/protocol/vlan.rs4
4 files changed, 191 insertions, 9 deletions
diff --git a/src/protocol/icmp.rs b/src/protocol/icmp.rs
index c1352d5..314c3d7 100644
--- a/src/protocol/icmp.rs
+++ b/src/protocol/icmp.rs
@@ -32,7 +32,7 @@ pub struct IcmpHeader {
pub icmp_type: IcmpType,
pub icmp_code: u8,
pub icmp_checksum: u16,
- pub icmp_payload: Vec<u8>,
+ pub icmp_extended: Vec<u8>,
}
/******************************************************************************
@@ -69,7 +69,7 @@ impl Decode for IcmpHeader {
let (input, icmp_type) = number::streaming::be_u8(input)?;
let (input, icmp_code) = number::streaming::be_u8(input)?;
let (input, icmp_checksum) = number::streaming::be_u16(input)?;
- let (input, icmp_payload) = nom::bytes::streaming::take(4u8)(input)?;
+ let (input, icmp_extended) = nom::bytes::streaming::take(4u8)(input)?;
Ok((
input,
@@ -77,7 +77,7 @@ impl Decode for IcmpHeader {
icmp_type: icmp_type.into(),
icmp_code,
icmp_checksum,
- icmp_payload: icmp_payload.to_vec(),
+ icmp_extended: icmp_extended.to_vec(),
},
))
}
@@ -129,14 +129,14 @@ mod tests {
icmp_type: IcmpType::EchoRequest,
icmp_code: 0,
icmp_checksum: 0xab05,
- icmp_payload: vec![0x5f, 0x2b, 0x00, 0x01],
+ icmp_extended: vec![0x5f, 0x2b, 0x00, 0x01],
};
assert_eq!(IcmpHeader::decode(&bytes), Ok((LAST_SLICE, expectation)));
// example
- let vlan = IcmpHeader::decode(&bytes);
- if let Ok((payload, header)) = vlan {
+ let result = IcmpHeader::decode(&bytes);
+ if let Ok((payload, header)) = result {
println!("return: {:?}, payload: {}", header, payload.len());
} else {
println!("return: Incomplete data");
diff --git a/src/protocol/icmpv6.rs b/src/protocol/icmpv6.rs
new file mode 100644
index 0000000..837f2e6
--- /dev/null
+++ b/src/protocol/icmpv6.rs
@@ -0,0 +1,181 @@
+use crate::protocol::codec::Decode;
+use nom::number;
+use nom::IResult;
+
+/******************************************************************************
+ * Struct
+ ******************************************************************************/
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum Icmpv6Type {
+ DestinationUnreachable,
+ PacketTooBig,
+ TimeExceeded,
+ ParameterProblem,
+ EchoRequest,
+ EchoReply,
+ MulticastListenerQuery,
+ MulticastListenerReport,
+ MulticastListenerDone,
+ RouterSolicitation,
+ RouterAdvertisement,
+ NeighborSolicitation,
+ NeighborAdvertisement,
+ RedirectMessage,
+ RouterRenumbering,
+ NodeInformationQuery,
+ NodeInformationResponse,
+ InverseNeighborDiscoverySolicitation,
+ InverseNeighborDiscoveryAdvertisement,
+ Version2MulticastListenerReport,
+ HomeAgentAddressDiscoveryRequest,
+ HomeAgentAddressDiscoveryReply,
+ MobilePrefixSolicitation,
+ MobilePrefixAdvertisement,
+ CertificationPathSolicitation,
+ CertificationPathAdvertisement,
+ MulticastRouterAdvertisement,
+ MulticastRouterSolicitation,
+ MulticastRouterTermination,
+ Fmipv6Messages,
+ RplControlMessage,
+ Ilnpv6LocatorUpdateMessage,
+ DuplicateAddressRequest,
+ DuplicateAddressConfirmation,
+ MplControlMessage,
+ ExtendedEchoRequest,
+ ExtendedEchoReply,
+ Other(u8),
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct Icmpv6Header {
+ pub icmp_type: Icmpv6Type,
+ pub icmp_code: u8,
+ pub checksum: u16,
+}
+
+/******************************************************************************
+ * API
+ ******************************************************************************/
+
+impl From<u8> for Icmpv6Type {
+ fn from(raw: u8) -> Self {
+ match raw {
+ 1 => Icmpv6Type::DestinationUnreachable,
+ 2 => Icmpv6Type::PacketTooBig,
+ 3 => Icmpv6Type::TimeExceeded,
+ 4 => Icmpv6Type::ParameterProblem,
+ 128 => Icmpv6Type::EchoRequest,
+ 129 => Icmpv6Type::EchoReply,
+ 130 => Icmpv6Type::MulticastListenerQuery,
+ 131 => Icmpv6Type::MulticastListenerReport,
+ 132 => Icmpv6Type::MulticastListenerDone,
+ 133 => Icmpv6Type::RouterSolicitation,
+ 134 => Icmpv6Type::RouterAdvertisement,
+ 135 => Icmpv6Type::NeighborSolicitation,
+ 136 => Icmpv6Type::NeighborAdvertisement,
+ 137 => Icmpv6Type::RedirectMessage,
+ 138 => Icmpv6Type::RouterRenumbering,
+ 139 => Icmpv6Type::NodeInformationQuery,
+ 140 => Icmpv6Type::NodeInformationResponse,
+ 141 => Icmpv6Type::InverseNeighborDiscoverySolicitation,
+ 142 => Icmpv6Type::InverseNeighborDiscoveryAdvertisement,
+ 143 => Icmpv6Type::Version2MulticastListenerReport,
+ 144 => Icmpv6Type::HomeAgentAddressDiscoveryRequest,
+ 145 => Icmpv6Type::HomeAgentAddressDiscoveryReply,
+ 146 => Icmpv6Type::MobilePrefixSolicitation,
+ 147 => Icmpv6Type::MobilePrefixAdvertisement,
+ 148 => Icmpv6Type::CertificationPathSolicitation,
+ 149 => Icmpv6Type::CertificationPathAdvertisement,
+ 151 => Icmpv6Type::MulticastRouterAdvertisement,
+ 152 => Icmpv6Type::MulticastRouterSolicitation,
+ 153 => Icmpv6Type::MulticastRouterTermination,
+ 154 => Icmpv6Type::Fmipv6Messages,
+ 155 => Icmpv6Type::RplControlMessage,
+ 156 => Icmpv6Type::Ilnpv6LocatorUpdateMessage,
+ 157 => Icmpv6Type::DuplicateAddressRequest,
+ 158 => Icmpv6Type::DuplicateAddressConfirmation,
+ 159 => Icmpv6Type::MplControlMessage,
+ 160 => Icmpv6Type::ExtendedEchoRequest,
+ 161 => Icmpv6Type::ExtendedEchoReply,
+ other => Icmpv6Type::Other(other),
+ }
+ }
+}
+
+impl Decode for Icmpv6Header {
+ type Iterm = Icmpv6Header;
+ fn decode(input: &[u8]) -> IResult<&[u8], Icmpv6Header> {
+ let (input, icmp_type) = number::streaming::be_u8(input)?;
+ let (input, icmp_code) = number::streaming::be_u8(input)?;
+ let (input, checksum) = number::streaming::be_u16(input)?;
+ Ok((
+ input,
+ Icmpv6Header {
+ icmp_type: Icmpv6Type::from(icmp_type),
+ icmp_code,
+ checksum,
+ },
+ ))
+ }
+}
+
+/******************************************************************************
+ * TEST
+ ******************************************************************************/
+
+#[cfg(test)]
+mod tests {
+ use super::Icmpv6Header;
+ use super::Icmpv6Type;
+ use crate::protocol::codec::Decode;
+ const LAST_SLICE: &'static [u8] = &[
+ 0x11, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
+ 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
+ ];
+
+ #[test]
+ fn icmpv6_header_decode() {
+ /*
+ * Internet Control Message Protocol v6
+ * Type: Echo (ping) request (128)
+ * Code: 0
+ * Checksum: 0x863c [correct]
+ * [Checksum Status: Good]
+ * Identifier: 0x110d
+ * Sequence: 0
+ * [Response In: 2]
+ * Data (52 bytes)
+ * Data: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223…
+ * [Length: 52]
+ */
+ let bytes = [
+ 0x80, 0x00, 0x86, 0x3c, 0x11, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21,
+ 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33,
+ ];
+
+ let expectation = Icmpv6Header {
+ icmp_type: Icmpv6Type::EchoRequest,
+ icmp_code: 0,
+ checksum: 0x863c,
+ };
+
+ assert_eq!(Icmpv6Header::decode(&bytes), Ok((LAST_SLICE, expectation)));
+
+ // example
+ let result = Icmpv6Header::decode(&bytes);
+ if let Ok((payload, header)) = result {
+ println!("return: {:?}, payload: {}", header, payload.len());
+ } else {
+ println!("return: Incomplete data");
+ }
+
+ // assert_eq!(1, 0);
+ }
+}
diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs
index ba06b66..c82e203 100644
--- a/src/protocol/mod.rs
+++ b/src/protocol/mod.rs
@@ -8,4 +8,5 @@ pub mod tcp;
pub mod dns;
pub mod http;
pub mod vlan;
-pub mod icmp; \ No newline at end of file
+pub mod icmp;
+pub mod icmpv6; \ No newline at end of file
diff --git a/src/protocol/vlan.rs b/src/protocol/vlan.rs
index a6b7202..7f64780 100644
--- a/src/protocol/vlan.rs
+++ b/src/protocol/vlan.rs
@@ -83,8 +83,8 @@ mod tests {
assert_eq!(VlanHeader::decode(&bytes), Ok((LAST_SLICE, expectation)));
// example
- let vlan = VlanHeader::decode(&bytes);
- if let Ok((payload, header)) = vlan {
+ let result = VlanHeader::decode(&bytes);
+ if let Ok((payload, header)) = result {
println!("return: {:?}, payload: {}", header, payload.len());
} else {
println!("return: Incomplete data");