1use rasn::prelude::*;
3
4pub use smi::v2::{IpAddress, ObjectName, ObjectSyntax, TimeTicks};
5
6#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
7#[rasn(choice)]
8pub enum Pdus {
9 GetRequest(GetRequest),
10 GetNextRequest(GetNextRequest),
11 Response(Response),
12 SetRequest(SetRequest),
13 GetBulkRequest(GetBulkRequest),
14 InformRequest(InformRequest),
15 Trap(Trap),
16 Report(Report),
17}
18
19#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
20#[rasn(tag(0))]
21#[rasn(delegate)]
22pub struct GetRequest(pub Pdu);
23
24#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
25#[rasn(tag(1))]
26#[rasn(delegate)]
27pub struct GetNextRequest(pub Pdu);
28
29#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
30#[rasn(tag(2))]
31#[rasn(delegate)]
32pub struct Response(pub Pdu);
33
34#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
35#[rasn(tag(3))]
36#[rasn(delegate)]
37pub struct SetRequest(pub Pdu);
38
39#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
40#[rasn(tag(5))]
41#[rasn(delegate)]
42pub struct GetBulkRequest(pub BulkPdu);
43
44#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
45#[rasn(tag(6))]
46#[rasn(delegate)]
47pub struct InformRequest(pub Pdu);
48
49#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
50#[rasn(tag(7))]
51#[rasn(delegate)]
52pub struct Trap(pub Pdu);
53
54#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
55#[rasn(tag(8))]
56#[rasn(delegate)]
57pub struct Report(pub Pdu);
58
59#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
60pub struct Pdu {
61 pub request_id: i32,
62 pub error_status: u32,
63 pub error_index: u32,
64 pub variable_bindings: VarBindList,
65}
66
67impl Pdu {
68 pub const ERROR_STATUS_NO_ERROR: u32 = 0;
69 pub const ERROR_STATUS_TOO_BIG: u32 = 1;
70 pub const ERROR_STATUS_NO_SUCH_NAME: u32 = 2;
71 pub const ERROR_STATUS_BAD_VALUE: u32 = 3;
72 pub const ERROR_STATUS_READ_ONLY: u32 = 4;
73 pub const ERROR_STATUS_GEN_ERR: u32 = 5;
74 pub const ERROR_STATUS_NO_ACCESS: u32 = 6;
75 pub const ERROR_STATUS_WRONG_TYPE: u32 = 7;
76 pub const ERROR_STATUS_WRONG_LENGTH: u32 = 8;
77 pub const ERROR_STATUS_WRONG_ENCODING: u32 = 9;
78 pub const ERROR_STATUS_WRONG_VALUE: u32 = 10;
79 pub const ERROR_STATUS_NO_CREATION: u32 = 11;
80 pub const ERROR_STATUS_INCONSISTENT_VALUE: u32 = 12;
81 pub const ERROR_STATUS_RESOURCE_UNAVAILABLE: u32 = 13;
82 pub const ERROR_STATUS_COMMIT_FAILED: u32 = 14;
83 pub const ERROR_STATUS_UNDO_FAILED: u32 = 15;
84 pub const ERROR_STATUS_AUTHORIZATION_ERROR: u32 = 16;
85 pub const ERROR_STATUS_NOT_WRITABLE: u32 = 17;
86 pub const ERROR_STATUS_INCONSISTENT_NAME: u32 = 18;
87}
88
89#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
90pub struct BulkPdu {
91 pub request_id: i32,
92 pub non_repeaters: u32,
93 pub max_repetitions: u32,
94 pub variable_bindings: VarBindList,
95}
96
97pub type VarBindList = alloc::vec::Vec<VarBind>;
98
99#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
100pub struct VarBind {
101 pub name: ObjectName,
102 pub value: VarBindValue,
103}
104
105#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
106#[rasn(choice)]
107pub enum VarBindValue {
108 Value(ObjectSyntax),
109 Unspecified,
110 #[rasn(tag(0))]
111 NoSuchObject,
112 #[rasn(tag(1))]
113 NoSuchInstance,
114 #[rasn(tag(2))]
115 EndOfMibView,
116}
117
118#[cfg(test)]
119mod tests {
120 use pretty_assertions::assert_eq;
121
122 use super::*;
123 use alloc::vec;
124 use rasn::types::ObjectIdentifier;
125 use smi::v2::SimpleSyntax;
126
127 #[test]
128 fn encode_decode_response() {
129 let request = crate::v2c::Message {
130 version: 1.into(),
131 community: "public".as_bytes().into(),
132 data: Response(Pdu {
133 request_id: 1414684022,
134 error_status: Pdu::ERROR_STATUS_NO_ERROR,
135 error_index: 0,
136 variable_bindings: vec![
137 VarBind {
138 name: ObjectIdentifier::new_unchecked(
139 vec![1, 3, 6, 1, 2, 1, 2, 2, 1, 1, 12].into(),
140 ),
141 value: VarBindValue::NoSuchInstance,
142 },
143 VarBind {
144 name: ObjectIdentifier::new_unchecked(
145 vec![1, 3, 6, 1, 2, 1, 2, 2, 1, 1, 13].into(),
146 ),
147 value: VarBindValue::Value(ObjectSyntax::Simple(SimpleSyntax::Integer(
148 6.into(),
149 ))),
150 },
151 ],
152 }),
153 };
154
155 #[rustfmt::skip]
156 let expected_data: &[u8] = &[
157 0x30, 0x3C,
179
180 0x02, 0x01,
182
183 0x01, 0x04,
185
186 0x06, 0x70, 0x75, 0x62, 0x6C, 0x69, 0x63,
188
189 0xA2, 0x2F,
191
192 0x02, 0x04, 0x54, 0x52, 0x5D, 0x76,
194
195 0x02, 0x01, 0x00,
197
198 0x02, 0x01, 0x00,
200
201 0x30, 0x21,
203
204 0x30, 0x0E,
206 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x0C,
208
209 0x81, 0x00,
211
212 0x30, 0x0F,
214 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x0D,
216
217 0x02, 0x01, 0x06,
219 ];
220
221 let encoded_data = rasn::ber::encode(&request).unwrap();
223 assert_eq!(encoded_data, expected_data);
224
225 let decoded_request = rasn::ber::decode(&encoded_data);
227
228 assert!(decoded_request.is_ok());
229 assert_eq!(request, decoded_request.unwrap());
230 }
231
232 #[test]
233 fn get_bulk_request() {
234 let request = GetBulkRequest(BulkPdu {
235 request_id: 1414684022,
236 non_repeaters: 1,
237 max_repetitions: 2,
238 variable_bindings: vec![
239 VarBind {
240 name: ObjectIdentifier::new_unchecked(vec![1, 3, 6, 1, 2, 1, 1, 3].into()),
241 value: VarBindValue::Unspecified,
242 },
243 VarBind {
244 name: ObjectIdentifier::new_unchecked(
245 vec![1, 3, 6, 1, 2, 1, 4, 0x16, 1, 2].into(),
246 ),
247 value: VarBindValue::Unspecified,
248 },
249 VarBind {
250 name: ObjectIdentifier::new_unchecked(
251 vec![1, 3, 6, 1, 2, 1, 4, 0x16, 1, 4].into(),
252 ),
253 value: VarBindValue::Unspecified,
254 },
255 ],
256 });
257
258 let data = rasn::ber::encode(&request).unwrap();
259
260 rasn::ber::decode::<GetBulkRequest>(&data).unwrap();
261 assert_eq!(
262 data,
263 vec![
264 0xA5, 0x39, 0x02, 0x04, 0x54, 0x52, 0x5d, 0x76, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x30, 0x2b, 0x30, 0x0b, 0x06, 0x07, 0x2b, 0x06, 0x01, 0x02, 0x01, 0x01, 0x03, 0x05, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x02, 0x01, 0x04, 0x16, 0x01, 0x02, 0x05, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x02, 0x01, 0x04, 0x16, 0x01, 0x04, 0x05, 0x00,
279 ]
280 );
281 }
282}