Commit a9fadfc3 authored by Michael Ott's avatar Michael Ott
Browse files

Switch to single session net-snmp API to ensure thread safety in the SNMP plugin

parent e2426341
...@@ -27,6 +27,7 @@ SNMPConnection::SNMPConnection() { ...@@ -27,6 +27,7 @@ SNMPConnection::SNMPConnection() {
_snmpSession.peername = NULL; _snmpSession.peername = NULL;
_snmpSession.community_len = 0; _snmpSession.community_len = 0;
_snmpSession.securityNameLen = 0; _snmpSession.securityNameLen = 0;
_snmpSessp = NULL;
_strand = NULL; _strand = NULL;
} }
...@@ -60,6 +61,13 @@ void SNMPConnection::init() { ...@@ -60,6 +61,13 @@ void SNMPConnection::init() {
} }
snmp_sess_init(&_snmpSession); snmp_sess_init(&_snmpSession);
int liberr, syserr;
char *errstr;
snmp_error(&_snmpSession, &liberr, &syserr, &errstr);
if (liberr || syserr) {
LOG(error) << "SNMP: Error initializing session: " + std::string(errstr);
free(errstr);
}
_snmpSession.version = _version; _snmpSession.version = _version;
_snmpSession.peername = strdup(_host.c_str()); _snmpSession.peername = strdup(_host.c_str());
...@@ -122,24 +130,43 @@ void SNMPConnection::init() { ...@@ -122,24 +130,43 @@ void SNMPConnection::init() {
_isInitialized = true; _isInitialized = true;
} }
int64_t SNMPConnection::issueGet(const oid* const OID, size_t OIDLen) { bool SNMPConnection::open() {
_snmpSessp = snmp_sess_open(&_snmpSession);
int liberr, syserr;
char *errstr;
snmp_error(&_snmpSession, &liberr, &syserr, &errstr);
if (liberr || syserr) {
LOG(error) << "SNMP-open: " << errstr;
free(errstr);
return false;
}
return true;
}
void SNMPConnection::close() {
if (_snmpSessp) {
snmp_sess_close(_snmpSessp);
_snmpSessp = NULL;
}
}
int64_t SNMPConnection::get(const oid* const OID, size_t OIDLen) {
struct snmp_session* ss; struct snmp_session* ss;
struct snmp_pdu *pdu, *response; struct snmp_pdu *pdu, *response;
struct variable_list *vp; struct variable_list *vp;
int status; int status;
int64_t ret = 0; int64_t ret = 0;
ss = snmp_open(&_snmpSession); if (!_snmpSessp) {
open();
if (!ss) {
throw std::runtime_error("Could not open SNMP Session!");
} }
pdu = snmp_pdu_create(SNMP_MSG_GET); pdu = snmp_pdu_create(SNMP_MSG_GET);
snmp_add_null_var(pdu, OID, OIDLen); snmp_add_null_var(pdu, OID, OIDLen);
status = snmp_synch_response(ss, pdu, &response); status = snmp_sess_synch_response(_snmpSessp, pdu, &response);
if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) { if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
vp = response->variables; vp = response->variables;
...@@ -167,6 +194,7 @@ int64_t SNMPConnection::issueGet(const oid* const OID, size_t OIDLen) { ...@@ -167,6 +194,7 @@ int64_t SNMPConnection::issueGet(const oid* const OID, size_t OIDLen) {
char* err; char* err;
snmp_error(ss, NULL, NULL, &err); snmp_error(ss, NULL, NULL, &err);
LOG(error) << "SNMP-get: " << err; LOG(error) << "SNMP-get: " << err;
free(err);
} }
throw std::runtime_error("Request failed!"); throw std::runtime_error("Request failed!");
...@@ -175,7 +203,6 @@ int64_t SNMPConnection::issueGet(const oid* const OID, size_t OIDLen) { ...@@ -175,7 +203,6 @@ int64_t SNMPConnection::issueGet(const oid* const OID, size_t OIDLen) {
if (response) { if (response) {
snmp_free_pdu(response); snmp_free_pdu(response);
} }
snmp_close(ss);
return ret; return ret;
} }
......
...@@ -147,6 +147,16 @@ public: ...@@ -147,6 +147,16 @@ public:
*/ */
void init(); void init();
/**
* Open SNMP Session. Must be called once before issuing a get() call.
*/
bool open();
/**
* Close SNMP Session.
*/
void close();
/** /**
* Issues a get request to _host for the value specified by the OID. * Issues a get request to _host for the value specified by the OID.
* *
...@@ -155,7 +165,7 @@ public: ...@@ -155,7 +165,7 @@ public:
* *
* @return The requested value * @return The requested value
*/ */
int64_t issueGet(const oid* const OID, size_t OIDLen); int64_t get(const oid* const OID, size_t OIDLen);
private: private:
bool _isInitialized; bool _isInitialized;
...@@ -175,8 +185,11 @@ private: ...@@ -175,8 +185,11 @@ private:
int _securityLevel; int _securityLevel;
long int _version; long int _version;
struct snmp_session _snmpSession; struct snmp_session _snmpSession;
void* _snmpSessp;
boost::asio::io_service::strand* _strand; boost::asio::io_service::strand* _strand;
LOGGER lg; LOGGER lg;
}; };
......
...@@ -62,9 +62,10 @@ void SNMPSensorGroup::read() { ...@@ -62,9 +62,10 @@ void SNMPSensorGroup::read() {
reading_t reading; reading_t reading;
reading.timestamp = getTimestamp(); reading.timestamp = getTimestamp();
if (_connection->open()) {
for(const auto& s : _sensors) { for(const auto& s : _sensors) {
try { try {
reading.value = _connection->issueGet(s->getOID(), s->getOIDLen()); reading.value = _connection->get(s->getOID(), s->getOIDLen());
#ifdef DEBUG #ifdef DEBUG
LOG(debug) << _groupName << "::" << s->getName() << " raw reading: \"" << reading.value << "\""; LOG(debug) << _groupName << "::" << s->getName() << " raw reading: \"" << reading.value << "\"";
#endif #endif
...@@ -74,6 +75,8 @@ void SNMPSensorGroup::read() { ...@@ -74,6 +75,8 @@ void SNMPSensorGroup::read() {
continue; continue;
} }
} }
_connection->close();
}
} }
void SNMPSensorGroup::readAsync() { void SNMPSensorGroup::readAsync() {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment