Skip to main content

Client

Struct Client 

Source
pub struct Client<T: Transport = UdpHandle> { /* private fields */ }
Expand description

SNMP client.

Generic over transport type, with UdpHandle as default.

Implementations§

Source§

impl<T: Transport> Client<T>

Source

pub async fn rediscover_engine(&self) -> Result<()>

Discover and replace the established authoritative engine.

This is the intentional recovery path when a device at the target address has been replaced or reconfigured with a new engine ID. Discovery never replaces an established identity during ordinary request processing. The current identity, localized keys, and shared cache mapping remain usable until a fresh response has been strictly validated and replacement keys have been derived. A failed or cancelled rediscovery therefore leaves the previous generation intact.

Client clones share a successful replacement because they share the same live engine state. Independently constructed clients retain their own established identity until explicitly rediscovered. For UDP, source-address policy is controlled by TargetClientBuilder::strict_source or by the supplied transport handle.

This convenience method discards accepted discovery-response metadata. Use Self::rediscover_engine_with_metadata to retain it.

Source

pub async fn rediscover_engine_with_metadata(&self) -> Result<ResponseMetadata>

Discover and replace the authoritative engine while retaining accepted wire deviations from the discovery Report.

Source§

impl Client<UdpHandle>

Source

pub fn builder( target: impl Into<Target>, auth: impl Into<Auth>, ) -> TargetClientBuilder

Create an SNMP client builder.

This convenience entry point configures a library-maintained target transport. Use ClientBuilder::new when supplying an existing transport or reusing protocol/client policy across targets.

§Example
use async_snmp::{Auth, Client, Retry};
use std::time::Duration;

// (host, port) tuple - convenient when host and port are separate
let client = Client::builder(("192.168.1.1", 161), Auth::v2c("public"))
    .connect().await?;

// Combined address string (port defaults to 161 if omitted)
let client = Client::builder("switch.local", Auth::v2c("public"))
    .connect().await?;

// SocketAddr works too
let addr: std::net::SocketAddr = "192.168.1.1:161".parse().unwrap();
let client = Client::builder(addr, Auth::v2c("public"))
    .connect().await?;

UDP clients expose endpoint observation but not lifecycle authority:

async fn invalid(client: async_snmp::UdpClient) {
    let _control = client.control();
    client.shutdown().await;
}
Source

pub fn stats(&self) -> UdpStats

Snapshot cumulative statistics for this client’s UDP endpoint.

Dedicated clients observe their private endpoint. Clients built from a shared UdpTransport observe the same counters as every other client and handle using that endpoint.

Source§

impl<T: Transport> Client<T>

Source

pub fn new(transport: T, config: ClientConfig) -> Result<Self>

Create a client with the given transport and configuration.

For most use cases, prefer Client::builder() for a library-created transport or ClientBuilder::build_with_transport for an existing or custom Transport. Use this lower-level constructor when configuring the client directly with ClientConfig.

§Errors

Returns Error::Config when the configuration violates a client invariant, or Error::RandomSource when an authPriv client cannot initialize its privacy salt.

Source

pub fn with_engine_cache( transport: T, config: ClientConfig, engine_cache: Arc<EngineCache>, ) -> Result<Self>

Create an SNMPv3 client with a shared engine cache.

§Errors

Returns Error::Config when the configuration violates a client invariant, or Error::RandomSource when an authPriv client cannot initialize its privacy salt.

Source

pub fn peer_addr(&self) -> SocketAddr

Returns the peer address.

Returns the remote address that this client sends requests to. Named to match std::net::TcpStream::peer_addr().

Source

pub fn version(&self) -> Version

Returns the SNMP version configured for this client.

The version is selected by the client’s authentication configuration and does not expose community or USM identity data.

Source

pub fn decode_config(&self) -> DecodeConfig

Return the configured response decode configuration.

Source

pub fn walk_options(&self) -> WalkOptions

Return the default options snapshotted by Self::walk and Self::walk_with_metadata.

Source

pub fn security_level(&self) -> Option<SecurityLevel>

Returns the configured SNMPv3 USM security level.

