support snmp v1
This commit is contained in:
parent
0548ca313d
commit
dbf66af5c0
2 changed files with 76 additions and 20 deletions
|
|
@ -24,29 +24,23 @@ impl SnmpClient {
|
|||
port: u16,
|
||||
oid: &str,
|
||||
) -> SnmpResult<SnmpValue> {
|
||||
// Only SNMPv2c is supported by the snmp crate
|
||||
if version != "2c" {
|
||||
return Err(SnmpError::RequestFailed(format!(
|
||||
"Unsupported SNMP version: {}. Only 2c is supported.",
|
||||
version
|
||||
)));
|
||||
}
|
||||
|
||||
// Parse OID string to Vec<u32>
|
||||
let oid_parts = parse_oid(oid)?;
|
||||
|
||||
// Clone data for the blocking task
|
||||
let addr = format!("{}:{}", ip_address, port);
|
||||
let community = community.as_bytes().to_vec();
|
||||
let version_num = parse_snmp_version(version)?;
|
||||
|
||||
// Run SNMP operation in blocking thread pool
|
||||
let result = tokio::task::spawn_blocking(move || {
|
||||
// Create session with configurable timeout
|
||||
// The snmp crate supports both v1 (0) and v2c (1)
|
||||
let mut session = SyncSession::new(
|
||||
addr.as_str(),
|
||||
&community,
|
||||
Some(Duration::from_secs(SNMP_TIMEOUT_SECS)),
|
||||
0,
|
||||
version_num,
|
||||
)
|
||||
.map_err(|_| SnmpError::NetworkUnreachable)?;
|
||||
|
||||
|
|
@ -84,29 +78,23 @@ impl SnmpClient {
|
|||
port: u16,
|
||||
base_oid: &str,
|
||||
) -> SnmpResult<Vec<(String, SnmpValue)>> {
|
||||
// Only SNMPv2c is supported by the snmp crate
|
||||
if version != "2c" {
|
||||
return Err(SnmpError::RequestFailed(format!(
|
||||
"Unsupported SNMP version: {}. Only 2c is supported.",
|
||||
version
|
||||
)));
|
||||
}
|
||||
|
||||
// Parse OID string to Vec<u32>
|
||||
let base_oid_parts = parse_oid(base_oid)?;
|
||||
|
||||
// Clone data for the blocking task
|
||||
let addr = format!("{}:{}", ip_address, port);
|
||||
let community = community.as_bytes().to_vec();
|
||||
let version_num = parse_snmp_version(version)?;
|
||||
|
||||
// Run SNMP walk in blocking thread pool
|
||||
let results = tokio::task::spawn_blocking(move || {
|
||||
// Create session with configurable timeout
|
||||
// The snmp crate supports both v1 (0) and v2c (1)
|
||||
let mut session = SyncSession::new(
|
||||
addr.as_str(),
|
||||
&community,
|
||||
Some(Duration::from_secs(SNMP_TIMEOUT_SECS)),
|
||||
0,
|
||||
version_num,
|
||||
)
|
||||
.map_err(|_| SnmpError::NetworkUnreachable)?;
|
||||
|
||||
|
|
@ -167,6 +155,21 @@ impl Default for SnmpClient {
|
|||
}
|
||||
}
|
||||
|
||||
/// Parse SNMP version string to integer for snmp crate
|
||||
/// Returns: 0 for SNMPv1, 1 for SNMPv2c
|
||||
fn parse_snmp_version(version: &str) -> SnmpResult<i32> {
|
||||
let normalized = version.trim().to_lowercase();
|
||||
|
||||
match normalized.as_str() {
|
||||
"1" | "v1" | "snmpv1" => Ok(0),
|
||||
"2c" | "v2c" | "snmpv2c" | "2" | "v2" => Ok(1),
|
||||
_ => Err(SnmpError::RequestFailed(format!(
|
||||
"Unsupported SNMP version: '{}'. Supported versions: 1, v1, 2c, v2c",
|
||||
version
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse OID string like "1.3.6.1.2.1.1.1.0" to Vec<u32>
|
||||
fn parse_oid(oid: &str) -> SnmpResult<Vec<u32>> {
|
||||
oid.split('.')
|
||||
|
|
@ -246,6 +249,36 @@ mod tests {
|
|||
assert!(format!("{:?}", client).contains("SnmpClient"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_snmp_version_v1() {
|
||||
assert_eq!(parse_snmp_version("1").unwrap(), 0);
|
||||
assert_eq!(parse_snmp_version("v1").unwrap(), 0);
|
||||
assert_eq!(parse_snmp_version("V1").unwrap(), 0);
|
||||
assert_eq!(parse_snmp_version("snmpv1").unwrap(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_snmp_version_v2c() {
|
||||
assert_eq!(parse_snmp_version("2c").unwrap(), 1);
|
||||
assert_eq!(parse_snmp_version("2C").unwrap(), 1);
|
||||
assert_eq!(parse_snmp_version("v2c").unwrap(), 1);
|
||||
assert_eq!(parse_snmp_version("V2C").unwrap(), 1);
|
||||
assert_eq!(parse_snmp_version("2").unwrap(), 1);
|
||||
assert_eq!(parse_snmp_version("v2").unwrap(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_snmp_version_invalid() {
|
||||
let result = parse_snmp_version("3");
|
||||
assert!(result.is_err());
|
||||
match result {
|
||||
Err(SnmpError::RequestFailed(msg)) => {
|
||||
assert!(msg.contains("Unsupported SNMP version"));
|
||||
}
|
||||
_ => panic!("Expected RequestFailed error"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_oid_valid() {
|
||||
let result = parse_oid("1.3.6.1.2.1.1.1.0");
|
||||
|
|
|
|||
|
|
@ -357,6 +357,23 @@ impl AgentClient {
|
|||
/// Execute an SNMP job and collect results.
|
||||
async fn execute_job(job: AgentJob, result_tx: mpsc::UnboundedSender<SnmpResult>) -> Result<()> {
|
||||
let snmp_device = job.snmp_device.ok_or("Job missing SNMP device info")?;
|
||||
|
||||
// Log SNMP connection parameters for debugging (mask community for security)
|
||||
let community_masked = if snmp_device.community.len() > 4 {
|
||||
format!("{}***", &snmp_device.community[..2])
|
||||
} else {
|
||||
"***".to_string()
|
||||
};
|
||||
|
||||
crate::log_info!(
|
||||
"Executing SNMP job for device {} at {}:{} (community: {}, version: {})",
|
||||
job.device_id,
|
||||
snmp_device.ip,
|
||||
snmp_device.port,
|
||||
community_masked,
|
||||
snmp_device.version
|
||||
);
|
||||
|
||||
let mut oid_values: HashMap<String, String> = HashMap::new();
|
||||
let snmp_client = SnmpClient::new();
|
||||
|
||||
|
|
@ -382,9 +399,12 @@ async fn execute_job(job: AgentJob, result_tx: mpsc::UnboundedSender<SnmpResult>
|
|||
}
|
||||
Err(e) => {
|
||||
crate::log_warn!(
|
||||
"SNMP GET failed for device {} ({}), OID {}: {}",
|
||||
"SNMP GET failed for device {} at {}:{} (version: {}, community: {}), OID {}: {}",
|
||||
job.device_id,
|
||||
snmp_device.ip,
|
||||
snmp_device.port,
|
||||
snmp_device.version,
|
||||
community_masked,
|
||||
oid,
|
||||
e
|
||||
);
|
||||
|
|
@ -412,9 +432,12 @@ async fn execute_job(job: AgentJob, result_tx: mpsc::UnboundedSender<SnmpResult>
|
|||
}
|
||||
Err(e) => {
|
||||
crate::log_warn!(
|
||||
"SNMP WALK failed for device {} ({}), OID {}: {}",
|
||||
"SNMP WALK failed for device {} at {}:{} (version: {}, community: {}), OID {}: {}",
|
||||
job.device_id,
|
||||
snmp_device.ip,
|
||||
snmp_device.port,
|
||||
snmp_device.version,
|
||||
community_masked,
|
||||
base_oid,
|
||||
e
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue