mirror of
https://github.com/centreon/centreon-plugins.git
synced 2025-07-31 01:24:35 +02:00
wip(generic-snmp): labels on the way
This commit is contained in:
parent
679d222759
commit
1e69310f40
@ -2,7 +2,7 @@ extern crate serde;
|
||||
extern crate serde_json;
|
||||
|
||||
use serde::Deserialize;
|
||||
use snmp::{r_snmp_bulk_get, r_snmp_bulk_walk, SnmpResult, SnmpValue};
|
||||
use snmp::{snmp_bulk_get, snmp_bulk_walk, SnmpResult, SnmpValue};
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
@ -71,6 +71,7 @@ pub struct Snmp {
|
||||
name: String,
|
||||
oid: String,
|
||||
query: QueryType,
|
||||
labels: Option<BTreeMap<String, String>>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
@ -188,7 +189,7 @@ impl Command {
|
||||
for s in self.collect.snmp.iter() {
|
||||
match s.query {
|
||||
QueryType::Walk => {
|
||||
let r = r_snmp_bulk_walk(target, version, community, &s.oid);
|
||||
let r = snmp_bulk_walk(target, version, community, &s.oid);
|
||||
match r.variables.len() {
|
||||
1 => {
|
||||
let result = r.variables.get(0).unwrap();
|
||||
@ -212,7 +213,7 @@ impl Command {
|
||||
}
|
||||
}
|
||||
if !to_get.is_empty() {
|
||||
let r = r_snmp_bulk_get(target, version, community, 1, 1, &to_get);
|
||||
let r = snmp_bulk_get(target, version, community, 1, 1, &to_get);
|
||||
for (idx, result) in r.variables.iter().enumerate() {
|
||||
if let SnmpValue::Integer(v) = result.value {
|
||||
res.insert(get_name[idx].to_string(), v);
|
||||
@ -231,7 +232,7 @@ impl Command {
|
||||
// QueryType::Walk => {
|
||||
// res = Some((
|
||||
// &query.name,
|
||||
// r_snmp_bulk_walk(target, version, community, &query.oid),
|
||||
// snmp_bulk_walk(target, version, community, &query.oid),
|
||||
// ));
|
||||
// }
|
||||
// },
|
||||
|
@ -4,7 +4,6 @@ extern crate rasn_smi;
|
||||
extern crate rasn_snmp;
|
||||
|
||||
use log::{info, trace, warn};
|
||||
use rasn::types::IntegerType;
|
||||
use rasn::types::ObjectIdentifier;
|
||||
use rasn_snmp::v2::Pdus;
|
||||
use rasn_snmp::v2::VarBind;
|
||||
@ -12,18 +11,21 @@ use rasn_snmp::v2::VarBindValue;
|
||||
use rasn_snmp::v2::{BulkPdu, Pdu};
|
||||
use rasn_snmp::v2::{GetBulkRequest, GetNextRequest, GetRequest};
|
||||
use rasn_snmp::v2c::Message;
|
||||
use std::collections::BTreeMap;
|
||||
use std::convert::TryInto;
|
||||
use std::ffi::CStr;
|
||||
use std::ffi::CString;
|
||||
use std::net::UdpSocket;
|
||||
use std::os::raw::{c_char, c_void};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct SnmpResult {
|
||||
pub struct SnmpSubResult<'a> {
|
||||
pub label: &'a str,
|
||||
pub value: &'a str,
|
||||
pub variables: Vec<SnmpVariable>,
|
||||
}
|
||||
|
||||
type CSnmpVariable = c_void;
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct SnmpResult<'a> {
|
||||
pub labels: Vec<SnmpSubResult<'a>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum SnmpValue {
|
||||
@ -43,233 +45,162 @@ impl SnmpVariable {
|
||||
}
|
||||
}
|
||||
|
||||
type CSnmpResult = c_void;
|
||||
|
||||
impl SnmpResult {
|
||||
fn new() -> SnmpResult {
|
||||
SnmpResult {
|
||||
impl<'a> SnmpResult<'a> {
|
||||
fn new(labels: &'a BTreeMap<String, String>) -> SnmpResult<'a> {
|
||||
let mut retval: Vec<SnmpSubResult> = Vec::new();
|
||||
retval.reserve(labels.len());
|
||||
for (label, value) in labels.iter() {
|
||||
let item = SnmpSubResult {
|
||||
label: &label,
|
||||
value: &value,
|
||||
variables: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn add_variable(&mut self, name: String, value: SnmpValue) {
|
||||
self.variables.push(SnmpVariable::new(name, value));
|
||||
}
|
||||
|
||||
fn concat(&mut self, other: SnmpResult) {
|
||||
self.variables.extend(other.variables);
|
||||
}
|
||||
}
|
||||
|
||||
//#[allow(non_snake_case)]
|
||||
//#[no_mangle]
|
||||
//pub extern "C" fn snmpresult_DESTROY(p: *mut CSnmpResult) {
|
||||
// unsafe { Box::from_raw(p as *mut SnmpResult) };
|
||||
//}
|
||||
|
||||
//#[allow(non_snake_case)]
|
||||
//#[no_mangle]
|
||||
//pub extern "C" fn snmpresult_get_variable(p: *mut CSnmpResult, index: usize) -> *mut CSnmpVariable {
|
||||
// trace!("snmpresult_get_variable {}", index);
|
||||
// let p = p as *mut SnmpResult;
|
||||
// let p = unsafe { &mut *p };
|
||||
// if index >= p.variables.len() {
|
||||
// return Box::into_raw(Box::new(SnmpVariable::new("".to_string(), "".to_string())))
|
||||
// as *mut CSnmpVariable;
|
||||
// }
|
||||
// let v = &p.variables[index];
|
||||
// Box::into_raw(Box::new(SnmpVariable {
|
||||
// name: v.name.clone(),
|
||||
// value: v.value.clone(),
|
||||
// })) 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)]
|
||||
//#[no_mangle]
|
||||
//pub extern "C" fn snmpvariable_get_name(p: *mut CSnmpVariable) -> *mut c_char {
|
||||
// let p = p as *mut SnmpVariable;
|
||||
// let p = unsafe { &mut *p };
|
||||
// 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()
|
||||
//}
|
||||
|
||||
//#[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 {
|
||||
let oid_tab = oid
|
||||
.split('.')
|
||||
.map(|x| x.parse::<u32>().unwrap())
|
||||
.collect::<Vec<u32>>();
|
||||
|
||||
let request_id = 1;
|
||||
|
||||
let variable_bindings = vec![VarBind {
|
||||
name: ObjectIdentifier::new_unchecked(oid_tab.into()),
|
||||
value: VarBindValue::Unspecified,
|
||||
}];
|
||||
|
||||
let pdu = Pdu {
|
||||
request_id,
|
||||
error_status: 0,
|
||||
error_index: 0,
|
||||
variable_bindings,
|
||||
};
|
||||
|
||||
let get_request = GetRequest(pdu);
|
||||
|
||||
let message: rasn_snmp::v2c::Message<GetRequest> = Message {
|
||||
version: 1.into(),
|
||||
community: community.to_string().into(),
|
||||
data: get_request.into(),
|
||||
};
|
||||
|
||||
// Send the message through an UDP socket
|
||||
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||
socket.connect(target).expect("connect function failed");
|
||||
let duration = std::time::Duration::from_millis(1000);
|
||||
socket.set_read_timeout(Some(duration)).unwrap();
|
||||
|
||||
let encoded = rasn::der::encode(&message).unwrap();
|
||||
let res = socket.send(&encoded).unwrap();
|
||||
assert!(res == encoded.len());
|
||||
|
||||
let mut buf = [0; 1024];
|
||||
let resp = 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();
|
||||
build_response(decoded, "", false).0
|
||||
retval.push(item);
|
||||
}
|
||||
SnmpResult { labels: retval }
|
||||
}
|
||||
|
||||
//#[no_mangle]
|
||||
//pub extern "C" fn snmp_walk(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_walk(target, oid))) as *mut CSnmpResult
|
||||
//}
|
||||
|
||||
pub fn r_snmp_walk(target: &str, oid: &str) -> SnmpResult {
|
||||
let community = "public";
|
||||
let 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 create_next_request = |id: i32, oid: &[u32]| -> Message<GetNextRequest> {
|
||||
let variable_bindings = vec![VarBind {
|
||||
name: ObjectIdentifier::new_unchecked(oid.to_vec().into()),
|
||||
value: VarBindValue::Unspecified,
|
||||
}];
|
||||
|
||||
let pdu = Pdu {
|
||||
request_id: id,
|
||||
error_status: 0,
|
||||
error_index: 0,
|
||||
variable_bindings,
|
||||
};
|
||||
let get_request: GetNextRequest = GetNextRequest(pdu);
|
||||
|
||||
Message {
|
||||
version: 1.into(),
|
||||
community: community.into(),
|
||||
data: get_request.into(),
|
||||
fn new_simple() -> SnmpResult<'a> {
|
||||
let label = SnmpSubResult{label: "", value: "", variables: Vec::new() };
|
||||
SnmpResult { labels: vec![label], }
|
||||
}
|
||||
};
|
||||
|
||||
let mut message = create_next_request(request_id, &oid_tab);
|
||||
// Send the message through an UDP socket
|
||||
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||
socket.connect(target).expect("connect function failed");
|
||||
let duration = std::time::Duration::from_millis(1000);
|
||||
socket.set_read_timeout(Some(duration)).unwrap();
|
||||
fn add_variable(&mut self, idx: usize, name: String, value: SnmpValue) {
|
||||
self.labels[idx].variables.push(SnmpVariable::new(name, value));
|
||||
}
|
||||
|
||||
loop {
|
||||
let encoded: Vec<u8> = rasn::der::encode(&message).unwrap();
|
||||
let res: usize = socket.send(&encoded).unwrap();
|
||||
assert!(res == encoded.len());
|
||||
fn get_last_oid(&self, idx: usize) -> &str {
|
||||
if self.labels.is_empty() {
|
||||
return "";
|
||||
}
|
||||
let last = self.labels[idx].variables.iter().last().unwrap();
|
||||
if last.name.is_empty() {
|
||||
return "";
|
||||
}
|
||||
last.name.as_str()
|
||||
}
|
||||
|
||||
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;
|
||||
if resp_oid[0..n] != oid_tab[0..n] {
|
||||
fn concat(&mut self, mut other: SnmpResult) {
|
||||
for v in other.labels.iter_mut() {
|
||||
for vv in self.labels.iter_mut() {
|
||||
if v.label == vv.label {
|
||||
vv.variables.extend(v.variables);
|
||||
break;
|
||||
}
|
||||
message = create_next_request(request_id, &resp_oid);
|
||||
}
|
||||
retval.concat(build_response(decoded, &oid, true).0);
|
||||
request_id += 1;
|
||||
}
|
||||
retval
|
||||
}
|
||||
}
|
||||
|
||||
//pub fn snmp_get(target: &str, oid: &str, community: &str) -> SnmpResult {
|
||||
// let oid_tab = oid
|
||||
// .split('.')
|
||||
// .map(|x| x.parse::<u32>().unwrap())
|
||||
// .collect::<Vec<u32>>();
|
||||
//
|
||||
// let request_id = 1;
|
||||
//
|
||||
// let variable_bindings = vec![VarBind {
|
||||
// name: ObjectIdentifier::new_unchecked(oid_tab.into()),
|
||||
// value: VarBindValue::Unspecified,
|
||||
// }];
|
||||
//
|
||||
// let pdu = Pdu {
|
||||
// request_id,
|
||||
// error_status: 0,
|
||||
// error_index: 0,
|
||||
// variable_bindings,
|
||||
// };
|
||||
//
|
||||
// let get_request = GetRequest(pdu);
|
||||
//
|
||||
// let message: rasn_snmp::v2c::Message<GetRequest> = Message {
|
||||
// version: 1.into(),
|
||||
// community: community.to_string().into(),
|
||||
// data: get_request.into(),
|
||||
// };
|
||||
//
|
||||
// // Send the message through an UDP socket
|
||||
// let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||
// socket.connect(target).expect("connect function failed");
|
||||
// let duration = std::time::Duration::from_millis(1000);
|
||||
// socket.set_read_timeout(Some(duration)).unwrap();
|
||||
//
|
||||
// let encoded = rasn::der::encode(&message).unwrap();
|
||||
// let res = socket.send(&encoded).unwrap();
|
||||
// assert!(res == encoded.len());
|
||||
//
|
||||
// let mut buf = [0; 1024];
|
||||
// let resp = 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();
|
||||
// build_response(decoded, "", {}, false).0
|
||||
//}
|
||||
|
||||
//pub fn snmp_walk(target: &str, oid: &str) -> SnmpResult {
|
||||
// let community = "public";
|
||||
// let 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 create_next_request = |id: i32, oid: &[u32]| -> Message<GetNextRequest> {
|
||||
// let variable_bindings = vec![VarBind {
|
||||
// name: ObjectIdentifier::new_unchecked(oid.to_vec().into()),
|
||||
// value: VarBindValue::Unspecified,
|
||||
// }];
|
||||
//
|
||||
// let pdu = Pdu {
|
||||
// request_id: id,
|
||||
// error_status: 0,
|
||||
// error_index: 0,
|
||||
// variable_bindings,
|
||||
// };
|
||||
// let get_request: GetNextRequest = GetNextRequest(pdu);
|
||||
//
|
||||
// Message {
|
||||
// version: 1.into(),
|
||||
// community: community.into(),
|
||||
// data: get_request.into(),
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// let mut message = create_next_request(request_id, &oid_tab);
|
||||
// // Send the message through an UDP socket
|
||||
// let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||
// socket.connect(target).expect("connect function failed");
|
||||
// let duration = std::time::Duration::from_millis(1000);
|
||||
// socket.set_read_timeout(Some(duration)).unwrap();
|
||||
//
|
||||
// loop {
|
||||
// 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;
|
||||
// if resp_oid[0..n] != oid_tab[0..n] {
|
||||
// break;
|
||||
// }
|
||||
// message = create_next_request(request_id, &resp_oid);
|
||||
// }
|
||||
// retval.concat(build_response(decoded, &oid, true).0);
|
||||
// request_id += 1;
|
||||
// }
|
||||
// retval
|
||||
//}
|
||||
|
||||
///
|
||||
/// Bulk get
|
||||
@ -285,71 +216,71 @@ pub fn r_snmp_walk(target: &str, oid: &str) -> SnmpResult {
|
||||
/// # 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");
|
||||
/// let result = 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,
|
||||
non_repeaters: u32,
|
||||
max_repetitions: u32,
|
||||
oid: &Vec<&str>,
|
||||
) -> SnmpResult {
|
||||
let mut oids_tab = oid
|
||||
.iter()
|
||||
.map(|x| {
|
||||
x.split('.')
|
||||
.map(|x| x.parse::<u32>().unwrap())
|
||||
.collect::<Vec<u32>>()
|
||||
})
|
||||
.collect::<Vec<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");
|
||||
let duration = std::time::Duration::from_millis(1000);
|
||||
socket.set_read_timeout(Some(duration)).unwrap();
|
||||
|
||||
let variable_bindings = oids_tab
|
||||
.iter()
|
||||
.map(|x| VarBind {
|
||||
name: ObjectIdentifier::new_unchecked(x.to_vec().into()),
|
||||
value: VarBindValue::Unspecified,
|
||||
})
|
||||
.collect::<Vec<VarBind>>();
|
||||
|
||||
let pdu = BulkPdu {
|
||||
request_id,
|
||||
non_repeaters,
|
||||
max_repetitions,
|
||||
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();
|
||||
let (result, _completed) = build_response(decoded, "", false);
|
||||
retval.concat(result);
|
||||
retval
|
||||
}
|
||||
//pub fn snmp_bulk_get(
|
||||
// target: &str,
|
||||
// _version: &str,
|
||||
// community: &str,
|
||||
// non_repeaters: u32,
|
||||
// max_repetitions: u32,
|
||||
// oid: &Vec<&str>,
|
||||
//) -> SnmpResult {
|
||||
// let mut oids_tab = oid
|
||||
// .iter()
|
||||
// .map(|x| {
|
||||
// x.split('.')
|
||||
// .map(|x| x.parse::<u32>().unwrap())
|
||||
// .collect::<Vec<u32>>()
|
||||
// })
|
||||
// .collect::<Vec<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");
|
||||
// let duration = std::time::Duration::from_millis(1000);
|
||||
// socket.set_read_timeout(Some(duration)).unwrap();
|
||||
//
|
||||
// let variable_bindings = oids_tab
|
||||
// .iter()
|
||||
// .map(|x| VarBind {
|
||||
// name: ObjectIdentifier::new_unchecked(x.to_vec().into()),
|
||||
// value: VarBindValue::Unspecified,
|
||||
// })
|
||||
// .collect::<Vec<VarBind>>();
|
||||
//
|
||||
// let pdu = BulkPdu {
|
||||
// request_id,
|
||||
// non_repeaters,
|
||||
// max_repetitions,
|
||||
// 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();
|
||||
// let (result, _completed) = build_response(decoded, "", false);
|
||||
// retval.concat(result);
|
||||
// retval
|
||||
//}
|
||||
|
||||
///
|
||||
/// Bulk walk
|
||||
@ -364,17 +295,92 @@ pub fn r_snmp_bulk_get(
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use snmp_rust::r_snmp_bulk_walk;
|
||||
/// let result = r_snmp_bulk_walk("127.0.0.1:161", "2c", "public", "1.3.6.1.2.1.25.3.3.1.2");
|
||||
/// use snmp_rust::snmp_bulk_walk;
|
||||
/// let result = snmp_bulk_walk("127.0.0.1:161", "2c", "public", "1.3.6.1.2.1.25.3.3.1.2");
|
||||
/// ```
|
||||
pub fn r_snmp_bulk_walk(target: &str, _version: &str, community: &str, oid: &str) -> SnmpResult {
|
||||
//pub fn snmp_bulk_walk(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_simple();
|
||||
// let mut request_id: i32 = 1;
|
||||
//
|
||||
// let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||
// socket.connect(target).expect("connect function failed");
|
||||
// let duration = std::time::Duration::from_millis(1000);
|
||||
// socket.set_read_timeout(Some(duration)).unwrap();
|
||||
//
|
||||
// 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, &oid, true);
|
||||
// retval.concat(result);
|
||||
// if completed {
|
||||
// break;
|
||||
// }
|
||||
// if !retval.variables.is_empty() {
|
||||
// oid_tab = retval
|
||||
// .variables
|
||||
// .last()
|
||||
// .unwrap()
|
||||
// .name
|
||||
// .split('.')
|
||||
// .map(|x| x.parse::<u32>().unwrap())
|
||||
// .collect::<Vec<u32>>();
|
||||
// }
|
||||
// }
|
||||
// retval
|
||||
//}
|
||||
|
||||
pub fn snmp_bulk_walk_with_labels<'a>(
|
||||
target: &str,
|
||||
_version: &str,
|
||||
community: &str,
|
||||
oid: &str,
|
||||
labels: &'a BTreeMap<String, String>,
|
||||
) -> SnmpResult<'a> {
|
||||
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 mut retval = SnmpResult::new(&labels);
|
||||
let request_id: i32 = 1;
|
||||
|
||||
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||
socket.connect(target).expect("connect function failed");
|
||||
@ -416,27 +422,28 @@ pub fn r_snmp_bulk_walk(target: &str, _version: &str, community: &str, oid: &str
|
||||
if let Pdus::Response(resp) = &decoded.data {
|
||||
let resp_oid = &resp.0.variable_bindings[0].name;
|
||||
let n = resp_oid.len() - 1;
|
||||
oid_tab = resp.0.variable_bindings[n - 1].name.to_string().split('.')
|
||||
.map(|x| x.parse::<u32>().unwrap())
|
||||
.collect::<Vec<u32>>();
|
||||
}
|
||||
let (result, completed) = build_response(decoded, &oid, true);
|
||||
let (result, completed) = build_response_with_labels(decoded, &oid, labels, 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
|
||||
}
|
||||
|
||||
fn build_response(decoded: Message<Pdus>, oid: &str, walk: bool) -> (SnmpResult, bool) {
|
||||
let mut retval = SnmpResult::new();
|
||||
fn build_response_with_labels<'a>(
|
||||
decoded: Message<Pdus>,
|
||||
oid: &str,
|
||||
labels: &'a BTreeMap<String, String>,
|
||||
walk: bool,
|
||||
) -> (SnmpResult<'a>, bool) {
|
||||
let mut retval = SnmpResult::new(labels);
|
||||
let mut completed = false;
|
||||
let mut last_oid: &str = "";
|
||||
|
||||
if let Pdus::Response(resp) = &decoded.data {
|
||||
let vars = &resp.0.variable_bindings;
|
||||
@ -445,9 +452,20 @@ fn build_response(decoded: Message<Pdus>, oid: &str, walk: bool) -> (SnmpResult,
|
||||
if walk {
|
||||
if !name.starts_with(oid) {
|
||||
completed = true;
|
||||
last_oid = "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
let mut idx: i32 = -1;
|
||||
retval.labels.iter().enumerate().for_each(|label| {
|
||||
if name.ends_with(label.1.label) {
|
||||
idx = label.0 as i32;
|
||||
return;
|
||||
}
|
||||
});
|
||||
if idx == -1 {
|
||||
continue;
|
||||
}
|
||||
match &var.value {
|
||||
VarBindValue::Unspecified => {
|
||||
warn!("Unspecified");
|
||||
@ -469,20 +487,30 @@ fn build_response(decoded: Message<Pdus>, oid: &str, walk: bool) -> (SnmpResult,
|
||||
match value {
|
||||
rasn_smi::v2::SimpleSyntax::Integer(value) => {
|
||||
let v = value.try_into().unwrap();
|
||||
retval.add_variable(name, SnmpValue::Integer(v));
|
||||
retval.add_variable(idx as usize, name, SnmpValue::Integer(v));
|
||||
last_oid = retval.get_last_oid(idx as usize);
|
||||
}
|
||||
rasn_smi::v2::SimpleSyntax::String(value) => {
|
||||
// We transform the value into a rust String
|
||||
retval.add_variable(
|
||||
idx as usize,
|
||||
name,
|
||||
SnmpValue::String(
|
||||
String::from_utf8(value.to_vec()).unwrap(),
|
||||
),
|
||||
);
|
||||
last_oid = retval.get_last_oid(idx as usize);
|
||||
}
|
||||
rasn_smi::v2::SimpleSyntax::ObjectId(value) => {
|
||||
let oid: String =
|
||||
value.iter().map(|&id| id.to_string() + ".").collect();
|
||||
retval.add_variable(idx as usize, name, SnmpValue::String(oid));
|
||||
last_oid = retval.get_last_oid(idx as usize);
|
||||
}
|
||||
_ => {
|
||||
retval
|
||||
.add_variable(name, SnmpValue::String("Other".to_string()));
|
||||
.add_variable(idx as usize, name, SnmpValue::String("Other".to_string()));
|
||||
last_oid = retval.get_last_oid(idx as usize);
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -497,6 +525,93 @@ fn build_response(decoded: Message<Pdus>, oid: &str, walk: bool) -> (SnmpResult,
|
||||
(retval, completed)
|
||||
}
|
||||
|
||||
fn build_response<'a>(
|
||||
decoded: Message<Pdus>,
|
||||
oid: &str,
|
||||
walk: bool,
|
||||
) -> (SnmpResult<'a>, bool) {
|
||||
let mut retval = SnmpResult::new_simple();
|
||||
let mut completed = false;
|
||||
let mut last_oid: &str = "";
|
||||
|
||||
if let Pdus::Response(resp) = &decoded.data {
|
||||
let vars = &resp.0.variable_bindings;
|
||||
for var in vars {
|
||||
let name = var.name.to_string();
|
||||
if walk {
|
||||
if !name.starts_with(oid) {
|
||||
completed = true;
|
||||
last_oid = "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
let mut idx: i32 = -1;
|
||||
retval.labels.iter().enumerate().for_each(|label| {
|
||||
if name.ends_with(label.1.label) {
|
||||
idx = label.0 as i32;
|
||||
return;
|
||||
}
|
||||
});
|
||||
if idx == -1 {
|
||||
continue;
|
||||
}
|
||||
match &var.value {
|
||||
VarBindValue::Unspecified => {
|
||||
warn!("Unspecified");
|
||||
}
|
||||
VarBindValue::NoSuchObject => {
|
||||
warn!("NoSuchObject");
|
||||
}
|
||||
VarBindValue::NoSuchInstance => {
|
||||
warn!("NoSuchInstance");
|
||||
}
|
||||
VarBindValue::EndOfMibView => {
|
||||
warn!("EndOfMibView");
|
||||
}
|
||||
VarBindValue::Value(value) => {
|
||||
warn!("Value {:?}", &value);
|
||||
match value {
|
||||
rasn_smi::v2::ObjectSyntax::Simple(value) => {
|
||||
info!("Simple {:?}", value);
|
||||
match value {
|
||||
rasn_smi::v2::SimpleSyntax::Integer(value) => {
|
||||
let v = value.try_into().unwrap();
|
||||
retval.add_variable(idx as usize, name, SnmpValue::Integer(v));
|
||||
last_oid = retval.get_last_oid(idx as usize);
|
||||
}
|
||||
rasn_smi::v2::SimpleSyntax::String(value) => {
|
||||
// We transform the value into a rust String
|
||||
retval.add_variable(idx as usize,
|
||||
name,
|
||||
SnmpValue::String(
|
||||
String::from_utf8(value.to_vec()).unwrap(),
|
||||
),
|
||||
);
|
||||
last_oid = retval.get_last_oid(idx as usize);
|
||||
}
|
||||
rasn_smi::v2::SimpleSyntax::ObjectId(value) => {
|
||||
let oid: String =
|
||||
value.iter().map(|&id| id.to_string() + ".").collect();
|
||||
retval.add_variable(idx as usize, name, SnmpValue::String(oid));
|
||||
last_oid = retval.get_last_oid(idx as usize);
|
||||
}
|
||||
_ => {
|
||||
retval
|
||||
.add_variable(idx as usize, name, SnmpValue::String("Other".to_string()));
|
||||
last_oid = retval.get_last_oid(idx as usize);
|
||||
}
|
||||
};
|
||||
}
|
||||
rasn_smi::v2::ObjectSyntax::ApplicationWide(value) => {
|
||||
info!("Application {:?}", value);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
(retval, completed)
|
||||
}
|
||||
//mod tests {
|
||||
// use super::*;
|
||||
//
|
||||
|
Loading…
x
Reference in New Issue
Block a user