0

I am trying to use Perl and Net::SNMP to query a device that has multiple configured views/contexts (a Cisco ACE 4710, for example). The equivalent snmpwalk command is:

snmpwalk -c public@CONTEXT_NAME -v 2c 1.2.3.4 '.1.3.6.1.4.1.9.9.480.1.1.2'

I can enumerate the various contexts/views with SNMP-VIEW-BASED-ACM-MIB, e.g.:

my $vacmContextName = '.1.3.6.1.6.3.16.1.1.1.1';
my ($session, $error) = Net::SNMP->session(-hostname => '1.2.3.4', -community => 'public');
my %contexts = %{ $snmp->get_entries(-columns => [ $vacmContextName ]) };

...but am having trouble now reading any further OIDs from each specific context, e.g.:

my $ciscoL4L7ResourceLimitTable = '.1.3.6.1.4.1.9.9.480.1.1.2';
my ($session, $error) = Net::SNMP->session(-hostname => '1.2.3.4', -community => 'public@CONTEXT_NAME');
my %stats = %{ $snmp->get_entries(-columns => [ $ciscoL4L7ResourceLimitTable ]) }

If I run with -debug => DEBUG_ALL, I see the data being returned in the packet inspection (with recognisable data from that context), but then I get a lot of the following errors:

error: [131] Net::SNMP::Security::Community::process_incoming_msg(): The community name "public@CONTEXT_NAME" was expected, but "public" was found
error: [218] Net::SNMP::MessageProcessing::prepare_data_elements(): The community name "public@CONTEXT_NAME" was expected, but "public" was found
error: [398] Net::SNMP::Dispatcher::_transport_response_received(): The community name "public@CONTEXT_NAME" was expected, but "public" was found
error: [1234] Net::SNMP::__ANON__(): The community name "public@CONTEXT_NAME" was expected, but "public" was found
error: [2363] Net::SNMP::__ANON__(): The community name "public@CONTEXT_NAME" was expected, but "public" was found

...and the resulting contents of %stats is undef.

If I try with -community => 'public', it works, but I only get values from the default context (which doesn't contain everything I need).

If I try with -contextname => 'CONTEXT_NAME', I just get:

error: [2423] Net::SNMP::_context_name(): The contextName argument is only supported in SNMPv3

Is it not possible to do what I need with Net::SNMP?

This is perl, v5.10.1 (*) built for i386-linux-thread-multi
CPAN_FILE    D/DT/DTOWN/Net-SNMP-v6.0.1.tar.gz
INST_VERSION v6.0.1
jimbobmcgee
  • 1,561
  • 11
  • 34
  • 1) You do not specify the SNMP version in `Net::SNMP->session()` (defaults to v1). 2) According to the [administration guide for the ACE 4700 series](http://www.cisco.com/en/US/docs/app_ntwk_services/data_center_app_services/ace_appliances/vA3_1_0/configuration/admin/guide/snmp.html#wp1082931), each context has its own IP address. Your code snippets only show one IP. 3) Contexts were introduced in SNMP v3, hence the Net::SNMP error. Cisco has provided a means to access context for SNMP v1, v2, and v2c if you follow the guide above. – ThisSuitIsBlackNot Nov 19 '13 at 16:44
  • @ThisSuitIsBlackNot - **1)** An artifact of trying to keep the code to a minimum to demonstrate the issue - it does not work with either `snmpv1` or `snmpv2c`; **2)** Each context does have its own IP but it is not typical to (and thus, I am not going to) enable management traffic on all IPs, just that of the admin context (which is on a dedicated VLAN); **3)** The guide shows the use of `snmpget -c COMMUNITY@CONTEXT ...` which I have already demonstrated above, but the same does not seem to apply to Net::SNMP (or rather Net::SNMP explictly prevents this). – jimbobmcgee Nov 19 '13 at 17:07
  • It doesn't help others debug your code if you remove important bits, but that's neither here nor there. Just to clarify, the *admin* context IP is `1.2.3.4`, the *admin* context community string is `public` and the *user* context you wish to access is `CONTEXT_NAME`? – ThisSuitIsBlackNot Nov 19 '13 at 17:17
  • @ThisSuitIsBlackNot - that's correct. – jimbobmcgee Nov 19 '13 at 17:55

1 Answers1

1

From an email conversation I just had with the package author, Word-of-$DEITY is:

Cisco's "context implementation" is vendor specific and is not standards based. The use of "contexts" is officially defined in the SNMPv3 RFCs (specifications). The Net::SNMP modules tries to follow the RFCs in its implementation. I would have to go back to the RFCs determine if it is legal to respond to an SNMP v1/2c message with a "community" string that is not the same as the one with which the request was made. This is the problem that you are seeing.

You are most likely not going to get Cisco to change their implementation even if it is violating an RFC, so your only recourse is to comment out the code in the Net/SNMP/Security/Community.pm module that is returning an error on the send/receive of differing community strings. I typically do not add modification to the module to work around vendor specific problems.

Rather than comment out the relevant section of the Community.pm (which is used by far more on my server than just this script), I have instead elected to shim/monkey-patch the method in question in my own code, for example:

no warnings 'redefine';
use Net::SNMP::Security::Community;
*Net::SNMP::Security::Community::process_incoming_msg = sub { return 1; };

This way, the failing method is bypassed in favour of just accepting any returned community string.

Filthy dirty on all counts, but acceptable within my controlled environment. Anyone coming across this in the future should make sure that version != 6.0.1 hasn't changed the way this module works, or what the existing subroutine does before attempting the same.

jimbobmcgee
  • 1,561
  • 11
  • 34