@@ -5,13 +5,70 @@ use asn1_rs::{Any, FromBer, Tag};
55use nom:: combinator:: map_res;
66use nom:: { Err , IResult } ;
77
8+ /// An SNMP messsage parser, accepting v1, v2c or v3 messages
9+ ///
10+ /// # Examples
11+ ///
12+ /// ```rust
13+ /// use snmp_parser::{ScopedPduData, SecurityModel, SnmpGenericMessage};
14+ /// use snmp_parser::asn1_rs::FromBer;
15+ ///
16+ /// static SNMPV3_REQ: &[u8] = include_bytes!("../assets/snmpv3_req.bin");
17+ ///
18+ /// match SnmpGenericMessage::from_ber(&SNMPV3_REQ) {
19+ /// Ok((_, msg)) => {
20+ /// match msg {
21+ /// SnmpGenericMessage::V1(_) => todo!(),
22+ /// SnmpGenericMessage::V2(_) => todo!(),
23+ /// SnmpGenericMessage::V3(msgv3) => {
24+ /// assert!(msgv3.version == 3);
25+ /// assert!(msgv3.header_data.msg_security_model == SecurityModel::USM);
26+ /// match msgv3.data {
27+ /// ScopedPduData::Plaintext(_pdu) => { },
28+ /// ScopedPduData::Encrypted(_) => (),
29+ /// }
30+ /// }
31+ /// }
32+ /// },
33+ /// Err(e) => panic!("{}", e),
34+ /// }
35+ /// ```
836#[ derive( Debug , PartialEq ) ]
937pub enum SnmpGenericMessage < ' a > {
38+ /// SNMP Version 1 (SNMPv1) message
1039 V1 ( SnmpMessage < ' a > ) ,
40+ /// SNMP Version 2c (SNMPv2c) message
1141 V2 ( SnmpMessage < ' a > ) ,
42+ /// SNMP Version 3 (SNMPv3) message
1243 V3 ( SnmpV3Message < ' a > ) ,
1344}
1445
46+ impl < ' 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+
1572fn parse_snmp_v1_pdu_content ( i : & [ u8 ] ) -> IResult < & [ u8 ] , SnmpMessage , SnmpError > {
1673 let ( i, community) = parse_ber_octetstring_as_str ( i) . map_err ( Err :: convert) ?;
1774 let ( i, pdu) = parse_snmp_v1_pdu ( i) ?;
@@ -47,26 +104,9 @@ fn parse_snmp_v3_pdu_content(i: &[u8]) -> IResult<&[u8], SnmpV3Message, SnmpErro
47104 Ok ( ( i, msg) )
48105}
49106
107+ /// Parse an SNMP messsage, accepting v1, v2c or v3 messages
108+ ///
109+ /// This function is equivalent to `SnmpGenericMessage::from_ber`
50110pub fn parse_snmp_generic_message ( i : & [ u8 ] ) -> IResult < & [ u8 ] , SnmpGenericMessage , SnmpError > {
51- let ( rem, any) = Any :: from_ber ( i) . or ( Err ( Err :: Error ( SnmpError :: InvalidMessage ) ) ) ?;
52- if any. tag ( ) != Tag :: Sequence {
53- return Err ( Err :: Error ( SnmpError :: InvalidMessage ) ) ;
54- }
55- let ( r, version) = u32:: from_ber ( any. data ) . map_err ( Err :: convert) ?;
56- let ( _, msg) = match version {
57- 0 => {
58- let ( rem, msg) = parse_snmp_v1_pdu_content ( r) ?;
59- ( rem, SnmpGenericMessage :: V1 ( msg) )
60- }
61- 1 => {
62- let ( rem, msg) = parse_snmp_v2c_pdu_content ( r) ?;
63- ( rem, SnmpGenericMessage :: V2 ( msg) )
64- }
65- 3 => {
66- let ( rem, msg) = parse_snmp_v3_pdu_content ( r) ?;
67- ( rem, SnmpGenericMessage :: V3 ( msg) )
68- }
69- _ => return Err ( Err :: Error ( SnmpError :: InvalidVersion ) ) ,
70- } ;
71- Ok ( ( rem, msg) )
111+ SnmpGenericMessage :: from_ber ( i)
72112}
0 commit comments