1use crate::error::SnmpError;
2use crate::snmp::*;
3use crate::snmpv3::*;
4use asn1_rs::{Any, FromBer, Tag};
5use nom::combinator::map_res;
6use nom::{Err, IResult};
7
8#[derive(Debug, PartialEq)]
37pub enum SnmpGenericMessage<'a> {
38 V1(SnmpMessage<'a>),
40 V2(SnmpMessage<'a>),
42 V3(SnmpV3Message<'a>),
44}
45
46impl<'a> FromBer<'a, SnmpError> for SnmpGenericMessage<'a> {
47 fn from_ber(bytes: &'a [u8]) -> asn1_rs::ParseResult<'a, Self, SnmpError> {
48 let (rem, any) = Any::from_ber(bytes).or(Err(Err::Error(SnmpError::InvalidMessage)))?;
49 if any.tag() != Tag::Sequence {
50 return Err(Err::Error(SnmpError::InvalidMessage));
51 }
52 let (r, version) = u32::from_ber(any.data).map_err(Err::convert)?;
53 let (_, msg) = match version {
54 0 => {
55 let (rem, msg) = parse_snmp_v1_pdu_content(r)?;
56 (rem, SnmpGenericMessage::V1(msg))
57 }
58 1 => {
59 let (rem, msg) = parse_snmp_v2c_pdu_content(r)?;
60 (rem, SnmpGenericMessage::V2(msg))
61 }
62 3 => {
63 let (rem, msg) = parse_snmp_v3_pdu_content(r)?;
64 (rem, SnmpGenericMessage::V3(msg))
65 }
66 _ => return Err(Err::Error(SnmpError::InvalidVersion)),
67 };
68 Ok((rem, msg))
69 }
70}
71
72fn parse_snmp_v1_pdu_content(i: &[u8]) -> IResult<&[u8], SnmpMessage, SnmpError> {
73 let (i, community) = parse_ber_octetstring_as_str(i).map_err(Err::convert)?;
74 let (i, pdu) = parse_snmp_v1_pdu(i)?;
75 let msg = SnmpMessage {
76 version: 0,
77 community: community.to_string(),
78 pdu,
79 };
80 Ok((i, msg))
81}
82
83fn parse_snmp_v2c_pdu_content(i: &[u8]) -> IResult<&[u8], SnmpMessage, SnmpError> {
84 let (i, community) = parse_ber_octetstring_as_str(i).map_err(Err::convert)?;
85 let (i, pdu) = parse_snmp_v2c_pdu(i)?;
86 let msg = SnmpMessage {
87 version: 1,
88 community: community.to_string(),
89 pdu,
90 };
91 Ok((i, msg))
92}
93
94fn parse_snmp_v3_pdu_content(i: &[u8]) -> IResult<&[u8], SnmpV3Message, SnmpError> {
95 let (i, hdr) = parse_snmp_v3_headerdata(i)?;
96 let (i, secp) = map_res(<&[u8]>::from_ber, |x| parse_secp(x, &hdr))(i).map_err(Err::convert)?;
97 let (i, data) = parse_snmp_v3_data(i, &hdr)?;
98 let msg = SnmpV3Message {
99 version: 3,
100 header_data: hdr,
101 security_params: secp,
102 data,
103 };
104 Ok((i, msg))
105}
106
107pub fn parse_snmp_generic_message(i: &[u8]) -> IResult<&[u8], SnmpGenericMessage, SnmpError> {
111 SnmpGenericMessage::from_ber(i)
112}