Net_SNMP_util(3pm)

🌸 Net_SNMP_util πŸ’…

okay bestie, gather round, because this is Net_SNMP_util(3pm) β€” straight outta the User Contributed Perl Documentation β€” and it's genuinely one of those pages you're gonna wanna bookmark. it's a whole toolkit of SNMP utilities built on top of Net::SNMP, and it's about to make your network management life so much easier, no cap. 🫢


✨ NAME ✨

Net_SNMP_util β€” SNMP utilities based on Net::SNMP


πŸŽ€ SYNOPSIS πŸŽ€

so the Net_SNMP_util module implements SNMP utilities using the Net::SNMP module. it implements snmpget, snmpgetnext, snmpwalk, snmpset, snmptrap, and snmpgetbulk. lowkey important: the Net_SNMP_util module assumes you've got a basic understanding of the Simple Network Management Protocol and related network management concepts. like, it's not gonna hold your hand through the theory, bestie, it's gonna hand you the vibes. ✨


πŸ’– DESCRIPTION πŸ’–

the Net_SNMP_util module simplifies SNMP queries even more than Net::SNMP alone. it's giving convenience. easy-to-use get, getnext, walk, set, trap, and getbulk routines are provided, hiding all the details of a SNMP query. you just... ask. and it answers. iconic behaviour honestly. πŸ‘‘

🌈 Option Notes

🌸 host Parameter

SNMP parameters can be specified as part of the hostname/ip address passed as the first argument. the syntax is:

    community@host:port:timeout:retries:backoff:version

if the community is left off, it defaults to public. if the port is left off, it defaults to 161 for everything but snmptrap(). the snmptrap() routine uses a default port of 162. timeout and retries default to whatever Net::SNMP uses, currently 5.0 seconds and 1 retry (2 tries total). the backoff parameter is currently unimplemented. the version parameter defaults to SNMP version 1.

⚠️ some SNMP values such as 64-bit counters have to be queried using SNMP version 2. specifying 2 or 2c as the version parameter will accomplish this. the snmpgetbulk routine is only supported in SNMP version 2 and higher. additional security features are available under SNMP version 3.

some machines have additional security features that only allow SNMP queries to come from certain IP addresses. if the host doing the query has multiple interfaces, it may be necessary to specify the interface the query should come from. the port parameter is further broken down into:

    remote_port!local_address!local_port

here are some examples, bestie, take notes πŸ“:

    somehost
    somehost:161
    somehost:161!192.168.2.4!4000  use 192.168.2.4 and port 4000 as source
    somehost:!192.168.2.4          use 192.168.2.4 as source
    somehost:!!4000                use port 4000 as source

most people will only need to use the first form (somehost). fr fr, keep it simple.

πŸ¦‹ OBJECT IDENTIFIERs

to further simplify SNMP queries, the query routines use a small table that maps the textual representation of OBJECT IDENTIFIERs to their dotted notation. the OBJECT IDENTIFIERs from RFC1213 (MIB-II) and RFC1315 (Frame Relay) are preloaded. this allows OBJECT IDENTIFIERs like ifInOctets.4 to be used instead of the more cumbersome 1.3.6.1.2.1.2.2.1.10.4. the GLOW UP. ✨

several functions are provided to manage the mapping table. mapping entries can be added directly, SNMP MIB files can be read, and a cache file with the text-to-OBJECT-IDENTIFIER mappings are maintained. by default, the file OID_cache.txt is loaded, but it can by changed by setting the variable $Net_SNMP_util::CacheFile to the desired file name. the functions to manipulate the mappings are:

    snmpmapOID                  Add a textual OID mapping directly
    snmpMIB_to_OID              Read a SNMP MIB file
    snmpLoad_OID_Cache          Load an OID-mapping cache file
    snmpQueue_MIB_File          Queue a SNMP MIB file for loading on demand

πŸ’œ Net::SNMP extensions

