1use std::net::SocketAddr;
6
7use super::length::decode_length;
8use super::tag;
9use crate::error::internal::DecodeErrorKind;
10use crate::error::{Error, Result, UNKNOWN_TARGET};
11use crate::oid::Oid;
12use bytes::Bytes;
13
14pub struct Decoder {
16 data: Bytes,
17 offset: usize,
18 target: Option<SocketAddr>,
19}
20
21impl Decoder {
22 pub fn new(data: Bytes) -> Self {
24 Self {
25 data,
26 offset: 0,
27 target: None,
28 }
29 }
30
31 pub fn with_target(data: Bytes, target: SocketAddr) -> Self {
33 Self {
34 data,
35 offset: 0,
36 target: Some(target),
37 }
38 }
39
40 pub fn from_slice(data: &[u8]) -> Self {
42 Self::new(Bytes::copy_from_slice(data))
43 }
44
45 fn target(&self) -> SocketAddr {
47 self.target.unwrap_or(UNKNOWN_TARGET)
48 }
49
50 pub fn offset(&self) -> usize {
52 self.offset
53 }
54
55 pub fn remaining(&self) -> usize {
57 self.data.len() - self.offset
58 }
59
60 pub fn is_empty(&self) -> bool {
62 self.offset >= self.data.len()
63 }
64
65 pub fn peek_byte(&self) -> Option<u8> {
67 if self.offset < self.data.len() {
68 Some(self.data[self.offset])
69 } else {
70 None
71 }
72 }
73
74 pub fn peek_tag(&self) -> Option<u8> {
76 self.peek_byte()
77 }
78
79 pub fn read_byte(&mut self) -> Result<u8> {
81 if self.offset >= self.data.len() {
82 tracing::debug!(target: "async_snmp::ber", { snmp.offset = %self.offset, kind = %DecodeErrorKind::TruncatedData }, "truncated data: unexpected end of input");
83 return Err(Error::MalformedResponse {
84 target: self.target(),
85 }
86 .boxed());
87 }
88 let byte = self.data[self.offset];
89 self.offset += 1;
90 Ok(byte)
91 }
92
93 pub fn read_tag(&mut self) -> Result<u8> {
95 self.read_byte()
96 }
97
98 pub fn read_length(&mut self) -> Result<usize> {
100 let (len, consumed) = decode_length(&self.data[self.offset..], self.offset, self.target)?;
101 self.offset += consumed;
102 Ok(len)
103 }
104
105 pub fn read_bytes(&mut self, len: usize) -> Result<Bytes> {
107 if self.offset.saturating_add(len) > self.data.len() {
109 tracing::debug!(target: "async_snmp::ber", { snmp.offset = %self.offset, kind = %DecodeErrorKind::InsufficientData { needed: len, available: self.remaining() } }, "insufficient data");
110 return Err(Error::MalformedResponse {
111 target: self.target(),
112 }
113 .boxed());
114 }
115 let bytes = self.data.slice(self.offset..self.offset + len);
116 self.offset += len;
117 Ok(bytes)
118 }
119
120 pub fn expect_tag(&mut self, expected: u8) -> Result<usize> {
122 let tag = self.read_tag()?;
123 if tag != expected {
124 tracing::debug!(target: "async_snmp::ber", { snmp.offset = %self.offset - 1, kind = %DecodeErrorKind::UnexpectedTag { expected, actual: tag } }, "unexpected tag");
125 return Err(Error::MalformedResponse {
126 target: self.target(),
127 }
128 .boxed());
129 }
130 self.read_length()
131 }
132
133 pub fn read_integer(&mut self) -> Result<i32> {
135 let len = self.expect_tag(tag::universal::INTEGER)?;
136 self.read_integer_value(len)
137 }
138
139 pub fn read_integer_value(&mut self, len: usize) -> Result<i32> {
141 if len == 0 {
142 tracing::debug!(target: "async_snmp::ber", { snmp.offset = %self.offset, kind = %DecodeErrorKind::ZeroLengthInteger }, "zero-length integer");
143 return Err(Error::MalformedResponse {
144 target: self.target(),
145 }
146 .boxed());
147 }
148 if len > 4 {
149 tracing::warn!(target: "async_snmp::ber", { snmp.offset = %self.offset, length = len }, "integer too long, truncating to 4 bytes");
151 }
152
153 let bytes = self.read_bytes(len)?;
154
155 let is_negative = bytes[0] & 0x80 != 0;
157 let mut value: i32 = if is_negative { -1 } else { 0 };
158
159 for &byte in bytes.iter().take(4) {
160 value = (value << 8) | (byte as i32);
161 }
162
163 Ok(value)
164 }
165
166 pub fn read_integer64(&mut self, expected_tag: u8) -> Result<u64> {
168 let len = self.expect_tag(expected_tag)?;
169 self.read_integer64_value(len)
170 }
171
172 pub fn read_integer64_value(&mut self, len: usize) -> Result<u64> {
174 if len == 0 {
175 tracing::debug!(target: "async_snmp::ber", { snmp.offset = %self.offset, kind = %DecodeErrorKind::ZeroLengthInteger }, "zero-length integer");
176 return Err(Error::MalformedResponse {
177 target: self.target(),
178 }
179 .boxed());
180 }
181 if len > 9 {
182 tracing::debug!(target: "async_snmp::ber", { snmp.offset = %self.offset, kind = %DecodeErrorKind::Integer64TooLong { length: len } }, "integer64 too long");
184 return Err(Error::MalformedResponse {
185 target: self.target(),
186 }
187 .boxed());
188 }
189
190 let bytes = self.read_bytes(len)?;
191 let mut value: u64 = 0;
192
193 for &byte in bytes.iter() {
194 value = (value << 8) | (byte as u64);
195 }
196
197 Ok(value)
198 }
199
200 pub fn read_unsigned32(&mut self, expected_tag: u8) -> Result<u32> {
202 let len = self.expect_tag(expected_tag)?;
203 self.read_unsigned32_value(len)
204 }
205
206 pub fn read_unsigned32_value(&mut self, len: usize) -> Result<u32> {
208 if len == 0 {
209 tracing::debug!(target: "async_snmp::ber", { snmp.offset = %self.offset, kind = %DecodeErrorKind::ZeroLengthInteger }, "zero-length integer");
210 return Err(Error::MalformedResponse {
211 target: self.target(),
212 }
213 .boxed());
214 }
215 if len > 5 {
216 tracing::warn!(target: "async_snmp::ber", { snmp.offset = %self.offset, length = len }, "unsigned integer too long, truncating to 4 bytes");
218 }
219
220 let bytes = self.read_bytes(len)?;
221 let mut value: u32 = 0;
222
223 for &byte in bytes.iter().take(5) {
224 value = (value << 8) | (byte as u32);
225 }
226
227 Ok(value)
228 }
229
230 pub fn read_octet_string(&mut self) -> Result<Bytes> {
232 let len = self.expect_tag(tag::universal::OCTET_STRING)?;
233 self.read_bytes(len)
234 }
235
236 pub fn read_null(&mut self) -> Result<()> {
238 let len = self.expect_tag(tag::universal::NULL)?;
239 if len != 0 {
240 tracing::debug!(target: "async_snmp::ber", { snmp.offset = %self.offset, kind = %DecodeErrorKind::InvalidNull }, "NULL with non-zero length");
241 return Err(Error::MalformedResponse {
242 target: self.target(),
243 }
244 .boxed());
245 }
246 Ok(())
247 }
248
249 pub fn read_oid(&mut self) -> Result<Oid> {
251 let len = self.expect_tag(tag::universal::OBJECT_IDENTIFIER)?;
252 let bytes = self.read_bytes(len)?;
253 Oid::from_ber(&bytes)
254 }
255
256 pub fn read_oid_value(&mut self, len: usize) -> Result<Oid> {
258 let bytes = self.read_bytes(len)?;
259 Oid::from_ber(&bytes)
260 }
261
262 pub fn read_sequence(&mut self) -> Result<Decoder> {
264 let len = self.expect_tag(tag::universal::SEQUENCE)?;
265 let content = self.read_bytes(len)?;
266 Ok(Decoder {
267 data: content,
268 offset: 0,
269 target: self.target,
270 })
271 }
272
273 pub fn read_constructed(&mut self, expected_tag: u8) -> Result<Decoder> {
275 let len = self.expect_tag(expected_tag)?;
276 let content = self.read_bytes(len)?;
277 Ok(Decoder {
278 data: content,
279 offset: 0,
280 target: self.target,
281 })
282 }
283
284 pub fn read_ip_address(&mut self) -> Result<[u8; 4]> {
286 let len = self.expect_tag(tag::application::IP_ADDRESS)?;
287 if len != 4 {
288 tracing::debug!(target: "async_snmp::ber", { snmp.offset = %self.offset, kind = %DecodeErrorKind::InvalidIpAddressLength { length: len } }, "IP address must be 4 bytes");
289 return Err(Error::MalformedResponse {
290 target: self.target(),
291 }
292 .boxed());
293 }
294 let bytes = self.read_bytes(4)?;
295 Ok([bytes[0], bytes[1], bytes[2], bytes[3]])
296 }
297
298 pub fn skip_tlv(&mut self) -> Result<()> {
300 let _tag = self.read_tag()?;
301 let len = self.read_length()?;
302 let new_offset = self.offset.saturating_add(len);
304 if new_offset > self.data.len() {
305 tracing::debug!(target: "async_snmp::ber", { snmp.offset = %self.offset, kind = %DecodeErrorKind::TlvOverflow }, "TLV extends past end of data");
306 return Err(Error::MalformedResponse {
307 target: self.target(),
308 }
309 .boxed());
310 }
311 self.offset = new_offset;
312 Ok(())
313 }
314
315 pub fn sub_decoder(&mut self, len: usize) -> Result<Decoder> {
317 let content = self.read_bytes(len)?;
318 Ok(Decoder {
319 data: content,
320 offset: 0,
321 target: self.target,
322 })
323 }
324
325 pub fn as_bytes(&self) -> &Bytes {
327 &self.data
328 }
329
330 pub fn remaining_slice(&self) -> &[u8] {
332 &self.data[self.offset..]
333 }
334}
335
336#[cfg(test)]
337mod tests {
338 use super::*;
339
340 #[test]
341 fn test_decode_integer() {
342 let mut dec = Decoder::from_slice(&[0x02, 0x01, 0x00]);
343 assert_eq!(dec.read_integer().unwrap(), 0);
344
345 let mut dec = Decoder::from_slice(&[0x02, 0x01, 0x7F]);
346 assert_eq!(dec.read_integer().unwrap(), 127);
347
348 let mut dec = Decoder::from_slice(&[0x02, 0x02, 0x00, 0x80]);
349 assert_eq!(dec.read_integer().unwrap(), 128);
350
351 let mut dec = Decoder::from_slice(&[0x02, 0x01, 0xFF]);
352 assert_eq!(dec.read_integer().unwrap(), -1);
353
354 let mut dec = Decoder::from_slice(&[0x02, 0x01, 0x80]);
355 assert_eq!(dec.read_integer().unwrap(), -128);
356 }
357
358 #[test]
359 fn test_decode_null() {
360 let mut dec = Decoder::from_slice(&[0x05, 0x00]);
361 dec.read_null().unwrap();
362 }
363
364 #[test]
365 fn test_decode_octet_string() {
366 let mut dec = Decoder::from_slice(&[0x04, 0x05, b'h', b'e', b'l', b'l', b'o']);
367 let s = dec.read_octet_string().unwrap();
368 assert_eq!(&s[..], b"hello");
369 }
370
371 #[test]
372 fn test_decode_oid() {
373 let mut dec = Decoder::from_slice(&[0x06, 0x03, 0x2B, 0x06, 0x01]);
375 let oid = dec.read_oid().unwrap();
376 assert_eq!(oid.arcs(), &[1, 3, 6, 1]);
377 }
378
379 #[test]
380 fn test_decode_sequence() {
381 let mut dec = Decoder::from_slice(&[0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02]);
383 let mut seq = dec.read_sequence().unwrap();
384 assert_eq!(seq.read_integer().unwrap(), 1);
385 assert_eq!(seq.read_integer().unwrap(), 2);
386 }
387
388 #[test]
389 fn test_accept_non_minimal_integer() {
390 let mut dec = Decoder::from_slice(&[0x02, 0x02, 0x00, 0x01]);
392 assert_eq!(dec.read_integer().unwrap(), 1);
393
394 let mut dec = Decoder::from_slice(&[0x02, 0x02, 0x00, 0x7F]);
396 assert_eq!(dec.read_integer().unwrap(), 127);
397
398 let mut dec = Decoder::from_slice(&[0x02, 0x03, 0x00, 0x00, 0x80]);
400 assert_eq!(dec.read_integer().unwrap(), 128);
401
402 let mut dec = Decoder::from_slice(&[0x02, 0x02, 0xFF, 0xFF]);
404 assert_eq!(dec.read_integer().unwrap(), -1);
405 }
406
407 #[test]
408 fn test_integer_overflow_truncation() {
409 let mut dec = Decoder::from_slice(&[0x02, 0x05, 0x01, 0x02, 0x03, 0x04, 0x05]);
412 let result = dec.read_integer();
413 assert!(result.is_ok());
415 assert_eq!(result.unwrap(), 0x01020304);
417
418 let mut dec = Decoder::from_slice(&[0x02, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06]);
420 let result = dec.read_integer();
421 assert!(result.is_ok());
422 assert_eq!(result.unwrap(), 0x01020304);
423 }
424
425 #[test]
426 fn test_read_bytes_rejects_oversized_length() {
427 let mut dec = Decoder::from_slice(&[0x01, 0x02, 0x03]);
429 let result = dec.read_bytes(100);
431 assert!(result.is_err());
432 let err = result.unwrap_err();
433 assert!(
434 matches!(*err, crate::error::Error::MalformedResponse { .. }),
435 "expected MalformedResponse error, got {:?}",
436 err
437 );
438 }
439
440 #[test]
441 fn test_skip_tlv_rejects_oversized_length() {
442 let mut dec = Decoder::from_slice(&[0x04, 0x82, 0x01, 0x00, 0xAA, 0xBB, 0xCC]);
445 let result = dec.skip_tlv();
446 assert!(result.is_err());
447 let err = result.unwrap_err();
448 assert!(
449 matches!(*err, crate::error::Error::MalformedResponse { .. }),
450 "expected MalformedResponse error, got {:?}",
451 err
452 );
453 }
454}