The Net::Raddle::SNMPAgent package provides complete control over the data returned by an SNMP agent. This is useful when building emulated networks for testing network management packages or teaching people to use them.
In its simplest form, Raddle will replay static data captured from a real SNMP agent (e.g. using the snmpwalk command).
More advanced usage includes adding interfaces and entries in various tables, to build up a complex emulated device.
Raddle requires net-snmp version 5.0.8 or later, built with the Perl module enabled. If using 5.0.8, a patch must be applied to the source code first.
The Perl modules Digest::MD5 and Carp are also required.
To emulate a router called r1 using an snmpwalk output file in /usr/local/etc/snmp-emulator/r1.snmp, put this in /usr/local/etc/snmp-emulator/r1.pl:
use Net::Raddle::SNMPAgent; my $agent = Net::Raddle::SNMPAgent->new() or die "Could not initialise Raddle"; $agent->ParseDataFile( '/usr/local/etc/snmp-emulator/r1.snmp', 0 );
This is the config file /usr/local/etc/snmp-emulator/r1.conf:
# Listen on port 9501 agentaddress udp:localhost:9501,tcp:localhost:9501
# Access control com2sec notConfigUser default public group notConfigGroup v1 notConfigUser group notConfigGroup v2c notConfigUser view iso included .iso access notConfigGroup "" any noauth exact iso none none
# Emulator script perl do "/usr/local/etc/snmp-emulator/r1.pl"
It is wise to test the emulator script before trying to run it with snmpd, as the daemon seems to hide certain types of error report. Do something like this:
perl -w /usr/local/etc/snmp-emulator/r1.pl
Start snmpd like this:
snmpd -C -I vacm_vars -c /usr/local/etc/snmp-emulator/r1.conf
SNMPD will now respond on localhost:9501 using data from the r1.snmp
file.
Use snmpwalk or snmpbulkwalk:
snmpwalk -v 1 -c <community> -OneU <device>
It is OK to miss the 'n' option from -O if you prefer to use symbolic names
Parameter errors and other serious problems are signalled using
confess
from the Carp module. This in turn calls die
Net::Raddle::SNMPAgent->new(params)
params is a key-value list, which can specify:
debugging => 0, # higher number for more debugging subagent => 0, # Should this be an AgentX subagent?
If $subagent
is true, register as an AgentX subagent.
If $subagent
is false (e.g. zero), run as part of the main agent process.
e.g.:
my $agent = Net::Raddle::SNMPAgent->new( debugging => 1 );
$agent->AgentXMainLoop()
$agent->ParseDataFile($filename,$CompatKludges)
If $CompatKludges is true, tries to parse output from earlier versions of Net-SNMP and UCD-SNMP. This is not completely successful, as the output formats are ambiguous. It is strongly suggested that $CompatKludges should be zero.
$agent->version
NOTE these are not exported by default. You should either import them explicitly with:
use Net::Raddle::SNMPAgent qw(IPToMAC Netmask CanonicalOID);
or you should refer to them using the package name, e.g.:
my $mask = Net::Raddle::SNMPAgent::Netmask(27);
CanonicalOID($oid)
my $oidstr = CanonicalOID( 'IF-MIB::ifNumber.0' );
Canonical OIDs have the form: '.1.3.6.1.2.1.1.3.0'
Returns undef if the OID cannot be processed.
IPToMAC($prefix,$IP)
my $MACaddr = IPToMac( '00:30', '10.3.76.45' );
This allows the ARP tables of different devices to be set up with consistent data without having to hand-configure the mappings.
Netmask($length)
my $mask = Netmask(24); # $mask is now '255.255.255.0'
$agent->TieMIBItem($canonicaloid,$type,$classname,$classparam)
$agent->TieMIBItem( CanonicalOID('SNMPv2-MIB::sysUpTime.0'), ASN_TIMETICKS, "TicksSince", Mktime( 2002, 9, 24, 3, 59, 14) );
Available data types are:
ASN_OBJECT_ID An OID - must be in canonical form. ASN_OCTET_STR Octet string. Can be text or binary. ASN_INTEGER 32-bit integer. ASN_TIMETICKS Time ticks (units of 0.01s) ASN_GAUGE 32-bit non-wrapping integer. ASN_IPADDRESS An IP address in the form 10.3.27.200 ASN_COUNTER 32-bit counter. ASN_COUNTER64 64-bit counter (not yet working properly).
$agent->SetMIBValue($canonicaloid,$type,$initialvalue)
SetMIBValue( '.1.3.6.1.2.1.1.5.0', ASN_OCTET_STR, 'router.example.org' )
$agent->GetMIBValue($canonicaloid,$type,$initialvalue)
Returns a hash of the form:
{ type => DATATYPE, value => VALUE }
Returns undef if the item is not defined.
already exist. e.g.:
my %mibitem = $agent->GetMIBValue( '.1.3.6.1.2.1.1.5.0' );
$agent->AddIF($datahash)
$datahash
e.g.:
$IFIndex = $agent->AddIF( { ifType => 'csmacd', ifSpeed => 10000000 } );
The complete list of values that can be specified is the ifTable:
ifIndex InterfaceIndex, ifDescr DisplayString, ifType IANAifType, ifMtu Integer32, ifSpeed Gauge32, ifPhysAddress PhysAddress, ifAdminStatus INTEGER, ifOperStatus INTEGER, ifLastChange TimeTicks, ifInOctets Counter32, ifInUcastPkts Counter32, ifInNUcastPkts Counter32, -- deprecated ifInDiscards Counter32, ifInErrors Counter32, ifInUnknownProtos Counter32, ifOutOctets Counter32, ifOutUcastPkts Counter32, ifOutNUcastPkts Counter32, -- deprecated ifOutDiscards Counter32, ifOutErrors Counter32, ifOutQLen Gauge32, -- deprecated ifSpecific OBJECT IDENTIFIER -- deprecated
These items from ifXTable may also be specified:
ifName DisplayString, ifInMulticastPkts Counter32, ifInBroadcastPkts Counter32, ifOutMulticastPkts Counter32, ifOutBroadcastPkts Counter32, ifAlias DisplayString,
Any value that is not supplied will be defaulted.
Include 'WithDeprecatedItems => 1' in $datahash
if you want
to return data for the items marked as deprecated.
$agent->AddIpAddrEntry($datahash)
e.g.:
$agent->AddIpAddrEntry( { ipAdEntAddr => '10.0.0.177', ipAdEntIfIndex => 2, ipAdEntNetMask => '255.255.255.0', ipAdEntBcastAddr => 1, ipAdEntReasmMaxSize => 8192, } );
ipAdEntAddr and ipAdEntIfIndex MUST be specified. Other values default as shown above if not specified.
$agent->AddIpNetToMediaEntry($datahash)
$agent->AddIpNetToMediaEntry( { ipNetToMediaIfIndex => 3, ipNetToMediaPhysAddress => '0:30:b6:36:14:d4', ipNetToMediaNetAddress => '10.0.0.177', ipNetToMediaType => 4, } );
The first three MUST be specified.
ipNetToMediaType defaults to type static(4)
if not specified
Possible values are:
other(1), -- none of the following invalid(2), -- an invalidated mapping dynamic(3), -- obtained by dynamic means (e.g. ARP) static(4) -- static (configuration or hardware)
$agent->AddIpRouteEntry($datahash)
$agent->AddIpRouteEntry ({ ipRouteDest => '10.1.3.0', ipRouteIfIndex => 2, ipRouteMetric1 => -1, * ipRouteMetric2 => -1, * ipRouteMetric3 => -1, * ipRouteMetric4 => -1, * ipRouteNextHop => '10.0.2.34', ipRouteType => 4, * ipRouteProto => 2, * ipRouteAge => 0, * ipRouteMask => '255.255.255.0', ipRouteMetric5 => -1, * ipRouteInfo => '.0.0', * });
Items marked '*' above can be omitted, and will default to the values shown.
For detailed code examples, see the examples
directory in the
Raddle distribution.
Raddle is distributed from SourceForge: http://raddle.sourceforge.net/
Andrew Findlay <andrew.findlay@skills-1st.co.uk>