You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
288 lines
7.9 KiB
288 lines
7.9 KiB
/* This file is part of the KDE project
|
|
Copyright (C) 2003 Simon Hausmann <hausmann@kde.org>
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; see the file COPYING. If not, write to
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "session.h"
|
|
#include "snmp.h"
|
|
#include "snmp_p.h"
|
|
#include "snmplib.h"
|
|
#include "pdu.h"
|
|
|
|
#include <assert.h>
|
|
|
|
using namespace KSim::Snmp;
|
|
|
|
// ### clean me up
|
|
struct Session::Data
|
|
{
|
|
Data() : session( 0 ) {}
|
|
|
|
netsnmp_session defaultSession;
|
|
netsnmp_session *session;
|
|
|
|
bool initialized;
|
|
|
|
HostConfig source;
|
|
|
|
TQCString host;
|
|
TQCString community;
|
|
TQCString securityName;
|
|
TQCString authPassPhrase;
|
|
TQCString privPassPhrase;
|
|
};
|
|
|
|
Session::Session( const HostConfig &source )
|
|
{
|
|
d = new Data;
|
|
d->initialized = false;
|
|
|
|
d->source = source;
|
|
|
|
// unicode madness
|
|
d->host = source.name.ascii();
|
|
d->community = source.community.ascii();
|
|
d->securityName = source.securityName.ascii();
|
|
d->authPassPhrase = source.authentication.key.ascii();
|
|
d->privPassPhrase = source.privacy.key.ascii();
|
|
|
|
SnmpLib::self()->snmp_sess_init( &d->defaultSession );
|
|
}
|
|
|
|
bool Session::snmpGetInternal( int getType, const IdentifierList &identifiers, ValueMap &variables, ErrorInfo *error )
|
|
{
|
|
if ( !d->initialized && !initialize( error ) )
|
|
return false;
|
|
|
|
bool result = false;
|
|
|
|
if ( getType != SNMP_MSG_GETNEXT && d->session ) {
|
|
SnmpLib::self()->snmp_close( d->session );
|
|
d->session = 0;
|
|
}
|
|
|
|
if ( getType != SNMP_MSG_GETNEXT ||
|
|
!d->session ) {
|
|
|
|
if ( ( d->session = SnmpLib::self()->snmp_open( &d->defaultSession ) ) == 0 ) {
|
|
if ( error )
|
|
*error = ErrorInfo( sessionErrorCode( d->defaultSession ) );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
PDU request( getType );
|
|
PDU response;
|
|
|
|
request.addNullVariables( identifiers );
|
|
|
|
int status = SnmpLib::self()->snmp_synch_response( d->session, request.release(), &response );
|
|
|
|
if ( status == STAT_SUCCESS ) {
|
|
|
|
if ( response.hasError() ) {
|
|
|
|
if ( error )
|
|
*error = ErrorInfo( response.errorCode() );
|
|
|
|
} else {
|
|
|
|
variables = response.variables();
|
|
result = true;
|
|
|
|
if ( error )
|
|
*error = ErrorInfo( ErrorInfo::NoError );
|
|
}
|
|
|
|
} else if ( status == STAT_TIMEOUT ) {
|
|
|
|
if ( error )
|
|
*error = ErrorInfo( ErrorInfo::ErrTimeout );
|
|
|
|
} else {
|
|
|
|
if ( error )
|
|
*error = ErrorInfo( sessionErrorCode( *d->session ) );
|
|
|
|
}
|
|
|
|
if ( getType != SNMP_MSG_GETNEXT ) {
|
|
SnmpLib::self()->snmp_close( d->session );
|
|
d->session = 0;
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
bool Session::initialize( ErrorInfo *error )
|
|
{
|
|
if ( d->initialized ) {
|
|
if ( error )
|
|
*error = ErrorInfo( ErrorInfo::NoError );
|
|
return true;
|
|
}
|
|
|
|
HostConfig &source = d->source;
|
|
|
|
d->defaultSession.peername = d->host.data();
|
|
|
|
d->defaultSession.version = snmpVersionToSnmpLibConstant( source.version );
|
|
|
|
if ( source.version != SnmpVersion3 ) {
|
|
d->defaultSession.community = reinterpret_cast<u_char *>( d->community.data() );
|
|
d->defaultSession.community_len = d->community.length();
|
|
d->initialized = true;
|
|
return true;
|
|
}
|
|
|
|
d->defaultSession.securityName = d->securityName.data();
|
|
d->defaultSession.securityNameLen = d->securityName.length();
|
|
|
|
d->defaultSession.securityLevel = snmpSecurityLevelToSnmpLibConstant( source.securityLevel );
|
|
|
|
// ### clean me up
|
|
switch ( source.authentication.protocol ) {
|
|
case MD5Auth: {
|
|
d->defaultSession.securityAuthProto = usmHMACMD5AuthProtocol;
|
|
d->defaultSession.securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN;
|
|
break;
|
|
}
|
|
case SHA1Auth: {
|
|
d->defaultSession.securityAuthProto = usmHMACSHA1AuthProtocol;
|
|
d->defaultSession.securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN;
|
|
break;
|
|
}
|
|
default: assert( false );
|
|
}
|
|
|
|
d->defaultSession.securityAuthKeyLen = USM_AUTH_KU_LEN;
|
|
|
|
int result;
|
|
if ( ( result = SnmpLib::self()->generate_Ku( d->defaultSession.securityAuthProto, d->defaultSession.securityAuthProtoLen,
|
|
reinterpret_cast<uchar *>( d->authPassPhrase.data() ), d->authPassPhrase.length(),
|
|
d->defaultSession.securityAuthKey, &d->defaultSession.securityAuthKeyLen ) )
|
|
!= SNMPERR_SUCCESS ) {
|
|
|
|
if ( error )
|
|
*error = ErrorInfo( result );
|
|
|
|
return false;
|
|
}
|
|
|
|
switch ( source.privacy.protocol ) {
|
|
case AESPrivacy: {
|
|
d->defaultSession.securityPrivProto = usmAESPrivProtocol;
|
|
d->defaultSession.securityPrivProtoLen = USM_PRIV_PROTO_AES_LEN;
|
|
break;
|
|
}
|
|
case DESPrivacy: {
|
|
#ifndef NETSNMP_DISABLE_DES
|
|
d->defaultSession.securityPrivProto = usmDESPrivProtocol;
|
|
d->defaultSession.securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN;
|
|
#endif
|
|
break;
|
|
}
|
|
default: assert( false );
|
|
}
|
|
|
|
d->defaultSession.securityPrivKeyLen = USM_PRIV_KU_LEN;
|
|
|
|
if ( ( result = SnmpLib::self()->generate_Ku( d->defaultSession.securityAuthProto, d->defaultSession.securityAuthProtoLen,
|
|
reinterpret_cast<u_char *>( d->privPassPhrase.data() ), d->privPassPhrase.length(),
|
|
d->defaultSession.securityPrivKey, &d->defaultSession.securityPrivKeyLen ) )
|
|
!= SNMPERR_SUCCESS ) {
|
|
|
|
if ( error )
|
|
*error = ErrorInfo( result );
|
|
|
|
|
|
return false;
|
|
}
|
|
|
|
d->initialized = true;
|
|
return true;
|
|
}
|
|
|
|
bool Session::snmpGet( const TQString &identifier, Value &value, ErrorInfo *error )
|
|
{
|
|
bool ok = false;
|
|
Identifier oid = Identifier::fromString( identifier, &ok );
|
|
if ( !ok ) {
|
|
if ( error )
|
|
*error = ErrorInfo( ErrorInfo::ErrUnknownOID );
|
|
return false;
|
|
}
|
|
|
|
return snmpGet( oid, value, error );
|
|
}
|
|
|
|
bool Session::snmpGet( const Identifier &identifier, Value &value, ErrorInfo *error )
|
|
{
|
|
ValueMap vars;
|
|
IdentifierList ids;
|
|
|
|
ids << identifier;
|
|
|
|
if ( !snmpGet( ids, vars, error ) )
|
|
return false;
|
|
|
|
ValueMap::ConstIterator it = vars.find( identifier );
|
|
if ( it == vars.end() ) {
|
|
if ( error )
|
|
*error = ErrorInfo( ErrorInfo::ErrMissingVariables );
|
|
return false;
|
|
}
|
|
|
|
value = it.data();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Session::snmpGet( const IdentifierList &identifiers, ValueMap &variables, ErrorInfo *error )
|
|
{
|
|
return snmpGetInternal( SNMP_MSG_GET, identifiers, variables, error );
|
|
}
|
|
|
|
bool Session::snmpGetNext( Identifier &identifier, Value &value, ErrorInfo *error )
|
|
{
|
|
ValueMap vars;
|
|
IdentifierList ids;
|
|
|
|
ids << identifier;
|
|
|
|
if ( !snmpGetInternal( SNMP_MSG_GETNEXT, ids, vars, error ) )
|
|
return false;
|
|
|
|
assert( vars.count() == 1 );
|
|
|
|
ValueMap::ConstIterator it = vars.begin();
|
|
identifier = it.key();
|
|
value = it.data();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
Session::~Session()
|
|
{
|
|
if ( d->session )
|
|
SnmpLib::self()->snmp_close( d->session );
|
|
delete d;
|
|
}
|