this module is built on top of Net::SNMP. Net::SNMP has a different method of specifying SNMP parameters. to support this different method, this module will accept an optional hash reference containing the SNMP parameters. the hash may contain the following:

        [-port          => $port,]
        [-localaddr     => $localaddr,]
        [-localport     => $localport,]
        [-version       => $version,]
        [-domain        => $domain,]
        [-timeout       => $seconds,]
        [-retries       => $count,]
        [-maxmsgsize    => $octets,]
        [-debug         => $bitmask,]
        [-community     => $community,]   # v1/v2c
        [-username      => $username,]    # v3
        [-authkey       => $authkey,]     # v3
        [-authpassword  => $authpasswd,]  # v3
        [-authprotocol  => $authproto,]   # v3
        [-privkey       => $privkey,]     # v3
        [-privpassword  => $privpasswd,]  # v3
        [-privprotocol  => $privproto,]   # v3
        [-contextengineid => $engine_id,] # v3
        [-contextname     => $name,]      # v3

please see the documentation for Net::SNMP for a description of these parameters. (iykyk, go read that one too)

🧚 SNMPv3 Arguments

a SNMP context is a collection of management information accessible by a SNMP entity. an item of management information may exist in more than one context and a SNMP entity potentially has access to many contexts. the combination of a contextEngineID and a contextName unambiguously identifies a context within an administrative domain. in a SNMPv3 message, the contextEngineID and contextName are included as part of the scopedPDU. all methods that generate a SNMP message optionally take a -contextengineid and -contextname argument to configure these fields.

πŸ‘‘ Context Engine ID

the -contextengineid argument expects a hexadecimal string representing the desired contextEngineID. the string must be 10 to 64 characters (5 to 32 octets) long and can be prefixed with an optional 0x. once the -contextengineid is specified it stays with the object until it is changed again or reset to default by passing in the undefined value. by default, the contextEngineID is set to match the authoritativeEngineID of the authoritative SNMP engine.

πŸŽ€ Context Name

the contextName is passed as a string which must be 0 to 32 octets in length using the -contextname argument. the contextName stays with the object until it is changed. the contextName defaults to an empty string which represents the default context.


πŸ”₯ Functions πŸ”₯

🌟 snmpget() - send a SNMP get-request to the remote agent

    @result = snmpget(
                [community@]host[:port[:timeout[:retries[:backoff[:version]]]]],
                [\%param_hash],
                @oids
            );

this function performs a SNMP get-request query to gather data from the remote agent on the host specified. the message is built using the list of OBJECT IDENTIFIERs passed as an array. each OBJECT IDENTIFIER is placed into a single SNMP GetRequest-PDU in the same order that it held in the original list.

the requested values are returned in an array in the same order as they were requested. in scalar context the first requested value is returned. order preserved, always. we love consistency. πŸ’–

🌟 snmpgetnext() - send a SNMP get-next-request to the remote agent

    @result = snmpgetnext(
                [community@]host[:port[:timeout[:retries[:backoff[:version]]]]],
                [\%param_hash],
                @oids
            );

this function performs a SNMP get-next-request query to gather data from the remote agent on the host specified. the message is built using the list of OBJECT IDENTIFIERs passed as an array. each OBJECT IDENTIFIER is placed into a single SNMP GetNextRequest-PDU in the same order that it held in the original list.

the requested values are returned in an array in the same order as they were requested. the OBJECT IDENTIFIER number is added as a prefix to each value using a colon as a separator, like '1.3.6.1.2.1.2.2.1.2.1:ethernet'. in scalar context the first requested value is returned.

🌟 snmpgetbulk() - send a SNMP get-bulk-request to the remote agent

    @result = snmpgetbulk(
                [community@]host[:port[:timeout[:retries[:backoff[:version]]]]],
                $nonrepeaters,
                $maxrepetitions,
                [\%param_hash],
                @oids
            );

this function performs a SNMP get-bulk-request query to gather data from the remote agent on the host specified.

  • the $nonrepeaters value specifies the number of variables in the @oids list for which a single successor is to be returned. if it is null or undefined, a value of 0 is used.
  • the $maxrepetitions value specifies the number of successors to be returned for the remaining variables in the @oids list. if it is null or undefined, the default value of 12 is used.
  • the message is built using the list of OBJECT IDENTIFIERs passed as an array. each OBJECT IDENTIFIER is placed into a single SNMP GetNextRequest-PDU in the same order that it held in the original list.

the requested values are returned in an array in the same order as they were requested.

πŸ’€ NOTE: this function can only be used when the SNMP version is set to SNMPv2c or SNMPv3. don't even try it otherwise, bestie, it's not happening.

🌟 snmpwalk() - walk OBJECT IDENTIFIER tree(s) on the remote agent

    @result = snmpwalk(
                [community@]host[:port[:timeout[:retries[:backoff[:version]]]]],
                [\%param_hash],
                @oids
            );

this function performs a sequence of SNMP get-next-request or get-bulk-request (if the SNMP version is 2 or higher) queries to gather data from the remote agent on the host specified. the initial message is built using the list of OBJECT IDENTIFIERs passed as an array. each OBJECT IDENTIFIER is placed into a single SNMP GetNextRequest-PDU in the same order that it held in the original list. queries continue until all the returned OBJECT IDENTIFIERs are no longer a child of the base OBJECT IDENTIFIERs. it just keeps going until it's done. main character energy. 🌈

the requested values are returned in an array in the same order as they were requested. the OBJECT IDENTIFIER number is added as a prefix to each value using a colon as a separator, like '1.3.6.1.2.1.2.2.1.2.1:ethernet'. if only one OBJECT IDENTIFIER is requested, just the instance part of the OBJECT IDENTIFIER is added as a prefix, like '1:ethernet', '2:ethernet', '3:fddi'.

🌟 snmpset() - send a SNMP set-request to the remote agent

    @result = snmpset(
                [community@]host[:port[:timeout[:retries[:backoff[:version]]]]],
                [\%param_hash],
                $oid1, $type1, $value1,
                [$oid2, $type2, $value2 ...]
            );

this function is used to modify data on the remote agent using a SNMP set-request. the message is built using the list of values consisting of groups of an OBJECT IDENTIFIER, an object type, and the actual value to be set. the object type can be one of the following strings:

           integer | int
           string | octetstring | octet string
           oid | object id | object identifier
           ipaddr | ip addr4ess
           timeticks
           uint | uinteger | uinteger32 | unsigned int | unsigned integer | unsigned integer32
           counter | counter 32
           counter64
           gauge | gauge32

Bestie you can also just hand over an octet that matches the ASN.1 type, no big deal. Wanna know more? The Net::SNMP docs have you covered. πŸ’–

And the values you asked for come back in an array, in the exact same order you asked for them. In scalar context? You only get the first requested value. That's it, that's the deal. ✨


πŸ’… snmptrap() β€” send a SNMP trap to the remote manager πŸ’…

@result = snmptrap(
            [community@]host[:port[:timeout[:retries[:backoff[:version]]]]],
            $enterprise,
            $agentaddr,
            $generictrap,
            $specifictrap,
            [\%param_hash],
            $oid1, $type1, $value1,
            [$oid2, $type2, $value2 ...]
        );

Okay so this one sends a SNMP trap to the remote manager living on the host you named. 🌸 The message gets built out of that list of values, which comes in little groups of three: an OBJECT IDENTIFIER, an object type, and the actual value to be set. The object type can be any one of these strings:

integer | int
string | octetstring | octet string
oid | object id | object identifier
ipaddr | ip addr4ess
timeticks
uint | uinteger | uinteger32 | unsigned int | unsigned integer | unsigned integer32
counter | counter 32
counter64
gauge | gauge32

Or, plot twist, the object type can be an octet matching the ASN.1 type. Net::SNMP documentation has the deets. πŸ‘‘

You get a true value back if the trap went out successfully. If something went sideways, you get the undefined value. 😭

When the trap is sent as SNMPv2c, the $enterprise, $agentaddr, $generictrap, and $specifictrap arguments are ignored β€” literally just sitting there, ignored. And on top of that, your first two (oid, type, value) tuples should be:

  • sysUpTime.0 β€” ('1.3.6.1.2.1.1.3.0', 'timeticks', $timeticks)
  • snmpTrapOID.0 β€” ('1.3.6.1.6.3.1.1.4.1.0', 'oid', $oid)