Returns None for SNMPv1 and SNMPv2c clients. For SNMPv3 clients, the value describes the configured security level and does not expose the USM identity or credentials.

Source

pub async fn get(&self, oid: &Oid) -> Result<FixedCardinalityResponse>

GET a single OID.

Compatible mode preserves every returned binding and describes empty, excess, or renamed responses in anomalies.

Source

pub async fn get_many(&self, oids: &[Oid]) -> Result<FixedCardinalityResponse>
where T: 'static,

GET multiple OIDs.

If the OID list exceeds max_oids_per_request, the request is automatically split into multiple batches. Response bindings are retained in received batch order; consult anomalies before assuming positional correspondence with the input OIDs. If any batch fails, this aggregate convenience method returns the error without returning earlier results; use get_many_chunks() to retain partial work.

§Example
let results = client.get_many(&[
    oid!(1, 3, 6, 1, 2, 1, 1, 1, 0),  // sysDescr
    oid!(1, 3, 6, 1, 2, 1, 1, 3, 0),  // sysUpTime
    oid!(1, 3, 6, 1, 2, 1, 1, 5, 0),  // sysName
]).await?;
Source

pub fn get_many_chunks( &self, oids: &[Oid], ) -> Result<FixedCardinalityChunkStream<T>>
where T: 'static,

Lazily GET multiple OIDs as sequential wire-level response chunks.

All OIDs are validated when this method is called. No request is sent until the returned stream is polled, and after each item the next request waits for another poll. An agent tooBig response or a local Error::OutboundMessageTooLarge bisects a multi-OID request range and exposes successful child leaves independently. Either error on a single-OID range is terminal and is returned in FixedCardinalityChunkError::source.

The stream emits one FixedCardinalityChunkError for a terminal failure, then remains fused. Dropping a chunk stream while a TCP request is in flight follows TcpTransport’s cancellation contract: cancellation after acquiring the connection lock poisons that connection, and later operations fail with Error::Closed.

§Errors

Returns Error::InvalidOid before any I/O if any input OID cannot be represented on the wire.

Source

pub async fn get_next(&self, oid: &Oid) -> Result<FixedCardinalityResponse>

GETNEXT for a single OID.

Source

pub async fn get_next_many( &self, oids: &[Oid], ) -> Result<FixedCardinalityResponse>
where T: 'static,

GETNEXT for multiple OIDs.

If the OID list exceeds max_oids_per_request, the request is automatically split into multiple batches. Response bindings are retained in received batch order; consult anomalies before assuming positional correspondence with the input OIDs. If any batch fails, this aggregate convenience method returns the error without returning earlier results; use get_next_many_chunks() to retain partial work.

§Example
let results = client.get_next_many(&[
    oid!(1, 3, 6, 1, 2, 1, 2, 2, 1, 2),  // ifDescr
    oid!(1, 3, 6, 1, 2, 1, 2, 2, 1, 3),  // ifType
]).await?;
Source

pub fn get_next_many_chunks( &self, oids: &[Oid], ) -> Result<FixedCardinalityChunkStream<T>>
where T: 'static,

Lazily GETNEXT multiple OIDs as sequential wire-level response chunks.

This has the same validation, backpressure, bisection, terminal-error, and TCP cancellation behavior as get_many_chunks().

Source

pub async fn set( &self, oid: &Oid, value: Value, ) -> Result<FixedCardinalityResponse>

SET a single OID.

Source

pub async fn set_many( &self, varbinds: &[(Oid, Value)], ) -> Result<FixedCardinalityResponse>

SET multiple OIDs in a single atomic PDU.

RFC 3416 requires that a SET request be atomic: either all variables in the request are set, or none are. To preserve this guarantee, set_many refuses to split the varbind list across multiple PDUs.

If varbinds.len() exceeds max_oids_per_request, this method returns Error::Config rather than silently batching the request. Callers that need to set more variables than the per-request limit must issue multiple explicit set_many calls and handle partial failure themselves.

§Example
let results = client.set_many(&[
    (oid!(1, 3, 6, 1, 2, 1, 1, 5, 0), Value::from("new-hostname")),
    (oid!(1, 3, 6, 1, 2, 1, 1, 6, 0), Value::from("new-location")),
]).await?;
Source

