1SNMP_Session(3) User Contributed Perl Documentation SNMP_Session(3)
2
3
4
6 SNMP_Session - SNMPv1/v2 Protocol Handling
7
9 use SNMP_Session;
10 $session = SNMP_Session->open ($host, $community, $port)
11 or die "couldn't open SNMP session to $host";
12 if ($session->get_request_response ($oid1, $oid2, ...)) {
13 ($bindings) = $session->decode_get_response ($session->{pdu_buffer});
14 while ($bindings ne '') {
15 ($binding,$bindings) = decode_sequence ($bindings);
16 ($oid,$value) = decode_by_template ($binding, "%O%@");
17 print pretty_print ($oid)," => ", pretty_print ($value), "\n";
18 }
19 } else {
20 die "No response from agent on $host";
21 }
22
24 The "default_..." variables all specify default values that are used
25 for "SNMP_Session" objects when no other value is specified. These
26 values can be overridden on a per-session basis, for example by passing
27 additional arguments to the constructor.
28
29 $default_max_repetitions - default value for "maxRepetitions".
30 This specifies how many table rows are requested in "getBulk" requests.
31 Used when walking tables using "getBulk" (only available in SNMPv2(c)
32 and later). If this is too small, then a table walk will need
33 unnecessarily many request/response exchanges. If it is too big, the
34 agent may compute many variables after the end of the table. It is
35 recommended to set this explicitly for each table walk by using
36 map_table_4().
37
38 $default_avoid_negative_request_ids - default value for
39 "avoid_negative_request_ids".
40 Set this to non-zero if you have agents that have trouble with negative
41 request IDs, and don't forget to complain to your agent vendor.
42 According to the spec (RFC 1905), the request-id is an "Integer32",
43 i.e. its range is from -(2^31) to (2^31)-1. However, some agents
44 erroneously encode the response ID as an unsigned, which prevents this
45 code from matching such responses to requests.
46
47 $default_use_16bit_request_ids - default value for "use_16bit_request_ids".
48 Set this to non-zero if you have agents that use 16bit request IDs, and
49 don't forget to complain to your agent vendor.
50
51 $errmsg - error message from last failed operation.
52 When they encounter errors, the routines in this module will generally
53 return "undef") and leave an informative error message in $errmsg).
54
55 $suppress_warnings - whether warnings should be suppressed.
56 If this variable is zero, as is the default, this code will output
57 informative error messages whenever it encounters an error. Set this
58 to a non-zero value if you want to suppress these messages. In any
59 case, the last error message can be found in $errmsg.
60
62 The abstract class "SNMP_Session" defines objects that can be used to
63 communicate with SNMP entities. It has methods to send requests to and
64 receive responses from an agent.
65
66 Two instantiable subclasses are defined: "SNMPv1_Session" implements
67 SNMPv1 (RFC 1157) functionality "SNMPv2c_Session" implements community-
68 based SNMPv2 (RFC 3410-3417).
69
70 open() - create an SNMP session object
71 $session = SNMP_Session->open
72 ($host, $community, $port,
73 $max_pdu_len, $local_port, $max_repetitions,
74 $local_host, $ipv4only);
75
76 The calling and return conventions are identical to
77 SNMPv1_Session::open().
78
79 timeout() - return timeout value.
80 Initial timeout, in seconds, to wait for a response PDU after a request
81 is sent. Note that when a request is retried, the timeout is increased
82 by backoff (see below). The standard value is 2.0 (seconds).
83
84 retries() - number of attempts to get a reply.
85 Maximum number of attempts to get a reply for an SNMP request. If no
86 response is received after timeout seconds, the request is resent and a
87 new response awaited with a longer timeout, see the documentation on
88 backoff below. The retries value should be at least 1, because the
89 first attempt counts, too (the name "retries" is confusing, sorry for
90 that).
91
92 backoff() - backoff factor.for timeout on successive retries.
93 Default backoff factor for "SNMP_Session" objects. This factor is used
94 to increase the TIMEOUT every time an SNMP request is retried. The
95 standard value is 1.0, which means the same timeout is used for all
96 attempts.
97
98 set_timeout() - set initial timeout for session
99 set_retries() - set maximum number of attempts for session
100 set_backoff() - set backoff factor for session
101 Example usage:
102
103 $session->set_backoff (1.5);
104
105 ..._request_response() - Send some request and receive response.
106 Encodes a specific SNMP request, sends it to the destination address of
107 the session, and waits for a matching response. If such a response is
108 received, this function will return the size of the response, which is
109 necessarily greater than zero.
110
111 An undefined value is returned if some error happens during encoding or
112 sending, or if no matching response is received after the wait/retry
113 schedule is exhausted. See the documentation on the timeout(),
114 retries(), and backoff() methods on how the wait/retry logic works.
115
116 get_request_response() - Send "get" request and receive response.
117 getnext_request_response() - Send "get-next" request and receive response.
118 $result = $session->get_request_response (@encoded_oids);
119 $result = $session->getnext_request_response (@encoded_oids);
120
121 set_request_response() - Send "set" request and receive response.
122 $result = $session->set_request_response (@encoded_pair_list);
123
124 This method takes its arguments in a different form; they are a list of
125 pairs - references to two-element arrays - which respresent the
126 variables to be set and the intended values, e.g.
127
128 ([$encoded_oid_0, $encoded_value_0],
129 [$encoded_oid_1, $encoded_value_1],
130 [$encoded_oid_2, $encoded_value_2], ...)
131
132 trap_request_send() - send SNMPv1 Trap.
133 $result = $session->trap_request_send ($ent, $gent, $gen, $spec, $dt, @pairs);
134
135 v2_trap_request_send() - send SNMPv2 Trap.
136 $result = $session->v2_trap_request_send ($trap_oid, $dt, @pairs);
137
138 map_table() - traverse an SNMP table.
139 $result = $session->map_table ([$col0, $col1, ...], $mapfn);
140
141 This will call the provided function (&$mapfn) once for each row of the
142 table defined by the column OIDs $col0, $col1... If the session can
143 handle SNMPv2 operations, "get-bulk" will be used to traverse the
144 table. Otherwise, "get-next" will be used.
145
146 If the first argument is a list of n columns, the mapping function will
147 be called with n+1 arguments. The first argument will be the row
148 index, i.e. the list of sub-IDs that was appended to the provided
149 column OIDs for this row. Note that the row index will be represented
150 as a string, using dot-separated numerical OID notation.
151
152 The remaining arguments to the mapping function will be the values of
153 each column at the current index. It is possible that the table has
154 "holes", i.e. that for a given row index, not all columns have a value.
155 For columns with no value at the current row index, "undef" will be
156 passed to the mapping function.
157
158 If an error is encountered at any point during the table traversal,
159 this method will return undef and leave an error message in $errmsg
160 (which is also written out unless $suppress_warnings is non-zero).
161
162 Otherwise, the function will return the number of rows traversed, i.e.
163 the number of times that the mapping function has been called.
164
165 map_table_4() - traverse an SNMP table with more control.
166 map_table_start_end() - traverse an SNMP table with lower/upper index
167 limits.
168 $result = $session->map_table_start_end ($columns, $mapfn,
169 $start, $end, $max_repetition);
170
171 Similar to map_table_4(), except that the start and end index can be
172 specified.
173
174 receive_trap_1() - receive message on trap socket.
175 This method waits until a message is received on the trap socket. If
176 successful, it returns two values: the message that was received, and
177 the address of the sender as a "sockaddr" structure. This address can
178 be passed to getnameinfo() to convert it to readable output.
179
180 This method doesn't check whether the message actually encodes a trap
181 or anything else - the caller should use decode_trap_request() to find
182 out.
183
184 receive_trap() - receive message on trap socket (deprecated version).
185 This function is identical to receive_trap_1(), except that it returns
186 the sender address as three (formerly two) separate values: The host IP
187 address, the port, and (since version 1.14) the address family. If you
188 use this, please consider moving to receive_trap_1(), because it is
189 easier to process the sender address in sockaddr format, in particular
190 in a world where IPv4 and IPv6 coexist.
191
192 decode_trap_request()
193 ($community, $ent, $agent, $gen, $spec, $dt, $bindings)
194 = $session->decode_trap_request ($trap);
195
196 Given a message such as one returned as the first return value from
197 receive_trap_1() or receive_trap(), try to decode it as some
198 notification PDU. The code can handle SNMPv1 and SNMPv2 traps as well
199 as SNMPv2 INFORMs, although it fails to distinguish traps from informs,
200 which makes it hard to handle informs correctly (they should be
201 acknowledged).
202
203 The $ent, $agent, $gen, $spec, and $dt values will only be defined for
204 SNMPv1 traps. For SNMPv2 traps and informs, some of this information
205 will be encoded as bindings.
206
208 open() - create an SNMPv1 session object
209 $session = SNMPv1_Session->open
210 ($host, $community, $port,
211 $max_pdu_len, $local_port, $max_repetitions,
212 $local_host, $ipv4only);
213
214 Note that all arguments except for $host are optional. The $host can
215 be specified either as a hostname or as a numeric address. Numeric
216 IPv6 addresses must be enclosed in square brackets []
217
218 $community defaults to "public".
219
220 $port defaults to 161, the standard UDP port to send SNMP requests to.
221
222 $max_pdu_len defaults to 8000.
223
224 $local_port can be specified if a specific local port is desired, for
225 example because of firewall rules for the response packets. If none is
226 specified, the operating system will choose a random port.
227
228 $max_repetitions is the maximum number of repetitions requested in
229 "get-bulk" requests. It is only relevant in SNMPv2(c) and later.
230
231 $local_host can be used to specify a specific address/interface. It is
232 useful on hosts that have multiple addresses if a specific address
233 should be used, for example because of firewall rules.
234
235 If $ipv4only is either not present or non-zero, then an IPv4-only
236 socket will be used. This is also the case if the system only supports
237 IPv4. Otherwise, an IPv6 socket is created. IPv6 sockets support both
238 IPv6 and IPv4 requests and responses.
239
240 open_trap_session() - create a session for receiving SNMP traps.
241 $session = open_trap_session ($port, $ipv4only);
242
243 $port defaults to 162, the standard UDP port that SNMP notifications
244 are sent to.
245
246 If $ipv4only is either not present or non-zero, then an IPv4-only
247 socket will be used. This is also the case if the system only supports
248 IPv4. Otherwise, an IPv6 socket is created. IPv6 sockets can receive
249 messages over both IPv6 and IPv4.
250
252 open() - create an SNMPv2(c) session object
253 $session = SNMPv2c_Session->open
254 ($host, $community, $port,
255 $max_pdu_len, $local_port, $max_repetitions,
256 $local_host, $ipv4only);
257
258 The calling and return conventions are identical to
259 SNMPv1_Session::open(), except that this returns a session object that
260 supports SNMPv2 operations.
261
263 The basic usage of these routines works like this:
264
265 use BER;
266 use SNMP_Session;
267
268 # Set $host to the name of the host whose SNMP agent you want
269 # to talk to. Set $community to the community name under
270 # which you want to talk to the agent. Set port to the UDP
271 # port on which the agent listens (usually 161).
272
273 $session = SNMP_Session->open ($host, $community, $port)
274 or die "couldn't open SNMP session to $host";
275
276 # Set $oid1, $oid2... to the BER-encoded OIDs of the MIB
277 # variables you want to get.
278
279 if ($session->get_request_response ($oid1, $oid2, ...)) {
280 ($bindings) = $session->decode_get_response ($session->{pdu_buffer});
281
282 while ($bindings ne '') {
283 ($binding,$bindings) = decode_sequence ($bindings);
284 ($oid,$value) = decode_by_template ($binding, "%O%@");
285 print pretty_print ($oid)," => ", pretty_print ($value), "\n";
286 }
287 } else {
288 die "No response from agent on $host";
289 }
290
291 Encoding OIDs
292 In order to BER-encode OIDs, you can use the function BER::encode_oid.
293 It takes (a vector of) numeric subids as an argument. For example,
294
295 use BER;
296 encode_oid (1, 3, 6, 1, 2, 1, 1, 1, 0)
297
298 will return the BER-encoded OID for the sysDescr.0 (1.3.6.1.2.1.1.1.0)
299 instance of MIB-2.
300
301 Decoding the results
302 When get_request_response() returns success, you must decode the
303 response PDU from the remote agent. The function decode_get_response()
304 can be used to do this. It takes a "get-response" PDU, checks its
305 syntax and returns the bindings part of the PDU. This is where the
306 remote agent actually returns the values of the variables in your
307 query.
308
309 You should iterate over the individual bindings in this bindings part
310 and extract the value for each variable. In the example above, the
311 returned bindings are simply printed using the BER::pretty_print()
312 function.
313
314 For better readability of the OIDs, you can also use the following
315 idiom, where the %pretty_oids hash maps BER-encoded numerical OIDs to
316 symbolic OIDs. Note that this simple-minded mapping only works for
317 response OIDs that exactly match known OIDs, so it's unsuitable for
318 table walking (where the response OIDs include an additional row
319 index).
320
321 %ugly_oids = qw(sysDescr.0 1.3.6.1.2.1.1.1.0
322 sysContact.0 1.3.6.1.2.1.1.4.0);
323 foreach (keys %ugly_oids) {
324 $ugly_oids{$_} = encode_oid (split (/\./, $ugly_oids{$_}));
325 $pretty_oids{$ugly_oids{$_}} = $_;
326 }
327 ...
328 if ($session->get_request_response ($ugly_oids{'sysDescr.0'},
329 $ugly_oids{'sysContact.0'})) {
330 ($bindings) = $session->decode_get_response ($session->{pdu_buffer});
331 while ($bindings ne '') {
332 ($binding,$bindings) = decode_sequence ($bindings);
333 ($oid,$value) = decode_by_template ($binding, "%O%@");
334 print $pretty_oids{$oid}," => ",
335 pretty_print ($value), "\n";
336 }
337 } ...
338
339 Set Requests
340 Set requests are generated much like "get" or "getNext" requests are,
341 with the exception that you have to specify not just OIDs, but also the
342 values the variables should be set to. Every binding is passed as a
343 reference to a two-element array, the first element being the encoded
344 OID and the second one the encoded value. See the "test/set-test.pl"
345 script for an example, in particular the subroutine "snmpset".
346
347 Walking Tables
348 Beginning with version 0.57 of "SNMP_Session.pm", there is API support
349 for walking tables. The map_table() method can be used for this as
350 follows:
351
352 sub walk_function ($$$) {
353 my ($index, $val1, $val3) = @_;
354 ...
355 }
356
357 ...
358 $columns = [$base_oid1, $base_oid3];
359 $n_rows = $session->map_table ($columns, \&walk_function);
360
361 The columns argument must be a reference to a list of OIDs for table
362 columns sharing the same index. The method will traverse the table and
363 call the walk_function for each row. The arguments for these calls will
364 be:
365
366 1. the row index as a partial OID in dotted notation, e.g. 1.3, or
367 10.0.1.34.
368 2. the values of the requested table columns in that row, in BER-
369 encoded form. If you want to use the standard pretty_print() subroutine
370 to decode the values, you can use the following idiom:
371 grep (defined $_ && ($_=pretty_print $_), ($val1, $val3));
372
373 Walking Tables With "get-bulk"
374 Since version 0.67, "SNMP_Session" uses a different "get_table"
375 implementation for "SNMPv2c_Session"s. This version uses the ``powerful
376 "get-bulk" operator'' to retrieve many table rows with each request. In
377 general, this will make table walking much faster under SNMPv2c,
378 especially when round-trip times to the agent are long.
379
380 There is one difficulty, however: With "get-bulk", a management
381 application can specify the maximum number of rows to return in a
382 single response. "SNMP_Session.pm" provides a new function,
383 "map_table_4", in which this "maxRepetitions" value can be specified
384 explicitly.
385
386 For maximum efficiency, it should be set to a value that is one greater
387 than the number of rows in the table. If it is smaller, then
388 map_table() will use more request/response cycles than necessary; if it
389 is bigger, the agent will have to compute variable bindings beyond the
390 end of the table (which map_table() will throw away).
391
392 Of course it is usually impossible to know the size of the table in
393 advance. If you don't specify "maxRepetitions" when walking a table,
394 then map_table() will use a per-session default
395 ("$session->default_max_repetitions"). The default value for this
396 default is 12.
397
398 If you walk a table multiple times, and the size of the table is
399 relatively stable, you should use the return value of map_table()
400 (which is the number of rows it has encountered) to compute the next
401 value of "maxRepetitions". Remember to add one so that map_table()
402 notices when the table is finished!
403
404 Note that for really big tables, this doesn't make a big difference,
405 since the table won't fit in a single response packet anyway.
406
407 Sending Traps
408 To send a trap, you have to open an SNMP session to the trap receiver.
409 Usually this is a process listening to UDP port 162 on a network
410 management station. Then you can use the trap_request_send() method to
411 encode and send SNMPv1 traps. There is no way to find out whether the
412 trap was actually received at the management station - SNMP traps are
413 fundamentally unreliable.
414
415 When constructing an SNMPv1 trap, you must provide
416
417 • the "enterprise" Object Identifier for the entity that generates
418 the trap
419
420 • your IP address
421
422 • the generic trap type
423
424 • the specific trap type
425
426 • the "sysUpTime" at the time of trap generation
427
428 • a sequence (may be empty) of variable bindings further describing
429 the trap.
430
431 For SNMPv2 traps, you need:
432
433 • the trap's OID
434
435 • the "sysUpTime" at the time of trap generation
436
437 • the bindings list as above
438
439 For SNMPv2 traps, the uptime and trap OID are encoded as bindings which
440 are added to the front of the other bindings you provide.
441
442 Here is a short example:
443
444 my $trap_receiver = "netman.noc";
445 my $trap_community = "SNMP_Traps";
446 my $trap_session = $version eq '1'
447 ? SNMP_Session->open ($trap_receiver, $trap_community, 162)
448 : SNMPv2c_Session->open ($trap_receiver, $trap_community, 162);
449 my $myIpAddress = ...;
450 my $start_time = time;
451
452 ...
453
454 sub link_down_trap ($$) {
455 my ($if_index, $version) = @_;
456 my $genericTrap = 2; # linkDown
457 my $specificTrap = 0;
458 my @ifIndexOID = ( 1,3,6,1,2,1,2,2,1,1 );
459 my $upTime = int ((time - $start_time) * 100.0);
460 my @myOID = ( 1,3,6,1,4,1,2946,0,8,15 );
461
462 warn "Sending trap failed"
463 unless ($version eq '1')
464 ? $trap_session->trap_request_send (encode_oid (@myOID),
465 encode_ip_address ($myIpAddress),
466 encode_int ($genericTrap),
467 encode_int ($specificTrap),
468 encode_timeticks ($upTime),
469 [encode_oid (@ifIndex_OID,$if_index),
470 encode_int ($if_index)],
471 [encode_oid (@ifDescr_OID,$if_index),
472 encode_string ("foo")])
473 : $trap_session->v2_trap_request_send (\@linkDown_OID, $upTime,
474 [encode_oid (@ifIndex_OID,$if_index),
475 encode_int ($if_index)],
476 [encode_oid (@ifDescr_OID,$if_index),
477 encode_string ("foo")]);
478 }
479
480 Receiving Traps
481 Since version 0.60, "SNMP_Session.pm" supports the receipt and decoding
482 of SNMPv1 trap requests. Since version 0.75, SNMPv2 Trap PDUs are also
483 recognized.
484
485 To receive traps, you have to create a special SNMP session that
486 passively listens on the SNMP trap transport address, usually on UDP
487 port 162. Then you can receive traps - actually, SNMPv1 traps, SNMPv2
488 traps, and SNMPv2 informs, using the receive_trap_1() method and decode
489 them using decode_trap_request(). The enterprise, agent, generic,
490 specific and sysUptime return values are only defined for SNMPv1 traps.
491 In SNMPv2 traps and informs, the equivalent information is contained in
492 the bindings.
493
494 my $trap_session = SNMPv1_Session->open_trap_session (162, 0)
495 or die "cannot open trap session";
496 my ($trap, $sender_sockaddr) = $trap_session->receive_trap_1 ()
497 or die "cannot receive trap";
498 my ($community, $enterprise, $agent,
499 $generic, $specific, $sysUptime, $bindings)
500 = $trap_session->decode_trap_request ($trap)
501 or die "cannot decode trap received"
502 ...
503 my ($binding, $oid, $value);
504 while ($bindings ne '') {
505 ($binding,$bindings) = decode_sequence ($bindings);
506 ($oid, $value) = decode_by_template ($binding, "%O%@");
507 print BER::pretty_oid ($oid)," => ",pretty_print ($value),"\n";
508 }
509
511 Created by: Simon Leinen <simon.leinen@switch.ch>
512
513 Contributions and fixes by:
514
515 Matthew Trunnell <matter@media.mit.edu>
516 Tobias Oetiker <tobi@oetiker.ch>
517 Heine Peters <peters@dkrz.de>
518 Daniel L. Needles <dan_needles@INS.COM>
519 Mike Mitchell <mcm@unx.sas.com>
520 Clinton Wong <clintdw@netcom.com>
521 Alan Nichols <Alan.Nichols@Ebay.Sun.COM>
522 Mike McCauley <mikem@open.com.au>
523 Andrew W. Elble <elble@icculus.nsg.nwu.edu>
524 Brett T Warden <wardenb@eluminant.com>: pretty "UInteger32"
525 Michael Deegan <michael@cnspc18.murdoch.edu.au>
526 Sergio Macedo <macedo@tmp.com.br>
527 Jakob Ilves (/IlvJa) <jakob.ilves@oracle.com>: PDU capture
528 Valerio Bontempi <v.bontempi@inwind.it>: IPv6 support
529 Lorenzo Colitti <lorenzo@colitti.com>: IPv6 support
530 Philippe Simonet <Philippe.Simonet@swisscom.com>: Export "avoid..."
531 Luc Pauwels <Luc.Pauwels@xalasys.com>: "use_16bit_request_ids"
532 Andrew Cornford-Matheson <andrew.matheson@corenetworks.com>: inform
533 Gerry Dalton <gerry.dalton@consolidated.com>: "strict subs" bug
534 Mike Fischer <mlf2@tampabay.rr.com>: pass MSG_DONTWAIT to recv()
535
537 Copyright (c) 1995-2009, Simon Leinen.
538
539 This program is free software; you can redistribute it under the
540 "Artistic License 2.0" included in this distribution (file "Artistic").
541
542
543
544perl v5.38.0 2023-07-21 SNMP_Session(3)