🚨 NOTE: This function can only be used when the SNMP version is set to SNMPv1 or SNMPv2c. No other versions, bestie, don't even try it.

πŸ¦‹ snmpmaptable() β€” walk OBJECT IDENTIFIER tree(s) on the remote agent πŸ¦‹

$result = snmpmaptable(
            [community@]host[:port[:timeout[:retries[:backoff[:version]]]]],
            \&function,
            [\%param_hash],
            @oids
        );

This one runs a whole sequence of SNMP get-next-request or get-bulk-request queries (get-bulk only if the SNMP version is 2 or higher, iykyk) to hoover up data from the remote agent on the host you specified. πŸ“ The initial message gets built from that list of OBJECT IDENTIFIERs you pass as an array. Every single OBJECT IDENTIFIER gets dropped into its own SNMP GetNextRequest-PDU, in the same order it had in your original list. Queries keep going until all the returned OBJECT IDENTIFIERs are no longer a child of the base OBJECT IDENTIFIERs. The OBJECT IDENTIFIERs have to correspond to column entries for a conceptual row in a table β€” but plot twist, they can totally be columns in different tables as long as each table is indexed the same way. πŸ’œ

  • Your \&function argument gets called once per row of the table. It's passed the row index as a partial OBJECT IDENTIFIER in dotted notation β€” like "1.3" or "10.0.1.34" β€” plus the values of the requested table columns in that row. πŸŽ€

You get the number of rows in the table back on success. On failure? undefined value, bestie. 😭


🌈 snmpmaptable4() β€” walk OBJECT IDENTIFIER tree(s) on the remote agent 🌈

$result = snmpmaptable4(
            [community@]host[:port[:timeout[:retries[:backoff[:version]]]]],
            \&function,
            $maxrepetitions,
            [\%param_hash],
            @oids
        );

Same energy as above, fr fr: a sequence of SNMP get-next-request or get-bulk-request queries (again, get-bulk only if the SNMP version is 2 or higher) to gather data from the remote agent on the host you specified. The initial message is built from the list of OBJECT IDENTIFIERs passed as an array. Each OBJECT IDENTIFIER goes into a single SNMP GetNextRequest-PDU, keeping the same order it had in the original list. Queries continue until all returned OBJECT IDENTIFIERs are no longer a child of the base OBJECT IDENTIFIERs. And yes β€” the OBJECT IDENTIFIERs must correspond to column entries for a conceptual row in a table, though they can be columns in different tables as long as every table is indexed the same way. ✨

  • The \&function argument gets called once per row of the table. It's passed the row index as a partial OBJECT IDENTIFIER in dotted notation, e.g. "1.3" or "10.0.1.34", plus the values of the requested table columns in that row. πŸ’–
  • The $maxrepetitions argument says how many rows a single get-bulk-request should return. If it's null or undefined, the default value of 12 is used. πŸ‘‘

Returns the number of rows in the table on success. On failure, undefined value. Periodt.


πŸ’€ snmpwalkhash() β€” send a SNMP get-next-request to the remote agent πŸ’€

@result = snmpwalkhash(
            [community@]host[:port[:timeout[:retries[:backoff[:version]]]]],
            \&function(),
            [\%param_hash],
            @oids,
            [\%hash]
        );

Okay so this one runs a sequence of SNMP get-next-request or get-bulk-request queries (get-bulk when the SNMP version is 2 or higher) to gather data from the remote agent on the host you specified. 🌸 The message is built from the list of OBJECT IDENTIFIERs you pass as an array. Each OBJECT IDENTIFIER goes into a single SNMP GetNextRequest-PDU, same order as the original list. Queries keep going until all the returned OBJECT IDENTIFIERs are outside of the tree specified by the initial OBJECT IDENTIFIERs. πŸ¦‹

