mirror of
https://github.com/centreon/centreon-plugins.git
synced 2025-07-31 01:24:35 +02:00
enh(generic-snmp): work on bulk snmp get
This commit is contained in:
parent
8256c01111
commit
4a31f1b2e4
@ -1,8 +1,10 @@
|
|||||||
extern crate serde;
|
extern crate serde;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
|
|
||||||
use snmp::{r_snmp_bulk_walk, SnmpResult};
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
use snmp::{r_snmp_bulk_walk, SnmpResult, SnmpValue};
|
||||||
|
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub enum Status {
|
pub enum Status {
|
||||||
@ -177,199 +179,227 @@ impl Command {
|
|||||||
target: &str,
|
target: &str,
|
||||||
version: &str,
|
version: &str,
|
||||||
community: &str,
|
community: &str,
|
||||||
ext: &CommandExt,
|
//ext: &CommandExt,
|
||||||
) -> CmdResult {
|
) -> CmdResult {
|
||||||
// let mut agregation = ("", 0, Operation::None);
|
let mut res: BTreeMap<String, i64> = BTreeMap::new();
|
||||||
// let mut res: Option<(&str, SnmpResult)> = None;
|
for s in self.collect.snmp.iter() {
|
||||||
// for (idx, entry) in self.leaf.entries.iter().enumerate() {
|
match s.query {
|
||||||
// match entry {
|
QueryType::Walk => {
|
||||||
// Entry::Agregation(op) => {
|
let r = r_snmp_bulk_walk(target, version, community, &s.oid);
|
||||||
// agregation = (&op.name, idx, op.op);
|
match r.variables.len() {
|
||||||
// }
|
1 => {
|
||||||
// Entry::Query(query) => match query.query {
|
let result = r.variables.get(0).unwrap();
|
||||||
// QueryType::Walk => {
|
if let SnmpValue::Integer(v) = result.value {
|
||||||
// res = Some((
|
res.insert(s.name.clone(), v);
|
||||||
// &query.name,
|
}
|
||||||
// r_snmp_bulk_walk(target, version, community, &query.oid),
|
}
|
||||||
// ));
|
_ => {
|
||||||
// }
|
for (idx, result) in r.variables.iter().enumerate() {
|
||||||
// },
|
if let SnmpValue::Integer(v) = result.value {
|
||||||
// }
|
res.insert(format!("{}_{}", &s.name, idx), v);
|
||||||
// }
|
}
|
||||||
// match res {
|
}
|
||||||
// Some(r) => {
|
}
|
||||||
// let mut values: Vec<(String, f32)> = Vec::new();
|
}
|
||||||
// let mut idx = 0;
|
}
|
||||||
// r.1.variables.iter().for_each(|v| {
|
QueryType::Get => {
|
||||||
// let label = r.0.replace("{idx}", &idx.to_string());
|
// let r = r_snmp_bulk_get(target, version, community, &s.oid);
|
||||||
// values.push((label, v.value.parse().unwrap()));
|
// res.insert(&s.name, r);
|
||||||
// idx += 1;
|
}
|
||||||
// });
|
}
|
||||||
// let count = values.len();
|
}
|
||||||
// let ag = match agregation.2 {
|
println!("{:?}", res);
|
||||||
// Operation::Average => {
|
// let mut aggregation = ("", 0, Operation::None);
|
||||||
// let sum: f32 = values.iter().map(|(_, v)| v).sum();
|
// let mut res: Option<(&str, SnmpResult)> = None;
|
||||||
// let avg = sum / values.len() as f32;
|
// for (idx, entry) in self.leaf.entries.iter().enumerate() {
|
||||||
// Some((agregation.0, agregation.1, avg))
|
// match entry {
|
||||||
// }
|
// Entry::Agregation(op) => {
|
||||||
// _ => None,
|
// agregation = (&op.name, idx, op.op);
|
||||||
// };
|
// }
|
||||||
// let (metrics, status) = build_metrics(&values, &ag, &ext);
|
// Entry::Query(query) => match query.query {
|
||||||
// let output = self.build_output(count, status, &metrics, &ag, &ext);
|
// QueryType::Walk => {
|
||||||
// return CmdResult { status, output };
|
// res = Some((
|
||||||
// }
|
// &query.name,
|
||||||
// None => {
|
// r_snmp_bulk_walk(target, version, community, &query.oid),
|
||||||
// return CmdResult {
|
// ));
|
||||||
// status: Status::Unknown,
|
// }
|
||||||
// output: "No result".to_string(),
|
// },
|
||||||
// };
|
// }
|
||||||
// }
|
// }
|
||||||
// }
|
// match res {
|
||||||
|
// Some(r) => {
|
||||||
|
// let mut values: Vec<(String, f32)> = Vec::new();
|
||||||
|
// let mut idx = 0;
|
||||||
|
// r.1.variables.iter().for_each(|v| {
|
||||||
|
// let label = r.0.replace("{idx}", &idx.to_string());
|
||||||
|
// values.push((label, v.value.parse().unwrap()));
|
||||||
|
// idx += 1;
|
||||||
|
// });
|
||||||
|
// let count = values.len();
|
||||||
|
// let ag = match agregation.2 {
|
||||||
|
// Operation::Average => {
|
||||||
|
// let sum: f32 = values.iter().map(|(_, v)| v).sum();
|
||||||
|
// let avg = sum / values.len() as f32;
|
||||||
|
// Some((agregation.0, agregation.1, avg))
|
||||||
|
// }
|
||||||
|
// _ => None,
|
||||||
|
// };
|
||||||
|
// let (metrics, status) = build_metrics(&values, &ag, &ext);
|
||||||
|
// let output = self.build_output(count, status, &metrics, &ag, &ext);
|
||||||
|
// return CmdResult { status, output };
|
||||||
|
// }
|
||||||
|
// None => {
|
||||||
|
// return CmdResult {
|
||||||
|
// status: Status::Unknown,
|
||||||
|
// output: "No result".to_string(),
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// }
|
||||||
CmdResult {
|
CmdResult {
|
||||||
status: Status::Unknown,
|
status: Status::Unknown,
|
||||||
output: "No result".to_string(),
|
output: "No result".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn build_output(
|
// fn build_output(
|
||||||
// &self,
|
// &self,
|
||||||
// count: usize,
|
// count: usize,
|
||||||
// status: Status,
|
// status: Status,
|
||||||
// metrics: &Vec<Metric>,
|
// metrics: &Vec<Metric>,
|
||||||
// ag: &Option<(&str, usize, f32)>,
|
// ag: &Option<(&str, usize, f32)>,
|
||||||
// ext: &CommandExt,
|
// ext: &CommandExt,
|
||||||
// ) -> String {
|
// ) -> String {
|
||||||
// let no_threshold = ext.warning_core.is_none()
|
// let no_threshold = ext.warning_core.is_none()
|
||||||
// && ext.critical_core.is_none()
|
// && ext.critical_core.is_none()
|
||||||
// && ext.warning_agregation.is_none()
|
// && ext.warning_agregation.is_none()
|
||||||
// && ext.critical_agregation.is_none();
|
// && ext.critical_agregation.is_none();
|
||||||
// let write_details =
|
// let write_details =
|
||||||
// no_threshold || (ext.warning_core.is_some() || ext.critical_core.is_some());
|
// no_threshold || (ext.warning_core.is_some() || ext.critical_core.is_some());
|
||||||
// let write_agregation_details =
|
// let write_agregation_details =
|
||||||
// no_threshold || (ext.warning_agregation.is_some() || ext.critical_agregation.is_some());
|
// no_threshold || (ext.warning_agregation.is_some() || ext.critical_agregation.is_some());
|
||||||
// let mut output_text = "".to_string();
|
// let mut output_text = "".to_string();
|
||||||
// let mut begun = false;
|
// let mut begun = false;
|
||||||
// if &self.leaf.output.header != "" {
|
// if &self.leaf.output.header != "" {
|
||||||
// output_text = self.leaf.output.header.replace("{status}", status.as_str());
|
// output_text = self.leaf.output.header.replace("{status}", status.as_str());
|
||||||
// }
|
// }
|
||||||
// for line in &self.leaf.output.text {
|
// for line in &self.leaf.output.text {
|
||||||
// if line.contains("idx") {
|
// if line.contains("idx") {
|
||||||
// if write_details {
|
// if write_details {
|
||||||
// // We have to iterate on metrics
|
// // We have to iterate on metrics
|
||||||
// let mut output_vec = (Vec::new(), Vec::new(), Vec::new());
|
// let mut output_vec = (Vec::new(), Vec::new(), Vec::new());
|
||||||
// let mut idx = 0;
|
// let mut idx = 0;
|
||||||
// for m in metrics.iter() {
|
// for m in metrics.iter() {
|
||||||
// if !m.agregated {
|
// if !m.agregated {
|
||||||
// let text = line
|
// let text = line
|
||||||
// .replace("{idx}", idx.to_string().as_str())
|
// .replace("{idx}", idx.to_string().as_str())
|
||||||
// .replace("{name}", m.name.as_str())
|
// .replace("{name}", m.name.as_str())
|
||||||
// .replace("{value}", format!("{:.2}", m.value).as_str())
|
// .replace("{value}", format!("{:.2}", m.value).as_str())
|
||||||
// .replace("{count}", count.to_string().as_str());
|
// .replace("{count}", count.to_string().as_str());
|
||||||
// match m.status {
|
// match m.status {
|
||||||
// Status::Ok => {
|
// Status::Ok => {
|
||||||
// output_vec.0.push(text);
|
// output_vec.0.push(text);
|
||||||
// }
|
// }
|
||||||
// Status::Warning => {
|
// Status::Warning => {
|
||||||
// output_vec.1.push(text);
|
// output_vec.1.push(text);
|
||||||
// }
|
// }
|
||||||
// Status::Critical => {
|
// Status::Critical => {
|
||||||
// output_vec.2.push(text);
|
// output_vec.2.push(text);
|
||||||
// }
|
// }
|
||||||
// Status::Unknown => (),
|
// Status::Unknown => (),
|
||||||
// }
|
// }
|
||||||
// idx += 1;
|
// idx += 1;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// if !output_vec.2.is_empty() {
|
// if !output_vec.2.is_empty() {
|
||||||
// if begun {
|
// if begun {
|
||||||
// output_text += " - ";
|
// output_text += " - ";
|
||||||
// } else {
|
// } else {
|
||||||
// begun = true;
|
// begun = true;
|
||||||
// }
|
// }
|
||||||
// output_text += output_vec.2.join(" - ").as_str();
|
// output_text += output_vec.2.join(" - ").as_str();
|
||||||
// }
|
// }
|
||||||
// if !output_vec.1.is_empty() {
|
// if !output_vec.1.is_empty() {
|
||||||
// if begun {
|
// if begun {
|
||||||
// output_text += " - ";
|
// output_text += " - ";
|
||||||
// } else {
|
// } else {
|
||||||
// begun = true;
|
// begun = true;
|
||||||
// }
|
// }
|
||||||
// output_text += output_vec.1.join(" - ").as_str();
|
// output_text += output_vec.1.join(" - ").as_str();
|
||||||
// }
|
// }
|
||||||
// if !output_vec.0.is_empty() {
|
// if !output_vec.0.is_empty() {
|
||||||
// if begun {
|
// if begun {
|
||||||
// output_text += " - ";
|
// output_text += " - ";
|
||||||
// }
|
// }
|
||||||
// output_text += output_vec.0.join(" - ").as_str();
|
// output_text += output_vec.0.join(" - ").as_str();
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// } else {
|
// } else {
|
||||||
// if write_agregation_details {
|
// if write_agregation_details {
|
||||||
// match ag {
|
// match ag {
|
||||||
// Some(a) => {
|
// Some(a) => {
|
||||||
// output_text += line
|
// output_text += line
|
||||||
// .replace(
|
// .replace(
|
||||||
// format!("{{{}}}", a.0).as_str(),
|
// format!("{{{}}}", a.0).as_str(),
|
||||||
// format!("{:.2}", a.2).as_str(),
|
// format!("{:.2}", a.2).as_str(),
|
||||||
// )
|
// )
|
||||||
// .replace("{count}", count.to_string().as_str())
|
// .replace("{count}", count.to_string().as_str())
|
||||||
// .as_str();
|
// .as_str();
|
||||||
// begun = true;
|
// begun = true;
|
||||||
// }
|
// }
|
||||||
// None => output_text += line,
|
// None => output_text += line,
|
||||||
// };
|
// };
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// let mut perfdata = " |".to_string();
|
// let mut perfdata = " |".to_string();
|
||||||
// match &self.leaf.data {
|
// match &self.leaf.data {
|
||||||
// Some(d) => {
|
// Some(d) => {
|
||||||
// metrics.iter().for_each(|m| {
|
// metrics.iter().for_each(|m| {
|
||||||
// perfdata += format!(
|
// perfdata += format!(
|
||||||
// " '{}'={}{};{};{};{};{}",
|
// " '{}'={}{};{};{};{};{}",
|
||||||
// m.name,
|
// m.name,
|
||||||
// m.value,
|
// m.value,
|
||||||
// d.uom,
|
// d.uom,
|
||||||
// match m.warning {
|
// match m.warning {
|
||||||
// Some(m) => m.to_string(),
|
// Some(m) => m.to_string(),
|
||||||
// None => "".to_string(),
|
// None => "".to_string(),
|
||||||
// },
|
// },
|
||||||
// match m.critical {
|
// match m.critical {
|
||||||
// Some(m) => m.to_string(),
|
// Some(m) => m.to_string(),
|
||||||
// None => "".to_string(),
|
// None => "".to_string(),
|
||||||
// },
|
// },
|
||||||
// match d.min {
|
// match d.min {
|
||||||
// Some(m) => m.to_string(),
|
// Some(m) => m.to_string(),
|
||||||
// None => "".to_string(),
|
// None => "".to_string(),
|
||||||
// },
|
// },
|
||||||
// match d.max {
|
// match d.max {
|
||||||
// Some(m) => m.to_string(),
|
// Some(m) => m.to_string(),
|
||||||
// None => "".to_string(),
|
// None => "".to_string(),
|
||||||
// },
|
// },
|
||||||
// )
|
// )
|
||||||
// .as_str();
|
// .as_str();
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
// None => {
|
// None => {
|
||||||
// metrics.iter().for_each(|m| {
|
// metrics.iter().for_each(|m| {
|
||||||
// perfdata += format!(
|
// perfdata += format!(
|
||||||
// " '{}'={};{};{}",
|
// " '{}'={};{};{}",
|
||||||
// m.name,
|
// m.name,
|
||||||
// m.value,
|
// m.value,
|
||||||
// match m.warning {
|
// match m.warning {
|
||||||
// Some(v) => v.to_string(),
|
// Some(v) => v.to_string(),
|
||||||
// None => "".to_string(),
|
// None => "".to_string(),
|
||||||
// },
|
// },
|
||||||
// match m.critical {
|
// match m.critical {
|
||||||
// Some(v) => v.to_string(),
|
// Some(v) => v.to_string(),
|
||||||
// None => "".to_string(),
|
// None => "".to_string(),
|
||||||
// }
|
// }
|
||||||
// )
|
// )
|
||||||
// .as_str();
|
// .as_str();
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
// };
|
// };
|
||||||
// output_text + &perfdata
|
// output_text + &perfdata
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,8 @@ fn main() {
|
|||||||
let mut parser = lexopt::Parser::from_env();
|
let mut parser = lexopt::Parser::from_env();
|
||||||
let mut hostname = "localhost".to_string();
|
let mut hostname = "localhost".to_string();
|
||||||
let mut port = 161;
|
let mut port = 161;
|
||||||
|
let mut snmp_version = "2c".to_string();
|
||||||
|
let mut snmp_community = "public".to_string();
|
||||||
let mut json = None;
|
let mut json = None;
|
||||||
loop {
|
loop {
|
||||||
let arg = parser.next();
|
let arg = parser.next();
|
||||||
@ -91,6 +93,14 @@ fn main() {
|
|||||||
json = Some(parser.value().unwrap().into_string().unwrap());
|
json = Some(parser.value().unwrap().into_string().unwrap());
|
||||||
println!("json: {:?}", json);
|
println!("json: {:?}", json);
|
||||||
},
|
},
|
||||||
|
Short('v') | Long("snmp-version") => {
|
||||||
|
snmp_version = parser.value().unwrap().into_string().unwrap();
|
||||||
|
println!("snmp_version: {}", snmp_version);
|
||||||
|
},
|
||||||
|
Short('c') | Long("snmp-community") => {
|
||||||
|
snmp_community = parser.value().unwrap().into_string().unwrap();
|
||||||
|
println!("snmp_community: {}", snmp_community);
|
||||||
|
},
|
||||||
_ => {
|
_ => {
|
||||||
println!("other");
|
println!("other");
|
||||||
}
|
}
|
||||||
@ -123,7 +133,7 @@ fn main() {
|
|||||||
// warning_agregation: cli.warning_agregation,
|
// warning_agregation: cli.warning_agregation,
|
||||||
// critical_agregation: cli.critical_agregation,
|
// critical_agregation: cli.critical_agregation,
|
||||||
//};
|
//};
|
||||||
//let result = cmd.execute(&url, &cli.snmp_version, &cli.community, &ext);
|
let result = cmd.execute(&url, &snmp_version, &snmp_community);
|
||||||
//println!("{}", result.output);
|
//println!("{}", result.output);
|
||||||
//std::process::exit(result.status as i32);
|
//std::process::exit(result.status as i32);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ extern crate rasn_smi;
|
|||||||
extern crate rasn_snmp;
|
extern crate rasn_snmp;
|
||||||
|
|
||||||
use log::{info, trace, warn};
|
use log::{info, trace, warn};
|
||||||
|
use rasn::types::IntegerType;
|
||||||
use rasn::types::ObjectIdentifier;
|
use rasn::types::ObjectIdentifier;
|
||||||
use rasn_snmp::v2::Pdus;
|
use rasn_snmp::v2::Pdus;
|
||||||
use rasn_snmp::v2::VarBind;
|
use rasn_snmp::v2::VarBind;
|
||||||
@ -11,6 +12,7 @@ use rasn_snmp::v2::VarBindValue;
|
|||||||
use rasn_snmp::v2::{BulkPdu, Pdu};
|
use rasn_snmp::v2::{BulkPdu, Pdu};
|
||||||
use rasn_snmp::v2::{GetBulkRequest, GetNextRequest, GetRequest};
|
use rasn_snmp::v2::{GetBulkRequest, GetNextRequest, GetRequest};
|
||||||
use rasn_snmp::v2c::Message;
|
use rasn_snmp::v2c::Message;
|
||||||
|
use std::convert::TryInto;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::net::UdpSocket;
|
use std::net::UdpSocket;
|
||||||
@ -23,14 +25,20 @@ pub struct SnmpResult {
|
|||||||
|
|
||||||
type CSnmpVariable = c_void;
|
type CSnmpVariable = c_void;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum SnmpValue {
|
||||||
|
Integer(i64),
|
||||||
|
String(String),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct SnmpVariable {
|
pub struct SnmpVariable {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub value: String,
|
pub value: SnmpValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SnmpVariable {
|
impl SnmpVariable {
|
||||||
fn new(name: String, value: String) -> SnmpVariable {
|
fn new(name: String, value: SnmpValue) -> SnmpVariable {
|
||||||
SnmpVariable { name, value }
|
SnmpVariable { name, value }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -44,7 +52,7 @@ impl SnmpResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_variable(&mut self, name: String, value: String) {
|
fn add_variable(&mut self, name: String, value: SnmpValue) {
|
||||||
self.variables.push(SnmpVariable::new(name, value));
|
self.variables.push(SnmpVariable::new(name, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,83 +61,83 @@ impl SnmpResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
//#[allow(non_snake_case)]
|
||||||
#[no_mangle]
|
//#[no_mangle]
|
||||||
pub extern "C" fn snmpresult_DESTROY(p: *mut CSnmpResult) {
|
//pub extern "C" fn snmpresult_DESTROY(p: *mut CSnmpResult) {
|
||||||
unsafe { Box::from_raw(p as *mut SnmpResult) };
|
// unsafe { Box::from_raw(p as *mut SnmpResult) };
|
||||||
}
|
//}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
//#[allow(non_snake_case)]
|
||||||
#[no_mangle]
|
//#[no_mangle]
|
||||||
pub extern "C" fn snmpresult_get_variable(p: *mut CSnmpResult, index: usize) -> *mut CSnmpVariable {
|
//pub extern "C" fn snmpresult_get_variable(p: *mut CSnmpResult, index: usize) -> *mut CSnmpVariable {
|
||||||
trace!("snmpresult_get_variable {}", index);
|
// trace!("snmpresult_get_variable {}", index);
|
||||||
let p = p as *mut SnmpResult;
|
// let p = p as *mut SnmpResult;
|
||||||
let p = unsafe { &mut *p };
|
// let p = unsafe { &mut *p };
|
||||||
if index >= p.variables.len() {
|
// if index >= p.variables.len() {
|
||||||
return Box::into_raw(Box::new(SnmpVariable::new("".to_string(), "".to_string())))
|
// return Box::into_raw(Box::new(SnmpVariable::new("".to_string(), "".to_string())))
|
||||||
as *mut CSnmpVariable;
|
// as *mut CSnmpVariable;
|
||||||
}
|
// }
|
||||||
let v = &p.variables[index];
|
// let v = &p.variables[index];
|
||||||
Box::into_raw(Box::new(SnmpVariable {
|
// Box::into_raw(Box::new(SnmpVariable {
|
||||||
name: v.name.clone(),
|
// name: v.name.clone(),
|
||||||
value: v.value.clone(),
|
// value: v.value.clone(),
|
||||||
})) as *mut CSnmpVariable
|
// })) as *mut CSnmpVariable
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
|
//#[allow(non_snake_case)]
|
||||||
|
//#[no_mangle]
|
||||||
|
//pub extern "C" fn snmpresult_variables_count(p: *mut CSnmpResult) -> usize {
|
||||||
|
// let p = p as *mut SnmpResult;
|
||||||
|
// let p = unsafe { &mut *p };
|
||||||
|
// p.variables.len()
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//#[allow(non_snake_case)]
|
||||||
|
//#[no_mangle]
|
||||||
|
//pub extern "C" fn snmpvariable_DESTROY(p: *mut CSnmpVariable) {
|
||||||
|
// unsafe { Box::from_raw(p as *mut SnmpVariable) };
|
||||||
|
//}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
//#[allow(non_snake_case)]
|
||||||
#[no_mangle]
|
//#[no_mangle]
|
||||||
pub extern "C" fn snmpresult_variables_count(p: *mut CSnmpResult) -> usize {
|
//pub extern "C" fn snmpvariable_get_name(p: *mut CSnmpVariable) -> *mut c_char {
|
||||||
let p = p as *mut SnmpResult;
|
// let p = p as *mut SnmpVariable;
|
||||||
let p = unsafe { &mut *p };
|
// let p = unsafe { &mut *p };
|
||||||
p.variables.len()
|
// let c = CString::new(p.name.clone()).unwrap();
|
||||||
}
|
// c.into_raw()
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//#[allow(non_snake_case)]
|
||||||
|
//#[no_mangle]
|
||||||
|
//pub extern "C" fn snmpvariable_get_value(p: *mut CSnmpVariable) -> *mut c_char {
|
||||||
|
// let p = p as *mut SnmpVariable;
|
||||||
|
// let p = unsafe { &mut *p };
|
||||||
|
// let c = CString::new(p.value.clone()).unwrap();
|
||||||
|
// c.into_raw()
|
||||||
|
//}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
//#[no_mangle]
|
||||||
#[no_mangle]
|
//pub extern "C" fn snmp_get(target: *const c_char, oid: *const c_char) -> *mut CSnmpResult {
|
||||||
pub extern "C" fn snmpvariable_DESTROY(p: *mut CSnmpVariable) {
|
// if target.is_null() {
|
||||||
unsafe { Box::from_raw(p as *mut SnmpVariable) };
|
// return Box::into_raw(Box::new(SnmpResult::new())) as *mut CSnmpResult;
|
||||||
}
|
// }
|
||||||
|
// let target = unsafe { CStr::from_ptr(target) };
|
||||||
#[allow(non_snake_case)]
|
// let target = match target.to_str() {
|
||||||
#[no_mangle]
|
// Ok(s) => s,
|
||||||
pub extern "C" fn snmpvariable_get_name(p: *mut CSnmpVariable) -> *mut c_char {
|
// Err(_) => "",
|
||||||
let p = p as *mut SnmpVariable;
|
// };
|
||||||
let p = unsafe { &mut *p };
|
//
|
||||||
let c = CString::new(p.name.clone()).unwrap();
|
// if oid.is_null() {
|
||||||
c.into_raw()
|
// return Box::into_raw(Box::new(SnmpResult::new())) as *mut CSnmpResult;
|
||||||
}
|
// }
|
||||||
|
// let oid = unsafe { CStr::from_ptr(oid) };
|
||||||
#[allow(non_snake_case)]
|
// let oid = match oid.to_str() {
|
||||||
#[no_mangle]
|
// Ok(s) => s,
|
||||||
pub extern "C" fn snmpvariable_get_value(p: *mut CSnmpVariable) -> *mut c_char {
|
// Err(_) => "",
|
||||||
let p = p as *mut SnmpVariable;
|
// };
|
||||||
let p = unsafe { &mut *p };
|
//
|
||||||
let c = CString::new(p.value.clone()).unwrap();
|
// Box::into_raw(Box::new(r_snmp_get(target, oid, "public"))) as *mut CSnmpResult
|
||||||
c.into_raw()
|
//}
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn snmp_get(target: *const c_char, oid: *const c_char) -> *mut CSnmpResult {
|
|
||||||
if target.is_null() {
|
|
||||||
return Box::into_raw(Box::new(SnmpResult::new())) as *mut CSnmpResult;
|
|
||||||
}
|
|
||||||
let target = unsafe { CStr::from_ptr(target) };
|
|
||||||
let target = match target.to_str() {
|
|
||||||
Ok(s) => s,
|
|
||||||
Err(_) => "",
|
|
||||||
};
|
|
||||||
|
|
||||||
if oid.is_null() {
|
|
||||||
return Box::into_raw(Box::new(SnmpResult::new())) as *mut CSnmpResult;
|
|
||||||
}
|
|
||||||
let oid = unsafe { CStr::from_ptr(oid) };
|
|
||||||
let oid = match oid.to_str() {
|
|
||||||
Ok(s) => s,
|
|
||||||
Err(_) => "",
|
|
||||||
};
|
|
||||||
|
|
||||||
Box::into_raw(Box::new(r_snmp_get(target, oid, "public"))) as *mut CSnmpResult
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn r_snmp_get(target: &str, oid: &str, community: &str) -> SnmpResult {
|
pub fn r_snmp_get(target: &str, oid: &str, community: &str) -> SnmpResult {
|
||||||
let oid_tab = oid
|
let oid_tab = oid
|
||||||
@ -175,27 +183,27 @@ pub fn r_snmp_get(target: &str, oid: &str, community: &str) -> SnmpResult {
|
|||||||
build_response(decoded, false).0
|
build_response(decoded, false).0
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
//#[no_mangle]
|
||||||
pub extern "C" fn snmp_walk(target: *const c_char, oid: *const c_char) -> *mut CSnmpResult {
|
//pub extern "C" fn snmp_walk(target: *const c_char, oid: *const c_char) -> *mut CSnmpResult {
|
||||||
if target.is_null() {
|
// if target.is_null() {
|
||||||
return Box::into_raw(Box::new(SnmpResult::new())) as *mut CSnmpResult;
|
// return Box::into_raw(Box::new(SnmpResult::new())) as *mut CSnmpResult;
|
||||||
}
|
// }
|
||||||
let target = unsafe { CStr::from_ptr(target) };
|
// let target = unsafe { CStr::from_ptr(target) };
|
||||||
let target = match target.to_str() {
|
// let target = match target.to_str() {
|
||||||
Ok(s) => s,
|
// Ok(s) => s,
|
||||||
Err(_) => "",
|
// Err(_) => "",
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
if oid.is_null() {
|
// if oid.is_null() {
|
||||||
return Box::into_raw(Box::new(SnmpResult::new())) as *mut CSnmpResult;
|
// return Box::into_raw(Box::new(SnmpResult::new())) as *mut CSnmpResult;
|
||||||
}
|
// }
|
||||||
let oid = unsafe { CStr::from_ptr(oid) };
|
// let oid = unsafe { CStr::from_ptr(oid) };
|
||||||
let oid = match oid.to_str() {
|
// let oid = match oid.to_str() {
|
||||||
Ok(s) => s,
|
// Ok(s) => s,
|
||||||
Err(_) => "",
|
// Err(_) => "",
|
||||||
};
|
// };
|
||||||
Box::into_raw(Box::new(r_snmp_walk(target, oid))) as *mut CSnmpResult
|
// Box::into_raw(Box::new(r_snmp_walk(target, oid))) as *mut CSnmpResult
|
||||||
}
|
//}
|
||||||
|
|
||||||
pub fn r_snmp_walk(target: &str, oid: &str) -> SnmpResult {
|
pub fn r_snmp_walk(target: &str, oid: &str) -> SnmpResult {
|
||||||
let community = "public";
|
let community = "public";
|
||||||
@ -258,6 +266,87 @@ pub fn r_snmp_walk(target: &str, oid: &str) -> SnmpResult {
|
|||||||
retval
|
retval
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Bulk get
|
||||||
|
/// This function is similar to the get function but it uses the GetBulkRequest PDU
|
||||||
|
/// to retrieve multiple values at once.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
/// * `target` - The target IP address and port
|
||||||
|
/// * `oid` - The OID to walk
|
||||||
|
/// # Returns
|
||||||
|
/// An SnmpResult structure containing the variables
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// use snmp_rust::r_snmp_bulk_get;
|
||||||
|
/// let result = r_snmp_bulk_get("127.0.0.1:161", "2c", "public", "1.3.6.1.2.1.25.3.3.1.2");
|
||||||
|
/// ```
|
||||||
|
pub fn r_snmp_bulk_get(target: &str, _version: &str, community: &str, oid: &str) -> SnmpResult {
|
||||||
|
let mut oid_tab = oid
|
||||||
|
.split('.')
|
||||||
|
.map(|x| x.parse::<u32>().unwrap())
|
||||||
|
.collect::<Vec<u32>>();
|
||||||
|
|
||||||
|
let mut retval = SnmpResult::new();
|
||||||
|
let mut request_id: i32 = 1;
|
||||||
|
|
||||||
|
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||||
|
socket.connect(target).expect("connect function failed");
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let variable_bindings = vec![VarBind {
|
||||||
|
name: ObjectIdentifier::new_unchecked(oid_tab.to_vec().into()),
|
||||||
|
value: VarBindValue::Unspecified,
|
||||||
|
}];
|
||||||
|
|
||||||
|
let pdu = BulkPdu {
|
||||||
|
request_id,
|
||||||
|
non_repeaters: 0,
|
||||||
|
max_repetitions: 10,
|
||||||
|
variable_bindings,
|
||||||
|
};
|
||||||
|
|
||||||
|
let get_request: GetBulkRequest = GetBulkRequest(pdu);
|
||||||
|
|
||||||
|
let message: Message<GetBulkRequest> = Message {
|
||||||
|
version: 1.into(),
|
||||||
|
community: community.to_string().into(),
|
||||||
|
data: get_request.into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Send the message through an UDP socket
|
||||||
|
let encoded: Vec<u8> = rasn::der::encode(&message).unwrap();
|
||||||
|
let res: usize = socket.send(&encoded).unwrap();
|
||||||
|
assert!(res == encoded.len());
|
||||||
|
|
||||||
|
let mut buf: [u8; 1024] = [0; 1024];
|
||||||
|
let resp: (usize, std::net::SocketAddr) = socket.recv_from(buf.as_mut_slice()).unwrap();
|
||||||
|
|
||||||
|
trace!("Received {} bytes", resp.0);
|
||||||
|
assert!(resp.0 > 0);
|
||||||
|
let decoded: Message<Pdus> = rasn::ber::decode(&buf[0..resp.0]).unwrap();
|
||||||
|
if let Pdus::Response(resp) = &decoded.data {
|
||||||
|
let resp_oid = &resp.0.variable_bindings[0].name;
|
||||||
|
let n = resp_oid.len() - 1;
|
||||||
|
}
|
||||||
|
let (result, completed) = build_response(decoded, true);
|
||||||
|
retval.concat(result);
|
||||||
|
if completed {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
oid_tab = retval
|
||||||
|
.variables
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
.name
|
||||||
|
.split('.')
|
||||||
|
.map(|x| x.parse::<u32>().unwrap())
|
||||||
|
.collect::<Vec<u32>>();
|
||||||
|
}
|
||||||
|
retval
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Bulk walk
|
/// Bulk walk
|
||||||
/// This function is similar to the walk function but it uses the GetBulkRequest PDU
|
/// This function is similar to the walk function but it uses the GetBulkRequest PDU
|
||||||
@ -378,17 +467,18 @@ fn build_response(decoded: Message<Pdus>, walk: bool) -> (SnmpResult, bool) {
|
|||||||
info!("Simple {:?}", value);
|
info!("Simple {:?}", value);
|
||||||
match value {
|
match value {
|
||||||
rasn_smi::v2::SimpleSyntax::Integer(value) => {
|
rasn_smi::v2::SimpleSyntax::Integer(value) => {
|
||||||
retval.add_variable(name, value.to_string());
|
let v = value.try_into().unwrap();
|
||||||
|
retval.add_variable(name, SnmpValue::Integer(v));
|
||||||
}
|
}
|
||||||
rasn_smi::v2::SimpleSyntax::String(value) => {
|
rasn_smi::v2::SimpleSyntax::String(value) => {
|
||||||
// We transform the value into a rust String
|
// We transform the value into a rust String
|
||||||
retval.add_variable(
|
retval.add_variable(
|
||||||
name,
|
name,
|
||||||
String::from_utf8(value.to_vec()).unwrap(),
|
SnmpValue::String(String::from_utf8(value.to_vec()).unwrap()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
retval.add_variable(name, String::from("Other"));
|
retval.add_variable(name, SnmpValue::String("Other".to_string()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user