pub async fn send_trap( &self, trap_oid: &Oid, uptime: u32, varbinds: Vec<VarBind>, ) -> Result<()>

Send a trap (fire-and-forget).

For V1 clients: constructs a TrapV1 PDU. The trap_oid is reverse-mapped to v1 generic_trap/specific_trap/enterprise fields per RFC 3584 Section 3.2. The agent_addr is set from the transport’s local IPv4 address, or [0,0,0,0] if the local address is IPv6. Use send_v1_trap for explicit control over v1 fields.

For V2c/V3 clients: constructs a TrapV2 PDU with the mandatory sysUpTime.0 and snmpTrapOID.0 prefix.

For V3: uses the persisted local authoritative engine state configured through ClientBuilder::local_authoritative_engine.

§Arguments
  • trap_oid - The trap OID (snmpTrapOID.0 value)
  • uptime - sysUpTime.0 value in hundredths of seconds
  • varbinds - Additional variable bindings (appended after the prefix)
Source

pub async fn send_v1_trap(&self, trap: TrapV1Notification) -> Result<()>

Send an SNMPv1 trap with explicit v1 PDU fields.

This is a lower-level method that accepts a validated TrapV1Notification, giving full control over enterprise OID, agent_addr, generic_trap, specific_trap, and time_stamp fields.

The client must be configured for V1 (Auth::v1()). Returns an error if the client version is not V1.

§Example
let client = Client::builder("192.168.1.100:162", Auth::v1("public"))
    .connect().await?;

let trap = TrapV1Notification::new(
    oid!(1, 3, 6, 1, 4, 1, 9999),  // enterprise
    [192, 168, 1, 1],               // agent address
    GenericTrap::ColdStart,
    0,
    12345,                          // uptime in centiseconds
    vec![],
)?;
client.send_v1_trap(trap).await?;
Source

pub async fn send_inform( &self, trap_oid: &Oid, uptime: u32, varbinds: Vec<VarBind>, ) -> Result<()>

Send a v2c/v3 inform and wait for acknowledgement.

Constructs an InformRequest PDU with the mandatory sysUpTime.0 and snmpTrapOID.0 prefix, sends it to the target, and waits for a Response PDU that echoes the request variable bindings. Uses the same retry and timeout logic as other request types.

For V3: uses engine discovery against the receiver (same as GET/SET). V1 is not supported and returns an error.

§Arguments
  • trap_oid - The trap OID (snmpTrapOID.0 value)
  • uptime - sysUpTime.0 value in hundredths of seconds
  • varbinds - Additional variable bindings (appended after the prefix)

This convenience method intentionally discards accepted wire-deviation metadata. Use Self::send_inform_with_metadata when it is needed.

Source

pub async fn send_inform_with_metadata( &self, trap_oid: &Oid, uptime: u32, varbinds: Vec<VarBind>, ) -> Result<ResponseMetadata>

Send an Inform and retain metadata from discovery, correction Reports, and the acknowledgement in exchange order.

Source

pub async fn get_bulk( &self, oids: &[Oid], non_repeaters: u32, max_repetitions: u32, ) -> Result<Vec<VarBind>>

GETBULK request (SNMPv2c/v3 only).

Efficiently retrieves multiple variable bindings in a single request. GETBULK splits the requested OIDs into two groups:

  • Non-repeaters (first N OIDs): Each gets a single GETNEXT, returning the first lexicographic successor of the requested OID. To retrieve a scalar instance such as sysUpTime.0, request its object OID without the .0 instance suffix.
  • Repeaters (remaining OIDs): Each gets up to max_repetitions GETNEXTs, returning multiple values per OID. Use for walking table columns.
§Arguments
  • oids - OIDs to retrieve
  • non_repeaters - How many OIDs (from the start) are non-repeating
  • max_repetitions - Maximum rows to return for each repeating OID
§Errors

Returns Error::InvalidMessage when either GETBULK parameter exceeds i32::MAX.

§Example
// Get sysUpTime.0 (non-repeater) plus 10 interface descriptions (repeater).
// Both inputs are object OIDs; GETBULK returns their instance successors.
let results = client.get_bulk(
    &[oid!(1, 3, 6, 1, 2, 1, 1, 3), oid!(1, 3, 6, 1, 2, 1, 2, 2, 1, 2)],
    1,  // first OID is non-repeating
    10, // get up to 10 values for the second OID
).await?;
// Results: [sysUpTime value, ifDescr.1, ifDescr.2, ..., ifDescr.10]

This convenience method discards accepted response metadata. Use Self::get_bulk_with_metadata when compatibility deviations must be retained.

Source

pub async fn get_bulk_with_metadata( &self, oids: &[Oid], non_repeaters: u32, max_repetitions: u32, ) -> Result<BulkResponse>

GETBULK with accepted wire deviations retained as response metadata.

Source

pub fn walk(&self, oid: Oid) -> Result<WalkStream<T>>
where T: 'static,

Walk an OID subtree.

Auto-selects GETNEXT for V1 and GETBULK for V2c/V3 by default. WalkOptions::method can select either operation explicitly.

Returns an async stream that yields each variable binding in the subtree. This convenience stream intentionally discards decode metadata; use Self::walk_with_metadata to retain it. The walk terminates when an OID outside the subtree is encountered or when EndOfMibView is returned. All consumption methods observe this same GETNEXT/GETBULK sequence. A scalar instance OID is not retrieved as a fallback; use get() to retrieve a scalar value.

Uses the client’s snapshotted WalkOptions. At a configured result limit, the stream inspects one look-ahead candidate and may make one extra request. Definite truncation is emitted as WalkAbortReason::ResultLimitExceeded. A walk is not an atomic MIB snapshot; values can change between the main sequence and the look-ahead.

§Example
// Auto-selects GETBULK for V2c/V3, GETNEXT for V1
let results = client.walk(oid!(1, 3, 6, 1, 2, 1, 1))?.collect().await?;
Source

pub fn walk_with(&self, oid: Oid, options: WalkOptions) -> Result<WalkStream<T>>
where T: 'static,

Walk using an operation-specific options snapshot.

This override does not mutate the client default or teach the client a persistent device capability. GetBulk on SNMPv1 is rejected here, before the returned stream can perform transport I/O.

Source

pub fn walk_with_metadata(&self, oid: Oid) -> Result<WalkMetadataStream<T>>
where T: 'static,

Walk using the client’s default options while retaining response metadata.

Source

pub fn walk_with_metadata_and( &self, oid: Oid, options: WalkOptions, ) -> Result<WalkMetadataStream<T>>
where T: 'static,

Walk with metadata using an operation-specific options snapshot.

Source

pub fn walk_getnext(&self, oid: Oid) -> Result<WalkStream<T>>
where T: 'static,

Explicit GETNEXT convenience returning the common plain stream type.

Source

pub fn walk_getnext_with_metadata( &self, oid: Oid, ) -> Result<WalkMetadataStream<T>>
where T: 'static,

Explicit GETNEXT convenience returning the common metadata stream type.

Source

pub fn bulk_walk(&self, oid: Oid, max_repetitions: u32) -> Result<WalkStream<T>>
where T: 'static,

Explicit GETBULK convenience returning the common plain stream type.

Source

pub fn bulk_walk_with_metadata( &self, oid: Oid, max_repetitions: u32, ) -> Result<WalkMetadataStream<T>>
where T: 'static,

Explicit GETBULK convenience returning the common metadata stream type.

Source

pub fn bulk_walk_default(&self, oid: Oid) -> Result<WalkStream<T>>
where T: 'static,

Explicit GETBULK convenience using the client’s default repetitions.

Trait Implementations§

Source§

impl<T: Transport> Clone for Client<T>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

§

impl<T = UdpHandle> !RefUnwindSafe for Client<T>

§

impl<T = UdpHandle> !UnwindSafe for Client<T>

§

impl<T> Freeze for Client<T>

§

impl<T> Send for Client<T>

§

impl<T> Sync for Client<T>

§

impl<T> Unpin for Client<T>

§

impl<T> UnsafeUnpin for Client<T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more