The \&function gets called once for every returned value. It's passed a reference to a hash, the hostname, the textual OBJECT IDENTIFIER, the dotted-numberic OBJECT IDENTIFIER, the instance, the value, and the requested textual OBJECT IDENTIFIER. That function can customize the result so you can pull the values back out later by hosts, by oid_names, by oid_numbers, by instances... like these:

$hash{$host}{$name}{$inst} = $value;
$hash{$host}{$oid}{$inst} = $value;
$hash{$name}{$inst} = $value;
$hash{$oid}{$inst} = $value;
$hash{$oid . '.' . $ints} = $value;
$hash{$inst} = $value;
...

If the last argument to snmpwalkhash is a reference to a hash, that hash reference gets passed to your passed-in function instead of a local hash reference. Which means the function can go look up other objects unrelated to the current invocation of snmpwalkhash. Iconic behaviour honestly. πŸ’…

And snmpwalkhash returns the hash. That's it. πŸŽ€


⭐ snmpmapOID() β€” add textual OBJECT INDENTIFIER mapping ⭐

snmpmapOID(
    $text1, $oid1,
    [ $text2, $oid2 ...]
);

This routine adds entries to the table that maps textual representation of OBJECT IDENTIFIERs to their dotted notation. For example,

snmpmapOID('ciscoCPU', '1.3.6.1.4.1.9.9.109.1.1.1.1.5.1');

lets you use the string 'ciscoCPU' as an OBJECT IDENTIFIER in any SNMP query routine. So convenient. πŸ˜­πŸ’–

This routine doesn't return anything. Nothing. Nada. 🫢


πŸŽ€ snmpLoad_OID_Cache() β€” Read a file of cached OID mappings πŸŽ€

$result = snmpLoad_OID_Cache(
            $file
        );

This routine opens the file named by the $file argument and reads it. That file should contain text, OBJECT IDENTIFIER pairs, one pair per line. It adds the pairs as entries to the table that maps textual representation of OBJECT IDENTIFIERs to their dotted notation. Blank lines get ignored, and so does anything after a '#' or anything between '--'. 🌈

Returns 0 on success and -1 if the $file couldn't be opened. Simple as that. ✨


πŸ‘‘ snmpMIB_to_OID() β€” Read a MIB file for textual OID mappings πŸ‘‘

$result = snmpMIB_to_OID(
            $file
        );

This routine opens the file named by the $file argument and reads it. That file should be an SNMP Management Information Base (MIB) file that describes OBJECT IDENTIFIERs supported by an SNMP agent. per line. It adds the textual representation of the OBJECT IDENTIFIERs to the text-to-OID mapping table. πŸ’œ

Returns the number of entries added to the table, or -1 if the $file couldn't be opened. πŸ’…


🧚 snmpQueue_MIB_File() β€” queue a MIB file for reading "on demand" 🧚

snmpQueue_MIB_File(
    $file1,
    [$file2, ...]
);

This routine queues up the list of SNMP MIB files for later processing. πŸ“ And here's the magic: whenever a text-to-OBJECT IDENTIFIER lookup fails, the list of queued MIB files gets consulted. If it isn't empty, the first MIB file in the list is removed and handed to snmpMIB_to_OID(). Then the lookup is attempted again, and if it still fails, the next MIB file in the list is removed and passed to snmpMIB_to_OID(). This whole little loop keeps going until the lookup succeeds or the list is exhausted. 😭

This routine doesn't return anything. 🫢


✨ EXPORTS ✨

The Net_SNMP_util module uses the Exporter module to export useful constants and subroutines. These exportable symbols are defined below and follow the rules and conventions of the Exporter module (see Exporter). πŸ’–

🌸 Exportable 🌸

&snmpget, &snmpgetnext, &snmpgetbulk, &snmpwalk, &snmpset,
&snmptrap, &snmpmaptable, &snmpmaptable4, &snmpwalkhash,
&snmpmapOID, &snmpMIB_to_OID, &snmpLoad_OID_Cache,
&snmpQueue_MIB_File, ErrorMessage

✨ EXAMPLES ✨

Okay bestie, here are the examples, and they are literally so helpful. Four of them. Each one is a whole little Perl script. Keep the code exactly as shown, no cap. πŸ’…


