Compare commits

...

53 Commits

Author SHA1 Message Date
Ilya Etingof 6a850eaf01 Disable Travis builds for py 2.6, 3.2 & 3.3
Seems like they discontinued those.
2018-11-03 13:20:40 +01:00
Ilya Etingof cd48f6e128
Fix hlapi LCD to include `contextName` (#217)
Fixed hlapi LCD configurator to include `contextName`.
Prior to this fix sending SNMPv3 TRAP with non-default
`contextName` would fail.

This change modifies the signature of the internal
LCD methods.
2018-11-03 12:51:35 +01:00
Ilya Etingof c8d699ca0a Expose ASN.1 `Null` type through `rfc1902` module 2018-10-26 08:44:06 +02:00
Ilya Etingof 5057a1fd59 Use `compile()` before `exec` of MIB modules
This change attaches the file name to the stack frames
what is helpful when reading traceback or debugging
interactively.
2018-10-26 08:34:26 +02:00
Ilya Etingof 1315e5e979 Fix Sphinx markup for USM crypto algorithm IDs 2018-10-06 20:00:41 +02:00
Ilya Etingof 4cf3317ce9 Reformat `isAccessAllowed()` for clarity 2018-10-06 09:29:29 +02:00
Fabrizio Vanni c7f8654c98 Avoid deprecation warnings for asyncio.async() in server mode (#202)
This is actually needed for Python 3.7 which introduces async and await
as  reserved keywords, see https://docs.python.org/3/whatsnew/3.7.html
2018-09-26 11:13:10 +02:00
Ilya Etingof 250deca6ed Ensure distinct transports if timeout/retries differ
Fix hlapi/v3arch transport target caching to ensure transport targets
are different even if just timeout/retries options differ.
2018-09-20 10:44:11 +02:00
Ilya Etingof 2d91fa167e Cut for 4.4.7 2018-09-14 01:43:17 +02:00
Ilya Etingof ddf3085179 Release 4.4.6 2018-09-13 23:47:22 +02:00
Ilya Etingof 51a15bdaa0 Tolerate non-initialised entries in SNMP community table
It can happen that SNMP community table contains uninitialized entries.
These entries may stop internal SNMP community table indexing which
is done in rfc2576 to speed up SNMP engine operations when SNMPv1/v2c
is involved. Once a bad entry gets into SNMP community table, all
the rest queries would start failing.

This patch ignores incomplete SNMP community table entries in the
course of building indices.
2018-09-13 19:42:05 +02:00
Ilya Etingof 2a9466dbe4 Tolerate duplicate enumerations
Possible duplicate enumerations in `Bits` and `Integer` SMI types
causes pyasn1 exception. This fix reduces duplicates prior to
passing them to pyasn1.
2018-09-09 12:26:10 +02:00
Ilya Etingof fcd4435dd8 Add a CHANGELOG entry for previous fix 2018-09-09 09:41:20 +02:00
Ryan Van Gilder daa2ce0171 Fix lcd.unconfigure not removing cached addr value preventing the same target being re-configured (#194) 2018-09-09 09:30:46 +02:00
Ilya Etingof 34836cc484 Recover missing LICENSE in tarball 2018-08-08 07:55:56 +02:00
Ilya Etingof b0bbd37e82 Improve long description in Trove 2018-08-06 23:22:48 +02:00
Ilya Etingof be8d2caccf Improve package build and dependency tracking 2018-08-06 23:18:42 +02:00
Ilya Etingof 98e2a3e838 prepare 4.4.6 2018-08-06 23:01:36 +02:00
Ilya Etingof 8a3727a9fc Fix Python 2.4-2.5 except statement
Older Pythons do not support 'except ... as...' syntax.
2018-08-05 22:47:36 +02:00
Ilya Etingof 43a181b692 Rename LICENSE.txt -> LICENSE.rst 2018-08-05 21:27:08 +02:00
Ilya Etingof d9f5fd2efb changelog typo 2018-08-05 21:15:29 +02:00
Ilya Etingof 44ab5d3a77 release 4.4.5 2018-08-05 21:08:19 +02:00
Ilya Etingof d72ad91b3a Fix PySnmpError implementation
This is a follow up fix to make PySnmpError properly
overriding base Exception call signature
2018-08-05 10:24:50 +02:00
Ilya Etingof 36f7584402
Add PySnmpError.cause attribute (#168)
To convey parent exception information on re-raise
2018-08-05 09:56:41 +02:00
Ilya Etingof ee321e0479
Fix out-of-scope OID leak in hlapi table (#172)
Fixed out-of-scope OIDs possibly leaking at the end of
SNMP table at hlapi `nextCmd` and `bulkCmd` calls when
`lexicographicMode = False`.
2018-08-05 09:52:42 +02:00
Ilya Etingof 7abfa51a99 Fix crash on wrong SNMPv3 security model
Fixed crash caused by incoming SNMPv3 message
requesting SNMPv1/v2c security model
2018-08-04 20:24:26 +02:00
Michal Arbet 0d7f612468 Fix py3.7 syntax error caused by async keyword (#180)
As async is the keyword since Python 3.7, let's use gettattr
built-in function to call async function from asyncio.
2018-07-31 14:50:46 +02:00
Vincent Bernat 83a8ac9e3a Ensure tests run through tox are using the expected Python executable (#175)
Otherwise, they are likely to use the system python.
2018-07-31 08:55:28 +02:00
mattsb42-aws 5e13765c6e adding py33 to the tox auto-run environments 2018-07-31 08:54:58 +02:00
mattsb42-aws e25f1287e0 adding a basic tox handle to simplify running tests 2018-07-31 08:53:50 +02:00
Ilya Etingof 6031836dfa Fix `Bits` initialization with `namedValues` 2018-07-20 09:53:47 +02:00
Ilya Etingof d70831c76f Revert "Fix var-bind initialization from ObjectIdentity at hlapi"
This reverts commit 23d1aa7bf5.
2018-07-05 13:39:18 +02:00
Ilya Etingof d7b86be500 Fix typo in docstring 2018-07-05 10:39:53 +02:00
Ilya Etingof 23d1aa7bf5 Fix var-bind initialization from ObjectIdentity at hlapi 2018-07-05 10:38:56 +02:00
Ilya Etingof 06eeaf6fbf Fix scoping bug in asyncio wrapper
Probably introduced by commit 2b27b49db7
2018-07-04 09:32:15 +02:00
Eric Brown f08dad8829 Switch back to offical Python 3.7 build (#163)
It appears that Python 3.7 use in Travis-CI is finally fixed. However,
it requires use of xenial distribution and sudo: true.  Those have
now been added to the matrix.

Signed-off-by: Eric Brown <browne@vmware.com>
2018-07-03 08:19:57 +02:00
Ilya Etingof ee4c0a5375 Fix typos 2018-07-03 08:05:57 +02:00
Ilya Etingof ed7e72c6a1 switch Travis back to 3.7-dev while 3.7 is not avail 2018-06-29 09:06:28 +02:00
Ilya Etingof 9051369318 reduce tests output by tailing them 2018-06-29 09:00:14 +02:00
Aaron Spike 1cec4e7bb3 Typo "preperly" -> "properly" (#156) 2018-06-28 09:54:47 +02:00
Ilya Etingof 49927e0809 pin twisted versions 2018-06-28 09:53:07 +02:00
Eric Brown acab4ce4dc Add Python 3.7 support (#162)
Python 3.7 was just released [1]. This is a small change to
enable support in pysnmp.

[1] https://docs.python.org/3.7/whatsnew/3.7.html

Signed-off-by: Eric Brown <browne@vmware.com>
2018-06-28 08:59:32 +02:00
Ilya Etingof 293f451513 VACM contextName memory leak fix followup 2018-04-24 12:00:53 +02:00
Ilya Etingof e7ca18b846 VACM contextName memory leakk fix 2018-04-24 11:25:31 +02:00
Ilya Etingof 8da24e3fdb fix potential infinite loop in GETBULK response builder 2018-04-21 23:16:17 +02:00
Cameron 4938e8e383 asyncio.async deprecated since 3.4.4 (#143)
* asyncio.async deprecated since 3.4.4
2018-04-21 18:47:40 +02:00
Ilya Etingof 1021d56e1b better InetAddressType rendering fix 2018-04-21 17:11:54 +02:00
Ilya Etingof c419576445 fix InetAddressType rendering 2018-04-19 01:10:24 +02:00
Ilya Etingof dff00bf90f Use old Sphinx with old Python 2018-04-13 09:36:19 +02:00
Ilya Etingof bec02e6fc1 Include LICENSE in wheel 2018-04-13 08:57:55 +02:00
Ilya Etingof 6aed418b86 4.4.5 2018-04-09 11:56:57 +02:00
Ilya Etingof 4b21d3da29 typo fix in RFC1158::snmpOutReadOnlys 2018-04-09 11:55:20 +02:00
Ilya Etingof 194d2ec820 pysnmp-apps renamed into snmpclitools 2018-04-09 11:52:11 +02:00
45 changed files with 645 additions and 228 deletions

3
.gitignore vendored
View File

@ -23,3 +23,6 @@ docs/source/.templates/layout.html
# Virtual envs
venv*
# Tox
.tox/

View File

@ -1,16 +1,39 @@
language: python
python:
- "2.6"
- "2.7"
- "3.2"
- "3.3"
- "3.4"
- "3.5"
- "3.6"
- "nightly"
# - "pypy"
# - "pypy3"
cache: pip
matrix:
include:
- os: linux
dist: xenial
sudo: false
python: '2.7'
- os: linux
dist: xenial
sudo: false
python: '3.4'
- os: linux
dist: xenial
sudo: false
python: '3.5'
- os: linux
dist: xenial
sudo: false
python: '3.6'
- os: linux
dist: xenial
sudo: true
python: '3.7'
- os: linux
dist: xenial
sudo: false
python: 'nightly'
# - os: linux
# dist: xenial
# sudo: false
# python: 'pypy'
# - os: linux
# dist: xenial
# sudo: false
# python: 'pypy3'
install:
- pip install -r requirements.txt -r devel-requirements.txt
- pip install -e .

View File

@ -1,4 +1,44 @@
Revision 4.4.7, released 2018-11-XX
-----------------------------------
- Exposed ASN.1 `Null` type through `rfc1902` module for convenience.
- Use `compile()` before `exec`'ing MIB modules to attach filename to
the stack frames (ultimately shown in traceback/debugger)
- Fixed hlapi/v3arch transport target caching to ensure transport targets
are different even if just timeout/retries options differ
- Fixed hlapi LCD configurator to include `contextName`. Prior to this fix
sending SNMPv3 TRAP with non-default `contextName` would fail.
Revision 4.4.6, released 2018-09-13
-----------------------------------
- Improved package build and dependency tracking
- Fixed missing LICENSE from the tarball distribution
- Fixed `CommandGeneratorLcdConfigurator.unconfigure()` to fully clean up
internal caches, otherwise repetitive attempts to configure the target
would fail.
- Fix to tolerate possible duplicate enumerations in `Bits` and `Integer`
SMI types.
- Fix to tolerate non-initialised entries in SNMP community table. Once a
bad entry sneaked into the SNMP community table, all the subsequent
SNMP v1/v2c operations failed. The fix ignores incomplete SNMP community
table entries in the course of building indices.
Revision 4.4.5, released 2018-08-05
-----------------------------------
- Added PySnmpError.cause attribute holding parent exception tuple
- Fixed broken InetAddressType rendering caused by a pyasn1 regression
- Fixed typo in RFC1158 module
- Fixed possible infinite loop in GETBULK response PDU builder
- Fixed memory leak in the `config.delContext()` VACM management harness
- Fixed `Bits` class initialization when enumeration values are given
- Fixed crash caused by incoming SNMPv3 message requesting SNMPv1/v2c
security model
- Fixed out-of-scope OIDs leaking at the end of SNMP table at hlapi
`nextCmd` and `bulkCmd` calls when `lexicographicMode = False`
Revision 4.4.4, released 2018-01-03
-----------------------------------
@ -557,7 +597,7 @@ Revision 4.2.4, released 2013-01-30
defaulted value changed from None to () meaning no var-binds.
- Attempt to convert Windows style EOL into UNIX ones in MIB source
modules appeared to be unnecessary and even destructive to modules
data in some cases. So the convertion code removed altogether.
data in some cases. So the conversion code removed altogether.
- Fix to isAccessAllowed() error handling at NotificationOriginator. System
used to crash on access denied condition.
- Fix to NotificationOriginator to make it use system uptime and trap OID
@ -818,7 +858,7 @@ Revision 4.1.16a, released 2011-03-17
configuration (LCD).
+ default debug.logger is now just a zero value instead of an object
what saves big on frequent calls
+ SNMPv2-SMI columnar indices <-> index values convertion code optimized.
+ SNMPv2-SMI columnar indices <-> index values conversion code optimized.
+ pre-compute and re-use some of ASN.1 structures.
+ avoid setting PDU defaults to save on unnecessary initialization.
+ skip ASN.1 types verification where possible.
@ -1008,7 +1048,7 @@ Revision 4.1.9a, released 2007-11-28
effects.
- Fix to rfc2576.v1ToV2c() PDU converter to perform noSuchName error code
translation.
- Fixes to Notification PDU convertion code at rfc2576 in part of
- Fixes to Notification PDU conversion code at rfc2576 in part of
snmpTrapOID handling.
- Fix to nonRepeaters object use as sequence slicer (must be int) at
cmdrsp.CommandResponderApplication
@ -1030,7 +1070,7 @@ Revision 4.1.8a, released 2007-08-14
------------------------------------
- UNSTABLE ALPHA RELEASE.
- SMI/dispatcher timeout convertion multiplier is actually 100 (1/100 sec)
- SMI/dispatcher timeout conversion multiplier is actually 100 (1/100 sec)
rather than 1/1000. This fix affects timeouts specified through SMI.
- __repr__() implemented for UdpTransportTarget, CommunityData, UsmUserData
in oneliner module.
@ -1081,7 +1121,7 @@ Revision 4.1.7a, released 2007-02-19
- Fix to MibViewController.getNodeName() to take MIB module name
into account (SF bug #1505847).
- Do explicit check for Counter32,Unsigned32,TimeTicks,Counter64 value types
in MibTableRow index convertion and in TextualConvention.prettyPrint()
in MibTableRow index conversion and in TextualConvention.prettyPrint()
methods (SF bug #1506341). Handle Bits in indices as RFC2578 suggests.
- Apply read-create column status to libsmi2pysnmp-generated code
whenever MIB text specifies that (SF bug #1508955).
@ -1105,7 +1145,7 @@ Revision 4.1.7a, released 2007-02-19
- LCD unconfiguration functions for oneliners implemented (SF bug #1635270).
- unloadModules() and unexportSymbols() implemented at MibBuilder
- Notification type PDU proxy code fixed to produce symmetrical
convertion.
conversion.
- Various SNMP engine-internal caches expiration implemented.
- SMI-level access control now takes effect only if AC object is
passed to MIB instrumentation API.

View File

@ -1,4 +1,4 @@
include *.txt *.md *.sh
include *.rst *.txt *.md *.sh
recursive-include examples *.py
recursive-include docs/source *.rst *.svg *.py
recursive-include docs/mibs *.txt

View File

@ -4,7 +4,7 @@ SNMP library for Python
[![PyPI](https://img.shields.io/pypi/v/pysnmp.svg?maxAge=2592000)](https://pypi.python.org/pypi/pysnmp)
[![Python Versions](https://img.shields.io/pypi/pyversions/pysnmp.svg)](https://pypi.python.org/pypi/pysnmp/)
[![Build status](https://travis-ci.org/etingof/pysnmp.svg?branch=master)](https://secure.travis-ci.org/etingof/pysnmp)
[![GitHub license](https://img.shields.io/badge/license-BSD-blue.svg)](https://raw.githubusercontent.com/etingof/pysnmp/master/LICENSE.txt)
[![GitHub license](https://img.shields.io/badge/license-BSD-blue.svg)](https://raw.githubusercontent.com/etingof/pysnmp/master/LICENSE.rst)
This is a pure-Python, open source and free implementation of v1/v2c/v3
SNMP engine distributed under 2-clause [BSD license](http://snmplabs.com/pysnmp/license.html).
@ -27,7 +27,7 @@ Features
* [PySMI](http://snmplabs.com/pysmi/) integration for dynamic MIB compilation
* Built-in instrumentation exposing protocol engine operations
* Python eggs and py2exe friendly
* 100% Python, works with Python 2.4 though 3.6
* 100% Python, works with Python 2.4 though 3.7
* MT-safe (if SnmpEngine is thread-local)
Features, specific to SNMPv3 model include:
@ -59,11 +59,11 @@ to download and install PySNMP along with its dependencies:
* [PyCryptodomex](https://pycryptodome.readthedocs.io) (required only if SNMPv3 encryption is in use)
* [PySMI](http://snmplabs.com/pysmi/) (required for MIB services only)
Besides the library, command-line [SNMP utilities](https://github.com/etingof/pysnmp-apps)
Besides the library, command-line [SNMP utilities](https://github.com/etingof/snmpclitools)
written in pure-Python could be installed via:
```bash
$ pip install pysnmp-apps
$ pip install snmpclitools
```
and used in the very similar manner as conventional Net-SNMP tools:

View File

@ -1,3 +1,10 @@
sphinx
twisted
Sphinx <= 1.6; python_version < '2.7'
Sphinx > 1.6; python_version >= '2.7'
trollius; python_version < '3.0'
twisted < 15.4; python_version < '2.7'
twisted; python_version == '2.7'
twisted < 17.9; python_version == '3.0'
twisted < 17.9; python_version == '3.1'
twisted < 17.9; python_version == '3.2'
twisted <= 17.9; python_version == '3.3'
twisted; python_version >= '3.4'

View File

@ -17,14 +17,14 @@ multilingual capabilities, remote configuration and other features.
PySNMP implementation closely follows intricate system details and features
bringing most possible power and flexibility to its users.
Current PySNMP stable version is 4.4. It runs with Python 2.4 through 3.6
Current PySNMP stable version is 4.4. It runs with Python 2.4 through 3.7
and is recommended for new applications as well as for migration from
older, now obsolete, PySNMP releases. All site documentation and
examples are written for the 4.4 and later versions in mind.
Older materials are still available under the obsolete section.
Besides the libraries, a set of pure-Python
`command-line tools <https://pypi.python.org/pypi/pysnmp-apps/>`_
`command-line tools <https://pypi.python.org/pypi/snmpclitools/>`_
are shipped along with the system. Those tools mimic the interface
and behaviour of popular Net-SNMP snmpget/snmpset/snmpwalk utilities.
They may be useful in a cross-platform situations as well as a testing

View File

@ -93,7 +93,7 @@ sponsoring it. Please get back to us to discuss details.
Contributions to the PySNMP source code is greatly appreciated as well.
We require contributed code to run with Python 2.4 through the latest
Python version (which is 3.6 at the time of this writing). Contributed
Python version (which is 3.7 at the time of this writing). Contributed
code will be redistributed under the terms of the same
`license <http://snmplabs.com/pysnmp/>`_ as PySNMP is.

View File

@ -219,8 +219,7 @@ Security Model configuration for SNMP v3 systems.
.. autoclass:: pysnmp.hlapi.UsmUserData(userName, authKey=None, privKey=None, authProtocol=usmNoAuthProtocol, privProtocol=usmNoPrivProtocol, securityEngineId=None)
Identification of Authentication and Privacy Protocols is done
via constant OIDs:
**Authentication protocol identifiers**
.. autodata:: pysnmp.hlapi.usmNoAuthProtocol
.. autodata:: pysnmp.hlapi.usmHMACMD5AuthProtocol
@ -230,6 +229,8 @@ via constant OIDs:
.. autodata:: pysnmp.hlapi.usmHMAC256SHA384AuthProtocol
.. autodata:: pysnmp.hlapi.usmHMAC384SHA512AuthProtocol
**Privacy (encryption) protocol identifiers**
.. autodata:: pysnmp.hlapi.usmNoPrivProtocol
.. autodata:: pysnmp.hlapi.usmDESPrivProtocol
.. autodata:: pysnmp.hlapi.usm3DESEDEPrivProtocol
@ -239,6 +240,11 @@ via constant OIDs:
.. autodata:: pysnmp.hlapi.usmAesBlumenthalCfb192Protocol
.. autodata:: pysnmp.hlapi.usmAesBlumenthalCfb256Protocol
.. note::
SNMP authentication and encryption keys must be at least *eight*
octets long.
Transport configuration is I/O framework specific and is described in
respective sections.
@ -334,6 +340,20 @@ data description language. PySNMP types are derived from
.. toctree::
:maxdepth: 2
.. _null:
Null type
+++++++++
.. autoclass:: pysnmp.proto.rfc1902.Null(initializer)
:members:
.. note::
The `NULL` type actually belongs to the base ASN.1 types. It is not defined
in :RFC:`1902#section-2` as an SNMP type. The `Null` type is exposed through
`rfc1902` module just for convenience.
.. _integer32:
Integer32 type

View File

@ -126,7 +126,7 @@ objects representing completely different instances of hardware
or software being managed. This is where SNMP context could
be used.
To indicate SNMP context at high-level API a preperly initialized
To indicate SNMP context at high-level API a properly initialized
:py:class:`~pysnmp.hlapi.ContextData` object should be used.
For this example we will use the 'empty' context (default).

View File

@ -227,7 +227,7 @@ engine loads those modules at runtime on demand. PySNMP MIB modules
are universal -- the same module can be consumed by both managed and
managing entities.
MIB convertion is performed automatically by PySNMP, but technically,
MIB conversion is performed automatically by PySNMP, but technically,
it is handled by PySNMP sister project called
`PySMI <http://snmplabs.com/pysmi/>`_. However you can also perform said
conversion by hand with PySMI's *mibdump.py* tool.

View File

@ -2,4 +2,4 @@
License
=======
.. include:: ../../LICENSE.txt
.. include:: ../../LICENSE.rst

View File

@ -58,10 +58,10 @@ print('MIB node lookup by location: '),
rowNode, = mibBuilder.importSymbols(modName, symName)
print(rowNode)
print('Conceptual table index value to oid convertion: '),
print('Conceptual table index value to oid conversion: '),
oid = rowNode.getInstIdFromIndices('router')
print(oid)
print('Conceptual table index oid to value convertion: '),
print('Conceptual table index oid to value conversion: '),
print(rowNode.getIndicesFromInstId(oid))
print('MIB tree traversal')

View File

@ -1,5 +1,5 @@
# http://www.python.org/dev/peps/pep-0396/
__version__ = '4.4.4'
__version__ = '4.4.7'
# backward compatibility
version = tuple([int(x) for x in __version__.split('.')])
majorVersionId = version[0]

View File

@ -31,6 +31,7 @@
# THE POSSIBILITY OF SUCH DAMAGE.
#
import sys
import platform
import traceback
from pysnmp.carrier.asyncio.base import AbstractAsyncioTransport
from pysnmp.carrier import error
@ -41,6 +42,8 @@ try:
except ImportError:
import trollius as asyncio
IS_PYTHON_344_PLUS = platform.python_version_tuple() >= ('3', '4', '4')
class DgramAsyncioProtocol(asyncio.DatagramProtocol, AbstractAsyncioTransport):
"""Base Asyncio datagram Transport, to be used with AsyncioDispatcher"""
@ -83,7 +86,12 @@ class DgramAsyncioProtocol(asyncio.DatagramProtocol, AbstractAsyncioTransport):
c = self.loop.create_datagram_endpoint(
lambda: self, local_addr=iface, family=self.sockFamily
)
self._lport = asyncio.async(c)
# Avoid deprecation warning for asyncio.async()
if IS_PYTHON_344_PLUS:
self._lport = asyncio.ensure_future(c)
else: # pragma: no cover
self._lport = getattr(asyncio, 'async')(c)
except Exception:
raise error.CarrierError(';'.join(traceback.format_exception(*sys.exc_info())))
return self
@ -93,7 +101,11 @@ class DgramAsyncioProtocol(asyncio.DatagramProtocol, AbstractAsyncioTransport):
c = self.loop.create_datagram_endpoint(
lambda: self, local_addr=iface, family=self.sockFamily
)
self._lport = asyncio.async(c)
# Avoid deprecation warning for asyncio.async()
if IS_PYTHON_344_PLUS:
self._lport = asyncio.ensure_future(c)
else: # pragma: no cover
self._lport = getattr(asyncio, 'async')(c)
except Exception:
raise error.CarrierError(';'.join(traceback.format_exception(*sys.exc_info())))
return self

View File

@ -31,6 +31,7 @@
# THE POSSIBILITY OF SUCH DAMAGE.
#
import sys
import platform
import traceback
from pysnmp.carrier.base import AbstractTransportDispatcher
from pysnmp.error import PySnmpError
@ -40,6 +41,7 @@ try:
except ImportError:
import trollius as asyncio
IS_PYTHON_344_PLUS = platform.python_version_tuple() >= ('3', '4', '4')
class AsyncioDispatcher(AbstractTransportDispatcher):
"""AsyncioDispatcher based on asyncio event loop"""
@ -66,10 +68,14 @@ class AsyncioDispatcher(AbstractTransportDispatcher):
raise
except Exception:
raise PySnmpError(';'.join(traceback.format_exception(*sys.exc_info())))
def registerTransport(self, tDomain, transport):
if self.loopingcall is None and self.getTimerResolution() > 0:
self.loopingcall = asyncio.async(self.handle_timeout())
# Avoid deprecation warning for asyncio.async()
if IS_PYTHON_344_PLUS:
self.loopingcall = asyncio.ensure_future(self.handle_timeout())
else: # pragma: no cover
self.loopingcall = getattr(asyncio, 'async')(self.handle_timeout())
AbstractTransportDispatcher.registerTransport(
self, tDomain, transport
)

View File

@ -28,7 +28,9 @@ usmHMAC128SHA224AuthProtocol = hmacsha2.HmacSha2.sha224ServiceID
usmHMAC192SHA256AuthProtocol = hmacsha2.HmacSha2.sha256ServiceID
usmHMAC256SHA384AuthProtocol = hmacsha2.HmacSha2.sha384ServiceID
usmHMAC384SHA512AuthProtocol = hmacsha2.HmacSha2.sha512ServiceID
usmNoAuthProtocol = noauth.NoAuth.serviceID
"""No authentication service"""
# Privacy protocol
usmDESPrivProtocol = des.Des.serviceID
@ -389,13 +391,30 @@ delSocketTransport = delTransport
# VACM shortcuts
def addContext(snmpEngine, contextName):
def __cookVacmContextInfo(snmpEngine, contextName):
mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder
vacmContextEntry, = mibBuilder.importSymbols('SNMP-VIEW-BASED-ACM-MIB', 'vacmContextEntry')
tblIdx = vacmContextEntry.getInstIdFromIndices(contextName)
return vacmContextEntry, tblIdx
def addContext(snmpEngine, contextName):
vacmContextEntry, tblIdx = __cookVacmContextInfo(snmpEngine, contextName)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
((vacmContextEntry.name + (1,) + tblIdx, contextName),)
((vacmContextEntry.name + (2,) + tblIdx, 'destroy'),)
)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
((vacmContextEntry.name + (1,) + tblIdx, contextName),
(vacmContextEntry.name + (2,) + tblIdx, 'createAndGo'))
)
def delContext(snmpEngine, contextName):
vacmContextEntry, tblIdx = __cookVacmContextInfo(snmpEngine, contextName)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
((vacmContextEntry.name + (2,) + tblIdx, 'destroy'),)
)
@ -448,7 +467,7 @@ def addVacmAccess(snmpEngine, groupName, contextName, securityModel,
contextName, securityModel,
securityLevel)
addContext(snmpEngine, contextName) # this is leaky
addContext(snmpEngine, contextName)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
((vacmAccessEntry.name + (9,) + tblIdx, 'destroy'),)
@ -470,6 +489,9 @@ def delVacmAccess(snmpEngine, groupName, contextName, securityModel,
vacmAccessEntry, tblIdx = __cookVacmAccessInfo(snmpEngine, groupName,
contextName, securityModel,
securityLevel)
delContext(snmpEngine, contextName)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
((vacmAccessEntry.name + (9,) + tblIdx, 'destroy'),)
)
@ -538,12 +560,13 @@ def addVacmUser(snmpEngine, securityModel, securityName, securityLevel,
def delVacmUser(snmpEngine, securityModel, securityName, securityLevel,
readSubTree=(), writeSubTree=(), notifySubTree=()):
readSubTree=(), writeSubTree=(), notifySubTree=(),
contextName=null):
(groupName, securityLevel, readView, writeView,
notifyView) = __cookVacmUserInfo(snmpEngine, securityModel,
securityName, securityLevel)
delVacmGroup(snmpEngine, securityModel, securityName)
delVacmAccess(snmpEngine, groupName, null, securityModel, securityLevel)
delVacmAccess(snmpEngine, groupName, contextName, securityModel, securityLevel)
if readSubTree:
delVacmView(
snmpEngine, readView, readSubTree
@ -560,36 +583,40 @@ def delVacmUser(snmpEngine, securityModel, securityName, securityLevel,
# Obsolete shortcuts for add/delVacmUser() wrappers
def addRoUser(snmpEngine, securityModel, securityName, securityLevel, subTree):
addVacmUser(snmpEngine, securityModel, securityName,
securityLevel, subTree)
def delRoUser(snmpEngine, securityModel, securityName, securityLevel, subTree):
delVacmUser(snmpEngine, securityModel, securityName, securityLevel,
subTree)
def addRwUser(snmpEngine, securityModel, securityName, securityLevel, subTree):
def addRoUser(snmpEngine, securityModel, securityName, securityLevel,
subTree, contextName=null):
addVacmUser(snmpEngine, securityModel, securityName, securityLevel,
subTree, subTree)
subTree, contextName=contextName)
def delRwUser(snmpEngine, securityModel, securityName, securityLevel, subTree):
def delRoUser(snmpEngine, securityModel, securityName, securityLevel,
subTree, contextName=null):
delVacmUser(snmpEngine, securityModel, securityName, securityLevel,
subTree, subTree)
subTree, contextName=contextName)
def addRwUser(snmpEngine, securityModel, securityName, securityLevel,
subTree, contextName=null):
addVacmUser(snmpEngine, securityModel, securityName, securityLevel,
subTree, subTree, contextName=contextName)
def delRwUser(snmpEngine, securityModel, securityName, securityLevel,
subTree, contextName=null):
delVacmUser(snmpEngine, securityModel, securityName, securityLevel,
subTree, subTree, contextName=contextName)
def addTrapUser(snmpEngine, securityModel, securityName,
securityLevel, subTree):
securityLevel, subTree, contextName=null):
addVacmUser(snmpEngine, securityModel, securityName, securityLevel,
(), (), subTree)
(), (), subTree, contextName=contextName)
def delTrapUser(snmpEngine, securityModel, securityName,
securityLevel, subTree):
securityLevel, subTree, contextName=null):
delVacmUser(snmpEngine, securityModel, securityName, securityLevel,
(), (), subTree)
(), (), subTree, contextName=contextName)
# Notification target setup

View File

@ -292,7 +292,7 @@ class BulkCommandResponder(CommandResponderBase):
R = max(len(reqVarBinds) - N, 0)
if R:
M = min(M, self.maxVarBinds / R)
M = min(M, self.maxVarBinds // R)
debug.logger & debug.flagApp and debug.logger('handleMgmtOperation: N %d, M %d, R %d' % (N, M, R))

View File

@ -5,6 +5,19 @@
# License: http://snmplabs.com/pysnmp/license.html
#
import sys
class PySnmpError(Exception):
pass
def __init__(self, *args):
msg = args and str(args[0]) or ''
self.cause = sys.exc_info()
if self.cause[0]:
msg += 'caused by %s: %s' % (self.cause[0], self.cause[1])
if msg:
args = (msg,) + args[1:]
Exception.__init__(self, *args)

View File

@ -7,9 +7,58 @@
from pysnmp.proto.rfc1902 import *
from pysnmp.proto.rfc1905 import NoSuchInstance, NoSuchObject, EndOfMibView
from pysnmp.smi.rfc1902 import *
from pysnmp.hlapi.auth import *
from pysnmp.hlapi import auth
from pysnmp.hlapi.context import *
from pysnmp.entity.engine import *
# default is synchronous asyncore-based API
from pysnmp.hlapi.asyncore.sync import *
CommunityData = auth.CommunityData
UsmUserData = auth.UsmUserData
usmNoAuthProtocol = auth.usmNoAuthProtocol
"""No Authentication Protocol"""
usmHMACMD5AuthProtocol = auth.usmHMACMD5AuthProtocol
"""The HMAC-MD5-96 Digest Authentication Protocol (:RFC:`3414#section-6`)"""
usmHMACSHAAuthProtocol = auth.usmHMACSHAAuthProtocol
"""The HMAC-SHA-96 Digest Authentication Protocol AKA SHA-1 (:RFC:`3414#section-7`)"""
usmHMAC128SHA224AuthProtocol = auth.usmHMAC128SHA224AuthProtocol
"""The HMAC-SHA-2 Digest Authentication Protocols (:RFC:`7860`)"""
usmHMAC192SHA256AuthProtocol = auth.usmHMAC192SHA256AuthProtocol
"""The HMAC-SHA-2 Digest Authentication Protocols (:RFC:`7860`)"""
usmHMAC256SHA384AuthProtocol = auth.usmHMAC256SHA384AuthProtocol
"""The HMAC-SHA-2 Digest Authentication Protocols (:RFC:`7860`)"""
usmHMAC384SHA512AuthProtocol = auth.usmHMAC384SHA512AuthProtocol
"""The HMAC-SHA-2 Digest Authentication Protocols (:RFC:`7860`)"""
usmNoPrivProtocol = auth.usmNoPrivProtocol
"""No Privacy Protocol"""
usmDESPrivProtocol = auth.usmDESPrivProtocol
"""The CBC-DES Symmetric Encryption Protocol (:RFC:`3414#section-8`)"""
usm3DESEDEPrivProtocol = auth.usm3DESEDEPrivProtocol
"""The 3DES-EDE Symmetric Encryption Protocol (`draft-reeder-snmpv3-usm-3desede-00 <https:://tools.ietf.org/html/draft-reeder-snmpv3-usm-3desede-00#section-5>`_)"""
usmAesCfb128Protocol = auth.usmAesCfb128Protocol
"""The CFB128-AES-128 Symmetric Encryption Protocol (:RFC:`3826#section-3`)"""
usmAesCfb192Protocol = auth.usmAesCfb192Protocol
"""The CFB128-AES-192 Symmetric Encryption Protocol (`draft-blumenthal-aes-usm-04 <https:://tools.ietf.org/html/draft-blumenthal-aes-usm-04#section-3>`_) with Reeder key localization"""
usmAesCfb256Protocol = auth.usmAesCfb256Protocol
"""The CFB128-AES-256 Symmetric Encryption Protocol (`draft-blumenthal-aes-usm-04 <https:://tools.ietf.org/html/draft-blumenthal-aes-usm-04#section-3>`_) with Reeder key localization"""
usmAesBlumenthalCfb192Protocol = auth.usmAesBlumenthalCfb192Protocol
"""The CFB128-AES-192 Symmetric Encryption Protocol (`draft-blumenthal-aes-usm-04 <https:://tools.ietf.org/html/draft-blumenthal-aes-usm-04#section-3>`_)"""
usmAesBlumenthalCfb256Protocol = auth.usmAesBlumenthalCfb256Protocol
"""The CFB128-AES-256 Symmetric Encryption Protocol (`draft-blumenthal-aes-usm-04 <https:://tools.ietf.org/html/draft-blumenthal-aes-usm-04#section-3>`_)"""

View File

@ -31,6 +31,8 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
#
import sys
from pysnmp.smi.rfc1902 import *
from pysnmp.hlapi.auth import *
from pysnmp.hlapi.context import *
@ -41,6 +43,7 @@ from pysnmp.entity.rfc3413 import cmdgen
try:
import asyncio
except ImportError:
import trollius as asyncio
@ -57,7 +60,7 @@ def getCmd(snmpEngine, authData, transportTarget, contextData,
*varBinds, **options):
"""Creates a generator to perform SNMP GET query.
When itereator gets advanced by :py:mod:`asyncio` main loop,
When iterator gets advanced by :py:mod:`asyncio` main loop,
SNMP GET request is send (:RFC:`1905#section-4.2.1`).
The iterator yields :py:class:`asyncio.Future` which gets done whenever
response arrives or error occurs.
@ -137,14 +140,16 @@ def getCmd(snmpEngine, authData, transportTarget, contextData,
try:
varBindsUnmade = vbProcessor.unmakeVarBinds(snmpEngine, varBinds,
lookupMib)
except Exception as e:
future.set_exception(e)
except Exception:
ex = sys.exc_info()[1]
future.set_exception(ex)
else:
future.set_result(
(errorIndication, errorStatus, errorIndex, varBindsUnmade)
)
addrName, paramsName = lcd.configure(snmpEngine, authData, transportTarget)
addrName, paramsName = lcd.configure(
snmpEngine, authData, transportTarget, contextData.contextName)
future = asyncio.Future()
@ -162,7 +167,7 @@ def setCmd(snmpEngine, authData, transportTarget, contextData,
*varBinds, **options):
"""Creates a generator to perform SNMP SET query.
When itereator gets advanced by :py:mod:`asyncio` main loop,
When iterator gets advanced by :py:mod:`asyncio` main loop,
SNMP SET request is send (:RFC:`1905#section-4.2.5`).
The iterator yields :py:class:`asyncio.Future` which gets done whenever
response arrives or error occurs.
@ -242,14 +247,16 @@ def setCmd(snmpEngine, authData, transportTarget, contextData,
try:
varBindsUnmade = vbProcessor.unmakeVarBinds(snmpEngine, varBinds,
lookupMib)
except Exception as e:
future.set_exception(e)
except Exception:
ex = sys.exc_info()[1]
future.set_exception(ex)
else:
future.set_result(
(errorIndication, errorStatus, errorIndex, varBindsUnmade)
)
addrName, paramsName = lcd.configure(snmpEngine, authData, transportTarget)
addrName, paramsName = lcd.configure(
snmpEngine, authData, transportTarget, contextData.contextName)
future = asyncio.Future()
@ -267,7 +274,7 @@ def nextCmd(snmpEngine, authData, transportTarget, contextData,
*varBinds, **options):
"""Creates a generator to perform SNMP GETNEXT query.
When itereator gets advanced by :py:mod:`asyncio` main loop,
When iterator gets advanced by :py:mod:`asyncio` main loop,
SNMP GETNEXT request is send (:RFC:`1905#section-4.2.2`).
The iterator yields :py:class:`asyncio.Future` which gets done whenever
response arrives or error occurs.
@ -353,14 +360,16 @@ def nextCmd(snmpEngine, authData, transportTarget, contextData,
varBindTableRow,
lookupMib)
for varBindTableRow in varBindTable]
except Exception as e:
future.set_exception(e)
except Exception:
ex = sys.exc_info()[1]
future.set_exception(ex)
else:
future.set_result(
(errorIndication, errorStatus, errorIndex, varBindsUnmade)
)
addrName, paramsName = lcd.configure(snmpEngine, authData, transportTarget)
addrName, paramsName = lcd.configure(
snmpEngine, authData, transportTarget, contextData.contextName)
future = asyncio.Future()
@ -378,7 +387,7 @@ def bulkCmd(snmpEngine, authData, transportTarget, contextData,
nonRepeaters, maxRepetitions, *varBinds, **options):
"""Creates a generator to perform SNMP GETBULK query.
When itereator gets advanced by :py:mod:`asyncio` main loop,
When iterator gets advanced by :py:mod:`asyncio` main loop,
SNMP GETBULK request is send (:RFC:`1905#section-4.2.3`).
The iterator yields :py:class:`asyncio.Future` which gets done whenever
response arrives or error occurs.
@ -493,14 +502,16 @@ def bulkCmd(snmpEngine, authData, transportTarget, contextData,
varBindTableRow,
lookupMib)
for varBindTableRow in varBindTable]
except Exception as e:
future.set_exception(e)
except Exception:
ex = sys.exc_info()[1]
future.set_exception(ex)
else:
future.set_result(
(errorIndication, errorStatus, errorIndex, varBindsUnmade)
)
addrName, paramsName = lcd.configure(snmpEngine, authData, transportTarget)
addrName, paramsName = lcd.configure(
snmpEngine, authData, transportTarget, contextData.contextName)
future = asyncio.Future()

View File

@ -8,6 +8,8 @@
# Authors: Matt Hooks <me@matthooks.com>
# Zachary Lorusso <zlorusso@gmail.com>
#
import sys
from pysnmp.smi.rfc1902 import *
from pysnmp.hlapi.auth import *
from pysnmp.hlapi.context import *
@ -18,6 +20,7 @@ from pysnmp.entity.rfc3413 import ntforg
try:
import asyncio
except ImportError:
import trollius as asyncio
@ -32,7 +35,7 @@ def sendNotification(snmpEngine, authData, transportTarget, contextData,
notifyType, varBinds, **options):
"""Creates a generator to send SNMP notification.
When itereator gets advanced by :py:mod:`asyncio` main loop,
When iterator gets advanced by :py:mod:`asyncio` main loop,
SNMP TRAP or INFORM notification is send (:RFC:`1905#section-4.2.6`).
The iterator yields :py:class:`asyncio.Future` which gets done whenever
response arrives or error occurs.
@ -127,16 +130,17 @@ def sendNotification(snmpEngine, authData, transportTarget, contextData,
try:
varBindsUnmade = vbProcessor.unmakeVarBinds(snmpEngine, varBinds,
lookupMib)
except Exception as e:
future.set_exception(e)
except Exception:
ex = sys.exc_info()[1]
future.set_exception(ex)
else:
future.set_result(
(errorIndication, errorStatus, errorIndex, varBindsUnmade)
)
notifyName = lcd.configure(
snmpEngine, authData, transportTarget, notifyType
)
snmpEngine, authData, transportTarget, notifyType,
contextData.contextName)
future = asyncio.Future()

View File

@ -121,7 +121,8 @@ def getCmd(snmpEngine, authData, transportTarget, contextData,
snmpEngine, varBinds, lookupMib
), cbCtx)
addrName, paramsName = lcd.configure(snmpEngine, authData, transportTarget)
addrName, paramsName = lcd.configure(
snmpEngine, authData, transportTarget, contextData.contextName)
return cmdgen.GetCommandGenerator().sendVarBinds(
snmpEngine, addrName, contextData.contextEngineId,
@ -232,7 +233,8 @@ def setCmd(snmpEngine, authData, transportTarget, contextData,
snmpEngine, varBinds, lookupMib
), cbCtx)
addrName, paramsName = lcd.configure(snmpEngine, authData, transportTarget)
addrName, paramsName = lcd.configure(
snmpEngine, authData, transportTarget, contextData.contextName)
return cmdgen.SetCommandGenerator().sendVarBinds(
snmpEngine, addrName, contextData.contextEngineId,
@ -343,7 +345,9 @@ def nextCmd(snmpEngine, authData, transportTarget, contextData,
varBindTable],
cbCtx)
addrName, paramsName = lcd.configure(snmpEngine, authData, transportTarget)
addrName, paramsName = lcd.configure(
snmpEngine, authData, transportTarget, contextData.contextName)
return cmdgen.NextCommandGenerator().sendVarBinds(
snmpEngine, addrName,
contextData.contextEngineId, contextData.contextName,
@ -483,7 +487,9 @@ def bulkCmd(snmpEngine, authData, transportTarget, contextData,
[vbProcessor.unmakeVarBinds(snmpEngine, varBindTableRow, lookupMib) for varBindTableRow in
varBindTable], cbCtx)
addrName, paramsName = lcd.configure(snmpEngine, authData, transportTarget)
addrName, paramsName = lcd.configure(
snmpEngine, authData, transportTarget, contextData.contextName)
return cmdgen.BulkCommandGenerator().sendVarBinds(
snmpEngine, addrName, contextData.contextEngineId,
contextData.contextName, nonRepeaters, maxRepetitions,

View File

@ -131,7 +131,7 @@ def sendNotification(snmpEngine, authData, transportTarget, contextData,
)
notifyName = lcd.configure(snmpEngine, authData, transportTarget,
notifyType)
notifyType, contextData.contextName)
return ntforg.NotificationOriginator().sendVarBinds(
snmpEngine, notifyName,

View File

@ -351,6 +351,8 @@ def nextCmd(snmpEngine, authData, transportTarget, contextData,
totalRows = totalCalls = 0
while True:
previousVarBinds = varBinds
if varBinds:
cmdgen.nextCmd(snmpEngine, authData, transportTarget, contextData,
*[(x[0], Null('')) for x in varBinds],
@ -378,13 +380,22 @@ def nextCmd(snmpEngine, authData, transportTarget, contextData,
yield (errorIndication, errorStatus, errorIndex, varBinds)
return
else:
stopFlag = True
varBinds = cbCtx['varBindTable'] and cbCtx['varBindTable'][0]
for idx, varBind in enumerate(varBinds):
for col, varBind in enumerate(varBinds):
name, val = varBind
if not isinstance(val, Null):
if lexicographicMode or initialVars[idx].isPrefixOf(name):
break
else:
if isinstance(val, Null):
varBinds[col] = previousVarBinds[col][0], endOfMibView
if not lexicographicMode and not initialVars[col].isPrefixOf(name):
varBinds[col] = previousVarBinds[col][0], endOfMibView
if stopFlag and varBinds[col][1] is not endOfMibView:
stopFlag = False
if stopFlag:
return
totalRows += 1
@ -545,6 +556,8 @@ def bulkCmd(snmpEngine, authData, transportTarget, contextData,
if maxRows and totalRows < maxRows:
maxRepetitions = min(maxRepetitions, maxRows - totalRows)
previousVarBinds = varBinds
cmdgen.bulkCmd(snmpEngine, authData, transportTarget, contextData,
nonRepeaters, maxRepetitions,
*[(x[0], Null('')) for x in varBinds],
@ -583,14 +596,17 @@ def bulkCmd(snmpEngine, authData, transportTarget, contextData,
break
for col in range(len(varBindTable[row])):
name, val = varBindTable[row][col]
if row:
previousVarBinds = varBindTable[row - 1]
if nullVarBinds[col]:
varBindTable[row][col] = name, endOfMibView
varBindTable[row][col] = previousVarBinds[col][0], endOfMibView
continue
stopFlag = False
if isinstance(val, Null):
varBindTable[row][col] = previousVarBinds[col][0], endOfMibView
nullVarBinds[col] = True
elif not lexicographicMode and not initialVars[col].isPrefixOf(name):
varBindTable[row][col] = name, endOfMibView
if not lexicographicMode and not initialVars[col].isPrefixOf(name):
varBindTable[row][col] = previousVarBinds[col][0], endOfMibView
nullVarBinds[col] = True
if stopFlag:
varBindTable = row and varBindTable[:row - 1] or []
@ -607,9 +623,13 @@ def bulkCmd(snmpEngine, authData, transportTarget, contextData,
if maxCalls and totalCalls >= maxCalls:
stopFlag = True
for varBinds in varBindTable:
initialVarBinds = (yield errorIndication, errorStatus, errorIndex, varBinds)
varBinds = varBindTable and varBindTable[-1] or []
for varBindRow in varBindTable:
initialVarBinds = (yield errorIndication, errorStatus, errorIndex, varBindRow)
if initialVarBinds:
varBinds = initialVarBinds
initialVars = [x[0] for x in vbProcessor.makeVarBinds(snmpEngine, varBinds)]
nullVarBinds = [False] * len(initialVars)

View File

@ -151,35 +151,50 @@ class CommunityData(object):
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
#: The HMAC-SHA-2 Digest Authentication Protocols (:RFC:`7860`)
usmHMAC128SHA224AuthProtocol = config.usmHMAC128SHA224AuthProtocol
usmHMAC192SHA256AuthProtocol = config.usmHMAC192SHA256AuthProtocol
usmHMAC256SHA384AuthProtocol = config.usmHMAC256SHA384AuthProtocol
usmHMAC384SHA512AuthProtocol = config.usmHMAC384SHA512AuthProtocol
"""No Authentication Protocol"""
usmHMACMD5AuthProtocol = config.usmHMACMD5AuthProtocol
"""The HMAC-MD5-96 Digest Authentication Protocol (:RFC:`3414#section-6`)"""
usmHMACSHAAuthProtocol = config.usmHMACSHAAuthProtocol
"""The HMAC-SHA-96 Digest Authentication Protocol AKA SHA-1 (:RFC:`3414#section-7`)"""
usmHMAC128SHA224AuthProtocol = config.usmHMAC128SHA224AuthProtocol
"""The HMAC-SHA-2 Digest Authentication Protocols (:RFC:`7860`)"""
usmHMAC192SHA256AuthProtocol = config.usmHMAC192SHA256AuthProtocol
"""The HMAC-SHA-2 Digest Authentication Protocols (:RFC:`7860`)"""
usmHMAC256SHA384AuthProtocol = config.usmHMAC256SHA384AuthProtocol
"""The HMAC-SHA-2 Digest Authentication Protocols (:RFC:`7860`)"""
usmHMAC384SHA512AuthProtocol = config.usmHMAC384SHA512AuthProtocol
"""The HMAC-SHA-2 Digest Authentication Protocols (:RFC:`7860`)"""
#: No Privacy Protocol.
usmNoPrivProtocol = config.usmNoPrivProtocol
#: The CBC-DES Symmetric Encryption Protocol (:RFC:`3414#section-8`)
"""No Privacy Protocol"""
usmDESPrivProtocol = config.usmDESPrivProtocol
#: The 3DES-EDE Symmetric Encryption Protocol (`draft-reeder-snmpv3-usm-3desede-00 <https://tools.ietf.org/html/draft-reeder-snmpv3-usm-3desede-00#section-5>`_)
"""The CBC-DES Symmetric Encryption Protocol (:RFC:`3414#section-8`)"""
usm3DESEDEPrivProtocol = config.usm3DESEDEPrivProtocol
#: The CFB128-AES-128 Symmetric Encryption Protocol (:RFC:`3826#section-3`)
"""The 3DES-EDE Symmetric Encryption Protocol (`draft-reeder-snmpv3-usm-3desede-00 <https:://tools.ietf.org/html/draft-reeder-snmpv3-usm-3desede-00#section-5>`_)"""
usmAesCfb128Protocol = config.usmAesCfb128Protocol
#: The CFB128-AES-192 Symmetric Encryption Protocol (`draft-blumenthal-aes-usm-04 <https://tools.ietf.org/html/draft-blumenthal-aes-usm-04#section-3>`_) with Reeder key localization
"""The CFB128-AES-128 Symmetric Encryption Protocol (:RFC:`3826#section-3`)"""
usmAesCfb192Protocol = config.usmAesCfb192Protocol
#: The CFB128-AES-256 Symmetric Encryption Protocol (`draft-blumenthal-aes-usm-04 <https://tools.ietf.org/html/draft-blumenthal-aes-usm-04#section-3>`_) with Reeder key localization
"""The CFB128-AES-192 Symmetric Encryption Protocol (`draft-blumenthal-aes-usm-04 <https:://tools.ietf.org/html/draft-blumenthal-aes-usm-04#section-3>`_) with Reeder key localization"""
usmAesCfb256Protocol = config.usmAesCfb256Protocol
#: The CFB128-AES-192 Symmetric Encryption Protocol (`draft-blumenthal-aes-usm-04 <https://tools.ietf.org/html/draft-blumenthal-aes-usm-04#section-3>`_)
"""The CFB128-AES-256 Symmetric Encryption Protocol (`draft-blumenthal-aes-usm-04 <https:://tools.ietf.org/html/draft-blumenthal-aes-usm-04#section-3>`_) with Reeder key localization"""
usmAesBlumenthalCfb192Protocol = config.usmAesBlumenthalCfb192Protocol
#: The CFB128-AES-256 Symmetric Encryption Protocol (`draft-blumenthal-aes-usm-04 <https://tools.ietf.org/html/draft-blumenthal-aes-usm-04#section-3>`_)
"""The CFB128-AES-192 Symmetric Encryption Protocol (`draft-blumenthal-aes-usm-04 <https:://tools.ietf.org/html/draft-blumenthal-aes-usm-04#section-3>`_)"""
usmAesBlumenthalCfb256Protocol = config.usmAesBlumenthalCfb256Protocol
"""The CFB128-AES-256 Symmetric Encryption Protocol (`draft-blumenthal-aes-usm-04 <https:://tools.ietf.org/html/draft-blumenthal-aes-usm-04#section-3>`_)"""
class UsmUserData(object):

View File

@ -8,6 +8,8 @@ from pysnmp.entity import config
from pysnmp import nextid, error
from pysnmp.hlapi.auth import *
from pyasn1.compat.octets import null
__all__ = ['CommandGeneratorLcdConfigurator',
'NotificationOriginatorLcdConfigurator']
@ -24,17 +26,17 @@ class AbstractLcdConfigurator(object):
snmpEngine.setUserContext(**{cacheId: cache})
return cache
def configure(self, snmpEngine, authData, transportTarget, *options):
def configure(self, snmpEngine, *args, **kwargs):
pass
def unconfigure(self, snmpEngine, authData=None):
def unconfigure(self, snmpEngine, *args, **kwargs):
pass
class CommandGeneratorLcdConfigurator(AbstractLcdConfigurator):
cacheKeys = ['auth', 'parm', 'tran', 'addr']
def configure(self, snmpEngine, authData, transportTarget, *options):
def configure(self, snmpEngine, authData, transportTarget, contextName, **options):
cache = self._getCache(snmpEngine)
if isinstance(authData, CommunityData):
if authData.communityIndex not in cache['auth']:
@ -94,7 +96,10 @@ class CommandGeneratorLcdConfigurator(AbstractLcdConfigurator):
transportKey = (paramsName, transportTarget.transportDomain,
transportTarget.transportAddr,
transportTarget.tagList)
transportTarget.timeout,
transportTarget.retries,
transportTarget.tagList,
transportTarget.iface)
if transportKey in cache['addr']:
addrName, useCount = cache['addr'][transportKey]
@ -114,7 +119,7 @@ class CommandGeneratorLcdConfigurator(AbstractLcdConfigurator):
return addrName, paramsName
def unconfigure(self, snmpEngine, authData=None):
def unconfigure(self, snmpEngine, authData=None, contextName=null, **options):
cache = self._getCache(snmpEngine)
if authData:
if isinstance(authData, CommunityData):
@ -175,7 +180,7 @@ class CommandGeneratorLcdConfigurator(AbstractLcdConfigurator):
cache['addr'][addrKey] = addrName, useCount
else:
config.delTargetAddr(snmpEngine, addrName)
del cache['addr'][addrKey]
addrNames.add(addrKey)
if addrKey[1] in cache['tran']:
@ -195,9 +200,9 @@ class NotificationOriginatorLcdConfigurator(AbstractLcdConfigurator):
cacheKeys = ['auth', 'name']
_cmdGenLcdCfg = CommandGeneratorLcdConfigurator()
def configure(self, snmpEngine, authData, transportTarget, *options):
def configure(self, snmpEngine, authData, transportTarget, notifyType,
contextName, **options):
cache = self._getCache(snmpEngine)
notifyType = options and options[0] or 'trap'
notifyName = None
# Create matching transport tags if not given by user. Not good!
@ -208,7 +213,8 @@ class NotificationOriginatorLcdConfigurator(AbstractLcdConfigurator):
if isinstance(authData, CommunityData) and not authData.tag:
authData.tag = transportTarget.tagList.split()[0]
addrName, paramsName = self._cmdGenLcdCfg.configure(snmpEngine, authData, transportTarget)
addrName, paramsName = self._cmdGenLcdCfg.configure(
snmpEngine, authData, transportTarget, contextName, **options)
tagList = transportTarget.tagList.split()
if not tagList:
tagList = ['']
@ -227,7 +233,7 @@ class NotificationOriginatorLcdConfigurator(AbstractLcdConfigurator):
notifyType
)
cache['name'][notifyNameKey] = notifyName, paramsName, 1
authDataKey = authData.securityName, authData.securityModel
authDataKey = authData.securityName, authData.securityModel, authData.securityLevel, contextName
if authDataKey in cache['auth']:
authDataX, subTree, useCount = cache['auth'][authDataKey]
cache['auth'][authDataKey] = authDataX, subTree, useCount + 1
@ -235,23 +241,24 @@ class NotificationOriginatorLcdConfigurator(AbstractLcdConfigurator):
subTree = (1, 3, 6)
config.addTrapUser(snmpEngine, authData.securityModel,
authData.securityName, authData.securityLevel,
subTree)
subTree, contextName=contextName)
cache['auth'][authDataKey] = authData, subTree, 1
return notifyName
def unconfigure(self, snmpEngine, authData=None):
def unconfigure(self, snmpEngine, authData=None, contextName=null, **options):
cache = self._getCache(snmpEngine)
if authData:
authDataKey = authData.securityName, authData.securityModel
authDataKey = authData.securityName, authData.securityModel, authData.securityLevel, contextName
if authDataKey in cache['auth']:
authDataKeys = (authDataKey,)
else:
raise error.PySnmpError('Unknown authData %s' % (authData,))
else:
authDataKeys = tuple(cache['auth'].keys())
authDataKeys = tuple(cache['auth'])
addrNames, paramsNames = self._cmdGenLcdCfg.unconfigure(snmpEngine, authData)
addrNames, paramsNames = self._cmdGenLcdCfg.unconfigure(
snmpEngine, authData, contextName, **options)
notifyAndParamsNames = [(cache['name'][x], x) for x in cache['name'].keys() if x[0] in paramsNames]

View File

@ -4,6 +4,8 @@
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pysnmp/license.html
#
import sys
from pysnmp.smi.rfc1902 import *
from pysnmp.hlapi.auth import *
from pysnmp.hlapi.context import *
@ -120,13 +122,15 @@ def getCmd(snmpEngine, authData, transportTarget, contextData,
try:
varBindsUnmade = vbProcessor.unmakeVarBinds(snmpEngine, varBinds, lookupMib)
except Exception as e:
deferred.errback(Failure(e))
except Exception:
ex = sys.exc_info()[1]
deferred.errback(Failure(ex))
else:
deferred.callback((errorStatus, errorIndex, varBindsUnmade))
addrName, paramsName = lcd.configure(snmpEngine, authData, transportTarget)
addrName, paramsName = lcd.configure(
snmpEngine, authData, transportTarget, contextData.contextName)
deferred = Deferred()
@ -236,13 +240,15 @@ def setCmd(snmpEngine, authData, transportTarget, contextData,
try:
varBindsUnmade = vbProcessor.unmakeVarBinds(snmpEngine, varBinds, lookupMib)
except Exception as e:
deferred.errback(Failure(e))
except Exception:
ex = sys.exc_info()[1]
deferred.errback(Failure(ex))
else:
deferred.callback((errorStatus, errorIndex, varBindsUnmade))
addrName, paramsName = lcd.configure(snmpEngine, authData, transportTarget)
addrName, paramsName = lcd.configure(
snmpEngine, authData, transportTarget, contextData.contextName)
deferred = Deferred()
@ -366,13 +372,15 @@ def nextCmd(snmpEngine, authData, transportTarget, contextData,
lookupMib)
for varBindTableRow in varBindTable]
except Exception as e:
deferred.errback(Failure(e))
except Exception:
ex = sys.exc_info()[1]
deferred.errback(Failure(ex))
else:
deferred.callback((errorStatus, errorIndex, varBindsUnmade))
addrName, paramsName = lcd.configure(snmpEngine, authData, transportTarget)
addrName, paramsName = lcd.configure(
snmpEngine, authData, transportTarget, contextData.contextName)
deferred = Deferred()
@ -524,13 +532,15 @@ def bulkCmd(snmpEngine, authData, transportTarget, contextData,
lookupMib)
for varBindTableRow in varBindTable]
except Exception as e:
deferred.errback(Failure(e))
except Exception:
ex = sys.exc_info()[1]
deferred.errback(Failure(ex))
else:
deferred.callback((errorStatus, errorIndex, varBindsUnmade))
addrName, paramsName = lcd.configure(snmpEngine, authData, transportTarget)
addrName, paramsName = lcd.configure(
snmpEngine, authData, transportTarget, contextData.contextName)
deferred = Deferred()

View File

@ -4,6 +4,8 @@
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pysnmp/license.html
#
import sys
from pysnmp.smi.rfc1902 import *
from pysnmp.hlapi.auth import *
from pysnmp.hlapi.context import *
@ -128,15 +130,15 @@ def sendNotification(snmpEngine, authData, transportTarget, contextData,
try:
varBindsUnmade = vbProcessor.unmakeVarBinds(snmpEngine, varBinds, lookupMib)
except Exception as e:
deferred.errback(Failure(e))
except Exception:
ex = sys.exc_info()[1]
deferred.errback(Failure(ex))
else:
deferred.callback((errorStatus, errorIndex, varBindsUnmade))
notifyName = lcd.configure(
snmpEngine, authData, transportTarget, notifyType
)
notifyName = lcd.configure(snmpEngine, authData, transportTarget,
notifyType, contextData.contextName)
def __trapFun(deferred):
deferred.callback((0, 0, []))

View File

@ -8,14 +8,14 @@ from pysnmp.smi.error import NoSuchInstanceError
from pysnmp.proto import errind, error
from pysnmp import debug
__powOfTwoSeq = [128, 64, 32, 16, 8, 4, 2, 1]
# 3.2
class Vacm(object):
"""View-based Access Control Model"""
accessModelID = 3
_powOfTwoSeq = (128, 64, 32, 16, 8, 4, 2, 1)
def isAccessAllowed(self,
snmpEngine,
securityModel,
@ -31,25 +31,30 @@ class Vacm(object):
securityModel, securityName, securityLevel, viewType, contextName, variableName))
# 3.2.1
vacmContextEntry, = mibInstrumController.mibBuilder.importSymbols('SNMP-VIEW-BASED-ACM-MIB', 'vacmContextEntry')
vacmContextEntry, = mibInstrumController.mibBuilder.importSymbols(
'SNMP-VIEW-BASED-ACM-MIB', 'vacmContextEntry')
tblIdx = vacmContextEntry.getInstIdFromIndices(contextName)
try:
vacmContextName = vacmContextEntry.getNode(
vacmContextEntry.getNode(
vacmContextEntry.name + (1,) + tblIdx
).syntax
except NoSuchInstanceError:
raise error.StatusInformation(errorIndication=errind.noSuchContext)
# 3.2.2
vacmSecurityToGroupEntry, = mibInstrumController.mibBuilder.importSymbols('SNMP-VIEW-BASED-ACM-MIB',
'vacmSecurityToGroupEntry')
vacmSecurityToGroupEntry, = mibInstrumController.mibBuilder.importSymbols(
'SNMP-VIEW-BASED-ACM-MIB', 'vacmSecurityToGroupEntry')
tblIdx = vacmSecurityToGroupEntry.getInstIdFromIndices(
securityModel, securityName
)
try:
vacmGroupName = vacmSecurityToGroupEntry.getNode(
vacmSecurityToGroupEntry.name + (3,) + tblIdx
).syntax
except NoSuchInstanceError:
raise error.StatusInformation(errorIndication=errind.noGroupName)
@ -57,6 +62,7 @@ class Vacm(object):
vacmAccessEntry, = mibInstrumController.mibBuilder.importSymbols(
'SNMP-VIEW-BASED-ACM-MIB', 'vacmAccessEntry'
)
# XXX partial context name match
tblIdx = vacmAccessEntry.getInstIdFromIndices(
vacmGroupName, contextName, securityModel, securityLevel
@ -74,51 +80,62 @@ class Vacm(object):
try:
viewName = vacmAccessEntry.getNode(entryIdx).syntax
except NoSuchInstanceError:
raise error.StatusInformation(errorIndication=errind.noAccessEntry)
if not len(viewName):
if not viewName:
raise error.StatusInformation(errorIndication=errind.noSuchView)
# XXX split onto object & instance ?
# 3.2.5a
vacmViewTreeFamilyEntry, = mibInstrumController.mibBuilder.importSymbols('SNMP-VIEW-BASED-ACM-MIB',
'vacmViewTreeFamilyEntry')
vacmViewTreeFamilyEntry, = mibInstrumController.mibBuilder.importSymbols(
'SNMP-VIEW-BASED-ACM-MIB', 'vacmViewTreeFamilyEntry')
tblIdx = vacmViewTreeFamilyEntry.getInstIdFromIndices(viewName)
# Walk over entries
initialTreeName = treeName = vacmViewTreeFamilyEntry.name + (2,) + tblIdx
maskName = vacmViewTreeFamilyEntry.name + (3,) + tblIdx
while 1:
while True:
vacmViewTreeFamilySubtree = vacmViewTreeFamilyEntry.getNextNode(
treeName
)
vacmViewTreeFamilyMask = vacmViewTreeFamilyEntry.getNextNode(
maskName
)
treeName = vacmViewTreeFamilySubtree.name
maskName = vacmViewTreeFamilyMask.name
if initialTreeName != treeName[:len(initialTreeName)]:
# 3.2.5b
raise error.StatusInformation(errorIndication=errind.notInView)
l = len(vacmViewTreeFamilySubtree.syntax)
if l > len(variableName):
continue
if vacmViewTreeFamilyMask.syntax:
mask = []
for c in vacmViewTreeFamilyMask.syntax.asNumbers():
mask = mask + [b & c for b in __powOfTwoSeq]
mask.extend([b & c for b in self._powOfTwoSeq])
m = len(mask) - 1
idx = l - 1
while idx:
if idx > m or mask[idx] and \
vacmViewTreeFamilySubtree.syntax[idx] != variableName[idx]:
if (idx > m or mask[idx] and
vacmViewTreeFamilySubtree.syntax[idx] != variableName[idx]):
break
idx -= 1
if idx:
continue # no match
else: # no mask
if vacmViewTreeFamilySubtree.syntax != variableName[:l]:
continue # no match
# 3.2.5c
return error.StatusInformation(errorIndication=errind.accessAllowed)

View File

@ -271,7 +271,7 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel):
try:
try:
smHandler = snmpEngine.securityModels[int(securityModel)]
smHandler = snmpEngine.securityModels[securityModel]
except KeyError:
raise error.StatusInformation(

View File

@ -40,8 +40,11 @@ class HeaderData(univ.Sequence):
namedtype.NamedType('msgMaxSize',
univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(484, 2147483647))),
namedtype.NamedType('msgFlags', univ.OctetString().subtype(subtypeSpec=constraint.ValueSizeConstraint(1, 1))),
# NOTE (etingof): constrain SNMPv3 message to only USM+ security models
# because SNMPv1/v2c seems incompatible in pysnmp implementation, not sure
# if it's intended by the SNMP standard at all...
namedtype.NamedType('msgSecurityModel',
univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(1, 2147483647)))
univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(3, 2147483647)))
)

View File

@ -10,7 +10,32 @@ from pysnmp.proto import rfc1155, error
__all__ = ['Opaque', 'TimeTicks', 'Bits', 'Integer', 'OctetString',
'IpAddress', 'Counter64', 'Unsigned32', 'Gauge32', 'Integer32',
'ObjectIdentifier', 'Counter32']
'ObjectIdentifier', 'Counter32', 'Null']
class Null(univ.Null):
"""Creates an instance of SNMP Null class.
:py:class:`~pysnmp.proto.rfc1902.Null` type represents the absence
of value.
Parameters
----------
initializer: str
Python string object. Must be an empty string.
Raises
------
PyAsn1Error :
On constraint violation or bad initializer.
Examples
--------
>>> from pysnmp.proto.rfc1902 import *
>>> Null('')
Null('')
>>>
"""
class Integer32(univ.Integer):
@ -128,12 +153,17 @@ class Integer(Integer32):
@classmethod
def withNamedValues(cls, **values):
"""Creates a subclass with discreet named values constraint.
"""Create a subclass with discreet named values constraint.
Reduce fully duplicate enumerations along the way.
"""
enums = set(cls.namedValues.items())
enums.update(values.items())
class X(cls):
namedValues = cls.namedValues + namedval.NamedValues(*values.items())
subtypeSpec = cls.subtypeSpec + constraint.SingleValueConstraint(*values.values())
namedValues = namedval.NamedValues(*enums)
subtypeSpec = cls.subtypeSpec + constraint.SingleValueConstraint(
*values.values())
X.__name__ = cls.__name__
return X
@ -598,11 +628,12 @@ class Bits(OctetString):
"""
namedValues = namedval.NamedValues()
def __init__(self, value=univ.noValue, **kwargs):
if 'namedValues' not in kwargs:
kwargs['namedValues'] = self.namedValues
def __new__(cls, *args, **kwargs):
if 'namedValues' in kwargs:
Bits = cls.withNamedBits(**dict(kwargs.pop('namedValues')))
return Bits(*args, **kwargs)
OctetString.__init__(self, value, **kwargs)
return OctetString.__new__(cls)
def prettyIn(self, bits):
if not isinstance(bits, (tuple, list)):
@ -636,10 +667,14 @@ class Bits(OctetString):
@classmethod
def withNamedBits(cls, **values):
"""Creates a subclass with discreet named bits constraint.
Reduce fully duplicate enumerations along the way.
"""
enums = set(cls.namedValues.items())
enums.update(values.items())
class X(cls):
namedValues = cls.namedValues + namedval.NamedValues(*values.items())
namedValues = namedval.NamedValues(*enums)
X.__name__ = cls.__name__
return X

View File

@ -38,7 +38,7 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel):
nextMibNode = snmpTargetParamsSecurityName
while 1:
while True:
try:
nextMibNode = snmpTargetParamsSecurityName.getNextNode(nextMibNode.name)
@ -49,10 +49,18 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel):
mibNode = snmpTargetParamsSecurityModel.getNode(snmpTargetParamsSecurityModel.name + instId)
if mibNode.syntax not in self.__nameToModelMap:
self.__nameToModelMap[nextMibNode.syntax] = set()
try:
if mibNode.syntax not in self.__nameToModelMap:
self.__nameToModelMap[nextMibNode.syntax] = set()
self.__nameToModelMap[nextMibNode.syntax].add(mibNode.syntax)
self.__nameToModelMap[nextMibNode.syntax].add(mibNode.syntax)
except PyAsn1Error:
debug.logger & debug.flagSM and debug.logger(
'_sec2com: table entries %r/%r hashing failed' % (
nextMibNode.syntax, mibNode.syntax)
)
continue
self.__paramsBranchId = snmpTargetParamsSecurityName.branchVersionId
@ -72,7 +80,8 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel):
self.__securityMap = {}
nextMibNode = snmpCommunityName
while 1:
while True:
try:
nextMibNode = snmpCommunityName.getNextNode(nextMibNode.name)
@ -88,9 +97,17 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel):
_contextName = snmpCommunityContextName.getNode(snmpCommunityContextName.name + instId).syntax
self.__securityMap[(_securityName,
_contextEngineId,
_contextName)] = nextMibNode.syntax
try:
self.__securityMap[(_securityName,
_contextEngineId,
_contextName)] = nextMibNode.syntax
except PyAsn1Error:
debug.logger & debug.flagSM and debug.logger(
'_sec2com: table entries %r/%r/%r hashing failed' % (
_securityName, _contextEngineId, _contextName)
)
continue
self.__securityBranchId = snmpCommunityName.branchVersionId
@ -123,11 +140,14 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel):
self.__transportToTagMap = {}
nextMibNode = snmpTargetAddrTagList
while True:
try:
nextMibNode = snmpTargetAddrTagList.getNextNode(nextMibNode.name)
except NoSuchInstanceError:
break
instId = nextMibNode.name[len(snmpTargetAddrTagList.name):]
targetAddrTDomain = snmpTargetAddrTDomain.getNode(snmpTargetAddrTDomain.name + instId).syntax
targetAddrTAddress = snmpTargetAddrTAddress.getNode(snmpTargetAddrTAddress.name + instId).syntax
@ -144,17 +164,29 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel):
targetAddrTAddress = tuple(TransportAddressIPv6(targetAddrTAddress))
elif targetAddrTDomain[:len(unix.snmpLocalDomain)] == unix.snmpLocalDomain:
targetAddrTAddress = str(targetAddrTAddress)
targetAddr = targetAddrTDomain, targetAddrTAddress
targetAddrTagList = snmpTargetAddrTagList.getNode(snmpTargetAddrTagList.name + instId).syntax
if targetAddr not in self.__transportToTagMap:
self.__transportToTagMap[targetAddr] = set()
if targetAddrTagList:
self.__transportToTagMap[targetAddr].update(
[SnmpTagValue(x)
for x in targetAddrTagList.asOctets().split()]
try:
if targetAddrTagList:
self.__transportToTagMap[targetAddr].update(
[SnmpTagValue(x)
for x in targetAddrTagList.asOctets().split()]
)
else:
self.__transportToTagMap[targetAddr].add(self.__emptyTag)
except PyAsn1Error:
debug.logger & debug.flagSM and debug.logger(
'_com2sec: table entries %r/%r hashing failed' % (
targetAddr, targetAddrTagList)
)
else:
self.__transportToTagMap[targetAddr].add(self.__emptyTag)
continue
self.__transportBranchId = snmpTargetAddrTAddress.branchVersionId
@ -163,6 +195,7 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel):
snmpTargetParamsSecurityName, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
'SNMP-TARGET-MIB', 'snmpTargetParamsSecurityName')
if self.__paramsBranchId != snmpTargetParamsSecurityName.branchVersionId:
snmpTargetParamsSecurityModel, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
'SNMP-TARGET-MIB', 'snmpTargetParamsSecurityModel')
@ -182,10 +215,18 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel):
mibNode = snmpTargetParamsSecurityModel.getNode(snmpTargetParamsSecurityModel.name + instId)
if nextMibNode.syntax not in self.__nameToModelMap:
self.__nameToModelMap[nextMibNode.syntax] = set()
try:
if nextMibNode.syntax not in self.__nameToModelMap:
self.__nameToModelMap[nextMibNode.syntax] = set()
self.__nameToModelMap[nextMibNode.syntax].add(mibNode.syntax)
self.__nameToModelMap[nextMibNode.syntax].add(mibNode.syntax)
except PyAsn1Error:
debug.logger & debug.flagSM and debug.logger(
'_com2sec: table entries %r/%r hashing failed' % (
nextMibNode.syntax, mibNode.syntax)
)
continue
self.__paramsBranchId = snmpTargetParamsSecurityName.branchVersionId
@ -211,6 +252,7 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel):
self.__tagAndCommunityToSecurityMap = {}
nextMibNode = snmpCommunityName
while True:
try:
nextMibNode = snmpCommunityName.getNextNode(nextMibNode.name)
@ -231,17 +273,25 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel):
_tagAndCommunity = transportTag, nextMibNode.syntax
if _tagAndCommunity not in self.__tagAndCommunityToSecurityMap:
self.__tagAndCommunityToSecurityMap[_tagAndCommunity] = set()
try:
if _tagAndCommunity not in self.__tagAndCommunityToSecurityMap:
self.__tagAndCommunityToSecurityMap[_tagAndCommunity] = set()
self.__tagAndCommunityToSecurityMap[_tagAndCommunity].add(
(securityName, contextEngineId, contextName)
)
self.__tagAndCommunityToSecurityMap[_tagAndCommunity].add(
(securityName, contextEngineId, contextName)
)
if nextMibNode.syntax not in self.__communityToTagMap:
self.__communityToTagMap[nextMibNode.syntax] = set()
if nextMibNode.syntax not in self.__communityToTagMap:
self.__communityToTagMap[nextMibNode.syntax] = set()
self.__communityToTagMap[nextMibNode.syntax].add(transportTag)
self.__communityToTagMap[nextMibNode.syntax].add(transportTag)
except PyAsn1Error:
debug.logger & debug.flagSM and debug.logger(
'_com2sec: table entries %r/%r hashing failed' % (
_tagAndCommunity, nextMibNode.syntax)
)
continue
self.__communityBranchId = snmpCommunityName.branchVersionId

View File

@ -263,7 +263,7 @@ class MibBuilder(object):
self.mibSymbols = {}
self.__mibSources = []
self.__modSeen = {}
self.__modPathsSeen = {}
self.__modPathsSeen = set()
self.__mibCompiler = None
self.setMibSources(*sources)
@ -321,19 +321,19 @@ class MibBuilder(object):
debug.logger & debug.flagBld and debug.logger('loadModule: seen %s' % modPath)
break
else:
self.__modPathsSeen[modPath] = 1
self.__modPathsSeen.add(modPath)
debug.logger & debug.flagBld and debug.logger('loadModule: evaluating %s' % modPath)
g = {'mibBuilder': self, 'userCtx': userCtx}
try:
exec (modData, g)
exec(compile(modData, modPath, 'exec'), g)
except Exception:
del self.__modPathsSeen[modPath]
raise error.MibLoadError(
'MIB module \"%s\" load error: %s' % (modPath, traceback.format_exception(*sys.exc_info()))
'MIB module \'%s\' load error: %s' % (modPath, traceback.format_exception(*sys.exc_info()))
)
self.__modSeen[modName] = modPath

View File

@ -80,7 +80,7 @@ class InetAddress(TextualConvention, OctetString):
for parentIndex in reversed(parentIndices):
if isinstance(parentIndex, InetAddressType):
try:
return parentRow.setFromName(cls.typeMap[parentIndex], value, impliedFlag, parentIndices)
return parentRow.setFromName(cls.typeMap[int(parentIndex)], value, impliedFlag, parentIndices)
except KeyError:
pass
@ -90,7 +90,7 @@ class InetAddress(TextualConvention, OctetString):
for parentIndex in reversed(parentIndices):
if isinstance(parentIndex, InetAddressType):
try:
return parentRow.getAsName(self.typeMap[parentIndex].clone(self.asOctets()), impliedFlag, parentIndices)
return parentRow.getAsName(self.typeMap[int(parentIndex)].clone(self.asOctets().decode('ascii')), impliedFlag, parentIndices)
except KeyError:
pass

View File

@ -17,5 +17,5 @@ Integer32, MibScalar, MibTable, MibTableRow, MibTableColumn, TimeTicks, iso, Gau
snmpInBadTypes = MibScalar((1, 3, 6, 1, 2, 1, 11, 7), Counter32()).setMaxAccess("readonly")
if mibBuilder.loadTexts: snmpInBadTypes.setStatus('mandatory')
snmpOutReadOnlys = MibScalar((1, 3, 6, 1, 2, 1, 11, 23), Counter32()).setMaxAccess("readonly")
if mibBuilder.loadTexts: snmpInReadOnlys.setStatus('mandatory')
if mibBuilder.loadTexts: snmpOutReadOnlys.setStatus('mandatory')
mibBuilder.exportSymbols("RFC1158-MIB", snmpOutReadOnlys=snmpOutReadOnlys, snmpInBadTypes=snmpInBadTypes)

View File

@ -34,6 +34,10 @@ if mibBuilder.loadTexts: vacmContextEntry.setDescription('Information about a pa
vacmContextName = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 1, 1, 1), SnmpAdminString().subtype(subtypeSpec=ValueSizeConstraint(0, 32))).setMaxAccess("readonly")
if mibBuilder.loadTexts: vacmContextName.setStatus('current')
if mibBuilder.loadTexts: vacmContextName.setDescription('A human readable name identifying a particular context at a particular SNMP entity. The empty contextName (zero length) represents the default context. ')
# The RowStatus column is not present in the MIB
vacmContextStatus = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 1, 1, 2), RowStatus()).setMaxAccess("readcreate")
if mibBuilder.loadTexts: vacmContextStatus.setStatus('current')
if mibBuilder.loadTexts: vacmContextStatus.setDescription("The status of this conceptual row. Until instances of all corresponding columns are appropriately configured, the value of the corresponding instance of the vacmContextTableStatus column is 'notReady'. In particular, a newly created row cannot be made active until a value has been set for vacmContextName. The RowStatus TC [RFC2579] requires that this DESCRIPTION clause states under which circumstances other objects in this row can be modified: The value of this object has no effect on whether other objects in this conceptual row can be modified. ")
vacmSecurityToGroupTable = MibTable((1, 3, 6, 1, 6, 3, 16, 1, 2), )
if mibBuilder.loadTexts: vacmSecurityToGroupTable.setStatus('current')
if mibBuilder.loadTexts: vacmSecurityToGroupTable.setDescription('This table maps a combination of securityModel and securityName into a groupName which is used to define an access control policy for a group of principals. ')
@ -122,4 +126,4 @@ vacmMIBCompliance = ModuleCompliance((1, 3, 6, 1, 6, 3, 16, 2, 1, 1)).setObjects
if mibBuilder.loadTexts: vacmMIBCompliance.setDescription('The compliance statement for SNMP engines which implement the SNMP View-based Access Control Model configuration MIB. ')
vacmBasicGroup = ObjectGroup((1, 3, 6, 1, 6, 3, 16, 2, 2, 1)).setObjects(("SNMP-VIEW-BASED-ACM-MIB", "vacmContextName"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmGroupName"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmSecurityToGroupStorageType"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmSecurityToGroupStatus"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmAccessContextMatch"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmAccessReadViewName"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmAccessWriteViewName"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmAccessNotifyViewName"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmAccessStorageType"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmAccessStatus"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmViewSpinLock"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmViewTreeFamilyMask"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmViewTreeFamilyType"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmViewTreeFamilyStorageType"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmViewTreeFamilyStatus"))
if mibBuilder.loadTexts: vacmBasicGroup.setDescription('A collection of objects providing for remote configuration of an SNMP engine which implements the SNMP View-based Access Control Model. ')
mibBuilder.exportSymbols("SNMP-VIEW-BASED-ACM-MIB", vacmSecurityModel=vacmSecurityModel, vacmSecurityToGroupEntry=vacmSecurityToGroupEntry, vacmMIBConformance=vacmMIBConformance, vacmAccessReadViewName=vacmAccessReadViewName, vacmViewTreeFamilyMask=vacmViewTreeFamilyMask, snmpVacmMIB=snmpVacmMIB, vacmViewTreeFamilyType=vacmViewTreeFamilyType, vacmMIBGroups=vacmMIBGroups, vacmAccessContextMatch=vacmAccessContextMatch, vacmAccessNotifyViewName=vacmAccessNotifyViewName, vacmViewSpinLock=vacmViewSpinLock, vacmAccessWriteViewName=vacmAccessWriteViewName, vacmContextTable=vacmContextTable, PYSNMP_MODULE_ID=snmpVacmMIB, vacmViewTreeFamilyViewName=vacmViewTreeFamilyViewName, vacmMIBObjects=vacmMIBObjects, vacmViewTreeFamilyStatus=vacmViewTreeFamilyStatus, vacmSecurityName=vacmSecurityName, vacmGroupName=vacmGroupName, vacmAccessSecurityLevel=vacmAccessSecurityLevel, vacmBasicGroup=vacmBasicGroup, vacmContextName=vacmContextName, vacmSecurityToGroupStatus=vacmSecurityToGroupStatus, vacmAccessEntry=vacmAccessEntry, vacmMIBViews=vacmMIBViews, vacmAccessStorageType=vacmAccessStorageType, vacmMIBCompliances=vacmMIBCompliances, vacmViewTreeFamilyEntry=vacmViewTreeFamilyEntry, vacmViewTreeFamilyTable=vacmViewTreeFamilyTable, vacmSecurityToGroupStorageType=vacmSecurityToGroupStorageType, vacmAccessTable=vacmAccessTable, vacmAccessContextPrefix=vacmAccessContextPrefix, vacmViewTreeFamilyStorageType=vacmViewTreeFamilyStorageType, vacmMIBCompliance=vacmMIBCompliance, vacmAccessSecurityModel=vacmAccessSecurityModel, vacmAccessStatus=vacmAccessStatus, vacmContextEntry=vacmContextEntry, vacmSecurityToGroupTable=vacmSecurityToGroupTable, vacmViewTreeFamilySubtree=vacmViewTreeFamilySubtree)
mibBuilder.exportSymbols("SNMP-VIEW-BASED-ACM-MIB", vacmSecurityModel=vacmSecurityModel, vacmSecurityToGroupEntry=vacmSecurityToGroupEntry, vacmMIBConformance=vacmMIBConformance, vacmAccessReadViewName=vacmAccessReadViewName, vacmViewTreeFamilyMask=vacmViewTreeFamilyMask, snmpVacmMIB=snmpVacmMIB, vacmViewTreeFamilyType=vacmViewTreeFamilyType, vacmMIBGroups=vacmMIBGroups, vacmAccessContextMatch=vacmAccessContextMatch, vacmAccessNotifyViewName=vacmAccessNotifyViewName, vacmViewSpinLock=vacmViewSpinLock, vacmAccessWriteViewName=vacmAccessWriteViewName, vacmContextTable=vacmContextTable, PYSNMP_MODULE_ID=snmpVacmMIB, vacmViewTreeFamilyViewName=vacmViewTreeFamilyViewName, vacmMIBObjects=vacmMIBObjects, vacmViewTreeFamilyStatus=vacmViewTreeFamilyStatus, vacmSecurityName=vacmSecurityName, vacmGroupName=vacmGroupName, vacmAccessSecurityLevel=vacmAccessSecurityLevel, vacmBasicGroup=vacmBasicGroup, vacmContextName=vacmContextName, vacmContextStatus=vacmContextStatus, vacmSecurityToGroupStatus=vacmSecurityToGroupStatus, vacmAccessEntry=vacmAccessEntry, vacmMIBViews=vacmMIBViews, vacmAccessStorageType=vacmAccessStorageType, vacmMIBCompliances=vacmMIBCompliances, vacmViewTreeFamilyEntry=vacmViewTreeFamilyEntry, vacmViewTreeFamilyTable=vacmViewTreeFamilyTable, vacmSecurityToGroupStorageType=vacmSecurityToGroupStorageType, vacmAccessTable=vacmAccessTable, vacmAccessContextPrefix=vacmAccessContextPrefix, vacmViewTreeFamilyStorageType=vacmViewTreeFamilyStorageType, vacmMIBCompliance=vacmMIBCompliance, vacmAccessSecurityModel=vacmAccessSecurityModel, vacmAccessStatus=vacmAccessStatus, vacmContextEntry=vacmContextEntry, vacmSecurityToGroupTable=vacmSecurityToGroupTable, vacmViewTreeFamilySubtree=vacmViewTreeFamilySubtree)

View File

@ -184,7 +184,7 @@ class TextualConvention(object):
"""Implements DISPLAY-HINT parsing into base SNMP value
Proper parsing seems impossible due to ambiguities.
Here we are truing to do our best, but be prepared
Here we are trying to do our best, but be prepared
for failures on complicated DISPLAY-HINTs.
Keep in mind that this parser only works with "text"
@ -259,6 +259,7 @@ class TextualConvention(object):
# how do we know if object is initialized with display-hint
# formatted text? based on "text" input maybe?
# That boils down to `str` object on Py3 or `unicode` on Py2.
if octets.isStringType(value) and not octets.isOctetsType(value):
value = base.prettyIn(self, value)
else:
@ -267,6 +268,7 @@ class TextualConvention(object):
outputValue = octets.str2octs('')
runningValue = value
displayHint = self.displayHint
while runningValue and displayHint:
# 1 this information is totally lost, just fail explicitly
if displayHint[0] == '*':

View File

@ -506,7 +506,7 @@ class ObjectIdentity(object):
self.__oid += instIds
self.__indices = rowNode.getIndicesFromInstId(instIds)
except PyAsn1Error:
raise SmiError('Instance index %r to OID convertion failure at object %r: %s' % (
raise SmiError('Instance index %r to OID conversion failure at object %r: %s' % (
self.__args[2:], mibNode.getLabel(), sys.exc_info()[1]))
elif self.__args[2:]: # any other kind of MIB node with indices
if self.__args[2:]:

View File

@ -2,6 +2,8 @@
set -e
PYTHON=${1:-python}
for x in examples/hlapi/asyncore/sync/manager/cmdgen/*.py \
examples/hlapi/asyncore/sync/agent/ntforg/*.py \
examples/hlapi/asyncore/manager/cmdgen/*.py \
@ -19,7 +21,7 @@ do
continue
;;
*)
python "${x}"
$PYTHON "${x}" | tail -50
;;
esac
done
done

View File

@ -1,2 +1,5 @@
[bdist_wheel]
universal = 1
[metadata]
license_file = LICENSE.rst

View File

@ -1,12 +1,13 @@
#!/usr/bin/env python
"""SNMP library for Python
SNMP v1/v2c/v3 engine and apps written in pure-Python.
Supports Manager/Agent/Proxy roles, scriptable MIBs,
asynchronous operation and multiple transports.
SNMP v1/v2c/v3 engine and Standard Applications suite written in pure-Python.
Supports Manager/Agent/Proxy roles, Manager/Agent-side MIBs, asynchronous
operation and multiple network transports.
"""
import sys
import os
import re
classifiers = """\
Development Status :: 5 - Production/Stable
@ -30,6 +31,7 @@ Programming Language :: Python :: 3.3
Programming Language :: Python :: 3.4
Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Topic :: Communications
Topic :: System :: Monitoring
Topic :: System :: Networking :: Monitoring
@ -54,33 +56,52 @@ if sys.version_info[:2] < (2, 4):
print("ERROR: this package requires Python 2.4 or later!")
sys.exit(1)
requires = [ln.strip() for ln in open('requirements.txt').readlines()]
try:
from setuptools import setup
import setuptools
setup, Command = setuptools.setup, setuptools.Command
observed_version = [int(x) for x in setuptools.__version__.split('.')]
required_version = [36, 2, 0]
# NOTE(etingof): require fresh setuptools to build proper wheels
# See also: https://hynek.me/articles/conditional-python-dependencies/
if ('bdist_wheel' in sys.argv and
observed_version < required_version):
print("ERROR: your wheels won't come out round with setuptools %s! "
"Upgrade to %s and try again." % (
'.'.join([str(x) for x in observed_version]),
'.'.join([str(x) for x in required_version])))
sys.exit(1)
params = {
'install_requires': ['pyasn1>=0.2.3', 'pysmi', 'pycryptodomex'],
'install_requires': requires,
'zip_safe': True
}
except ImportError:
for arg in sys.argv:
if 'egg' in arg:
howto_install_setuptools()
sys.exit(1)
if 'bdist_wheel' in sys.argv or 'bdist_egg' in sys.argv:
howto_install_setuptools()
sys.exit(1)
from distutils.core import setup
params = {}
if sys.version_info[:2] > (2, 4):
params['requires'] = ['pyasn1(>=0.2.3)', 'pysmi', 'pycryptodomex']
doclines = [x.strip() for x in (__doc__ or '').split('\n') if x]
if sys.version_info[:2] > (2, 4):
params['requires'] = [
re.sub(r'(.*?)([<>=!~]+)(.*)', r'\g<1>\g<2>(\g<3>)', r) for r in requires
]
doclines = [x.strip() for x in (__doc__ or '').split('\n')]
params.update({
'name': 'pysnmp',
'version': open(os.path.join('pysnmp', '__init__.py')).read().split('\'')[1],
'description': doclines[0],
'long_description': ' '.join(doclines[1:]),
'long_description': '\n'.join(doclines[1:]),
'maintainer': 'Ilya Etingof <etingof@gmail.com>',
'author': 'Ilya Etingof',
'author_email': 'etingof@gmail.com',

5
tox.ini 100644
View File

@ -0,0 +1,5 @@
[envlist]
envlist = py{26,27,33,34,35,36,37}
[testenv]
commands = {toxinidir}/runtests.sh {envpython}