async_snmp/message/
mod.rs1mod community;
11mod v3;
12
13pub use community::{CommunityMessage, CommunityPdu};
14pub(crate) use v3::{MpdFailure, classify_mpd_failure};
15pub use v3::{
16 MsgFlags, MsgGlobalData, ScopedPdu, SecurityLevel, SecurityModel, V3Message, V3MessageData,
17};
18
19use crate::ber::Decoder;
20use crate::error::internal::DecodeErrorKind;
21use crate::error::{Error, Result, UNKNOWN_TARGET};
22use crate::pdu::Pdu;
23use crate::version::Version;
24use bytes::Bytes;
25
26#[derive(Debug)]
31pub enum Message {
32 Community(CommunityMessage),
34 V3(V3Message),
36}
37
38impl Message {
39 pub fn pdu(&self) -> Option<&Pdu> {
43 match self {
44 Message::Community(m) => m.pdu.standard(),
45 Message::V3(m) => m.pdu(),
46 }
47 }
48
49 pub fn into_pdu(self) -> Option<Pdu> {
53 match self {
54 Message::Community(m) => match m.pdu {
55 CommunityPdu::Standard(p) => Some(p),
56 CommunityPdu::TrapV1(_) => None,
57 },
58 Message::V3(m) => m.into_pdu(),
59 }
60 }
61
62 pub fn version(&self) -> Version {
64 match self {
65 Message::Community(m) => m.version,
66 Message::V3(_) => Version::V3,
67 }
68 }
69
70 pub fn decode(data: Bytes) -> Result<Self> {
74 let mut decoder = Decoder::new(data);
75 let mut seq = decoder.read_sequence()?;
76
77 let version_num = seq.read_integer()?;
79 let version = Version::from_i32(version_num).ok_or_else(|| {
80 tracing::debug!(target: "async_snmp::message", { offset = seq.offset(), kind = %DecodeErrorKind::UnknownVersion(version_num) }, "decode error");
81 Error::MalformedResponse {
82 target: UNKNOWN_TARGET,
83 }
84 .boxed()
85 })?;
86
87 match version {
89 Version::V1 | Version::V2c => {
90 let msg = CommunityMessage::decode_from_sequence(&mut seq, version)?;
91 Ok(Message::Community(msg))
92 }
93 Version::V3 => {
94 let msg = V3Message::decode_from_sequence(&mut seq)?;
95 Ok(Message::V3(msg))
96 }
97 }
98 }
99}
100
101pub(crate) fn peek_version(data: Bytes, target: std::net::SocketAddr) -> Result<Version> {
105 let mut decoder = Decoder::with_target(data, target);
106 let mut seq = decoder.read_sequence()?;
107 let version_num = seq.read_integer()?;
108 Version::from_i32(version_num).ok_or_else(|| {
109 tracing::debug!(target: "async_snmp::message", { source = %target, kind = %DecodeErrorKind::UnknownVersion(version_num) }, "unknown SNMP version");
110 Error::MalformedResponse { target }.boxed()
111 })
112}
113
114impl From<CommunityMessage> for Message {
116 fn from(msg: CommunityMessage) -> Self {
117 Message::Community(msg)
118 }
119}
120
121impl From<V3Message> for Message {
122 fn from(msg: V3Message) -> Self {
123 Message::V3(msg)
124 }
125}