1. SNMPv1 get-request for sysUpTime

This one is giving SNMPv1 energy. It gets the sysUpTime from a remote host. Iconic.

#! /usr/local/bin/perl
use strict;
use Net_SNMP_util;
my ($host, $ret)
$host = shift || 'localhost';
$ret = snmpget($host, 'sysUpTime');

print("sysUpTime for $host is $ret\n");

exit 0;

2. SNMPv3 set-request of sysContact

This one sets the sysContact info on the remote host to "Help Desk x911". Important tea: the parameters passed to the snmpset function are for the demonstration of syntax only. These parameters will need to be set according to the SNMPv3 parameters of the remote host used by the script. So don't just copy-paste the keys and think you're done, bestie. πŸ™ˆ

#! /usr/local/bin/perl
use strict;
use Net_SNMP_util;
my($host, %v3hash, $ret);
$host = shift || 'localhost';
$v3hash{'-version'}         = 'snmpv3';
$v3hash{'-username'}        = 'myv3Username';
$v3hash{'-authkey'}         = '0x05c7fbde31916f64da4d5b77156bdfa7';
$v3hash{'-authprotocol'}    = 'md5';
$v3hash{'-privkey'}         = '0x93725fd3a02a48ce02df4e065a1c1746';

$ret = snmpset($host, \%v3hash, 'sysContact', 'string', 'Help Desk x911');

print "sysContact on $host is now $ret\n";
exit 0;

3. SNMPv2c walk for ifTable

This one gets the contents of the ifTable by sending get-bulk-requests until the responses are no longer part of the ifTable. Fun fact: the ifTable can also be retrieved using "snmpmaptable". Slay.

#! /usr/local/bin/perl
use strict;
use Net_SNMP_util;
my($host, @ret, $oid, $val);
$host = shift || 'localhost';

@ret = snmpwalk($host . ':::::2', 'ifTable');
foreach $val (@ret) {
    ($oid, $val) = split(':', $val, 2);
    print "$oid => $val\n";
}
exit 0;

4. SNMPv2c maptable collecting ifDescr, ifInOctets, and ifOutOctets.

This one collects a table containing the columns ifDescr, ifInOctets, and ifOutOctets. A printing function is called once per row. So organized. 🫢

#! /usr/local/bin/perl
use strict;
use Net_SNMP_util;

sub printfun($$$$) {
    my($inst, $desc, $in, $out) = @_;
    printf "%3d %-52.52s %10d %10d\n", $inst, $desc, $in, $out;
}

my($host, @ret);
$host = shift || 'localhost';

printf "%-3s %-52s %10s %10s\n", "Int", "Description", "In", "Out";
@ret = snmpmaptable($host . ':::::2', \&printfun,
                    'ifDescr', 'ifInOctets', 'ifOutOctets');

exit 0;

🌸 REQUIREMENTS 🌸

  • The Net_SNMP_util module uses syntax that is not supported in versions of Perl earlier than v5.6.0. So if you're on some ancient Perl, it's not gonna work, bestie. Upgrade era. πŸ’€
  • The Net_SNMP_util module uses the Net::SNMP module, and as such may depend on other modules. Please see the documentation on Net::SNMP for more information. Basically, check the Net::SNMP docs for the full dependency lore. πŸ“š

πŸ‘‘ AUTHOR πŸ‘‘

Mike Mitchell <Mike.Mitchell@sas.com>

The icon who wrote this. Bow down. πŸ‘‘


πŸ’– ACKNOWLEGEMENTS πŸ’–

The original concept for this module was based on SNMP_Session.pm written by Simon Leinen <simon@switch.ch>. Shoutout to Simon, fr fr. 🫢


Copyright (c) 2007 Mike Mitchell. All rights reserved. This program is free software; you may redistribute it and/or modify it under the same terms as Perl itself.


And that's the whole vibe, bestie. This page is Net_SNMP_util(3pm), from perl v5.36.0, dated 2023-06-16. Now go be the main character of your network. πŸ’…βœ¨

πŸ“¦ where this page comes from