From 2f24177c361ba4d9deba2d7378f84aa96111db80 Mon Sep 17 00:00:00 2001 From: elie Date: Mon, 14 Sep 2015 05:20:24 +0000 Subject: * synchronous oneliner apps redesigned to offer Python generator-based API along with a more comprehensive set of accepted parameters. * massively documented (in Sphinx, NumPy style) --- CHANGES.txt | 124 +++-- TODO.txt | 56 ++ .../agent/cmdrsp/v2c-custom-scalar-mib-objects.py | 145 +++++ .../agent/ntforg/trap-v1-multiple-transports.py | 78 +++ examples/v1arch/asyncore/manager/cmdgen/get-v1.py | 105 ++++ .../manager/cmdgen/get-v2c-spoof-source-address.py | 117 ++++ .../get-v2c-udp-broadcast-agent-discovery.py | 99 ++++ .../v1arch/asyncore/manager/cmdgen/getbulk-v2c.py | 112 ++++ .../v1arch/asyncore/manager/cmdgen/getnext-v1.py | 103 ++++ examples/v1arch/asyncore/manager/cmdgen/set-v2c.py | 85 +++ .../manager/ntfrcv/v1-multiple-transports.py | 100 ++++ .../asyncio/agent/cmdrsp/v3-multiple-users.py | 47 +- examples/v3arch/asyncio/agent/ntforg/inform-v3.py | 38 +- examples/v3arch/asyncio/agent/ntforg/trap-v1.py | 46 +- .../manager/cmdgen/get-v2c-custom-timeout.py | 37 +- .../asyncio/manager/cmdgen/get-v2c-over-ipv6.py | 35 +- .../v3arch/asyncio/manager/cmdgen/getbulk-v2c.py | 39 +- .../cmdgen/getnext-v2c-from-specific-address.py | 39 +- examples/v3arch/asyncio/manager/cmdgen/set-v2c.py | 36 +- .../manager/ntfrcv/v2c-multiple-interfaces.py | 42 +- .../agent/cmdrsp/v1-read-and-write-communities.py | 65 +++ .../agent/cmdrsp/v2c-custom-scalar-mib-objects.py | 82 +++ .../agent/cmdrsp/v2c-custom-tabular-mib-objects.py | 126 +++++ .../agent/cmdrsp/v2c-multiple-interfaces.py | 67 +++ .../agent/cmdrsp/v2c-multiple-transports.py | 68 +++ .../agent/cmdrsp/v3-alternative-mib-controller.py | 77 +++ .../asyncore/agent/cmdrsp/v3-alternative-mib.py | 77 +++ .../asyncore/agent/cmdrsp/v3-custom-engine-id.py | 65 +++ .../agent/cmdrsp/v3-multiple-snmp-engines.py | 93 ++++ .../asyncore/agent/cmdrsp/v3-multiple-users.py | 80 +++ .../agent/cmdrsp/v3-observe-request-processing.py | 90 +++ .../v3-preserve-original-destination-address.py | 91 ++++ .../agent/ntforg/inform-multiple-protocols.py | 119 ++++ .../v3arch/asyncore/agent/ntforg/inform-v2c.py | 95 ++++ examples/v3arch/asyncore/agent/ntforg/inform-v3.py | 88 +++ .../agent/ntforg/trap-v1-from-specific-address.py | 82 +++ examples/v3arch/asyncore/agent/ntforg/trap-v1.py | 99 ++++ .../asyncore/agent/ntforg/trap-v2c-custom-pdu.py | 90 +++ .../agent/ntforg/trap-v2c-multiple-addresses.py | 110 ++++ .../agent/ntforg/trap-v2c-multiple-transports.py | 106 ++++ .../asyncore/agent/ntforg/trap-v2c-with-objects.py | 108 ++++ examples/v3arch/asyncore/agent/ntforg/trap-v2c.py | 95 ++++ examples/v3arch/asyncore/agent/ntforg/trap-v3.py | 90 +++ examples/v3arch/asyncore/manager/cmdgen/get-v1.py | 76 +++ .../manager/cmdgen/get-v2c-custom-timeout.py | 79 +++ .../manager/cmdgen/get-v2c-spoof-source-address.py | 100 ++++ .../manager/cmdgen/get-v3-custom-context.py | 84 +++ .../cmdgen/get-v3-observe-request-processing.py | 105 ++++ examples/v3arch/asyncore/manager/cmdgen/get-v3.py | 82 +++ .../v3arch/asyncore/manager/cmdgen/getbulk-v2c.py | 82 +++ .../v3arch/asyncore/manager/cmdgen/getbulk-v3.py | 85 +++ .../v3arch/asyncore/manager/cmdgen/getnext-v1.py | 83 +++ .../cmdgen/getnext-v2c-from-specific-address.py | 82 +++ .../getnext-v2c-with-mib-compilation-and-lookup.py | 94 ++++ .../manager/cmdgen/getnext-v3-over-ipv6.py | 82 +++ .../manager/cmdgen/getnext-v3-pull-subtree.py | 86 +++ examples/v3arch/asyncore/manager/cmdgen/set-v1.py | 80 +++ examples/v3arch/asyncore/manager/cmdgen/set-v2c.py | 76 +++ examples/v3arch/asyncore/manager/cmdgen/set-v3.py | 78 +++ .../manager/ntfrcv/v2c-multiple-interfaces.py | 70 +++ .../manager/ntfrcv/v2c-multiple-transports.py | 71 +++ .../ntfrcv/v2c-observe-request-processing.py | 94 ++++ .../ntfrcv/v2c-with-regexp-community-name.py | 88 +++ .../manager/ntfrcv/v2c-with-request-details.py | 69 +++ .../asyncore/manager/ntfrcv/v3-multiple-users.py | 111 ++++ .../ntforg/inform-async-multiple-snmp-engines.py | 88 +++ ...form-async-multiple-transports-and-protocols.py | 60 ++ .../agent/ntforg/inform-v2c-with-mib-lookup.py | 87 +-- .../inform-v3-with-custom-contextengineid.py | 94 ++-- .../ntforg/inform-v3-with-custom-contextname.py | 87 +-- .../asyncore/oneliner/agent/ntforg/inform-v3.py | 87 +-- ...trap-async-multiple-transports-and-protocols.py | 51 ++ .../agent/ntforg/trap-v1-with-custom-values.py | 82 +-- .../agent/ntforg/trap-v1-with-default-values.py | 76 +-- .../agent/ntforg/trap-v2c-with-mib-lookup.py | 60 +- .../agent/ntforg/trap-v3-with-custom-engineid.py | 78 +-- .../cmdgen/get-async-multiple-snmp-engines.py | 106 ++-- .../get-async-multiple-transports-and-protocols.py | 106 ++-- ...t-threaded-multiple-transports-and-protocols.py | 127 +++++ .../asyncore/oneliner/manager/cmdgen/get-v1.py | 68 +-- .../get-v2c-with-custom-timeout-and-retries.py | 98 ++-- .../get-v2c-with-mib-compilation-and-lookup.py | 72 +-- .../asyncore/oneliner/manager/cmdgen/get-v2c.py | 69 +-- .../manager/cmdgen/get-v3-auth-priv-sha-aes128.py | 57 ++ .../oneliner/manager/cmdgen/get-v3-auth-priv.py | 39 ++ .../manager/cmdgen/get-v3-multiple-calls.py | 47 ++ .../manager/cmdgen/get-v3-noauth-nopriv.py | 39 ++ .../cmdgen/get-v3-over-ipv6-with-mib-lookup.py | 74 +-- .../manager/cmdgen/get-v3-table-object-by-index.py | 72 +-- .../get-v3-table-object-by-multiple-indices.py | 82 +-- .../cmdgen/get-v3-with-custom-security-name.py | 74 ++- .../manager/cmdgen/get-v3-with-mib-lookup.py | 67 +-- .../cmdgen/get-v3-with-specific-engine-id.py | 73 +-- .../cmdgen/getbulk-v2c-limiting-number-of-rows.py | 47 ++ .../oneliner/manager/cmdgen/getbulk-v2c.py | 56 +- .../getbulk-v3-limiting-number-of-packets.py | 44 ++ .../cmdgen/getbulk-v3-over-ipv6-with-mib-lookup.py | 58 +- .../getbulk-v3-with-custom-mib-path-and-options.py | 61 ++- ...next-async-multiple-transports-and-protocols.py | 96 ++-- .../cmdgen/getnext-v1-with-custom-mibs-location.py | 79 +-- .../asyncore/oneliner/manager/cmdgen/getnext-v1.py | 61 ++- .../cmdgen/getnext-v2c-with-mib-resolution.py | 66 ++- .../oneliner/manager/cmdgen/getnext-v2c.py | 53 +- .../cmdgen/getnext-v3-over-ipv6-with-mib-lookup.py | 58 +- .../getnext-v3-pull-whole-mib-with-mib-lookup.py | 55 +- .../getnext-v3-pull-whole-mib-with-options.py | 60 +- .../manager/cmdgen/set-v1-multiple-values.py | 83 +-- .../cmdgen/set-v2c-with-value-type-mib-lookup.py | 71 +-- ...-with-custom-contextengineid-and-contextname.py | 84 +-- .../cmdgen/set-v3-with-custom-contextengineid.py | 83 ++- .../cmdgen/set-v3-with-value-type-mib-lookup.py | 78 +-- .../proxy/command/udp6-to-udp4-conversion.py | 142 +++++ .../asyncore/proxy/command/v2c-to-v1-conversion.py | 140 +++++ .../asyncore/proxy/command/v2c-to-v3-conversion.py | 140 +++++ .../asyncore/proxy/command/v3-to-v2c-conversion.py | 143 +++++ examples/v3arch/trollius/agent/ntforg/inform-v3.py | 38 +- examples/v3arch/trollius/agent/ntforg/trap-v1.py | 46 +- examples/v3arch/trollius/manager/cmdgen/get-v1.py | 36 +- .../manager/cmdgen/get-v2c-custom-timeout.py | 36 +- .../v3arch/trollius/manager/cmdgen/getbulk-v3.py | 38 +- .../v3arch/trollius/manager/cmdgen/getnext-v3.py | 36 +- examples/v3arch/trollius/manager/cmdgen/set-v2c.py | 36 +- .../agent/cmdrsp/v1-read-and-write-communities.py | 36 +- .../agent/cmdrsp/v2c-custom-scalar-mib-objects.py | 36 +- .../agent/cmdrsp/v2c-multiple-interfaces.py | 36 +- .../twisted/agent/cmdrsp/v3-multiple-users.py | 43 +- examples/v3arch/twisted/agent/ntforg/inform-v2c.py | 38 +- examples/v3arch/twisted/agent/ntforg/inform-v3.py | 34 +- examples/v3arch/twisted/agent/ntforg/trap-v1.py | 42 +- .../agent/ntforg/trap-v2c-multiple-targets.py | 48 +- examples/v3arch/twisted/agent/ntforg/trap-v3.py | 34 +- examples/v3arch/twisted/manager/cmdgen/get-v1.py | 31 +- .../manager/cmdgen/get-v2c-custom-timeout.py | 32 +- .../manager/cmdgen/get-v3-custom-context.py | 36 +- examples/v3arch/twisted/manager/cmdgen/get-v3.py | 30 +- .../v3arch/twisted/manager/cmdgen/getbulk-v2c.py | 34 +- .../v3arch/twisted/manager/cmdgen/getbulk-v3.py | 34 +- .../v3arch/twisted/manager/cmdgen/getnext-v1.py | 32 +- .../cmdgen/getnext-v2c-from-specific-address.py | 34 +- .../manager/cmdgen/getnext-v3-pull-subtree.py | 32 +- examples/v3arch/twisted/manager/cmdgen/set-v1.py | 30 +- examples/v3arch/twisted/manager/cmdgen/set-v2c.py | 30 +- examples/v3arch/twisted/manager/cmdgen/set-v3.py | 30 +- .../manager/ntfrcv/v2c-multiple-interfaces.py | 39 +- .../twisted/manager/ntfrcv/v3-multiple-users.py | 44 +- pysnmp/entity/rfc3413/oneliner/auth.py | 126 ++++- pysnmp/entity/rfc3413/oneliner/cmdgen.py | 313 ++--------- pysnmp/entity/rfc3413/oneliner/ctx.py | 35 ++ pysnmp/entity/rfc3413/oneliner/ntforg.py | 91 +--- pysnmp/entity/rfc3413/oneliner/sync/__init__.py | 1 + pysnmp/entity/rfc3413/oneliner/sync/cmdgen.py | 602 +++++++++++++++++++++ .../rfc3413/oneliner/sync/compat/__init__.py | 1 + .../entity/rfc3413/oneliner/sync/compat/cmdgen.py | 256 +++++++++ .../entity/rfc3413/oneliner/sync/compat/ntforg.py | 48 ++ pysnmp/entity/rfc3413/oneliner/sync/ntforg.py | 126 +++++ pysnmp/entity/rfc3413/oneliner/target.py | 81 +++ pysnmp/smi/rfc1902.py | 457 +++++++++++++++- setup.py | 2 + 158 files changed, 10158 insertions(+), 2343 deletions(-) create mode 100644 TODO.txt create mode 100644 examples/v1arch/asyncore/agent/cmdrsp/v2c-custom-scalar-mib-objects.py create mode 100644 examples/v1arch/asyncore/agent/ntforg/trap-v1-multiple-transports.py create mode 100644 examples/v1arch/asyncore/manager/cmdgen/get-v1.py create mode 100644 examples/v1arch/asyncore/manager/cmdgen/get-v2c-spoof-source-address.py create mode 100644 examples/v1arch/asyncore/manager/cmdgen/get-v2c-udp-broadcast-agent-discovery.py create mode 100644 examples/v1arch/asyncore/manager/cmdgen/getbulk-v2c.py create mode 100644 examples/v1arch/asyncore/manager/cmdgen/getnext-v1.py create mode 100644 examples/v1arch/asyncore/manager/cmdgen/set-v2c.py create mode 100644 examples/v1arch/asyncore/manager/ntfrcv/v1-multiple-transports.py create mode 100644 examples/v3arch/asyncore/agent/cmdrsp/v1-read-and-write-communities.py create mode 100644 examples/v3arch/asyncore/agent/cmdrsp/v2c-custom-scalar-mib-objects.py create mode 100644 examples/v3arch/asyncore/agent/cmdrsp/v2c-custom-tabular-mib-objects.py create mode 100644 examples/v3arch/asyncore/agent/cmdrsp/v2c-multiple-interfaces.py create mode 100644 examples/v3arch/asyncore/agent/cmdrsp/v2c-multiple-transports.py create mode 100644 examples/v3arch/asyncore/agent/cmdrsp/v3-alternative-mib-controller.py create mode 100644 examples/v3arch/asyncore/agent/cmdrsp/v3-alternative-mib.py create mode 100644 examples/v3arch/asyncore/agent/cmdrsp/v3-custom-engine-id.py create mode 100644 examples/v3arch/asyncore/agent/cmdrsp/v3-multiple-snmp-engines.py create mode 100644 examples/v3arch/asyncore/agent/cmdrsp/v3-multiple-users.py create mode 100644 examples/v3arch/asyncore/agent/cmdrsp/v3-observe-request-processing.py create mode 100644 examples/v3arch/asyncore/agent/cmdrsp/v3-preserve-original-destination-address.py create mode 100644 examples/v3arch/asyncore/agent/ntforg/inform-multiple-protocols.py create mode 100644 examples/v3arch/asyncore/agent/ntforg/inform-v2c.py create mode 100644 examples/v3arch/asyncore/agent/ntforg/inform-v3.py create mode 100644 examples/v3arch/asyncore/agent/ntforg/trap-v1-from-specific-address.py create mode 100644 examples/v3arch/asyncore/agent/ntforg/trap-v1.py create mode 100644 examples/v3arch/asyncore/agent/ntforg/trap-v2c-custom-pdu.py create mode 100644 examples/v3arch/asyncore/agent/ntforg/trap-v2c-multiple-addresses.py create mode 100644 examples/v3arch/asyncore/agent/ntforg/trap-v2c-multiple-transports.py create mode 100644 examples/v3arch/asyncore/agent/ntforg/trap-v2c-with-objects.py create mode 100644 examples/v3arch/asyncore/agent/ntforg/trap-v2c.py create mode 100644 examples/v3arch/asyncore/agent/ntforg/trap-v3.py create mode 100644 examples/v3arch/asyncore/manager/cmdgen/get-v1.py create mode 100644 examples/v3arch/asyncore/manager/cmdgen/get-v2c-custom-timeout.py create mode 100644 examples/v3arch/asyncore/manager/cmdgen/get-v2c-spoof-source-address.py create mode 100644 examples/v3arch/asyncore/manager/cmdgen/get-v3-custom-context.py create mode 100644 examples/v3arch/asyncore/manager/cmdgen/get-v3-observe-request-processing.py create mode 100644 examples/v3arch/asyncore/manager/cmdgen/get-v3.py create mode 100644 examples/v3arch/asyncore/manager/cmdgen/getbulk-v2c.py create mode 100644 examples/v3arch/asyncore/manager/cmdgen/getbulk-v3.py create mode 100644 examples/v3arch/asyncore/manager/cmdgen/getnext-v1.py create mode 100644 examples/v3arch/asyncore/manager/cmdgen/getnext-v2c-from-specific-address.py create mode 100644 examples/v3arch/asyncore/manager/cmdgen/getnext-v2c-with-mib-compilation-and-lookup.py create mode 100644 examples/v3arch/asyncore/manager/cmdgen/getnext-v3-over-ipv6.py create mode 100644 examples/v3arch/asyncore/manager/cmdgen/getnext-v3-pull-subtree.py create mode 100644 examples/v3arch/asyncore/manager/cmdgen/set-v1.py create mode 100644 examples/v3arch/asyncore/manager/cmdgen/set-v2c.py create mode 100644 examples/v3arch/asyncore/manager/cmdgen/set-v3.py create mode 100644 examples/v3arch/asyncore/manager/ntfrcv/v2c-multiple-interfaces.py create mode 100644 examples/v3arch/asyncore/manager/ntfrcv/v2c-multiple-transports.py create mode 100644 examples/v3arch/asyncore/manager/ntfrcv/v2c-observe-request-processing.py create mode 100644 examples/v3arch/asyncore/manager/ntfrcv/v2c-with-regexp-community-name.py create mode 100644 examples/v3arch/asyncore/manager/ntfrcv/v2c-with-request-details.py create mode 100644 examples/v3arch/asyncore/manager/ntfrcv/v3-multiple-users.py create mode 100644 examples/v3arch/asyncore/oneliner/agent/ntforg/inform-async-multiple-snmp-engines.py create mode 100644 examples/v3arch/asyncore/oneliner/agent/ntforg/inform-async-multiple-transports-and-protocols.py create mode 100644 examples/v3arch/asyncore/oneliner/agent/ntforg/trap-async-multiple-transports-and-protocols.py create mode 100644 examples/v3arch/asyncore/oneliner/manager/cmdgen/get-threaded-multiple-transports-and-protocols.py create mode 100644 examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-auth-priv-sha-aes128.py create mode 100644 examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-auth-priv.py create mode 100644 examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-multiple-calls.py create mode 100644 examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-noauth-nopriv.py create mode 100644 examples/v3arch/asyncore/oneliner/manager/cmdgen/getbulk-v2c-limiting-number-of-rows.py create mode 100644 examples/v3arch/asyncore/oneliner/manager/cmdgen/getbulk-v3-limiting-number-of-packets.py create mode 100644 examples/v3arch/asyncore/proxy/command/udp6-to-udp4-conversion.py create mode 100644 examples/v3arch/asyncore/proxy/command/v2c-to-v1-conversion.py create mode 100644 examples/v3arch/asyncore/proxy/command/v2c-to-v3-conversion.py create mode 100644 examples/v3arch/asyncore/proxy/command/v3-to-v2c-conversion.py create mode 100644 pysnmp/entity/rfc3413/oneliner/sync/__init__.py create mode 100644 pysnmp/entity/rfc3413/oneliner/sync/cmdgen.py create mode 100644 pysnmp/entity/rfc3413/oneliner/sync/compat/__init__.py create mode 100644 pysnmp/entity/rfc3413/oneliner/sync/compat/cmdgen.py create mode 100644 pysnmp/entity/rfc3413/oneliner/sync/compat/ntforg.py create mode 100644 pysnmp/entity/rfc3413/oneliner/sync/ntforg.py diff --git a/CHANGES.txt b/CHANGES.txt index 8a58ef9..7d812f6 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,6 +1,6 @@ -Revision 4.3.0 --------------- +Revision 4.3.0, work in progress +-------------------------------- - Critical error fixed in key localization procedure for AES192/AES256/3DES cyphers. Previous versions might never worked properly in this respect. @@ -9,6 +9,7 @@ Revision 4.3.0 example scripts added. Obsolete libsmi-based scripts removed. - Major rewrite of native SNMPv3 CommandGenerator and NotificationOriginator applications towards the following goals: + * avoid binding to specific SNMP engine instance to promote single SNMP app instance using many SNMP engine instances * support two APIs for working with request data: one operates on the @@ -23,6 +24,7 @@ Revision 4.3.0 * Synchronous oneliner apps redesigned to offer Python generator-based API along with a more comprehensive set of accepted parameters. * keep backward compatibility for all existing major/documented interfaces + - Execution Observer facility implemented to give app an inside view of SNMP engine inner workings. This is thought to be a generic framework for viewing (and modifying) various internal states @@ -41,11 +43,13 @@ Revision 4.3.0 among other things, in the context of a transparent SNMP proxy application. Technically, the following features were brought into pysnmp with this update: + * Sending SNMP packets from a non-local IP address * Receiving IP packets for non-local IP addresses * Responding to SNMP requests from exactly the same IP address the query was sent to. This proves to be useful when listening on both primary and secondary IP interfaces. + - Internal oneliner apps configuration cache moved from respective apps objects to [a singular] snmpEngine "user context" object. That would allow for better cache reuse and allow for a single app @@ -158,8 +162,8 @@ Revision 4.3.0 (but ENOENT) and raise IOError uniformly on any directory/egg access failure. -Revision 4.2.5 --------------- +Revision 4.2.5, released 2013-10-02 +----------------------------------- - License updated to vanilla BSD 2-Clause to ease package use (http://opensource.org/licenses/BSD-2-Clause). @@ -281,8 +285,8 @@ Revision 4.2.5 - Missing import added to oneliner auth module. - Cosmetic changes to v3arch example scripts. -Revision 4.2.4 --------------- +Revision 4.2.4, released 2013-01-30 +----------------------------------- - SNMPv3 high-level and native API examples reworked and extended to cover many use cases. @@ -310,7 +314,7 @@ Revision 4.2.4 - Catch possible exceptions on pyasn1 encoder invocation. - VACM modules converted from a function into an object to let it keep state (caches) in the future. -- Unnecessary *MibSource explicit initialization calls removed at MibBuilder. +- Unnecessary MibSource explicit initialization calls removed at MibBuilder. - Example configuration for Net-SNMP's snmptrapd added. - Cast additionalVarBinds into ObjectIdentifier type at NotificationOriginator.sendNotification() @@ -323,7 +327,7 @@ Revision 4.2.4 a) the notificationType param mandatory b)t e varBinds param really optional - Fixes to ContextEngineId/ContextName support at the oneliner API: now - both items should be passed to request PDU through *Cmd() request + both items should be passed to request PDU through Cmd() request initiation method, the items of authData object should be used only for LCD configuration. - Fix to MibVariable handling of the MIB, initializers. @@ -347,8 +351,8 @@ Revision 4.2.4 SNMP working again. Wrong method (instumClone) was probed at terminal MIB nodes values instead of the right one (setValue). -Revision 4.2.3 --------------- +Revision 4.2.3, released 2012-09-06 +----------------------------------- - SECURITY FIX: USM subsystem did not verify securityLevel of a request to an authoritative SNMP engine against auth/priv protocols @@ -464,8 +468,8 @@ Revision 4.2.3 - Typo fix to snmpInASNParseErrs MIB instance object. - Typo fix to errind.EngineIdMismatch class and its instance. -Revision 4.2.2 --------------- +Revision 4.2.2, released 2012-04-21 +----------------------------------- - Oneliner CommandGenerator can now limit the number of SNMP table rows returned by nextCmd()/bulkCmd() methods. @@ -526,20 +530,21 @@ Revision 4.2.2 params. - Fix to libsmi2pysnmp to support inheritance of MIB types. -Revision 4.2.1 --------------- +Revision 4.2.1, released 2011-11-07 +----------------------------------- - Support string OIDs at one-liner API. - Code quality of libsmi2pysnmp tool improved, MIBs re-built. - SNMP-PROXY-MIB & SNMP-USER-BASED-SM-3DES-MIB added - v1arch bulkgen.py example added - Major overhawl for Python 2.4 -- 3.2 compatibility: + + get rid of old-style types + drop string module usage + switch to rich comparation + drop explicit long integer type use + map()/filter() replaced with list comprehension - + apply() replaced with */**args + + apply() replaced with var-args + dictionary operations made 2K/3K compatible + division operator made 2K/3K compatible + sorting function now operates on key @@ -548,18 +553,18 @@ Revision 4.2.1 + tuple function arguments resolved to scalars to become py3k compatible + BER octetstream is now of type bytes (Py3k) or still string (Py2k) -Revision 4.1.16d ----------------- +Revision 4.1.16d, released 2011-09-22 +------------------------------------- - Fix to SNMPv1 Trap PDU agentAddress setter shortcut method. -Revision 4.1.16c ----------------- +Revision 4.1.16c, released 2011-08-14 +------------------------------------- - Missing module import fixed in privacy subsystem -Revision 4.1.16b ----------------- +Revision 4.1.16b, released 2011-08-13 +------------------------------------- - Oneliner CommandGenerator can now optionally ignore non-increasing OIDs. - Default CommandResponder now skips non-compliant (Counter64) values @@ -568,8 +573,8 @@ Revision 4.1.16b - Fix to Twisted reactor shutdown condition. - Fix to distutils dependencies syntax. -Revision 4.1.16a ----------------- +Revision 4.1.16a, released 2011-03-17 +------------------------------------- - Extended Security Options (3DESEDE, AES192, AES256) privacy protocols implemented. @@ -586,6 +591,7 @@ Revision 4.1.16a - MsgAndPduDsp expectResponse parameters passing reworked. - GetNext/GetBulk response processing logic moved to getNextVarBinds() - Changes towards performance improvement: + + all dict.has_key() & dict.get() invocations replaced with modern syntax (this breaks compatibility with Python 2.1 and older). + introduce the MibInstrumControlle.readVarsFast() method (which skips @@ -602,8 +608,8 @@ Revision 4.1.16a + cache MIB columnar objects instance ID <-> symbolic index representation mapping -Revision 4.1.15a ----------------- +Revision 4.1.15a, released 2010-12-13 +------------------------------------- - SNMP Proxy example added. - End-of-MIB condition detection reworked what caused backward @@ -662,8 +668,8 @@ Revision 4.1.15a - Fix to oneliner GETBULK table collection code to make it stripping uneven rows off table tail. -Revision 4.1.14a ----------------- +Revision 4.1.14a, released 2010-07-15 +------------------------------------- - Fix to maxSizeResponseScopedPDU calculation at USM security module: now more precise and robust against screwed values on input. @@ -699,8 +705,8 @@ Revision 4.1.14a now send up to two packets, not just one as it used to be. - Debugging printout now escapes non-printable characters. -Revision 4.1.13a ----------------- +Revision 4.1.13a, released 2010-02-09 +------------------------------------- - UDP over IPv6 transport implemented. - Fix to MIB tree walking code that used to fail on table columns where @@ -708,8 +714,8 @@ Revision 4.1.13a - SNMPv1/v2c snmpCommunityTransportTag-based imcoming message filtering implemented (rfc2576). -Revision 4.1.12a ----------------- +Revision 4.1.12a, released 2009-12-03 +------------------------------------- - API versioning retired (pysnmp.v4 -> pysnmp). - MIB loading mechanics re-designed to allow ZIP import. @@ -721,8 +727,8 @@ Revision 4.1.12a code reworked. - Fix to sysUpTime OID at SNMPv2 TRAP PDU. -Revision 4.1.11a ----------------- +Revision 4.1.11a, released 2009-08-21 +------------------------------------- - Twisted integration implemented. - Attempt to use hashlib whenever available. @@ -751,8 +757,8 @@ Revision 4.1.11a - Minor usability improvements to tools/build-pysnmp-mib. - Made MIB objects unexport feature operational. -Revision 4.1.10a ----------------- +Revision 4.1.10a, released 2008-05-25 +------------------------------------- - Internal MIB indexing method __indexMib() unmangled to facilitate setting up mutex there for sharing MIB stuff between threads. @@ -773,8 +779,8 @@ Revision 4.1.10a request IDs and handlers. - Built-in MIBs re-generated to include text fields. -Revision 4.1.9a ---------------- +Revision 4.1.9a, released 2007-11-28 +------------------------------------ - UNSTABLE ALPHA RELEASE. - At onliner CommandGenerator, close transport on destruction to @@ -801,8 +807,8 @@ Revision 4.1.9a This might fix a significant memory leak. - Typo fix to rfc3411 confirmed class PDU members. -Revision 4.1.8a ---------------- +Revision 4.1.8a, released 2007-08-14 +------------------------------------ - UNSTABLE ALPHA RELEASE. - SMI/dispatcher timeout convertion multiplier is actually 100 (1/100 sec) @@ -845,8 +851,8 @@ Revision 4.1.8a - Fix to errorIndex generation at CommandResponder application, the value should be a one-based. -Revision 4.1.7a ---------------- +Revision 4.1.7a, released 2007-02-19 +------------------------------------ - UNSTABLE ALPHA RELEASE. - Low-level debugging facility implemented. @@ -909,8 +915,8 @@ Revision 4.1.7a #1537600, #1537659, #1548208, #1560939, #1563715, #1575697, #1599220, #1615077, #1615365, #1616579). -Revision 4.1.6a ---------------- +Revision 4.1.6a, released 2006-05-25 +------------------------------------ - UNSTABLE ALPHA RELEASE. - pysnmpUsmSecretAuthKey and pysnmpUsmSecretPrivKey length increased @@ -937,8 +943,8 @@ Revision 4.1.6a - Documentation improved - Minor fixes towards Python 1.5 compatibility -Revision 4.1.5a ---------------- +Revision 4.1.5a, released 2005-11-04 +------------------------------------ - UNSTABLE ALPHA RELEASE. - Multi-lingual SNMP Trap/Inform Applications completed; examples added @@ -948,8 +954,8 @@ Revision 4.1.5a - Minor, though backward incompatible, changes to one-liner API - Many bugfixes -Revision 4.1.4a ---------------- +Revision 4.1.4a, released 2005-08-16 +------------------------------------ - UNSTABLE ALPHA RELEASE. - SHA-based authentication fixed and privacy implemented @@ -957,8 +963,8 @@ Revision 4.1.4a authProtocol and privProtocol parameters in a backward incompatible manner. -Revision 4.1.3a ---------------- +Revision 4.1.3a, released 2005-07-28 +------------------------------------ - UNSTABLE ALPHA RELEASE. - rfc3413 applications API changes (related to callback function @@ -967,8 +973,8 @@ Revision 4.1.3a for better control of dispatcher's execution. - Many minor fixes. -Revision 4.1.2a ---------------- +Revision 4.1.2a, released 2005-07-12 +------------------------------------ - UNSTABLE ALPHA RELEASE. - Top-level application classes renamed into longer, self descripting names @@ -977,26 +983,26 @@ Revision 4.1.2a stand-alone SnmpContext for application registration. - Many minor fixes (inspired by testing on WinXP) -Revision 4.1.1a ---------------- +Revision 4.1.1a, released 2005-06-29 +------------------------------------ - UNSTABLE ALPHA RELEASE. - SNMPv3 code first published - SNMP engine and applications implemented on library level - Major re-design towards SNMPv3-style API. -Release 4.0.2a --------------- +Revision 4.0.2a, released 2005-03-01 +------------------------------------ - Adopted to slightly changed asyncore API (as shipped with python 2,4) -Release 4.0.1a --------------- +Revision 4.0.1a, released 2004-11-18 +------------------------------------ - Minor bug/typo fixes, mostly in example/ scripts. -Release 4.0.0a --------------- +Revision 4.0.0a, released 2004-11-15 +------------------------------------ - UNSTABLE EARLY ALPHA RELEASE. - Major re-design and re-implementation. diff --git a/TODO.txt b/TODO.txt new file mode 100644 index 0000000..ae8ded1 --- /dev/null +++ b/TODO.txt @@ -0,0 +1,56 @@ +Sparse notes on major existing problems/plans + +* SMI issues remained include: + + 1) multiple OID registration should be posible for + customizing Managed Objects classes + 2) in MIBVIEW object model: MIB module name, MIB object + name and object instance should be clearly separated. + Dedicated, simple API for table cells mangling should be + provided. + +* Walking over VACM shadowed OIDs is painfully slow + +* Notification filtering (RFC3413) not implemented. + +* MsgAndPduDispatcher should use TransportDispatcher jobs interface + to handle SNMPv3 handshake + +* Implement 'oneliner' API for v1arch, possibly compatible with v3arch API + +* Implement prettyIn value format parser at TC + +* Disallow SNMP access to USM objects + +* Maybe MibInstrumentationController should be async what + implies callback function interface. + +* Re-work ACL to get rid of linear search there + +* Implement partial context name match at isAccessAllowed() + +* Sort out whether pyasn1 objects should probably have either clone() or + subtype() methods. + +* Review PDU components coercion code at proxy/rfc2576 + +* TextualConvention subclassing order now depends upon DisplayHint + clause presense in MIB definition (for useful prettyIn/Out()). Maybe + this should be re-worked. + +* exclude SNMP-COMMUNITY-MIB from view for better security + +* re-design something to get rid of an ugly hack coercing MIB values into + SNMP message header as it has incompatible constraints set + +* Implement OID prefix to MIB module mapping then dynamic MIB modules + loading on OID to MIB symbol resolution + +* Implement TCP transport support + +* Rework UNIX sockets transport to make it STREAM-type. + +* The get-first/get-last operations of pysnmp.smi.rfc1902.ObjectIdentity() + may need a means to deal only with specific node types. + +* redesign proto.errind.ErrorIndication diff --git a/examples/v1arch/asyncore/agent/cmdrsp/v2c-custom-scalar-mib-objects.py b/examples/v1arch/asyncore/agent/cmdrsp/v2c-custom-scalar-mib-objects.py new file mode 100644 index 0000000..5119a15 --- /dev/null +++ b/examples/v1arch/asyncore/agent/cmdrsp/v2c-custom-scalar-mib-objects.py @@ -0,0 +1,145 @@ +""" +Implementing scalar MIB objects ++++++++++++++++++++++++++++++++ + +Listen and respond to SNMP GET/GETNEXT queries with the following options: + +* SNMPv1 or SNMPv2c +* with SNMP community "public" +* over IPv4/UDP, listening at 127.0.0.1:161 +* over IPv6/UDP, listening at [::1]:161 +* serving two Managed Objects Instances (sysDescr.0 and sysUptime.0) + +Either of the following Net-SNMP commands will walk this Agent: + +| $ snmpwalk -v2c -c public 127.0.0.1 .1.3.6 +| $ snmpwalk -v2c -c public udp6:[::1] .1.3.6 + +The Command Receiver below uses two distinct transports for communication +with Command Generators - UDP over IPv4 and UDP over IPv6. + +"""# +from pysnmp.carrier.asyncore.dispatch import AsyncoreDispatcher +from pysnmp.carrier.asyncore.dgram import udp, udp6, unix +from pyasn1.codec.ber import encoder, decoder +from pysnmp.proto import api +import time, bisect + +class SysDescr: + name = (1,3,6,1,2,1,1,1,0) + def __eq__(self, other): return self.name == other + def __ne__(self, other): return self.name != other + def __lt__(self, other): return self.name < other + def __le__(self, other): return self.name <= other + def __gt__(self, other): return self.name > other + def __ge__(self, other): return self.name >= other + def __call__(self, protoVer): + return api.protoModules[protoVer].OctetString( + 'PySNMP example command responder' + ) + +class Uptime: + name = (1,3,6,1,2,1,1,3,0) + birthday = time.time() + def __eq__(self, other): return self.name == other + def __ne__(self, other): return self.name != other + def __lt__(self, other): return self.name < other + def __le__(self, other): return self.name <= other + def __gt__(self, other): return self.name > other + def __ge__(self, other): return self.name >= other + def __call__(self, protoVer): + return api.protoModules[protoVer].TimeTicks( + (time.time()-self.birthday)*100 + ) + +mibInstr = ( + SysDescr(), Uptime() # sorted by object name + ) + +mibInstrIdx = {} +for mibVar in mibInstr: + mibInstrIdx[mibVar.name] = mibVar + +def cbFun(transportDispatcher, transportDomain, transportAddress, wholeMsg): + while wholeMsg: + msgVer = api.decodeMessageVersion(wholeMsg) + if msgVer in api.protoModules: + pMod = api.protoModules[msgVer] + else: + print('Unsupported SNMP version %s' % msgVer) + return + reqMsg, wholeMsg = decoder.decode( + wholeMsg, asn1Spec=pMod.Message(), + ) + rspMsg = pMod.apiMessage.getResponse(reqMsg) + rspPDU = pMod.apiMessage.getPDU(rspMsg) + reqPDU = pMod.apiMessage.getPDU(reqMsg) + varBinds = []; pendingErrors = [] + errorIndex = 0 + # GETNEXT PDU + if reqPDU.isSameTypeWith(pMod.GetNextRequestPDU()): + # Produce response var-binds + for oid, val in pMod.apiPDU.getVarBinds(reqPDU): + errorIndex = errorIndex + 1 + # Search next OID to report + nextIdx = bisect.bisect(mibInstr, oid) + if nextIdx == len(mibInstr): + # Out of MIB + varBinds.append((oid, val)) + pendingErrors.append( + (pMod.apiPDU.setEndOfMibError, errorIndex) + ) + else: + # Report value if OID is found + varBinds.append( + (mibInstr[nextIdx].name, mibInstr[nextIdx](msgVer)) + ) + elif reqPDU.isSameTypeWith(pMod.GetRequestPDU()): + for oid, val in pMod.apiPDU.getVarBinds(reqPDU): + if oid in mibInstrIdx: + varBinds.append((oid, mibInstrIdx[oid](msgVer))) + else: + # No such instance + varBinds.append((oid, val)) + pendingErrors.append( + (pMod.apiPDU.setNoSuchInstanceError, errorIndex) + ) + break + else: + # Report unsupported request type + pMod.apiPDU.setErrorStatus(rspPDU, 'genErr') + pMod.apiPDU.setVarBinds(rspPDU, varBinds) + # Commit possible error indices to response PDU + for f, i in pendingErrors: + f(rspPDU, i) + transportDispatcher.sendMessage( + encoder.encode(rspMsg), transportDomain, transportAddress + ) + return wholeMsg + +transportDispatcher = AsyncoreDispatcher() +transportDispatcher.registerRecvCbFun(cbFun) + +# UDP/IPv4 +transportDispatcher.registerTransport( + udp.domainName, udp.UdpSocketTransport().openServerMode(('localhost', 161)) +) + +# UDP/IPv6 +transportDispatcher.registerTransport( + udp6.domainName, udp6.Udp6SocketTransport().openServerMode(('::1', 161)) +) + +## Local domain socket +#transportDispatcher.registerTransport( +# unix.domainName, unix.UnixSocketTransport().openServerMode('/tmp/snmp-agent') +#) + +transportDispatcher.jobStarted(1) + +try: + # Dispatcher will never finish as job#1 never reaches zero + transportDispatcher.runDispatcher() +except: + transportDispatcher.closeDispatcher() + raise diff --git a/examples/v1arch/asyncore/agent/ntforg/trap-v1-multiple-transports.py b/examples/v1arch/asyncore/agent/ntforg/trap-v1-multiple-transports.py new file mode 100644 index 0000000..e0be25a --- /dev/null +++ b/examples/v1arch/asyncore/agent/ntforg/trap-v1-multiple-transports.py @@ -0,0 +1,78 @@ +""" +TRAP over multiple transports ++++++++++++++++++++++++++++++ + +The following script sends two SNMP TRAP notification using the +following options: + +* with SNMPv1 +* with community name 'public' +* over IPv4/UDP and IPv6/UDP +* send TRAP notification +* to a Manager at 127.0.0.1:162 and [::1] +* with TRAP ID 'coldStart' specified as an OID +* include managed objects information: +* with default Uptime value +* with default Agent Address with '127.0.0.1' +* overriding Enterprise OID with 1.3.6.1.4.1.20408.4.1.1.2 + +The following Net-SNMP commands will produce similar SNMP notification: + +| $ snmptrap -v1 -c public udp:127.0.0.1 1.3.6.1.4.1.20408.4.1.1.2 127.0.0.1 1 0 12345 +| $ snmptrap -v1 -c public udp6:[::1] 1.3.6.1.4.1.20408.4.1.1.2 127.0.0.1 1 0 12345 + +"""# +from pysnmp.carrier.asyncore.dispatch import AsyncoreDispatcher +from pysnmp.carrier.asyncore.dgram import udp, udp6, unix +from pyasn1.codec.ber import encoder +from pysnmp.proto import api + +# Protocol version to use +pMod = api.protoModules[api.protoVersion1] +#pMod = api.protoModules[api.protoVersion2c] + +# Build PDU +trapPDU = pMod.TrapPDU() +pMod.apiTrapPDU.setDefaults(trapPDU) + +# Traps have quite different semantics across proto versions +if pMod == api.protoModules[api.protoVersion1]: + pMod.apiTrapPDU.setEnterprise(trapPDU, (1,3,6,1,1,2,3,4,1)) + pMod.apiTrapPDU.setGenericTrap(trapPDU, 'coldStart') + +# Build message +trapMsg = pMod.Message() +pMod.apiMessage.setDefaults(trapMsg) +pMod.apiMessage.setCommunity(trapMsg, 'public') +pMod.apiMessage.setPDU(trapMsg, trapPDU) + +transportDispatcher = AsyncoreDispatcher() + +# UDP/IPv4 +transportDispatcher.registerTransport( + udp.domainName, udp.UdpSocketTransport().openClientMode() + ) +transportDispatcher.sendMessage( + encoder.encode(trapMsg), udp.domainName, ('localhost', 162) + ) + +# UDP/IPv6 +transportDispatcher.registerTransport( + udp6.domainName, udp6.Udp6SocketTransport().openClientMode() +) +transportDispatcher.sendMessage( + encoder.encode(trapMsg), udp6.domainName, ('::1', 162) +) + +## Local domain socket +#transportDispatcher.registerTransport( +# unix.domainName, unix.UnixSocketTransport().openClientMode() +#) +#transportDispatcher.sendMessage( +# encoder.encode(trapMsg), unix.domainName, '/tmp/snmp-manager' +#) + +# Dispatcher will finish as all scheduled messages are sent +transportDispatcher.runDispatcher() + +transportDispatcher.closeDispatcher() diff --git a/examples/v1arch/asyncore/manager/cmdgen/get-v1.py b/examples/v1arch/asyncore/manager/cmdgen/get-v1.py new file mode 100644 index 0000000..e7fa029 --- /dev/null +++ b/examples/v1arch/asyncore/manager/cmdgen/get-v1.py @@ -0,0 +1,105 @@ +""" +Fetch scalar MIB variables (SNMPv1) ++++++++++++++++++++++++++++++++++++ + +Perform SNMP GET operation with the following options: + +* with SNMPv1, community 'public' +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for OIDs in tuple form + +This script performs similar to the following Net-SNMP command: + +| $ snmpget -v1 -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1.1.0 1.3.6.1.2.1.1.3.0 + +"""# +from pysnmp.carrier.asyncore.dispatch import AsyncoreDispatcher +from pysnmp.carrier.asyncore.dgram import udp, udp6, unix +from pyasn1.codec.ber import encoder, decoder +from pysnmp.proto import api +from time import time + +# Protocol version to use +pMod = api.protoModules[api.protoVersion1] +#pMod = api.protoModules[api.protoVersion2c] + +# Build PDU +reqPDU = pMod.GetRequestPDU() +pMod.apiPDU.setDefaults(reqPDU) +pMod.apiPDU.setVarBinds( + reqPDU, ( ('1.3.6.1.2.1.1.1.0', pMod.Null('')), + ('1.3.6.1.2.1.1.3.0', pMod.Null('')) ) + ) + +# Build message +reqMsg = pMod.Message() +pMod.apiMessage.setDefaults(reqMsg) +pMod.apiMessage.setCommunity(reqMsg, 'public') +pMod.apiMessage.setPDU(reqMsg, reqPDU) + +startedAt = time() + +def cbTimerFun(timeNow): + if timeNow - startedAt > 3: + raise Exception("Request timed out") + +def cbRecvFun(transportDispatcher, transportDomain, transportAddress, + wholeMsg, reqPDU=reqPDU): + while wholeMsg: + rspMsg, wholeMsg = decoder.decode(wholeMsg, asn1Spec=pMod.Message()) + rspPDU = pMod.apiMessage.getPDU(rspMsg) + # Match response to request + if pMod.apiPDU.getRequestID(reqPDU)==pMod.apiPDU.getRequestID(rspPDU): + # Check for SNMP errors reported + errorStatus = pMod.apiPDU.getErrorStatus(rspPDU) + if errorStatus: + print(errorStatus.prettyPrint()) + else: + for oid, val in pMod.apiPDU.getVarBinds(rspPDU): + print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + transportDispatcher.jobFinished(1) + return wholeMsg + +transportDispatcher = AsyncoreDispatcher() + +transportDispatcher.registerRecvCbFun(cbRecvFun) +transportDispatcher.registerTimerCbFun(cbTimerFun) + +# UDP/IPv4 +transportDispatcher.registerTransport( + udp.domainName, udp.UdpSocketTransport().openClientMode() +) + +# Pass message to dispatcher +transportDispatcher.sendMessage( + encoder.encode(reqMsg), udp.domainName, ('demo.snmplabs.com', 161) +) +transportDispatcher.jobStarted(1) + +## UDP/IPv6 (second copy of the same PDU will be sent) +transportDispatcher.registerTransport( + udp6.domainName, udp6.Udp6SocketTransport().openClientMode() +) + +# Pass message to dispatcher +transportDispatcher.sendMessage( + encoder.encode(reqMsg), udp6.domainName, ('::1', 161) +) +transportDispatcher.jobStarted(1) + +## Local domain socket +#transportDispatcher.registerTransport( +# unix.domainName, unix.UnixSocketTransport().openClientMode() +#) +# +# Pass message to dispatcher +#transportDispatcher.sendMessage( +# encoder.encode(reqMsg), unix.domainName, '/tmp/snmp-agent' +#) +#transportDispatcher.jobStarted(1) + +# Dispatcher will finish as job#1 counter reaches zero +transportDispatcher.runDispatcher() + +transportDispatcher.closeDispatcher() diff --git a/examples/v1arch/asyncore/manager/cmdgen/get-v2c-spoof-source-address.py b/examples/v1arch/asyncore/manager/cmdgen/get-v2c-spoof-source-address.py new file mode 100644 index 0000000..16009ab --- /dev/null +++ b/examples/v1arch/asyncore/manager/cmdgen/get-v2c-spoof-source-address.py @@ -0,0 +1,117 @@ +""" +Spoof IPv4 source address ++++++++++++++++++++++++++ + +Send SNMP GET request from a non-local IP address: + +* with SNMPv2c, community 'public' +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* from a non-local, spoofed IP 1.2.3.4 (root and Python 3.3+ required) +* for OIDs in string form + +This script performs similar to the following Net-SNMP command: + +| $ snmpget -v2c -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1.1.0 1.3.6.1.2.1.1.3.0 + +But unlike the above command, this script issues SNMP request from a +non-default, non-local IP address. + +It is indeed possible to originate SNMP traffic from any valid local IP +addresses. It could be a secondary IP interface, for instance. Superuser +privileges are only required to send spoofed packets. Alternatively, +sending from local interface could also be achieved by binding to +it (via openClientMode() parameter). + +Agent would respond to the IP address you used as a source. So this script +could only get a response if that source address is somehow routed to the +host this script is running on. Otherwise it just times out. + +"""# +from pysnmp.carrier.asyncore.dispatch import AsyncoreDispatcher +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.proto import api +from pyasn1.codec.ber import encoder, decoder +from time import time + +# Send request message to this address +transportAddress = udp.UdpTransportAddress(('195.218.195.228', 161)) + +# Send request message from this non-local (!) IP address +transportAddress.setLocalAddress(('1.2.3.4', 0)) + +# Protocol version to use +#pMod = api.protoModules[api.protoVersion1] +pMod = api.protoModules[api.protoVersion2c] + +# Build PDU +reqPDU = pMod.GetRequestPDU() +pMod.apiPDU.setDefaults(reqPDU) +pMod.apiPDU.setVarBinds( + reqPDU, ( ('1.3.6.1.2.1.1.1.0', pMod.Null('')), + ('1.3.6.1.2.1.1.3.0', pMod.Null('')) ) + ) + +# Build message +reqMsg = pMod.Message() +pMod.apiMessage.setDefaults(reqMsg) +pMod.apiMessage.setCommunity(reqMsg, 'public') +pMod.apiMessage.setPDU(reqMsg, reqPDU) + +startedAt = time() + +class StopWaiting(Exception): pass + +def cbTimerFun(timeNow): + if timeNow - startedAt > 3: + raise StopWaiting() + +def cbRecvFun(transportDispatcher, transportDomain, transportAddress, + wholeMsg, reqPDU=reqPDU): + while wholeMsg: + rspMsg, wholeMsg = decoder.decode(wholeMsg, asn1Spec=pMod.Message()) + rspPDU = pMod.apiMessage.getPDU(rspMsg) + # Match response to request + if pMod.apiPDU.getRequestID(reqPDU)==pMod.apiPDU.getRequestID(rspPDU): + # Check for SNMP errors reported + errorStatus = pMod.apiPDU.getErrorStatus(rspPDU) + if errorStatus: + print(errorStatus.prettyPrint()) + else: + for oid, val in pMod.apiPDU.getVarBinds(rspPDU): + print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + transportDispatcher.jobFinished(1) + return wholeMsg + +transportDispatcher = AsyncoreDispatcher() + +transportDispatcher.registerRecvCbFun(cbRecvFun) +transportDispatcher.registerTimerCbFun(cbTimerFun) + +# Initialize UDP/IPv4 transport +udpSocketTransport = udp.UdpSocketTransport().openClientMode() + +# Use sendmsg()/recvmsg() for socket communication (required for +# IP source spoofing functionality) +udpSocketTransport.enablePktInfo() + +# Enable IP source spoofing (requires root privileges) +udpSocketTransport.enableTransparent() + +transportDispatcher.registerTransport(udp.domainName, udpSocketTransport) + +# Pass message to dispatcher +transportDispatcher.sendMessage( + encoder.encode(reqMsg), udp.domainName, transportAddress +) + +# We might never receive any response as we sent request with fake source IP +transportDispatcher.jobStarted(1) + +# Dispatcher will finish as all jobs counter reaches zero +try: + transportDispatcher.runDispatcher() +except StopWaiting: + transportDispatcher.closeDispatcher() +else: + raise diff --git a/examples/v1arch/asyncore/manager/cmdgen/get-v2c-udp-broadcast-agent-discovery.py b/examples/v1arch/asyncore/manager/cmdgen/get-v2c-udp-broadcast-agent-discovery.py new file mode 100644 index 0000000..cd8c3c9 --- /dev/null +++ b/examples/v1arch/asyncore/manager/cmdgen/get-v2c-udp-broadcast-agent-discovery.py @@ -0,0 +1,99 @@ +""" +Broadcast SNMP message (IPv4) ++++++++++++++++++++++++++++++ + +Send SNMP GET request to broadcast address and wait for respons(es): + +* with SNMPv2c, community 'public' +* over IPv4/UDP +* to all Agents via broadcast address 255.255.255.255:161 +* for OIDs in tuple form + +Here we send out a single SNMP request and wait for potentially many SNMP +responses from multiple SNMP Agents listening in local broadcast domain. +Since we can't predict the exact number of Agents responding, this script +just waits for arbitrary time for collecting all responses. This technology +is also known as SNMP-based discovery. + +This script performs similar to the following Net-SNMP command: + +| $ snmpget -v2c -c public -ObentU 255.255.255.255 1.3.6.1.2.1.1.1.0 1.3.6.1.2.1.1.3.0 + +"""# +from pysnmp.carrier.asyncore.dispatch import AsyncoreDispatcher +from pysnmp.carrier.asyncore.dgram import udp +from pyasn1.codec.ber import encoder, decoder +from pysnmp.proto import api +from time import time + +# Broadcast manager settings +maxWaitForResponses = 5 +maxNumberResponses = 10 + +# Protocol version to use +#pMod = api.protoModules[api.protoVersion1] +pMod = api.protoModules[api.protoVersion2c] + +# Build PDU +reqPDU = pMod.GetRequestPDU() +pMod.apiPDU.setDefaults(reqPDU) +pMod.apiPDU.setVarBinds( + reqPDU, ( ('1.3.6.1.2.1.1.1.0', pMod.Null('')), + ('1.3.6.1.2.1.1.3.0', pMod.Null('')) ) + ) + +# Build message +reqMsg = pMod.Message() +pMod.apiMessage.setDefaults(reqMsg) +pMod.apiMessage.setCommunity(reqMsg, 'public') +pMod.apiMessage.setPDU(reqMsg, reqPDU) + +startedAt = time() + +class StopWaiting(Exception): pass + +def cbTimerFun(timeNow): + if timeNow - startedAt > maxWaitForResponses: + raise StopWaiting() + +def cbRecvFun(transportDispatcher, transportDomain, transportAddress, + wholeMsg, reqPDU=reqPDU): + while wholeMsg: + rspMsg, wholeMsg = decoder.decode(wholeMsg, asn1Spec=pMod.Message()) + rspPDU = pMod.apiMessage.getPDU(rspMsg) + # Match response to request + if pMod.apiPDU.getRequestID(reqPDU)==pMod.apiPDU.getRequestID(rspPDU): + # Check for SNMP errors reported + errorStatus = pMod.apiPDU.getErrorStatus(rspPDU) + if errorStatus: + print(errorStatus.prettyPrint()) + else: + for oid, val in pMod.apiPDU.getVarBinds(rspPDU): + print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + transportDispatcher.jobFinished(1) + return wholeMsg + +transportDispatcher = AsyncoreDispatcher() + +transportDispatcher.registerRecvCbFun(cbRecvFun) +transportDispatcher.registerTimerCbFun(cbTimerFun) + +# UDP/IPv4 +udpSocketTransport = udp.UdpSocketTransport().openClientMode().enableBroadcast() +transportDispatcher.registerTransport(udp.domainName, udpSocketTransport) + +# Pass message to dispatcher +transportDispatcher.sendMessage( + encoder.encode(reqMsg), udp.domainName, ('255.255.255.255', 161) +) + +# wait for a maximum of 10 responses or time out +transportDispatcher.jobStarted(1, maxNumberResponses) + +# Dispatcher will finish as all jobs counter reaches zero +try: + transportDispatcher.runDispatcher() +except StopWaiting: + transportDispatcher.closeDispatcher() +else: + raise diff --git a/examples/v1arch/asyncore/manager/cmdgen/getbulk-v2c.py b/examples/v1arch/asyncore/manager/cmdgen/getbulk-v2c.py new file mode 100644 index 0000000..8ba9af6 --- /dev/null +++ b/examples/v1arch/asyncore/manager/cmdgen/getbulk-v2c.py @@ -0,0 +1,112 @@ +""" +Bulk walk Agent MIB (SNMPv2c) ++++++++++++++++++++++++++++++ + +Perform SNMP GETBULK operation with the following options: + +* with SNMPv2c, community 'public' +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for OID in tuple form +* with non-repeaters=0 and max-repeaters=25 + +This script performs similar to the following Net-SNMP command: + +| $ snmpbulkwalk -v2c -c public -ObentU -Cn0 -Cr25 195.218.195.228 1.3.6 + +"""# +from pysnmp.carrier.asyncore.dispatch import AsyncoreDispatcher +from pysnmp.carrier.asyncore.dgram import udp +from pyasn1.codec.ber import encoder, decoder +from pysnmp.proto.api import v2c +from time import time + +# SNMP table header +headVars = [ v2c.ObjectIdentifier((1,3,6)) ] + +# Build PDU +reqPDU = v2c.GetBulkRequestPDU() +v2c.apiBulkPDU.setDefaults(reqPDU) +v2c.apiBulkPDU.setNonRepeaters(reqPDU, 0) +v2c.apiBulkPDU.setMaxRepetitions(reqPDU, 25) +v2c.apiBulkPDU.setVarBinds(reqPDU, [ (x, v2c.null) for x in headVars ]) + +# Build message +reqMsg = v2c.Message() +v2c.apiMessage.setDefaults(reqMsg) +v2c.apiMessage.setCommunity(reqMsg, 'public') +v2c.apiMessage.setPDU(reqMsg, reqPDU) + +startedAt = time() + +def cbTimerFun(timeNow): + if timeNow - startedAt > 3: + raise Exception("Request timed out") + +def cbRecvFun(transportDispatcher, transportDomain, transportAddress, + wholeMsg, reqPDU=reqPDU, headVars=headVars): + while wholeMsg: + rspMsg, wholeMsg = decoder.decode(wholeMsg, asn1Spec=v2c.Message()) + + rspPDU = v2c.apiMessage.getPDU(rspMsg) + + # Match response to request + if v2c.apiBulkPDU.getRequestID(reqPDU)==v2c.apiBulkPDU.getRequestID(rspPDU): + # Format var-binds table + varBindTable = v2c.apiBulkPDU.getVarBindTable(reqPDU, rspPDU) + + # Check for SNMP errors reported + errorStatus = v2c.apiBulkPDU.getErrorStatus(rspPDU) + if errorStatus and errorStatus != 2: + errorIndex = v2c.apiBulkPDU.getErrorIndex(rspPDU) + print('%s at %s' % (errorStatus.prettyPrint(), + errorIndex and varBindTable[int(errorIndex)-1] or '?')) + transportDispatcher.jobFinished(1) + break + + # Report SNMP table + for tableRow in varBindTable: + for name, val in tableRow: + print('from: %s, %s = %s' % ( + transportAddress, name.prettyPrint(), val.prettyPrint() + ) + ) + + # Stop on EOM + for oid, val in varBindTable[-1]: + if not isinstance(val, v2c.Null): + break + else: + transportDispatcher.jobFinished(1) + + # Generate request for next row + v2c.apiBulkPDU.setVarBinds( + reqPDU, [ (x, v2c.null) for x,y in varBindTable[-1] ] + ) + v2c.apiBulkPDU.setRequestID(reqPDU, v2c.getNextRequestID()) + transportDispatcher.sendMessage( + encoder.encode(reqMsg), transportDomain, transportAddress + ) + global startedAt + if time() - startedAt > 3: + raise Exception('Request timed out') + startedAt = time() + return wholeMsg + +transportDispatcher = AsyncoreDispatcher() + +transportDispatcher.registerRecvCbFun(cbRecvFun) +transportDispatcher.registerTimerCbFun(cbTimerFun) + +transportDispatcher.registerTransport( + udp.domainName, udp.UdpSocketTransport().openClientMode() +) +transportDispatcher.sendMessage( + encoder.encode(reqMsg), udp.domainName, ('demo.snmplabs.com', 161) +) +transportDispatcher.jobStarted(1) + +# Dispatcher will finish as job#1 counter reaches zero +transportDispatcher.runDispatcher() + +transportDispatcher.closeDispatcher() diff --git a/examples/v1arch/asyncore/manager/cmdgen/getnext-v1.py b/examples/v1arch/asyncore/manager/cmdgen/getnext-v1.py new file mode 100644 index 0000000..b3e16f1 --- /dev/null +++ b/examples/v1arch/asyncore/manager/cmdgen/getnext-v1.py @@ -0,0 +1,103 @@ +""" +Walk Agent MIB (SNMPv1) ++++++++++++++++++++++++ + +Perform SNMP GETNEXT operation with the following options: + +* with SNMPv1, community 'public' +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for OID in tuple form + +This script performs similar to the following Net-SNMP command: + +| $ snmpwalk -v1 -c public -ObentU 195.218.195.228 1.3.6 + +"""# +from pysnmp.carrier.asyncore.dispatch import AsyncoreDispatcher +from pysnmp.carrier.asyncore.dgram import udp +from pyasn1.codec.ber import encoder, decoder +from pysnmp.proto import api +from time import time + +# Protocol version to use +pMod = api.protoModules[api.protoVersion1] +#pMod = api.protoModules[api.protoVersion2c] + +# SNMP table header +headVars = [ pMod.ObjectIdentifier((1,3,6)) ] + +# Build PDU +reqPDU = pMod.GetNextRequestPDU() +pMod.apiPDU.setDefaults(reqPDU) +pMod.apiPDU.setVarBinds(reqPDU, [ (x, pMod.null) for x in headVars ]) + +# Build message +reqMsg = pMod.Message() +pMod.apiMessage.setDefaults(reqMsg) +pMod.apiMessage.setCommunity(reqMsg, 'public') +pMod.apiMessage.setPDU(reqMsg, reqPDU) + +startedAt = time() + +def cbTimerFun(timeNow): + if timeNow - startedAt > 3: + raise Exception("Request timed out") + +def cbRecvFun(transportDispatcher, transportDomain, transportAddress, + wholeMsg, reqPDU=reqPDU, headVars=headVars): + while wholeMsg: + rspMsg, wholeMsg = decoder.decode(wholeMsg, asn1Spec=pMod.Message()) + rspPDU = pMod.apiMessage.getPDU(rspMsg) + # Match response to request + if pMod.apiPDU.getRequestID(reqPDU)==pMod.apiPDU.getRequestID(rspPDU): + # Check for SNMP errors reported + errorStatus = pMod.apiPDU.getErrorStatus(rspPDU) + if errorStatus and errorStatus != 2: + raise Exception(errorStatus) + # Format var-binds table + varBindTable = pMod.apiPDU.getVarBindTable(reqPDU, rspPDU) + # Report SNMP table + for tableRow in varBindTable: + for name, val in tableRow: + print('from: %s, %s = %s' % ( + transportAddress, name.prettyPrint(), val.prettyPrint() + ) + ) + # Stop on EOM + for oid, val in varBindTable[-1]: + if not isinstance(val, pMod.Null): + break + else: + transportDispatcher.jobFinished(1) + + # Generate request for next row + pMod.apiPDU.setVarBinds( + reqPDU, [ (x, pMod.null) for x,y in varBindTable[-1] ] + ) + pMod.apiPDU.setRequestID(reqPDU, pMod.getNextRequestID()) + transportDispatcher.sendMessage( + encoder.encode(reqMsg), transportDomain, transportAddress + ) + global startedAt + if time() - startedAt > 3: + raise Exception('Request timed out') + startedAt = time() + return wholeMsg + +transportDispatcher = AsyncoreDispatcher() + +transportDispatcher.registerRecvCbFun(cbRecvFun) +transportDispatcher.registerTimerCbFun(cbTimerFun) + +transportDispatcher.registerTransport( + udp.domainName, udp.UdpSocketTransport().openClientMode() +) +transportDispatcher.sendMessage( + encoder.encode(reqMsg), udp.domainName, ('demo.snmplabs.com', 161) +) +transportDispatcher.jobStarted(1) + +transportDispatcher.runDispatcher() + +transportDispatcher.closeDispatcher() diff --git a/examples/v1arch/asyncore/manager/cmdgen/set-v2c.py b/examples/v1arch/asyncore/manager/cmdgen/set-v2c.py new file mode 100644 index 0000000..a30bebb --- /dev/null +++ b/examples/v1arch/asyncore/manager/cmdgen/set-v2c.py @@ -0,0 +1,85 @@ +""" +SET string and integer scalars (SNMPv2c) +++++++++++++++++++++++++++++++++++++++++ + +Perform SNMP SET operation with the following options: + +* with SNMPv2c, community 'public' +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for OIDs in string form and values in form of pyasn1 objects + +This script performs similar to the following Net-SNMP command: + +| $ snmpset -v2c -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1.9.1.3.1 s 'New description' 1.3.6.1.2.1.1.9.1.4.1 t 12 + +"""# +from pysnmp.carrier.asyncore.dispatch import AsyncoreDispatcher +from pysnmp.carrier.asyncore.dgram import udp +from pyasn1.codec.ber import encoder, decoder +from pysnmp.proto import api +from time import time + +# Protocol version to use +#pMod = api.protoModules[api.protoVersion1] +pMod = api.protoModules[api.protoVersion2c] + +# Build PDU +reqPDU = pMod.SetRequestPDU() +pMod.apiPDU.setDefaults(reqPDU) +pMod.apiPDU.setVarBinds( + reqPDU, + # A list of Var-Binds to SET + ( ('1.3.6.1.2.1.1.9.1.3.1', pMod.OctetString('New system description')), + ('1.3.6.1.2.1.1.9.1.4.1', pMod.TimeTicks(12)) ) + ) + +# Build message +reqMsg = pMod.Message() +pMod.apiMessage.setDefaults(reqMsg) +pMod.apiMessage.setCommunity(reqMsg, 'public') +pMod.apiMessage.setPDU(reqMsg, reqPDU) + +startedAt = time() + +def cbTimerFun(timeNow): + if timeNow - startedAt > 3: + raise Exception("Request timed out") + +def cbRecvFun(transportDispatcher, transportDomain, transportAddress, + wholeMsg, reqPDU=reqPDU): + while wholeMsg: + rspMsg, wholeMsg = decoder.decode(wholeMsg, asn1Spec=pMod.Message()) + rspPDU = pMod.apiMessage.getPDU(rspMsg) + # Match response to request + if pMod.apiPDU.getRequestID(reqPDU)==pMod.apiPDU.getRequestID(rspPDU): + # Check for SNMP errors reported + errorStatus = pMod.apiPDU.getErrorStatus(rspPDU) + if errorStatus: + print(errorStatus.prettyPrint()) + else: + for oid, val in pMod.apiPDU.getVarBinds(rspPDU): + print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + transportDispatcher.jobFinished(1) + return wholeMsg + +transportDispatcher = AsyncoreDispatcher() + +transportDispatcher.registerRecvCbFun(cbRecvFun) +transportDispatcher.registerTimerCbFun(cbTimerFun) + +# UDP/IPv4 +transportDispatcher.registerTransport( + udp.domainName, udp.UdpSocketTransport().openClientMode() +) + +# Pass message to dispatcher +transportDispatcher.sendMessage( + encoder.encode(reqMsg), udp.domainName, ('demo.snmplabs.com', 161) +) +transportDispatcher.jobStarted(1) + +# Dispatcher will finish as job#1 counter reaches zero +transportDispatcher.runDispatcher() + +transportDispatcher.closeDispatcher() diff --git a/examples/v1arch/asyncore/manager/ntfrcv/v1-multiple-transports.py b/examples/v1arch/asyncore/manager/ntfrcv/v1-multiple-transports.py new file mode 100644 index 0000000..b9073cf --- /dev/null +++ b/examples/v1arch/asyncore/manager/ntfrcv/v1-multiple-transports.py @@ -0,0 +1,100 @@ +""" +Listen for notifications at IPv4 & IPv6 interfaces +++++++++++++++++++++++++++++++++++++++++++++++++++ + +Receive SNMP TRAP messages with the following options: + +* SNMPv1/SNMPv2c +* with SNMP community "public" +* over IPv4/UDP, listening at 127.0.0.1:162 +* over IPv6/UDP, listening at [::1]:162 +* print received data on stdout + +Either of the following Net-SNMP commands will send notifications to this +receiver: + +| $ snmptrap -v1 -c public 127.0.0.1 1.3.6.1.4.1.20408.4.1.1.2 127.0.0.1 1 1 123 1.3.6.1.2.1.1.1.0 s test +| $ snmptrap -v2c -c public udp6:[::1] 123 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.5.0 s test + +Notification Receiver below uses two different transports for communication +with Notification Originators - UDP over IPv4 and UDP over IPv6. + +"""# +from pysnmp.carrier.asyncore.dispatch import AsyncoreDispatcher +from pysnmp.carrier.asyncore.dgram import udp, udp6, unix +from pyasn1.codec.ber import decoder +from pysnmp.proto import api + +def cbFun(transportDispatcher, transportDomain, transportAddress, wholeMsg): + while wholeMsg: + msgVer = int(api.decodeMessageVersion(wholeMsg)) + if msgVer in api.protoModules: + pMod = api.protoModules[msgVer] + else: + print('Unsupported SNMP version %s' % msgVer) + return + reqMsg, wholeMsg = decoder.decode( + wholeMsg, asn1Spec=pMod.Message(), + ) + print('Notification message from %s:%s: ' % ( + transportDomain, transportAddress + ) + ) + reqPDU = pMod.apiMessage.getPDU(reqMsg) + if reqPDU.isSameTypeWith(pMod.TrapPDU()): + if msgVer == api.protoVersion1: + print('Enterprise: %s' % ( + pMod.apiTrapPDU.getEnterprise(reqPDU).prettyPrint() + ) + ) + print('Agent Address: %s' % ( + pMod.apiTrapPDU.getAgentAddr(reqPDU).prettyPrint() + ) + ) + print('Generic Trap: %s' % ( + pMod.apiTrapPDU.getGenericTrap(reqPDU).prettyPrint() + ) + ) + print('Specific Trap: %s' % ( + pMod.apiTrapPDU.getSpecificTrap(reqPDU).prettyPrint() + ) + ) + print('Uptime: %s' % ( + pMod.apiTrapPDU.getTimeStamp(reqPDU).prettyPrint() + ) + ) + varBinds = pMod.apiTrapPDU.getVarBindList(reqPDU) + else: + varBinds = pMod.apiPDU.getVarBindList(reqPDU) + print('Var-binds:') + for oid, val in varBinds: + print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + return wholeMsg + +transportDispatcher = AsyncoreDispatcher() + +transportDispatcher.registerRecvCbFun(cbFun) + +# UDP/IPv4 +transportDispatcher.registerTransport( + udp.domainName, udp.UdpSocketTransport().openServerMode(('localhost', 162)) +) + +# UDP/IPv6 +transportDispatcher.registerTransport( + udp6.domainName, udp6.Udp6SocketTransport().openServerMode(('::1', 162)) +) + +## Local domain socket +#transportDispatcher.registerTransport( +# unix.domainName, unix.UnixSocketTransport().openServerMode('/tmp/snmp-manager') +#) + +transportDispatcher.jobStarted(1) + +try: + # Dispatcher will never finish as job#1 never reaches zero + transportDispatcher.runDispatcher() +except: + transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncio/agent/cmdrsp/v3-multiple-users.py b/examples/v3arch/asyncio/agent/cmdrsp/v3-multiple-users.py index cdc264b..b0b7e5b 100644 --- a/examples/v3arch/asyncio/agent/cmdrsp/v3-multiple-users.py +++ b/examples/v3arch/asyncio/agent/cmdrsp/v3-multiple-users.py @@ -1,25 +1,28 @@ -# -# Command Responder -# -# Listen and respond to SNMP GET/SET/GETNEXT/GETBULK queries with -# the following options: -# -# * SNMPv3 -# * with USM user 'usr-md5-des', auth: MD5, priv DES or -# with USM user 'usr-sha-none', auth: SHA, no privacy -# with USM user 'usr-sha-aes128', auth: SHA, priv AES -# * allow access to SNMPv2-MIB objects (1.3.6.1.2.1) -# * over IPv4/UDP, listening at 127.0.0.1:161 -# * using asyncio network transport (available since Python 3.4) -# -# Either of the following Net-SNMP's commands will walk this Agent: -# -# $ snmpwalk -v3 -u usr-md5-des -l authPriv -A authkey1 -X privkey1 localhost .1.3.6 -# $ snmpwalk -v3 -u usr-sha-none -l authNoPriv -a SHA -A authkey1 localhost .1.3.6 -# $ snmpwalk -v3 -u usr-sha-aes128 -l authPriv -a SHA -A authkey1 -x AES -X privkey1 localhost .1.3.6 -# -# Requires Python 3.4 and later! -# +""" +Multiple SNMP USM users ++++++++++++++++++++++++ + +Listen and respond to SNMP GET/SET/GETNEXT/GETBULK queries with +the following options: + +* SNMPv3 +* with USM user: + - 'usr-md5-des', auth: MD5, priv DES or + - 'usr-sha-none', auth: SHA, no privacy + - 'usr-sha-aes128', auth: SHA, priv AES +* allow access to SNMPv2-MIB objects (1.3.6.1.2.1) +* over IPv4/UDP, listening at 127.0.0.1:161 +* using asyncio network transport (available since Python 3.4) + +Either of the following Net-SNMP commands will walk this Agent: + +| $ snmpwalk -v3 -u usr-md5-des -l authPriv -A authkey1 -X privkey1 localhost .1.3.6 +| $ snmpwalk -v3 -u usr-sha-none -l authNoPriv -a SHA -A authkey1 localhost .1.3.6 +| $ snmpwalk -v3 -u usr-sha-aes128 -l authPriv -a SHA -A authkey1 -x AES -X privkey1 localhost .1.3.6 + +Requires Python 3.4 and later! + +"""# from pysnmp.entity import engine, config from pysnmp.entity.rfc3413 import cmdrsp, context from pysnmp.carrier.asyncio.dgram import udp diff --git a/examples/v3arch/asyncio/agent/ntforg/inform-v3.py b/examples/v3arch/asyncio/agent/ntforg/inform-v3.py index 133ff05..3474495 100644 --- a/examples/v3arch/asyncio/agent/ntforg/inform-v3.py +++ b/examples/v3arch/asyncio/agent/ntforg/inform-v3.py @@ -1,19 +1,25 @@ -# -# Notification Originator -# -# Send SNMP INFORM notification using the following options: -# -# * SNMPv3 -# * with user 'usr-md5-none', auth: MD5, priv NONE -# * over IPv4/UDP -# * using asyncio network transport (available from Python 3.4) -# * to a Manager at 127.0.0.1:162 -# * send INFORM notification -# * with TRAP ID 'warmStart' specified as an OID -# * include managed object information 1.3.6.1.2.1.1.5.0 = 'system name' -# -# Requires Python 3.4 and later! -# +""" +SNMP IMFORM notification +++++++++++++++++++++++++ + +Send SNMP INFORM notification using the following options: + +* SNMPv3 +* with user 'usr-md5-none', auth: MD5, priv NONE +* over IPv4/UDP +* using asyncio network transport (available from Python 3.4) +* to a Manager at 127.0.0.1:162 +* send INFORM notification +* with TRAP ID 'warmStart' specified as an OID +* include managed object information 1.3.6.1.2.1.1.5.0 = 'system name' + +Functionally similar to: + +| $ snmpinform -v3 -l authPriv -u usr-md5-none -A authkey1 127.0.0.1 0 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.5.0 s 'system name' + +Requires Python 3.4 and later! + +"""# from pysnmp.entity import engine, config from pysnmp.entity.rfc3413 import context from pysnmp.entity.rfc3413.asyncio import ntforg diff --git a/examples/v3arch/asyncio/agent/ntforg/trap-v1.py b/examples/v3arch/asyncio/agent/ntforg/trap-v1.py index 5104f90..28f8ba5 100644 --- a/examples/v3arch/asyncio/agent/ntforg/trap-v1.py +++ b/examples/v3arch/asyncio/agent/ntforg/trap-v1.py @@ -1,23 +1,29 @@ -# -# Notification Originator -# -# Send SNMP notification using the following options: -# -# * SNMPv1 -# * with community name 'public' -# * over IPv4/UDP -# * using asyncio network transport (available from Python 3.4) -# * to a Manager at 127.0.0.1:162 -# * send TRAP notification -# * with TRAP ID 'coldStart' specified as an OID -# * include managed objects information: -# * overriding Uptime value with 12345 -# * overriding Agent Address with '127.0.0.1' -# * overriding Enterprise OID with 1.3.6.1.4.1.20408.4.1.1.2 -# * include managed object information '1.3.6.1.2.1.1.1.0' = 'my system' -# -# Requires Python 3.4 and later! -# +""" +SNMP TRAP notification +++++++++++++++++++++++ + +Send SNMP notification using the following options: + +* SNMPv1 +* with community name 'public' +* over IPv4/UDP +* using asyncio network transport (available from Python 3.4) +* to a Manager at 127.0.0.1:162 +* send TRAP notification +* with TRAP ID 'coldStart' specified as an OID +* include managed objects information: +* overriding Uptime value with 12345 +* overriding Agent Address with '127.0.0.1' +* overriding Enterprise OID with 1.3.6.1.4.1.20408.4.1.1.2 +* include managed object information '1.3.6.1.2.1.1.1.0' = 'my system' + +Functionally similar to: + +| $ snmptrap -v1 -c public demo.snmplabs.com 1.3.6.1.4.1.20408.4.1.1.2 127.0.0.1 6 432 12345 1.3.6.1.2.1.1.1.0 s 'my system' + +Requires Python 3.4 and later! + +"""# from pysnmp.entity import engine, config from pysnmp.entity.rfc3413 import context from pysnmp.entity.rfc3413.asyncio import ntforg diff --git a/examples/v3arch/asyncio/manager/cmdgen/get-v2c-custom-timeout.py b/examples/v3arch/asyncio/manager/cmdgen/get-v2c-custom-timeout.py index c2ef8b5..93efaba 100644 --- a/examples/v3arch/asyncio/manager/cmdgen/get-v2c-custom-timeout.py +++ b/examples/v3arch/asyncio/manager/cmdgen/get-v2c-custom-timeout.py @@ -1,20 +1,23 @@ -# -# GET Command Generator -# -# Send a SNMP GET request -# with SNMPv2c, community 'public' -# using Asyncio framework for network transport -# over IPv4/UDP -# to an Agent at 195.218.195.228:161 -# wait 3 seconds for response, retry 5 times (plus one initial attempt) -# for an OID in string form -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpget -v2c -c public -ObentU -r 5 -t 1 195.218.195.228 1.3.6.1.2.1.1.1.0 -# -# Requires Python 3.4 and later! -# +""" +Fetch scalar value +++++++++++++++++++ + +Send SNMP GET request with the following options: + +* with SNMPv2c, community 'public' +* using Asyncio framework for network transport +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* wait 3 seconds for response, retry 5 times (plus one initial attempt) +* for an OID in string form + +This script performs similar to the following Net-SNMP command: + +| $ snmpget -v2c -c public -ObentU -r 5 -t 1 195.218.195.228 1.3.6.1.2.1.1.1.0 + +Requires Python 3.4 and later! + +"""# from pysnmp.carrier.asyncio.dgram import udp from pysnmp.entity.rfc3413.asyncio import cmdgen from pysnmp.entity import engine, config diff --git a/examples/v3arch/asyncio/manager/cmdgen/get-v2c-over-ipv6.py b/examples/v3arch/asyncio/manager/cmdgen/get-v2c-over-ipv6.py index e1b3171..da3a0d0 100644 --- a/examples/v3arch/asyncio/manager/cmdgen/get-v2c-over-ipv6.py +++ b/examples/v3arch/asyncio/manager/cmdgen/get-v2c-over-ipv6.py @@ -1,19 +1,22 @@ -# -# GET Command Generator -# -# Send a SNMP GET request -# with SNMPv2c, community 'public' -# using Asyncio framework for network transport -# over IPv6/UDP -# to an Agent at [::]:161 -# for an OID in string form -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpget -v2c -c public -ObentU udp6:[::1]:161 1.3.6.1.2.1.1.1.0 -# -# Requires Python 3.4 and later! -# +""" +Fetch scalar value over IPv6 +++++++++++++++++++++++++++++ + +Send SNMP GET request with the following options: + +* with SNMPv2c, community 'public' +* using Asyncio framework for network transport +* over IPv6/UDP +* to an Agent at [::]:161 +* for an OID in string form + +This script performs similar to the following Net-SNMP command: + +| $ snmpget -v2c -c public -ObentU udp6:[::1]:161 1.3.6.1.2.1.1.1.0 + +Requires Python 3.4 and later! + +"""# from pysnmp.carrier.asyncio.dgram import udp6 from pysnmp.entity.rfc3413.asyncio import cmdgen from pysnmp.entity import engine, config diff --git a/examples/v3arch/asyncio/manager/cmdgen/getbulk-v2c.py b/examples/v3arch/asyncio/manager/cmdgen/getbulk-v2c.py index 5cbe619..939c846 100644 --- a/examples/v3arch/asyncio/manager/cmdgen/getbulk-v2c.py +++ b/examples/v3arch/asyncio/manager/cmdgen/getbulk-v2c.py @@ -1,21 +1,24 @@ -# -# GETBULK Command Generator -# -# Send a series of SNMP GETBULK requests -# with SNMPv2c, community 'public' -# using Asyncio framework for network transport -# over IPv4/UDP -# to an Agent at 195.218.195.228:161 -# with values non-repeaters = 0, max-repetitions = 25 -# for two OIDs in string form -# stop on end-of-mib condition for both OIDs -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpbulkwalk -v2c -c public -C n0 -C r25 -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 -# -# Requires Python 3.4 and later! -# +""" +Bulk walk MIB ++++++++++++++ + +Send a series of SNMP GETBULK requests with the following options: + +* with SNMPv2c, community 'public' +* using Asyncio framework for network transport +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* with values non-repeaters = 0, max-repetitions = 25 +* for two OIDs in string form +* stop on end-of-mib condition for both OIDs + +This script performs similar to the following Net-SNMP command: + +| $ snmpbulkwalk -v2c -c public -C n0 -C r25 -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 + +Requires Python 3.4 and later! + +"""# from pysnmp.entity import engine, config from pysnmp.proto import rfc1905 from pysnmp.entity.rfc3413.asyncio import cmdgen diff --git a/examples/v3arch/asyncio/manager/cmdgen/getnext-v2c-from-specific-address.py b/examples/v3arch/asyncio/manager/cmdgen/getnext-v2c-from-specific-address.py index e50eac8..10a97eb 100644 --- a/examples/v3arch/asyncio/manager/cmdgen/getnext-v2c-from-specific-address.py +++ b/examples/v3arch/asyncio/manager/cmdgen/getnext-v2c-from-specific-address.py @@ -1,21 +1,24 @@ -# -# GETNEXT Command Generator -# -# Send a series of SNMP GETNEXT requests -# with SNMPv2c, community 'public' -# using Asyncio framework for network transport -# over IPv4/UDP -# to an Agent at 195.218.195.228:161 -# sending packets from any local interface (0.0.0.0), local port 61024 -# for two OIDs in string form -# stop on end-of-mib condition for both OIDs -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpwalk -v2c -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 -# -# Requires Python 3.4 and later! -# +""" +Send packets from specific local interface +++++++++++++++++++++++++++++++++++++++++++ + +Send a series of SNMP GETNEXT requests with the following options: + +* with SNMPv2c, community 'public' +* using Asyncio framework for network transport +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* sending packets from any local interface (0.0.0.0), local port 61024 +* for two OIDs in string form +* stop on end-of-mib condition for both OIDs + +This script performs similar to the following Net-SNMP command: + +| $ snmpwalk -v2c -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 + +Requires Python 3.4 and later! + +"""# from pysnmp.entity import engine, config from pysnmp.proto import rfc1905 from pysnmp.entity.rfc3413.asyncio import cmdgen diff --git a/examples/v3arch/asyncio/manager/cmdgen/set-v2c.py b/examples/v3arch/asyncio/manager/cmdgen/set-v2c.py index 1e512f2..381f11a 100644 --- a/examples/v3arch/asyncio/manager/cmdgen/set-v2c.py +++ b/examples/v3arch/asyncio/manager/cmdgen/set-v2c.py @@ -1,20 +1,22 @@ -# -# Command Generator -# -# Send SNMP SET request using the following options: -# -# * with SNMPv1, community 'public' -# * using Asyncio framework for network transport -# * over IPv4/UDP -# * to an Agent at 195.218.195.228:161 -# * for OIDs in tuple form and an integer and string-typed values -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpset -v1 -c private -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.9.1.3.1 s 'my value' 1.3.6.1.2.1.1.9.1.4.1 t 123 -# -# Requires Python 3.4 and later! -# +""" +SET string and integer scalars +++++++++++++++++++++++++++++++ + +Send SNMP SET request using the following options: + +* with SNMPv1, community 'public' +* using Asyncio framework for network transport +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for OIDs in tuple form and an integer and string-typed values + +This script performs similar to the following Net-SNMP command: + +| $ snmpset -v1 -c private -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.9.1.3.1 s 'my value' 1.3.6.1.2.1.1.9.1.4.1 t 123 + +Requires Python 3.4 and later! + +"""# from pysnmp.carrier.asyncio.dgram import udp from pysnmp.entity.rfc3413.asyncio import cmdgen from pysnmp.entity import engine, config diff --git a/examples/v3arch/asyncio/manager/ntfrcv/v2c-multiple-interfaces.py b/examples/v3arch/asyncio/manager/ntfrcv/v2c-multiple-interfaces.py index a5fa241..30dc511 100644 --- a/examples/v3arch/asyncio/manager/ntfrcv/v2c-multiple-interfaces.py +++ b/examples/v3arch/asyncio/manager/ntfrcv/v2c-multiple-interfaces.py @@ -1,23 +1,25 @@ -# -# Notification Receiver -# -# Receive SNMP TRAP/INFORM messages with the following options: -# -# * SNMPv1/SNMPv2c -# * with SNMP community "public" -# * over IPv4/UDP, listening at 127.0.0.1:162 -# over IPv4/UDP, listening at 127.0.0.1:2162 -# * using Asyncio framework for network transport -# * print received data on stdout -# -# Either of the following Net-SNMP's commands will send notifications to this -# receiver: -# -# $ snmptrap -v2c -c public 127.0.0.1:162 123 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.5.0 s test -# $ snmpinform -v2c -c public 127.0.0.1:2162 123 1.3.6.1.6.3.1.1.5.1 -# -# Requires Python 3.4 and later! -# +""" +Serving multiple network interfaces ++++++++++++++++++++++++++++++++++++ + +Receive SNMP TRAP/INFORM messages with the following options: + +* SNMPv1/SNMPv2c +* with SNMP community "public" +* over IPv4/UDP, listening at 127.0.0.1:162 + over IPv4/UDP, listening at 127.0.0.1:2162 +* using Asyncio framework for network transport +* print received data on stdout + +Either of the following Net-SNMP commands will send notifications to this +receiver: + +| $ snmptrap -v2c -c public 127.0.0.1:162 123 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.5.0 s test +| $ snmpinform -v2c -c public 127.0.0.1:2162 123 1.3.6.1.6.3.1.1.5.1 + +Requires Python 3.4 and later! + +"""# from pysnmp.entity import engine, config from pysnmp.carrier.asyncio.dgram import udp from pysnmp.entity.rfc3413 import ntfrcv diff --git a/examples/v3arch/asyncore/agent/cmdrsp/v1-read-and-write-communities.py b/examples/v3arch/asyncore/agent/cmdrsp/v1-read-and-write-communities.py new file mode 100644 index 0000000..5780025 --- /dev/null +++ b/examples/v3arch/asyncore/agent/cmdrsp/v1-read-and-write-communities.py @@ -0,0 +1,65 @@ +""" +Multiple SNMP communities ++++++++++++++++++++++++++ + +Respond to SNMP GET/SET/GETNEXT queries with the following options: + +* SNMPv1 +* with SNMP community "public" (read access) or "private" (write access) +* allow access to SNMPv2-MIB objects (1.3.6.1.2.1) +* over IPv4/UDP, listening at 127.0.0.1:161 + +Allow read/write access to all objects in the same MIB subtree. + +The following Net-SNMP's commands will GET/SET a value at this Agent: + +| $ snmpget -v1 -c public 127.0.0.1 SNMPv2-MIB::sysLocation.0 +| $ snmpset -v1 -c private 127.0.0.1 SNMPv2-MIB::sysLocation.0 s "far away" + +"""# +from pysnmp.entity import engine, config +from pysnmp.entity.rfc3413 import cmdrsp, context +from pysnmp.carrier.asyncore.dgram import udp + +# Create SNMP engine with autogenernated engineID and pre-bound +# to socket transport dispatcher +snmpEngine = engine.SnmpEngine() + +# Transport setup + +# UDP over IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpTransport().openServerMode(('127.0.0.1', 161)) +) + +# SNMPv1 setup + +# SecurityName <-> CommunityName mapping. +# Here we configure two distinct CommunityName's to control read and write +# operations. +config.addV1System(snmpEngine, 'my-read-area', 'public') +config.addV1System(snmpEngine, 'my-write-area', 'private') + +# Allow full MIB access for this user / securityModels at VACM +config.addVacmUser(snmpEngine, 1, 'my-read-area', 'noAuthNoPriv', (1,3,6,1,2,1)) +config.addVacmUser(snmpEngine, 1, 'my-write-area', 'noAuthNoPriv', (1,3,6,1,2,1), (1,3,6,1,2,1)) + +# Get default SNMP context this SNMP engine serves +snmpContext = context.SnmpContext(snmpEngine) + +# Register SNMP Applications at the SNMP engine for particular SNMP context +cmdrsp.GetCommandResponder(snmpEngine, snmpContext) +cmdrsp.SetCommandResponder(snmpEngine, snmpContext) +cmdrsp.NextCommandResponder(snmpEngine, snmpContext) + +# Register an imaginary never-ending job to keep I/O dispatcher running forever +snmpEngine.transportDispatcher.jobStarted(1) + +# Run I/O dispatcher which would receive queries and send responses +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/agent/cmdrsp/v2c-custom-scalar-mib-objects.py b/examples/v3arch/asyncore/agent/cmdrsp/v2c-custom-scalar-mib-objects.py new file mode 100644 index 0000000..196ee9c --- /dev/null +++ b/examples/v3arch/asyncore/agent/cmdrsp/v2c-custom-scalar-mib-objects.py @@ -0,0 +1,82 @@ +""" +Implementing scalar MIB objects ++++++++++++++++++++++++++++++++ + +Listen and respond to SNMP GET/SET/GETNEXT/GETBULK queries with +the following options: + +* SNMPv2c +* with SNMP community "public" +* serving custom Managed Object Instance defined within this script +* allow read access only to the subtree where the custom MIB object resides +* over IPv4/UDP, listening at 127.0.0.1:161 + +The following Net-SNMP commands will walk this Agent: + +| $ snmpwalk -v2c -c public 127.0.0.1 .1.3.6 + +"""# +import sys +from pysnmp.entity import engine, config +from pysnmp.entity.rfc3413 import cmdrsp, context +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.proto.api import v2c + +# Create SNMP engine +snmpEngine = engine.SnmpEngine() + +# Transport setup + +# UDP over IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpTransport().openServerMode(('127.0.0.1', 161)) +) + +# SNMPv2c setup + +# SecurityName <-> CommunityName mapping. +config.addV1System(snmpEngine, 'my-area', 'public') + +# Allow read MIB access for this user / securityModels at VACM +config.addVacmUser(snmpEngine, 2, 'my-area', 'noAuthNoPriv', (1,3,6,5)) + +# Create an SNMP context +snmpContext = context.SnmpContext(snmpEngine) + +# --- create custom Managed Object Instance --- + +mibBuilder = snmpContext.getMibInstrum().getMibBuilder() + +MibScalar, MibScalarInstance = mibBuilder.importSymbols( + 'SNMPv2-SMI', 'MibScalar', 'MibScalarInstance' +) + +class MyStaticMibScalarInstance(MibScalarInstance): + def getValue(self, name, idx): + return self.getSyntax().clone( + 'Python %s running on a %s platform' % (sys.version, sys.platform) + ) + +mibBuilder.exportSymbols( + '__MY_MIB', MibScalar((1,3,6,5,1), v2c.OctetString()), + MyStaticMibScalarInstance((1,3,6,5,1), (0,), v2c.OctetString()) +) + +# --- end of Managed Object Instance initialization ---- + +# Register SNMP Applications at the SNMP engine for particular SNMP context +cmdrsp.GetCommandResponder(snmpEngine, snmpContext) +cmdrsp.NextCommandResponder(snmpEngine, snmpContext) +cmdrsp.BulkCommandResponder(snmpEngine, snmpContext) + +# Register an imaginary never-ending job to keep I/O dispatcher running forever +snmpEngine.transportDispatcher.jobStarted(1) + +# Run I/O dispatcher which would receive queries and send responses +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/agent/cmdrsp/v2c-custom-tabular-mib-objects.py b/examples/v3arch/asyncore/agent/cmdrsp/v2c-custom-tabular-mib-objects.py new file mode 100644 index 0000000..bf6d042 --- /dev/null +++ b/examples/v3arch/asyncore/agent/cmdrsp/v2c-custom-tabular-mib-objects.py @@ -0,0 +1,126 @@ +""" +Implementing conceptual table ++++++++++++++++++++++++++++++ + +Listen and respond to SNMP GET/SET/GETNEXT/GETBULK queries with +the following options: + +* SNMPv2c +* with SNMP community "public" +* define a simple SNMP Table within a newly created EXAMPLE-MIB +* pre-populate SNMP Table with a single row of values +* allow read access only to the subtree where example SNMP Table resides +* over IPv4/UDP, listening at 127.0.0.1:161 + +The following Net-SNMP commands will populate and walk a table: + +| $ snmpset -v2c -c public 127.0.0.1 1.3.6.6.1.5.2.97.98.99 s 'my value' +| $ snmpset -v2c -c public 127.0.0.1 1.3.6.6.1.5.4.97.98.99 i 4 +| $ snmpwalk -v2c -c public 127.0.0.1 1.3.6 + +...while the following command will destroy the same row + +| $ snmpset -v2c -c public 127.0.0.1 1.3.6.6.1.5.4.97.98.99 i 6 +| $ snmpwalk -v2c -c public 127.0.0.1 1.3.6 + +"""# +from pysnmp.entity import engine, config +from pysnmp.entity.rfc3413 import cmdrsp, context +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.proto.api import v2c + +# Create SNMP engine +snmpEngine = engine.SnmpEngine() + +# Transport setup + +# UDP over IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpTransport().openServerMode(('127.0.0.1', 161)) +) + +# SNMPv2c setup + +# SecurityName <-> CommunityName mapping. +config.addV1System(snmpEngine, 'my-area', 'public') + +# Allow read MIB access for this user / securityModels at VACM +config.addVacmUser(snmpEngine, 2, 'my-area', 'noAuthNoPriv', (1,3,6,6), (1,3,6,6)) + +# Create an SNMP context +snmpContext = context.SnmpContext(snmpEngine) + +# --- define custom SNMP Table within a newly defined EXAMPLE-MIB --- + +mibBuilder = snmpContext.getMibInstrum().getMibBuilder() + +( MibTable, + MibTableRow, + MibTableColumn, + MibScalarInstance ) = mibBuilder.importSymbols( + 'SNMPv2-SMI', + 'MibTable', + 'MibTableRow', + 'MibTableColumn', + 'MibScalarInstance' + ) + +RowStatus, = mibBuilder.importSymbols('SNMPv2-TC', 'RowStatus') + +mibBuilder.exportSymbols( + '__EXAMPLE-MIB', + # table object + exampleTable=MibTable((1,3,6,6,1)).setMaxAccess('readcreate'), + # table row object, also carries references to table indices + exampleTableEntry=MibTableRow((1,3,6,6,1,5)).setMaxAccess('readcreate').setIndexNames((0, '__EXAMPLE-MIB', 'exampleTableColumn1')), + # table column: string index + exampleTableColumn1=MibTableColumn((1,3,6,6,1,5,1), v2c.OctetString()).setMaxAccess('readcreate'), + # table column: string value + exampleTableColumn2=MibTableColumn((1,3,6,6,1,5,2), v2c.OctetString()).setMaxAccess('readcreate'), + # table column: integer value with default + exampleTableColumn3=MibTableColumn((1,3,6,6,1,5,3), v2c.Integer32(123)).setMaxAccess('readcreate'), + # table column: row status + exampleTableStatus=MibTableColumn((1,3,6,6,1,5,4), RowStatus('notExists')).setMaxAccess('readcreate') +) + +# --- end of custom SNMP table definition, empty table now exists --- + +# --- populate custom SNMP table with one row --- + +( exampleTableEntry, + exampleTableColumn2, + exampleTableColumn3, + exampleTableStatus ) = mibBuilder.importSymbols( + '__EXAMPLE-MIB', + 'exampleTableEntry', + 'exampleTableColumn2', + 'exampleTableColumn3', + 'exampleTableStatus' +) +rowInstanceId = exampleTableEntry.getInstIdFromIndices('example record one') +mibInstrumentation = snmpContext.getMibInstrum() +mibInstrumentation.writeVars( + ( (exampleTableColumn2.name+rowInstanceId, 'my string value'), + (exampleTableColumn3.name+rowInstanceId, 123456), + (exampleTableStatus.name+rowInstanceId, 'createAndGo') ) +) + +# --- end of SNMP table population --- + +# Register SNMP Applications at the SNMP engine for particular SNMP context +cmdrsp.GetCommandResponder(snmpEngine, snmpContext) +cmdrsp.SetCommandResponder(snmpEngine, snmpContext) +cmdrsp.NextCommandResponder(snmpEngine, snmpContext) +cmdrsp.BulkCommandResponder(snmpEngine, snmpContext) + +# Register an imaginary never-ending job to keep I/O dispatcher running forever +snmpEngine.transportDispatcher.jobStarted(1) + +# Run I/O dispatcher which would receive queries and send responses +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/agent/cmdrsp/v2c-multiple-interfaces.py b/examples/v3arch/asyncore/agent/cmdrsp/v2c-multiple-interfaces.py new file mode 100644 index 0000000..25beef3 --- /dev/null +++ b/examples/v3arch/asyncore/agent/cmdrsp/v2c-multiple-interfaces.py @@ -0,0 +1,67 @@ +""" +Listen on multiple network interfaces ++++++++++++++++++++++++++++++++++++++ + +Listen and respond to SNMP GET/SET/GETNEXT/GETBULK queries with +the following options: + +* SNMPv2c +* with SNMP community "public" +* allow access to SNMPv2-MIB objects (1.3.6.1.2.1) +* over IPv4/UDP, listening at 127.0.0.1:161 and 127.0.0.2:161 interfaces + +Either of the following Net-SNMP commands will walk this Agent: + +| $ snmpwalk -v2c -c public 127.0.0.1 .1.3.6 +| $ snmpwalk -v2c -c public 127.0.0.2 .1.3.6 + +"""# +from pysnmp.entity import engine, config +from pysnmp.entity.rfc3413 import cmdrsp, context +from pysnmp.carrier.asyncore.dgram import udp + +# Create SNMP engine with autogenernated engineID and pre-bound +# to socket transport dispatcher +snmpEngine = engine.SnmpEngine() + +# Transport setup + +# UDP over IPv4 at 127.0.0.1:161 +config.addTransport( + snmpEngine, + udp.domainName + (1,), + udp.UdpTransport().openServerMode(('127.0.0.1', 161)) +) +# UDP over IPv4 at 127.0.0.2:161 +config.addTransport( + snmpEngine, + udp.domainName + (2,), + udp.UdpTransport().openServerMode(('127.0.0.2', 161)) +) + +# SNMPv2c setup + +# SecurityName <-> CommunityName mapping. +config.addV1System(snmpEngine, 'my-area', 'public') + +# Allow full MIB access for this user / securityModels at VACM +config.addVacmUser(snmpEngine, 2, 'my-area', 'noAuthNoPriv', (1,3,6,1,2,1), (1,3,6,1,2,1)) + +# Get default SNMP context this SNMP engine serves +snmpContext = context.SnmpContext(snmpEngine) + +# Register SNMP Applications at the SNMP engine for particular SNMP context +cmdrsp.GetCommandResponder(snmpEngine, snmpContext) +cmdrsp.SetCommandResponder(snmpEngine, snmpContext) +cmdrsp.NextCommandResponder(snmpEngine, snmpContext) +cmdrsp.BulkCommandResponder(snmpEngine, snmpContext) + +# Register an imaginary never-ending job to keep I/O dispatcher running forever +snmpEngine.transportDispatcher.jobStarted(1) + +# Run I/O dispatcher which would receive queries and send responses +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/agent/cmdrsp/v2c-multiple-transports.py b/examples/v3arch/asyncore/agent/cmdrsp/v2c-multiple-transports.py new file mode 100644 index 0000000..24de061 --- /dev/null +++ b/examples/v3arch/asyncore/agent/cmdrsp/v2c-multiple-transports.py @@ -0,0 +1,68 @@ +""" +Serve multiple network transports ++++++++++++++++++++++++++++++++++ + +Listen and respond to SNMP GET/SET/GETNEXT/GETBULK queries with +the following options: + +* SNMPv2c +* with SNMP community "public" +* allow access to SNMPv2-MIB objects (1.3.6.1.2.1) +* over IPv4/UDP, listening at 127.0.0.1:161 and + over IPv6/UDP, listening at [::1]:161 + +Either of the following Net-SNMP commands will walk this Agent: + +| $ snmpwalk -v2c -c public 127.0.0.1 .1.3.6 +| $ snmpwalk -v2c -c public udp6:[::1] .1.3.6 + +"""# +from pysnmp.entity import engine, config +from pysnmp.entity.rfc3413 import cmdrsp, context +from pysnmp.carrier.asyncore.dgram import udp, udp6 + +# Create SNMP engine with autogenernated engineID and pre-bound +# to socket transport dispatcher +snmpEngine = engine.SnmpEngine() + +# Transport setup + +# UDP over IPv4 at 127.0.0.1:161 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpTransport().openServerMode(('127.0.0.1', 161)) +) +# UDP over IPv6 at [::1]:161 +config.addTransport( + snmpEngine, + udp6.domainName, + udp6.Udp6Transport().openServerMode(('::1', 161)) +) + +# SNMPv2c setup + +# SecurityName <-> CommunityName mapping. +config.addV1System(snmpEngine, 'my-area', 'public') + +# Allow full MIB access for this user / securityModels at VACM +config.addVacmUser(snmpEngine, 2, 'my-area', 'noAuthNoPriv', (1,3,6,1,2,1), (1,3,6,1,2,1)) + +# Get default SNMP context this SNMP engine serves +snmpContext = context.SnmpContext(snmpEngine) + +# Register SNMP Applications at the SNMP engine for particular SNMP context +cmdrsp.GetCommandResponder(snmpEngine, snmpContext) +cmdrsp.SetCommandResponder(snmpEngine, snmpContext) +cmdrsp.NextCommandResponder(snmpEngine, snmpContext) +cmdrsp.BulkCommandResponder(snmpEngine, snmpContext) + +# Register an imaginary never-ending job to keep I/O dispatcher running forever +snmpEngine.transportDispatcher.jobStarted(1) + +# Run I/O dispatcher which would receive queries and send responses +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/agent/cmdrsp/v3-alternative-mib-controller.py b/examples/v3arch/asyncore/agent/cmdrsp/v3-alternative-mib-controller.py new file mode 100644 index 0000000..1711133 --- /dev/null +++ b/examples/v3arch/asyncore/agent/cmdrsp/v3-alternative-mib-controller.py @@ -0,0 +1,77 @@ +""" +Custom MIB Controller ++++++++++++++++++++++ + +Listen and respond to SNMP GET/SET/GETNEXT/GETBULK queries with +the following options: + +* SNMPv3 +* with USM username usr-none-none +* using alternative set of Managed Objects addressed by + contextName: my-context +* allow access to SNMPv2-MIB objects (1.3.6.1.2.1) +* over IPv4/UDP, listening at 127.0.0.1:161 + +The following Net-SNMP command will send GET request to this Agent: + +| $ snmpget -v3 -u usr-none-none -l noAuthNoPriv -n my-context -Ir 127.0.0.1 sysDescr.0 + +"""# +from pysnmp.entity import engine, config +from pysnmp.entity.rfc3413 import cmdrsp, context +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.smi import instrum +from pysnmp.proto.api import v2c + +# Create SNMP engine +snmpEngine = engine.SnmpEngine() + +# Transport setup + +# UDP over IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpTransport().openServerMode(('127.0.0.1', 161)) +) + +# SNMPv3/USM setup + +# user: usr-none-none, auth: NONE, priv NONE +config.addV3User( + snmpEngine, 'usr-none-none' +) + +# Allow full MIB access for each user at VACM +config.addVacmUser(snmpEngine, 3, 'usr-none-none', 'noAuthNoPriv', (1,3,6,1,2,1), (1,3,6,1,2,1)) + +# Create an SNMP context +snmpContext = context.SnmpContext(snmpEngine) + +# Very basic Management Instrumentation Controller without +# any Managed Objects attached. It supports only GET's and +# always echos request var-binds in response. +class EchoMibInstrumController(instrum.AbstractMibInstrumController): + def readVars(self, vars, acInfo=(None, None)): + return [ (ov[0], v2c.OctetString('You queried OID %s' % ov[0])) for ov in vars] + +# Create a custom Management Instrumentation Controller and register at +# SNMP Context under ContextName 'my-context' +snmpContext.registerContextName( + v2c.OctetString('my-context'), # Context Name + EchoMibInstrumController() # Management Instrumentation +) + +# Register GET&SET Applications at the SNMP engine for a custom SNMP context +cmdrsp.GetCommandResponder(snmpEngine, snmpContext) +cmdrsp.SetCommandResponder(snmpEngine, snmpContext) + +# Register an imaginary never-ending job to keep I/O dispatcher running forever +snmpEngine.transportDispatcher.jobStarted(1) + +# Run I/O dispatcher which would receive queries and send responses +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/agent/cmdrsp/v3-alternative-mib.py b/examples/v3arch/asyncore/agent/cmdrsp/v3-alternative-mib.py new file mode 100644 index 0000000..fa3bc6b --- /dev/null +++ b/examples/v3arch/asyncore/agent/cmdrsp/v3-alternative-mib.py @@ -0,0 +1,77 @@ +""" +Serve non-default MIB tree +++++++++++++++++++++++++++ + +Listen and respond to SNMP GET/SET/GETNEXT/GETBULK queries with +the following options: + +* SNMPv3 +* with USM username usr-md5-none +* using alternative set of Managed Objects addressed by + contextEngineId: 8000000001020304, contextName: my-context +* allow access to SNMPv2-MIB objects (1.3.6.1.2.1) +* over IPv4/UDP, listening at 127.0.0.1:161 + +Either of the following Net-SNMP commands will walk this Agent: + +| $ snmpwalk -v3 -u usr-md5-none -l authNoPriv -A authkey1 -E 8000000001020304 -n my-context 127.0.0.1 .1.3.6 +| $ snmpwalk -v3 -u usr-md5-none -l authNoPriv -A authkey1 -E 8000000001020304 127.0.0.1 .1.3.6 + +"""# +from pysnmp.entity import engine, config +from pysnmp.entity.rfc3413 import cmdrsp, context +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.smi import instrum, builder +from pysnmp.proto.api import v2c + +# Create SNMP engine +snmpEngine = engine.SnmpEngine() + +# Transport setup + +# UDP over IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpTransport().openServerMode(('127.0.0.1', 161)) +) + +# SNMPv3/USM setup + +# user: usr-md5-none, auth: MD5, priv NONE +config.addV3User( + snmpEngine, 'usr-md5-none', + config.usmHMACMD5AuthProtocol, 'authkey1' +) + +# Allow full MIB access for each user at VACM +config.addVacmUser(snmpEngine, 3, 'usr-md5-none', 'authNoPriv', (1,3,6,1,2,1), (1,3,6,1,2,1)) + +# Create an SNMP context with ContextEngineId = 8000000001020304 +snmpContext = context.SnmpContext( + snmpEngine, contextEngineId=v2c.OctetString(hexValue='8000000001020304') +) + +# Create an [empty] set of Managed Objects (MibBuilder), pass it to +# Management Instrumentation Controller and register at SNMP Context +# under ContextName 'my-context' +snmpContext.registerContextName( + v2c.OctetString('my-context'), # Context Name + instrum.MibInstrumController(builder.MibBuilder()) # Managed Objects +) + +# Register SNMP Applications at the SNMP engine for particular SNMP context +cmdrsp.GetCommandResponder(snmpEngine, snmpContext) +cmdrsp.SetCommandResponder(snmpEngine, snmpContext) +cmdrsp.NextCommandResponder(snmpEngine, snmpContext) +cmdrsp.BulkCommandResponder(snmpEngine, snmpContext) + +# Register an imaginary never-ending job to keep I/O dispatcher running forever +snmpEngine.transportDispatcher.jobStarted(1) + +# Run I/O dispatcher which would receive queries and send responses +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/agent/cmdrsp/v3-custom-engine-id.py b/examples/v3arch/asyncore/agent/cmdrsp/v3-custom-engine-id.py new file mode 100644 index 0000000..e2452ca --- /dev/null +++ b/examples/v3arch/asyncore/agent/cmdrsp/v3-custom-engine-id.py @@ -0,0 +1,65 @@ +""" +Specific SNMP Engine ID ++++++++++++++++++++++++ + +Listen and respond to SNMP GET/SET/GETNEXT/GETBULK queries with +the following options: + +* SNMPv3 +* with SNMP EngineID: 8000000004030201 +* with USM user 'usr-md5-des', auth: MD5, priv DES +* allow access to SNMPv2-MIB objects (1.3.6.1.2.1) +* over IPv4/UDP, listening at 127.0.0.1:161 + +The following Net-SNMP command will walk this Agent: + +| $ snmpwalk -v3 -u usr-md5-des -l authPriv -A authkey1 -X privkey1 -e 8000000004030201 localhost .1.3.6 + +"""# +from pysnmp.entity import engine, config +from pysnmp.entity.rfc3413 import cmdrsp, context +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.proto import rfc1902 + +# Create SNMP engine +snmpEngine = engine.SnmpEngine(rfc1902.OctetString(hexValue='8000000004030201')) + +# Transport setup + +# UDP over IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpTransport().openServerMode(('127.0.0.1', 161)) +) + +# SNMPv3/USM setup + +# user: usr-md5-des, auth: MD5, priv DES +config.addV3User( + snmpEngine, 'usr-md5-des', + config.usmHMACMD5AuthProtocol, 'authkey1', + config.usmDESPrivProtocol, 'privkey1' +) + +# Allow full MIB access for each user at VACM +config.addVacmUser(snmpEngine, 3, 'usr-md5-des', 'authPriv', (1,3,6,1,2,1), (1,3,6,1,2,1)) + +# Get default SNMP context this SNMP engine serves +snmpContext = context.SnmpContext(snmpEngine) + +# Register SNMP Applications at the SNMP engine for particular SNMP context +cmdrsp.GetCommandResponder(snmpEngine, snmpContext) +cmdrsp.SetCommandResponder(snmpEngine, snmpContext) +cmdrsp.NextCommandResponder(snmpEngine, snmpContext) +cmdrsp.BulkCommandResponder(snmpEngine, snmpContext) + +# Register an imaginary never-ending job to keep I/O dispatcher running forever +snmpEngine.transportDispatcher.jobStarted(1) + +# Run I/O dispatcher which would receive queries and send responses +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/agent/cmdrsp/v3-multiple-snmp-engines.py b/examples/v3arch/asyncore/agent/cmdrsp/v3-multiple-snmp-engines.py new file mode 100644 index 0000000..0a7b3a2 --- /dev/null +++ b/examples/v3arch/asyncore/agent/cmdrsp/v3-multiple-snmp-engines.py @@ -0,0 +1,93 @@ +""" +Multiple SNMP Engines ++++++++++++++++++++++ + +Run multiple SNMP Engines each with a complete Command Responder. +Bind each SNMP Engine to a dedicated network transport endpoint: + +* IPv4/UDP, listening at 127.0.0.1:161 +* IPv4/UDP, listening at 127.0.0.2:161 + +Each Command Responder will respond to SNMP GET/SET/GETNEXT/GETBULK +queries with the following options: + +* SNMPv3 +* with USM user 'usr-md5-des', auth: MD5, priv DES +* allow read access to SNMPv2-MIB objects (1.3.6) +* allow write access to SNMPv2-MIB objects (1.3.6.1.2.1) + +The following Net-SNMP commands will walk the first and the second +Agent respectively: + +| $ snmpwalk -Ob -v3 -u usr-md5-des -l authPriv -A authkey1 -X privkey1 127.0.0.1 usmUserEntry +| $ snmpwalk -Ob -v3 -u usr-md5-des -l authPriv -A authkey1 -X privkey1 127.0.0.2 usmUserEntry + +Notice differently configured snmpEngineId's in usmUserEntry columns. + +"""# +from pysnmp.entity import engine, config +from pysnmp.entity.rfc3413 import cmdrsp, context +from pysnmp.proto import rfc1902 +from pysnmp.carrier.asyncore.dispatch import AsyncoreDispatcher +from pysnmp.carrier.asyncore.dgram import udp + +# Configuration parameters for each of SNMP Engines +snmpEngineInfo = ( + ( '0102030405060708', udp.domainName + (0,), ('127.0.0.1', 161) ), + ( '0807060504030201', udp.domainName + (1,), ('127.0.0.2', 161) ) +) + +# Instantiate the single transport dispatcher object +transportDispatcher = AsyncoreDispatcher() + +# Setup a custom data routing function to select snmpEngine by transportDomain +transportDispatcher.registerRoutingCbFun(lambda td,t,d: td) + +# Instantiate and configure SNMP Engines +for snmpEngineId, transportDomain, transportAddress in snmpEngineInfo: + # Create SNMP engine with specific engineID + snmpEngine = engine.SnmpEngine(rfc1902.OctetString(hexValue=snmpEngineId)) + + # Register SNMP Engine object with transport dispatcher. Request incoming + # data from specific transport endpoint to be funneled to this SNMP Engine. + snmpEngine.registerTransportDispatcher(transportDispatcher, transportDomain) + + # Transport setup + + # UDP over IPv4 + config.addTransport( + snmpEngine, + transportDomain, + udp.UdpTransport().openServerMode(transportAddress) + ) + + # SNMPv3/USM setup + + # user: usr-md5-des, auth: MD5, priv DES + config.addV3User( + snmpEngine, 'usr-md5-des', + config.usmHMACMD5AuthProtocol, 'authkey1', + config.usmDESPrivProtocol, 'privkey1' + ) + + # Allow full MIB access for this user / securityModels at VACM + config.addVacmUser(snmpEngine, 3, 'usr-md5-des', 'authPriv', (1,3,6), (1,3,6,1,2,1)) + + # Get default SNMP context this SNMP engine serves + snmpContext = context.SnmpContext(snmpEngine) + + # Register SNMP Applications at the SNMP engine for particular SNMP context + cmdrsp.GetCommandResponder(snmpEngine, snmpContext) + cmdrsp.SetCommandResponder(snmpEngine, snmpContext) + cmdrsp.NextCommandResponder(snmpEngine, snmpContext) + cmdrsp.BulkCommandResponder(snmpEngine, snmpContext) + +# Register an imaginary never-ending job to keep I/O dispatcher running forever +transportDispatcher.jobStarted(1) + +# Run I/O dispatcher which would receive queries and send responses +try: + transportDispatcher.runDispatcher() +except: + transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/agent/cmdrsp/v3-multiple-users.py b/examples/v3arch/asyncore/agent/cmdrsp/v3-multiple-users.py new file mode 100644 index 0000000..150a0f4 --- /dev/null +++ b/examples/v3arch/asyncore/agent/cmdrsp/v3-multiple-users.py @@ -0,0 +1,80 @@ +""" +Multiple SNMP USM users ++++++++++++++++++++++++ + +Listen and respond to SNMP GET/SET/GETNEXT/GETBULK queries with +the following options: + +* SNMPv3 +* with USM user 'usr-md5-des', auth: MD5, priv DES or + with USM user 'usr-sha-none', auth: SHA, no privacy + with USM user 'usr-sha-aes128', auth: SHA, priv AES +* allow access to SNMPv2-MIB objects (1.3.6.1.2.1) +* over IPv4/UDP, listening at 127.0.0.1:161 + +Either of the following Net-SNMP commands will walk this Agent: + +| $ snmpwalk -v3 -u usr-md5-des -l authPriv -A authkey1 -X privkey1 localhost .1.3.6 +| $ snmpwalk -v3 -u usr-sha-none -l authNoPriv -a SHA -A authkey1 localhost .1.3.6 +| $ snmpwalk -v3 -u usr-sha-aes128 -l authPriv -a SHA -A authkey1 -x AES -X privkey1 localhost .1.3.6 + +"""# +from pysnmp.entity import engine, config +from pysnmp.entity.rfc3413 import cmdrsp, context +from pysnmp.carrier.asyncore.dgram import udp + +# Create SNMP engine +snmpEngine = engine.SnmpEngine() + +# Transport setup + +# UDP over IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpTransport().openServerMode(('127.0.0.1', 161)) +) + +# SNMPv3/USM setup + +# user: usr-md5-des, auth: MD5, priv DES +config.addV3User( + snmpEngine, 'usr-md5-des', + config.usmHMACMD5AuthProtocol, 'authkey1', + config.usmDESPrivProtocol, 'privkey1' +) +# user: usr-sha-none, auth: SHA, priv NONE +config.addV3User( + snmpEngine, 'usr-sha-none', + config.usmHMACSHAAuthProtocol, 'authkey1' +) +# user: usr-sha-none, auth: SHA, priv AES +config.addV3User( + snmpEngine, 'usr-sha-aes128', + config.usmHMACSHAAuthProtocol, 'authkey1', + config.usmAesCfb128Protocol, 'privkey1' +) + +# Allow full MIB access for each user at VACM +config.addVacmUser(snmpEngine, 3, 'usr-md5-des', 'authPriv', (1,3,6,1,2,1), (1,3,6,1,2,1)) +config.addVacmUser(snmpEngine, 3, 'usr-sha-none', 'authNoPriv', (1,3,6,1,2,1), (1,3,6,1,2,1)) +config.addVacmUser(snmpEngine, 3, 'usr-sha-aes128', 'authPriv', (1,3,6,1,2,1), (1,3,6,1,2,1)) + +# Get default SNMP context this SNMP engine serves +snmpContext = context.SnmpContext(snmpEngine) + +# Register SNMP Applications at the SNMP engine for particular SNMP context +cmdrsp.GetCommandResponder(snmpEngine, snmpContext) +cmdrsp.SetCommandResponder(snmpEngine, snmpContext) +cmdrsp.NextCommandResponder(snmpEngine, snmpContext) +cmdrsp.BulkCommandResponder(snmpEngine, snmpContext) + +# Register an imaginary never-ending job to keep I/O dispatcher running forever +snmpEngine.transportDispatcher.jobStarted(1) + +# Run I/O dispatcher which would receive queries and send responses +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/agent/cmdrsp/v3-observe-request-processing.py b/examples/v3arch/asyncore/agent/cmdrsp/v3-observe-request-processing.py new file mode 100644 index 0000000..d03c52c --- /dev/null +++ b/examples/v3arch/asyncore/agent/cmdrsp/v3-observe-request-processing.py @@ -0,0 +1,90 @@ +""" +Observe SNMP engine operations +++++++++++++++++++++++++++++++ + +Listen and respond to SNMP GET/SET/GETNEXT/GETBULK queries with +the following options: + +* SNMPv3 +* with USM user 'usr-md5-des', auth: MD5, priv DES or +* allow access to SNMPv2-MIB objects (1.3.6.1.2.1) +* over IPv4/UDP, listening at 127.0.0.1:161 +* registers its own execution observer to snmpEngine + +The following Net-SNMP command will walk this Agent: + +| $ snmpwalk -v3 -u usr-md5-des -l authPriv -A authkey1 -X privkey1 localhost .1.3.6 + +This script will report some details on request processing as seen +by rfc3412.receiveMessage() and rfc3412.returnResponsePdu() +abstract interfaces. + +"""# +from pysnmp.entity import engine, config +from pysnmp.entity.rfc3413 import cmdrsp, context +from pysnmp.carrier.asyncore.dgram import udp + +# Create SNMP engine +snmpEngine = engine.SnmpEngine() + +# Execution point observer setup + +# Register a callback to be invoked at specified execution point of +# SNMP Engine and passed local variables at code point's local scope +def requestObserver(snmpEngine, execpoint, variables, cbCtx): + print('Execution point: %s' % execpoint) + print('* transportDomain: %s' % '.'.join([str(x) for x in variables['transportDomain']])) + print('* transportAddress: %s (local %s)' % ('@'.join([str(x) for x in variables['transportAddress']]), '@'.join([str(x) for x in variables['transportAddress'].getLocalAddress()]))) + print('* securityModel: %s' % variables['securityModel']) + print('* securityName: %s' % variables['securityName']) + print('* securityLevel: %s' % variables['securityLevel']) + print('* contextEngineId: %s' % variables['contextEngineId'].prettyPrint()) + print('* contextName: %s' % variables['contextName'].prettyPrint()) + print('* PDU: %s' % variables['pdu'].prettyPrint()) + +snmpEngine.observer.registerObserver( + requestObserver, + 'rfc3412.receiveMessage:request', + 'rfc3412.returnResponsePdu' +) + +# Transport setup + +# UDP over IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpTransport().openServerMode(('127.0.0.1', 161)) +) + +# SNMPv3/USM setup + +# user: usr-md5-des, auth: MD5, priv DES +config.addV3User( + snmpEngine, 'usr-md5-des', + config.usmHMACMD5AuthProtocol, 'authkey1', + config.usmDESPrivProtocol, 'privkey1' +) + +# Allow full MIB access for each user at VACM +config.addVacmUser(snmpEngine, 3, 'usr-md5-des', 'authPriv', (1,3,6,1,2,1), (1,3,6,1,2,1)) + +# Get default SNMP context this SNMP engine serves +snmpContext = context.SnmpContext(snmpEngine) + +# Register SNMP Applications at the SNMP engine for particular SNMP context +cmdrsp.GetCommandResponder(snmpEngine, snmpContext) +cmdrsp.SetCommandResponder(snmpEngine, snmpContext) +cmdrsp.NextCommandResponder(snmpEngine, snmpContext) +cmdrsp.BulkCommandResponder(snmpEngine, snmpContext) + +# Register an imaginary never-ending job to keep I/O dispatcher running forever +snmpEngine.transportDispatcher.jobStarted(1) + +# Run I/O dispatcher which would receive queries and send responses +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.observer.unregisterObserver() + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/agent/cmdrsp/v3-preserve-original-destination-address.py b/examples/v3arch/asyncore/agent/cmdrsp/v3-preserve-original-destination-address.py new file mode 100644 index 0000000..1e86270 --- /dev/null +++ b/examples/v3arch/asyncore/agent/cmdrsp/v3-preserve-original-destination-address.py @@ -0,0 +1,91 @@ +""" +Running at secondary network interface +++++++++++++++++++++++++++++++++++++++ + +Listen on all local IPv4 interfaces respond to SNMP GET/SET/GETNEXT/GETBULK +queries with the following options: + +* SNMPv3 +* with USM user 'usr-md5-des', auth: MD5, priv DES +* allow access to SNMPv2-MIB objects (1.3.6.1.2.1) +* over IPv4/UDP, listening at 0.0.0.0:161 +* preserve local IP address when responding (Python 3.3+ required) + +The following Net-SNMP command will walk this Agent: + +| $ snmpwalk -v3 -u usr-md5-des -l authPriv -A authkey1 -X privkey1 localhost .1.3.6 + +In the situation when UDP responder receives a datagram targeted to +a secondary (AKA virtial) IP interface or a non-local IP interface +(e.g. routed through policy routing or iptables TPROXY facility), +OS stack will by default put primary local IP interface address into +the IP source field of the response IP packet. Such datagram may not +reach the sender as either the sender itself or a stateful firewall +somewhere in between would not be able to match response to original +request. + +The following script solves this problem by preserving original request +destination IP address and put it back into response IP packet's source +address field. + +To respond from a non-local (e.g. spoofed) IP address, uncomment the +.enableTransparent() method call and run this script as root. + +"""# +from pysnmp.entity import engine, config +from pysnmp.entity.rfc3413 import cmdrsp, context +from pysnmp.carrier.asyncore.dgram import udp + +# Create SNMP engine +snmpEngine = engine.SnmpEngine() + +# Transport setup + +# Initialize asyncore-based UDP/IPv4 transport +udpSocketTransport = udp.UdpSocketTransport().openServerMode(('0.0.0.0', 161)) + +# Use sendmsg()/recvmsg() for socket communication (used for preserving +# original destination IP address when responding) +udpSocketTransport.enablePktInfo() + +# Enable IP source spoofing (requires root privileges) +# udpSocketTransport.enableTransparent() + +# Register this transport at SNMP Engine +config.addTransport( + snmpEngine, + udp.domainName, + udpSocketTransport +) + +# SNMPv3/USM setup + +# user: usr-md5-des, auth: MD5, priv DES +config.addV3User( + snmpEngine, 'usr-md5-des', + config.usmHMACMD5AuthProtocol, 'authkey1', + config.usmDESPrivProtocol, 'privkey1' +) + +# Allow full MIB access for each user at VACM +config.addVacmUser(snmpEngine, 3, 'usr-md5-des', 'authPriv', (1,3,6,1,2,1), (1,3,6,1,2,1)) + +# Get default SNMP context this SNMP engine serves +snmpContext = context.SnmpContext(snmpEngine) + +# Register SNMP Applications at the SNMP engine for particular SNMP context +cmdrsp.GetCommandResponder(snmpEngine, snmpContext) +cmdrsp.SetCommandResponder(snmpEngine, snmpContext) +cmdrsp.NextCommandResponder(snmpEngine, snmpContext) +cmdrsp.BulkCommandResponder(snmpEngine, snmpContext) + +# Register an imaginary never-ending job to keep I/O dispatcher running forever +snmpEngine.transportDispatcher.jobStarted(1) + +# Run I/O dispatcher which would receive queries and send responses +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.observer.unregisterObserver() + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/agent/ntforg/inform-multiple-protocols.py b/examples/v3arch/asyncore/agent/ntforg/inform-multiple-protocols.py new file mode 100644 index 0000000..ab5f641 --- /dev/null +++ b/examples/v3arch/asyncore/agent/ntforg/inform-multiple-protocols.py @@ -0,0 +1,119 @@ +""" +Notification over multiple SNMP versions +++++++++++++++++++++++++++++++++++++++++ + +Send SNMP INFORM notifications to multiple Managers using different +security settings: + +* SNMPv2c +* with community name 'public' +* AND +* SNMPv3 +* with user 'usr-md5-none', auth: MD5, priv NONE +* over IPv4/UDP +* send INFORM notification +* to multiple Managers at 127.0.0.1:162, 127.0.0.2:162 +* with TRAP ID 'coldStart' specified as an OID +* include managed objects information: + 1.3.6.1.2.1.1.1.0 = 'Example Notificator' + +Functionally similar to: + +| $ snmpinform -v3 -l authPriv -u usr-md5-none -A authkey1 127.0.0.1 0 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.1.0 s 'Example notification' + +and + +| $ snmpinform -v2c -c public 127.0.0.2 0 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.1.0 s 'Example notification' + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import ntforg +from pysnmp.proto.api import v2c + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# SNMPv2c: + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public', transportTag='all-my-managers') + +# Specify security settings per SecurityName (SNMPv2c -> 1) +config.addTargetParams(snmpEngine, 'my-creds-1', 'my-area', 'noAuthNoPriv', 1) + +# SNMPv3: + +config.addV3User( + snmpEngine, 'usr-md5-none', + config.usmHMACMD5AuthProtocol, 'authkey1' +) +config.addTargetParams(snmpEngine, 'my-creds-2', 'usr-md5-none', 'authNoPriv') + +# Setup transport endpoint and bind it with security settings yielding +# a target name +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +# First target +config.addTargetAddr( + snmpEngine, 'my-nms-1', + udp.domainName, ('127.0.0.1', 162), + 'my-creds-1', + tagList='all-my-managers' +) +# Second target +config.addTargetAddr( + snmpEngine, 'my-nms-2', + udp.domainName, ('127.0.0.1', 162), + 'my-creds-2', + tagList='all-my-managers' +) + +# Specify what kind of notification should be sent (TRAP or INFORM), +# to what targets (chosen by tag) and what filter should apply to +# the set of targets (selected by tag) +config.addNotificationTarget( + snmpEngine, 'my-notification', 'my-filter', 'all-my-managers', 'inform' +) + +# Allow NOTIFY access to Agent's MIB by this SNMP model (2&3), securityLevel +# and SecurityName +config.addContext(snmpEngine, '') +config.addVacmUser(snmpEngine, 2, 'my-area', 'noAuthNoPriv', (), (), (1,3,6)) +config.addVacmUser(snmpEngine, 3, 'usr-md5-none', 'authNoPriv', (), (), (1,3,6)) + +# *** SNMP engine configuration is complete by this line *** + +# Create Notification Originator App instance. +ntfOrg = ntforg.NotificationOriginator() + +# Error/confirmation receiver +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBinds, cbCtx): + print('Notification %s, status - %s' % ( + sendRequestHandle, errorIndication and errorIndication or 'delivered' + ) + ) + +# Build and submit notification message to dispatcher +sendRequestHandle = ntfOrg.sendVarBinds( + snmpEngine, + 'my-notification', # notification targets + None, '', # contextEngineId, contextName + # var-binds + [ + # SNMPv2-SMI::snmpTrapOID.0 = SNMPv2-MIB::coldStart + ((1,3,6,1,6,3,1,1,4,1,0), v2c.ObjectIdentifier((1,3,6,1,6,3,1,1,5,1))), + # additional var-binds: ( (oid, value), ... ) + ((1,3,6,1,2,1,1,1,0), v2c.OctetString('Example Notificator')) + ], + cbFun +) + +print('Notifications %s are scheduled to be sent' % sendRequestHandle) + +# Run I/O dispatcher which would send pending message and process response +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/agent/ntforg/inform-v2c.py b/examples/v3arch/asyncore/agent/ntforg/inform-v2c.py new file mode 100644 index 0000000..026d36f --- /dev/null +++ b/examples/v3arch/asyncore/agent/ntforg/inform-v2c.py @@ -0,0 +1,95 @@ +""" +INFORM notification ++++++++++++++++++++ + +Send SNMP INFORM notification using the following options: + +* SNMPv2c +* with community name 'public' +* over IPv4/UDP +* send INFORM notification +* to a Manager at 127.0.0.1:162 +* with TRAP ID 'coldStart' specified as an OID +* include managed objects information: + 1.3.6.1.2.1.1.1.0 = 'Example Notificator' + 1.3.6.1.2.1.1.5.0 = 'Notificator Example' + +Functionally similar to: + +| $ snmpinform -v2c -c public demo.snmplabs.com 12345 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.1.0 s 'Example Notificator' 1.3.6.1.2.1.1.5.0 s 'Notificator Example' + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import ntforg +from pysnmp.proto.api import v2c + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# SecurityName <-> CommunityName mapping (+ transport binding) +config.addV1System(snmpEngine, 'my-area', 'public', + transportTag='all-my-managers') + +# Specify security settings per SecurityName (SNMPv2c -> 1) +config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 1) + +# Setup transport endpoint and bind it with security settings yielding +# a target name +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-nms', + udp.domainName, ('195.218.195.228', 162), + 'my-creds', + tagList='all-my-managers' +) + +# Specify what kind of notification should be sent (TRAP or INFORM), +# to what targets (chosen by tag) and what filter should apply to +# the set of targets (selected by tag) +config.addNotificationTarget( + snmpEngine, 'my-notification', 'my-filter', 'all-my-managers', 'inform' +) + +# Allow NOTIFY access to Agent's MIB by this SNMP model (2), securityLevel +# and SecurityName +config.addContext(snmpEngine, '') +config.addVacmUser(snmpEngine, 2, 'my-area', 'noAuthNoPriv', (), (), (1,3,6)) + +# *** SNMP engine configuration is complete by this line *** + +# Create Notification Originator App instance. +ntfOrg = ntforg.NotificationOriginator() + +# Error/confirmation receiver +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBinds, cbCtx): + print('Notification %s, status - %s' % ( + sendRequestHandle, errorIndication and errorIndication or 'delivered' + ) + ) + +# Build and submit notification message to dispatcher +sendRequestHandle = ntfOrg.sendVarBinds( + snmpEngine, + 'my-notification', # notification targets + None, '', # contextEngineId, contextName + # var-binds + [ + # SNMPv2-SMI::snmpTrapOID.0 = SNMPv2-MIB::coldStart + ((1,3,6,1,6,3,1,1,4,1,0), v2c.ObjectIdentifier((1,3,6,1,6,3,1,1,5,1))), + # additional var-binds: ( (oid, value), ... ) + ((1,3,6,1,2,1,1,1,0), v2c.OctetString('Example Notificator')), + ((1,3,6,1,2,1,1,5,0), v2c.OctetString('Notificator Example')) + ], + cbFun +) + +print('Notification %s scheduled to be sent' % sendRequestHandle) + +# Run I/O dispatcher which would send pending message and process response +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/agent/ntforg/inform-v3.py b/examples/v3arch/asyncore/agent/ntforg/inform-v3.py new file mode 100644 index 0000000..116d679 --- /dev/null +++ b/examples/v3arch/asyncore/agent/ntforg/inform-v3.py @@ -0,0 +1,88 @@ +""" +SNMPv3 INFORM, auth: MD5, privacy: none ++++++++++++++++++++++++++++++++++++++++ + +Send SNMP INFORM notification using the following options: + +* SNMPv3 +* with user 'usr-md5-none', auth: MD5, priv NONE +* over IPv4/UDP +* to a Manager at 127.0.0.1:162 +* send INFORM notification +* with TRAP ID 'warmStart' specified as an OID +* include managed object information 1.3.6.1.2.1.1.5.0 = 'system name' + +Functionally similar to: + +| $ snmpinform -v3 -l authNoPriv -u usr-md5-none -A authkey1 demo.snmplabs.com 0 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.5.0 = 'system name' + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import ntforg +from pysnmp.proto.api import v2c + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# Add USM user +config.addV3User( + snmpEngine, 'usr-md5-none', + config.usmHMACMD5AuthProtocol, 'authkey1' +) +config.addTargetParams(snmpEngine, 'my-creds', 'usr-md5-none', 'authNoPriv') + +# Setup transport endpoint and bind it with security settings yielding +# a target name +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-nms', + udp.domainName, ('127.0.0.1', 162), + 'my-creds', + tagList='all-my-managers' +) + +# Specify what kind of notification should be sent (TRAP or INFORM), +# to what targets (chosen by tag) and what filter should apply to +# the set of targets (selected by tag) +config.addNotificationTarget( + snmpEngine, 'my-notification', 'my-filter', 'all-my-managers', 'inform' +) + +# Allow NOTIFY access to Agent's MIB by this SNMP model (3), securityLevel +# and SecurityName +config.addContext(snmpEngine, '') +config.addVacmUser(snmpEngine, 3, 'usr-md5-none', 'authNoPriv', (), (), (1,3,6)) + +# *** SNMP engine configuration is complete by this line *** + +# Create Notification Originator App instance. +ntfOrg = ntforg.NotificationOriginator() + +# Error/confirmation receiver +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBinds, cbCtx): + print('Notification %s, status - %s' % ( + sendRequestHandle, errorIndication and errorIndication or 'delivered' + ) + ) + +# Build and submit notification message to dispatcher +sendRequestHandle = ntfOrg.sendVarBinds( + snmpEngine, + 'my-notification', # notification targets + None, '', # contextEngineId, contextName + # var-binds: SNMPv2-MIB::coldStart, ... + [ ((1,3,6,1,6,3,1,1,5,1), v2c.ObjectIdentifier((1,3,6,1,6,3,1,1,5,1))), + ((1,3,6,1,2,1,1,5,0), v2c.OctetString('system name')) ], + cbFun +) + +print('Notification %s scheduled to be sent' % sendRequestHandle) + +# Run I/O dispatcher which would send pending message and process response +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/agent/ntforg/trap-v1-from-specific-address.py b/examples/v3arch/asyncore/agent/ntforg/trap-v1-from-specific-address.py new file mode 100644 index 0000000..c7dfedb --- /dev/null +++ b/examples/v3arch/asyncore/agent/ntforg/trap-v1-from-specific-address.py @@ -0,0 +1,82 @@ +""" +Send packet from specific network interface/port +++++++++++++++++++++++++++++++++++++++++++++++++ + +Send SNMP notification using the following options: + +* SNMPv1 +* with community name 'public' +* over IPv4/UDP +* to a Manager at 127.0.0.1 UDP port 162 +* from local address 127.0.0.1, UDP port 61024 +* send TRAP notification +* with TRAP ID 'coldStart' specified as an OID + +Functionally similar to: + +| $ snmptrap -v1 -c public 127.0.0.1 1.3.6.1.6.3.1.1.5.1 0.0.0.0 1 0 0 + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import ntforg +from pysnmp.proto.api import v2c + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public', + transportTag='all-my-managers') + +# Specify security settings per SecurityName (SNMPv1 -> 0) +config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 0) + +# Setup transport endpoint and bind it with security settings yielding +# a target name. Pay attention to the openClientMode() parameter -- it's +# used to originate packets from particular local IP:port +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode(iface=('127.0.0.1', 61024)) +) +config.addTargetAddr( + snmpEngine, 'my-nms', + udp.domainName, ('127.0.0.1', 162), + 'my-creds', + tagList='all-my-managers' +) + +# Specify what kind of notification should be sent (TRAP or INFORM), +# to what targets (chosen by tag) and what filter should apply to +# the set of targets (selected by tag) +config.addNotificationTarget( + snmpEngine, 'my-notification', 'my-filter', 'all-my-managers', 'trap' +) + +# Allow NOTIFY access to Agent's MIB by this SNMP model (1), securityLevel +# and SecurityName +config.addContext(snmpEngine, '') +config.addVacmUser(snmpEngine, 1, 'my-area', 'noAuthNoPriv', (), (), (1,3,6)) + +# *** SNMP engine configuration is complete by this line *** + +# Create Notification Originator App instance. +ntfOrg = ntforg.NotificationOriginator() + +# Build and submit notification message to dispatcher +ntfOrg.sendVarBinds( + snmpEngine, + 'my-notification', # notification targets + None, '', # contextEngineId, contextName + # var-binds + [ + # SNMPv2-SMI::snmpTrapOID.0 = SNMPv2-MIB::coldStart + ((1,3,6,1,6,3,1,1,4,1,0), v2c.ObjectIdentifier((1,3,6,1,6,3,1,1,5,1))) + ] +) + +print('Notification is scheduled to be sent') + +# Run I/O dispatcher which would send pending message and stop +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/agent/ntforg/trap-v1.py b/examples/v3arch/asyncore/agent/ntforg/trap-v1.py new file mode 100644 index 0000000..226788a --- /dev/null +++ b/examples/v3arch/asyncore/agent/ntforg/trap-v1.py @@ -0,0 +1,99 @@ +""" +SNMPv1 TRAP ++++++++++++ + +Send SNMP notification using the following options: + +* SNMPv1 +* with community name 'public' +* over IPv4/UDP +* to a Manager at 127.0.0.1:162 +* send TRAP notification +* with TRAP ID 'coldStart' specified as an OID +* include managed objects information: +* overriding Uptime value with 12345 +* overriding Agent Address with '127.0.0.1' +* overriding Enterprise OID with 1.3.6.1.4.1.20408.4.1.1.2 +* include managed object information '1.3.6.1.2.1.1.1.0' = 'my system' + +Functionally similar to: + +| $ snmptrap -v1 -c public 127.0.0.1 1.3.6.1.4.1.20408.4.1.1.2 127.0.0.1 6 432 12345 1.3.6.1.2.1.1.1.0 s 'my system' + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import ntforg +from pysnmp.proto.api import v2c + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public', transportTag='all-my-managers') + +# Specify security settings per SecurityName (SNMPv1 -> 0) +config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 0) + +# Setup transport endpoint and bind it with security settings yielding +# a target name +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-nms', + udp.domainName, ('127.0.0.1', 162), + 'my-creds', + tagList='all-my-managers' +) + +# Specify what kind of notification should be sent (TRAP or INFORM), +# to what targets (chosen by tag) and what filter should apply to +# the set of targets (selected by tag) +config.addNotificationTarget( + snmpEngine, 'my-notification', 'my-filter', 'all-my-managers', 'trap' +) + +# Allow NOTIFY access to Agent's MIB by this SNMP model (1), securityLevel +# and SecurityName +config.addContext(snmpEngine, '') +config.addVacmUser(snmpEngine, 1, 'my-area', 'noAuthNoPriv', (), (), (1,3,6)) + +# *** SNMP engine configuration is complete by this line *** + +# Create Notification Originator App instance. +ntfOrg = ntforg.NotificationOriginator() + +# Build and submit notification message to dispatcher +ntfOrg.sendVarBinds( + snmpEngine, + # Notification targets + 'my-notification', # notification targets + None, '', # contextEngineId, contextName + # var-binds + [ + # Uptime value with 12345 + (v2c.ObjectIdentifier('1.3.6.1.2.1.1.3.0'), + v2c.TimeTicks(12345)), + # trap OID: Generic Trap #6 (enterpriseSpecific) + # and Specific Trap 432 + (v2c.ObjectIdentifier('1.3.6.1.6.3.1.1.5.1'), + v2c.ObjectIdentifier('1.3.6.1.4.1.20408.4.1.1.2.0.432')), + # Agent Address with '127.0.0.1' + (v2c.ObjectIdentifier('1.3.6.1.6.3.18.1.3.0'), + v2c.IpAddress('127.0.0.1')), + # Enterprise OID with 1.3.6.1.4.1.20408.4.1.1.2 + (v2c.ObjectIdentifier('1.3.6.1.6.3.1.1.4.3.0'), + v2c.ObjectIdentifier('1.3.6.1.4.1.20408.4.1.1.2')), + # managed object '1.3.6.1.2.1.1.1.0' = 'my system' + (v2c.ObjectIdentifier('1.3.6.1.2.1.1.1.0'), + v2c.OctetString('my system')) + ] +) + +print('Notification is scheduled to be sent') + +# Run I/O dispatcher which would send pending message and stop +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/agent/ntforg/trap-v2c-custom-pdu.py b/examples/v3arch/asyncore/agent/ntforg/trap-v2c-custom-pdu.py new file mode 100644 index 0000000..1051754 --- /dev/null +++ b/examples/v3arch/asyncore/agent/ntforg/trap-v2c-custom-pdu.py @@ -0,0 +1,90 @@ +""" +Send crafted TRAP PDU ++++++++++++++++++++++ + +Initialize TRAP PDU and pass it over to unified SNMPv3 message processing +framework for further treatment. + +* SNMPv2c +* with community name 'public' +* over IPv4/UDP +* send TRAP notification +* initialize TRAP PDU with the following var-binds: + 1.3.6.1.2.1.1.3.0 = 123 + 1.3.6.1.6.3.1.1.4.1.0 = 1.3.6.1.6.3.1.1.5.1 + +Functionally similar to: + +| $ snmptrap -v1 -c public 127.0.0.1 1.3.6.1.6.3.1.1.5.1 0.0.0.0 1 0 123 + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import ntforg +from pysnmp.proto.api import v2c + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public') + +# Specify security settings per SecurityName (SNMPv2c -> 1) +config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 1) + +# Setup transport endpoint and bind it with security settings yielding +# a target name +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) + +# Create named target +config.addTargetAddr( + snmpEngine, 'my-nms', + udp.domainName, ('127.0.0.1', 162), + 'my-creds' +) + +# *** SNMP engine configuration is complete by this line *** + +# Create SNMP v2c TRAP PDU with defaults +trapPDU = v2c.TrapPDU() +v2c.apiTrapPDU.setDefaults(trapPDU) + +# Set custom var-binds to TRAP PDU +v2c.apiTrapPDU.setVarBinds( + trapPDU, [ + # sysUpTime + ( v2c.ObjectIdentifier('1.3.6.1.2.1.1.3.0'), v2c.TimeTicks(123) ), + # snmpTrapPDU + ( (1,3,6,1,6,3,1,1,4,1,0), v2c.ObjectIdentifier((1,3,6,1,6,3,1,1,5,1)) ) + ] +) + +# Create Notification Originator App instance. +ntfOrg = ntforg.NotificationOriginator() + +# Error/confirmation receiver +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBinds, cbCtx): + print('Notification %s, status - %s' % ( + sendRequestHandle, errorIndication and errorIndication or 'delivered' + ) + ) + +# Build and submit notification message to dispatcher +ntfOrg.sendPdu( + snmpEngine, + # Notification targets + 'my-nms', # target address + None, '', # contextEngineId, contextName + trapPDU, + cbFun +) + +print('Notification is scheduled to be sent') + +# Run I/O dispatcher which would send pending message and process response +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/agent/ntforg/trap-v2c-multiple-addresses.py b/examples/v3arch/asyncore/agent/ntforg/trap-v2c-multiple-addresses.py new file mode 100644 index 0000000..ce82f60 --- /dev/null +++ b/examples/v3arch/asyncore/agent/ntforg/trap-v2c-multiple-addresses.py @@ -0,0 +1,110 @@ +""" +Notification to multiple addresses +++++++++++++++++++++++++++++++++++ + +Send SNMP TRAP notifications to multiple Managers using different +security settings: + +* SNMPv2c +* with community name 'public' +* over IPv4/UDP +* send TRAP notification +* to multiple Managers at 127.0.0.1:162, 127.0.0.2:162 +* with TRAP ID 'coldStart' specified as an OID +* include managed objects information: + 1.3.6.1.2.1.1.1.0 = 'Example Notificator' + 1.3.6.1.2.1.1.5.0 = 'Notificator Example' + +Functionally similar to: + +| $ snmptrap -v2c -c public 127.0.0.1 0 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.1.0 s 'Example notification' 1.3.6.1.2.1.1.5.0 s 'Notificator Example' + +and + +| $ snmptrap -v2c -c public 127.0.0.2 0 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.1.0 s 'Example notification' 1.3.6.1.2.1.1.5.0 s 'Notificator Example' + +and + +| $ snmptrap -v2c -c public 127.0.0.3 0 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.1.0 s 'Example notification' 1.3.6.1.2.1.1.5.0 s 'Notificator Example' + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import ntforg +from pysnmp.proto.api import v2c + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public', transportTag='all-my-managers') + +# Specify security settings per SecurityName (SNMPv2c -> 1) +config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 1) + +# Setup transport endpoint and bind it with security settings yielding +# a target name +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +# First target +config.addTargetAddr( + snmpEngine, 'my-nms-1', + udp.domainName, ('127.0.0.1', 162), + 'my-creds', + tagList='all-my-managers' +) +# Second target +config.addTargetAddr( + snmpEngine, 'my-nms-2', + udp.domainName, ('127.0.0.2', 162), + 'my-creds', + tagList='all-my-managers' +) +# Third target +config.addTargetAddr( + snmpEngine, 'my-nms-3', + udp.domainName, ('127.0.0.3', 162), + 'my-creds', + tagList='all-my-managers' +) + +# Specify what kind of notification should be sent (TRAP or INFORM), +# to what targets (chosen by tag) and what filter should apply to +# the set of targets (selected by tag) +config.addNotificationTarget( + snmpEngine, 'my-notification', 'my-filter', 'all-my-managers', 'trap' +) + +# Allow NOTIFY access to Agent's MIB by this SNMP model (2), securityLevel +# and SecurityName +config.addContext(snmpEngine, '') +config.addVacmUser(snmpEngine, 2, 'my-area', 'noAuthNoPriv', (), (), (1,3,6)) + +# *** SNMP engine configuration is complete by this line *** + +# Create Notification Originator App instance. +ntfOrg = ntforg.NotificationOriginator() + +# Build and submit notification message to dispatcher +ntfOrg.sendVarBinds( + snmpEngine, + # Notification targets + 'my-notification', # notification targets + None, '', # contextEngineId, contextName + # var-binds + [ + # SNMPv2-SMI::snmpTrapOID.0 = SNMPv2-MIB::coldStart + ((1,3,6,1,6,3,1,1,4,1,0), v2c.ObjectIdentifier((1,3,6,1,6,3,1,1,5,1))), + # additional var-binds: ( (oid, value), ... ) + ((1,3,6,1,2,1,1,1,0), v2c.OctetString('Example Notificator')), + ((1,3,6,1,2,1,1,5,0), v2c.OctetString('Notificator Example')) + ] +) + +print('Notifications are scheduled to be sent') + +# Run I/O dispatcher which would send pending message and process response +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/agent/ntforg/trap-v2c-multiple-transports.py b/examples/v3arch/asyncore/agent/ntforg/trap-v2c-multiple-transports.py new file mode 100644 index 0000000..1c93e62 --- /dev/null +++ b/examples/v3arch/asyncore/agent/ntforg/trap-v2c-multiple-transports.py @@ -0,0 +1,106 @@ +""" +Notification over multiple network protocols +++++++++++++++++++++++++++++++++++++++++++++ + +Send SNMP INFORM notifications to multiple Managers over different +network protocols: + +* SNMPv2c +* with community name 'public' +* over IPv4/UDP and UDP/IPv6 +* send TRAP notification +* to two Managers through different network transports +* with TRAP ID 'coldStart' specified as an OID +* include managed objects information: + 1.3.6.1.2.1.1.1.0 = 'Example Notificator' + 1.3.6.1.2.1.1.5.0 = 'Notificator Example' + +Functionally similar to: + +| $ snmptrap -v2c -c public udp:127.0.0.1 0 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.1.0 s 'Example notification' 1.3.6.1.2.1.1.5.0 s 'Notificator Example' + +and + +| $ snmptrap -v2c -c public udp6:[::1] 0 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.1.0 s 'Example notification' 1.3.6.1.2.1.1.5.0 s 'Notificator Example' + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp, udp6 +from pysnmp.entity.rfc3413 import ntforg +from pysnmp.proto.api import v2c + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public', transportTag='all-my-managers') + +# Specify security settings per SecurityName (SNMPv2c -> 1) +config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 1) + +# Setup transport endpoints and bind it with security settings yielding +# a target name: + +# UDP/IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-nms-1', + udp.domainName, ('127.0.0.1', 162), + 'my-creds', + tagList='all-my-managers' +) + +# UDP/IPv6 +config.addTransport( + snmpEngine, + udp6.domainName, + udp6.Udp6SocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-nms-2', + udp6.domainName, ('::1', 162), + 'my-creds', + tagList='all-my-managers' +) + +# Specify what kind of notification should be sent (TRAP or INFORM), +# to what targets (chosen by tag) and what filter should apply to +# the set of targets (selected by tag) +config.addNotificationTarget( + snmpEngine, 'my-notification', 'my-filter', 'all-my-managers', 'trap' +) + +# Allow NOTIFY access to Agent's MIB by this SNMP model (2), securityLevel +# and SecurityName +config.addContext(snmpEngine, '') +config.addVacmUser(snmpEngine, 2, 'my-area', 'noAuthNoPriv', (), (), (1,3,6)) + +# *** SNMP engine configuration is complete by this line *** + +# Create Notification Originator App instance. +ntfOrg = ntforg.NotificationOriginator() + +# Build and submit notification message to dispatcher +ntfOrg.sendVarBinds( + snmpEngine, + # Notification targets + 'my-notification', # notification targets + None, '', # contextEngineId, contextName + # var-binds + [ + # SNMPv2-SMI::snmpTrapOID.0 = SNMPv2-MIB::coldStart + ((1,3,6,1,6,3,1,1,4,1,0), v2c.ObjectIdentifier((1,3,6,1,6,3,1,1,5,1))), + # additional var-binds: ( (oid, value), ... ) + ((1,3,6,1,2,1,1,1,0), v2c.OctetString('Example Notificator')), + ((1,3,6,1,2,1,1,5,0), v2c.OctetString('Notificator Example')) + ] +) + +print('Notification is scheduled to be sent') + +# Run I/O dispatcher which would send pending message and process response +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/agent/ntforg/trap-v2c-with-objects.py b/examples/v3arch/asyncore/agent/ntforg/trap-v2c-with-objects.py new file mode 100644 index 0000000..b72c5a7 --- /dev/null +++ b/examples/v3arch/asyncore/agent/ntforg/trap-v2c-with-objects.py @@ -0,0 +1,108 @@ +""" +Sending notification with OBJECT's +++++++++++++++++++++++++++++++++++ + +Send SNMP TRAP notification using the following options: + +* SNMPv2c +* with community name 'public' +* over IPv4/UDP +* send TRAP notification +* to a Manager at 127.0.0.1:162 +* with TRAP ID IF-MIB::ifLink as MIB symbol + +The IF-MIB::ifLink NOTIFICATION-TYPE implies including four other +var-binds into the notification message describing the incident +occurred. These var-binds are: +IF-MIB::ifIndex."x" +IF-MIB::ifAdminStatus."x" +IF-MIB::ifOperStatus."x" +IF-MIB::ifDescr."x" + +Where "x" is MIB table index (instance index). + +Functionally similar to: + +| $ snmptrap -v2c -c public 127.0.0.1 0 1.3.6.1.6.3.1.1.5.3 IF-MIB::ifIndex."1" IF-MIB::ifAdminStatus."1" IF-MIB::ifOperStatus."1" IF-MIB::ifDescr."1" + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import ntforg +from pysnmp.smi import rfc1902, view + +# +# Here we fill in some values for Managed Objects Instances (invoked +# later while building TRAP message) by NOTIFICATION-TYPE macro evaluation. +# In real Agent app, these values should already be initialized during +# Agent runtime. +# +instanceIndex = (1,) +objects = { + ('IF-MIB', 'ifIndex'): instanceIndex[0], + ('IF-MIB', 'ifAdminStatus'): 'up', + ('IF-MIB', 'ifOperStatus'): 'down', + ('IF-MIB', 'ifDescr'): 'eth0' +} + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# MIB view controller is used for MIB lookup purposes +mibViewController = view.MibViewController(snmpEngine.getMibBuilder()) + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public', transportTag='all-my-managers') + +# Specify security settings per SecurityName (SNMPv2c -> 1) +config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 1) + +# Setup transport endpoints and bind it with security settings yielding +# a target name: + +# UDP/IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-nms-1', + udp.domainName, ('127.0.0.1', 162), + 'my-creds', + tagList='all-my-managers' +) + +# Specify what kind of notification should be sent (TRAP or INFORM), +# to what targets (chosen by tag) and what filter should apply to +# the set of targets (selected by tag) +config.addNotificationTarget( + snmpEngine, 'my-notification', 'my-filter', 'all-my-managers', 'trap' +) + +# Allow NOTIFY access to Agent's MIB by this SNMP model (2), securityLevel +# and SecurityName +config.addContext(snmpEngine, '') +config.addVacmUser(snmpEngine, 2, 'my-area', 'noAuthNoPriv', (), (), (1,3,6)) + +# *** SNMP engine configuration is complete by this line *** + +# Create Notification Originator App instance. +ntfOrg = ntforg.NotificationOriginator() + +# Build and submit notification message to dispatcher +ntfOrg.sendVarBinds( + snmpEngine, + 'my-notification', # notification targets + None, '', # contextEngineId, contextName + rfc1902.NotificationType( + rfc1902.ObjectIdentity('IF-MIB', 'linkUp'), + instanceIndex=instanceIndex, + objects=objects + ).resolveWithMib(mibViewController) +) + +print('Notification is scheduled to be sent') + +# Run I/O dispatcher which would send pending message and process response +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/agent/ntforg/trap-v2c.py b/examples/v3arch/asyncore/agent/ntforg/trap-v2c.py new file mode 100644 index 0000000..2a926d8 --- /dev/null +++ b/examples/v3arch/asyncore/agent/ntforg/trap-v2c.py @@ -0,0 +1,95 @@ +""" +SNMPv2c TRAP +++++++++++++ + +Send SNMP TRAP notification using the following options: + +* SNMPv2c +* with community name 'public' +* over IPv4/UDP +* send TRAP notification +* to a Manager at 127.0.0.1:162 +* with TRAP ID 'coldStart' specified as an OID +* include managed objects information: + 1.3.6.1.2.1.1.1.0 = 'Example Notificator' + 1.3.6.1.2.1.1.5.0 = 'Notificator Example' + +Functionally similar to: + +| $ snmptrap -v2c -c public 127.0.0.1 12345 1.3.6.1.4.1.20408.4.1.1.2 + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import ntforg +from pysnmp.proto.api import v2c + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public', transportTag='all-my-managers') + +# Specify security settings per SecurityName (SNMPv2c -> 1) +config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 1) + +# Setup transport endpoint and bind it with security settings yielding +# a target name +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-nms', + udp.domainName, ('127.0.0.1', 162), + 'my-creds', + tagList='all-my-managers' +) + +# Specify what kind of notification should be sent (TRAP or INFORM), +# to what targets (chosen by tag) and what filter should apply to +# the set of targets (selected by tag) +config.addNotificationTarget( + snmpEngine, 'my-notification', 'my-filter', 'all-my-managers', 'trap' +) + +# Allow NOTIFY access to Agent's MIB by this SNMP model (2), securityLevel +# and SecurityName +config.addContext(snmpEngine, '') +config.addVacmUser(snmpEngine, 2, 'my-area', 'noAuthNoPriv', (), (), (1,3,6)) + +# *** SNMP engine configuration is complete by this line *** + +# Create Notification Originator App instance. +ntfOrg = ntforg.NotificationOriginator() + +# Error/confirmation receiver +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBinds, cbCtx): + print('Notification %s, status - %s' % ( + sendRequestHandle, errorIndication and errorIndication or 'delivered' + ) + ) + +# Build and submit notification message to dispatcher +sendRequestHandle = ntfOrg.sendVarBinds( + snmpEngine, + # Notification targets + 'my-notification', # notification targets + None, '', # contextEngineId, contextName + # var-binds + [ + # SNMPv2-SMI::snmpTrapOID.0 = SNMPv2-MIB::coldStart + ((1,3,6,1,6,3,1,1,4,1,0), v2c.ObjectIdentifier((1,3,6,1,6,3,1,1,5,1))), + # additional var-binds: ( (oid, value), ... ) + ((1,3,6,1,2,1,1,1,0), v2c.OctetString('Example Notificator')), + ((1,3,6,1,2,1,1,5,0), v2c.OctetString('Notificator Example')) + ], + cbFun +) + +print('Notification %s is scheduled to be sent' % sendRequestHandle) + +# Run I/O dispatcher which would send pending message and process response +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/agent/ntforg/trap-v3.py b/examples/v3arch/asyncore/agent/ntforg/trap-v3.py new file mode 100644 index 0000000..d43fe27 --- /dev/null +++ b/examples/v3arch/asyncore/agent/ntforg/trap-v3.py @@ -0,0 +1,90 @@ +""" +SNMPv3 TRAP, auth: MD5, privacy: DES +++++++++++++++++++++++++++++++++++++ + +Send SNMP TRAP notification using the following options: + +* SNMPv3 +* with user 'usr-md5-des', auth: MD5, priv DES +* over IPv4/UDP +* send TRAP notification +* to a Manager at 127.0.0.1:162 +* with TRAP ID 'warmStart' specified as an OID +* include managed object information 1.3.6.1.2.1.1.5.0 = 'system name' + +Functionally similar to: + +| $ snmptrap -v3 -l authPriv -u usr-md5-des -A authkey1 -X privkey1 -e 800000000 +1020304 0 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.5.0 s 'my system' + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import ntforg +from pysnmp.proto.api import v2c + +# Create SNMP engine instance with specific (and locally unique) +# SnmpEngineId -- it must also be known to the receiving party +# and configured at its VACM users table. +snmpEngine = engine.SnmpEngine( + snmpEngineID=v2c.OctetString(hexValue='8000000001020304') +) + +# Add USM user +config.addV3User( + snmpEngine, 'usr-md5-des', + config.usmHMACMD5AuthProtocol, 'authkey1', + config.usmDESPrivProtocol, 'privkey1' +) +config.addTargetParams(snmpEngine, 'my-creds', 'usr-md5-des', 'authPriv') + +# Setup transport endpoint and bind it with security settings yielding +# a target name +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-nms', + udp.domainName, ('127.0.0.1', 162), + 'my-creds', + tagList='all-my-managers' +) + +# Specify what kind of notification should be sent (TRAP or INFORM), +# to what targets (chosen by tag) and what filter should apply to +# the set of targets (selected by tag) +config.addNotificationTarget( + snmpEngine, 'my-notification', 'my-filter', 'all-my-managers', 'trap' +) + +# Allow NOTIFY access to Agent's MIB by this SNMP model (3), securityLevel +# and SecurityName +config.addContext(snmpEngine, '') +config.addVacmUser(snmpEngine, 3, 'usr-md5-des', 'authPriv', (), (), (1,3,6)) + +# *** SNMP engine configuration is complete by this line *** + +# Create Notification Originator App instance. +ntfOrg = ntforg.NotificationOriginator() + +# Build and submit notification message to dispatcher +ntfOrg.sendVarBinds( + snmpEngine, + # Notification targets + 'my-notification', # notification targets + None, '', # contextEngineId, contextName + # var-binds + [ + # SNMPv2-SMI::snmpTrapOID.0 = SNMPv2-MIB::coldStart + ((1,3,6,1,6,3,1,1,4,1,0), v2c.ObjectIdentifier((1,3,6,1,6,3,1,1,5,1))), + # additional var-binds: ( (oid, value), ... ) + ((1,3,6,1,2,1,1,5,0), v2c.OctetString('Notificator Example')) + ] +) + +print('Notification is scheduled to be sent') + +# Run I/O dispatcher which would send pending message and process response +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/manager/cmdgen/get-v1.py b/examples/v3arch/asyncore/manager/cmdgen/get-v1.py new file mode 100644 index 0000000..234d414 --- /dev/null +++ b/examples/v3arch/asyncore/manager/cmdgen/get-v1.py @@ -0,0 +1,76 @@ +""" +SNMPv1 +++++++ + +* with SNMPv1, community 'public' +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for an OID in tuple form + +This script performs similar to the following Net-SNMP command: + +| $ snmpget -v1 -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1.1.0 + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import cmdgen + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# +# SNMPv1 setup +# + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public') + +# Specify security settings per SecurityName (SNMPv1 - 0, SNMPv2c - 1) +config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 0) + +# +# Setup transport endpoint and bind it with security settings yielding +# a target name +# + +# UDP/IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-router', + udp.domainName, ('195.218.195.228', 161), + 'my-creds' +) + +# Error/response receiver +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBinds, cbCtx): + if errorIndication: + print(errorIndication) + # SNMPv1 response may contain noSuchName error *and* SNMPv2c exception, + # so we ignore noSuchName error here + elif errorStatus and errorStatus != 2: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for oid, val in varBinds: + print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + +# Prepare and send a request message +cmdgen.GetCommandGenerator().sendVarBinds( + snmpEngine, + 'my-router', + None, '', # contextEngineId, contextName + [ ((1,3,6,1,2,1,1,1,0), None) ], + cbFun +) + +# Run I/O dispatcher which would send pending queries and process responses +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/manager/cmdgen/get-v2c-custom-timeout.py b/examples/v3arch/asyncore/manager/cmdgen/get-v2c-custom-timeout.py new file mode 100644 index 0000000..b91a4b6 --- /dev/null +++ b/examples/v3arch/asyncore/manager/cmdgen/get-v2c-custom-timeout.py @@ -0,0 +1,79 @@ +""" +SNMPv2c, custom timeout ++++++++++++++++++++++++ + +Send a SNMP GET request: + +* with SNMPv2c, community 'public' +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* wait 3 seconds for response, retry 5 times (plus one initial attempt) +* for an OID in tuple form + +This script performs similar to the following Net-SNMP command: + +| $ snmpget -v2c -c public -ObentU -r 5 -t 1 195.218.195.228 1.3.6.1.2.1.1.1.0 + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import cmdgen + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# +# SNMPv2c setup +# + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public') + +# Specify security settings per SecurityName (SNMPv1 - 0, SNMPv2c - 1) +config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 1) + +# +# Setup transport endpoint and bind it with security settings yielding +# a target name +# + +# UDP/IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-router', + udp.domainName, ('195.218.195.228', 161), + 'my-creds', + timeout=300, # in 1/100 sec + retryCount=5 +) + +# Error/response receiver +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBinds, cbCtx): + if errorIndication: + print(errorIndication) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for oid, val in varBinds: + print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + +# Prepare and send a request message +cmdgen.GetCommandGenerator().sendVarBinds( + snmpEngine, + 'my-router', + None, '', # contextEngineId, contextName + [ ((1,3,6,1,2,1,1,1,0), None) ], + cbFun +) + +# Run I/O dispatcher which would send pending queries and process responses +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/manager/cmdgen/get-v2c-spoof-source-address.py b/examples/v3arch/asyncore/manager/cmdgen/get-v2c-spoof-source-address.py new file mode 100644 index 0000000..998d40f --- /dev/null +++ b/examples/v3arch/asyncore/manager/cmdgen/get-v2c-spoof-source-address.py @@ -0,0 +1,100 @@ +""" +Spoof source address +++++++++++++++++++++ + +Send a SNMP GET request +* with SNMPv2c, community 'public' +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* from a non-local, spoofed IP 1.2.3.4 (root and Python 3.3+ required) +* for an OID in tuple form + +This script performs similar to the following Net-SNMP command: + +| $ snmpget -v2c -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1.1.0 + +But unlike the above command, this script issues SNMP request from +a non-default, non-local IP address. + +It is indeed possible to originate SNMP traffic from any valid local +IP addresses. It could be a secondary IP interface, for instance. +Superuser privileges are only required to send spoofed packets. +Alternatively, sending from local interface could also be achieved by +binding to it (via openClientMode() parameter). + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import cmdgen + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# +# SNMPv1 setup +# + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public') + +# Specify security settings per SecurityName (SNMPv1 - 0, SNMPv2c - 1) +config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 0) + +# +# Setup transport endpoint and bind it with security settings yielding +# a target name +# + +# Initialize asyncore-based UDP/IPv4 transport +udpSocketTransport = udp.UdpSocketTransport().openClientMode() + +# Use sendmsg()/recvmsg() for socket communication (required for +# IP source spoofing functionality) +udpSocketTransport.enablePktInfo() + +# Enable IP source spoofing (requires root privileges) +udpSocketTransport.enableTransparent() + +# Register this transport at SNMP Engine +config.addTransport( + snmpEngine, + udp.domainName, + udpSocketTransport +) + +# Configure destination IPv4 address as well as source IPv4 address +config.addTargetAddr( + snmpEngine, 'my-router', + udp.domainName, ('195.218.195.228', 161), + 'my-creds', + sourceAddress=('1.2.3.4', 0) +) + +# Error/response receiver +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBinds, cbCtx): + if errorIndication: + print(errorIndication) + # SNMPv1 response may contain noSuchName error *and* SNMPv2c exception, + # so we ignore noSuchName error here + elif errorStatus and errorStatus != 2: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for oid, val in varBinds: + print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + +# Prepare and send a request message +cmdgen.GetCommandGenerator().sendVarBinds( + snmpEngine, + 'my-router', + None, '', # contextEngineId, contextName + [ ((1,3,6,1,2,1,1,1,0), None) ], + cbFun +) + +# Run I/O dispatcher which would send pending queries and process responses +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/manager/cmdgen/get-v3-custom-context.py b/examples/v3arch/asyncore/manager/cmdgen/get-v3-custom-context.py new file mode 100644 index 0000000..e61e538 --- /dev/null +++ b/examples/v3arch/asyncore/manager/cmdgen/get-v3-custom-context.py @@ -0,0 +1,84 @@ +""" +Custom ContextEngineId and ContextName +++++++++++++++++++++++++++++++++++++++ + +Send a SNMP GET request with the following options: + +* with SNMPv3 with user 'usr-md5-none', SHA auth and no privacy protocols +* for MIB instance identified by +* contextEngineId: 0x80004fb805636c6f75644dab22cc, +* contextName: da761cfc8c94d3aceef4f60f049105ba +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for an OID in tuple form + +This script performs similar to the following Net-SNMP command: + +| $ snmpget -v3 -l authNoPriv -u usr-md5-none -A authkey1 -E 80004fb805636c6f75644dab22cc -n da761cfc8c94d3aceef4f60f049105ba -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.1.0 + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import cmdgen +from pysnmp.proto import rfc1902 + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# +# SNMPv3/USM setup +# + +# user: usr-md5-none, auth: MD5, priv: NONE +config.addV3User( + snmpEngine, 'usr-md5-none', + config.usmHMACMD5AuthProtocol, 'authkey1' +) +config.addTargetParams(snmpEngine, 'my-creds', 'usr-md5-none', 'authNoPriv') + +# +# Setup transport endpoint and bind it with security settings yielding +# a target name +# + +# UDP/IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-router', + udp.domainName, ('195.218.195.228', 161), + 'my-creds' +) + +# Error/response receiver +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBinds, cbCtx): + if errorIndication: + print(errorIndication) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for oid, val in varBinds: + print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + +# Prepare and send a request message, pass custom ContextEngineId & ContextName +cmdgen.GetCommandGenerator().sendVarBinds( + snmpEngine, + 'my-router', + # contextEngineId + rfc1902.OctetString(hexValue='80004fb805636c6f75644dab22cc'), + # contextName + rfc1902.OctetString('da761cfc8c94d3aceef4f60f049105ba'), + [ ((1,3,6,1,2,1,1,1,0), None) ], + cbFun +) + +# Run I/O dispatcher which would send pending queries and process responses +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/manager/cmdgen/get-v3-observe-request-processing.py b/examples/v3arch/asyncore/manager/cmdgen/get-v3-observe-request-processing.py new file mode 100644 index 0000000..0914ac3 --- /dev/null +++ b/examples/v3arch/asyncore/manager/cmdgen/get-v3-observe-request-processing.py @@ -0,0 +1,105 @@ +""" +Report SNMP engine processing details ++++++++++++++++++++++++++++++++++++++ + +Send SNMP GET request with the following options: + +* with SNMPv3 with user 'usr-sha-aes', SHA auth and AES128 privacy protocols +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for an OID in tuple form +* also registers its own execution observer to snmpEngine + +While execution, this script will report some details on request processing +as seen by rfc3412.sendPdu() and rfc3412.receiveMessage() abstract interfaces. + +This script performs similar to the following Net-SNMP command: + +| $ snmpget -v3 -l authPriv -u usr-sha-aes -a SHA -A authkey1 -x AES -X privkey1 -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.1.0 + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import cmdgen + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# Execution point observer setup + +# Register a callback to be invoked at specified execution point of +# SNMP Engine and passed local variables at code point's local scope +def requestObserver(snmpEngine, execpoint, variables, cbCtx): + print('Execution point: %s' % execpoint) + print('* transportDomain: %s' % '.'.join([str(x) for x in variables['transportDomain']])) + print('* transportAddress: %s' % '@'.join([str(x) for x in variables['transportAddress']])) + print('* securityModel: %s' % variables['securityModel']) + print('* securityName: %s' % variables['securityName']) + print('* securityLevel: %s' % variables['securityLevel']) + print('* contextEngineId: %s' % (variables['contextEngineId'] and variables['contextEngineId'].prettyPrint() or '',)) + print('* contextName: %s' % variables['contextName'].prettyPrint()) + print('* PDU: %s' % variables['pdu'].prettyPrint()) + +snmpEngine.observer.registerObserver( + requestObserver, + 'rfc3412.sendPdu', + 'rfc3412.receiveMessage:response' +) + +# +# SNMPv3/USM setup +# + +# user: usr-sha-aes, auth: SHA, priv AES +config.addV3User( + snmpEngine, 'usr-sha-aes', + config.usmHMACSHAAuthProtocol, 'authkey1', + config.usmAesCfb128Protocol, 'privkey1' +) +config.addTargetParams(snmpEngine, 'my-creds', 'usr-sha-aes', 'authPriv') + +# +# Setup transport endpoint and bind it with security settings yielding +# a target name +# + +# UDP/IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-router', + udp.domainName, ('195.218.195.228', 161), + 'my-creds' +) + +# Error/response receiver +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBinds, cbCtx): + if errorIndication: + print(errorIndication) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for oid, val in varBinds: + print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + +# Prepare and send a request message +cmdgen.GetCommandGenerator().sendVarBinds( + snmpEngine, + 'my-router', + None, '', # contextEngineId, contextName + [ ((1,3,6,1,2,1,1,1,0), None) ], + cbFun +) + +# Run I/O dispatcher which would send pending queries and process responses +snmpEngine.transportDispatcher.runDispatcher() + +snmpEngine.observer.unregisterObserver() diff --git a/examples/v3arch/asyncore/manager/cmdgen/get-v3.py b/examples/v3arch/asyncore/manager/cmdgen/get-v3.py new file mode 100644 index 0000000..f7ff4ee --- /dev/null +++ b/examples/v3arch/asyncore/manager/cmdgen/get-v3.py @@ -0,0 +1,82 @@ +""" +SNMPv3, auth: SHA, privacy: AES128 +++++++++++++++++++++++++++++++++++ + +Send a SNMP GET request +* with SNMPv3 with user 'usr-sha-aes', SHA auth and AES128 privacy protocols +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for an OID in tuple form + +This script performs similar to the following Net-SNMP command: + +| $ snmpget -v3 -l authPriv -u usr-sha-aes -a SHA -A authkey1 -x AES -X privkey1 -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.1.0 + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import cmdgen + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# +# SNMPv3/USM setup +# + +# user: usr-sha-aes, auth: SHA, priv AES +config.addV3User( + snmpEngine, 'usr-sha-aes', + config.usmHMACSHAAuthProtocol, 'authkey1', + config.usmAesCfb128Protocol, 'privkey1' +) +config.addTargetParams(snmpEngine, 'my-creds', 'usr-sha-aes', 'authPriv') + +# +# Setup transport endpoint and bind it with security settings yielding +# a target name +# + +# UDP/IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-router', + udp.domainName, ('195.218.195.228', 161), + 'my-creds' +) + +# Error/response receiver +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBinds, cbCtx): + if errorIndication: + print(errorIndication) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for oid, val in varBinds: + print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + +# Prepare and send a request message +cmdgen.GetCommandGenerator().sendVarBinds( + snmpEngine, + 'my-router', + None, '', # contextEngineId, contextName + [ ((1,3,6,1,2,1,1,1,0), None) ], + cbFun +) + +# Run I/O dispatcher which would send pending queries and process responses +snmpEngine.transportDispatcher.runDispatcher() + +config.delTransport( + snmpEngine, + udp.domainName +).closeTransport() diff --git a/examples/v3arch/asyncore/manager/cmdgen/getbulk-v2c.py b/examples/v3arch/asyncore/manager/cmdgen/getbulk-v2c.py new file mode 100644 index 0000000..9f5db70 --- /dev/null +++ b/examples/v3arch/asyncore/manager/cmdgen/getbulk-v2c.py @@ -0,0 +1,82 @@ +""" +Bulk walk MIB ++++++++++++++ + +Send a series of SNMP GETBULK requests +* with SNMPv2c, community 'public' +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* with values non-repeaters = 0, max-repetitions = 25 +* for two OIDs in tuple form +* stop on end-of-mib condition for both OIDs + +This script performs similar to the following Net-SNMP command: + +| $ snmpbulkwalk -v2c -c public -C n0 -C r25 -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 + +"""# +from pysnmp.entity import engine, config +from pysnmp.entity.rfc3413 import cmdgen +from pysnmp.carrier.asyncore.dgram import udp + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# +# SNMPv2c setup +# + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public') + +# Specify security settings per SecurityName (SNMPv1 - 0, SNMPv2c - 1) +config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 1) + +# +# Setup transport endpoint and bind it with security settings yielding +# a target name +# + +# UDP/IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-router', + udp.domainName, ('195.218.195.228', 161), + 'my-creds' +) + +# Error/response receiver +def cbFun(snmpEngine, sendRequesthandle, errorIndication, + errorStatus, errorIndex, varBindTable, cbCtx): + if errorIndication: + print(errorIndication) + return # stop on error + if errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBindTable[-1][int(errorIndex)-1][0] or '?' + ) + ) + return # stop on error + for varBindRow in varBindTable: + for oid, val in varBindRow: + print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + return True # signal dispatcher to continue walking + +# Prepare initial request to be sent +cmdgen.BulkCommandGenerator().sendVarBinds( + snmpEngine, + 'my-router', + None, '', # contextEngineId, contextName + 0, 25, # non-repeaters, max-repetitions + [ ((1,3,6,1,2,1,1), None), + ((1,3,6,1,4,1,1), None) ], + cbFun +) + +# Run I/O dispatcher which would send pending queries and process responses +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/manager/cmdgen/getbulk-v3.py b/examples/v3arch/asyncore/manager/cmdgen/getbulk-v3.py new file mode 100644 index 0000000..8bd04a5 --- /dev/null +++ b/examples/v3arch/asyncore/manager/cmdgen/getbulk-v3.py @@ -0,0 +1,85 @@ +""" +Fetch scalar and table variables +++++++++++++++++++++++++++++++++ + +Send a series of SNMP GETBULK requests with the following options: + +* with SNMPv3 with user 'usr-md5-des', MD5 auth and DES privacy protocols +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* with values non-repeaters = 1, max-repetitions = 25 +* for two OIDs in tuple form (first OID is non-repeating) +* stop on end-of-mib condition for both OIDs + +This script performs similar to the following Net-SNMP command: + +| $ snmpbulkwalk -v3 -l authPriv -u usr-md5-des -A authkey1 -X privkey1 -C n1 -C r25 -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 + +"""# +from pysnmp.entity import engine, config +from pysnmp.entity.rfc3413 import cmdgen +from pysnmp.carrier.asyncore.dgram import udp + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# +# SNMPv3/USM setup +# + +# user: usr-md5-des, auth: MD5, priv DES +config.addV3User( + snmpEngine, 'usr-md5-des', + config.usmHMACMD5AuthProtocol, 'authkey1', + config.usmDESPrivProtocol, 'privkey1' +) +config.addTargetParams(snmpEngine, 'my-creds', 'usr-md5-des', 'authPriv') + +# +# Setup transport endpoint and bind it with security settings yielding +# a target name +# + +# UDP/IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-router', + udp.domainName, ('195.218.195.228', 161), + 'my-creds' +) + +# Error/response receiver +def cbFun(snmpEngine, sendRequesthandle, errorIndication, + errorStatus, errorIndex, varBindTable, cbCtx): + if errorIndication: + print(errorIndication) + return # stop on error + if errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBindTable[-1][int(errorIndex)-1][0] or '?' + ) + ) + return # stop on error + for varBindRow in varBindTable: + for oid, val in varBindRow: + print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + return True # signal dispatcher to continue walking + +# Prepare initial request to be sent +cmdgen.BulkCommandGenerator().sendVarBinds( + snmpEngine, + 'my-router', + None, '', # contextEngineId, contextName + 0, 25, # non-repeaters, max-repetitions + ( ((1,3,6,1,2,1,1), None), + ((1,3,6,1,4,1,1), None) ), + cbFun +) + +# Run I/O dispatcher which would send pending queries and process responses +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/manager/cmdgen/getnext-v1.py b/examples/v3arch/asyncore/manager/cmdgen/getnext-v1.py new file mode 100644 index 0000000..0a41a41 --- /dev/null +++ b/examples/v3arch/asyncore/manager/cmdgen/getnext-v1.py @@ -0,0 +1,83 @@ +""" +Fetch two subtrees in parallel +++++++++++++++++++++++++++++++ + +Send a series of SNMP GETNEXT requests with the following options: + +* with SNMPv1, community 'public' +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for two OIDs in tuple form +* stop on end-of-mib condition for both OIDs + +This script performs similar to the following Net-SNMP command: + +| $ snmpwalk -v1 -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import cmdgen + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# +# SNMPv1/2c setup +# + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public') + +# Specify security settings per SecurityName (SNMPv1 - 0, SNMPv2c - 1) +config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 0) + +# +# Setup transport endpoint and bind it with security settings yielding +# a target name +# + +# UDP/IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-router', + udp.domainName, ('195.218.195.228', 161), + 'my-creds' +) + +# Error/response receiver +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBindTable, cbCtx): + if errorIndication: + print(errorIndication) + return + # SNMPv1 response may contain noSuchName error *and* SNMPv2c exception, + # so we ignore noSuchName error here + if errorStatus and errorStatus != 2: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBindTable[-1][int(errorIndex)-1][0] or '?' + ) + ) + return # stop on error + for varBindRow in varBindTable: + for oid, val in varBindRow: + print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + return 1 # signal dispatcher to continue + +# Prepare initial request to be sent +cmdgen.NextCommandGenerator().sendVarBinds( + snmpEngine, + 'my-router', + None, '', # contextEngineId, contextName + [ ((1,3,6,1,2,1,1), None), + ((1,3,6,1,4,1,1), None) ], + cbFun +) + +# Run I/O dispatcher which would send pending queries and process responses +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/manager/cmdgen/getnext-v2c-from-specific-address.py b/examples/v3arch/asyncore/manager/cmdgen/getnext-v2c-from-specific-address.py new file mode 100644 index 0000000..022742a --- /dev/null +++ b/examples/v3arch/asyncore/manager/cmdgen/getnext-v2c-from-specific-address.py @@ -0,0 +1,82 @@ +""" +Send packets from specific local interface +++++++++++++++++++++++++++++++++++++++++++ + +Send a series of SNMP GETNEXT requests with the following options: + +* with SNMPv2c, community 'public' +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* sending packets from primary local interface 0.0.0.0, local port 61024 +* for two OIDs in tuple form +* stop on end-of-mib condition for both OIDs + +This script performs similar to the following Net-SNMP command: + +| $ snmpwalk -v2c -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import cmdgen + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# +# SNMPv1/2c setup (if you use SNMPv1 or v2c) +# + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public') + +# Specify security settings per SecurityName (SNMPv1 - 0, SNMPv2c - 1) +config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 0) + +# +# Setup transport endpoint and bind it with security settings yielding +# a target name +# + +# UDP/IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode(('0.0.0.0', 61024)) +) +config.addTargetAddr( + snmpEngine, 'my-router', + udp.domainName, ('195.218.195.228', 161), + 'my-creds' +) + +# Error/response receiver +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBindTable, cbCtx): + if errorIndication: + print(errorIndication) + return + if errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBindTable[-1][int(errorIndex)-1][0] or '?' + ) + ) + return # stop on error + for varBindRow in varBindTable: + for oid, val in varBindRow: + print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + return 1 # signal dispatcher to continue + +# Prepare initial request to be sent +cmdgen.NextCommandGenerator().sendVarBinds( + snmpEngine, + 'my-router', + None, '', # contextEngineId, contextName + [ ((1,3,6,1,2,1,1), None), + ((1,3,6,1,2,1,11), None) ], + cbFun +) + +# Run I/O dispatcher which would send pending queries and process responses +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/manager/cmdgen/getnext-v2c-with-mib-compilation-and-lookup.py b/examples/v3arch/asyncore/manager/cmdgen/getnext-v2c-with-mib-compilation-and-lookup.py new file mode 100644 index 0000000..d69abfe --- /dev/null +++ b/examples/v3arch/asyncore/manager/cmdgen/getnext-v2c-with-mib-compilation-and-lookup.py @@ -0,0 +1,94 @@ +""" +Walk Agent and resolve variables at MIB ++++++++++++++++++++++++++++++++++++++++ + +Send a series of SNMP GETNEXT requests with the following options: + +* with SNMPv1, community 'public' +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for two OIDs in tuple form +* stop on end-of-mib condition for both OIDs + +This script performs similar to the following Net-SNMP command: + +| $ snmpwalk -v1 -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import cmdgen +from pysnmp.smi import compiler, view, rfc1902 + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# Attach MIB compiler to SNMP Engine (MIB Builder) +# This call will fail if PySMI is not present on the system +compiler.addMibCompiler(snmpEngine.getMibBuilder()) +# ... alternatively, this call will not complain on missing PySMI +#compiler.addMibCompiler(snmpEngine.getMibBuilder(), ifAvailable=True) + +# Used for MIB objects resolution +mibViewController = view.MibViewController(snmpEngine.getMibBuilder()) + +# +# +# SNMPv1/2c setup +# + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public') + +# Specify security settings per SecurityName (SNMPv1 - 0, SNMPv2c - 1) +config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 1) + +# +# Setup transport endpoint and bind it with security settings yielding +# a target name +# + +# UDP/IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-router', + udp.domainName, ('195.218.195.228', 161), + 'my-creds' +) + +# Error/response receiver +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBindTable, cbCtx): + if errorIndication: + print(errorIndication) + return + # SNMPv1 response may contain noSuchName error *and* SNMPv2c exception, + # so we ignore noSuchName error here + if errorStatus and errorStatus != 2: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBindTable[-1][int(errorIndex)-1][0] or '?' + ) + ) + return # stop on error + for varBindRow in varBindTable: + for varBind in varBindRow: + print(rfc1902.ObjectType(rfc1902.ObjectIdentity(varBind[0]), varBind[1]).resolveWithMib(mibViewController).prettyPrint()) + return 1 # signal dispatcher to continue + +# Prepare initial request to be sent +cmdgen.NextCommandGenerator().sendVarBinds( + snmpEngine, + 'my-router', + None, '', # contextEngineId, contextName + [ rfc1902.ObjectType(rfc1902.ObjectIdentity('iso.org.dod')).resolveWithMib(mibViewController), + rfc1902.ObjectType(rfc1902.ObjectIdentity('IF-MIB', 'ifMIB')).resolveWithMib(mibViewController) ], + cbFun +) + +# Run I/O dispatcher which would send pending queries and process responses +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/manager/cmdgen/getnext-v3-over-ipv6.py b/examples/v3arch/asyncore/manager/cmdgen/getnext-v3-over-ipv6.py new file mode 100644 index 0000000..1856d80 --- /dev/null +++ b/examples/v3arch/asyncore/manager/cmdgen/getnext-v3-over-ipv6.py @@ -0,0 +1,82 @@ +""" +Walk Agent over IPv6 +++++++++++++++++++++ + +Send a series of SNMP GETNEXT requests with the following options: + +* with SNMPv3 with user 'usr-md5-none', MD5 auth and no privacy protocols +* over IPv6/UDP +* to an Agent at [::1]:161 +* for two OIDs in tuple form +* stop on end-of-mib condition for both OIDs + +This script performs similar to the following Net-SNMP command: + +| $ snmpwalk -v3 -l authNoPriv -u usr-md5-none -A authkey1 -ObentU udp6:[::1]:161 1.3.6.1.2.1.1 1.3.6.1.4.1.1 + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp6 +from pysnmp.entity.rfc3413 import cmdgen + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# +# SNMPv3/USM setup +# + +# user: usr-md5-des, auth: MD5, priv NONE +config.addV3User( + snmpEngine, 'usr-md5-none', + config.usmHMACMD5AuthProtocol, 'authkey1' +) +config.addTargetParams(snmpEngine, 'my-creds', 'usr-md5-none', 'authNoPriv') + +# +# Setup transport endpoint and bind it with security settings yielding +# a target name +# + +# UDP/IPv6 +config.addTransport( + snmpEngine, + udp6.domainName, + udp6.Udp6SocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-router', + udp6.domainName, ('::1', 161), + 'my-creds' +) + +# Error/response receiver +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBindTable, cbCtx): + if errorIndication: + print(errorIndication) + return + if errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBindTable[-1][int(errorIndex)-1][0] or '?' + ) + ) + return # stop on error + for varBindRow in varBindTable: + for oid, val in varBindRow: + print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + return True # signal dispatcher to continue + +# Prepare initial request to be sent +cmdgen.NextCommandGenerator().sendVarBinds( + snmpEngine, + 'my-router', + None, '', # contextEngineId, contextName + [ ((1,3,6,1,2,1,1), None), + ((1,3,6,1,4,1,1), None) ], + cbFun +) + +# Run I/O dispatcher which would send pending queries and process responses +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/manager/cmdgen/getnext-v3-pull-subtree.py b/examples/v3arch/asyncore/manager/cmdgen/getnext-v3-pull-subtree.py new file mode 100644 index 0000000..5edc744 --- /dev/null +++ b/examples/v3arch/asyncore/manager/cmdgen/getnext-v3-pull-subtree.py @@ -0,0 +1,86 @@ +""" +Pull MIB subtree +++++++++++++++++ + +Send a series of SNMP GETNEXT requests +* with SNMPv3 with user 'usr-none-none', no auth and no privacy protocols +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for an OID in string form +* stop whenever received OID goes out of initial prefix (it may be a table) + +This script performs similar to the following Net-SNMP command: + +| $ snmpwalk -v3 -l noAuthNoPriv -u usr-none-none -ObentU 195.218.195.228:161 1.3.6.1.2.1.1 + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import cmdgen +from pysnmp.proto import rfc1902 + +# Initial OID prefix +initialOID = rfc1902.ObjectName('1.3.6.1.2.1.1') + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# +# SNMPv3/USM setup +# + +# user: usr-none-none, auth: none, priv: none +config.addV3User( + snmpEngine, 'usr-none-none', +) +config.addTargetParams(snmpEngine, 'my-creds', 'usr-none-none', 'noAuthNoPriv') + +# +# Setup transport endpoint and bind it with security settings yielding +# a target name +# + +# UDP/IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-router', + udp.domainName, ('195.218.195.228', 161), + 'my-creds' +) + +# Error/response receiver +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBindTable, cbCtx): + if errorIndication: + print(errorIndication) + return + if errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBindTable[-1][int(errorIndex)-1][0] or '?' + ) + ) + return # stop on error + for varBindRow in varBindTable: + for oid, val in varBindRow: + if initialOID.isPrefixOf(oid): + print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + else: + return False # signal dispatcher to stop + return True # signal dispatcher to continue + +# Prepare initial request to be sent +cmdgen.NextCommandGenerator().sendVarBinds( + snmpEngine, + 'my-router', + None, '', # contextEngineId, contextName + [ (initialOID, None) ], + cbFun +) + +# Run I/O dispatcher which would send pending queries and process responses +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/manager/cmdgen/set-v1.py b/examples/v3arch/asyncore/manager/cmdgen/set-v1.py new file mode 100644 index 0000000..55a8720 --- /dev/null +++ b/examples/v3arch/asyncore/manager/cmdgen/set-v1.py @@ -0,0 +1,80 @@ +""" +SET string and integer scalars +++++++++++++++++++++++++++++++ + +Send SNMP SET request with the following options: + +* with SNMPv1 with community name 'private' +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for OIDs in tuple form and an integer and string-typed values + +This script performs similar to the following Net-SNMP command: + +| $ snmpset -v1 -c private -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.9.1.3.1 s 'my value' 1.3.6.1.2.1.1.9.1.4.1 t 123 + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import cmdgen +from pysnmp.proto import rfc1902 + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# +# SNMPv1 setup +# + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'private') + +# Specify security settings per SecurityName (SNMPv1 - 0, SNMPv2c - 1) +config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 0) + +# +# Setup transport endpoint and bind it with security settings yielding +# a target name +# + +# UDP/IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-router', + udp.domainName, ('195.218.195.228', 161), + 'my-creds' +) + +# Error/response receiver +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBinds, cbCtx): + if errorIndication: + print(errorIndication) + # SNMPv1 response may contain noSuchName error *and* SNMPv2c exception, + # so we ignore noSuchName error here + elif errorStatus and errorStatus != 2: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for oid, val in varBinds: + print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + +# Prepare and send a request message +cmdgen.SetCommandGenerator().sendVarBinds( + snmpEngine, + 'my-router', + None, '', # contextEngineId, contextName + [ ((1,3,6,1,2,1,1,9,1,3,1), rfc1902.OctetString('my value')), + ((1,3,6,1,2,1,1,9,1,4,1), rfc1902.TimeTicks(123)) ], + cbFun +) + +# Run I/O dispatcher which would send pending queries and process responses +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/manager/cmdgen/set-v2c.py b/examples/v3arch/asyncore/manager/cmdgen/set-v2c.py new file mode 100644 index 0000000..9f7068f --- /dev/null +++ b/examples/v3arch/asyncore/manager/cmdgen/set-v2c.py @@ -0,0 +1,76 @@ +""" +Set scalar value +++++++++++++++++ + +Send a SNMP SET request +* with SNMPv2c with community name 'private' +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for an OID in tuple form and an integer-typed value + +This script performs similar to the following Net-SNMP command: + +| $ snmpset -v2c -c private -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.9.1.4.1 t 123 + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import cmdgen +from pysnmp.proto import rfc1902 + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# +# SNMPv2c setup +# + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'private') + +# Specify security settings per SecurityName (SNMPv1 - 0, SNMPv2c - 1) +config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 1) + +# +# Setup transport endpoint and bind it with security settings yielding +# a target name +# + +# UDP/IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-router', + udp.domainName, ('195.218.195.228', 161), + 'my-creds' +) + +# Error/response receiver +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBinds, cbCtx): + if errorIndication: + print(errorIndication) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for oid, val in varBinds: + print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + +# Prepare and send a request message +cmdgen.SetCommandGenerator().sendVarBinds( + snmpEngine, + 'my-router', + None, '', # contextEngineId, contextName + [ ((1,3,6,1,2,1,1,9,1,4,1), rfc1902.TimeTicks(123)) ], + cbFun +) + +# Run I/O dispatcher which would send pending queries and process responses +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/manager/cmdgen/set-v3.py b/examples/v3arch/asyncore/manager/cmdgen/set-v3.py new file mode 100644 index 0000000..1c39d33 --- /dev/null +++ b/examples/v3arch/asyncore/manager/cmdgen/set-v3.py @@ -0,0 +1,78 @@ +""" +Set string value +++++++++++++++++ + +Send a SNMP SET request with the following options: + +* with SNMPv3 with user 'usr-sha-none', SHA auth and no privacy protocols +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for an OID in tuple form and a string-typed value + +This script performs similar to the following Net-SNMP command: + +| $ snmpset -v3 -l authNoPriv -u usr-sha-none -a SHA -A authkey1 -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.9.1.3.1 s 'my new value' + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import cmdgen +from pysnmp.proto import rfc1902 + +# Create SNMP engine instance +snmpEngine = engine.SnmpEngine() + +# +# SNMPv3/USM setup +# + +# user: usr-sha-none, auth: SHA, priv none +config.addV3User( + snmpEngine, 'usr-sha-none', + config.usmHMACSHAAuthProtocol, 'authkey1' +) +config.addTargetParams(snmpEngine, 'my-creds', 'usr-sha-none', 'authNoPriv') + +# +# Setup transport endpoint and bind it with security settings yielding +# a target name +# + +# UDP/IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpSocketTransport().openClientMode() +) +config.addTargetAddr( + snmpEngine, 'my-router', + udp.domainName, ('195.218.195.228', 161), + 'my-creds' +) + +# Error/response receiver +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBinds, cbCtx): + if errorIndication: + print(errorIndication) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for oid, val in varBinds: + print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + +# Prepare and send a request message +cmdgen.SetCommandGenerator().sendVarBinds( + snmpEngine, + 'my-router', + None, '', # contextEngineId, contextName + [ ((1,3,6,1,2,1,1,9,1,3,1), rfc1902.OctetString('my new value')) ], + cbFun +) + +# Run I/O dispatcher which would send pending queries and process responses +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/manager/ntfrcv/v2c-multiple-interfaces.py b/examples/v3arch/asyncore/manager/ntfrcv/v2c-multiple-interfaces.py new file mode 100644 index 0000000..402f930 --- /dev/null +++ b/examples/v3arch/asyncore/manager/ntfrcv/v2c-multiple-interfaces.py @@ -0,0 +1,70 @@ +""" +Serving multiple network interfaces ++++++++++++++++++++++++++++++++++++ + +Receive SNMP TRAP/INFORM messages with the following options: + +* SNMPv1/SNMPv2c +* with SNMP community "public" +* over IPv4/UDP, listening at 127.0.0.1:162 + over IPv4/UDP, listening at 127.0.0.1:2162 +* print received data on stdout + +Either of the following Net-SNMP commands will send notifications to this +receiver: + +| $ snmptrap -v2c -c public 127.0.0.1:162 123 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.5.0 s test +| $ snmpinform -v2c -c public 127.0.0.1:2162 123 1.3.6.1.6.3.1.1.5.1 + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import ntfrcv + +# Create SNMP engine with autogenernated engineID and pre-bound +# to socket transport dispatcher +snmpEngine = engine.SnmpEngine() + +# Transport setup + +# UDP over IPv4, first listening interface/port +config.addTransport( + snmpEngine, + udp.domainName + (1,), + udp.UdpTransport().openServerMode(('127.0.0.1', 162)) +) + +# UDP over IPv4, second listening interface/port +config.addTransport( + snmpEngine, + udp.domainName + (2,), + udp.UdpTransport().openServerMode(('127.0.0.1', 2162)) +) + +# SNMPv1/2c setup + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public') + +# Callback function for receiving notifications +def cbFun(snmpEngine, stateReference, contextEngineId, contextName, + varBinds, cbCtx): + print('Notification from ContextEngineId "%s", ContextName "%s"' % ( + contextEngineId.prettyPrint(), + contextName.prettyPrint() + ) + ) + for name, val in varBinds: + print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) + +# Register SNMP Application at the SNMP engine +ntfrcv.NotificationReceiver(snmpEngine, cbFun) + +snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish + +# Run I/O dispatcher which would receive queries and send confirmations +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/manager/ntfrcv/v2c-multiple-transports.py b/examples/v3arch/asyncore/manager/ntfrcv/v2c-multiple-transports.py new file mode 100644 index 0000000..31fcb2b --- /dev/null +++ b/examples/v3arch/asyncore/manager/ntfrcv/v2c-multiple-transports.py @@ -0,0 +1,71 @@ +""" +Using multiple network transports ++++++++++++++++++++++++++++++++++ + +Receive SNMP TRAP/INFORM messages with the following options: + +* SNMPv1/SNMPv2c +* with SNMP community "public" +* over IPv4/UDP, listening at 127.0.0.1:162 + over IPv6/UDP, listening at [::1]:162 +* print received data on stdout + +Either of the following Net-SNMP commands will send notifications to this +receiver: + +| $ snmptrap -v1 -c public 127.0.0.1 1.3.6.1.4.1.20408.4.1.1.2 127.0.0.1 1 1 123 1.3.6.1.2.1.1.1.0 s test +| $ snmptrap -v2c -c public udp6:[::1]:162 123 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.5.0 s test +| $ snmpinform -v2c -c public 127.0.0.1 123 1.3.6.1.6.3.1.1.5.1 + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp, udp6 +from pysnmp.entity.rfc3413 import ntfrcv + +# Create SNMP engine with autogenernated engineID and pre-bound +# to socket transport dispatcher +snmpEngine = engine.SnmpEngine() + +# Transport setup + +# UDP over IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpTransport().openServerMode(('127.0.0.1', 162)) +) + +# UDP over IPv6 +config.addTransport( + snmpEngine, + udp6.domainName, + udp6.Udp6Transport().openServerMode(('::1', 162)) + ) + +# SNMPv1/2c setup + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public') + +# Callback function for receiving notifications +def cbFun(snmpEngine, stateReference, contextEngineId, contextName, + varBinds, cbCtx): + print('Notification from ContextEngineId "%s", ContextName "%s"' % ( + contextEngineId.prettyPrint(), + contextName.prettyPrint() + ) + ) + for name, val in varBinds: + print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) + +# Register SNMP Application at the SNMP engine +ntfrcv.NotificationReceiver(snmpEngine, cbFun) + +snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish + +# Run I/O dispatcher which would receive queries and send confirmations +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/manager/ntfrcv/v2c-observe-request-processing.py b/examples/v3arch/asyncore/manager/ntfrcv/v2c-observe-request-processing.py new file mode 100644 index 0000000..ed44146 --- /dev/null +++ b/examples/v3arch/asyncore/manager/ntfrcv/v2c-observe-request-processing.py @@ -0,0 +1,94 @@ +""" +Observe SNMP engine internal operations ++++++++++++++++++++++++++++++++++++++++ + +Receive SNMP TRAP/INFORM messages with the following options: + +* SNMPv1/SNMPv2c +* with SNMP community "public" +* over IPv4/UDP, listening at 127.0.0.1:162 + over IPv6/UDP, listening at [::1]:162 +* registers its own execution observer to snmpEngine +* print received data on stdout + +Either of the following Net-SNMP commands will send notifications to this +receiver: + +| $ snmptrap -v1 -c public 127.0.0.1 1.3.6.1.4.1.20408.4.1.1.2 127.0.0.1 1 1 123 1.3.6.1.2.1.1.1.0 s test +| $ snmptrap -v2c -c public udp6:[::1]:162 123 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.5.0 s test +| $ snmpinform -v2c -c public 127.0.0.1 123 1.3.6.1.6.3.1.1.5.1 + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp, udp6 +from pysnmp.entity.rfc3413 import ntfrcv + +# Create SNMP engine with autogenernated engineID and pre-bound +# to socket transport dispatcher +snmpEngine = engine.SnmpEngine() + +# Execution point observer setup + +# Register a callback to be invoked at specified execution point of +# SNMP Engine and passed local variables at code point's local scope +def requestObserver(snmpEngine, execpoint, variables, cbCtx): + print('Execution point: %s' % execpoint) + print('* transportDomain: %s' % '.'.join([str(x) for x in variables['transportDomain']])) + print('* transportAddress: %s' % '@'.join([str(x) for x in variables['transportAddress']])) + print('* securityModel: %s' % variables['securityModel']) + print('* securityName: %s' % variables['securityName']) + print('* securityLevel: %s' % variables['securityLevel']) + print('* contextEngineId: %s' % variables['contextEngineId'].prettyPrint()) + print('* contextName: %s' % variables['contextName'].prettyPrint()) + print('* PDU: %s' % variables['pdu'].prettyPrint()) + +snmpEngine.observer.registerObserver( + requestObserver, + 'rfc3412.receiveMessage:request', + 'rfc3412.returnResponsePdu' +) + +# Transport setup + +# UDP over IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpTransport().openServerMode(('127.0.0.1', 162)) +) + +# UDP over IPv6 +config.addTransport( + snmpEngine, + udp6.domainName, + udp6.Udp6Transport().openServerMode(('::1', 162)) + ) + +# SNMPv1/2c setup + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public') + +# Callback function for receiving notifications +def cbFun(snmpEngine, stateReference, contextEngineId, contextName, + varBinds, cbCtx): + print('Notification from ContextEngineId "%s", ContextName "%s"' % ( + contextEngineId.prettyPrint(), + contextName.prettyPrint() + ) + ) + for name, val in varBinds: + print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) + +# Register SNMP Application at the SNMP engine +ntfrcv.NotificationReceiver(snmpEngine, cbFun) + +snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish + +# Run I/O dispatcher which would receive queries and send confirmations +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.observer.unregisterObserver() + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/manager/ntfrcv/v2c-with-regexp-community-name.py b/examples/v3arch/asyncore/manager/ntfrcv/v2c-with-regexp-community-name.py new file mode 100644 index 0000000..759bf98 --- /dev/null +++ b/examples/v3arch/asyncore/manager/ntfrcv/v2c-with-regexp-community-name.py @@ -0,0 +1,88 @@ +""" +Serve SNMP Community names defined by regexp +++++++++++++++++++++++++++++++++++++++++++++ + +Receive SNMP TRAP/INFORM messages with the following options: + +* SNMPv1/SNMPv2c +* with any SNMP community matching regexp '.*love.*' +* over IPv4/UDP, listening at 127.0.0.1:162 +* print received data on stdout + +Either of the following Net-SNMP commands will send notifications to this +receiver: + +| $ snmptrap -v1 -c rollover 127.0.0.1 1.3.6.1.4.1.20408.4.1.1.2 127.0.0.1 1 1 123 1.3.6.1.2.1.1.1.0 s test +| $ snmpinform -v2c -c glove 127.0.0.1 123 1.3.6.1.6.3.1.1.5.1 + +The Notification Receiver below taps on v1/v2c SNMP security module +to deliver certains values, normally internal to SNMP Engine, up to +the context of user application. + +This script examines the value of CommunityName, as it came from peer SNMP +Engine, and may modify it to match the only locally configured CommunityName +'public'. This effectively makes NotificationReceiver accepting messages with +CommunityName's, not explicitly configured to local SNMP Engine. + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import ntfrcv +from pysnmp.proto.api import v2c +import re + +# Create SNMP engine with autogenernated engineID and pre-bound +# to socket transport dispatcher +snmpEngine = engine.SnmpEngine() + +# Register a callback to be invoked at specified execution point of +# SNMP Engine and passed local variables at execution point's local scope. +# If at this execution point passed variables are modified, their new +# values will be propagated back and used by SNMP Engine for securityName +# selection. +def requestObserver(snmpEngine, execpoint, variables, cbCtx): + if re.match('.*love.*', str(variables['communityName'])): + print('Rewriting communityName \'%s\' from %s into \'public\'' % (variables['communityName'], ':'.join([str(x) for x in variables['transportInformation'][1]]))) + variables['communityName'] = variables['communityName'].clone('public') + +snmpEngine.observer.registerObserver( + requestObserver, + 'rfc2576.processIncomingMsg:writable' +) + +# Transport setup + +# UDP over IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpTransport().openServerMode(('127.0.0.1', 162)) +) + +# SNMPv1/2c setup + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public') + +# Callback function for receiving notifications +def cbFun(snmpEngine, stateReference, contextEngineId, contextName, + varBinds, cbCtx): + print('Notification from ContextEngineId "%s", ContextName "%s"' % ( + contextEngineId.prettyPrint(), + contextName.prettyPrint() + ) + ) + for name, val in varBinds: + print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) + +# Register SNMP Application at the SNMP engine +ntfrcv.NotificationReceiver(snmpEngine, cbFun) + +snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish + +# Run I/O dispatcher which would receive queries and send confirmations +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/manager/ntfrcv/v2c-with-request-details.py b/examples/v3arch/asyncore/manager/ntfrcv/v2c-with-request-details.py new file mode 100644 index 0000000..d8619de --- /dev/null +++ b/examples/v3arch/asyncore/manager/ntfrcv/v2c-with-request-details.py @@ -0,0 +1,69 @@ +""" +Receive notifications noting peer address ++++++++++++++++++++++++++++++++++++++++++ + +Receive SNMP TRAP/INFORM messages with the following options: + +* SNMPv1/SNMPv2c +* with SNMP community "public" +* over IPv4/UDP, listening at 127.0.0.1:162 +* use observer facility to pull lower-level request details from SNMP engine +* print received data on stdout + +Either of the following Net-SNMP commands will send notifications to this +receiver: + +| $ snmptrap -v2c -c public 127.0.0.1:162 123 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.5.0 s test + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import ntfrcv + +# Create SNMP engine with autogenernated engineID and pre-bound +# to socket transport dispatcher +snmpEngine = engine.SnmpEngine() + +# Transport setup + +# UDP over IPv4, first listening interface/port +config.addTransport( + snmpEngine, + udp.domainName + (1,), + udp.UdpTransport().openServerMode(('127.0.0.1', 162)) +) + +# SNMPv1/2c setup + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public') + +# Callback function for receiving notifications +def cbFun(snmpEngine, stateReference, contextEngineId, contextName, + varBinds, cbCtx): + # Get an execution context... + execContext = snmpEngine.observer.getExecutionContext( + 'rfc3412.receiveMessage:request' + ) + + # ... and use inner SNMP engine data to figure out peer address + print('Notification from %s, ContextEngineId "%s", ContextName "%s"' % ( + '@'.join([str(x) for x in execContext['transportAddress']]), + contextEngineId.prettyPrint(), + contextName.prettyPrint() + ) + ) + for name, val in varBinds: + print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) + +# Register SNMP Application at the SNMP engine +ntfrcv.NotificationReceiver(snmpEngine, cbFun) + +snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish + +# Run I/O dispatcher which would receive queries and send confirmations +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/manager/ntfrcv/v3-multiple-users.py b/examples/v3arch/asyncore/manager/ntfrcv/v3-multiple-users.py new file mode 100644 index 0000000..037062b --- /dev/null +++ b/examples/v3arch/asyncore/manager/ntfrcv/v3-multiple-users.py @@ -0,0 +1,111 @@ +""" +Multiple SNMP USM users ++++++++++++++++++++++++ + +Receive SNMP TRAP/INFORM messages with the following options: + +* SNMPv3 +* with USM users: + + * 'usr-md5-des', auth: MD5, priv DES, ContextEngineId: 8000000001020304 + * 'usr-md5-none', auth: MD5, priv NONE, ContextEngineId: 8000000001020304 + * 'usr-sha-aes128', auth: SHA, priv AES, ContextEngineId: 8000000001020304 + +* over IPv4/UDP, listening at 127.0.0.1:162 +* print received data on stdout + +Either of the following Net-SNMP commands will send notifications to this +receiver: + +| $ snmptrap -v3 -u usr-md5-des -l authPriv -A authkey1 -X privkey1 -e 8000000001020304 127.0.0.1 123 1.3.6.1.6.3.1.1.5.1 +| $ snmptrap -v3 -u usr-md5-none -l authNoPriv -A authkey1 -e 8000000001020304 127.0.0.1 123 1.3.6.1.6.3.1.1.5.1 +| $ snmpinform -v3 -u usr-sha-aes128 -l authPriv -a SHA -A authkey1 -x AES -X privkey1 127.0.0.1 123 1.3.6.1.6.3.1.1.5.1 + +"""# +from pysnmp.entity import engine, config +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity.rfc3413 import ntfrcv +from pysnmp.proto.api import v2c + +# Create SNMP engine with autogenernated engineID and pre-bound +# to socket transport dispatcher +snmpEngine = engine.SnmpEngine() + +# Transport setup + +# UDP over IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpTransport().openServerMode(('127.0.0.1', 162)) +) + +# SNMPv3/USM setup + +# user: usr-md5-des, auth: MD5, priv DES +config.addV3User( + snmpEngine, 'usr-md5-des', + config.usmHMACMD5AuthProtocol, 'authkey1', + config.usmDESPrivProtocol, 'privkey1' +) + +# user: usr-md5-des, auth: MD5, priv DES, securityEngineId: 8000000001020304 +# this USM entry is used for TRAP receiving purposes +config.addV3User( + snmpEngine, 'usr-md5-des', + config.usmHMACMD5AuthProtocol, 'authkey1', + config.usmDESPrivProtocol, 'privkey1', + securityEngineId=v2c.OctetString(hexValue='8000000001020304') +) + +# user: usr-md5-none, auth: MD5, priv NONE +config.addV3User( + snmpEngine, 'usr-md5-none', + config.usmHMACMD5AuthProtocol, 'authkey1' +) + +# user: usr-md5-none, auth: MD5, priv NONE, securityEngineId: 8000000001020304 +# this USM entry is used for TRAP receiving purposes +config.addV3User( + snmpEngine, 'usr-md5-none', + config.usmHMACMD5AuthProtocol, 'authkey1', + securityEngineId=v2c.OctetString(hexValue='8000000001020304') +) + +# user: usr-sha-aes128, auth: SHA, priv AES +config.addV3User( + snmpEngine, 'usr-sha-aes128', + config.usmHMACSHAAuthProtocol, 'authkey1', + config.usmAesCfb128Protocol, 'privkey1' +) +# user: usr-sha-aes128, auth: SHA, priv AES, securityEngineId: 8000000001020304 +# this USM entry is used for TRAP receiving purposes +config.addV3User( + snmpEngine, 'usr-sha-aes128', + config.usmHMACSHAAuthProtocol, 'authkey1', + config.usmAesCfb128Protocol, 'privkey1', + securityEngineId=v2c.OctetString(hexValue='8000000001020304') +) + +# Callback function for receiving notifications +def cbFun(snmpEngine, stateReference, contextEngineId, contextName, + varBinds, cbCtx): + print('Notification from ContextEngineId "%s", ContextName "%s"' % ( + contextEngineId.prettyPrint(), + contextName.prettyPrint() + ) + ) + for name, val in varBinds: + print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) + +# Register SNMP Application at the SNMP engine +ntfrcv.NotificationReceiver(snmpEngine, cbFun) + +snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish + +# Run I/O dispatcher which would receive queries and send confirmations +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-async-multiple-snmp-engines.py b/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-async-multiple-snmp-engines.py new file mode 100644 index 0000000..aa96c1e --- /dev/null +++ b/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-async-multiple-snmp-engines.py @@ -0,0 +1,88 @@ +""" +Multiple SNMP Engines ++++++++++++++++++++++ + +Send SNMP notifications in behalf of multiple independend SNMP engines +using the following options: + +* with a single transport dispatcher and two independent SNMP engines +* SNMPv2c and SNMPv3 +* with community name 'public' or USM username usr-md5-des +* over IPv4/UDP +* send IMFORM notification +* to multiple Managers +* with TRAP ID 'coldStart' specified as a MIB symbol +* include managed object information specified as var-bind objects pair + +Within this script we have a single asynchronous TransportDispatcher +and a single UDP-based transport serving two independent SNMP engines. +We use a single instance of AsyncNotificationOriginator with each of +SNMP Engines to communicate INFORM notification to remote systems. + +When we receive a [response] message from remote system we use +a custom message router to choose what of the two SNMP engines +data packet should be handed over. The selection criteria we +employ here is based on peer's UDP port number. Other selection +criterias are also possible. + +"""# +from pysnmp.entity.rfc3413.oneliner.ntforg import * +from pysnmp.carrier.asyncore.dispatch import AsyncoreDispatcher + +# List of targets in the following format: +# ( ( authData, transportTarget ), ... ) +targets = ( + # 1-st target (SNMPv2c over IPv4/UDP) + ( CommunityData('public'), + UdpTransportTarget(('localhost', 1162)), + ContextData() ), + # 2-nd target (SNMPv3 over IPv4/UDP) + ( UsmUserData('usr-md5-des', 'authkey1', 'privkey1'), + UdpTransportTarget(('localhost', 162)), + ContextData() ), +) + +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBinds, cbCtx): + snmpEngine = cbCtx + if errorIndication: + print('Notification %s for %s not sent: %s' % (sendRequestHandle, snmpEngine.snmpEngineID.prettyPrint(), errorIndication)) + elif errorStatus: + print('Notification Receiver returned error for request %s, SNMP Engine %s: %s @%s' % (sendRequestHandle, snmpEngine.snmpEngineID.prettyPrint(), errorStatus, errorIndex)) + else: + print('Notification %s for SNMP Engine %s delivered:' % (sendRequestHandle, snmpEngine.snmpEngineID.prettyPrint())) + for name, val in varBinds: + print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) + +# Instantiate the single transport dispatcher object +transportDispatcher = AsyncoreDispatcher() + +# Setup a custom data routing function to select snmpEngine by transportDomain +transportDispatcher.registerRoutingCbFun( + lambda td,ta,d: ta[1] % 3 and 'A' or 'B' +) + +snmpEngineA = engine.SnmpEngine() +snmpEngineA.registerTransportDispatcher(transportDispatcher, 'A') + +snmpEngineB = engine.SnmpEngine() +snmpEngineB.registerTransportDispatcher(transportDispatcher, 'B') + +ntfOrg = AsyncNotificationOriginator() + +for authData, transportTarget, contextData in targets: + snmpEngine = transportTarget.getTransportInfo()[1][1] % 3 and \ + snmpEngineA or snmpEngineB + sendPduHandle = ntfOrg.sendNotification( + snmpEngine, + authData, + transportTarget, + contextData, + 'inform', # NotifyType + NotificationType( + ObjectIdentity('SNMPv2-MIB', 'coldStart') + ).addVarBinds( ( '1.3.6.1.2.1.1.1.0', 'my name' ) ), + cbInfo=(cbFun, snmpEngine) + ) + +transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-async-multiple-transports-and-protocols.py b/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-async-multiple-transports-and-protocols.py new file mode 100644 index 0000000..cfa2acd --- /dev/null +++ b/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-async-multiple-transports-and-protocols.py @@ -0,0 +1,60 @@ +""" +Multiple concurrent notifications ++++++++++++++++++++++++++++++++++ + +Send multiple SNMP notifications at once using the following options: + +* SNMPv2c and SNMPv3 +* with community name 'public' or USM username usr-md5-des +* over IPv4/UDP +* send INFORM notification +* to multiple Managers +* with TRAP ID 'coldStart' specified as a MIB symbol +* include managed object information specified as var-bind objects pair + +"""# +from pysnmp.entity.rfc3413.oneliner.ntforg import * + +# List of targets in the followin format: +# ( ( authData, transportTarget ), ... ) +targets = ( + # 1-st target (SNMPv2c over IPv4/UDP) + ( CommunityData('public'), + UdpTransportTarget(('localhost', 162)), + ContextData() ), + # 2-nd target (SNMPv3 over IPv4/UDP) + ( UsmUserData('usr-md5-des', 'authkey1', 'privkey1'), + UdpTransportTarget(('localhost', 162)), + ContextData() ), +) + +def cbFun(snmpEngine, sendRequestHandle, errorIndication, + errorStatus, errorIndex, varBinds, cbctx): + if errorIndication: + print('Notification %s not sent: %s' % (sendRequestHandle, errorIndication)) + elif errorStatus: + print('Notification Receiver returned error for %s: %s @%s' % + (sendRequestHandle, errorStatus, errorIndex)) + else: + print('Notification %s delivered:' % sendRequestHandle) + for name, val in varBinds: + print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) + +snmpEngine = engine.SnmpEngine() + +ntfOrg = AsyncNotificationOriginator() + +for authData, transportTarget, contextData in targets: + sendPduHandle = ntfOrg.sendNotification( + snmpEngine, + authData, + transportTarget, + contextData, + 'inform', # NotifyType + NotificationType( + ObjectIdentity('SNMPv2-MIB', 'coldStart') + ).addVarBinds( ( '1.3.6.1.2.1.1.1.0', 'my name' ) ), + cbInfo=(cbFun, None) + ) + +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-v2c-with-mib-lookup.py b/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-v2c-with-mib-lookup.py index 6eebaa9..4d99a12 100644 --- a/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-v2c-with-mib-lookup.py +++ b/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-v2c-with-mib-lookup.py @@ -1,42 +1,49 @@ -# -# Notification Originator -# -# Send SNMP notification using the following options: -# -# * SNMPv2c -# * with community name 'public' -# * over IPv4/UDP -# * send INFORM notification -# * with TRAP ID 'coldStart' specified as a MIB symbol -# * include managed object information specified as a MIB symbol -# * perform response OIDs and values resolution at MIB -# +""" +Sending additional var-binds +++++++++++++++++++++++++++++ + +Send SNMP notification using the following options: + +* SNMPv2c +* with community name 'public' +* over IPv4/UDP +* send INFORM notification +* with TRAP ID 'coldStart' specified as a MIB symbol +* include managed object information specified as a MIB symbol + +Functionally similar to: + +| $ snmpinform -v2c -c public +| demo.snmplabs.com \ +| 12345 \ +| 1.3.6.1.6.3.1.1.5.1 \ +| 1.3.6.1.2.1.1.1.0 s 'my system' + +"""# from pysnmp.entity.rfc3413.oneliner.ntforg import * -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in \ - sendNotification(SnmpEngine(), - CommunityData('public'), - UdpTransportTarget(('localhost', 162)), - ContextData(), - 'inform', - NotificationType( - ObjectIdentity('SNMPv2-MIB', 'coldStart') - ).addVarBinds( - ( ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysName', 0), 'my system') ) - ), - lookupNames=True, lookupValues=True): - # Check for errors and print out results - if errorIndication: - print(errorIndication) - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) - ) - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) +errorIndication, errorStatus, errorIndex, varBinds = next( + sendNotification(SnmpEngine(), + CommunityData('public'), + UdpTransportTarget(('localhost', 162)), + ContextData(), + 'inform', + NotificationType( + ObjectIdentity('SNMPv2-MIB', 'coldStart') + ).addVarBinds( + ObjectType(ObjectIdentity('SNMPv2-MIB','sysName',0), + 'my system') + )) +) + +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-v3-with-custom-contextengineid.py b/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-v3-with-custom-contextengineid.py index 071c336..0c75c21 100644 --- a/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-v3-with-custom-contextengineid.py +++ b/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-v3-with-custom-contextengineid.py @@ -1,46 +1,50 @@ -# -# Notification Originator -# -# Send SNMP notification using the following options: -# -# * SNMPv3 -# * with user 'usr-md5-none', MD5 auth, no priv -# * send INFORM notification -# * in behalf of contextEngineId 0x8000000004030201, contextName '' -# * over IPv4/UDP -# * with TRAP ID 'warmStart' specified as a string OID -# -# Sending SNMPv3 Notification in behalf of non-default ContextEngineId -# requires having a collection of Managed Objects registered under -# the ContextEngineId being used. -# +""" +INFORM with custom ContextEngineId +++++++++++++++++++++++++++++++++++ + +Send SNMP notification using the following options: + +* SNMPv3 +* with user 'usr-md5-none', MD5 auth, no priv +* send INFORM notification +* in behalf of contextEngineId 0x8000000004030201, contextName '' +* over IPv4/UDP +* with TRAP ID 'warmStart' specified as a string OID + +Sending SNMPv3 Notification in behalf of non-default ContextEngineId +requires having a collection of Managed Objects registered under +the ContextEngineId being used. + +Functionally similar to: + +| $ snmpinform -v3 -l authNoPriv -u usr-md5-none -A authkey1 \ +| -E 0x8000000004030201 +| demo.snmplabs.com \ +| 12345 \ +| 1.3.6.1.6.3.1.1.5.2 + +"""# from pysnmp.entity.rfc3413.oneliner.ntforg import * -from pysnmp.proto import rfc1902 - -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in \ - sendNotification(SnmpEngine(), - UsmUserData('usr-md5-none', 'authkey1'), - UdpTransportTarget(('localhost', 162)), - ContextData( - rfc1902.OctetString(hexValue='8000000004030201') - ), - 'inform', - NotificationType( - ObjectIdentity('1.3.6.1.6.3.1.1.5.2') - ), - lookupNames=True, lookupValues=True): - # Check for errors and print out results - if errorIndication: - print(errorIndication) - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) - ) - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) + +errorIndication, errorStatus, errorIndex, varBinds = next( + sendNotification(SnmpEngine(), + UsmUserData('usr-md5-none', 'authkey1'), + UdpTransportTarget(('localhost', 162)), + ContextData( + rfc1902.OctetString(hexValue='8000000004030201') + ), + 'inform', + NotificationType(ObjectIdentity('1.3.6.1.6.3.1.1.5.2'))) +) + +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-v3-with-custom-contextname.py b/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-v3-with-custom-contextname.py index ed87fdc..1b3e1f8 100644 --- a/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-v3-with-custom-contextname.py +++ b/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-v3-with-custom-contextname.py @@ -1,43 +1,48 @@ -# -# Notification Originator -# -# Send SNMP notification using the following options: -# -# * SNMPv3 -# * with user 'usr-md5-none', MD5 auth, no priv -# * send INFORM notification -# * in behalf of contextEngineId = SnmpEngineId, contextName 'my-context' -# * over IPv4/UDP -# * with TRAP ID 'warmStart' specified as a string OID -# -# Sending SNMPv3 Notification in behalf of non-default ContextName -# requires having a collection of Managed Objects registered under -# the ContextName being used. -# +""" +INFORM with custom ContextName +++++++++++++++++++++++++++++++ + +Send SNMP notification using the following options: + +* SNMPv3 +* with user 'usr-md5-none', MD5 auth, no priv +* send INFORM notification +* in behalf of contextEngineId = SnmpEngineId, contextName 'my-context' +* over IPv4/UDP +* with TRAP ID 'warmStart' specified as a string OID + +Sending SNMPv3 Notification in behalf of non-default ContextName +requires having a collection of Managed Objects registered under +the ContextName being used. + +Functionally similar to: + +| $ snmpinform -v3 -l authNoPriv -u usr-md5-none -A authkey1 \ +| -n my-context \ +| demo.snmplabs.com \ +| 12345 \ +| 1.3.6.1.6.3.1.1.5.2 + +"""# from pysnmp.entity.rfc3413.oneliner.ntforg import * -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in \ - sendNotification(SnmpEngine(), - UsmUserData('usr-md5-none', 'authkey1'), - UdpTransportTarget(('localhost', 162)), - ContextData(contextName='my-context'), - 'inform', - NotificationType( - ObjectIdentity('1.3.6.1.6.3.1.1.5.2') - ), - lookupNames=True, lookupValues=True): - # Check for errors and print out results - if errorIndication: - print(errorIndication) - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) - ) - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) +errorIndication, errorStatus, errorIndex, varBinds = next( + sendNotification(SnmpEngine(), + UsmUserData('usr-md5-none', 'authkey1'), + UdpTransportTarget(('localhost', 162)), + ContextData(contextName='my-context'), + 'inform', + NotificationType(ObjectIdentity('1.3.6.1.6.3.1.1.5.2'))) +) + +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-v3.py b/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-v3.py index 2996eb5..161427a 100644 --- a/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-v3.py +++ b/examples/v3arch/asyncore/oneliner/agent/ntforg/inform-v3.py @@ -1,44 +1,49 @@ -## -# Notification Originator -# -# Send SNMP notification using the following options: -# -# * SNMPv3 -# * with user 'usr-md5-des', auth: MD5, priv DES -# * over IPv4/UDP -# * send INFORM notification -# * with TRAP ID 'warmStart' specified as a string OID -# * include managed object information 1.3.6.1.2.1.1.5.0 = 'system name' -# +""" +INFORM, auth: MD5 privacy: DES +++++++++++++++++++++++++++++++ + +Send SNMP INFORM notification using the following options: + +* SNMPv3 +* with user 'usr-md5-des', auth: MD5, priv DES +* over IPv4/UDP +* send INFORM notification +* with TRAP ID 'warmStart' specified as a string OID +* include managed object information 1.3.6.1.2.1.1.5.0 = 'system name' + +Functionally similar to: + +| $ snmpinform -v3 -l authPriv -u usr-sha-aes -A authkey1 -X privkey1 \ +| demo.snmplabs.com \ +| 12345 \ +| 1.3.6.1.4.1.20408.4.1.1.2 \ +| '1.3.6.1.2.1.1.1.0' s 'my system' + +"""# from pysnmp.entity.rfc3413.oneliner.ntforg import * -from pysnmp.proto import rfc1902 -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in \ - sendNotification(SnmpEngine(), - UsmUserData('usr-md5-des', 'authkey1', 'privkey1'), - UdpTransportTarget(('localhost', 162)), - ContextData(), - 'inform', - NotificationType( - ObjectIdentity('1.3.6.1.6.3.1.1.5.2') - ).addVarBinds( - ( ObjectType(ObjectIdentity('1.3.6.1.2.1.1.5.0'), - rfc1902.OctetString('system name')) ) - ), - lookupNames=True, lookupValues=True): - # Check for errors and print out results - if errorIndication: - print(errorIndication) - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) - ) - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) +errorIndication, errorStatus, errorIndex, varBinds = next( + sendNotification(SnmpEngine(), + UsmUserData('usr-md5-des', 'authkey1', 'privkey1'), + UdpTransportTarget(('localhost', 162)), + ContextData(), + 'inform', + NotificationType( + ObjectIdentity('1.3.6.1.6.3.1.1.5.2') + ).addVarBinds( + ObjectType(ObjectIdentity('1.3.6.1.2.1.1.5.0'), + 'system name') + )) +) +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/agent/ntforg/trap-async-multiple-transports-and-protocols.py b/examples/v3arch/asyncore/oneliner/agent/ntforg/trap-async-multiple-transports-and-protocols.py new file mode 100644 index 0000000..60c557a --- /dev/null +++ b/examples/v3arch/asyncore/oneliner/agent/ntforg/trap-async-multiple-transports-and-protocols.py @@ -0,0 +1,51 @@ +""" +Multiple concurrent queries ++++++++++++++++++++++++++++ + +Send a bunch of different SNMP Notifications to different peers all at once, +wait for responses asynchronously: + +* SNMPv1 and SNMPv2c +* with community name 'public' +* over IPv4/UDP +* send TRAP notification +* to multiple Managers +* with TRAP ID 'coldStart' specified as a MIB symbol +* include managed object information specified as var-bind objects pair + +"""# +from pysnmp.entity.rfc3413.oneliner.ntforg import * + +# List of targets in the followin format: +# ( ( authData, transportTarget ), ... ) +targets = ( + # 1-st target (SNMPv1 over IPv4/UDP) + ( CommunityData('public', mpModel=0), + UdpTransportTarget(('localhost', 162)), + ContextData() ), + # 2-nd target (SNMPv2c over IPv4/UDP) + ( CommunityData('public'), + UdpTransportTarget(('localhost', 162)), + ContextData() ), +) + +snmpEngine = SnmpEngine() + +ntfOrg = AsyncNotificationOriginator() + +for authData, transportTarget, contextData in targets: + ntfOrg.sendNotification( + snmpEngine, + authData, + transportTarget, + contextData, + 'trap', # NotifyType + NotificationType( + ObjectIdentity('SNMPv2-MIB', 'coldStart') + ).addVarBinds( + ( ObjectName('1.3.6.1.2.1.1.1.0'), + OctetString('my name') ) + ) + ) + +snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/oneliner/agent/ntforg/trap-v1-with-custom-values.py b/examples/v3arch/asyncore/oneliner/agent/ntforg/trap-v1-with-custom-values.py index 1d2b825..85e130b 100644 --- a/examples/v3arch/asyncore/oneliner/agent/ntforg/trap-v1-with-custom-values.py +++ b/examples/v3arch/asyncore/oneliner/agent/ntforg/trap-v1-with-custom-values.py @@ -1,36 +1,50 @@ -# -# Notification Originator -# -# Send SNMP notification using the following options: -# -# * SNMPv1 -# * with community name 'public' -# * over IPv4/UDP -# * send TRAP notification -# * with Generic Trap #6 (enterpriseSpecific) and Specific Trap 432 -# * overriding Uptime value with 12345 -# * overriding Agent Address with '127.0.0.1' -# * overriding Enterprise OID with 1.3.6.1.4.1.20408.4.1.1.2 -# * include managed object information '1.3.6.1.2.1.1.1.0' = 'my system' -# +""" +Custom SNMPv1 TRAP +++++++++++++++++++ + +Send SNMPv1 TRAP through unified SNMPv3 message processing framework. + +Original v1 TRAP fields are mapped into dedicated variable-bindings, +(see `RFC2576 `_) for details. + +* SNMPv1 +* with community name 'public' +* over IPv4/UDP +* send TRAP notification +* with Generic Trap #6 (enterpriseSpecific) and Specific Trap 432 +* overriding Uptime value with 12345 +* overriding Agent Address with '127.0.0.1' +* overriding Enterprise OID with 1.3.6.1.4.1.20408.4.1.1.2 +* include managed object information '1.3.6.1.2.1.1.1.0' = 'my system' + +Functionally similar to: + +| $ snmptrap -v1 -c public demo.snmplabs.com \ +| 1.3.6.1.4.1.20408.4.1.1.2 \ +| 127.0.0.1 \ +| 6 \ +| 432 \ +| 12345 \ +| '1.3.6.1.2.1.1.1.0' s 'my system' + +"""# from pysnmp.entity.rfc3413.oneliner.ntforg import * -from pysnmp.proto import rfc1902 -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in \ - sendNotification(SnmpEngine(), - CommunityData('public', mpModel=0), - UdpTransportTarget(('localhost', 162)), - ContextData(), - 'trap', - NotificationType( - ObjectIdentity('1.3.6.1.4.1.20408.4.1.1.2.0.432'), - ).addVarBinds( - ('1.3.6.1.2.1.1.3.0', 12345), - ('1.3.6.1.6.3.18.1.3.0', '127.0.0.1'), - ('1.3.6.1.6.3.1.1.4.3.0', '1.3.6.1.4.1.20408.4.1.1.2'), - ('1.3.6.1.2.1.1.1.0', rfc1902.OctetString('my system')) - )): - if errorIndication: - print(errorIndication) +errorIndication, errorStatus, errorIndex, varBinds = next( + sendNotification(SnmpEngine(), + CommunityData('public', mpModel=0), + UdpTransportTarget(('localhost', 162)), + ContextData(), + 'trap', + NotificationType( + ObjectIdentity('1.3.6.1.4.1.20408.4.1.1.2.0.432'), + ).addVarBinds( + ('1.3.6.1.2.1.1.3.0', 12345), + ('1.3.6.1.6.3.18.1.3.0', '127.0.0.1'), + ('1.3.6.1.6.3.1.1.4.3.0', '1.3.6.1.4.1.20408.4.1.1.2'), + ('1.3.6.1.2.1.1.1.0', rfc1902.OctetString('my system')) + ) + ) +) +if errorIndication: + print(errorIndication) diff --git a/examples/v3arch/asyncore/oneliner/agent/ntforg/trap-v1-with-default-values.py b/examples/v3arch/asyncore/oneliner/agent/ntforg/trap-v1-with-default-values.py index a704146..5ad5ef7 100644 --- a/examples/v3arch/asyncore/oneliner/agent/ntforg/trap-v1-with-default-values.py +++ b/examples/v3arch/asyncore/oneliner/agent/ntforg/trap-v1-with-default-values.py @@ -1,34 +1,46 @@ -# -# Notification Originator -# -# Send SNMP notification using the following options: -# -# * SNMPv1 -# * with community name 'public' -# * over IPv4/UDP -# * send TRAP notification -# * with Generic Trap #1 (warmStart) and Specific Trap 0 -# * with default Uptime -# * with default Agent Address -# * with Enterprise OID 1.3.6.1.4.1.20408.4.1.1.2 -# * include managed object information '1.3.6.1.2.1.1.1.0' = 'my system' -# +""" +SNMPv1 TRAP with defaults ++++++++++++++++++++++++++ + +Send SNMPv1 TRAP through unified SNMPv3 message processing framework +using the following options: + +* SNMPv1 +* with community name 'public' +* over IPv4/UDP +* send TRAP notification +* with Generic Trap #1 (warmStart) and Specific Trap 0 +* with default Uptime +* with default Agent Address +* with Enterprise OID 1.3.6.1.4.1.20408.4.1.1.2 +* include managed object information '1.3.6.1.2.1.1.1.0' = 'my system' + +Functionally similar to: + +| $ snmptrap -v1 -c public demo.snmplabs.com \ +| 1.3.6.1.4.1.20408.4.1.1.2 \ +| 0.0.0.0 \ +| 1 \ +| 0 \ +| 0 +| '1.3.6.1.2.1.1.1.0' s 'my system' + +"""# from pysnmp.entity.rfc3413.oneliner.ntforg import * -from pysnmp.proto import rfc1902 -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in \ - sendNotification(SnmpEngine(), - CommunityData('public', mpModel=0), - UdpTransportTarget(('localhost', 162)), - ContextData(), - 'trap', - NotificationType( - ObjectIdentity('1.3.6.1.6.3.1.1.5.2') - ).addVarBinds( - ('1.3.6.1.6.3.1.1.4.3.0', '1.3.6.1.4.1.20408.4.1.1.2'), - ('1.3.6.1.2.1.1.1.0', rfc1902.OctetString('my system')) - )): - if errorIndication: - print(errorIndication) +errorIndication, errorStatus, errorIndex, varBinds = next( + sendNotification(SnmpEngine(), + CommunityData('public', mpModel=0), + UdpTransportTarget(('localhost', 162)), + ContextData(), + 'trap', + NotificationType( + ObjectIdentity('1.3.6.1.6.3.1.1.5.2') + ).addVarBinds( + ('1.3.6.1.6.3.1.1.4.3.0', '1.3.6.1.4.1.20408.4.1.1.2'), + ('1.3.6.1.2.1.1.1.0', rfc1902.OctetString('my system')) + ) + ) +) +if errorIndication: + print(errorIndication) diff --git a/examples/v3arch/asyncore/oneliner/agent/ntforg/trap-v2c-with-mib-lookup.py b/examples/v3arch/asyncore/oneliner/agent/ntforg/trap-v2c-with-mib-lookup.py index b243f43..a328a2c 100644 --- a/examples/v3arch/asyncore/oneliner/agent/ntforg/trap-v2c-with-mib-lookup.py +++ b/examples/v3arch/asyncore/oneliner/agent/ntforg/trap-v2c-with-mib-lookup.py @@ -1,27 +1,37 @@ -# -# Notification Originator -# -# Send SNMP notification using the following options: -# -# * SNMPv2c -# * with community name 'public' -# * over IPv4/UDP -# * send TRAP notification -# * with TRAP ID 'coldStart' specified as a MIB symbol -# * include managed object information specified as a MIB symbol -# +""" +SNMPv2c TRAP via NOTIFICATION-TYPE +++++++++++++++++++++++++++++++++++ + +Initialize TRAP message contents from variables specified +in *NOTIFICATION-TYPE* SMI macro. + +* SNMPv2c +* with community name 'public' +* over IPv4/UDP +* send TRAP notification +* with TRAP ID 'coldStart' specified as a MIB symbol +* include managed object information specified as a MIB symbol + +Functionally similar to: + +| $ snmptrap -v2c -c public demo.snmplabs.com \ +| 12345 +| 1.3.6.1.4.1.20408.4.1.1.2 \ + +"""# from pysnmp.entity.rfc3413.oneliner.ntforg import * -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in \ - sendNotification(SnmpEngine(), - CommunityData('public'), - UdpTransportTarget(('localhost', 162)), - ContextData(), - 'trap', - NotificationType( - ObjectIdentity('SNMPv2-MIB', 'coldStart') - )): - if errorIndication: - print(errorIndication) +errorIndication, errorStatus, errorIndex, varBinds = next( + sendNotification(SnmpEngine(), + CommunityData('public'), + UdpTransportTarget(('localhost', 162)), + ContextData(), + 'trap', + NotificationType( + ObjectIdentity('SNMPv2-MIB', 'coldStart') + ) + ) +) + +if errorIndication: + print(errorIndication) diff --git a/examples/v3arch/asyncore/oneliner/agent/ntforg/trap-v3-with-custom-engineid.py b/examples/v3arch/asyncore/oneliner/agent/ntforg/trap-v3-with-custom-engineid.py index bbc9194..f03948f 100644 --- a/examples/v3arch/asyncore/oneliner/agent/ntforg/trap-v3-with-custom-engineid.py +++ b/examples/v3arch/asyncore/oneliner/agent/ntforg/trap-v3-with-custom-engineid.py @@ -1,37 +1,45 @@ -# -# Notification Originator -# -# Send SNMP notification using the following options: -# -# * SNMPv3 -# * with local snmpEngineId = 0x8000000001020304 (must configure at Receiver) -# * with user 'usr-sha-aes128', auth: SHA, priv: AES128 -# * over IPv4/UDP -# * send TRAP notification -# * with TRAP ID 'authenticationFailure' specified as a MIB symbol -# * do not include any additional managed object information -# -# SNMPv3 TRAPs requires pre-sharing the Notification Originator's -# value of SnmpEngineId with Notification Receiver. To facilitate that -# we will use static (e.g. not autogenerated) version of snmpEngineId. -# +""" +SNMPv3 TRAP: auth SHA, privacy: AES128 +++++++++++++++++++++++++++++++++++++++ + +Send SNMP notification using the following options: + +* SNMPv3 +* with local snmpEngineId = 0x8000000001020304 (must configure at Receiver) +* with user 'usr-sha-aes128', auth: SHA, priv: AES128 +* over IPv4/UDP +* send TRAP notification +* with TRAP ID 'authenticationFailure' specified as a MIB symbol +* do not include any additional managed object information + +SNMPv3 TRAPs requires pre-sharing the Notification Originator's +value of SnmpEngineId with Notification Receiver. To facilitate that +we will use static (e.g. not autogenerated) version of snmpEngineId. + +Functionally similar to: + +| $ snmptrap -v3 -l authPriv -u usr-sha-aes -A authkey1 -X privkey1 \ +| -a SHA -x AES \ +| demo.snmplabs.com \ +| 12345 \ +| 1.3.6.1.4.1.20408.4.1.1.2 \ +| '1.3.6.1.2.1.1.1.0' s 'my system' + +"""# from pysnmp.entity.rfc3413.oneliner.ntforg import * -from pysnmp.proto.rfc1902 import OctetString -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in \ - sendNotification(SnmpEngine( - OctetString(hexValue='8000000001020304') - ), - UsmUserData('usr-sha-aes128', 'authkey1', 'privkey1', - authProtocol=usmHMACSHAAuthProtocol, - privProtocol=usmAesCfb128Protocol), - UdpTransportTarget(('localhost', 162)), - ContextData(), - 'trap', - NotificationType( - ObjectIdentity('SNMPv2-MIB', 'authenticationFailure') - )): - if errorIndication: - print(errorIndication) +errorIndication, errorStatus, errorIndex, varBinds = next( + sendNotification(SnmpEngine(OctetString(hexValue='8000000001020304')), + UsmUserData('usr-sha-aes128', 'authkey1', 'privkey1', + authProtocol=usmHMACSHAAuthProtocol, + privProtocol=usmAesCfb128Protocol), + UdpTransportTarget(('localhost', 162)), + ContextData(), + 'trap', + NotificationType( + ObjectIdentity('SNMPv2-MIB', 'authenticationFailure') + ) + ) +) +if errorIndication: + print(errorIndication) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-async-multiple-snmp-engines.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-async-multiple-snmp-engines.py index 85586ed..96ce80f 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-async-multiple-snmp-engines.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-async-multiple-snmp-engines.py @@ -1,52 +1,54 @@ -# -# Asynchronous Command Generator -# -# Send SNMP GET requests using multiple independend SNMP engines -# with the following options: -# -# * with SNMPv1, community 'public' and -# with SNMPv2c, community 'public' and -# with SNMPv3, user 'usr-md5-des', MD5 auth and DES privacy -# * over IPv4/UDP and -# over IPv6/UDP -# * to an Agent at demo.snmplabs.com:161 and -# to an Agent at [::1]:161 -# * for instances of SNMPv2-MIB::sysDescr.0 and -# SNMPv2-MIB::sysLocation.0 MIB objects -# -# Within this script we have a single asynchronous TransportDispatcher -# and a single UDP-based transport serving two independent SNMP engines. -# We use a single instance of AsyncCommandGenerator with each of -# SNMP Engines to comunicate GET command request to remote systems. -# -# When we receive a [response] message from remote system we use -# a custom message router to choose what of the two SNMP engines -# data packet should be handed over. The selection criteria we -# employ here is based on peer's UDP port number. Other selection -# criterias are also possible. -# -from pysnmp.entity.rfc3413.oneliner import cmdgen -from pysnmp.entity import engine +""" +Multiple SNMP engines ++++++++++++++++++++++ + +Send multiple SNMP GET requests to multiple peers using multiple +independend SNMP engines. Deal with peers asynchronously. SNMP options +are: + +* with SNMPv1, community 'public' and + with SNMPv2c, community 'public' and + with SNMPv3, user 'usr-md5-des', MD5 auth and DES privacy +* over IPv4/UDP and + over IPv6/UDP +* to an Agent at demo.snmplabs.com:161 and + to an Agent at [::1]:161 +* for instances of SNMPv2-MIB::sysDescr.0 and + SNMPv2-MIB::sysLocation.0 MIB objects + +Within this script we have a single asynchronous TransportDispatcher +and a single UDP-based transport serving two independent SNMP engines. +We use a single instance of AsyncCommandGenerator with each of +SNMP Engines to comunicate GET command request to remote systems. + +When we receive a [response] message from remote system we use +a custom message router to choose what of the two SNMP engines +data packet should be handed over. The selection criteria we +employ here is based on peer's UDP port number. Other selection +criterias are also possible. + +"""# +from pysnmp.entity.rfc3413.oneliner.cmdgen import * from pysnmp.carrier.asyncore.dispatch import AsyncoreDispatcher -# List of targets in the followin format: +# List of targets in the following format: # ( ( authData, transportTarget, varNames ), ... ) targets = ( # 1-st target (SNMPv1 over IPv4/UDP) - ( cmdgen.CommunityData('public', mpModel=0), - cmdgen.UdpTransportTarget(('demo.snmplabs.com', 161)), - ( cmdgen.ObjectType(cmdgen.ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), - cmdgen.ObjectType(cmdgen.ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0) )) ), + ( CommunityData('public', mpModel=0), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ( ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0) )) ), # 2-nd target (SNMPv2c over IPv4/UDP) - ( cmdgen.CommunityData('public'), - cmdgen.UdpTransportTarget(('demo.snmplabs.com', 1161)), - ( cmdgen.ObjectType(cmdgen.ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), - cmdgen.ObjectType(cmdgen.ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0) )) ), + ( CommunityData('public'), + UdpTransportTarget(('demo.snmplabs.com', 1161)), + ( ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0) )) ), # 3-nd target (SNMPv3 over IPv4/UDP) - ( cmdgen.UsmUserData('usr-md5-des', 'authkey1', 'privkey1'), - cmdgen.UdpTransportTarget(('demo.snmplabs.com', 2161)), - ( cmdgen.ObjectType(cmdgen.ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), - cmdgen.ObjectType(cmdgen.ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0) )) ) + ( UsmUserData('usr-md5-des', 'authkey1', 'privkey1'), + UdpTransportTarget(('demo.snmplabs.com', 2161)), + ( ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0) )) ) # N-th target # ... ) @@ -61,20 +63,16 @@ def cbFun(snmpEngine, sendRequestHandle, errorIndication, if errorIndication: print(errorIndication) return 1 - if errorStatus: + elif errorStatus: print('%s at %s' % ( errorStatus.prettyPrint(), errorIndex and varBinds[int(errorIndex)-1][0] or '?' ) ) return 1 - - for oid, val in varBinds: - if val is None: - print(oid.prettyPrint()) - else: - print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) - + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) # Instantiate the single transport dispatcher object transportDispatcher = AsyncoreDispatcher() @@ -84,19 +82,19 @@ transportDispatcher.registerRoutingCbFun( lambda td,ta,d: ta[1] % 3 and 'A' or 'B' ) -snmpEngineA = engine.SnmpEngine() +snmpEngineA = SnmpEngine() snmpEngineA.registerTransportDispatcher(transportDispatcher, 'A') -snmpEngineB = engine.SnmpEngine() +snmpEngineB = SnmpEngine() snmpEngineB.registerTransportDispatcher(transportDispatcher, 'B') -cmdGen = cmdgen.AsyncCommandGenerator() +cmdGen = AsyncCommandGenerator() for authData, transportTarget, varBinds in targets: snmpEngine = transportTarget.getTransportInfo()[1][1] % 3 and \ snmpEngineA or snmpEngineB cmdGen.getCmd( - snmpEngine, authData, transportTarget, cmdgen.ContextData(), varBinds, + snmpEngine, authData, transportTarget, ContextData(), varBinds, (cbFun, (snmpEngine, authData, transportTarget)) ) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-async-multiple-transports-and-protocols.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-async-multiple-transports-and-protocols.py index e50a54b..f5c0569 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-async-multiple-transports-and-protocols.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-async-multiple-transports-and-protocols.py @@ -1,50 +1,52 @@ -# -# Asynchronous Command Generator -# -# Send a bunch of SNMP GET requests all at once using the following options: -# -# * with SNMPv1, community 'public' and -# with SNMPv2c, community 'public' and -# with SNMPv3, user 'usr-md5-des', MD5 auth and DES privacy -# * over IPv4/UDP and -# over IPv6/UDP -# * to an Agent at demo.snmplabs.com:161 and -# to an Agent at [::1]:161 -# * for instances of SNMPv2-MIB::sysDescr.0 and -# SNMPv2-MIB::sysLocation.0 MIB objects -# -from pysnmp.entity import engine -from pysnmp.entity.rfc3413.oneliner import cmdgen +""" +Multiple concurrent queries ++++++++++++++++++++++++++++ + +Send a bunch of different SNMP GET requests to different peers all at once, +wait for responses asynchronously: + +* with SNMPv1, community 'public' and + with SNMPv2c, community 'public' and + with SNMPv3, user 'usr-md5-des', MD5 auth and DES privacy +* over IPv4/UDP and + over IPv6/UDP +* to an Agent at demo.snmplabs.com:161 and + to an Agent at [::1]:161 +* for instances of SNMPv2-MIB::sysDescr.0 and + SNMPv2-MIB::sysLocation.0 MIB objects + +"""# +from pysnmp.entity.rfc3413.oneliner.cmdgen import * # List of targets in the followin format: # ( ( authData, transportTarget, varNames ), ... ) targets = ( # 1-st target (SNMPv1 over IPv4/UDP) - ( cmdgen.CommunityData('public', mpModel=0), - cmdgen.UdpTransportTarget(('demo.snmplabs.com', 161)), - ( cmdgen.ObjectType(cmdgen.ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), - cmdgen.ObjectType(cmdgen.ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0) )) ), + ( CommunityData('public', mpModel=0), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ( ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0) )) ), # 2-nd target (SNMPv2c over IPv4/UDP) - ( cmdgen.CommunityData('public'), - cmdgen.UdpTransportTarget(('demo.snmplabs.com', 161)), - ( cmdgen.ObjectType(cmdgen.ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), - cmdgen.ObjectType(cmdgen.ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0) )) ), + ( CommunityData('public'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ( ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0) )) ), # 3-nd target (SNMPv2c over IPv4/UDP) - same community and # different transport address. - ( cmdgen.CommunityData('public'), - cmdgen.UdpTransportTarget(('localhost', 161)), - ( cmdgen.ObjectType(cmdgen.ObjectIdentity('SNMPv2-MIB', 'sysContact', 0)), - cmdgen.ObjectType(cmdgen.ObjectIdentity('SNMPv2-MIB', 'sysName', 0))) ), + ( CommunityData('public'), + UdpTransportTarget(('localhost', 161)), + ( ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysContact', 0)), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysName', 0))) ), # 4-nd target (SNMPv3 over IPv4/UDP) - ( cmdgen.UsmUserData('usr-md5-des', 'authkey1', 'privkey1'), - cmdgen.UdpTransportTarget(('demo.snmplabs.com', 161)), - ( cmdgen.ObjectType(cmdgen.ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), - cmdgen.ObjectType(cmdgen.ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0) )) ), + ( UsmUserData('usr-md5-des', 'authkey1', 'privkey1'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ( ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0) )) ), # 5-th target (SNMPv3 over IPv6/UDP) - ( cmdgen.UsmUserData('usr-md5-none', 'authkey1'), - cmdgen.Udp6TransportTarget(('::1', 161)), - ( cmdgen.ObjectType(cmdgen.ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), - cmdgen.ObjectType(cmdgen.ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0) )) ), + ( UsmUserData('usr-md5-none', 'authkey1'), + Udp6TransportTarget(('::1', 161)), + ( ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0) )) ), # N-th target # ... ) @@ -52,36 +54,32 @@ targets = ( # Wait for responses or errors def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx): - (authData, transportTarget) = cbCtx + authData, transportTarget = cbCtx print('%s via %s' % (authData, transportTarget)) if errorIndication: print(errorIndication) - return 1 - if errorStatus: + return True + elif errorStatus: print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' ) ) - return 1 - - for oid, val in varBinds: - if val is None: - print(oid.prettyPrint()) - else: - print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + return True + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) -snmpEngine = engine.SnmpEngine() +snmpEngine = SnmpEngine() -cmdGen = cmdgen.AsyncCommandGenerator() +cmdGen = AsyncCommandGenerator() # Submit GET requests for authData, transportTarget, varNames in targets: cmdGen.getCmd( - snmpEngine, authData, transportTarget, cmdgen.ContextData(), varNames, + snmpEngine, authData, transportTarget, ContextData(), varNames, # User-space callback function and its context - (cbFun, (authData, transportTarget)), - lookupNames=True, lookupValues=True + (cbFun, (authData, transportTarget)) ) snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-threaded-multiple-transports-and-protocols.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-threaded-multiple-transports-and-protocols.py new file mode 100644 index 0000000..47630ea --- /dev/null +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-threaded-multiple-transports-and-protocols.py @@ -0,0 +1,127 @@ +""" +Query Agents from multiple threads +++++++++++++++++++++++++++++++++++ + +Send a bunch of SNMP GET requests simultaneously using the following options: + +* process 5 GET requests in 3 parallel threads +* with SNMPv1, community 'public' and + with SNMPv2c, community 'public' and + with SNMPv3, user 'usr-md5-des', MD5 auth and DES privacy +* over IPv4/UDP and + over IPv6/UDP +* to an Agent at demo.snmplabs.com:161 and + to an Agent at [::1]:161 +* for instances of SNMPv2-MIB::sysDescr.0 and + SNMPv2-MIB::sysLocation.0 MIB objects + +"""# +from sys import version_info +if version_info[0] == 2: + from Queue import Queue +else: + from queue import Queue +from threading import Thread +from pysnmp.entity.rfc3413.oneliner.cmdgen import * + +# List of targets in the followin format: +# ( ( authData, transportTarget, varNames ), ... ) +targets = ( + # 1-st target (SNMPv1 over IPv4/UDP) + ( CommunityData('public', mpModel=0), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ( ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0)))), + # 2-nd target (SNMPv2c over IPv4/UDP) + ( CommunityData('public'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ( ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0)))), + # 3-nd target (SNMPv2c over IPv4/UDP) - same community and + # different transport address. + ( CommunityData('public'), + UdpTransportTarget(('localhost', 161)), + ( ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysContact', 0)), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysName', 0)))), + # 4-nd target (SNMPv3 over IPv4/UDP) + ( UsmUserData('usr-md5-des', 'authkey1', 'privkey1'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ( ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0) ))), + # 5-th target (SNMPv3 over IPv6/UDP) + ( UsmUserData('usr-md5-none', 'authkey1'), + Udp6TransportTarget(('::1', 161)), + ( ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0)))), + # N-th target + # ... +) + +class Worker(Thread): + def __init__(self, requests, responses): + Thread.__init__(self) + self.snmpEngine = SnmpEngine() + self.requests = requests + self.responses = responses + self.setDaemon(True) + self.start() + + def run(self): + while True: + authData, transportTarget, varBinds = self.requests.get() + self.responses.append( + next( + getCmd( + self.snmpEngine, + authData, transportTarget, ContextData(), *varBinds + ) + ) + ) + if hasattr(self.requests, 'task_done'): # 2.5+ + self.requests.task_done() + +class ThreadPool: + def __init__(self, num_threads): + self.requests = Queue(num_threads) + self.responses = [] + for _ in range(num_threads): + Worker(self.requests, self.responses) + + def addRequest(self, authData, transportTarget, varBinds): + self.requests.put((authData, transportTarget, varBinds)) + + def getResponses(self): return self.responses + + def waitCompletion(self): + if hasattr(self.requests, 'join'): + self.requests.join() # 2.5+ + else: + from time import sleep + # this is a lame substitute for missing .join() + # adding an explicit synchronization might be a better solution + while not self.requests.empty(): + sleep(1) + +pool = ThreadPool(3) + +# Submit GET requests +for authData, transportTarget, varBinds in targets: + pool.addRequest(authData, transportTarget, varBinds) + +# Wait for responses or errors +pool.waitCompletion() + +# Walk through responses +for errorIndication, errorStatus, errorIndex, varBinds in pool.getResponses(): + print('Response for %s from %s:' % (authData, transportTarget)) + if errorIndication: + print(errorIndication) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v1.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v1.py index aca4129..2e9c298 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v1.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v1.py @@ -1,35 +1,37 @@ -# -# Command Generator -# -# Send SNMP GET request using the following options: -# -# * with SNMPv1, community 'public' -# * over IPv4/UDP -# * to an Agent at demo.snmplabs.com:161 -# * for two instances of SNMPv2-MIB::sysDescr.0 MIB object, -# * one in label and another in MIB symbol form -# +""" +SNMPv1 +++++++ + +Send SNMP GET request using the following options: + + * with SNMPv1, community 'public' + * over IPv4/UDP + * to an Agent at demo.snmplabs.com:161 + * for two instances of SNMPv2-MIB::sysDescr.0 MIB object, + +Functionally similar to: + +| $ snmpget -v1 -c public demo.snmplabs.com SNMPv2-MIB::sysDescr.0 + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in getCmd(SnmpEngine(), - CommunityData('public', mpModel=0), - UdpTransportTarget(('demo.snmplabs.com', 161)), - ContextData(), - ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), - lookupNames=True, lookupValues=True): - # Check for errors and print out results - if errorIndication: - print(errorIndication) - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) - ) - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) - break +errorIndication, errorStatus, errorIndex, varBinds = next( + getCmd(SnmpEngine(), + CommunityData('public', mpModel=0), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0))) +) + +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v2c-with-custom-timeout-and-retries.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v2c-with-custom-timeout-and-retries.py index d9fc491..1439aeb 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v2c-with-custom-timeout-and-retries.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v2c-with-custom-timeout-and-retries.py @@ -1,49 +1,53 @@ -# -# Command Generator -# -# Send SNMP GET request using the following options: -# -# * with SNMPv2c, community 'public' -# * over IPv4/UDP -# * to an Agent at demo.snmplabs.com:161 -# * for an OID in string form -# * use custom timeout and request retries values -# -# Transport timing settings (maximum number of request retries and -# individual request timeout in seconds) can be set on a per-target basis -# as explained by the code that follows. -# -# Keep in mind that while timeout value can be specified in fractions of a -# second, default pysnmp timer resolution is quite low (about 0.5 sec) -# so there's no much point in using timeouts which is not a multiple of 0.5 -# Internal timer can be programmatically adjusted to finer resolution if needed. -# -# If retries value is set to 0, pysnmp will issue a single request. Even -# if no response arrives, there will be no retry. Likewise, retries=1 -# means one initial request plus one retry. -# +""" +Custom request timeout +++++++++++++++++++++++ + +Send SNMP GET request using the following options: + +* with SNMPv2c, community 'public' +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for an OID in string form +* use custom timeout and request retries values + +Transport timing settings (maximum number of request retries and +individual request timeout in seconds) can be set on a per-target basis +as explained by the code that follows. + +Keep in mind that while timeout value can be specified in fractions of a +second, default pysnmp timer resolution is quite low (about 0.5 sec) +so there's no much point in using timeouts which is not a multiple of 0.5 +Internal timer can be programmatically adjusted to finer resolution if needed. + +If retries value is set to 0, pysnmp will issue a single request. Even +if no response arrives, there will be no retry. Likewise, retries=1 +means one initial request plus one retry. + +Functionally similar to: + +| $ snmpget -v1 -c public demo.snmplabs.com 1.3.6.1.2.1.1.1.0 + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in getCmd(SnmpEngine(), - CommunityData('public'), - UdpTransportTarget( - ('demo.snmplabs.com', 161), timeout=1.5, retries=0 - ), - ContextData(), - ObjectType(ObjectIdentity('1.3.6.1.2.1.1.1.0'))): - # Check for errors and print out results - if errorIndication: - print(errorIndication) - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) - ) - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) - break +errorIndication, errorStatus, errorIndex, varBinds = next( + getCmd(SnmpEngine(), + CommunityData('public'), + UdpTransportTarget( + ('demo.snmplabs.com', 161), timeout=1.5, retries=0 + ), + ContextData(), + ObjectType(ObjectIdentity('1.3.6.1.2.1.1.1.0'))) +) + +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v2c-with-mib-compilation-and-lookup.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v2c-with-mib-compilation-and-lookup.py index fba316f..e994dba 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v2c-with-mib-compilation-and-lookup.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v2c-with-mib-compilation-and-lookup.py @@ -1,37 +1,39 @@ -# -# Command Generator -# -# Send SNMP GET request using the following options: -# -# * with SNMPv2c, community 'public' -# * over IPv4/UDP -# * to an Agent at demo.snmplabs.com:161 -# * for IF-MIB::ifInOctets.1 MIB object -# * Pass attached MIB compiler non-default ASN.1 MIB source -# +""" +Custom ASN.1 MIB path ++++++++++++++++++++++ + +Send SNMP GET request using the following options: + +* with SNMPv2c, community 'public' +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for IF-MIB::ifInOctets.1 MIB object +* pass non-default ASN.1 MIB source to MIB compiler + +Functionally similar to: + +| $ snmpget -v2c -c public -M /usr/share/snmp demo.snmplabs.com \ +| IF-MIB::ifInOctets.1 + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in getCmd(SnmpEngine(), - CommunityData('public'), - UdpTransportTarget(('demo.snmplabs.com', 161)), - ContextData(), - ObjectType( - ObjectIdentity('IF-MIB', 'ifInOctets', 1).addAsn1MibSource('file:///usr/share/snmp', 'http://mibs.snmplabs.com/asn1/@mib@') - ), - lookupNames=True, lookupValues=True): - # Check for errors and print out results - if errorIndication: - print(errorIndication) - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) - ) - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) - break +errorIndication, errorStatus, errorIndex, varBinds = next( + getCmd(SnmpEngine(), + CommunityData('public'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + ObjectType(ObjectIdentity('IF-MIB', 'ifInOctets', 1).addAsn1MibSource('file:///usr/share/snmp', 'http://mibs.snmplabs.com/asn1/@mib@'))) +) + +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v2c.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v2c.py index 5fe5bfe..dcc4ccf 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v2c.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v2c.py @@ -1,34 +1,39 @@ -# -# Command Generator -# -# Send SNMP GET request using the following options: -# -# * with SNMPv2c, community 'public' -# * over IPv4/UDP -# * to an Agent at demo.snmplabs.com:161 -# * for two OIDs in string form -# +""" +SNMPv2c ++++++++ + +Send SNMP GET request using the following options: + +* with SNMPv2c, community 'public' +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for two OIDs in string form + +Functionally similar to: + +| $ snmpget -v2c -c public demo.snmplabs.com 1.3.6.1.2.1.1.1.0 \ +| 1.3.6.1.2.1.1.6.0 + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in getCmd(SnmpEngine(), - CommunityData('public'), - UdpTransportTarget(('demo.snmplabs.com', 161)), - ContextData(), - ObjectType(ObjectIdentity('1.3.6.1.2.1.1.1.0')), - ObjectType(ObjectIdentity('1.3.6.1.2.1.1.6.0'))): - # Check for errors and print out results - if errorIndication: - print(errorIndication) - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) - ) - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) - break +errorIndication, errorStatus, errorIndex, varBinds = next( + getCmd(SnmpEngine(), + CommunityData('public'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + ObjectType(ObjectIdentity('1.3.6.1.2.1.1.1.0')), + ObjectType(ObjectIdentity('1.3.6.1.2.1.1.6.0'))) +) + +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-auth-priv-sha-aes128.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-auth-priv-sha-aes128.py new file mode 100644 index 0000000..85a0399 --- /dev/null +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-auth-priv-sha-aes128.py @@ -0,0 +1,57 @@ +""" +SNMPv3: auth SHA, privacy AES128 +++++++++++++++++++++++++++++++++ + +Send SNMP GET request using the following options: + +* with SNMPv3, user 'usr-sha-aes', SHA authentication, AES128 encryption +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for SNMPv2-MIB::sysDescr.0 MIB object + +Available authentication protocols: + +#. usmHMACMD5AuthProtocol +#. usmHMACSHAAuthProtocol +#. usmNoAuthProtocol + +Available privacy protocols: + +#. usmDESPrivProtocol +#. usm3DESEDEPrivProtocol +#. usmAesCfb128Protocol +#. usmAesCfb192Protocol +#. usmAesCfb256Protocol +#. usmNoPrivProtocol + +Functionally similar to: + +| $ snmpget -v3 -l authPriv -u usr-sha-aes -A authkey1 -X privkey1 \ +| -a SHA -x AES \ +| demo.snmplabs.com \ +| SNMPv2-MIB::sysDescr.0 + +"""# +from pysnmp.entity.rfc3413.oneliner.cmdgen import * + +errorIndication, errorStatus, errorIndex, varBinds = next( + getCmd(SnmpEngine(), + UsmUserData('usr-sha-aes', 'authkey1', 'privkey1', + authProtocol=usmHMACSHAAuthProtocol, + privProtocol=usmAesCfb128Protocol), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0))) +) + +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-auth-priv.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-auth-priv.py new file mode 100644 index 0000000..2c53b29 --- /dev/null +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-auth-priv.py @@ -0,0 +1,39 @@ +""" +SNMPv3: auth MD5, privacy DES ++++++++++++++++++++++++++++++ + +Send SNMP GET request using the following options: + +* with SNMPv3, user 'usr-md5-des', MD5 authentication, DES encryption +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for IF-MIB::ifInOctets.1 MIB object + +Functionally similar to: + +| $ snmpget -v3 -l authPriv -u usr-md5-des -A authkey1 -X privkey1 \ +| demo.snmplabs.com \ +| IF-MIB::ifInOctets.1 + +"""# +from pysnmp.entity.rfc3413.oneliner.cmdgen import * + +errorIndication, errorStatus, errorIndex, varBinds = next( + getCmd(SnmpEngine(), + UsmUserData('usr-md5-des', 'authkey1', 'privkey1'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + ObjectType(ObjectIdentity('IF-MIB', 'ifInOctets', 1))) +) + +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-multiple-calls.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-multiple-calls.py new file mode 100644 index 0000000..116d99f --- /dev/null +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-multiple-calls.py @@ -0,0 +1,47 @@ +""" +Sequence Of GET's ++++++++++++++++++ + +Send two SNMP GET requests in a row using the following options: + +* with SNMPv3, user 'usr-md5-none', MD5 authentication, no privacy +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for IF-MIB::ifInOctets.1 and IF-MIB::ifOutOctets.1 MIB objects + +Use a queue of MIB objects to query. + +The next() call is used to forward Python iterator to the position where it +could consume input + +Functionally similar to: + +| $ snmpget -v3 -l authNoPriv -u usr-md5-none -A authkey1 demo.snmplabs.com \ +| IF-MIB::ifInOctets.1 + +"""# +from pysnmp.entity.rfc3413.oneliner.cmdgen import * + +queue = [ [ ObjectType(ObjectIdentity('IF-MIB', 'ifInOctets', 1)) ], + [ ObjectType(ObjectIdentity('IF-MIB', 'ifOutOctets', 1)) ] ] + +iter = getCmd(SnmpEngine(), + UsmUserData('usr-md5-none', 'authkey1'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData()) + +next(iter) + +while queue: + errorIndication, errorStatus, errorIndex, varBinds = iter.send(queue.pop()) + if errorIndication: + print(errorIndication) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-noauth-nopriv.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-noauth-nopriv.py new file mode 100644 index 0000000..976e0f4 --- /dev/null +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-noauth-nopriv.py @@ -0,0 +1,39 @@ +""" +SNMPv3: no auth, no privacy ++++++++++++++++++++++++++++ + +Send SNMP GET request using the following options: + +* with SNMPv3, user 'usr-none-none', no authentication, no encryption +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for IF-MIB::ifInOctets.1 MIB object + +Functionally similar to: + +| $ snmpget -v3 -l noAuthNoPriv -u usr-none-none +| demo.snmplabs.com \ +| IF-MIB::ifInOctets.1 + +"""# +from pysnmp.entity.rfc3413.oneliner.cmdgen import * + +errorIndication, errorStatus, errorIndex, varBinds = next( + getCmd(SnmpEngine(), + UsmUserData('usr-none-none'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + ObjectType(ObjectIdentity('IF-MIB', 'ifInOctets', 1))) +) + +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-over-ipv6-with-mib-lookup.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-over-ipv6-with-mib-lookup.py index 716d1e9..9499a38 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-over-ipv6-with-mib-lookup.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-over-ipv6-with-mib-lookup.py @@ -1,36 +1,42 @@ -# -# Command Generator -# -# Send SNMP GET request using the following options: -# -# * with SNMPv3 with user 'usr-md5-des', MD5 auth and DES privacy protocols -# * over IPv6/UDP -# * to an Agent at [::1]:161 -# * for three OIDs: one passed as a ObjectIdentity object while others are -# * in string form -# +""" +GET over IPv6 ++++++++++++++ + +Send SNMP GET request using the following options: + +* with SNMPv3 with user 'usr-md5-des', MD5 auth and DES privacy protocols +* over IPv6/UDP +* to an Agent at [::1]:161 +* for three OIDs in string form + +Functionally similar to: + +| $ snmpget -v3 -l authPriv -u usr-md5-des -A authkey1 -X privkey1 \ +| udp6:[::1]:161 \ +| 1.3.6.1.2.1.1.1.0 \ +| 1.3.6.1.2.1.1.2.0 \ +| 1.3.6.1.2.1.1.3.0 +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in getCmd(SnmpEngine(), - UsmUserData('usr-md5-des', 'authkey1', 'privkey1'), - Udp6TransportTarget(('::1', 161)), - ContextData(), - ObjectType(ObjectIdentity('1.3.6.1.2.1.1.1.0')), - ObjectType(ObjectIdentity('1.3.6.1.2.1.1.2.0')), - ObjectType(ObjectIdentity('1.3.6.1.2.1.1.3.0'))): - # Check for errors and print out results - if errorIndication: - print(errorIndication) - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) - ) - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) - break +errorIndication, errorStatus, errorIndex, varBinds = next( + getCmd(SnmpEngine(), + UsmUserData('usr-md5-des', 'authkey1', 'privkey1'), + Udp6TransportTarget(('::1', 161)), + ContextData(), + ObjectType(ObjectIdentity('1.3.6.1.2.1.1.1.0')), + ObjectType(ObjectIdentity('1.3.6.1.2.1.1.2.0')), + ObjectType(ObjectIdentity('1.3.6.1.2.1.1.3.0'))) +) + +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-table-object-by-index.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-table-object-by-index.py index e83e0d2..84b9105 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-table-object-by-index.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-table-object-by-index.py @@ -1,35 +1,41 @@ -# -# Command Generator -# -# Send SNMP GET request using the following options: -# -# * with SNMPv3, user 'usr-none-none', no authentication, no privacy -# * over IPv4/UDP -# * to an Agent at demo.snmplabs.com:161 -# * for IF-MIB::ifInOctets.1 MIB object -# * perform response OIDs and values resolution at MIB -# +""" +GET table row ++++++++++++++ + +Send SNMP GET request using the following options: + +* with SNMPv3, user 'usr-none-none', no authentication, no privacy +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for IF-MIB::ifInOctets.1 and IF-MIB::ifOutOctets.1 MIB object +* perform response OIDs and values resolution at MIB + +Functionally similar to: + +| $ snmpget -v3 -l authPriv -u usr-md5-des -A authkey1 -X privkey1 \ +| demo.snmplabs.com \ +| IF-MIB::ifInOctets.1 IF-MIB::ifOutOctets.1 + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in getCmd(SnmpEngine(), - UsmUserData('usr-none-none'), - UdpTransportTarget(('demo.snmplabs.com', 161)), - ContextData(), - ObjectType(ObjectIdentity('IF-MIB', 'ifInOctets', 1)), - lookupNames=True, lookupValues=True): - # Check for errors and print out results - if errorIndication: - print(errorIndication) - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) - ) - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) - break +errorIndication, errorStatus, errorIndex, varBinds = next( + getCmd(SnmpEngine(), + UsmUserData('usr-none-none'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + ObjectType(ObjectIdentity('IF-MIB', 'ifInOctets', 1)), + ObjectType(ObjectIdentity('IF-MIB', 'ifOutOctets', 1))) +) + +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-table-object-by-multiple-indices.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-table-object-by-multiple-indices.py index 7b78a35..ebc2b0c 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-table-object-by-multiple-indices.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-table-object-by-multiple-indices.py @@ -1,40 +1,46 @@ -# -# Command Generator -# -# Send SNMP GET request using the following options: -# -# * with SNMPv3, user 'usr-sha-aes128', SHA auth, AES128 privacy -# * over IPv4/UDP -# * to an Agent at demo.snmplabs.com:161 -# * for TCP-MIB::tcpConnLocalAddress."0.0.0.0".22."0.0.0.0".0 MIB object -# +""" +Fetch table row by composite index +++++++++++++++++++++++++++++++++++ + +Send SNMP GET request using the following options: + +* with SNMPv3, user 'usr-sha-aes128', SHA auth, AES128 privacy +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for TCP-MIB::tcpConnLocalAddress."0.0.0.0".22."0.0.0.0".0 MIB object + +Functionally similar to: + +| $ snmpget -v3 -l authPriv -u usr-md5-des -A authkey1 -X privkey1 \ +| -a SHA -x AES \ +| demo.snmplabs.com \ +| TCP-MIB::tcpConnLocalAddress."0.0.0.0".22."0.0.0.0".0 + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in getCmd(SnmpEngine(), - UsmUserData('usr-sha-aes128', 'authkey1', 'privkey1', - authProtocol=usmHMACSHAAuthProtocol, - privProtocol=usmAesCfb128Protocol ), - UdpTransportTarget(('demo.snmplabs.com', 161)), - ContextData(), - ObjectType( - ObjectIdentity('TCP-MIB', - 'tcpConnLocalAddress', - '0.0.0.0', 22, - '0.0.0.0', 0) - )): - # Check for errors and print out results - if errorIndication: - print(errorIndication) - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) - ) - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) - break +errorIndication, errorStatus, errorIndex, varBinds = next( + getCmd(SnmpEngine(), + UsmUserData('usr-sha-aes128', 'authkey1', 'privkey1', + authProtocol=usmHMACSHAAuthProtocol, + privProtocol=usmAesCfb128Protocol ), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + ObjectType(ObjectIdentity('TCP-MIB', + 'tcpConnLocalAddress', + '0.0.0.0', 22, + '0.0.0.0', 0)) + ) +) + +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-with-custom-security-name.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-with-custom-security-name.py index 4770c5d..ae5e656 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-with-custom-security-name.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-with-custom-security-name.py @@ -1,40 +1,38 @@ -# -# Command Generator -# -# Send SNMP GET request using the following options: -# -# * with SNMPv3, user 'usr-md5-none', securityName 'myuser' -# MD5 authentication, no privacy -# * over IPv4/UDP -# * to an Agent at demo.snmplabs.com:161 -# * for an OID in text form -# -# The securityName parameter can be thought as an alias to userName and -# allows you to address a USM Table row just as userName does. However -# securityName can be made human-readable, also it is not an index in -# usmUserTable, thus duplicate securityName parameters are possible. -# +""" +Custom SecurityName ++++++++++++++++++++ + +Send SNMP GET request using the following options: + +* with SNMPv3, user 'usr-md5-none', securityName 'myuser' + MD5 authentication, no privacy +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for an OID in text form + +The securityName parameter can be thought as an alias to userName and +allows you to address a USM Table row just as userName does. However +securityName can be made human-readable, also it is not an index in +usmUserTable, thus duplicate securityName parameters are possible. +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in getCmd(SnmpEngine(), - UsmUserData('usr-md5-none', 'authkey1', - securityName='myuser'), - UdpTransportTarget(('demo.snmplabs.com', 161)), - ContextData(), - ObjectType(ObjectIdentity('1.3.6.1.2.1.1.1.0'))): - # Check for errors and print out results - if errorIndication: - print(errorIndication) - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) - ) - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) - break +errorIndication, errorStatus, errorIndex, varBinds = next( + getCmd(SnmpEngine(), + UsmUserData('usr-md5-none', 'authkey1', securityName='myuser'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + ObjectType(ObjectIdentity('1.3.6.1.2.1.1.1.0'))) +) + +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-with-mib-lookup.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-with-mib-lookup.py index c01a61d..6e0d1c5 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-with-mib-lookup.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-with-mib-lookup.py @@ -1,33 +1,38 @@ -# -# Command Generator -# -# Send SNMP GET request using the following options: -# -# * with SNMPv3, user 'usr-md5-none', MD5 authentication, no privacy -# * over IPv4/UDP -# * to an Agent at demo.snmplabs.com:161 -# * for IF-MIB::ifInOctets.1 MIB object -# +""" +SNMPv3: auth MD5, no privacy +++++++++++++++++++++++++++++ + +Send SNMP GET request using the following options: + +* with SNMPv3, user 'usr-md5-none', MD5 authentication, no privacy +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for IF-MIB::ifInOctets.1 MIB object + +Functionally similar to: + +| $ snmpget -v3 -l authNoPriv -u usr-md5-none -A authkey1 demo.snmplabs.com \ +| IF-MIB::ifInOctets.1 + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in getCmd(SnmpEngine(), - UsmUserData('usr-md5-none', 'authkey1'), - UdpTransportTarget(('demo.snmplabs.com', 161)), - ContextData(), - ObjectType(ObjectIdentity('IF-MIB', 'ifInOctets', 1))): - # Check for errors and print out results - if errorIndication: - print(errorIndication) - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) - ) - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) - break +errorIndication, errorStatus, errorIndex, varBinds = next( + getCmd(SnmpEngine(), + UsmUserData('usr-md5-none', 'authkey1'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + ObjectType(ObjectIdentity('IF-MIB', 'ifInOctets', 1))) +) + +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-with-specific-engine-id.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-with-specific-engine-id.py index ca1d1fe..18b3a47 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-with-specific-engine-id.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/get-v3-with-specific-engine-id.py @@ -1,18 +1,23 @@ -# -# Command Generator -# -# Send SNMP GET request using the following scenario and options: -# -# * try to communicate with a SNMPv3 Engine using: -# ** a non-existing user -# ** over IPv4/UDP -# ** to an Agent at demo.snmplabs.com:161 -# * if remote SNMP Engine ID is discovered, send SNMP GET request: -# ** with SNMPv3, user 'usr-md5-none', MD5 authentication, no privacy -# at discovered securityEngineId -# ** to the same SNMP Engine ID -# ** for an OID in text form -# +""" +Discover SNMPv3 SecurityEngineId +++++++++++++++++++++++++++++++++ + +Send SNMP GET request using the following scenario and options: + +* try to communicate with a SNMPv3 Engine using: + +* a non-existing user +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 + +* if remote SNMP Engine ID is discovered, send SNMP GET request: + +* with SNMPv3, user 'usr-md5-none', MD5 authentication, no privacy + at discovered securityEngineId +* to the same SNMP Engine ID +* for an OID in text form + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * snmpEngine = SnmpEngine() @@ -38,10 +43,10 @@ snmpEngine.observer.registerObserver( authData = UsmUserData('non-existing-user') -for errorIndication, errorStatus, errorIndex, \ - varBinds in getCmd(snmpEngine, authData, - transportTarget, ContextData()): - break +errorIndication, errorStatus, errorIndex, varBinds = next( + getCmd(snmpEngine, authData, transportTarget, ContextData(), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0))) +) # See if our SNMP engine received REPORT PDU containing securityEngineId @@ -60,22 +65,22 @@ print('Remote securityEngineId = %s' % securityEngineId.prettyPrint()) authData = UsmUserData('usr-md5-none', 'authkey1', securityEngineId=securityEngineId) -for errorIndication, errorStatus, errorIndex, \ - varBinds in getCmd(snmpEngine, authData, \ - transportTarget, ContextData(), \ - ObjectType(ObjectIdentity('1.3.6.1.2.1.1.1.0'))): - break +errorIndication, errorStatus, errorIndex, varBinds = next( + getCmd(snmpEngine, + authData, + transportTarget, + ContextData(), + ObjectType(ObjectIdentity('1.3.6.1.2.1.1.1.0'))) +) -# Check for errors and print out results if errorIndication: print(errorIndication) -else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' ) - else: - for name, val in varBinds: - print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) + ) +else: + for name, val in varBinds: + print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getbulk-v2c-limiting-number-of-rows.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getbulk-v2c-limiting-number-of-rows.py new file mode 100644 index 0000000..ac4887a --- /dev/null +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getbulk-v2c-limiting-number-of-rows.py @@ -0,0 +1,47 @@ +""" +Walk MIB, limit number of response rows ++++++++++++++++++++++++++++++++++++++++ + +Send a series of SNMP GETBULK requests using the following options: + +* with SNMPv2c, community 'public' +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* with values non-repeaters = 0, max-repetitions = 25 +* for two OIDs in string form +* stop when response OIDs leave the scopes of initial OIDs OR + number of response rows reach fixed value (20) + +Functionally similar to: + +| $ snmpbulkwalk -v2c -c public demo.snmplabs.com \ +| -Cn0 -Cr25 \ +| 1.3.6.1.2.1.2.2 1.3.6.1.2.1.2.3 + +"""# +from pysnmp.entity.rfc3413.oneliner.cmdgen import * + +for errorIndication, \ + errorStatus, errorIndex, \ + varBinds in bulkCmd(SnmpEngine(), + CommunityData('public'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + 0, 25, + ObjectType(ObjectIdentity('1.3.6.1.2.1.2.2')), + ObjectType(ObjectIdentity('1.3.6.1.2.1.2.3')), + lexicographicMode=False, maxRows=20): + + if errorIndication: + print(errorIndication) + break + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + break + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getbulk-v2c.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getbulk-v2c.py index 0bed0f0..bf167e4 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getbulk-v2c.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getbulk-v2c.py @@ -1,15 +1,23 @@ -# -# Command Generator -# -# Send SNMP GETBULK request using the following options: -# -# * with SNMPv2c, community 'public' -# * over IPv4/UDP -# * to an Agent at demo.snmplabs.com:161 -# * with values non-repeaters = 0, max-repetitions = 25 -# * for two OIDs in string form -# * stop when response OIDs leave the scopes of initial OIDs -# +""" +Bulk walk MIB ++++++++++++++ + +Send a series of SNMP GETBULK requests using the following options: + +* with SNMPv2c, community 'public' +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* with values non-repeaters = 0, max-repetitions = 25 +* for two OIDs in string form +* stop when response OIDs leave the scopes of initial OIDs + +Functionally similar to: + +| $ snmpbulkwalk -v2c -c public demo.snmplabs.com \ +| -Cn0 -Cr25 \ +| 1.3.6.1.2.1.2.2 1.3.6.1.2.1.2.3 + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * for errorIndication, \ @@ -20,19 +28,19 @@ for errorIndication, \ ContextData(), 0, 25, ObjectType(ObjectIdentity('1.3.6.1.2.1.2.2')), - ObjectType(ObjectIdentity('1.3.6.1.2.1.2.3'))): - # Check for errors and print out results + ObjectType(ObjectIdentity('1.3.6.1.2.1.2.3')), + lexicographicMode=False): + if errorIndication: print(errorIndication) break - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' ) - break - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) + ) + break + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getbulk-v3-limiting-number-of-packets.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getbulk-v3-limiting-number-of-packets.py new file mode 100644 index 0000000..4cb303e --- /dev/null +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getbulk-v3-limiting-number-of-packets.py @@ -0,0 +1,44 @@ +""" +Walk Agent, limit number of packets ++++++++++++++++++++++++++++++++++++ + +Send a series of SNMP GETBULK requests using the following options: + +* with SNMPv3, user 'usr-none-none', no authentication, no privacy +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for all OIDs past SNMPv2-MIB::system +* run till end-of-mib condition is reported by Agent OR + maxCalls == 10 request-response interactions occur + +Functionally similar to: + +| $ snmpbulkwalk -v3 -lnoAuthNoPriv -u usr-none-none -Cn0 -Cr50 \ +| demo.snmplabs.com SNMPv2-MIB::system + +"""# +from pysnmp.entity.rfc3413.oneliner.cmdgen import * + +for errorIndication, \ + errorStatus, errorIndex, \ + varBinds in bulkCmd(SnmpEngine(), + UsmUserData('usr-none-none'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + 0, 50, + ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')), + maxCalls=10): + + if errorIndication: + print(errorIndication) + break + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) + break + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getbulk-v3-over-ipv6-with-mib-lookup.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getbulk-v3-over-ipv6-with-mib-lookup.py index 9b255f3..6a09a13 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getbulk-v3-over-ipv6-with-mib-lookup.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getbulk-v3-over-ipv6-with-mib-lookup.py @@ -1,16 +1,25 @@ -# -# Command Generator -# -# Send SNMP GETBULK request using the following options: -# -# * with SNMPv3 with user 'usr-md5-des', MD5 auth and DES privacy protocols -# * over IPv6/UDP -# * to an Agent at [::1]:161 -# * with values non-repeaters = 1, max-repetitions = 25 -# * for IP-MIB::ipAdEntAddr and all columns of the IF-MIB::ifEntry table -# * stop when response OIDs leave the scopes of the table OR maxRows == 20 -# * perform response OIDs and values resolution at MIB -# +""" +Fetch scalar and table variables +++++++++++++++++++++++++++++++++ + +Send a series of SNMP GETBULK requests using the following options: + +* with SNMPv3 with user 'usr-md5-des', MD5 auth and DES privacy protocols +* over IPv6/UDP +* to an Agent at [::1]:161 +* with values non-repeaters = 1, max-repetitions = 25 +* for IP-MIB::ipAdEntAddr and all columns of the IF-MIB::ifEntry table +* stop when response OIDs leave the scopes of the table + +Functionally similar to: + +| $ snmpbulkwalk -v3 -lauthPriv -u usr-md5-none -A authkey1 -X privkey1 \ +| -Cn1, -Cr25 \ +| demo.snmplabs.com \ +| IP-MIB::ipAdEntAddr \ +| IP-MIB::ipAddrEntry + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * for errorIndication, \ @@ -22,19 +31,18 @@ for errorIndication, \ 1, 25, ObjectType(ObjectIdentity('IP-MIB', 'ipAdEntAddr')), ObjectType(ObjectIdentity('IP-MIB', 'ipAddrEntry')), - lookupNames=True, lookupValues=True, maxRows=20): - # Check for errors and print out results + lexicographicMode=False): + if errorIndication: print(errorIndication) break - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' ) - break - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) + ) + break + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getbulk-v3-with-custom-mib-path-and-options.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getbulk-v3-with-custom-mib-path-and-options.py index 5d1eb81..9c97465 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getbulk-v3-with-custom-mib-path-and-options.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getbulk-v3-with-custom-mib-path-and-options.py @@ -1,17 +1,23 @@ -# -# Command Generator -# -# Send SNMP GETBULK request using the following options: -# -# * with SNMPv3, user 'usr-none-none', no authentication, no privacy -# * over IPv4/UDP -# * to an Agent at demo.snmplabs.com:161 -# * for all OIDs past TCP-MIB::tcpConnTable -# * TCP-MIB will be searched by a user-specified path -# * run till end-of-mib condition is reported by Agent OR maxRows == 100 OR -# maxCalls == 10 request-response interactions occur -# * ignoring non-increasing OIDs whenever reported by Agent -# +""" +Custom PySNMP MIBs location ++++++++++++++++++++++++++++ + +Send a series of SNMP GETBULK requests using the following options: + +* with SNMPv3, user 'usr-none-none', no authentication, no privacy +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for all OIDs within TCP-MIB::tcpConnTable column +* TCP-MIB Python module will be searched by a user-specified filesystem + path (/opt/mib/pysnmp) and in Python package (python_packaged_mibs) + which should be in sys.path + +Functionally similar to: + +| $ snmpbulkwalk -v3 -lnoAuthNoPriv -u usr-none-none -Cn0 -Cr50 \ +| demo.snmplabs.com TCP-MIB::tcpConnTable + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * for errorIndication, \ @@ -21,22 +27,19 @@ for errorIndication, \ UdpTransportTarget(('demo.snmplabs.com', 161)), ContextData(), 0, 50, - ObjectType(ObjectIdentity('TCP-MIB', 'tcpConnTable').addMibSource('/tmp/mibs')), - maxRows=100, maxCalls=10, - lexicographicMode=True, - ignoreNonIncreasingOid=True): - # Check for errors and print out results + ObjectType(ObjectIdentity('TCP-MIB', 'tcpConnTable').addMibSource('/opt/mibs/pysnmp').addMibSource('python_packaged_mibs')), + lexicographicMode=False): + if errorIndication: print(errorIndication) break - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' ) - break - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) + ) + break + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-async-multiple-transports-and-protocols.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-async-multiple-transports-and-protocols.py index b1304ae..a77dc49 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-async-multiple-transports-and-protocols.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-async-multiple-transports-and-protocols.py @@ -1,40 +1,42 @@ -## -# Asynchronous Command Generator -# -# Send a bunch of SNMP GETNEXT requests all at once using the following options: -# -# * with SNMPv1, community 'public' and -# with SNMPv2c, community 'public' and -# with SNMPv3, user 'usr-md5-des', MD5 auth and DES privacy -# * over IPv4/UDP and -# over IPv6/UDP -# * to an Agent at demo.snmplabs.com:161 and -# to an Agent at [::1]:161 -# * for multiple MIB subtrees and tables -# -from pysnmp.entity import engine -from pysnmp.entity.rfc3413.oneliner import cmdgen +""" +Walk multiple Agents at once +++++++++++++++++++++++++++++ + +Iterate over MIBs of multiple SNMP Agents asynchronously using the +following options: + +* with SNMPv1, community 'public' and + with SNMPv2c, community 'public' and + with SNMPv3, user 'usr-md5-des', MD5 auth and DES privacy +* over IPv4/UDP and + over IPv6/UDP +* to an Agent at demo.snmplabs.com:161 and + to an Agent at [::1]:161 +* for multiple MIB subtrees and tables + +"""# +from pysnmp.entity.rfc3413.oneliner.cmdgen import * # List of targets in the followin format: # ( ( authData, transportTarget, varNames ), ... ) targets = ( # 1-st target (SNMPv1 over IPv4/UDP) - ( cmdgen.CommunityData('public', mpModel=0), - cmdgen.UdpTransportTarget(('demo.snmplabs.com', 161)), - ( cmdgen.ObjectType(cmdgen.ObjectIdentity('1.3.6.1.2.1')), - cmdgen.ObjectType(cmdgen.ObjectIdentity('1.3.6.1.3.1')) ) ), + ( CommunityData('public', mpModel=0), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ( ObjectType(ObjectIdentity('1.3.6.1.2.1')), + ObjectType(ObjectIdentity('1.3.6.1.3.1')) ) ), # 2-nd target (SNMPv2c over IPv4/UDP) - ( cmdgen.CommunityData('public'), - cmdgen.UdpTransportTarget(('demo.snmplabs.com', 161)), - ( cmdgen.ObjectType(cmdgen.ObjectIdentity('1.3.6.1.4.1')), ) ), + ( CommunityData('public'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ( ObjectType(ObjectIdentity('1.3.6.1.4.1')), ) ), # 3-nd target (SNMPv3 over IPv4/UDP) - ( cmdgen.UsmUserData('usr-md5-des', 'authkey1', 'privkey1'), - cmdgen.UdpTransportTarget(('demo.snmplabs.com', 161)), - ( cmdgen.ObjectType(cmdgen.ObjectIdentity('SNMPv2-MIB', 'system')), ) ), + ( UsmUserData('usr-md5-des', 'authkey1', 'privkey1'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ( ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')), ) ), # 4-th target (SNMPv3 over IPv6/UDP) - ( cmdgen.UsmUserData('usr-md5-none', 'authkey1'), - cmdgen.Udp6TransportTarget(('::1', 161)), - ( cmdgen.ObjectType(cmdgen.ObjectIdentity('IF-MIB', 'ifTable')), ) ) + ( UsmUserData('usr-md5-none', 'authkey1'), + Udp6TransportTarget(('::1', 161)), + ( ObjectType(ObjectIdentity('IF-MIB', 'ifTable')), ) ) # N-th target # ... ) @@ -47,44 +49,38 @@ def cbFun(snmpEngine, sendRequestHandle, errorIndication, if errorIndication: print(errorIndication) return - if errorStatus: + elif errorStatus: print('%s at %s' % ( errorStatus.prettyPrint(), errorIndex and varBindTable[-1][int(errorIndex)-1][0] or '?' ) ) return - varBindTableRow = varBindTable[-1] - for idx in range(len(varBindTableRow)): - name, val = varBindTableRow[idx] - if val is not None and varBindHead[idx] <= name: - # still in table - break else: - print('went out of table at %s' % (name, )) - return + for idx, varBind in enumerate(varBindTable[-1]): + if varBind[1] is not None and varBindHead[idx] <= varBind[0]: + break # still in table + else: + print('went out of table at %s' % (name, )) + return - for varBindRow in varBindTable: - for oid, val in varBindRow: - if val is None: - print(oid.prettyPrint()) - else: - print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) + for varBindRow in varBindTable: + for varBind in varBindRow: + print(' = '.join([ x.prettyPrint() for x in varBind ])) - return True # continue table retrieval + return True # continue table retrieval -snmpEngine = engine.SnmpEngine() +snmpEngine = SnmpEngine() -cmdGen = cmdgen.AsyncCommandGenerator() +cmdGen = AsyncCommandGenerator() # Submit initial GETNEXT requests and wait for responses for authData, transportTarget, varBinds in targets: varBindHead = [ x[0] for x in cmdGen.makeVarBinds(snmpEngine, varBinds ) ] cmdGen.nextCmd( - snmpEngine, authData, transportTarget, cmdgen.ContextData(), varBinds, + snmpEngine, authData, transportTarget, ContextData(), varBinds, # User-space callback function and its context - (cbFun, (varBindHead, authData, transportTarget)), - lookupNames=True, lookupValues=True + (cbFun, (varBindHead, authData, transportTarget)) ) snmpEngine.transportDispatcher.runDispatcher() diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v1-with-custom-mibs-location.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v1-with-custom-mibs-location.py index 0367eb3..1d459ef 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v1-with-custom-mibs-location.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v1-with-custom-mibs-location.py @@ -1,29 +1,33 @@ -# -# GETNEXT Command Generator Application -# -# Perform SNMP GETNEXT operation with the following options: -# -# with SNMPv1, community 'public' -# over IPv4/UDP -# to an Agent at demo.snmplabs.com:161 -# two columns of the IF-MIB::ifEntry table -# search for pysnmp MIBs at specific filesystem location -# stop when response OIDs leave the scopes of initial OIDs -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpwalk -v1 -c public -ObentU demo.snmplabs.com IF-MIB::ifDescr IF-MIB::ifType -# -# The pysnmp engine maintains its own MIB search path which is usued -# for searching for MIB modules by name. By default pysnmp will search -# its built-in MIB repository (pysnmp.smi.mibs.instances, pysnmp.smi.mibs) -# and pysnmp-mibs package (pysnmp_mibs). Those two entries are normally -# found relative to $PYTHONPATH. Besides searching MIBs as Python modules -# (which could be egg-ed or not), pysnmp can also search for stand-alone -# files in given directories. The latter could be specified by -# ObjectIdentity.addMibSource() calls. New search path entries are added -# in front of existing ones in search path. -# +""" +Search PySNMP MIBs at custom location ++++++++++++++++++++++++++++++++++++++ + +Perform SNMP GETNEXT operation and resolve received var-binds with +PySNMP MIB(s) found at a custom location. Use the following SNMP options: + +* with SNMPv1, community 'public' +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* two columns of the IF-MIB::ifEntry table +* search for pysnmp MIBs at specific filesystem location +* stop when response OIDs leave the scopes of initial OIDs + +The pysnmp engine maintains its own MIB search path which is used +for searching for MIB modules by name. By default pysnmp will search +its built-in MIB repository (pysnmp.smi.mibs.instances, pysnmp.smi.mibs) +and pysnmp-mibs package (pysnmp_mibs). Those two entries are normally +found relative to $PYTHONPATH. Besides searching MIBs as Python modules +(which could be egg-ed or not), pysnmp can also search for stand-alone +files in given directories. The latter could be specified by +ObjectIdentity.addMibSource() calls. New search path entries are added +in front of existing ones in search path. + +Functionally similar to: + +| $ snmpwalk -v1 -c public -ObentU demo.snmplabs.com \ +| IF-MIB::ifDescr IF-MIB::ifType + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * for errorIndication, \ @@ -34,19 +38,18 @@ for errorIndication, \ ContextData(), ObjectType(ObjectIdentity('IF-MIB', 'ifDescr').addMibSource('/tmp/mymibs')), ObjectType(ObjectIdentity('IF-MIB', 'ifType')), - lookupNames=True, lookupValues=True): - # Check for errors and print out results + lexicographicMode=False): + if errorIndication: print(errorIndication) break - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' ) - break - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) + ) + break + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v1.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v1.py index 1c3a998..7530a39 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v1.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v1.py @@ -1,18 +1,31 @@ -# -# Command Generator -# -# Send SNMP GETNEXT request using the following options: -# -# * with SNMPv1, community 'public' -# * over IPv4/UDP -# * to an Agent at demo.snmplabs.com:161 -# * for some columns of the IF-MIB::ifEntry table -# * stop when response OIDs leave the scopes of initial OIDs -# +""" +Fetch whole SNMP table +++++++++++++++++++++++ + +Send a series of SNMP GETNEXT requests using the following options: + +* with SNMPv1, community 'public' +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for some columns of the IF-MIB::ifEntry table +* stop when response OIDs leave the scopes of initial OIDs + +Functionally similar to: + +| $ snmpwalk -v1 -c public demo.snmplabs.com \ +| IF-MIB::ifDescr \ +| IF-MIB::ifType \ +| IF-MIB::ifMtu \ +| IF-MIB::ifSpeed \ +| IF-MIB::ifPhysAddress \ +| IF-MIB::ifType \ + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * for errorIndication, \ - errorStatus, errorIndex, \ + errorStatus, \ + errorIndex, \ varBinds in nextCmd(SnmpEngine(), CommunityData('public', mpModel=0), UdpTransportTarget(('demo.snmplabs.com', 161)), @@ -22,19 +35,19 @@ for errorIndication, \ ObjectType(ObjectIdentity('IF-MIB', 'ifMtu')), ObjectType(ObjectIdentity('IF-MIB', 'ifSpeed')), ObjectType(ObjectIdentity('IF-MIB', 'ifPhysAddress')), - ObjectType(ObjectIdentity('IF-MIB', 'ifType'))): - # Check for errors and print out results + ObjectType(ObjectIdentity('IF-MIB', 'ifType')), + lexicographicMode=False): + if errorIndication: print(errorIndication) break - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' ) - break - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) + ) + break + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v2c-with-mib-resolution.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v2c-with-mib-resolution.py index e59b07b..a79fefb 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v2c-with-mib-resolution.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v2c-with-mib-resolution.py @@ -1,25 +1,24 @@ -# -# GETNEXT Command Generator Application -# -# Perform SNMP GETNEXT operation with the following options: -# -# * with SNMPv2c, community 'public' -# * over IPv4/UDP -# * to an Agent at demo.snmplabs.com:161 -# * for an OID in string form -# * resolve response OIDs and values into human-freidly form -# * stop when response OIDs leave the scopes of initial OIDs -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpwalk -v2c -c public demo.snmplabs.com 1.3.6.1.2.1.1 -# -# The lookupNames and lookupValues keyword arguments will make pysnmp -# trying to resolve OIDs and values, in response variable-bindings, -# into human-friendly form. If response OIDs do not belong to any of -# currently loaded MIBs, unresolved OIDs and values will still be -# returned. -# +""" +Waive MIB lookup +++++++++++++++++ + +Perform SNMP GETNEXT operation with the following options: + +* with SNMPv2c, community 'public' +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for an OID in string form +* do not resolve response OIDs and values into human-freidly form + +False lookupNames and lookupValues keyword arguments could make pysnmp +waiving OIDs and values resolution in response variable-bindings, +into human-friendly form. + +Functionally similar to: + +| $ snmpwalk -v2c -c public -ObentU demo.snmplabs.com 1.3.6.1.2.1 + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * for errorIndication, \ @@ -29,19 +28,18 @@ for errorIndication, \ UdpTransportTarget(('demo.snmplabs.com', 161)), ContextData(), ObjectType(ObjectIdentity('1.3.6.1.2.1.1')), - lookupNames=True, lookupValues=True): - # Check for errors and print out results + lookupMib=False): + if errorIndication: print(errorIndication) break - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' ) - break - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) + ) + break + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v2c.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v2c.py index 178cd09..514a6ce 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v2c.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v2c.py @@ -1,14 +1,21 @@ -# -# Command Generator -# -# Send SNMP GETNEXT requests using the following options: -# -# * with SNMPv2c, community 'public' -# * over IPv4/UDP -# * to an Agent at demo.snmplabs.com:161 -# * for two OIDs in string form -# * stop when response OIDs leave the scopes of initial OIDs -# +""" +Fetch two OID branches +++++++++++++++++++++++ + +Send a series of SNMP GETNEXT requests using the following options: + +* with SNMPv2c, community 'public' +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for two OIDs in string form +* stop when response OIDs leave the scopes of initial OIDs + +Functionally similar to: + +| $ snmpwalk -v2c -c public demo.snmplabs.com \ +| 1.3.6.1.2.1.2.2.1.2 1.3.6.1.2.1.2.2.1.3 + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * for errorIndication, \ @@ -18,19 +25,19 @@ for errorIndication, \ UdpTransportTarget(('demo.snmplabs.com', 161)), ContextData(), ObjectType(ObjectIdentity('1.3.6.1.2.1.2.2.1.2')), - ObjectType(ObjectIdentity('1.3.6.1.2.1.2.2.1.3'))): - # Check for errors and print out results + ObjectType(ObjectIdentity('1.3.6.1.2.1.2.2.1.3')), + lexicographicMode=False): + if errorIndication: print(errorIndication) break - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' ) - break - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) + ) + break + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v3-over-ipv6-with-mib-lookup.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v3-over-ipv6-with-mib-lookup.py index 01c74be..4a0877d 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v3-over-ipv6-with-mib-lookup.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v3-over-ipv6-with-mib-lookup.py @@ -1,17 +1,23 @@ -# -# Command Generator -# -# Send SNMP GETNEXT requests using the following options: -# -# * with SNMPv3 with user 'usr-md5-des', MD5 auth and DES privacy protocols -# * over IPv6/UDP -# * to an Agent at [::1]:161 -# * for all columns of the IF-MIB::ifEntry table -# * stop when response OIDs leave the scopes of the table -# * perform response OIDs and values resolution at MIB -# -# make sure IF-MIB.py is in search path -# +""" +Preload PySNMP MIBs ++++++++++++++++++++ + +Send a series of SNMP GETNEXT requests using the following options: + +* with SNMPv3 with user 'usr-md5-des', MD5 auth and DES privacy protocols +* over IPv6/UDP +* to an Agent at [::1]:161 +* for all OIDs starting from 1.3.6 +* preload all Python MIB modules found in search path + +Functionally similar to: + +| $ snmpwalk -v3 -l authPriv -u usr-md5-des -A authkey1 -X privkey1 \ +| -m ALL +| udp6:[::1]:161 \ +| 1.3.6 + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * for errorIndication, \ @@ -20,20 +26,18 @@ for errorIndication, \ UsmUserData('usr-md5-des', 'authkey1', 'privkey1'), Udp6TransportTarget(('::1', 161)), ContextData(), - ObjectType(ObjectIdentity('IF-MIB', 'ifEntry')), - lookupNames=True, lookupValues=True): - # Check for errors and print out results + ObjectType(ObjectIdentity('1.3.6').loadMibs())): + if errorIndication: print(errorIndication) break - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' ) - break - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) + ) + break + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v3-pull-whole-mib-with-mib-lookup.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v3-pull-whole-mib-with-mib-lookup.py index 658f6fc..4c0568a 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v3-pull-whole-mib-with-mib-lookup.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v3-pull-whole-mib-with-mib-lookup.py @@ -1,15 +1,21 @@ -# -# Command Generator -# -# Send SNMP GETNEXT requests using the following options: -# -# * with SNMPv3, user 'usr-md5-none', MD5 authentication, no privacy -# * over IPv4/UDP -# * to an Agent at demo.snmplabs.com:161 -# * for all OIDs in IF-MIB -# * stop when response OIDs leave the scopes of the table -# * perform response values resolution at MIB -# +""" +Walk whole MIB +++++++++++++++ + +Send a series of SNMP GETNEXT requests using the following options: + +* with SNMPv3, user 'usr-md5-none', MD5 authentication, no privacy +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* for all OIDs in IF-MIB +* stop when response OIDs leave the scopes of the table + +Functionally similar to: + +| $ snmpwalk -v3 -lauthPriv -u usr-md5-none -A authkey1 -X privkey1 \ +| demo.snmplabs.com IF-MIB:: + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * for errorIndication, \ @@ -18,20 +24,19 @@ for errorIndication, \ UsmUserData('usr-md5-none', 'authkey1'), UdpTransportTarget(('demo.snmplabs.com', 161)), ContextData(), - ObjectType(ObjectIdentity('IF-MIB', '')), - lookupValues=True): - # Check for errors and print out results + ObjectType(ObjectIdentity('IF-MIB')), + lexicographicMode=False): + if errorIndication: print(errorIndication) break - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' ) - break - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) + ) + break + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v3-pull-whole-mib-with-options.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v3-pull-whole-mib-with-options.py index 99eba51..19d7950 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v3-pull-whole-mib-with-options.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/getnext-v3-pull-whole-mib-with-options.py @@ -1,17 +1,23 @@ -# -# Command Generator -# -# Send SNMP GETNEXT requests using the following options: -# -# * with SNMPv3, user 'usr-sha-aes128', SHA auth, AES128 privacy -# * over Local Domain Sockets -# * to an Agent at demo.snmplabs.com:161 -# * for all OIDs past IF-MIB (load up all MIBs in search path) -# * run till end-of-mib condition is reported by Agent OR maxRows == 100 -# * ignoring non-increasing OIDs whenever reported by Agent -# -# make sure IF-MIB.py is search path -# +""" +Fetch fixed amount of MIB variables ++++++++++++++++++++++++++++++++++++ + +Send a series of SNMP GETNEXT requests using the following options: + +* with SNMPv3, user 'usr-sha-aes128', SHA auth, AES128 privacy +* over UDP/IPv4 +* to an Agent at demo.snmplabs.com:161 +* for all OIDs past SNMPv2-MIB +* run till end-of-mib condition is reported by Agent OR maxRows == 100 +* ignoring non-increasing OIDs whenever reported by Agent + +Functionally similar to: + +| $ snmpwalk -v3 -lauthPriv -u usr-sha-aes128 -A authkey1 -X privkey1 \ +| -a MD5 -x AES demo.snmplabs.com \ +| SNMPv2-MIB::system + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * for errorIndication, \ @@ -22,21 +28,19 @@ for errorIndication, \ privProtocol=usmAesCfb128Protocol), UdpTransportTarget(('demo.snmplabs.com', 161)), ContextData(), - ObjectType(ObjectIdentity('IF-MIB', '').loadMibs()), - lexicographicMode=True, maxRows=100, - ignoreNonIncreasingOid=True): - # Check for errors and print out results + ObjectType(ObjectIdentity('SNMPv2-MIB')), + maxRows=100, ignoreNonIncreasingOid=True): + if errorIndication: print(errorIndication) break - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) + elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' ) - break - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) + ) + break + else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/set-v1-multiple-values.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/set-v1-multiple-values.py index bba4a84..9b9fae7 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/set-v1-multiple-values.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/set-v1-multiple-values.py @@ -1,36 +1,49 @@ -# -# Command Generator -# -# Send SNMP SET request using the following options: -# -# * with SNMPv1, community 'public' -# * over IPv4/UDP -# * to an Agent at demo.snmplabs.com:161 -# * setting two OIDs to new values (types explicitly specified) -# +""" +SET scalars values +++++++++++++++++++ + +Send SNMP SET request using the following options: + +* with SNMPv1, community 'public' +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* setting three var-bindings to new values + +Please note, that in this example MIB lookup is only used +for the second var-bindins. For the rest, value types are +inferred from passed objects. + +Functionally similar to: + +| $ snmpset -v1 -c public demo.snmplabs.com \ +| 1.3.6.1.2.1.1.9.1.2.1 o 1.3.6.1.4.1.20408.1.1 \ +| 1.3.6.1.2.1.1.9.1.2.1 = 1.3.6.1.4.1.20408.1.1 \ +| 1.3.6.1.2.1.1.9.1.3.1 s "new system name" + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * -from pysnmp.proto import rfc1902 - -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in setCmd(SnmpEngine(), - CommunityData('public', mpModel=0), - UdpTransportTarget(('demo.snmplabs.com', 161)), - ContextData(), - ('1.3.6.1.2.1.1.9.1.2.1', rfc1902.ObjectName('1.3.6.1.4.1.20408.1.1')), - ('1.3.6.1.2.1.1.9.1.2.1', '1.3.6.1.4.1.20408.1.1'), - ('1.3.6.1.2.1.1.9.1.3.1', rfc1902.OctetString('new system name'))): - # Check for errors and print out results - if errorIndication: - print(errorIndication) - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) - ) - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) - break + +errorIndication, errorStatus, errorIndex, varBinds = next( + setCmd(SnmpEngine(), + CommunityData('public', mpModel=0), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + ObjectType(ObjectIdentity('1.3.6.1.2.1.1.9.1.2.1'), + ObjectIdentifier('1.3.6.1.4.1.20408.1.1')), + ObjectType(ObjectIdentity('1.3.6.1.2.1.1.9.1.2.1'), + '1.3.6.1.4.1.20408.1.1'), + ObjectType(ObjectIdentity('1.3.6.1.2.1.1.9.1.3.1'), + OctetString('new system name'))) +) + +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/set-v2c-with-value-type-mib-lookup.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/set-v2c-with-value-type-mib-lookup.py index 46d4c5e..62f7595 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/set-v2c-with-value-type-mib-lookup.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/set-v2c-with-value-type-mib-lookup.py @@ -1,36 +1,39 @@ -# -# Command Generator -# -# Send SNMP SET request using the following options: -# -# * with SNMPv2c, community 'public' -# * over IPv4/UDP -# * to an Agent at demo.snmplabs.com:161 -# * setting SNMPv2-MIB::sysName.0 to new value (type taken from MIB) -# +""" +Coerce value to SET to MIB spec ++++++++++++++++++++++++++++++++ + +Send SNMP SET request using the following options: + +* with SNMPv2c, community 'public' +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* setting SNMPv2-MIB::sysName.0 to new value (type taken from MIB) + +Functionally similar to: + +| $ snmpset -v2c -c public demo.snmplabs.com SNMPv2-MIB::sysDescr.0 \ +| = "new system name" + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in setCmd(SnmpEngine(), - CommunityData('public'), - UdpTransportTarget(('demo.snmplabs.com', 161)), - ContextData(), - ObjectType( - ObjectIdentity('SNMPv2-MIB', 'sysORDescr', 1), - 'new system name' - )): - # Check for errors and print out results - if errorIndication: - print(errorIndication) - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) - ) - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) - break +errorIndication, errorStatus, errorIndex, varBinds = next( + setCmd(SnmpEngine(), + CommunityData('public'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysORDescr', 1), + 'new system name')) +) + +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/set-v3-with-custom-contextengineid-and-contextname.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/set-v3-with-custom-contextengineid-and-contextname.py index 9c5b20f..f017882 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/set-v3-with-custom-contextengineid-and-contextname.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/set-v3-with-custom-contextengineid-and-contextname.py @@ -1,43 +1,45 @@ -# -# Command Generator -# -# Send SNMP SET request using the following options: -# -# * with SNMPv3 with user 'usr-md5-none', MD5 auth and no privacy protocols -# * over IPv4/UDP -# * to an Agent at demo.snmplabs.com:161 -# * addressing particular set of Managed Objects at remote SNMP Engine by: -# * contextEngineId 0x80004fb805636c6f75644dab22cc and -# * contextName 'a172334d7d97871b72241397f713fa12' -# * setting SNMPv2-MIB::sysName.0 to new value (type taken from MIB) -# +""" +Custom ContextEngineId and ContextName +++++++++++++++++++++++++++++++++++++++ + +Send SNMP SET request using the following options: + +* with SNMPv3 with user 'usr-md5-none', MD5 auth and no privacy protocols +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* addressing particular set of Managed Objects at remote SNMP Engine by: + * contextEngineId 0x80004fb805636c6f75644dab22cc and + * contextName 'a172334d7d97871b72241397f713fa12' +* setting SNMPv2-MIB::sysName.0 to new value (type taken from MIB) + +Functionally similar to: + +| $ snmpset -v3 -u usr-md5-des -l authPriv -A authkey1 -X privkey1 \ +| -E 80004fb805636c6f75644dab22cc -n a172334d7d97871b72241397f713fa12 \ +| demo.snmplabs.com \ +| SNMPv2-MIB::sysORDescr.1 = "new system name" + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * -from pysnmp.proto import rfc1902 -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in setCmd(SnmpEngine(), - UsmUserData('usr-md5-none', 'authkey1'), - UdpTransportTarget(('demo.snmplabs.com', 161)), - ContextData( - contextEngineId=rfc1902.OctetString(hexValue='80004fb805636c6f75644dab22cc'), - contextName='da761cfc8c94d3aceef4f60f049105ba' - ), - ObjectType( - ObjectIdentity('SNMPv2-MIB', 'sysORDescr', 1), - 'new system name' - )): - # Check for errors and print out results - if errorIndication: - print(errorIndication) - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) - ) - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) - break +errorIndication, errorStatus, errorIndex, varBinds = next( + setCmd(SnmpEngine(), + UsmUserData('usr-md5-none', 'authkey1'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(contextEngineId=OctetString(hexValue='80004fb805636c6f75644dab22cc'), + contextName='da761cfc8c94d3aceef4f60f049105ba'), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysORDescr', 1), + 'new system name')) +) + +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/set-v3-with-custom-contextengineid.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/set-v3-with-custom-contextengineid.py index 22d165d..46ef275 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/set-v3-with-custom-contextengineid.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/set-v3-with-custom-contextengineid.py @@ -1,44 +1,43 @@ -# -# Command Generator -# -# Send SNMP GET request using the following options: -# -# * with SNMPv3 with user 'usr-md5-des', MD5 auth and DES privacy protocols -# * use remote SNMP Engine ID 0x80004fb805636c6f75644dab22cc (USM -# autodiscovery will run) -# * over IPv4/UDP -# * to an Agent at demo.snmplabs.com:161 -# * setting SNMPv2-MIB::sysName.0 to new value (type taken from MIB) -# +""" +Custom ContextEngineId +++++++++++++++++++++++ + +Send SNMP GET request using the following options: + +* with SNMPv3 with user 'usr-md5-des', MD5 auth and DES privacy protocols +* use remote SNMP Engine ID 0x80004fb805636c6f75644dab22cc (USM + autodiscovery will run) +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* setting SNMPv2-MIB::sysName.0 to new value (type coerced from MIB) + +Functionally similar to: + +| $ snmpset -v3 -u usr-md5-des -l authPriv -A authkey1 -X privkey1 \ +| -E 80004fb805636c6f75644dab22cc demo.snmplabs.com \ +| SNMPv2-MIB::sysORDescr.1 = "new system name" + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * -from pysnmp.proto import rfc1902 -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in setCmd(SnmpEngine(), - UsmUserData( - 'usr-md5-des', 'authkey1', 'privkey1', - securityEngineId=rfc1902.OctetString( - hexValue='80004fb805636c6f75644dab22cc' - ) - ), - UdpTransportTarget(('demo.snmplabs.com', 161)), - ContextData(), - ObjectType( - ObjectIdentity('SNMPv2-MIB', 'sysORDescr', 1), - 'new system name' - )): - # Check for errors and print out results - if errorIndication: - print(errorIndication) - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) - ) - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) - break +errorIndication, errorStatus, errorIndex, varBinds = next( + setCmd(SnmpEngine(), + UsmUserData('usr-md5-des', 'authkey1', 'privkey1', + securityEngineId=OctetString(hexValue='80004fb805636c6f75644dab22cc')), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysName', 0), + 'new system name')) +) + +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/oneliner/manager/cmdgen/set-v3-with-value-type-mib-lookup.py b/examples/v3arch/asyncore/oneliner/manager/cmdgen/set-v3-with-value-type-mib-lookup.py index 379a0dd..e72587d 100644 --- a/examples/v3arch/asyncore/oneliner/manager/cmdgen/set-v3-with-value-type-mib-lookup.py +++ b/examples/v3arch/asyncore/oneliner/manager/cmdgen/set-v3-with-value-type-mib-lookup.py @@ -1,39 +1,41 @@ -# -# Command Generator -# -# Send SNMP SET request using the following options: -# -# * with SNMPv3 with user 'usr-md5-des', MD5 auth and DES privacy protocols -# * over IPv4/UDP -# * to an Agent at demo.snmplabs.com:161 -# * setting SNMPv2-MIB::sysName.0 to new value (type taken from MIB) -# * perform response OIDs and values resolution at MIB -# +""" +Coerce value to SET to MIB spec ++++++++++++++++++++++++++++++++ + + +Send SNMP SET request using the following options: + +* with SNMPv3 with user 'usr-md5-des', MD5 auth and DES privacy protocols +* over IPv4/UDP +* to an Agent at demo.snmplabs.com:161 +* setting SNMPv2-MIB::sysName.0 to new value (type taken from MIB) + +Functionally similar to: + +| $ snmpset -v3 -u usr-md5-des -l authPriv -A authkey1 -X privkey1 \ +| demo.snmplabs.com SNMPv2-MIB::sysORDescr.1 = "new system name" +| + +"""# from pysnmp.entity.rfc3413.oneliner.cmdgen import * -from pysnmp.proto import rfc1902 - -for errorIndication, \ - errorStatus, errorIndex, \ - varBinds in setCmd(SnmpEngine(), - UsmUserData('usr-md5-des', 'authkey1', 'privkey1'), - UdpTransportTarget(('demo.snmplabs.com', 161)), - ContextData(), - ObjectType( - ObjectIdentity('SNMPv2-MIB', 'sysORDescr', 1), - 'new system name' - ), - lookupNames=True, lookupValues=True): - # Check for errors and print out results - if errorIndication: - print(errorIndication) - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex)-1][0] or '?' - ) - ) - else: - for varBind in varBinds: - print(' = '.join([ x.prettyPrint() for x in varBind ])) - break + +errorIndication, errorStatus, errorIndex, varBinds = next( + setCmd(SnmpEngine(), + UsmUserData('usr-md5-des', 'authkey1', 'privkey1'), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysORDescr', 1), + 'new system name')) +) + +if errorIndication: + print(errorIndication) +elif errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex)-1][0] or '?' + ) + ) +else: + for varBind in varBinds: + print(' = '.join([ x.prettyPrint() for x in varBind ])) diff --git a/examples/v3arch/asyncore/proxy/command/udp6-to-udp4-conversion.py b/examples/v3arch/asyncore/proxy/command/udp6-to-udp4-conversion.py new file mode 100644 index 0000000..a13df6b --- /dev/null +++ b/examples/v3arch/asyncore/proxy/command/udp6-to-udp4-conversion.py @@ -0,0 +1,142 @@ +""" +IPv6-to-IPv4 conversion ++++++++++++++++++++++++ + +Act as a local SNMPv1/v2c Agent listening on a UDP/IPv6 transport, relay +messages to distant SNMPv1/2c Agent over UDP/IPv4 transport: + +* with local SNMPv2c community 'public' +* local Agent listening at [::1]:161 +* remote SNMPv2c community 'public' +* remote Agent listening at 195.218.195.228:161 + +This script can be queried with the following Net-SNMP command: + +| $ snmpget -v2c -c public udp6:[::1]:161 sysDescr.0 + +due to proxy, it is equivalent to + +| $ snmpget -v2c -c public 195.218.195.228:161 sysDescr.0 + +Warning: for production operation you would need to modify this script +so that it will re-map possible duplicate request-ID values, coming in +initial request PDUs from different Managers, into unique values to +avoid sending duplicate request-IDs to Agents. + +"""# +from pysnmp.carrier.asyncore.dgram import udp, udp6 +from pysnmp.entity import engine, config +from pysnmp.entity.rfc3413 import cmdrsp, cmdgen, context +from pysnmp.proto.api import v2c +from pysnmp import error + +# Create SNMP engine with autogenernated engineID and pre-bound +# to socket transport dispatcher +snmpEngine = engine.SnmpEngine() + +# +# Transport setup +# + +# Agent section + +# UDP over IPv6 +config.addTransport( + snmpEngine, + udp6.domainName, + udp6.Udp6Transport().openServerMode(('::1', 161)) +) + +# Manager section + +# UDP over IPv4 +config.addTransport( + snmpEngine, + udp.domainName, + udp.UdpTransport().openClientMode() +) + +# +# SNMPv1/2c setup (Agent role) +# + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, '1-my-area', 'public') + +# +# SNMPv1/v2c setup (Manager role) +# +# Here we configure securityName lexicographically lesser than '1-my-area' +# to let it match first in snmpCommunityTable on response processing. +# + +config.addV1System(snmpEngine, '0-distant-area', 'public', + transportTag='remote') + +# +# Transport target used by Manager +# + +config.addTargetParams( + snmpEngine, 'distant-agent-auth', '0-distant-area', 'noAuthNoPriv', 1 +) +config.addTargetAddr( + snmpEngine, 'distant-agent', + udp.domainName, ('195.218.195.228', 161), + 'distant-agent-auth', retryCount=0, tagList='remote' +) + +# Default SNMP context +config.addContext(snmpEngine, '') + +class CommandResponder(cmdrsp.CommandResponderBase): + cmdGenMap = { + v2c.GetRequestPDU.tagSet: cmdgen.GetCommandGenerator(), + v2c.SetRequestPDU.tagSet: cmdgen.SetCommandGenerator(), + v2c.GetNextRequestPDU.tagSet: cmdgen.NextCommandGeneratorSingleRun(), + v2c.GetBulkRequestPDU.tagSet: cmdgen.BulkCommandGeneratorSingleRun() + } + pduTypes = cmdGenMap.keys() # This app will handle these PDUs + + # SNMP request relay + def handleMgmtOperation(self, snmpEngine, stateReference, contextName, + PDU, acInfo): + cbCtx = stateReference, PDU + contextEngineId = None # address authoritative SNMP Engine + try: + self.cmdGenMap[PDU.tagSet].sendPdu( + snmpEngine, 'distant-agent', + contextEngineId, contextName, + PDU, + self.handleResponsePdu, cbCtx + ) + except error.PySnmpError: + self.handleResponsePdu( + stateReference, 'error', None, cbCtx + ) + + # SNMP response relay + def handleResponsePdu(self, snmpEngine, sendRequestHandle, + errorIndication, PDU, cbCtx): + stateReference, reqPDU = cbCtx + + if errorIndication: + PDU = v2c.apiPDU.getResponse(reqPDU) + PDU.setErrorStatus(PDU, 5) + + self.sendPdu( + snmpEngine, stateReference, PDU + ) + + self.releaseStateInformation(stateReference) + +CommandResponder(snmpEngine, context.SnmpContext(snmpEngine)) + +snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish + +# Run I/O dispatcher which would receive queries and send responses +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/proxy/command/v2c-to-v1-conversion.py b/examples/v3arch/asyncore/proxy/command/v2c-to-v1-conversion.py new file mode 100644 index 0000000..4e78dfc --- /dev/null +++ b/examples/v3arch/asyncore/proxy/command/v2c-to-v1-conversion.py @@ -0,0 +1,140 @@ +""" +SNMPv2c-to-SNMPv1 conversion +++++++++++++++++++++++++++++ + +Act as a local SNMPv2c Agent, relay messages to distant SNMPv1 Agent: + +* over IPv4/UDP +* with local SNMPv2c community public +* local Agent listening at 127.0.0.1:161 +* remote SNMPv1, community public +* remote Agent listening at 195.218.195.228:161 + +This script can be queried with the following Net-SNMP command: + +| $ snmpbulkwalk -v2c -c public -ObentU 127.0.0.1:161 system + +due to proxy, it is equivalent to + +| $ snmpwalk -v1 -c public 195.218.195.228:161 system + +Warning: for production operation you would need to modify this script +so that it will re-map possible duplicate request-ID values, coming in +initial request PDUs from different Managers, into unique values to +avoid sending duplicate request-IDs to Agents. + +"""# +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity import engine, config +from pysnmp.entity.rfc3413 import cmdrsp, cmdgen, context +from pysnmp.proto.api import v2c +from pysnmp import error + +# Create SNMP engine with autogenernated engineID and pre-bound +# to socket transport dispatcher +snmpEngine = engine.SnmpEngine() + +# +# Transport setup +# + +# Agent section + +# UDP over IPv4 +config.addTransport( + snmpEngine, + udp.domainName + (1,), + udp.UdpTransport().openServerMode(('127.0.0.1', 161)) +) + +# Manager section + +# UDP over IPv4 +config.addTransport( + snmpEngine, + udp.domainName + (2,), + udp.UdpTransport().openClientMode() +) + +# +# SNMPv2c setup (Agent role) +# + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public') + +# +# SNMPv1 setup (Manager role) +# + +# SecurityName <-> CommunityName <-> Transport mapping +config.addV1System(snmpEngine, 'distant-area', 'public', transportTag='distant') + +# +# Transport target used by Manager +# + +# Specify security settings per SecurityName (SNMPv1 - 0, SNMPv2c - 1) +config.addTargetParams(snmpEngine, 'distant-agent-auth', 'distant-area', + 'noAuthNoPriv', 0) + +config.addTargetAddr( + snmpEngine, 'distant-agent', + udp.domainName + (2,), ('195.218.195.228', 161), + 'distant-agent-auth', retryCount=0, tagList='distant' +) + +# Default SNMP context +config.addContext(snmpEngine, '') + +class CommandResponder(cmdrsp.CommandResponderBase): + cmdGenMap = { + v2c.GetRequestPDU.tagSet: cmdgen.GetCommandGenerator(), + v2c.SetRequestPDU.tagSet: cmdgen.SetCommandGenerator(), + v2c.GetNextRequestPDU.tagSet: cmdgen.NextCommandGeneratorSingleRun(), + v2c.GetBulkRequestPDU.tagSet: cmdgen.BulkCommandGeneratorSingleRun() + } + pduTypes = cmdGenMap.keys() # This app will handle these PDUs + + # SNMP request relay + def handleMgmtOperation(self, snmpEngine, stateReference, contextName, + PDU, acInfo): + cbCtx = stateReference, PDU + contextEngineId = None # address authoritative SNMP Engine + try: + self.cmdGenMap[PDU.tagSet].sendPdu( + snmpEngine, 'distant-agent', + contextEngineId, contextName, + PDU, + self.handleResponsePdu, cbCtx + ) + except error.PySnmpError: + self.handleResponsePdu( + stateReference, 'error', None, cbCtx + ) + + # SNMP response relay + def handleResponsePdu(self, snmpEngine, sendRequestHandle, + errorIndication, PDU, cbCtx): + stateReference, reqPDU = cbCtx + + if errorIndication: + PDU = v2c.apiPDU.getResponse(reqPDU) + PDU.setErrorStatus(PDU, 5) + + self.sendPdu( + snmpEngine, stateReference, PDU + ) + + self.releaseStateInformation(stateReference) + +CommandResponder(snmpEngine, context.SnmpContext(snmpEngine)) + +snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish + +# Run I/O dispatcher which would receive queries and send responses +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/proxy/command/v2c-to-v3-conversion.py b/examples/v3arch/asyncore/proxy/command/v2c-to-v3-conversion.py new file mode 100644 index 0000000..ca269f7 --- /dev/null +++ b/examples/v3arch/asyncore/proxy/command/v2c-to-v3-conversion.py @@ -0,0 +1,140 @@ +""" +SNMPv2c-to-SNMPv3 conversion +++++++++++++++++++++++++++++ + +Act as a local SNMPv1/v2c Agent, relay messages to distant SNMPv3 Agent: +* over IPv4/UDP +* with local SNMPv2c community 'public' +* local Agent listening at 127.0.0.1:161 +* remote SNMPv3 user usr-md5-none, MD5 auth and no privacy protocols +* remote Agent listening at 195.218.195.228:161 + +This script can be queried with the following Net-SNMP command: + +| $ snmpget -v2c -c public 127.0.0.1:161 1.3.6.1.2.1.1.1.0 + +due to proxy, it is equivalent to + +| $ snmpget -v3 -l authNoPriv -u usr-md5-none -A authkey1 -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.1.0 + +Warning: for production operation you would need to modify this script +so that it will re-map possible duplicate request-ID values, coming in +initial request PDUs from different Managers, into unique values to +avoid sending duplicate request-IDs to Agents. + +"""# +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity import engine, config +from pysnmp.entity.rfc3413 import cmdrsp, cmdgen, context +from pysnmp.proto.api import v2c +from pysnmp import error + +# Create SNMP engine with autogenernated engineID and pre-bound +# to socket transport dispatcher +snmpEngine = engine.SnmpEngine() + +# +# Transport setup +# + +# Agent section + +# UDP over IPv4 +config.addTransport( + snmpEngine, + udp.domainName + (1,), + udp.UdpTransport().openServerMode(('127.0.0.1', 161)) +) + +# Manager section + +# UDP over IPv4 +config.addTransport( + snmpEngine, + udp.domainName + (2,), + udp.UdpTransport().openClientMode() +) + +# +# SNMPv1/2c setup (Agent role) +# + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public') + +# +# SNMPv3/USM setup (Manager role) +# + +# user: usr-md5-none, auth: MD5, priv NONE +config.addV3User( + snmpEngine, 'usr-md5-none', config.usmHMACMD5AuthProtocol, 'authkey1' +) + +# +# Transport target used by Manager +# + +config.addTargetParams( + snmpEngine, 'distant-agent-auth', 'usr-md5-none', 'authNoPriv' +) +config.addTargetAddr( + snmpEngine, 'distant-agent', + udp.domainName + (2,), ('195.218.195.228', 161), + 'distant-agent-auth', retryCount=0 +) + +# Default SNMP context +config.addContext(snmpEngine, '') + +class CommandResponder(cmdrsp.CommandResponderBase): + cmdGenMap = { + v2c.GetRequestPDU.tagSet: cmdgen.GetCommandGenerator(), + v2c.SetRequestPDU.tagSet: cmdgen.SetCommandGenerator(), + v2c.GetNextRequestPDU.tagSet: cmdgen.NextCommandGeneratorSingleRun(), + v2c.GetBulkRequestPDU.tagSet: cmdgen.BulkCommandGeneratorSingleRun() + } + pduTypes = cmdGenMap.keys() # This app will handle these PDUs + + # SNMP request relay + def handleMgmtOperation(self, snmpEngine, stateReference, contextName, + PDU, acInfo): + cbCtx = stateReference, PDU + contextEngineId = None # address authoritative SNMP Engine + try: + self.cmdGenMap[PDU.tagSet].sendPdu( + snmpEngine, 'distant-agent', + contextEngineId, contextName, + PDU, + self.handleResponsePdu, cbCtx + ) + except error.PySnmpError: + self.handleResponsePdu( + stateReference, 'error', None, cbCtx + ) + + # SNMP response relay + def handleResponsePdu(self, snmpEngine, sendRequestHandle, + errorIndication, PDU, cbCtx): + stateReference, reqPDU = cbCtx + + if errorIndication: + PDU = v2c.apiPDU.getResponse(reqPDU) + PDU.setErrorStatus(PDU, 5) + + self.sendPdu( + snmpEngine, stateReference, PDU + ) + + self.releaseStateInformation(stateReference) + +CommandResponder(snmpEngine, context.SnmpContext(snmpEngine)) + +snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish + +# Run I/O dispatcher which would receive queries and send responses +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/asyncore/proxy/command/v3-to-v2c-conversion.py b/examples/v3arch/asyncore/proxy/command/v3-to-v2c-conversion.py new file mode 100644 index 0000000..da9aba3 --- /dev/null +++ b/examples/v3arch/asyncore/proxy/command/v3-to-v2c-conversion.py @@ -0,0 +1,143 @@ +""" +SNMPv3-to-SNMPv2c conversion +++++++++++++++++++++++++++++ + +Act as a local SNMPv3 Agent, relay messages to distant SNMPv1/v2c Agent: +* over IPv4/UDP +* with local SNMPv3 user usr-md5-des, MD5 auth and DES privacy protocols +* local Agent listening at 127.0.0.1:161 +* remote SNMPv1, community public +* remote Agent listening at 195.218.195.228:161 + +This script can be queried with the following Net-SNMP command: + +| $ snmpget -v3 -l authPriv -u usr-md5-des -A authkey1 -X privkey1 -ObentU 127.0.0.1:161 1.3.6.1.2.1.1.1.0 + +due to proxy, it is equivalent to + +| $ snmpget -v2c -c public 195.218.195.228:161 1.3.6.1.2.1.1.1.0 + +Warning: for production operation you would need to modify this script +so that it will re-map possible duplicate request-ID values, coming in +initial request PDUs from different Managers, into unique values to +avoid sending duplicate request-IDs to Agents. + +"""# +from pysnmp.carrier.asyncore.dgram import udp +from pysnmp.entity import engine, config +from pysnmp.entity.rfc3413 import cmdrsp, cmdgen, context +from pysnmp.proto.api import v2c +from pysnmp import error + +# Create SNMP engine with autogenernated engineID and pre-bound +# to socket transport dispatcher +snmpEngine = engine.SnmpEngine() + +# +# Transport setup +# + +# Agent section + +# UDP over IPv4 +config.addTransport( + snmpEngine, + udp.domainName + (1,), + udp.UdpTransport().openServerMode(('127.0.0.1', 161)) +) + +# Manager section + +# UDP over IPv4 +config.addTransport( + snmpEngine, + udp.domainName + (2,), + udp.UdpTransport().openClientMode() +) + +# +# SNMPv3/USM setup (Agent role) +# + +# user: usr-md5-des, auth: MD5, priv DES +config.addV3User( + snmpEngine, 'usr-md5-des', + config.usmHMACMD5AuthProtocol, 'authkey1', + config.usmDESPrivProtocol, 'privkey1' +) + +# +# SNMPv1/2c setup (Manager role) +# + +# SecurityName <-> CommunityName mapping +config.addV1System(snmpEngine, 'my-area', 'public') + +# +# Transport target used by Manager +# + +# Specify security settings per SecurityName (SNMPv1 - 0, SNMPv2c - 1) +config.addTargetParams(snmpEngine, 'distant-agent-auth', 'my-area', + 'noAuthNoPriv', 0) + +config.addTargetAddr( + snmpEngine, 'distant-agent', + udp.domainName + (2,), ('195.218.195.228', 161), + 'distant-agent-auth', retryCount=0 +) + +# Default SNMP context +config.addContext(snmpEngine, '') + +class CommandResponder(cmdrsp.CommandResponderBase): + cmdGenMap = { + v2c.GetRequestPDU.tagSet: cmdgen.GetCommandGenerator(), + v2c.SetRequestPDU.tagSet: cmdgen.SetCommandGenerator(), + v2c.GetNextRequestPDU.tagSet: cmdgen.NextCommandGeneratorSingleRun(), + v2c.GetBulkRequestPDU.tagSet: cmdgen.BulkCommandGeneratorSingleRun() + } + pduTypes = cmdGenMap.keys() # This app will handle these PDUs + + # SNMP request relay + def handleMgmtOperation(self, snmpEngine, stateReference, contextName, + PDU, acInfo): + cbCtx = stateReference, PDU + contextEngineId = None # address authoritative SNMP Engine + try: + self.cmdGenMap[PDU.tagSet].sendPdu( + snmpEngine, 'distant-agent', + contextEngineId, contextName, + PDU, + self.handleResponsePdu, cbCtx + ) + except error.PySnmpError: + self.handleResponsePdu( + stateReference, 'error', None, cbCtx + ) + + # SNMP response relay + def handleResponsePdu(self, snmpEngine, sendRequestHandle, + errorIndication, PDU, cbCtx): + stateReference, reqPDU = cbCtx + + if errorIndication: + PDU = v2c.apiPDU.getResponse(reqPDU) + PDU.setErrorStatus(PDU, 5) + + self.sendPdu( + snmpEngine, stateReference, PDU + ) + + self.releaseStateInformation(stateReference) + +CommandResponder(snmpEngine, context.SnmpContext(snmpEngine)) + +snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish + +# Run I/O dispatcher which would receive queries and send responses +try: + snmpEngine.transportDispatcher.runDispatcher() +except: + snmpEngine.transportDispatcher.closeDispatcher() + raise diff --git a/examples/v3arch/trollius/agent/ntforg/inform-v3.py b/examples/v3arch/trollius/agent/ntforg/inform-v3.py index 93fe5df..e4e87c1 100644 --- a/examples/v3arch/trollius/agent/ntforg/inform-v3.py +++ b/examples/v3arch/trollius/agent/ntforg/inform-v3.py @@ -1,19 +1,25 @@ -# -# Notification Originator -# -# Send SNMP INFORM notification using the following options: -# -# * SNMPv3 -# * with user 'usr-md5-none', auth: MD5, priv NONE -# * over IPv4/UDP -# * using Trollius framework for network transport -# * to a Manager at 127.0.0.1:162 -# * send INFORM notification -# * with TRAP ID 'warmStart' specified as an OID -# * include managed object information 1.3.6.1.2.1.1.5.0 = 'system name' -# -# Requires Trollius framework! -# +""" +SNMP INFORM notification +++++++++++++++++++++++++ + +Send SNMP INFORM notification using the following options: + +* SNMPv3 +* with user 'usr-md5-none', auth: MD5, priv NONE +* over IPv4/UDP +* using Trollius framework for network transport +* to a Manager at 127.0.0.1:162 +* send INFORM notification +* with TRAP ID 'warmStart' specified as an OID +* include managed object information 1.3.6.1.2.1.1.5.0 = 'system name' + +Functionally similar to: + +| $ snmpinform -v3 -l authPriv -u usr-md5-none -A authkey1 127.0.0.1 0 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.5.0 s 'system name' + +Requires Trollius framework! + +"""# from pysnmp.entity import engine, config from pysnmp.entity.rfc3413 import context from pysnmp.entity.rfc3413.asyncio import ntforg diff --git a/examples/v3arch/trollius/agent/ntforg/trap-v1.py b/examples/v3arch/trollius/agent/ntforg/trap-v1.py index b11b39f..50c26b8 100644 --- a/examples/v3arch/trollius/agent/ntforg/trap-v1.py +++ b/examples/v3arch/trollius/agent/ntforg/trap-v1.py @@ -1,23 +1,29 @@ -# -# Notification Originator -# -# Send SNMP notification using the following options: -# -# * SNMPv1 -# * with community name 'public' -# * over IPv4/UDP -# * using Trollius framework for network transport -# * to a Manager at 127.0.0.1:162 -# * send TRAP notification -# * with TRAP ID 'coldStart' specified as an OID -# * include managed objects information: -# * overriding Uptime value with 12345 -# * overriding Agent Address with '127.0.0.1' -# * overriding Enterprise OID with 1.3.6.1.4.1.20408.4.1.1.2 -# * include managed object information '1.3.6.1.2.1.1.1.0' = 'my system' -# -# Requires Trollius framework! -# +""" +SNMPv1 TRAP ++++++++++++ + +Send SNMP notification using the following options: + +* SNMPv1 +* with community name 'public' +* over IPv4/UDP +* using Trollius framework for network transport +* to a Manager at 127.0.0.1:162 +* send TRAP notification +* with TRAP ID 'coldStart' specified as an OID +* include managed objects information: +* overriding Uptime value with 12345 +* overriding Agent Address with '127.0.0.1' +* overriding Enterprise OID with 1.3.6.1.4.1.20408.4.1.1.2 +* include managed object information '1.3.6.1.2.1.1.1.0' = 'my system' + +Functionally similar to: + +| $ snmptrap -v1 -c public demo.snmplabs.com 1.3.6.1.4.1.20408.4.1.1.2 127.0.0.1 6 432 12345 1.3.6.1.2.1.1.1.0 s 'my system' + +Requires Trollius framework! + +"""# from pysnmp.entity import engine, config from pysnmp.entity.rfc3413 import context from pysnmp.entity.rfc3413.asyncio import ntforg diff --git a/examples/v3arch/trollius/manager/cmdgen/get-v1.py b/examples/v3arch/trollius/manager/cmdgen/get-v1.py index 3d14a15..9ecda4e 100644 --- a/examples/v3arch/trollius/manager/cmdgen/get-v1.py +++ b/examples/v3arch/trollius/manager/cmdgen/get-v1.py @@ -1,20 +1,22 @@ -# -# Command Generator -# -# Send SNMP GET request using the following options: -# -# * with SNMPv1, community 'public' -# * using Trollius framework for network transport -# * over IPv4/UDP -# * to an Agent at 195.218.195.228:161 -# * for an OID in string form -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpset -v1 -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1.1.0 -# -# Requires Trollius framework! -# +""" +SNMPv1 GET +++++++++++ + +Send SNMP GET request using the following options: + +* with SNMPv1, community 'public' +* using Trollius framework for network transport +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for an OID in string form + +This script performs similar to the following Net-SNMP command: + +| $ snmpset -v1 -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1.1.0 + +Requires Trollius framework! + +"""# from pysnmp.carrier.asyncio.dgram import udp from pysnmp.entity.rfc3413.asyncio import cmdgen from pysnmp.entity import engine, config diff --git a/examples/v3arch/trollius/manager/cmdgen/get-v2c-custom-timeout.py b/examples/v3arch/trollius/manager/cmdgen/get-v2c-custom-timeout.py index 4db7a8c..9da4301 100644 --- a/examples/v3arch/trollius/manager/cmdgen/get-v2c-custom-timeout.py +++ b/examples/v3arch/trollius/manager/cmdgen/get-v2c-custom-timeout.py @@ -1,20 +1,22 @@ -# -# GET Command Generator -# -# Send a SNMP GET request -# with SNMPv2c, community 'public' -# using Trollius framework for network transport -# over IPv4/UDP -# to an Agent at 195.218.195.228:161 -# wait 3 seconds for response, retry 5 times (plus one initial attempt) -# for an OID in string form -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpget -v2c -c public -ObentU -r 5 -t 1 195.218.195.228 1.3.6.1.2.1.1.1.0 -# -# Requires Trollius framework! -# +""" +Fetch scalar value with timeout ++++++++++++++++++++++++++++++++ + +Send a SNMP GET request +* with SNMPv2c, community 'public' +* using Trollius framework for network transport +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* wait 3 seconds for response, retry 5 times (plus one initial attempt) +* for an OID in string form + +This script performs similar to the following Net-SNMP command: + +| $ snmpget -v2c -c public -ObentU -r 5 -t 1 195.218.195.228 1.3.6.1.2.1.1.1.0 + +Requires Trollius framework! + +"""# from pysnmp.carrier.asyncio.dgram import udp from pysnmp.entity.rfc3413.asyncio import cmdgen from pysnmp.entity import engine, config diff --git a/examples/v3arch/trollius/manager/cmdgen/getbulk-v3.py b/examples/v3arch/trollius/manager/cmdgen/getbulk-v3.py index 50f4e69..94839b4 100644 --- a/examples/v3arch/trollius/manager/cmdgen/getbulk-v3.py +++ b/examples/v3arch/trollius/manager/cmdgen/getbulk-v3.py @@ -1,21 +1,23 @@ -# -# GETBULK Command Generator -# -# Send a series of SNMP GETBULK requests -# with SNMPv3 with user 'usr-md5-des', MD5 auth and DES privacy protocols -# using Trollius framework for network transport -# over IPv4/UDP -# to an Agent at 195.218.195.228:161 -# with values non-repeaters = 0, max-repetitions = 25 -# for two OIDs in string form -# stop on end-of-mib condition for both OIDs -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpbulkwalk -v2c -c public -C n0 -C r25 -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 -# -# Requires Trollius framework! -# +""" +BULK walk MIB ++++++++++++++ + +Send a series of SNMP GETBULK requests +* with SNMPv3 with user 'usr-md5-des', MD5 auth and DES privacy protocols +* using Trollius framework for network transport +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* with values non-repeaters = 0, max-repetitions = 25 +* for two OIDs in string form +* stop on end-of-mib condition for both OIDs + +This script performs similar to the following Net-SNMP command: + +| $ snmpbulkwalk -v2c -c public -C n0 -C r25 -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 + +Requires Trollius framework! + +"""# from pysnmp.entity import engine, config from pysnmp.proto import rfc1905 from pysnmp.entity.rfc3413.asyncio import cmdgen diff --git a/examples/v3arch/trollius/manager/cmdgen/getnext-v3.py b/examples/v3arch/trollius/manager/cmdgen/getnext-v3.py index 5b26bff..d5a852a 100644 --- a/examples/v3arch/trollius/manager/cmdgen/getnext-v3.py +++ b/examples/v3arch/trollius/manager/cmdgen/getnext-v3.py @@ -1,20 +1,22 @@ -# -# GETNEXT Command Generator -# -# Send a series of SNMP GETNEXT requests -# with SNMPv3 with user 'usr-none-none', no auth and no privacy protocols -# using Trollius framework for network transport -# over IPv4/UDP -# to an Agent at 195.218.195.228:161 -# for an OID in string form -# stop on end-of-mib condition for both OIDs -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpwalk -v2c -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 -# -# Requires Trollius framework! -# +""" +Walk MIB +++++++++ + +Send a series of SNMP GETNEXT requests +* with SNMPv3 with user 'usr-none-none', no auth and no privacy protocols +* using Trollius framework for network transport +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for an OID in string form +* stop on end-of-mib condition for both OIDs + +This script performs similar to the following Net-SNMP command: + +| $ snmpwalk -v2c -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 + +Requires Trollius framework! + +"""# from pysnmp.entity import engine, config from pysnmp.proto import rfc1905 from pysnmp.entity.rfc3413.asyncio import cmdgen diff --git a/examples/v3arch/trollius/manager/cmdgen/set-v2c.py b/examples/v3arch/trollius/manager/cmdgen/set-v2c.py index 966e78a..4939635 100644 --- a/examples/v3arch/trollius/manager/cmdgen/set-v2c.py +++ b/examples/v3arch/trollius/manager/cmdgen/set-v2c.py @@ -1,20 +1,22 @@ -# -# Command Generator -# -# Send SNMP SET request using the following options: -# -# * with SNMPv1, community 'public' -# * using Trollius framework for network transport -# * over IPv4/UDP -# * to an Agent at 195.218.195.228:161 -# * for OIDs in tuple form and an integer and string-typed values -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpset -v1 -c private -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.9.1.3.1 s 'my value' 1.3.6.1.2.1.1.9.1.4.1 t 123 -# -# Requires Trollius framework! -# +""" +SET scalar value +++++++++++++++++ + +Send SNMP SET request using the following options: + +* with SNMPv1, community 'public' +* using Trollius framework for network transport +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for OIDs in tuple form and an integer and string-typed values + +This script performs similar to the following Net-SNMP command: + +| $ snmpset -v1 -c private -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.9.1.3.1 s 'my value' 1.3.6.1.2.1.1.9.1.4.1 t 123 + +Requires Trollius framework! + +"""# from pysnmp.carrier.asyncio.dgram import udp from pysnmp.entity.rfc3413.asyncio import cmdgen from pysnmp.entity import engine, config diff --git a/examples/v3arch/twisted/agent/cmdrsp/v1-read-and-write-communities.py b/examples/v3arch/twisted/agent/cmdrsp/v1-read-and-write-communities.py index d346244..da6cc5f 100644 --- a/examples/v3arch/twisted/agent/cmdrsp/v1-read-and-write-communities.py +++ b/examples/v3arch/twisted/agent/cmdrsp/v1-read-and-write-communities.py @@ -1,20 +1,22 @@ -# -# Command Responder -# -# Listen and respond to SNMP GET/SET/GETNEXT queries with -# the following options: -# -# * SNMPv1 -# * with SNMP community "public" (read access) or "private" (write access) -# * allow access to SNMPv2-MIB objects (1.3.6.1.2.1) -# * over IPv4/UDP, listening at 127.0.0.1:161 -# * using Twisted fraework for network transport -# -# The following Net-SNMP's commands will GET/SET a value at this Agent: -# -# $ snmpget -v1 -c public 127.0.0.1 SNMPv2-MIB::sysLocation.0 -# $ snmpset -v1 -c private 127.0.0.1 SNMPv2-MIB::sysLocation.0 s "far away" -# +""" +Multiple SNMP communities ++++++++++++++++++++++++++ + +Listen and respond to SNMP GET/SET/GETNEXT queries with +the following options: + +* SNMPv1 +* with SNMP community "public" (read access) or "private" (write access) +* allow access to SNMPv2-MIB objects (1.3.6.1.2.1) +* over IPv4/UDP, listening at 127.0.0.1:161 +* using Twisted fraework for network transport + +The following Net-SNMP commands will GET/SET a value at this Agent: + +| $ snmpget -v1 -c public 127.0.0.1 SNMPv2-MIB::sysLocation.0 +| $ snmpset -v1 -c private 127.0.0.1 SNMPv2-MIB::sysLocation.0 s "far away" + +"""# from twisted.internet import reactor from pysnmp.entity import engine, config from pysnmp.entity.rfc3413 import cmdrsp, context diff --git a/examples/v3arch/twisted/agent/cmdrsp/v2c-custom-scalar-mib-objects.py b/examples/v3arch/twisted/agent/cmdrsp/v2c-custom-scalar-mib-objects.py index 091bb75..565419d 100644 --- a/examples/v3arch/twisted/agent/cmdrsp/v2c-custom-scalar-mib-objects.py +++ b/examples/v3arch/twisted/agent/cmdrsp/v2c-custom-scalar-mib-objects.py @@ -1,20 +1,22 @@ -# -# Command Responder -# -# Listen and respond to SNMP GET/SET/GETNEXT/GETBULK queries with -# the following options: -# -# * SNMPv2c -# * with SNMP community "public" -# * serving custom Managed Object Instance defined within this script -# * allow read access only to the subtree where the custom MIB object resides -# * over IPv4/UDP, listening at 127.0.0.1:161 -# * using Twisted fraework for network transport -# -# Either of the following Net-SNMP's commands will walk this Agent: -# -# $ snmpwalk -v2c -c public 127.0.0.1 .1.3.6 -# +""" +Implementing scalar MIB objects ++++++++++++++++++++++++++++++++ + +Listen and respond to SNMP GET/SET/GETNEXT/GETBULK queries with +the following options: + +* SNMPv2c +* with SNMP community "public" +* serving custom Managed Object Instance defined within this script +* allow read access only to the subtree where the custom MIB object resides +* over IPv4/UDP, listening at 127.0.0.1:161 +* using Twisted fraework for network transport + +Either of the following Net-SNMP commands will walk this Agent: + +| $ snmpwalk -v2c -c public 127.0.0.1 .1.3.6 + +"""# import sys from twisted.internet import reactor from pysnmp.entity import engine, config diff --git a/examples/v3arch/twisted/agent/cmdrsp/v2c-multiple-interfaces.py b/examples/v3arch/twisted/agent/cmdrsp/v2c-multiple-interfaces.py index 4f8b29d..a9e3e00 100644 --- a/examples/v3arch/twisted/agent/cmdrsp/v2c-multiple-interfaces.py +++ b/examples/v3arch/twisted/agent/cmdrsp/v2c-multiple-interfaces.py @@ -1,20 +1,22 @@ -# -# Command Responder -# -# Listen and respond to SNMP GET/SET/GETNEXT/GETBULK queries with -# the following options: -# -# * SNMPv2c -# * with SNMP community "public" -# * allow access to SNMPv2-MIB objects (1.3.6.1.2.1) -# * over IPv4/UDP, listening at 127.0.0.1:161 and 127.0.0.2:161 interfaces -# * using Twisted framework for network transport -# -# Either of the following Net-SNMP's commands will walk this Agent: -# -# $ snmpwalk -v2c -c public 127.0.0.1 .1.3.6 -# $ snmpwalk -v2c -c public 127.0.0.2 .1.3.6 -# +""" +Listen on multiple network interfaces ++++++++++++++++++++++++++++++++++++++ + +Listen and respond to SNMP GET/SET/GETNEXT/GETBULK queries with +the following options: + +* SNMPv2c +* with SNMP community "public" +* allow access to SNMPv2-MIB objects (1.3.6.1.2.1) +* over IPv4/UDP, listening at 127.0.0.1:161 and 127.0.0.2:161 interfaces +* using Twisted framework for network transport + +Either of the following Net-SNMP commands will walk this Agent: + +| $ snmpwalk -v2c -c public 127.0.0.1 .1.3.6 +| $ snmpwalk -v2c -c public 127.0.0.2 .1.3.6 + +"""# from twisted.internet import reactor from pysnmp.entity import engine, config from pysnmp.entity.rfc3413 import cmdrsp, context diff --git a/examples/v3arch/twisted/agent/cmdrsp/v3-multiple-users.py b/examples/v3arch/twisted/agent/cmdrsp/v3-multiple-users.py index 36d9d36..91fd955 100644 --- a/examples/v3arch/twisted/agent/cmdrsp/v3-multiple-users.py +++ b/examples/v3arch/twisted/agent/cmdrsp/v3-multiple-users.py @@ -1,23 +1,26 @@ -# -# Command Responder -# -# Listen and respond to SNMP GET/SET/GETNEXT/GETBULK queries with -# the following options: -# -# * SNMPv3 -# * with USM user 'usr-md5-des', auth: MD5, priv DES or -# with USM user 'usr-sha-none', auth: SHA, no privacy -# with USM user 'usr-sha-aes128', auth: SHA, priv AES -# * allow access to SNMPv2-MIB objects (1.3.6.1.2.1) -# * over IPv4/UDP, listening at 127.0.0.1:161 -# * using Twisted framework for network transport -# -# Either of the following Net-SNMP's commands will walk this Agent: -# -# $ snmpwalk -v3 -u usr-md5-des -l authPriv -A authkey1 -X privkey1 localhost .1.3.6 -# $ snmpwalk -v3 -u usr-sha-none -l authNoPriv -a SHA -A authkey1 localhost .1.3.6 -# $ snmpwalk -v3 -u usr-sha-aes128 -l authPriv -a SHA -A authkey1 -x AES -X privkey1 localhost .1.3.6 -# +""" +Multiple SNMP USM users ++++++++++++++++++++++++ + +Listen and respond to SNMP GET/SET/GETNEXT/GETBULK queries with +the following options: + +* SNMPv3 +* with USM user: + * 'usr-md5-des', auth: MD5, priv DES or + * 'usr-sha-none', auth: SHA, no privacy + * 'usr-sha-aes128', auth: SHA, priv AES +* allow access to SNMPv2-MIB objects (1.3.6.1.2.1) +* over IPv4/UDP, listening at 127.0.0.1:161 +* using Twisted framework for network transport + +Either of the following Net-SNMP commands will walk this Agent: + +| $ snmpwalk -v3 -u usr-md5-des -l authPriv -A authkey1 -X privkey1 localhost .1.3.6 +| $ snmpwalk -v3 -u usr-sha-none -l authNoPriv -a SHA -A authkey1 localhost .1.3.6 +| $ snmpwalk -v3 -u usr-sha-aes128 -l authPriv -a SHA -A authkey1 -x AES -X privkey1 localhost .1.3.6 + +"""# from twisted.internet import reactor from pysnmp.entity import engine, config from pysnmp.entity.rfc3413 import cmdrsp, context diff --git a/examples/v3arch/twisted/agent/ntforg/inform-v2c.py b/examples/v3arch/twisted/agent/ntforg/inform-v2c.py index 95ba561..77245fe 100644 --- a/examples/v3arch/twisted/agent/ntforg/inform-v2c.py +++ b/examples/v3arch/twisted/agent/ntforg/inform-v2c.py @@ -1,19 +1,25 @@ -# -# Notification Originator -# -# Send SNMP INFORM notification using the following options: -# -# * SNMPv2c -# * with community name 'public' -# * over IPv4/UDP -# * using Twisted framework for network transport -# * send INFORM notification -# * to a Manager at 127.0.0.1:162 -# * with TRAP ID 'coldStart' specified as an OID -# * include managed objects information: -# 1.3.6.1.2.1.1.1.0 = 'Example Notificator' -# 1.3.6.1.2.1.1.5.0 = 'Notificator Example' -# +""" +SNMPv2c INFORM +++++++++++++++ + +Send SNMP INFORM notification using the following options: + +* SNMPv2c +* with community name 'public' +* over IPv4/UDP +* using Twisted framework for network transport +* send INFORM notification +* to a Manager at 127.0.0.1:162 +* with TRAP ID 'coldStart' specified as an OID +* include managed objects information: + * 1.3.6.1.2.1.1.1.0 = 'Example Notificator' + * 1.3.6.1.2.1.1.5.0 = 'Notificator Example' + +Functionally similar to: + +| $ snmpinform -v2c -c public 127.0.0.2 0 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.1.0 s 'Example notification' 1.3.6.1.2.1.1.5.0 s 'Notificator Example' + +"""# from twisted.internet import reactor from pysnmp.entity import engine, config from pysnmp.carrier.twisted.dgram import udp diff --git a/examples/v3arch/twisted/agent/ntforg/inform-v3.py b/examples/v3arch/twisted/agent/ntforg/inform-v3.py index 376da6e..4473326 100644 --- a/examples/v3arch/twisted/agent/ntforg/inform-v3.py +++ b/examples/v3arch/twisted/agent/ntforg/inform-v3.py @@ -1,17 +1,23 @@ -# -# Notification Originator -# -# Send SNMP INFORM notification using the following options: -# -# * SNMPv3 -# * with user 'usr-md5-none', auth: MD5, priv NONE -# * over IPv4/UDP -# * using Twisted framework for network transport -# * to a Manager at 127.0.0.1:162 -# * send INFORM notification -# * with TRAP ID 'warmStart' specified as an OID -# * include managed object information 1.3.6.1.2.1.1.5.0 = 'system name' -# +""" +SNMPv3 INFORM ++++++++++++++ + +Send SNMP INFORM notification using the following options: + +* SNMPv3 +* with user 'usr-md5-none', auth: MD5, priv NONE +* over IPv4/UDP +* using Twisted framework for network transport +* to a Manager at 127.0.0.1:162 +* send INFORM notification +* with TRAP ID 'warmStart' specified as an OID +* include managed object information 1.3.6.1.2.1.1.5.0 = 'system name' + +Functionally similar to: + +| $ snmpinform -v3 -l authPriv -u usr-md5-none -A authkey1 127.0.0.1 0 1.3.6.1.6.3.1.1.5.2 1.3.6.1.2.1.1.5.0 s 'system name' + +"""# from twisted.internet import reactor from pysnmp.entity import engine, config from pysnmp.carrier.twisted.dgram import udp diff --git a/examples/v3arch/twisted/agent/ntforg/trap-v1.py b/examples/v3arch/twisted/agent/ntforg/trap-v1.py index 6863e0d..587314a 100644 --- a/examples/v3arch/twisted/agent/ntforg/trap-v1.py +++ b/examples/v3arch/twisted/agent/ntforg/trap-v1.py @@ -1,21 +1,27 @@ -# -# Notification Originator -# -# Send SNMP notification using the following options: -# -# * SNMPv1 -# * with community name 'public' -# * over IPv4/UDP -# * using Twisted framework for network transport -# * to a Manager at 127.0.0.1:162 -# * send TRAP notification -# * with TRAP ID 'coldStart' specified as an OID -# * include managed objects information: -# * overriding Uptime value with 12345 -# * overriding Agent Address with '127.0.0.1' -# * overriding Enterprise OID with 1.3.6.1.4.1.20408.4.1.1.2 -# * include managed object information '1.3.6.1.2.1.1.1.0' = 'my system' -# +""" +SNMPv1 TRAP ++++++++++++ + +Send SNMP notification using the following options: + +* SNMPv1 +* with community name 'public' +* over IPv4/UDP +* using Twisted framework for network transport +* to a Manager at 127.0.0.1:162 +* send TRAP notification +* with TRAP ID 'coldStart' specified as an OID +* include managed objects information: +* overriding Uptime value with 12345 +* overriding Agent Address with '127.0.0.1' +* overriding Enterprise OID with 1.3.6.1.4.1.20408.4.1.1.2 +* include managed object information '1.3.6.1.2.1.1.1.0' = 'my system' + +Functionally similar to: + +| $ snmptrap -v1 -c public 127.0.0.1 1.3.6.1.4.1.20408.4.1.1.2 127.0.0.1 6 432 12345 1.3.6.1.2.1.1.1.0 s 'my system' + +"""# from twisted.internet import reactor from pysnmp.entity import engine, config from pysnmp.carrier.twisted.dgram import udp diff --git a/examples/v3arch/twisted/agent/ntforg/trap-v2c-multiple-targets.py b/examples/v3arch/twisted/agent/ntforg/trap-v2c-multiple-targets.py index c63dc37..f1e95bf 100644 --- a/examples/v3arch/twisted/agent/ntforg/trap-v2c-multiple-targets.py +++ b/examples/v3arch/twisted/agent/ntforg/trap-v2c-multiple-targets.py @@ -1,20 +1,34 @@ -# -# Notification Originator -# -# Send SNMP TRAP notifications to multiple Managers using the -# following options: -# -# * SNMPv2c -# * with community name 'public' -# * over IPv4/UDP -# * using Twisted framework for network transport -# * send TRAP notification -# * to multiple Managers at 127.0.0.1:162, 127.0.0.2:162 -# * with TRAP ID 'coldStart' specified as an OID -# * include managed objects information: -# 1.3.6.1.2.1.1.1.0 = 'Example Notificator' -# 1.3.6.1.2.1.1.5.0 = 'Notificator Example' -# +""" +Notification to multiple addresses +++++++++++++++++++++++++++++++++++ + +Send SNMP TRAP notifications to multiple Managers using the +following options: + +* SNMPv2c +* with community name 'public' +* over IPv4/UDP +* using Twisted framework for network transport +* send TRAP notification +* to multiple Managers at 127.0.0.1:162, 127.0.0.2:162 and 127.0.0.3:162 +* with TRAP ID 'coldStart' specified as an OID +* include managed objects information: + * 1.3.6.1.2.1.1.1.0 = 'Example Notificator' + * 1.3.6.1.2.1.1.5.0 = 'Notificator Example' + +Functionally similar to: + +| $ snmptrap -v2c -c public 127.0.0.1 0 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.1.0 s 'Example notification' 1.3.6.1.2.1.1.5.0 s 'Notificator Example' + +and + +| $ snmptrap -v2c -c public 127.0.0.2 0 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.1.0 s 'Example notification' 1.3.6.1.2.1.1.5.0 s 'Notificator Example' + +and + +| $ snmptrap -v2c -c public 127.0.0.3 0 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.1.0 s 'Example notification' 1.3.6.1.2.1.1.5.0 s 'Notificator Example' + +"""# from twisted.internet import reactor from pysnmp.entity import engine, config from pysnmp.carrier.twisted.dgram import udp diff --git a/examples/v3arch/twisted/agent/ntforg/trap-v3.py b/examples/v3arch/twisted/agent/ntforg/trap-v3.py index c38e474..133f723 100644 --- a/examples/v3arch/twisted/agent/ntforg/trap-v3.py +++ b/examples/v3arch/twisted/agent/ntforg/trap-v3.py @@ -1,17 +1,23 @@ -# -# Notification Originator -# -# Send SNMP TRAP notification using the following options: -# -# * SNMPv3 -# * with user 'usr-md5-des', auth: MD5, priv DES -# * over IPv4/UDP -# * using Twisted framework for network transport -# * send TRAP notification -# * to a Manager at 127.0.0.1:162 -# * with TRAP ID 'warmStart' specified as an OID -# * include managed object information 1.3.6.1.2.1.1.5.0 = 'system name' -# +""" +SNMPv3 TRAP ++++++++++++ + +Send SNMP TRAP notification using the following options: + +* SNMPv3 +* with user 'usr-md5-des', auth: MD5, priv DES +* over IPv4/UDP +* using Twisted framework for network transport +* send TRAP notification +* to a Manager at 127.0.0.1:162 +* with TRAP ID 'warmStart' specified as an OID +* include managed object information 1.3.6.1.2.1.1.5.0 = 'system name' + +Functionally similar to: + +| $ snmptrap -v3 -l authPriv -u usr-md5-des -A authkey1 -X privkey1 -e 8000000001020304 0 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.5.0 s 'my system' + +"""# from twisted.internet import reactor from pysnmp.entity import engine, config from pysnmp.carrier.twisted.dgram import udp diff --git a/examples/v3arch/twisted/manager/cmdgen/get-v1.py b/examples/v3arch/twisted/manager/cmdgen/get-v1.py index 38428c6..2939f41 100644 --- a/examples/v3arch/twisted/manager/cmdgen/get-v1.py +++ b/examples/v3arch/twisted/manager/cmdgen/get-v1.py @@ -1,17 +1,20 @@ -# -# GET Command Generator -# -# Send a SNMP GET request -# with SNMPv1, community 'public' -# using Twisted framework for network transport -# over IPv4/UDP -# to an Agent at 195.218.195.228:161 -# for an OID in tuple form -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpget -v1 -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1.1.0 -# +""" +SNMPv1 GET +++++++++++ + +Send SNMP GET request with the following options: + +* with SNMPv1, community 'public' +* using Twisted framework for network transport +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for an OID in tuple form + +This script performs similar to the following Net-SNMP command: + +| $ snmpget -v1 -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1.1.0 + +"""# from twisted.internet import reactor, defer from pysnmp.entity import engine, config from pysnmp.entity.rfc3413.twisted import cmdgen diff --git a/examples/v3arch/twisted/manager/cmdgen/get-v2c-custom-timeout.py b/examples/v3arch/twisted/manager/cmdgen/get-v2c-custom-timeout.py index 246a1b9..e83e5e8 100644 --- a/examples/v3arch/twisted/manager/cmdgen/get-v2c-custom-timeout.py +++ b/examples/v3arch/twisted/manager/cmdgen/get-v2c-custom-timeout.py @@ -1,18 +1,20 @@ -# -# GET Command Generator -# -# Send a SNMP GET request -# with SNMPv2c, community 'public' -# using Twisted framework for network transport -# over IPv4/UDP -# to an Agent at 195.218.195.228:161 -# wait 3 seconds for response, retry 5 times (plus one initial attempt) -# for an OID in tuple form -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpget -v2c -c public -ObentU -r 5 -t 1 195.218.195.228 1.3.6.1.2.1.1.1.0 -# +""" +Fetch scalar value with timeout ++++++++++++++++++++++++++++++++ + +Send a SNMP GET request +* with SNMPv2c, community 'public' +* using Twisted framework for network transport +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* wait 3 seconds for response, retry 5 times (plus one initial attempt) +* for an OID in tuple form + +This script performs similar to the following Net-SNMP command: + +| $ snmpget -v2c -c public -ObentU -r 5 -t 1 195.218.195.228 1.3.6.1.2.1.1.1.0 + +"""# from twisted.internet import reactor, defer from pysnmp.entity import engine, config from pysnmp.entity.rfc3413.twisted import cmdgen diff --git a/examples/v3arch/twisted/manager/cmdgen/get-v3-custom-context.py b/examples/v3arch/twisted/manager/cmdgen/get-v3-custom-context.py index e85babe..527125f 100644 --- a/examples/v3arch/twisted/manager/cmdgen/get-v3-custom-context.py +++ b/examples/v3arch/twisted/manager/cmdgen/get-v3-custom-context.py @@ -1,20 +1,22 @@ -# -# GET Command Generator -# -# Send a SNMP GET request -# with SNMPv3 with user 'usr-md5-none', SHA auth and no privacy protocols -# for MIB instance identified by -# contextEngineId: 0x80004fb805636c6f75644dab22cc -# contextName: da761cfc8c94d3aceef4f60f049105ba -# using Twisted framework for network transport -# over IPv4/UDP -# to an Agent at 195.218.195.228:161 -# for an OID in tuple form -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpget -v3 -l authNoPriv -u usr-md5-none -A authkey1 -E 80004fb805636c6f75644dab22cc -n da761cfc8c94d3aceef4f60f049105ba -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.1.0 -# +""" +Custom ContextEngineId and ContextName +++++++++++++++++++++++++++++++++++++++ + +Send a SNMP GET request +* with SNMPv3 with user 'usr-md5-none', SHA auth and no privacy protocols +* for MIB instance identified by +* contextEngineId: 0x80004fb805636c6f75644dab22cc +* contextName: da761cfc8c94d3aceef4f60f049105ba +* using Twisted framework for network transport +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for an OID in tuple form + +This script performs similar to the following Net-SNMP command: + +| $ snmpget -v3 -l authNoPriv -u usr-md5-none -A authkey1 -E 80004fb805636c6f75644dab22cc -n da761cfc8c94d3aceef4f60f049105ba -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.1.0 + +"""# from twisted.internet import reactor, defer from pysnmp.entity import engine, config from pysnmp.entity.rfc3413.twisted import cmdgen diff --git a/examples/v3arch/twisted/manager/cmdgen/get-v3.py b/examples/v3arch/twisted/manager/cmdgen/get-v3.py index 0e3ab3e..d0a568d 100644 --- a/examples/v3arch/twisted/manager/cmdgen/get-v3.py +++ b/examples/v3arch/twisted/manager/cmdgen/get-v3.py @@ -1,17 +1,19 @@ -# -# GET Command Generator -# -# Send a SNMP GET request -# with SNMPv3 with user 'usr-sha-aes', SHA auth and AES128 privacy protocols -# using Twisted framework for network transport -# over IPv4/UDP -# to an Agent at 195.218.195.228:161 -# for an OID in tuple form -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpget -v3 -l authPriv -u usr-sha-aes -a SHA -A authkey1 -x AES -X privkey1 -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.1.0 -# +""" +SNMPv3, auth: SHA, privacy: AES ++++++++++++++++++++++++++++++++ + +Send a SNMP GET request +* with SNMPv3 with user 'usr-sha-aes', SHA auth and AES128 privacy protocols +* using Twisted framework for network transport +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for an OID in tuple form + +This script performs similar to the following Net-SNMP command: + +| $ snmpget -v3 -l authPriv -u usr-sha-aes -a SHA -A authkey1 -x AES -X privkey1 -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.1.0 + +"""# from twisted.internet import reactor, defer from pysnmp.entity import engine, config from pysnmp.entity.rfc3413.twisted import cmdgen diff --git a/examples/v3arch/twisted/manager/cmdgen/getbulk-v2c.py b/examples/v3arch/twisted/manager/cmdgen/getbulk-v2c.py index d5733aa..7adf6fe 100644 --- a/examples/v3arch/twisted/manager/cmdgen/getbulk-v2c.py +++ b/examples/v3arch/twisted/manager/cmdgen/getbulk-v2c.py @@ -1,19 +1,21 @@ -# -# GETBULK Command Generator -# -# Send a series of SNMP GETBULK requests -# with SNMPv2c, community 'public' -# using Twisted framework for network transport -# over IPv4/UDP -# to an Agent at 195.218.195.228:161 -# with values non-repeaters = 0, max-repetitions = 25 -# for two OIDs in tuple form -# stop on end-of-mib condition for both OIDs -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpbulkwalk -v2c -c public -C n0 -C r25 -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 -# +""" +Bulk walk MIB (SNMPv2c) ++++++++++++++++++++++++ + +Send a series of SNMP GETBULK requests +* with SNMPv2c, community 'public' +* using Twisted framework for network transport +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* with values non-repeaters = 0, max-repetitions = 25 +* for two OIDs in tuple form +* stop on end-of-mib condition for both OIDs + +This script performs similar to the following Net-SNMP command: + +| $ snmpbulkwalk -v2c -c public -C n0 -C r25 -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 + +"""# from twisted.internet import reactor, defer from pysnmp.entity import engine, config from pysnmp.entity.rfc3413.twisted import cmdgen diff --git a/examples/v3arch/twisted/manager/cmdgen/getbulk-v3.py b/examples/v3arch/twisted/manager/cmdgen/getbulk-v3.py index 2b734a1..04aa188 100644 --- a/examples/v3arch/twisted/manager/cmdgen/getbulk-v3.py +++ b/examples/v3arch/twisted/manager/cmdgen/getbulk-v3.py @@ -1,19 +1,21 @@ -# -# GETBULK Command Generator -# -# Send a series of SNMP GETBULK requests -# with SNMPv3 with user 'usr-md5-des', MD5 auth and DES privacy protocols -# over IPv4/UDP -# using Twisted framework for network transport -# to an Agent at 195.218.195.228:161 -# with values non-repeaters = 1, max-repetitions = 25 -# for two OIDs in tuple form (first OID is non-repeating) -# stop on end-of-mib condition for both OIDs -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpbulkwalk -v3 -l authPriv -u usr-md5-des -A authkey1 -X privkey1 -C n1 -C r25 -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 -# +""" +Walk and Bulk walk OIDs ++++++++++++++++++++++++ + +Send a series of SNMP GETBULK requests +* with SNMPv3 with user 'usr-md5-des', MD5 auth and DES privacy protocols +* over IPv4/UDP +* using Twisted framework for network transport +* to an Agent at 195.218.195.228:161 +* with values non-repeaters = 1, max-repetitions = 25 +* for two OIDs in tuple form (first OID is non-repeating) +* stop on end-of-mib condition for both OIDs + +This script performs similar to the following Net-SNMP command: + +| $ snmpbulkwalk -v3 -l authPriv -u usr-md5-des -A authkey1 -X privkey1 -C n1 -C r25 -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 + +"""# from twisted.internet import reactor, defer from pysnmp.entity import engine, config from pysnmp.entity.rfc3413.twisted import cmdgen diff --git a/examples/v3arch/twisted/manager/cmdgen/getnext-v1.py b/examples/v3arch/twisted/manager/cmdgen/getnext-v1.py index dede0ab..b7f4bb8 100644 --- a/examples/v3arch/twisted/manager/cmdgen/getnext-v1.py +++ b/examples/v3arch/twisted/manager/cmdgen/getnext-v1.py @@ -1,18 +1,20 @@ -# -# GETNEXT Command Generator -# -# Send a series of SNMP GETNEXT requests -# with SNMPv1, community 'public' -# using Twisted framework for network transport -# over IPv4/UDP -# to an Agent at 195.218.195.228:161 -# for two OIDs in tuple form -# stop on end-of-mib condition for both OIDs -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpwalk -v1 -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 -# +""" +Walk MIB (SNMPv1) ++++++++++++++++++ + +Send a series of SNMP GETNEXT requests +* with SNMPv1, community 'public' +* using Twisted framework for network transport +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for two OIDs in tuple form +* stop on end-of-mib condition for both OIDs + +This script performs similar to the following Net-SNMP command: + +| $ snmpwalk -v1 -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 + +"""# from twisted.internet import reactor, defer from pysnmp.entity import engine, config from pysnmp.entity.rfc3413.twisted import cmdgen diff --git a/examples/v3arch/twisted/manager/cmdgen/getnext-v2c-from-specific-address.py b/examples/v3arch/twisted/manager/cmdgen/getnext-v2c-from-specific-address.py index c27b643..902bd29 100644 --- a/examples/v3arch/twisted/manager/cmdgen/getnext-v2c-from-specific-address.py +++ b/examples/v3arch/twisted/manager/cmdgen/getnext-v2c-from-specific-address.py @@ -1,19 +1,21 @@ -# -# GETNEXT Command Generator -# -# Send a series of SNMP GETNEXT requests -# with SNMPv2c, community 'public' -# using Twisted framework for network transport -# over IPv4/UDP -# to an Agent at 195.218.195.228:161 -# sending packets from any local interface (0.0.0.0), local port 61024 -# for two OIDs in tuple form -# stop on end-of-mib condition for both OIDs -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpwalk -v2c -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 -# +""" +Send packets from specific local interface +++++++++++++++++++++++++++++++++++++++++++ + +Send a series of SNMP GETNEXT requests +* with SNMPv2c, community 'public' +* using Twisted framework for network transport +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* sending packets from any local interface (0.0.0.0), local port 61024 +* for two OIDs in tuple form +* stop on end-of-mib condition for both OIDs + +This script performs similar to the following Net-SNMP command: + +| $ snmpwalk -v2c -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1 1.3.6.1.4.1.1 + +"""# from twisted.internet import reactor, defer from pysnmp.entity import engine, config from pysnmp.entity.rfc3413.twisted import cmdgen diff --git a/examples/v3arch/twisted/manager/cmdgen/getnext-v3-pull-subtree.py b/examples/v3arch/twisted/manager/cmdgen/getnext-v3-pull-subtree.py index bff697e..d8e8612 100644 --- a/examples/v3arch/twisted/manager/cmdgen/getnext-v3-pull-subtree.py +++ b/examples/v3arch/twisted/manager/cmdgen/getnext-v3-pull-subtree.py @@ -1,18 +1,20 @@ -# -# GETNEXT Command Generator -# -# Send a series of SNMP GETNEXT requests -# with SNMPv3 with user 'usr-none-none', no auth and no privacy protocols -# over IPv4/UDP -# using Twisted framework for network transport -# to an Agent at 195.218.195.228:161 -# for an OID in string form -# stop whenever received OID goes out of initial prefix (it may be a table) -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpwalk -v3 -l noAuthNoPriv -u usr-none-none -ObentU 195.218.195.228:161 1.3.6.1.2.1.1 -# +""" +Pull MIB subtree (SNMPv3) ++++++++++++++++++++++++++ + +Send a series of SNMP GETNEXT requests +* with SNMPv3 with user 'usr-none-none', no auth and no privacy protocols +* over IPv4/UDP +* using Twisted framework for network transport +* to an Agent at 195.218.195.228:161 +* for an OID in string form +* stop whenever received OID goes out of initial prefix (it may be a table) + +This script performs similar to the following Net-SNMP command: + +| $ snmpwalk -v3 -l noAuthNoPriv -u usr-none-none -ObentU 195.218.195.228:161 1.3.6.1.2.1.1 + +"""# from twisted.internet import reactor, defer from pysnmp.entity import engine, config from pysnmp.entity.rfc3413.twisted import cmdgen diff --git a/examples/v3arch/twisted/manager/cmdgen/set-v1.py b/examples/v3arch/twisted/manager/cmdgen/set-v1.py index c372104..fee0ed2 100644 --- a/examples/v3arch/twisted/manager/cmdgen/set-v1.py +++ b/examples/v3arch/twisted/manager/cmdgen/set-v1.py @@ -1,17 +1,19 @@ -# -# SET Command Generator -# -# Send a SNMP SET request -# with SNMPv1, community 'private' -# using Twisted framework for network transport -# over IPv4/UDP -# to an Agent at 195.218.195.228:161 -# for OIDs in tuple form and an integer and string-typed values -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpset -v1 -c private -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.9.1.3.1 s 'my value' 1.3.6.1.2.1.1.9.1.4.1 t 123 -# +""" +SET string and integer scalars (SNMPv1) ++++++++++++++++++++++++++++++++++++++++ + +Send a SNMP SET request +* with SNMPv1, community 'private' +* using Twisted framework for network transport +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for OIDs in tuple form and an integer and string-typed values + +This script performs similar to the following Net-SNMP command: + +| $ snmpset -v1 -c private -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.9.1.3.1 s 'my value' 1.3.6.1.2.1.1.9.1.4.1 t 123 + +"""# from twisted.internet import reactor, defer from pysnmp.entity import engine, config from pysnmp.entity.rfc3413.twisted import cmdgen diff --git a/examples/v3arch/twisted/manager/cmdgen/set-v2c.py b/examples/v3arch/twisted/manager/cmdgen/set-v2c.py index 5fd91f1..e27b6e6 100644 --- a/examples/v3arch/twisted/manager/cmdgen/set-v2c.py +++ b/examples/v3arch/twisted/manager/cmdgen/set-v2c.py @@ -1,17 +1,19 @@ -# -# SET Command Generator -# -# Send a SNMP SET request -# with SNMPv2c, community 'private' -# using Twisted framework for network transport -# over IPv4/UDP -# to an Agent at 195.218.195.228:161 -# for OIDs in tuple form and an integer-typed value -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpset -v2c -c private -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.9.1.4.1 t 123 -# +""" +SET integer scalar (SNMPv2c) +++++++++++++++++++++++++++++ + +Send a SNMP SET request +* with SNMPv2c, community 'private' +* using Twisted framework for network transport +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for OIDs in tuple form and an integer-typed value + +This script performs similar to the following Net-SNMP command: + +| $ snmpset -v2c -c private -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.9.1.4.1 t 123 + +"""# from twisted.internet import reactor, defer from pysnmp.entity import engine, config from pysnmp.entity.rfc3413.twisted import cmdgen diff --git a/examples/v3arch/twisted/manager/cmdgen/set-v3.py b/examples/v3arch/twisted/manager/cmdgen/set-v3.py index 1fb7ce8..e787927 100644 --- a/examples/v3arch/twisted/manager/cmdgen/set-v3.py +++ b/examples/v3arch/twisted/manager/cmdgen/set-v3.py @@ -1,17 +1,19 @@ -# -# SET Command Generator -# -# Send a SNMP SET request -# with SNMPv3 with user 'usr-sha-none', SHA auth and no privacy protocols -# using Twisted framework for network transport -# over IPv4/UDP -# to an Agent at 195.218.195.228:161 -# for an OID in tuple form and a string-typed value -# -# This script performs similar to the following Net-SNMP command: -# -# $ snmpset -v3 -l authNoPriv -u usr-sha-none -a SHA -A authkey1 -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.9.1.3.1 s 'my new value' -# +""" +SET string scalar (SNMPv3) +++++++++++++++++++++++++++ + +Send a SNMP SET request +* with SNMPv3 with user 'usr-sha-none', SHA auth and no privacy protocols +* using Twisted framework for network transport +* over IPv4/UDP +* to an Agent at 195.218.195.228:161 +* for an OID in tuple form and a string-typed value + +This script performs similar to the following Net-SNMP command: + +| $ snmpset -v3 -l authNoPriv -u usr-sha-none -a SHA -A authkey1 -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.9.1.3.1 s 'my new value' + +"""# from twisted.internet import reactor, defer from pysnmp.entity import engine, config from pysnmp.entity.rfc3413.twisted import cmdgen diff --git a/examples/v3arch/twisted/manager/ntfrcv/v2c-multiple-interfaces.py b/examples/v3arch/twisted/manager/ntfrcv/v2c-multiple-interfaces.py index 4f9b68f..b7edf7d 100644 --- a/examples/v3arch/twisted/manager/ntfrcv/v2c-multiple-interfaces.py +++ b/examples/v3arch/twisted/manager/ntfrcv/v2c-multiple-interfaces.py @@ -1,21 +1,24 @@ -# -# Notification Receiver -# -# Receive SNMP TRAP/INFORM messages with the following options: -# -# * SNMPv1/SNMPv2c -# * with SNMP community "public" -# * over IPv4/UDP, listening at 127.0.0.1:162 -# over IPv4/UDP, listening at 127.0.0.1:2162 -# * using Twisted framework for network transport -# * print received data on stdout -# -# Either of the following Net-SNMP's commands will send notifications to this -# receiver: -# -# $ snmptrap -v2c -c public 127.0.0.1:162 123 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.5.0 s test -# $ snmpinform -v2c -c public 127.0.0.1:2162 123 1.3.6.1.6.3.1.1.5.1 -# +""" +Serving multiple network interfaces ++++++++++++++++++++++++++++++++++++ + +Receive SNMP TRAP/INFORM messages with the following options: + +* SNMPv1/SNMPv2c +* with SNMP community "public" +* listen on two local network interfaces: + * IPv4/UDP, listening at 127.0.0.1:162 + * IPv4/UDP, listening at 127.0.0.1:2162 +* using Twisted framework for network transport +* print received data on stdout + +Either of the following Net-SNMP commands will send notifications to this +receiver: + +| $ snmptrap -v2c -c public 127.0.0.1:162 123 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.5.0 s test +| $ snmpinform -v2c -c public 127.0.0.1:2162 123 1.3.6.1.6.3.1.1.5.1 + +"""# from twisted.internet import reactor from pysnmp.entity import engine, config from pysnmp.carrier.twisted.dgram import udp diff --git a/examples/v3arch/twisted/manager/ntfrcv/v3-multiple-users.py b/examples/v3arch/twisted/manager/ntfrcv/v3-multiple-users.py index 1192427..a82bd3d 100644 --- a/examples/v3arch/twisted/manager/ntfrcv/v3-multiple-users.py +++ b/examples/v3arch/twisted/manager/ntfrcv/v3-multiple-users.py @@ -1,24 +1,26 @@ -# -# Notification Receiver -# -# Receive SNMP TRAP/INFORM messages with the following options: -# -# * SNMPv3 -# * with USM users: -# 'usr-md5-des', auth: MD5, priv DES, ContextEngineId: 8000000001020304 -# 'usr-md5-none', auth: MD5, priv NONE, ContextEngineId: 8000000001020304 -# 'usr-sha-aes128', auth: SHA, priv AES, ContextEngineId: 8000000001020304 -# * over IPv4/UDP, listening at 127.0.0.1:162 -# * using Twisted framework for network transport -# * print received data on stdout -# -# Either of the following Net-SNMP's commands will send notifications to this -# receiver: -# -# $ snmptrap -v3 -u usr-md5-des -l authPriv -A authkey1 -X privkey1 -e 8000000001020304 127.0.0.1 123 1.3.6.1.6.3.1.1.5.1 -# $ snmptrap -v3 -u usr-md5-none -l authNoPriv -A authkey1 -e 8000000001020304 127.0.0.1 123 1.3.6.1.6.3.1.1.5.1 -# $ snmpinform -v3 -u usr-sha-aes128 -l authPriv -a SHA -A authkey1 -x AES -X privkey1 127.0.0.1 123 1.3.6.1.6.3.1.1.5.1 -# +""" +Multiple SNMP USM users ++++++++++++++++++++++++ + +Receive SNMP TRAP/INFORM messages with the following options: + +* SNMPv3 +* with USM users: + * 'usr-md5-des', auth: MD5, priv DES, ContextEngineId: 8000000001020304 + * 'usr-md5-none', auth: MD5, priv NONE, ContextEngineId: 8000000001020304 + * 'usr-sha-aes128', auth: SHA, priv AES, ContextEngineId: 8000000001020304 +* over IPv4/UDP, listening at 127.0.0.1:162 +* using Twisted framework for network transport +* print received data on stdout + +Either of the following Net-SNMP commands will send notifications to this +receiver: + +| $ snmptrap -v3 -u usr-md5-des -l authPriv -A authkey1 -X privkey1 -e 8000000001020304 127.0.0.1 123 1.3.6.1.6.3.1.1.5.1 +| $ snmptrap -v3 -u usr-md5-none -l authNoPriv -A authkey1 -e 8000000001020304 127.0.0.1 123 1.3.6.1.6.3.1.1.5.1 +| $ snmpinform -v3 -u usr-sha-aes128 -l authPriv -a SHA -A authkey1 -x AES -X privkey1 127.0.0.1 123 1.3.6.1.6.3.1.1.5.1 + +"""# from twisted.internet import reactor from pysnmp.entity import engine, config from pysnmp.carrier.twisted.dgram import udp diff --git a/pysnmp/entity/rfc3413/oneliner/auth.py b/pysnmp/entity/rfc3413/oneliner/auth.py index 8c7e5f6..df1eafe 100644 --- a/pysnmp/entity/rfc3413/oneliner/auth.py +++ b/pysnmp/entity/rfc3413/oneliner/auth.py @@ -3,6 +3,49 @@ from pysnmp import error from pyasn1.compat.octets import null class CommunityData: + """Creates SNMP v1/v2c configuration entry. + + This object can be used by + :py:class:`~pysnmp.entity.rfc3413.oneliner.cmdgen.AsyncCommandGenerator` or + :py:class:`~pysnmp.entity.rfc3413.oneliner.ntforg.AsyncNotificationOriginator` + and their derivatives for adding new entries to Local Configuration + Datastore (LCD) managed by :py:class:`~pysnmp.entity.engine.SnmpEngine` + class instance. + + See :RFC:`2576#section-5.3` for more information on the + *SNMP-COMMUNITY-MIB::snmpCommunityTable*. + + Parameters + ---------- + communityIndex : str + Unique index value of a row in snmpCommunityTable. If it is the + only positional parameter, it is taken as *communityName*. + communityName : str + SNMP v1/v2c community string. + mpModel : int + SNMP version - 0 for SNMPv1 and 1 for SNMPv2c. + contextEngineId : str + Indicates the location of the context in which management + information is accessed when using the community string + specified by the above communityName. + contextName : str + The context in which management information is accessed when + using the above communityName. + tag : str + Arbitrary string that specifies a set of transport endpoints + to which a notification may be sent using communityName above + (see also :RFC:`3413#section-4.1.4`). + + Examples + -------- + >>> from pysnmp.entity.rfc3413.oneliner.auth import CommunityData + >>> CommunityData('public') + CommunityData(communityIndex='s1410706889', communityName=, mpModel=1, contextEngineId=None, contextName='', tag='') + >>> CommunityData('public', 'public') + CommunityData(communityIndex='public', communityName=, mpModel=1, contextEngineId=None, contextName='', tag='') + >>> + + """ mpModel = 1 # Default is SMIv2 securityModel = mpModel + 1 securityLevel = 'noAuthNoPriv' @@ -65,8 +108,89 @@ class CommunityData: tag is None and self.tag or tag, securityName is None and self.securityName or securityName ) - + +#: No Authentication Protocol. +usmNoAuthProtocol = config.usmNoAuthProtocol +#: The HMAC-MD5-96 Digest Authentication Protocol (:RFC:`3414#section-6`) +usmHMACMD5AuthProtocol = config.usmHMACMD5AuthProtocol +#: The HMAC-SHA-96 Digest Authentication Protocol (:RFC:`3414#section-7`) +usmHMACSHAAuthProtocol = config.usmHMACSHAAuthProtocol + +#: No Privacy Protocol. +usmNoPrivProtocol = config.usmNoPrivProtocol +#: The CBC-DES Symmetric Encryption Protocol (:RFC:`3414#section-8`) +usmDESPrivProtocol = config.usmDESPrivProtocol +#: The 3DES-EDE Symmetric Encryption Protocol (`draft-reeder-snmpv3-usm-3desede-00 `_) +usm3DESEDEPrivProtocol = config.usm3DESEDEPrivProtocol +#: The CFB128-AES-128 Symmetric Encryption Protocol (:RFC:`3826#section-3`) +usmAesCfb128Protocol = config.usmAesCfb128Protocol +#: The CFB128-AES-192 Symmetric Encryption Protocol (`draft-blumenthal-aes-usm-04 `_) +usmAesCfb192Protocol = config.usmAesCfb192Protocol +#: The CFB128-AES-256 Symmetric Encryption Protocol (`draft-blumenthal-aes-usm-04 `_) +usmAesCfb256Protocol = config.usmAesCfb256Protocol + class UsmUserData: + """Creates SNMP v3 User Security Model (USM) configuration entry. + + This object can be used by + :py:class:`~pysnmp.entity.rfc3413.oneliner.cmdgen.AsyncCommandGenerator` or + :py:class:`~pysnmp.entity.rfc3413.oneliner.ntforg.AsyncNotificationOriginator` + and their derivatives for adding new entries to Local Configuration + Datastore (LCD) managed by :py:class:`~pysnmp.entity.engine.SnmpEngine` + class instance. + + See :RFC:`3414#section-5` for more information on the + *SNMP-USER-BASED-SM-MIB::usmUserTable*. + + Parameters + ---------- + userName : str + A human readable string representing the name of the SNMP USM user. + authKey : str + Initial value of the secret authentication key. If not set, + :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmNoAuthProtocol` + is implied. If set and no *authProtocol* is specified, + :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmHMACMD5AuthProtocol` + takes effect. + privKey : str + Initial value of the secret encryption key. If not set, + :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmNoPrivProtocol` + is implied. If set and no *privProtocol* is specified, + :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmDESPrivProtocol` + takes effect. + authProtocol : tuple + An indication of whether messages sent on behalf of this USM user + can be authenticated, and if so, the type of authentication protocol + which is used. + + Supported authentication protocol identifiers are: + + * :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmNoAuthProtocol` (default is *authKey* not given) + * :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmHMACMD5AuthProtocol` (default if *authKey* is given) + * :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmHMACSHAAuthProtocol` + privProtocol : tuple + An indication of whether messages sent on behalf of this USM user + be encrypted, and if so, the type of encryption protocol which is used. + + Supported encryption protocol identifiers are: + + * :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmNoPrivProtocol` (default is *authKey* not given) + * :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmDESPrivProtocol` (default if *authKey* is given) + * :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usm3DESEDEPrivProtocol` + * :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmAesCfb128Protocol` + * :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmAesCfb192Protocol` + * :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmAesCfb256Protocol` + + Examples + -------- + >>> from pysnmp.entity.rfc3413.oneliner.auth import UsmUserData + >>> UsmUserData('testuser', authKey='authenticationkey') + UsmUserData(userName='testuser', authKey=, privKey=, authProtocol=(1,3,6,1,6,3,10,1,1,2), privProtocol=(1,3,6,1,6,3,10,1,2,1)) + >>> UsmUserData('testuser', authKey='authenticationkey', privKey='encryptionkey') + UsmUserData(userName='testuser', authKey=, privKey=, authProtocol=(1,3,6,1,6,3,10,1,1,2), privProtocol=(1,3,6,1,6,3,10,1,2,2)) + >>> + + """ authKey = privKey = None authProtocol = config.usmNoAuthProtocol privProtocol = config.usmNoPrivProtocol diff --git a/pysnmp/entity/rfc3413/oneliner/cmdgen.py b/pysnmp/entity/rfc3413/oneliner/cmdgen.py index d646cf6..4f38d51 100644 --- a/pysnmp/entity/rfc3413/oneliner/cmdgen.py +++ b/pysnmp/entity/rfc3413/oneliner/cmdgen.py @@ -1,31 +1,19 @@ +from sys import version_info from pysnmp.entity import engine, config from pysnmp.entity.rfc3413 import cmdgen -from pysnmp.smi.rfc1902 import ObjectIdentity, ObjectType -from pysnmp.entity.rfc3413.oneliner.auth import CommunityData, UsmUserData -from pysnmp.entity.rfc3413.oneliner.target import UdpTransportTarget, \ - Udp6TransportTarget, UnixTransportTarget -from pysnmp.entity.rfc3413.oneliner.ctx import ContextData +from pysnmp.smi.rfc1902 import * +from pysnmp.entity.rfc3413.oneliner.auth import * +from pysnmp.entity.rfc3413.oneliner.target import * +from pysnmp.entity.rfc3413.oneliner.ctx import * from pysnmp.proto import rfc1905, errind from pysnmp.smi import view from pysnmp import nextid, error from pyasn1.type import univ, base from pyasn1.compat.octets import null + # obsolete, compatibility symbols from pysnmp.entity.rfc3413.oneliner.mibvar import MibVariable -# Auth protocol -usmHMACMD5AuthProtocol = config.usmHMACMD5AuthProtocol -usmHMACSHAAuthProtocol = config.usmHMACSHAAuthProtocol -usmNoAuthProtocol = config.usmNoAuthProtocol - -# Privacy protocol -usmDESPrivProtocol = config.usmDESPrivProtocol -usm3DESEDEPrivProtocol = config.usm3DESEDEPrivProtocol -usmAesCfb128Protocol = config.usmAesCfb128Protocol -usmAesCfb192Protocol = config.usmAesCfb192Protocol -usmAesCfb256Protocol = config.usmAesCfb256Protocol -usmNoPrivProtocol = config.usmNoPrivProtocol - # SNMP engine SnmpEngine = engine.SnmpEngine @@ -226,29 +214,21 @@ class AsyncCommandGenerator: return __varBinds - def unmakeVarBinds(self, snmpEngine, varBinds, lookupNames, lookupValues): - if lookupNames or lookupValues: + def unmakeVarBinds(self, snmpEngine, varBinds, lookupMib=False): + if lookupMib: mibViewController = self.getMibViewController(snmpEngine) varBinds = [ ObjectType(ObjectIdentity(x[0]), x[1]).resolveWithMib(mibViewController) for x in varBinds ] return varBinds - def makeVarBindsHead(self, snmpEngine, varNames): - return [ - x[0] for x in self.makeVarBinds( - snmpEngine, - [ (x, univ.Null('')) for x in varNames ] - ) - ] - # Async SNMP apps def getCmd(self, snmpEngine, authData, transportTarget, contextData, - varBinds, cbInfo, lookupNames=False, lookupValues=False): + varBinds, cbInfo, lookupMib=False): def __cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx): - lookupNames, lookupValues, cbFun, cbCtx = cbCtx + lookupMib, cbFun, cbCtx = cbCtx return cbFun( snmpEngine, sendRequestHandle, @@ -256,7 +236,7 @@ class AsyncCommandGenerator: errorStatus, errorIndex, self.unmakeVarBinds( - snmpEngine, varBinds, lookupNames, lookupValues + snmpEngine, varBinds, lookupMib ), cbCtx ) @@ -273,15 +253,15 @@ class AsyncCommandGenerator: contextData.contextName, self.makeVarBinds(snmpEngine, varBinds), __cbFun, - (lookupNames, lookupValues, cbFun, cbCtx) + (lookupMib, cbFun, cbCtx) ) def setCmd(self, snmpEngine, authData, transportTarget, contextData, - varBinds, cbInfo, lookupNames=False, lookupValues=False): + varBinds, cbInfo, lookupMib=False): def __cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx): - lookupNames, lookupValues, cbFun, cbCtx = cbCtx + lookupMib, cbFun, cbCtx = cbCtx return cbFun( snmpEngine, sendRequestHandle, @@ -289,7 +269,7 @@ class AsyncCommandGenerator: errorStatus, errorIndex, self.unmakeVarBinds( - snmpEngine, varBinds, lookupNames, lookupValues + snmpEngine, varBinds, lookupMib ), cbCtx ) @@ -306,22 +286,22 @@ class AsyncCommandGenerator: contextData.contextName, self.makeVarBinds(snmpEngine, varBinds), __cbFun, - (lookupNames, lookupValues, cbFun, cbCtx) + (lookupMib, cbFun, cbCtx) ) def nextCmd(self, snmpEngine, authData, transportTarget, contextData, - varBinds, cbInfo, lookupNames=False, lookupValues=False): + varBinds, cbInfo, lookupMib=False): def __cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBindTable, cbCtx): - lookupNames, lookupValues, cbFun, cbCtx = cbCtx + lookupMib, cbFun, cbCtx = cbCtx return cbFun( snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, - [ self.unmakeVarBinds(snmpEngine, varBindTableRow, lookupNames, lookupValues) for varBindTableRow in varBindTable ], + [ self.unmakeVarBinds(snmpEngine, varBindTableRow, lookupMib) for varBindTableRow in varBindTable ], cbCtx ) @@ -335,23 +315,23 @@ class AsyncCommandGenerator: contextData.contextEngineId, contextData.contextName, self.makeVarBinds(snmpEngine, varBinds), __cbFun, - (lookupNames, lookupValues, cbFun, cbCtx) + (lookupMib, cbFun, cbCtx) ) def bulkCmd(self, snmpEngine, authData, transportTarget, contextData, nonRepeaters, maxRepetitions, varBinds, cbInfo, - lookupNames=False, lookupValues=False): + lookupMib=False): def __cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBindTable, cbCtx): - lookupNames, lookupValues, cbFun, cbCtx = cbCtx + lookupMib, cbFun, cbCtx = cbCtx return cbFun( snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, - [ self.unmakeVarBinds(snmpEngine, varBindTableRow, lookupNames, lookupValues) for varBindTableRow in varBindTable ], + [ self.unmakeVarBinds(snmpEngine, varBindTableRow, lookupMib) for varBindTableRow in varBindTable ], cbCtx ) @@ -367,239 +347,9 @@ class AsyncCommandGenerator: nonRepeaters, maxRepetitions, self.makeVarBinds(snmpEngine, varBinds), __cbFun, - (lookupNames, lookupValues, cbFun, cbCtx) + (lookupMib, cbFun, cbCtx) ) -# Synchronous one-liner SNMP apps - -def getCmd(snmpEngine, authData, transportTarget, contextData, - *varBinds, **kwargs): - - def cbFun(snmpEngine, sendRequestHandle, - errorIndication, errorStatus, errorIndex, - varBinds, cbCtx): - cbCtx['errorIndication'] = errorIndication - cbCtx['errorStatus'] = errorStatus - cbCtx['errorIndex'] = errorIndex - cbCtx['varBinds'] = varBinds - - cbCtx = {} - - AsyncCommandGenerator().getCmd( - snmpEngine, - authData, - transportTarget, - contextData, - varBinds, - (cbFun, cbCtx), - kwargs.get('lookupNames'), - kwargs.get('lookupValues') - ) - - snmpEngine.transportDispatcher.runDispatcher() - - yield cbCtx['errorIndication'], \ - cbCtx['errorStatus'], cbCtx['errorIndex'], \ - cbCtx['varBinds'] - -def setCmd(snmpEngine, authData, transportTarget, contextData, - *varBinds, **kwargs): - - def cbFun(snmpEngine, sendRequestHandle, - errorIndication, errorStatus, errorIndex, - varBinds, cbCtx): - cbCtx['errorIndication'] = errorIndication - cbCtx['errorStatus'] = errorStatus - cbCtx['errorIndex'] = errorIndex - cbCtx['varBinds'] = varBinds - - cbCtx = {} - - AsyncCommandGenerator().setCmd( - snmpEngine, - authData, - transportTarget, - contextData, - varBinds, - (cbFun, cbCtx), - kwargs.get('lookupNames'), - kwargs.get('lookupValues') - ) - - snmpEngine.transportDispatcher.runDispatcher() - - yield cbCtx['errorIndication'], \ - cbCtx['errorStatus'], cbCtx['errorIndex'], \ - cbCtx['varBinds'] - -def nextCmd(snmpEngine, authData, transportTarget, contextData, - *varBinds, **kwargs): - - def cbFun(snmpEngine, sendRequestHandle, - errorIndication, errorStatus, errorIndex, - varBindTable, cbCtx): - cbCtx['errorIndication'] = errorIndication - cbCtx['errorStatus'] = errorStatus - cbCtx['errorIndex'] = errorIndex - cbCtx['varBindTable'] = varBindTable - - lookupNames = kwargs.get('lookupNames', False) - lookupValues = kwargs.get('lookupValues', False) - lexicographicMode = kwargs.get('lexicographicMode', False) - ignoreNonIncreasingOid = kwargs.get('ignoreNonIncreasingOid', False) - maxRows = kwargs.get('maxRows', 0) - maxCalls = kwargs.get('maxCalls', 0) - - cbCtx = {} - - cmdGen = AsyncCommandGenerator() - - initialVars = [ x[0] for x in cmdGen.makeVarBinds(snmpEngine, varBinds) ] - - totalRows = totalCalls = 0 - - while True: - cmdGen.nextCmd(snmpEngine, - authData, - transportTarget, - contextData, - [ (x[0], univ.Null()) for x in varBinds ], - (cbFun, cbCtx), - kwargs.get('lookupNames'), - kwargs.get('lookupValues')) - - snmpEngine.transportDispatcher.runDispatcher() - - errorIndication = cbCtx['errorIndication'] - errorStatus = cbCtx['errorStatus'] - errorIndex = cbCtx['errorIndex'] - - if ignoreNonIncreasingOid and errorIndication and \ - isinstance(errorIndication, errind.OidNotIncreasing): - errorIndication = None - if errorStatus or errorIndication: - if errorStatus == 2: - # Hide SNMPv1 noSuchName error which leaks in here - # from SNMPv1 Agent through internal pysnmp proxy. - errorStatus = errorStatus.clone(0) - errorIndex = errorIndex.clone(0) - yield errorIndication, errorStatus, errorIndex, varBinds - continue - else: - varBinds = cbCtx['varBindTable'] and cbCtx['varBindTable'][0] - for idx, varBind in enumerate(varBinds): - name, val = varBind - if not isinstance(val, univ.Null): - if lexicographicMode or initialVars[idx].isPrefixOf(name): - break - else: - return - - totalRows += 1 - totalCalls += 1 - - yield errorIndication, errorStatus, errorIndex, varBinds - - if maxRows and totalRows >= maxRows or \ - maxCalls and totalCalls >= maxCalls: - return - -def bulkCmd(snmpEngine, authData, transportTarget, contextData, - nonRepeaters, maxRepetitions, *varBinds, **kwargs): - - def cbFun(snmpEngine, sendRequestHandle, - errorIndication, errorStatus, errorIndex, - varBindTable, cbCtx): - cbCtx['errorIndication'] = errorIndication - cbCtx['errorStatus'] = errorStatus - cbCtx['errorIndex'] = errorIndex - cbCtx['varBindTable'] = varBindTable - - lookupNames = kwargs.get('lookupNames', False) - lookupValues = kwargs.get('lookupValues', False) - lexicographicMode = kwargs.get('lexicographicMode', False) - ignoreNonIncreasingOid = kwargs.get('ignoreNonIncreasingOid', False) - maxRows = kwargs.get('maxRows', 0) - maxCalls = kwargs.get('maxCalls', 0) - - cbCtx = {} - - cmdGen = AsyncCommandGenerator() - - initialVars = [ x[0] for x in cmdGen.makeVarBinds(snmpEngine, varBinds) ] - nullVarBinds = [ False ] * len(initialVars) - - totalRows = totalCalls = 0 - stopFlag = False - - while not stopFlag: - if maxRows and totalRows < maxRows: - maxRepetitions = min(maxRepetitions, maxRows-totalRows) - - cmdGen.bulkCmd(snmpEngine, - authData, - transportTarget, - contextData, - nonRepeaters, maxRepetitions, - [ (x[0], univ.Null()) for x in varBinds ], - (cbFun, cbCtx), - kwargs.get('lookupNames'), - kwargs.get('lookupValues')) - - snmpEngine.transportDispatcher.runDispatcher() - - errorIndication = cbCtx['errorIndication'] - errorStatus = cbCtx['errorStatus'] - errorIndex = cbCtx['errorIndex'] - varBindTable = cbCtx['varBindTable'] - - if ignoreNonIncreasingOid and errorIndication and \ - isinstance(errorIndication, errind.OidNotIncreasing): - errorIndication = None - if errorStatus or errorIndication: - if errorStatus == 2: - # Hide SNMPv1 noSuchName error which leaks in here - # from SNMPv1 Agent through internal pysnmp proxy. - errorStatus = errorStatus.clone(0) - errorIndex = errorIndex.clone(0) - yield errorIndication, errorStatus, errorIndex, varBindTable and varBindTable[0] or [] - continue - else: - for i in range(len(varBindTable)): - stopFlag = True - if len(varBindTable[i]) != len(initialVars): - varBindTable = i and varBindTable[:i-1] or [] - break - for j in range(len(varBindTable[i])): - name, val = varBindTable[i][j] - if nullVarBinds[j]: - varBindTable[i][j] = name, rfc1905.endOfMibView - continue - stopFlag = False - if isinstance(val, univ.Null): - nullVarBinds[j] = True - elif not lexicographicMode and \ - not initialVars[j].isPrefixOf(name): - varBindTable[i][j] = name, rfc1905.endOfMibView - nullVarBinds[j] = True - if stopFlag: - varBindTable = i and varBindTable[:i-1] or [] - break - - totalRows += len(varBindTable) - totalCalls += 1 - - if maxRows and totalRows >= maxRows: - if totalRows > maxRows: - varBindTable = varBindTable[:-(totalRows-maxRows)] - stopFlag = True - - if maxCalls and totalCalls >= maxCalls: - stopFlag = True - - for varBinds in varBindTable: - yield errorIndication, errorStatus, errorIndex, varBinds - # # The rest of code in this file belongs to obsolete, compatibility wrappers. # Never use interfaces below for new applications! @@ -641,7 +391,7 @@ class AsynCommandGenerator: def unmakeVarBinds(self, varBinds, lookupNames, lookupValues): return self.__asyncCmdGen.unmakeVarBinds( - self.snmpEngine, varBinds, lookupNames, lookupValues + self.snmpEngine, varBinds, lookupNames or lookupValues ) def getCmd(self, authData, transportTarget, varNames, cbInfo, @@ -668,7 +418,7 @@ class AsynCommandGenerator: ContextData(contextEngineId, contextName), [(x, self._null) for x in varNames], cbInfo, - lookupNames, lookupValues + lookupNames or lookupValues ) asyncGetCmd = getCmd @@ -695,7 +445,7 @@ class AsynCommandGenerator: self.snmpEngine, authData, transportTarget, ContextData(contextEngineId, contextName), varBinds, cbInfo, - lookupNames, lookupValues + lookupNames or lookupValues ) asyncSetCmd = setCmd @@ -724,7 +474,7 @@ class AsynCommandGenerator: ContextData(contextEngineId, contextName), [(x, self._null) for x in varNames], cbInfo, - lookupNames, lookupValues + lookupNames or lookupValues ) asyncNextCmd = nextCmd @@ -755,7 +505,7 @@ class AsynCommandGenerator: nonRepeaters, maxRepetitions, [(x, self._null) for x in varNames], cbInfo, - lookupNames, lookupValues + lookupNames or lookupValues ) asyncBulkCmd = bulkCmd @@ -816,3 +566,8 @@ class CommandGenerator: return errorIndication, errorStatus, errorIndex, varBindTable +# circular module import dependency +if version_info[:2] < (2, 6): + from pysnmp.entity.rfc3413.oneliner.sync.compat.cmdgen import * +else: + from pysnmp.entity.rfc3413.oneliner.sync.cmdgen import * diff --git a/pysnmp/entity/rfc3413/oneliner/ctx.py b/pysnmp/entity/rfc3413/oneliner/ctx.py index 3449912..528a2b0 100644 --- a/pysnmp/entity/rfc3413/oneliner/ctx.py +++ b/pysnmp/entity/rfc3413/oneliner/ctx.py @@ -1,6 +1,41 @@ from pyasn1.compat.octets import null class ContextData: + """Creates UDP/IPv6 configuration entry and initialize socket API if needed. + + This object can be used by + :py:class:`~pysnmp.entity.rfc3413.oneliner.cmdgen.AsyncCommandGenerator` or + :py:class:`~pysnmp.entity.rfc3413.oneliner.ntforg.AsyncNotificationOriginator` + and their derevatives for forming SNMP PDU and also adding new entries to + Local Configuration Datastore (LCD) in order to support SNMPv1/v2c with + SNMPv3 interoperability. + + See :RFC:`3411#section-4.1` for SNMP Context details. + + Parameters + ---------- + contextEngineId : str + Uniquely identifies an SNMP entity that may realize an instance of + a MIB with a particular contextName (:RFC:`3411#section-3.3.2`). + More frequently than not, ContextEngineID is the same as + authoritative SnmpEngineID, however if SNMP Engine serves multiple + SNMP Entities, their ContextEngineIDs would be distinct. + Default is authoritative SNMP Engine ID. + contextName : str + Used to name an instance of MIB (:RFC:`3411#section-3.3.3`). + Default is empty string. + + Examples + -------- + >>> from pysnmp.entity.rfc3413.oneliner.ctx import ContextData + >>> ContextData() + ContextData(contextEngineId=None, contextName='') + >>> ContextData(OctetString(hexValue='01020ABBA0')) + ContextData(contextEngineId=OctetString(hexValue='01020abba0'), contextName='') + >>> ContextData(contextName='mycontext') + ContextData(contextEngineId=None, contextName='mycontext') + + """ def __init__(self, contextEngineId=None, contextName=null): self.contextEngineId = contextEngineId self.contextName = contextName diff --git a/pysnmp/entity/rfc3413/oneliner/ntforg.py b/pysnmp/entity/rfc3413/oneliner/ntforg.py index 6ff9215..96a8456 100644 --- a/pysnmp/entity/rfc3413/oneliner/ntforg.py +++ b/pysnmp/entity/rfc3413/oneliner/ntforg.py @@ -1,30 +1,16 @@ from pyasn1.compat.octets import null from pysnmp import nextid, error from pysnmp.entity import engine, config -from pysnmp.smi.rfc1902 import ObjectIdentity, ObjectType, NotificationType +from pysnmp.smi.rfc1902 import * from pysnmp.entity.rfc3413 import ntforg, context -from pysnmp.entity.rfc3413.oneliner.auth import CommunityData, UsmUserData -from pysnmp.entity.rfc3413.oneliner.target import UdpTransportTarget, \ - Udp6TransportTarget, UnixTransportTarget +from pysnmp.entity.rfc3413.oneliner.auth import * +from pysnmp.entity.rfc3413.oneliner.target import * +from pysnmp.entity.rfc3413.oneliner.ctx import * from pysnmp.entity.rfc3413.oneliner import cmdgen # obsolete, compatibility symbols from pysnmp.entity.rfc3413.oneliner.mibvar import MibVariable -# Auth protocol -usmHMACMD5AuthProtocol = config.usmHMACMD5AuthProtocol -usmHMACSHAAuthProtocol = config.usmHMACSHAAuthProtocol -usmNoAuthProtocol = config.usmNoAuthProtocol - -# Privacy protocol -usmDESPrivProtocol = config.usmDESPrivProtocol -usm3DESEDEPrivProtocol = config.usm3DESEDEPrivProtocol -usmAesCfb128Protocol = config.usmAesCfb128Protocol -usmAesCfb192Protocol = config.usmAesCfb192Protocol -usmAesCfb256Protocol = config.usmAesCfb256Protocol -usmNoPrivProtocol = config.usmNoPrivProtocol - SnmpEngine = engine.SnmpEngine -ContextData = cmdgen.ContextData nextID = nextid.Integer(0xffffffff) @@ -135,8 +121,8 @@ class AsyncNotificationOriginator: __varBinds.append(varBind.resolveWithMib(mibViewController)) return __varBinds - def unmakeVarBinds(self, snmpEngine, varBinds, lookupNames, lookupValues): - if lookupNames or lookupValues: + def unmakeVarBinds(self, snmpEngine, varBinds, lookupMib=False): + if lookupMib: mibViewController = self.getMibViewController(snmpEngine) varBinds = [ ObjectType(ObjectIdentity(x[0]), x[1]).resolveWithMib(mibViewController) for x in varBinds ] return varBinds @@ -144,20 +130,20 @@ class AsyncNotificationOriginator: def sendNotification(self, snmpEngine, authData, transportTarget, contextData, notifyType, - varBinds=(), + varBinds, cbInfo=(None, None), - lookupNames=False, lookupValues=False): + lookupMib=False): def __cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx): - lookupNames, lookupValues, cbFun, cbCtx = cbCtx + lookupMib, cbFun, cbCtx = cbCtx return cbFun and cbFun( snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, self.unmakeVarBinds( - snmpEngine, varBinds, lookupNames, lookupValues + snmpEngine, varBinds, lookupMib ), cbCtx ) @@ -176,43 +162,7 @@ class AsyncNotificationOriginator: snmpEngine, authData, transportTarget, notifyType ) - return ntforg.NotificationOriginator().sendVarBinds(snmpEngine, notifyName, contextData.contextEngineId, contextData.contextName, self.makeVarBinds(snmpEngine, varBinds), __cbFun, (lookupNames, lookupValues, cbFun, cbCtx)) - -# -# Synchronous one-liner Notification Originator application -# - -def sendNotification(snmpEngine, authData, transportTarget, contextData, - notifyType, notificationType, **kwargs): - - def cbFun(snmpEngine, sendRequestHandle, - errorIndication, errorStatus, errorIndex, - varBinds, cbCtx): - cbCtx['errorIndication'] = errorIndication - cbCtx['errorStatus'] = errorStatus - cbCtx['errorIndex'] = errorIndex - cbCtx['varBinds'] = varBinds - - cbCtx = {} - - AsyncNotificationOriginator().sendNotification( - snmpEngine, - authData, - transportTarget, - contextData, - notifyType, - notificationType, - (cbFun, cbCtx), - kwargs.get('lookupNames'), - kwargs.get('lookupValues') - ) - - snmpEngine.transportDispatcher.runDispatcher() - - if cbCtx: - yield cbCtx['errorIndication'], \ - cbCtx['errorStatus'], cbCtx['errorIndex'], \ - cbCtx['varBinds'] + return ntforg.NotificationOriginator().sendVarBinds(snmpEngine, notifyName, contextData.contextEngineId, contextData.contextName, self.makeVarBinds(snmpEngine, varBinds), __cbFun, (lookupMib, cbFun, cbCtx)) # # The rest of code in this file belongs to obsolete, compatibility wrappers. @@ -256,6 +206,16 @@ class AsynNotificationOriginator: def uncfgNtfOrg(self, authData=None): return self.__asyncNtfOrg.uncfgNtfOrg(self.snmpEngine, authData) + def makeVarBinds(self, varBinds): + return self.__asyncNtfOrg.makeVarBinds( + self.snmpEngine, varBinds + ) + + def unmakeVarBinds(self, varBinds, lookupNames, lookupValues): + return self.__asyncNtfOrg.unmakeVarBinds( + self.snmpEngine, varBinds, lookupNames or lookupValues + ) + def sendNotification(self, authData, transportTarget, notifyType, notificationType, varBinds=(), # legacy, use NotificationType instead @@ -306,7 +266,7 @@ class AsynNotificationOriginator: contextName), notifyType, notificationType.addVarBinds(*varBinds), (__cbFun, cbInfo), - lookupNames, lookupValues + lookupNames or lookupValues ) asyncSendNotification = sendNotification @@ -328,3 +288,10 @@ class NotificationOriginator: notificationType.addVarBinds(*varBinds), **kwargs): return x + +# circular module import dependency +from sys import version_info +if version_info[:2] < (2, 6): + from pysnmp.entity.rfc3413.oneliner.sync.compat.ntforg import * +else: + from pysnmp.entity.rfc3413.oneliner.sync.ntforg import * diff --git a/pysnmp/entity/rfc3413/oneliner/sync/__init__.py b/pysnmp/entity/rfc3413/oneliner/sync/__init__.py new file mode 100644 index 0000000..8c3066b --- /dev/null +++ b/pysnmp/entity/rfc3413/oneliner/sync/__init__.py @@ -0,0 +1 @@ +# This file is necessary to make this directory a package. diff --git a/pysnmp/entity/rfc3413/oneliner/sync/cmdgen.py b/pysnmp/entity/rfc3413/oneliner/sync/cmdgen.py new file mode 100644 index 0000000..b3a42d7 --- /dev/null +++ b/pysnmp/entity/rfc3413/oneliner/sync/cmdgen.py @@ -0,0 +1,602 @@ +from pysnmp.entity.rfc3413.oneliner.cmdgen import * + +if version_info[:2] < (2, 6): + def next(iter): + return iter.next() + +def getCmd(snmpEngine, authData, transportTarget, contextData, + *varBinds, **options): + """Creates a generator to perform one or more SNMP GET queries. + + On each iteration, new SNMP GET request is send (:RFC:`1905#section-4.2.1`). + The iterator blocks waiting for response to arrive or error to occur. + + Parameters + ---------- + snmpEngine : :py:class:`~pysnmp.entity.engine.SnmpEngine` + Class instance representing SNMP engine. + + authData : :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.CommunityData` or :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.UsmUserData` + Class instance representing SNMP credentials. + + transportTarget : :py:class:`~pysnmp.entity.rfc3413.oneliner.target.UdpTransportTarget` or :py:class:`~pysnmp.entity.rfc3413.oneliner.target.Udp6TransportTarget` + Class instance representing transport type along with SNMP peer address. + + contextData : :py:class:`~pysnmp.entity.rfc3413.oneliner.ctx.ContextData` + Class instance representing SNMP ContextEngineId and ContextName values. + + *varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType` + One or more class instances representing MIB variables to place + into SNMP request. + + Other Parameters + ---------------- + **options : + Request options: + + * `lookupMib` - load MIB and resolve response MIB variables at + the cost of slightly reduced performance. Default is `True`. + + Yields + ------ + errorIndication : str + True value indicates SNMP engine error. + errorStatus : str + Non-zero value indicates SNMP PDU error. + errorIndex : int + Non-zero value refers to *varBinds[errorIndex-1] + varBinds : tuple + A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class + instances representing MIB variables returned in SNMP response. + + Raises + ------ + PySnmpError + Or its derivative indicating that an error occurred while + performing SNMP operation. + + Notes + ----- + The `getCmd` generator will be exhausted immidiately unless + a new sequence of `varBinds` are send back into running generator + (supported since Python 2.6). + + Examples + -------- + >>> from pysnmp.entity.rfc3413.oneliner.cmdgen import * + >>> g = getCmd(SnmpEngine(), + ... CommunityData('public'), + ... UdpTransportTarget(('demo.snmplabs.com', 161)), + ... ContextData(), + ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0))) + >>> next(g) + (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))]) + >>> + + """ + def cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBinds, cbCtx): + cbCtx['errorIndication'] = errorIndication + cbCtx['errorStatus'] = errorStatus + cbCtx['errorIndex'] = errorIndex + cbCtx['varBinds'] = varBinds + + cbCtx = {} + + cmdGen = AsyncCommandGenerator() + + while True: + if varBinds: + cmdGen.getCmd( + snmpEngine, + authData, + transportTarget, + contextData, + varBinds, + (cbFun, cbCtx), + options.get('lookupMib', True) + ) + + snmpEngine.transportDispatcher.runDispatcher() + + errorIndication = cbCtx['errorIndication'] + errorStatus = cbCtx['errorStatus'] + errorIndex = cbCtx['errorIndex'] + varBinds = cbCtx['varBinds'] + else: + errorIndication = errorStatus = errorIndex = None + varBinds = [] + + varBinds = ( yield errorIndication, errorStatus, errorIndex, varBinds ) + + if not varBinds: + break + +def setCmd(snmpEngine, authData, transportTarget, contextData, + *varBinds, **options): + """Creates a generator to perform one or more SNMP SET queries. + + On each iteration, new SNMP SET request is send (:RFC:`1905#section-4.2.5`). + The iterator blocks waiting for response to arrive or error to occur. + + Parameters + ---------- + snmpEngine : :py:class:`~pysnmp.entity.engine.SnmpEngine` + Class instance representing SNMP engine. + + authData : :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.CommunityData` or :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.UsmUserData` + Class instance representing SNMP credentials. + + transportTarget : :py:class:`~pysnmp.entity.rfc3413.oneliner.target.UdpTransportTarget` or :py:class:`~pysnmp.entity.rfc3413.oneliner.target.Udp6TransportTarget` + Class instance representing transport type along with SNMP peer address. + + contextData : :py:class:`~pysnmp.entity.rfc3413.oneliner.ctx.ContextData` + Class instance representing SNMP ContextEngineId and ContextName values. + + *varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType` + One or more class instances representing MIB variables to place + into SNMP request. + + Other Parameters + ---------------- + **options : + Request options: + + * `lookupMib` - load MIB and resolve response MIB variables at + the cost of slightly reduced performance. Default is `True`. + Default is `True`. + + Yields + ------ + errorIndication : str + True value indicates SNMP engine error. + errorStatus : str + Non-zero value indicates SNMP PDU error. + errorIndex : int + Non-zero value refers to *varBinds[errorIndex-1] + varBinds : tuple + A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class + instances representing MIB variables returned in SNMP response. + + Raises + ------ + PySnmpError + Or its derivative indicating that an error occurred while + performing SNMP operation. + + Notes + ----- + The `setCmd` generator will be exhausted immidiately unless + a new sequence of `varBinds` are send back into running generator + (supported since Python 2.6). + + Examples + -------- + >>> from pysnmp.entity.rfc3413.oneliner.cmdgen import * + >>> g = setCmd(SnmpEngine(), + ... CommunityData('public'), + ... UdpTransportTarget(('demo.snmplabs.com', 161)), + ... ContextData(), + ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0), 'Linux i386')) + >>> next(g) + (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('Linux i386'))]) + >>> + + """ + def cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBinds, cbCtx): + cbCtx['errorIndication'] = errorIndication + cbCtx['errorStatus'] = errorStatus + cbCtx['errorIndex'] = errorIndex + cbCtx['varBinds'] = varBinds + + cbCtx = {} + + cmdGen = AsyncCommandGenerator() + + while True: + if varBinds: + cmdGen.setCmd( + snmpEngine, + authData, + transportTarget, + contextData, + varBinds, + (cbFun, cbCtx), + options.get('lookupMib', True) + ) + + snmpEngine.transportDispatcher.runDispatcher() + + errorIndication = cbCtx['errorIndication'] + errorStatus = cbCtx['errorStatus'] + errorIndex = cbCtx['errorIndex'] + varBinds = cbCtx['varBinds'] + else: + errorIndication = errorStatus = errorIndex = None + varBinds = [] + + varBinds = ( yield errorIndication, errorStatus, errorIndex, varBinds ) + + if not varBinds: + break + +def nextCmd(snmpEngine, authData, transportTarget, contextData, + *varBinds, **options): + """Creates a generator to perform one or more SNMP GETNEXT queries. + + On each iteration, new SNMP GETNEXT request is send + (:RFC:`1905#section-4.2.2`). The iterator blocks waiting for response + to arrive or error to occur. + + Parameters + ---------- + snmpEngine : :py:class:`~pysnmp.entity.engine.SnmpEngine` + Class instance representing SNMP engine. + + authData : :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.CommunityData` or :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.UsmUserData` + Class instance representing SNMP credentials. + + transportTarget : :py:class:`~pysnmp.entity.rfc3413.oneliner.target.UdpTransportTarget` or :py:class:`~pysnmp.entity.rfc3413.oneliner.target.Udp6TransportTarget` + Class instance representing transport type along with SNMP peer address. + + contextData : :py:class:`~pysnmp.entity.rfc3413.oneliner.ctx.ContextData` + Class instance representing SNMP ContextEngineId and ContextName values. + + *varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType` + One or more class instances representing MIB variables to place + into SNMP request. + + Other Parameters + ---------------- + **options : + Request options: + + * `lookupMib` - load MIB and resolve response MIB variables at + the cost of slightly reduced performance. Default is `True`. + Default is `True`. + * `lexicographicMode` - stop iteration when all response MIB + variables leave the scope of initial MIB variables in + `varBinds`. Default is `True`. + * `ignoreNonIncreasingOid` - continue iteration even if response + MIB variables (OIDs) are not greater then request MIB variables. + Default is `False`. + * `maxRows` - stop iteration once this generator instance processed + `maxRows` of SNMP conceptual table. Default is `0` (no limit). + * `maxCalls` - stop iteration once this generator instance processed + `maxCalls` responses. Default is 0 (no limit). + + Yields + ------ + errorIndication : str + True value indicates SNMP engine error. + errorStatus : str + Non-zero value indicates SNMP PDU error. + errorIndex : int + Non-zero value refers to *varBinds[errorIndex-1] + varBinds : tuple + A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class + instances representing MIB variables returned in SNMP response. + + Raises + ------ + PySnmpError + Or its derivative indicating that an error occurred while + performing SNMP operation. + + Notes + ----- + The `nextCmd` generator will be exhausted on any of the following + conditions: + + * SNMP engine error occurs thus `errorIndication` is `True` + * SNMP PDU `errorStatus` is reported as `True` + * SNMP :py:class:`~pysnmp.proto.rfc1905.EndOfMibView` values + (also known as *SNMP exception values*) are reported for all + MIB variables in `varBinds` + * *lexicographicMode* option is set to `False` and all + response MIB variables leave the scope of `varBinds` + + At any moment a new sequence of `varBinds` could be send back into + running generator (supported since Python 2.6). + + Examples + -------- + >>> from pysnmp.entity.rfc3413.oneliner.cmdgen import * + >>> g = nextCmd(SnmpEngine(), + ... CommunityData('public'), + ... UdpTransportTarget(('demo.snmplabs.com', 161)), + ... ContextData(), + ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr'))) + >>> next(g) + (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))]) + >>> g.send( [ ObjectType(ObjectIdentity('IF-MIB', 'ifInOctets')) ] ) + (None, 0, 0, [(ObjectName('1.3.6.1.2.1.2.2.1.10.1'), Counter32(284817787))]) + """ + def cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBindTable, cbCtx): + cbCtx['errorIndication'] = errorIndication + cbCtx['errorStatus'] = errorStatus + cbCtx['errorIndex'] = errorIndex + cbCtx['varBindTable'] = varBindTable + + lookupMib = options.get('lookupMib', True) + lexicographicMode = options.get('lexicographicMode', True) + ignoreNonIncreasingOid = options.get('ignoreNonIncreasingOid', False) + maxRows = options.get('maxRows', 0) + maxCalls = options.get('maxCalls', 0) + + cbCtx = {} + + cmdGen = AsyncCommandGenerator() + + initialVars = [ x[0] for x in cmdGen.makeVarBinds(snmpEngine, varBinds) ] + + totalRows = totalCalls = 0 + + while True: + if varBinds: + cmdGen.nextCmd(snmpEngine, + authData, + transportTarget, + contextData, + [ (x[0], univ.Null()) for x in varBinds ], + (cbFun, cbCtx), + lookupMib) + + snmpEngine.transportDispatcher.runDispatcher() + + errorIndication = cbCtx['errorIndication'] + errorStatus = cbCtx['errorStatus'] + errorIndex = cbCtx['errorIndex'] + + if ignoreNonIncreasingOid and errorIndication and \ + isinstance(errorIndication, errind.OidNotIncreasing): + errorIndication = None + + if errorIndication: + yield errorIndication, errorStatus, errorIndex, varBinds + return + elif errorStatus: + if errorStatus == 2: + # Hide SNMPv1 noSuchName error which leaks in here + # from SNMPv1 Agent through internal pysnmp proxy. + errorStatus = errorStatus.clone(0) + errorIndex = errorIndex.clone(0) + yield errorIndication, errorStatus, errorIndex, varBinds + return + else: + varBinds = cbCtx['varBindTable'] and cbCtx['varBindTable'][0] + for idx, varBind in enumerate(varBinds): + name, val = varBind + if not isinstance(val, univ.Null): + if lexicographicMode or initialVars[idx].isPrefixOf(name): + break + else: + return + + totalRows += 1 + totalCalls += 1 + else: + errorIndication = errorStatus = errorIndex = None + varBinds = [] + + initialVarBinds = ( yield errorIndication, errorStatus, + errorIndex, varBinds ) + + if initialVarBinds: + varBinds = initialVarBinds + initialVars = [ x[0] for x in cmdGen.makeVarBinds(snmpEngine, + varBinds) ] + + if maxRows and totalRows >= maxRows or \ + maxCalls and totalCalls >= maxCalls: + return + +def bulkCmd(snmpEngine, authData, transportTarget, contextData, + nonRepeaters, maxRepetitions, *varBinds, **options): + """Creates a generator to perform one or more SNMP GETBULK queries. + + On each iteration, new SNMP GETBULK request is send + (:RFC:`1905#section-4.2.3`). The iterator blocks waiting for response + to arrive or error to occur. + + Parameters + ---------- + snmpEngine : :py:class:`~pysnmp.entity.engine.SnmpEngine` + Class instance representing SNMP engine. + + authData : :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.CommunityData` or :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.UsmUserData` + Class instance representing SNMP credentials. + + transportTarget : :py:class:`~pysnmp.entity.rfc3413.oneliner.target.UdpTransportTarget` or :py:class:`~pysnmp.entity.rfc3413.oneliner.target.Udp6TransportTarget` + Class instance representing transport type along with SNMP peer address. + + contextData : :py:class:`~pysnmp.entity.rfc3413.oneliner.ctx.ContextData` + Class instance representing SNMP ContextEngineId and ContextName values. + + nonRepeaters : int + One MIB variable is requested in response for the first + `nonRepeaters` MIB variables in request. + + maxRepetitions : int + `maxRepetitions` MIB variables are requested in response for each + of the remaining MIB variables in the request (e.g. excluding + `nonRepeaters`). Remote SNMP engine may choose lesser value than + requested. + + *varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType` + One or more class instances representing MIB variables to place + into SNMP request. + + Other Parameters + ---------------- + **options : + Request options: + + * `lookupMib` - load MIB and resolve response MIB variables at + the cost of slightly reduced performance. Default is `True`. + Default is `True`. + * `lexicographicMode` - stop iteration when all response MIB + variables leave the scope of initial MIB variables in + `varBinds`. Default is `True`. + * `ignoreNonIncreasingOid` - continue iteration even if response + MIB variables (OIDs) are not greater then request MIB variables. + Default is `False`. + * `maxRows` - stop iteration once this generator instance processed + `maxRows` of SNMP conceptual table. Default is `0` (no limit). + * `maxCalls` - stop iteration once this generator instance processed + `maxCalls` responses. Default is 0 (no limit). + + Yields + ------ + errorIndication : str + True value indicates SNMP engine error. + errorStatus : str + Non-zero value indicates SNMP PDU error. + errorIndex : int + Non-zero value refers to *varBinds[errorIndex-1] + varBinds : tuple + A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class + instances representing MIB variables returned in SNMP response. + + Raises + ------ + PySnmpError + Or its derivative indicating that an error occurred while + performing SNMP operation. + + Notes + ----- + The `bulkCmd` generator will be exhausted on any of the following + conditions: + + * SNMP engine error occurs thus `errorIndication` is `True` + * SNMP PDU `errorStatus` is reported as `True` + * SNMP :py:class:`~pysnmp.proto.rfc1905.EndOfMibView` values + (also known as *SNMP exception values*) are reported for all + MIB variables in `varBinds` + * *lexicographicMode* option is set to `False` and all + response MIB variables leave the scope of `varBinds` + + At any moment a new sequence of `varBinds` could be send back into + running generator (supported since Python 2.6). + + Setting `maxRepetitions` value to 15..50 might significantly improve + system performance, as many MIB variables get packed into a single + response message at once. + + Examples + -------- + >>> from pysnmp.entity.rfc3413.oneliner.cmdgen import * + >>> g = bulkCmd(SnmpEngine(), + ... CommunityData('public'), + ... UdpTransportTarget(('demo.snmplabs.com', 161)), + ... ContextData(), + ... 0, 25, + ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr'))) + >>> next(g) + (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))]) + >>> g.send( [ ObjectType(ObjectIdentity('IF-MIB', 'ifInOctets')) ] ) + (None, 0, 0, [(ObjectName('1.3.6.1.2.1.2.2.1.10.1'), Counter32(284817787))]) + """ + def cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBindTable, cbCtx): + cbCtx['errorIndication'] = errorIndication + cbCtx['errorStatus'] = errorStatus + cbCtx['errorIndex'] = errorIndex + cbCtx['varBindTable'] = varBindTable + + lookupMib = options.get('lookupMib', True) + lexicographicMode = options.get('lexicographicMode', True) + ignoreNonIncreasingOid = options.get('ignoreNonIncreasingOid', False) + maxRows = options.get('maxRows', 0) + maxCalls = options.get('maxCalls', 0) + + cbCtx = {} + + cmdGen = AsyncCommandGenerator() + + initialVars = [ x[0] for x in cmdGen.makeVarBinds(snmpEngine, varBinds) ] + nullVarBinds = [ False ] * len(initialVars) + + totalRows = totalCalls = 0 + stopFlag = False + + while not stopFlag: + if maxRows and totalRows < maxRows: + maxRepetitions = min(maxRepetitions, maxRows-totalRows) + + cmdGen.bulkCmd(snmpEngine, + authData, + transportTarget, + contextData, + nonRepeaters, maxRepetitions, + [ (x[0], univ.Null()) for x in varBinds ], + (cbFun, cbCtx), + lookupMib) + + snmpEngine.transportDispatcher.runDispatcher() + + errorIndication = cbCtx['errorIndication'] + errorStatus = cbCtx['errorStatus'] + errorIndex = cbCtx['errorIndex'] + varBindTable = cbCtx['varBindTable'] + + if ignoreNonIncreasingOid and errorIndication and \ + isinstance(errorIndication, errind.OidNotIncreasing): + errorIndication = None + + if errorIndication: + yield errorIndication, errorStatus, errorIndex, \ + varBindTable and varBindTable[0] or [] + if errorIndication != errind.requestTimedOut: + return + elif errorStatus: + if errorStatus == 2: + # Hide SNMPv1 noSuchName error which leaks in here + # from SNMPv1 Agent through internal pysnmp proxy. + errorStatus = errorStatus.clone(0) + errorIndex = errorIndex.clone(0) + yield errorIndication, errorStatus, errorIndex, \ + varBindTable and varBindTable[0] or [] + return + else: + for i in range(len(varBindTable)): + stopFlag = True + if len(varBindTable[i]) != len(initialVars): + varBindTable = i and varBindTable[:i-1] or [] + break + for j in range(len(varBindTable[i])): + name, val = varBindTable[i][j] + if nullVarBinds[j]: + varBindTable[i][j] = name, rfc1905.endOfMibView + continue + stopFlag = False + if isinstance(val, univ.Null): + nullVarBinds[j] = True + elif not lexicographicMode and \ + not initialVars[j].isPrefixOf(name): + varBindTable[i][j] = name, rfc1905.endOfMibView + nullVarBinds[j] = True + if stopFlag: + varBindTable = i and varBindTable[:i-1] or [] + break + + totalRows += len(varBindTable) + totalCalls += 1 + + if maxRows and totalRows >= maxRows: + if totalRows > maxRows: + varBindTable = varBindTable[:-(totalRows-maxRows)] + stopFlag = True + + if maxCalls and totalCalls >= maxCalls: + stopFlag = True + + for varBinds in varBindTable: + yield errorIndication, errorStatus, errorIndex, varBinds diff --git a/pysnmp/entity/rfc3413/oneliner/sync/compat/__init__.py b/pysnmp/entity/rfc3413/oneliner/sync/compat/__init__.py new file mode 100644 index 0000000..8c3066b --- /dev/null +++ b/pysnmp/entity/rfc3413/oneliner/sync/compat/__init__.py @@ -0,0 +1 @@ +# This file is necessary to make this directory a package. diff --git a/pysnmp/entity/rfc3413/oneliner/sync/compat/cmdgen.py b/pysnmp/entity/rfc3413/oneliner/sync/compat/cmdgen.py new file mode 100644 index 0000000..ebe3296 --- /dev/null +++ b/pysnmp/entity/rfc3413/oneliner/sync/compat/cmdgen.py @@ -0,0 +1,256 @@ +from pysnmp.entity.rfc3413.oneliner.cmdgen import * + +# Synchronous one-liner SNMP Command Generator apps + +if version_info[:2] < (2, 6): + def next(iter): + return iter.next() + +def getCmd(snmpEngine, authData, transportTarget, contextData, + *varBinds, **options): + + def cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBinds, cbCtx): + cbCtx['errorIndication'] = errorIndication + cbCtx['errorStatus'] = errorStatus + cbCtx['errorIndex'] = errorIndex + cbCtx['varBinds'] = varBinds + + cbCtx = {} + + cmdGen = AsyncCommandGenerator() + + if varBinds: + cmdGen.getCmd( + snmpEngine, + authData, + transportTarget, + contextData, + varBinds, + (cbFun, cbCtx), + options.get('lookupMib', True) + ) + + snmpEngine.transportDispatcher.runDispatcher() + + errorIndication = cbCtx['errorIndication'] + errorStatus = cbCtx['errorStatus'] + errorIndex = cbCtx['errorIndex'] + varBinds = cbCtx['varBinds'] + else: + errorIndication = errorStatus = errorIndex = None + varBinds = [] + + yield errorIndication, errorStatus, errorIndex, varBinds + +def setCmd(snmpEngine, authData, transportTarget, contextData, + *varBinds, **options): + + def cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBinds, cbCtx): + cbCtx['errorIndication'] = errorIndication + cbCtx['errorStatus'] = errorStatus + cbCtx['errorIndex'] = errorIndex + cbCtx['varBinds'] = varBinds + + cbCtx = {} + + cmdGen = AsyncCommandGenerator() + + while True: + cmdGen.setCmd( + snmpEngine, + authData, + transportTarget, + contextData, + varBinds, + (cbFun, cbCtx), + options.get('lookupMib', True) + ) + + snmpEngine.transportDispatcher.runDispatcher() + + yield cbCtx['errorIndication'], \ + cbCtx['errorStatus'], cbCtx['errorIndex'], \ + cbCtx['varBinds'] + + if cbCtx['errorIndication'] != errind.requestTimedOut: + break + +def nextCmd(snmpEngine, authData, transportTarget, contextData, + *varBinds, **options): + + def cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBindTable, cbCtx): + cbCtx['errorIndication'] = errorIndication + cbCtx['errorStatus'] = errorStatus + cbCtx['errorIndex'] = errorIndex + cbCtx['varBindTable'] = varBindTable + + lookupMib = options.get('lookupMib', True) + lexicographicMode = options.get('lexicographicMode', True) + ignoreNonIncreasingOid = options.get('ignoreNonIncreasingOid', False) + maxRows = options.get('maxRows', 0) + maxCalls = options.get('maxCalls', 0) + + cbCtx = {} + + cmdGen = AsyncCommandGenerator() + + initialVars = [ x[0] for x in cmdGen.makeVarBinds(snmpEngine, varBinds) ] + + totalRows = totalCalls = 0 + + while True: + cmdGen.nextCmd(snmpEngine, + authData, + transportTarget, + contextData, + [ (x[0], univ.Null()) for x in varBinds ], + (cbFun, cbCtx), + lookupMib) + + snmpEngine.transportDispatcher.runDispatcher() + + errorIndication = cbCtx['errorIndication'] + errorStatus = cbCtx['errorStatus'] + errorIndex = cbCtx['errorIndex'] + + if ignoreNonIncreasingOid and errorIndication and \ + isinstance(errorIndication, errind.OidNotIncreasing): + errorIndication = None + + if errorIndication: + yield errorIndication, errorStatus, errorIndex, varBinds + if errorIndication != errind.requestTimedOut: + return + elif errorStatus: + if errorStatus == 2: + # Hide SNMPv1 noSuchName error which leaks in here + # from SNMPv1 Agent through internal pysnmp proxy. + errorStatus = errorStatus.clone(0) + errorIndex = errorIndex.clone(0) + yield errorIndication, errorStatus, errorIndex, varBinds + return + else: + varBinds = cbCtx['varBindTable'] and cbCtx['varBindTable'][0] + for idx, varBind in enumerate(varBinds): + name, val = varBind + if not isinstance(val, univ.Null): + if lexicographicMode or initialVars[idx].isPrefixOf(name): + break + else: + return + + totalRows += 1 + totalCalls += 1 + + yield errorIndication, errorStatus, errorIndex, varBinds + + if maxRows and totalRows >= maxRows or \ + maxCalls and totalCalls >= maxCalls: + return + +def bulkCmd(snmpEngine, authData, transportTarget, contextData, + nonRepeaters, maxRepetitions, *varBinds, **options): + + def cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBindTable, cbCtx): + cbCtx['errorIndication'] = errorIndication + cbCtx['errorStatus'] = errorStatus + cbCtx['errorIndex'] = errorIndex + cbCtx['varBindTable'] = varBindTable + + lookupMib = options.get('lookupMib', True) + lexicographicMode = options.get('lexicographicMode', True) + ignoreNonIncreasingOid = options.get('ignoreNonIncreasingOid', False) + maxRows = options.get('maxRows', 0) + maxCalls = options.get('maxCalls', 0) + + cbCtx = {} + + cmdGen = AsyncCommandGenerator() + + initialVars = [ x[0] for x in cmdGen.makeVarBinds(snmpEngine, varBinds) ] + nullVarBinds = [ False ] * len(initialVars) + + totalRows = totalCalls = 0 + stopFlag = False + + while not stopFlag: + if maxRows and totalRows < maxRows: + maxRepetitions = min(maxRepetitions, maxRows-totalRows) + + cmdGen.bulkCmd(snmpEngine, + authData, + transportTarget, + contextData, + nonRepeaters, maxRepetitions, + [ (x[0], univ.Null()) for x in varBinds ], + (cbFun, cbCtx), + lookupMib) + + snmpEngine.transportDispatcher.runDispatcher() + + errorIndication = cbCtx['errorIndication'] + errorStatus = cbCtx['errorStatus'] + errorIndex = cbCtx['errorIndex'] + varBindTable = cbCtx['varBindTable'] + + if ignoreNonIncreasingOid and errorIndication and \ + isinstance(errorIndication, errind.OidNotIncreasing): + errorIndication = None + + if errorIndication: + yield errorIndication, errorStatus, errorIndex, \ + varBindTable and varBindTable[0] or [] + if errorIndication != errind.requestTimedOut: + return + elif errorStatus: + if errorStatus == 2: + # Hide SNMPv1 noSuchName error which leaks in here + # from SNMPv1 Agent through internal pysnmp proxy. + errorStatus = errorStatus.clone(0) + errorIndex = errorIndex.clone(0) + yield errorIndication, errorStatus, errorIndex, \ + varBindTable and varBindTable[0] or [] + return + else: + for i in range(len(varBindTable)): + stopFlag = True + if len(varBindTable[i]) != len(initialVars): + varBindTable = i and varBindTable[:i-1] or [] + break + for j in range(len(varBindTable[i])): + name, val = varBindTable[i][j] + if nullVarBinds[j]: + varBindTable[i][j] = name, rfc1905.endOfMibView + continue + stopFlag = False + if isinstance(val, univ.Null): + nullVarBinds[j] = True + elif not lexicographicMode and \ + not initialVars[j].isPrefixOf(name): + varBindTable[i][j] = name, rfc1905.endOfMibView + nullVarBinds[j] = True + if stopFlag: + varBindTable = i and varBindTable[:i-1] or [] + break + + totalRows += len(varBindTable) + totalCalls += 1 + + if maxRows and totalRows >= maxRows: + if totalRows > maxRows: + varBindTable = varBindTable[:-(totalRows-maxRows)] + stopFlag = True + + if maxCalls and totalCalls >= maxCalls: + stopFlag = True + + for varBinds in varBindTable: + yield errorIndication, errorStatus, errorIndex, varBinds diff --git a/pysnmp/entity/rfc3413/oneliner/sync/compat/ntforg.py b/pysnmp/entity/rfc3413/oneliner/sync/compat/ntforg.py new file mode 100644 index 0000000..7a9291c --- /dev/null +++ b/pysnmp/entity/rfc3413/oneliner/sync/compat/ntforg.py @@ -0,0 +1,48 @@ +from pysnmp.entity.rfc3413.oneliner.ntforg import * + +if version_info[:2] < (2, 6): + def next(iter): + return iter.next() + +# +# Synchronous one-liner SNMP Notification Originator application +# + +def sendNotification(snmpEngine, authData, transportTarget, contextData, + notifyType, varBinds, **options): + + def cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBinds, cbCtx): + cbCtx['errorIndication'] = errorIndication + cbCtx['errorStatus'] = errorStatus + cbCtx['errorIndex'] = errorIndex + cbCtx['varBinds'] = varBinds + + cbCtx = {} + + ntfOrg = AsyncNotificationOriginator() + + if varBinds: + ntfOrg.sendNotification( + snmpEngine, + authData, + transportTarget, + contextData, + notifyType, + varBinds, + (cbFun, cbCtx), + options.get('lookupMib', True) + ) + + snmpEngine.transportDispatcher.runDispatcher() + + errorIndication = cbCtx.get('errorIndication') + errorStatus = cbCtx.get('errorStatus') + errorIndex = cbCtx.get('errorIndex') + varBinds = cbCtx.get('varBinds', []) + else: + errorIndication = errorStatus = errorIndex = None + varBinds = [] + + yield errorIndication, errorStatus, errorIndex, varBinds diff --git a/pysnmp/entity/rfc3413/oneliner/sync/ntforg.py b/pysnmp/entity/rfc3413/oneliner/sync/ntforg.py new file mode 100644 index 0000000..16f3930 --- /dev/null +++ b/pysnmp/entity/rfc3413/oneliner/sync/ntforg.py @@ -0,0 +1,126 @@ +from pysnmp.entity.rfc3413.oneliner.ntforg import * + +if version_info[:2] < (2, 6): + def next(iter): + return iter.next() + +def sendNotification(snmpEngine, authData, transportTarget, contextData, + notifyType, varBinds, **options): + """Creates a generator to send one or more SNMP notifications. + + On each iteration, new SNMP TRAP or INFORM notification is send + (:RFC:`3413#section-3.3`). The iterator blocks waiting for + INFORM acknowlegement to arrive or error to occur. + + Parameters + ---------- + snmpEngine : :py:class:`~pysnmp.entity.engine.SnmpEngine` + Class instance representing SNMP engine. + + authData : :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.CommunityData` or :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.UsmUserData` + Class instance representing SNMP credentials. + + transportTarget : :py:class:`~pysnmp.entity.rfc3413.oneliner.target.UdpTransportTarget` or :py:class:`~pysnmp.entity.rfc3413.oneliner.target.Udp6TransportTarget` + Class instance representing transport type along with SNMP peer address. + + contextData : :py:class:`~pysnmp.entity.rfc3413.oneliner.ctx.ContextData` + Class instance representing SNMP ContextEngineId and ContextName values. + + notifyType : str + Indicates type of notification to be sent. Recognized literal + values are *trap* or *inform*. + + varBinds: tuple + Single :py:class:`~pysnmp.smi.rfc1902.NotificationType` class instance + representing a minimum sequence of MIB variables required for + particular notification type. + Alternatively, a sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` + objects could be passed instead. In the latter case it is up to + the user to ensure proper Notification PDU contents. + + Other Parameters + ---------------- + **options : + Request options: + + * `lookupMib` - load MIB and resolve response MIB variables at + the cost of slightly reduced performance. Default is `True`. + + Yields + ------ + errorIndication : str + True value indicates SNMP engine error. + errorStatus : str + Non-zero value indicates SNMP PDU error. + errorIndex : int + Non-zero value refers to *varBinds[errorIndex-1] + varBinds : tuple + A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class + instances representing MIB variables returned in SNMP response. + + Raises + ------ + PySnmpError + Or its derivative indicating that an error occurred while + performing SNMP operation. + + Notes + ----- + The `sendNotification` generator will be exhausted immidiately unless + an instance of :py:class:`~pysnmp.smi.rfc1902.NotificationType` class + or a sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` `varBinds` + are send back into running generator (supported since Python 2.6). + + Examples + -------- + >>> from pysnmp.entity.rfc3413.oneliner.ntforg import * + >>> g = sendNotification(SnmpEngine(), + ... CommunityData('public'), + ... UdpTransportTarget(('demo.snmplabs.com', 162)), + ... ContextData(), + ... 'trap', + ... NotificationType(ObjectIdentity('IF-MIB', 'linkDown'))) + >>> next(g) + (None, 0, 0, []) + >>> + + """ + def cbFun(snmpEngine, sendRequestHandle, + errorIndication, errorStatus, errorIndex, + varBinds, cbCtx): + cbCtx['errorIndication'] = errorIndication + cbCtx['errorStatus'] = errorStatus + cbCtx['errorIndex'] = errorIndex + cbCtx['varBinds'] = varBinds + + cbCtx = {} + + ntfOrg = AsyncNotificationOriginator() + + while True: + if varBinds: + ntfOrg.sendNotification( + snmpEngine, + authData, + transportTarget, + contextData, + notifyType, + varBinds, + cbInfo=(cbFun, cbCtx), + lookupMib=options.get('lookupMib', True) + ) + + snmpEngine.transportDispatcher.runDispatcher() + + errorIndication = cbCtx.get('errorIndication') + errorStatus = cbCtx.get('errorStatus') + errorIndex = cbCtx.get('errorIndex') + varBinds = cbCtx.get('varBinds', []) + else: + errorIndication = errorStatus = errorIndex = None + varBinds = [] + + varBinds = ( yield errorIndication, errorStatus, errorIndex, varBinds ) + + if not varBinds: + break diff --git a/pysnmp/entity/rfc3413/oneliner/target.py b/pysnmp/entity/rfc3413/oneliner/target.py index 04ecb5f..ecb7882 100644 --- a/pysnmp/entity/rfc3413/oneliner/target.py +++ b/pysnmp/entity/rfc3413/oneliner/target.py @@ -37,6 +37,42 @@ class _AbstractTransportTarget: def _resolveAddr(self, transportAddr): raise NotImplementedError() class UdpTransportTarget(_AbstractTransportTarget): + """Creates UDP/IPv4 configuration entry and initialize socket API if needed. + + This object can be used by + :py:class:`~pysnmp.entity.rfc3413.oneliner.cmdgen.AsyncCommandGenerator` or + :py:class:`~pysnmp.entity.rfc3413.oneliner.ntforg.AsyncNotificationOriginator` + and their derevatives for adding new entries to Local Configuration + Datastore (LCD) managed by :py:class:`~pysnmp.entity.engine.SnmpEngine` + class instance. + + See :RFC:`1906#section-3` for more information on the UDP transport mapping. + + Parameters + ---------- + transportAddr : tuple + Indicates remote address in Python :py:mod:`socket` module format + which is a tuple of FQDN, port where FQDN is a string representing + either hostname or IPv4 address in quad-dotted form, port is an + integer. + timeout : int + Response timeout in seconds. + retries : int + Maximum number of request retries, 0 retries means just a single + request. + tagList : str + Arbitrary string that contains a list of tag values which are used + to select target addresses for a particular operation + (:RFC:`3413#section-4.1.4`). + + Examples + -------- + >>> from pysnmp.entity.rfc3413.oneliner.target import UdpTransportTarget + >>> UdpTransportTarget(('demo.snmplabs.com', 161)) + UdpTransportTarget(('195.218.195.228', 161), timeout=1, retries=5, tagList='') + >>> + + """ transportDomain = udp.domainName protoTransport = udp.UdpSocketTransport def _resolveAddr(self, transportAddr): @@ -50,6 +86,51 @@ class UdpTransportTarget(_AbstractTransportTarget): raise error.PySnmpError('Bad IPv4/UDP transport address %s: %s' % ('@'.join([ str(x) for x in transportAddr ]), sys.exc_info()[1])) class Udp6TransportTarget(_AbstractTransportTarget): + """Creates UDP/IPv6 configuration entry and initialize socket API if needed. + + This object can be used by + :py:class:`~pysnmp.entity.rfc3413.oneliner.cmdgen.AsyncCommandGenerator` or + :py:class:`~pysnmp.entity.rfc3413.oneliner.ntforg.AsyncNotificationOriginator` + and their derevatives for adding new entries to Local Configuration + Datastore (LCD) managed by :py:class:`~pysnmp.entity.engine.SnmpEngine` + class instance. + + See :RFC:`1906#section-3`, :RFC:`2851#section-4` for more information + on the UDP and IPv6 transport mapping. + + Parameters + ---------- + transportAddr : tuple + Indicates remote address in Python :py:mod:`socket` module format + which is a tuple of FQDN, port where FQDN is a string representing + either hostname or IPv6 address in one of three conventional forms + (:RFC:`1924#section-3`), port is an integer. + timeout : int + Response timeout in seconds. + retries : int + Maximum number of request retries, 0 retries means just a single + request. + tagList : str + Arbitrary string that contains a list of tag values which are used + to select target addresses for a particular operation + (:RFC:`3413#section-4.1.4`). + + Examples + -------- + >>> from pysnmp.entity.rfc3413.oneliner.target import Udp6TransportTarget + >>> Udp6TransportTarget(('google.com', 161)) + Udp6TransportTarget(('2a00:1450:4014:80a::100e', 161), timeout=1, retries=5, tagList='') + >>> Udp6TransportTarget(('FEDC:BA98:7654:3210:FEDC:BA98:7654:3210', 161)) + Udp6TransportTarget(('fedc:ba98:7654:3210:fedc:ba98:7654:3210', 161), timeout=1, retries=5, tagList='') + >>> Udp6TransportTarget(('1080:0:0:0:8:800:200C:417A', 161)) + Udp6TransportTarget(('1080::8:800:200c:417a', 161), timeout=1, retries=5, tagList='') + >>> Udp6TransportTarget(('::0', 161)) + Udp6TransportTarget(('::', 161), timeout=1, retries=5, tagList='') + >>> Udp6TransportTarget(('::', 161)) + Udp6TransportTarget(('::', 161), timeout=1, retries=5, tagList='') + >>> + + """ transportDomain = udp6.domainName protoTransport = udp6.Udp6SocketTransport def _resolveAddr(self, transportAddr): diff --git a/pysnmp/smi/rfc1902.py b/pysnmp/smi/rfc1902.py index 8d66f25..b61f5a0 100644 --- a/pysnmp/smi/rfc1902.py +++ b/pysnmp/smi/rfc1902.py @@ -8,17 +8,83 @@ from pyasn1.type.base import AbstractSimpleAsn1Item from pyasn1.error import PyAsn1Error from pysnmp import debug -# -# An OID-like object that embeds MIB resolution. -# -# Valid initializers include: -# ObjectIdentity('1.3.6.1.2.1.1.1.0') -# ObjectIdentity('iso.org.dod.internet.mgmt.mib-2.system.sysDescr.0') -# ObjectIdentity('SNMPv2-MIB', 'system') -# ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0) -# ObjectIdentity('IP-MIB', 'ipAdEntAddr', '127.0.0.1', 123) -# +# expose SNMP types in this namespace for convenience +Integer = rfc1902.Integer +Integer32 = rfc1902.Integer32 +OctetString = rfc1902.OctetString +ObjectIdentifier = rfc1902.ObjectIdentifier +IpAddress = rfc1902.IpAddress +Counter32 = rfc1902.Counter32 +Gauge32 = rfc1902.Gauge32 +Unsigned32 = rfc1902.Unsigned32 +TimeTicks = rfc1902.TimeTicks +Opaque = rfc1902.Opaque +Counter64 = rfc1902.Counter64 +Bits = rfc1902.Bits +ObjectName = rfc1902.ObjectName + class ObjectIdentity: + """Create an object representing MIB variable ID. + + At the protocol level, MIB variable is only identified by an OID. + However, when interacting with humans, MIB variable can also be referred + to by its MIB name. The *ObjectIdentity* class supports various forms + of MIB variable identification, providing automatic conversion from + one to others. At the same time *ObjectIdentity* objects behave like + :py:obj:`tuples` of py:obj:`int` sub-OIDs. + + See :RFC:`1902#section-2` for more information on OBJECT-IDENTITY + SMI definitions. + + Parameters + ---------- + args + initial MIB variable identity. Recognized variants: + + * single :py:obj:`tuple` or integers representing OID + * single :py:obj:`str` representing OID in dot-separated + integers form + * single :py:obj:`str` representing MIB variable in + dot-separated labels form + * single :py:obj:`str` representing MIB name. First variable + defined in MIB is assumed. + * pair of :py:obj:`str` representing MIB name and variable name + * pair of :py:obj:`str` representing MIB name and variable name + followed by an arbitrary number of :py:obj:`str` and/or + :py:obj:`int` values representing MIB variable instance + identification. + + Other parameters + ---------------- + kwargs + MIB resolution options: + + * whenever only MIB name is given, resolve into last variable defined + in MIB if last=True. Otherwise resolves to first variable (default). + + Notes + ----- + Actual conversion between MIB variable representation formats occurs + upon :py:meth:`~pysnmp.smi.rfc1902.ObjectIdentity.resolveWithMib` + invocation. + + Examples + -------- + >>> from pysnmp.smi.rfc1902 import ObjectIdentity + >>> ObjectIdentity((1, 3, 6, 1, 2, 1, 1, 1, 0)) + ObjectIdentity((1, 3, 6, 1, 2, 1, 1, 1, 0)) + >>> ObjectIdentity('1.3.6.1.2.1.1.1.0') + ObjectIdentity('1.3.6.1.2.1.1.1.0') + >>> ObjectIdentity('iso.org.dod.internet.mgmt.mib-2.system.sysDescr.0') + ObjectIdentity('iso.org.dod.internet.mgmt.mib-2.system.sysDescr.0') + >>> ObjectIdentity('SNMPv2-MIB', 'system') + ObjectIdentity('SNMPv2-MIB', 'system') + >>> ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0) + ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0) + >>> ObjectIdentity('IP-MIB', 'ipAdEntAddr', '127.0.0.1', 123) + ObjectIdentity('IP-MIB', 'ipAdEntAddr', '127.0.0.1', 123) + + """ stDirty, stClean = 1, 2 def __init__(self, *args, **kwargs): @@ -28,22 +94,95 @@ class ObjectIdentity: self.__asn1SourcesToAdd = self.__asn1SourcesOptions = None self.__state = self.stDirty - # - # public API - # def getMibSymbol(self): + """Returns MIB variable symbolic identification. + + Returns + ------- + str + MIB module name + str + MIB variable symbolic name + : :py:class:`~pysnmp.proto.rfc1902.ObjectName` + class instance representing MIB variable instance index. + + Raises + ------ + SmiError + If MIB variable conversion has not been performed. + + Examples + -------- + >>> objectIdentity = ObjectIdentity('1.3.6.1.2.1.1.1.0') + >>> objectIdentity.resolveWithMib(mibViewController) + >>> objectIdentity.getMibSymbol() + ('SNMPv2-MIB', 'sysDescr', (0,)) + >>> + + """ if self.__state & self.stClean: return self.__modName, self.__symName, self.__indices else: raise SmiError('%s object not fully initialized' % self.__class__.__name__) def getOid(self): + """Returns OID identifying MIB variable. + + Returns + ------- + : :py:class:`~pysnmp.proto.rfc1902.ObjectName` + full OID identifying MIB variable including possible index part. + + Raises + ------ + SmiError + If MIB variable conversion has not been performed. + + Examples + -------- + >>> objectIdentity = ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0) + >>> objectIdentity.resolveWithMib(mibViewController) + >>> objectIdentity.getOid() + ObjectName('1.3.6.1.2.1.1.1.0') + >>> + + """ if self.__state & self.stClean: return self.__oid else: raise SmiError('%s object not fully initialized' % self.__class__.__name__) def getLabel(self): + """Returns symbolic path to this MIB variable. + + Meaning a sequence of symbolic identifications for each of parent + MIB objects in MIB tree. + + Returns + ------- + tuple + sequence of names of nodes in a MIB tree from the top of the tree + towards this MIB variable. + + Raises + ------ + SmiError + If MIB variable conversion has not been performed. + + Notes + ----- + Returned sequence may not contain full path to this MIB variable + if some symbols are now known at the moment of MIB look up. + + Examples + -------- + >>> objectIdentity = ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0) + >>> objectIdentity.resolveWithMib(mibViewController) + >>> objectIdentity.getOid() + ('iso', 'org', 'dod', 'internet', 'mgmt', 'mib-2', 'system', 'sysDescr') + >>> + + """ if self.__state & self.stClean: return self.__label else: @@ -63,6 +202,35 @@ class ObjectIdentity: # def addAsn1MibSource(self, *asn1Sources, **kwargs): + """Adds path to a repository to search ASN.1 MIB files. + + Parameters + ---------- + *asn1Sources : + one or more URL in form of :py:obj:`str` identifying local or + remote ASN.1 MIB repositories. Path must include the *@mib@* + component which will be replaced with MIB module name at the + time of search. + + Returns + ------- + : :py:class:`~pysnmp.smi.rfc1902.ObjectIdentity` + reference to itself + + Notes + ----- + Please refer to :py:class:`~pysmi.reader.localfile.FileReader`, + :py:class:`~pysmi.reader.httpclient.HttpReader` and + :py:class:`~pysmi.reader.ftpclient.FtpReader` classes for + in-depth information on ASN.1 MIB lookup. + + Examples + -------- + >>> ObjectIdentity('SNMPv2-MIB', 'sysDescr').addAsn1Source('http://mibs.snmplabs.com/asn1/@mib@') + ObjectIdentity('SNMPv2-MIB', 'sysDescr') + >>> + + """ if self.__asn1SourcesToAdd is None: self.__asn1SourcesToAdd = asn1Sources else: @@ -91,6 +259,47 @@ class ObjectIdentity: # this would eventually be called by an entity which posses a # reference to MibViewController def resolveWithMib(self, mibViewController): + """Perform MIB variable ID conversion. + + Parameters + ---------- + mibViewController : :py:class:`~pysnmp.smi.view.MibViewController` + class instance representing MIB browsing functionality. + + Returns + ------- + : :py:class:`~pysnmp.smi.rfc1902.ObjectIdentity` + reference to itself + + Raises + ------ + SmiError + In case of fatal MIB hanling errora + + Notes + ----- + Calling this method might cause the following sequence of + events (exact details depends on many factors): + + * ASN.1 MIB file downloaded and handed over to + :py:class:`~pysmi.compiler.MibCompiler` for conversion into + Python MIB module (based on pysnmp classes) + * Python MIB module is imported by SNMP engine, internal indices + created + * :py:class:`~pysnmp.smi.view.MibViewController` looks up the + rest of MIB identification information based on whatever information + is already available, :py:class:`~pysnmp.smi.rfc1902.ObjectIdentity` + class instance + gets updated and ready for further use. + + Examples + -------- + >>> objectIdentity = ObjectIdentity('SNMPv2-MIB', 'sysDescr') + >>> objectIdentity.resolveWithMib(mibViewController) + ObjectIdentity('SNMPv2-MIB', 'sysDescr') + >>> + + """ if self.__mibSourcesToAdd is not None: debug.logger & debug.flagMIB and debug.logger('adding MIB sources %s' % ', '.join(self.__mibSourcesToAdd)) mibViewController.mibBuilder.addMibSources( @@ -374,6 +583,63 @@ class ObjectIdentity: # A two-element sequence of ObjectIdentity and SNMP data type object class ObjectType: + """Create an object representing MIB variable. + + Instances of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class are + containters incorporating :py:class:`~pysnmp.smi.rfc1902.ObjectIdentity` + class instance (identifying MIB variable) and optional value belonging + to one of SNMP types (:RFC:`1902`). + + Typical MIB variable is defined like this (from *SNMPv2-MIB.txt*): + + .. code-block:: bash + + sysDescr OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A textual description of the entity. This value should..." + ::= { system 1 } + + Corresponding ObjectType instantiation would look like this: + + .. code-block:: python + + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr'), 'Linux i386 box') + + In order to behave like SNMP variable-binding (:RFC:`1157#section-4.1.1`), + :py:class:`~pysnmp.smi.rfc1902.ObjectType` objects also support + sequence protocol addressing `objectIdentity` as its 0-th element + and `objectSyntax` as 1-st. + + See :RFC:`1902#section-2` for more information on OBJECT-TYPE SMI + definitions. + + Parameters + ---------- + objectIdentity : :py:class:`~pysnmp.smi.rfc1902.ObjectIdentity` + Class instance representing MIB variable identification. + objectSyntax : + Represents a value associated with this MIB variable. Values of + built-in Python types will be automatically converted into SNMP + object as specified in OBJECT-TYPE->SYNTAX field. + + Notes + ----- + Actual conversion between MIB variable representation formats occurs + upon :py:meth:`~pysnmp.smi.rfc1902.ObjectType.resolveWithMib` + invocation. + + Examples + -------- + >>> from pysnmp.smi.rfc1902 import * + >>> ObjectType(ObjectIdentity('1.3.6.1.2.1.1.1.0')) + ObjectType(ObjectIdentity('1.3.6.1.2.1.1.1.0'), Null()) + >>> ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0), 'Linux i386') + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0), 'Linux i386') + + """ stDirty, stClean = 1, 2 def __init__(self, objectIdentity, objectSyntax=rfc1905.unSpecified): if not isinstance(objectIdentity, ObjectIdentity): @@ -387,6 +653,9 @@ class ObjectType: else: raise SmiError('%s object not fully initialized' % self.__class__.__name__) + def __str__(self): + return self.prettyPrint() + def __repr__(self): return '%s(%s)' % (self.__class__.__name__, ', '.join([ repr(x) for x in self.__args])) @@ -394,6 +663,39 @@ class ObjectType: return self.__state & self.stClean def resolveWithMib(self, mibViewController): + """Perform MIB variable ID and associated value conversion. + + Parameters + ---------- + mibViewController : :py:class:`~pysnmp.smi.view.MibViewController` + class instance representing MIB browsing functionality. + + Returns + ------- + : :py:class:`~pysnmp.smi.rfc1902.ObjectType` + reference to itself + + Raises + ------ + SmiError + In case of fatal MIB hanling errora + + Notes + ----- + Calling this method involves + :py:meth:`~pysnmp.smi.rfc1902.ObjectIdentity.resolveWithMib` + method invocation. + + Examples + -------- + >>> objectType = ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr'), 'Linux i386') + >>> objectType.resolveWithMib(mibViewController) + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr'), DisplayString('Linux i386')) + >>> str(objectType) + 'SNMPv2-MIB::sysDescr."0" = Linux i386' + >>> + + """ if self.__state & self.stClean: return self @@ -433,8 +735,71 @@ class ObjectType: else: raise SmiError('%s object not fully initialized' % self.__class__.__name__) -# A sequence of ObjectType's class NotificationType: + """Create an object representing SNMP Notification. + + Instances of :py:class:`~pysnmp.smi.rfc1902.NotificationType` class are + containters incorporating :py:class:`~pysnmp.smi.rfc1902.ObjectIdentity` + class instance (identifying particular notification) and a collection + of MIB variables IDs that + :py:class:`~pysnmp.entity.rfc3413.oneliner.cmdgen.NotificationOriginator` + should gather and put into notification message. + + Typical notification is defined like this (from *IF-MIB.txt*): + + .. code-block:: bash + + linkDown NOTIFICATION-TYPE + OBJECTS { ifIndex, ifAdminStatus, ifOperStatus } + STATUS current + DESCRIPTION + "A linkDown trap signifies that the SNMP entity..." + ::= { snmpTraps 3 } + + Corresponding NotificationType instantiation would look like this: + + .. code-block:: python + + NotificationType(ObjectIdentity('IF-MIB', 'linkDown')) + + To retain similarity with SNMP variable-bindings, + :py:class:`~pysnmp.smi.rfc1902.NotificationType` objects behave like + a sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class + instances. + + See :RFC:`1902#section-2` for more information on NOTIFICATION-TYPE SMI + definitions. + + Parameters + ---------- + objectIdentity : :py:class:`~pysnmp.smi.rfc1902.ObjectIdentity` + Class instance representing MIB notification type identification. + instanceIndex : :py:class:`~pysnmp.proto.rfc1902.ObjectName` + Trailing part of MIB variables OID identification that represents + concrete instance of a MIB variable. When notification is prepared, + `instanceIndex` is appended to each MIB variable identification + listed in NOTIFICATION-TYPE->OBJECTS clause. + objects : dict + Dictionary-like object that may return values by OID key. The + `objects` dictionary is consulted when notification is being + prepared. OIDs are taken from MIB variables listed in + NOTIFICATION-TYPE->OBJECTS with `instanceIndex` part appended. + + Notes + ----- + Actual notification type and MIB variables look up occurs + upon :py:meth:`~pysnmp.smi.rfc1902.NotificationType.resolveWithMib` + invocation. + + Examples + -------- + >>> from pysnmp.smi.rfc1902 import * + >>> NotificationType(ObjectIdentity('1.3.6.1.6.3.1.1.5.3')) + NotificationType(ObjectIdentity('1.3.6.1.6.3.1.1.5.3'), (), {}) + >>> NotificationType(ObjectIdentity('IP-MIB', 'linkDown'), ObjectName('3.5)) + NotificationType(ObjectIdentity('1.3.6.1.6.3.1.1.5.3'), ObjectName('3.5'), {}) + + """ stDirty, stClean = 1, 2 def __init__(self, objectIdentity, instanceIndex=(), objects={}): if not isinstance(objectIdentity, ObjectIdentity): @@ -456,6 +821,33 @@ class NotificationType: return '%s(%r, %r, %r)' % (self.__class__.__name__, self.__objectIdentity, self.__instanceIndex, self.__objects) def addVarBinds(self, *varBinds): + """Appends variable-binding to notification. + + Parameters + ---------- + *varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType` + One or more :py:class:`~pysnmp.smi.rfc1902.ObjectType` class + instances. + + Returns + ------- + : :py:class:`~pysnmp.smi.rfc1902.NotificationType` + reference to itself + + Notes + ----- + This method can be used to add custom variable-bindings to + notification message in addition to MIB variables specified + in NOTIFICATION-TYPE->OBJECTS clause. + + Examples + -------- + >>> nt = NotificationType(ObjectIdentity('IP-MIB', 'linkDown')) + >>> nt.addVarBinds(ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0))) + NotificationType(ObjectIdentity('IP-MIB', 'linkDown'), (), {}) + >>> + + """ debug.logger & debug.flagMIB and debug.logger('additional var-binds: %r' % (varBinds,)) if self.__state & self.stClean: self.__varBinds.extend(varBinds) @@ -467,6 +859,43 @@ class NotificationType: return self.__state & self.stClean def resolveWithMib(self, mibViewController): + """Perform MIB variable ID conversion and notification objects expansion. + + Parameters + ---------- + mibViewController : :py:class:`~pysnmp.smi.view.MibViewController` + class instance representing MIB browsing functionality. + + Returns + ------- + : :py:class:`~pysnmp.smi.rfc1902.NotificationType` + reference to itself + + Raises + ------ + SmiError + In case of fatal MIB hanling errora + + Notes + ----- + Calling this method might cause the following sequence of + events (exact details depends on many factors): + + * :py:meth:`pysnmp.smi.rfc1902.ObjectIdentity.resolveWithMib` is called + * MIB variables names are read from NOTIFICATION-TYPE->OBJECTS clause, + :py:class:`~pysnmp.smi.rfc1902.ObjectType` instances are created + from MIB variable OID and `indexInstance` suffix. + * `objects` dictionary is queried for each MIB variable OID, + acquired values are added to corresponding MIB variable + + Examples + -------- + >>> notificationType = NotificationType(ObjectIdentity('IF-MIB', 'linkDown')) + >>> notificationType.resolveWithMib(mibViewController) + NotificationType(ObjectIdentity('IF-MIB', 'linkDown'), (), {}) + >>> + + """ if self.__state & self.stClean: return self diff --git a/setup.py b/setup.py index fccda85..7941703 100644 --- a/setup.py +++ b/setup.py @@ -105,6 +105,8 @@ params.update( { 'pysnmp.entity', 'pysnmp.entity.rfc3413', 'pysnmp.entity.rfc3413.oneliner', + 'pysnmp.entity.rfc3413.oneliner.sync', + 'pysnmp.entity.rfc3413.oneliner.sync.compat', 'pysnmp.entity.rfc3413.twisted', 'pysnmp.entity.rfc3413.asyncio', 'pysnmp.proto', -- cgit v1.2.1