async_snmp/handler/
context.rs

1//! Request context for MIB handlers.
2//!
3//! This module provides [`RequestContext`], which contains information about
4//! incoming SNMP requests for use in handler authorization decisions.
5
6use std::net::SocketAddr;
7
8use bytes::Bytes;
9
10use crate::message::SecurityLevel;
11use crate::pdu::PduType;
12use crate::version::Version;
13
14use super::SecurityModel;
15
16/// Request context passed to MIB handlers.
17///
18/// Contains information about the incoming request for authorization decisions,
19/// including VACM-resolved access control information when VACM is enabled.
20///
21/// # Fields
22///
23/// The context provides:
24/// - **Request origin**: Source address and request ID
25/// - **Security info**: Version, model, level, and security name (community/username)
26/// - **VACM info**: Group name and view names (when VACM is configured)
27///
28/// # Example
29///
30/// ```rust
31/// use async_snmp::handler::{MibHandler, RequestContext, GetResult, BoxFuture};
32/// use async_snmp::{Oid, Value, oid};
33///
34/// struct LoggingHandler;
35///
36/// impl MibHandler for LoggingHandler {
37///     fn get<'a>(&'a self, ctx: &'a RequestContext, oid: &'a Oid) -> BoxFuture<'a, GetResult> {
38///         Box::pin(async move {
39///             // Log request details
40///             println!(
41///                 "GET {} from {} (user: {:?}, version: {:?})",
42///                 oid, ctx.source, ctx.security_name, ctx.version
43///             );
44///
45///             if oid == &oid!(1, 3, 6, 1, 4, 1, 99999, 1, 0) {
46///                 GetResult::Value(Value::Integer(42))
47///             } else {
48///                 GetResult::NoSuchObject
49///             }
50///         })
51///     }
52///
53///     fn get_next<'a>(
54///         &'a self,
55///         _ctx: &'a RequestContext,
56///         _oid: &'a Oid,
57///     ) -> BoxFuture<'a, async_snmp::handler::GetNextResult> {
58///         Box::pin(async { async_snmp::handler::GetNextResult::EndOfMibView })
59///     }
60/// }
61/// ```
62#[derive(Debug, Clone)]
63pub struct RequestContext {
64    /// Source address of the request.
65    ///
66    /// Use this for logging or additional access control beyond VACM.
67    pub source: SocketAddr,
68
69    /// SNMP version (V1, V2c, or V3).
70    pub version: Version,
71
72    /// Security model used for this request.
73    ///
74    /// - `V1` for SNMPv1 community-based
75    /// - `V2c` for SNMPv2c community-based
76    /// - `Usm` for SNMPv3 User-based Security Model
77    pub security_model: SecurityModel,
78
79    /// Security name (community string or USM username).
80    ///
81    /// For v1/v2c: the community string
82    /// For v3: the USM username
83    pub security_name: Bytes,
84
85    /// Security level (v3 only, NoAuthNoPriv for v1/v2c).
86    ///
87    /// Indicates whether authentication and/or privacy were used.
88    pub security_level: SecurityLevel,
89
90    /// Context name (v3 only, empty for v1/v2c).
91    ///
92    /// SNMPv3 contexts allow partitioning MIB views.
93    pub context_name: Bytes,
94
95    /// Request ID from the PDU.
96    ///
97    /// Useful for correlating requests with responses in logs.
98    pub request_id: i32,
99
100    /// PDU type (GetRequest, GetNextRequest, SetRequest, etc.).
101    pub pdu_type: PduType,
102
103    /// Resolved group name (if VACM enabled).
104    ///
105    /// Set when VACM successfully maps the security name to a group.
106    pub group_name: Option<Bytes>,
107
108    /// Read view name (if VACM enabled).
109    ///
110    /// The view that controls which OIDs can be read.
111    pub read_view: Option<Bytes>,
112
113    /// Write view name (if VACM enabled).
114    ///
115    /// The view that controls which OIDs can be written.
116    pub write_view: Option<Bytes>,
117}
118
119impl RequestContext {
120    /// Create a minimal context for unit testing.
121    pub fn test_context() -> Self {
122        use std::net::{IpAddr, Ipv4Addr, SocketAddr};
123
124        Self {
125            source: SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 0),
126            version: Version::V2c,
127            security_model: SecurityModel::V2c,
128            security_name: Bytes::from_static(b"public"),
129            security_level: SecurityLevel::NoAuthNoPriv,
130            context_name: Bytes::new(),
131            request_id: 1,
132            pdu_type: PduType::GetRequest,
133            group_name: None,
134            read_view: None,
135            write_view: None,
136        }
137    }
138}