summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/source/examples/contents.rst101
-rw-r--r--docs/source/faq/getting-peer-information.rst32
-rw-r--r--docs/source/faq/how-to-implement-agent-mib.rst120
-rw-r--r--docs/source/faq/ignored-snmp-packets.rst89
-rw-r--r--docs/source/faq/listening-on-multiple-interfaces.rst36
-rw-r--r--docs/source/faq/non-printable-snmp-values-apps.rst40
-rw-r--r--docs/source/faq/non-printable-snmp-values-tools.rst44
-rw-r--r--docs/source/faq/oids-not-increasing.rst29
-rw-r--r--docs/source/faq/pass-custom-mib-to-manager.rst70
-rw-r--r--docs/source/faq/py2exe-throws-error.rst45
-rw-r--r--docs/source/faq/response-values-mib-resolution.rst50
-rw-r--r--docs/source/faq/snmp-data-constraints-verification-failure.rst40
-rw-r--r--docs/source/faq/walk-whole-mib.rst26
-rw-r--r--examples/v1arch/asyncore/agent/ntforg/inform-v2c.py83
14 files changed, 805 insertions, 0 deletions
diff --git a/docs/source/examples/contents.rst b/docs/source/examples/contents.rst
new file mode 100644
index 0000000..8257a32
--- /dev/null
+++ b/docs/source/examples/contents.rst
@@ -0,0 +1,101 @@
+
+Examples scripts
+================
+
+.. toctree::
+ :maxdepth: 2
+
+SNMP is not really simple (PySNMP implementation takes over 15K lines of
+Python code), but PySNMP tries to isolate the complexities and let you
+perform typical SNMP operations in a quick and intuitive way.
+
+PySNMP offers three groups of programming interfaces to deal with
+SNMP protocol. In the order from most consice to most detailed those
+APIs are:
+
+#. High-level API
+
+ .. toctree::
+ :maxdepth: 2
+
+ /examples/v3arch/asyncore/oneliner/contents
+
+#. Complete implementation of all official Standard SNMP Applications. It
+ should let you implement any SNMP operation defined in the standard.
+
+ This API comes in several transport varieties.
+
+ #. Most mature and stable transport implementation is based on Python's
+ bult-in asyncore module. So this API is called Native or Asyncore API.
+
+ .. toctree::
+ :maxdepth: 2
+
+ /examples/v3arch/asyncore/contents
+
+ #. Modern, co-routines based API takes shape of asyncio bindings
+ (Python 3.3+) or Trollius bindings (Python 2.6-3.4)
+
+ .. toctree::
+ :maxdepth: 2
+
+ /examples/v3arch/asyncio/contents
+ /examples/v3arch/trollius/contents
+
+ #. Slightly aged, Twisted-based based API.
+
+ .. toctree::
+ :maxdepth: 2
+
+ /examples/v3arch/twisted/contents
+
+#. Packet-level API that lets you build SNMP messages from Python
+ objects and exchange them through asyncore transport (or you could
+ write your own). These interfaces are very low-level and aimed at
+ a rather specific programming tasks.
+
+ .. toctree::
+ :maxdepth: 2
+
+ /examples/v1arch/asyncore/contents
+
+Before doing cut&paste of the code below into your Python interpreter,
+make sure to install pysnmp and its dependencies by running pip or
+easy_install: ::
+
+ # pip pysnmp
+
+There's a public SNMP responder configured at *demo.snmplabs.com:161* to
+let you run PySNMP examples scripts in a cut&paste fashion. If you
+wish to use your own SNMP Agent with these scripts, make sure to either
+configure your local snmpd and/or snmptrapd or use a valid address and
+SNMP credentials of your SNMP Agent in the examples to let them work.
+
+If you find your PySNMP application behaving unexpectedly, try to enable
+a /more or less verbose/ built-in PySNMP debugging by adding the
+following snippet of code at the beginning of your application:
+
+.. code-block:: python
+
+ from pysnmp import debug
+
+ # use specific flags or 'all' for full debugging
+ debug.setLogger(debug.Debug('dsp', 'msgproc', 'secmode'))
+
+Then run your app and watch stderr. The Debug initializer enables debugging
+for a particular PySNMP subsystem, 'all' enables full debugging. More
+specific flags are:
+
+* io
+* dsp
+* msgproc
+* secmod
+* mibbuild
+* mibview
+* mibinstrum
+* acl
+* proxy
+* app
+
+For more details on PySNMP programming model and interfaces, please
+refer to the documentation.
diff --git a/docs/source/faq/getting-peer-information.rst b/docs/source/faq/getting-peer-information.rst
new file mode 100644
index 0000000..cf78802
--- /dev/null
+++ b/docs/source/faq/getting-peer-information.rst
@@ -0,0 +1,32 @@
+
+Getting peer address information
+--------------------------------
+
+Q. How do I find out peer transport address or security information within
+ my receiving app (CommandResponder or Notification Receiver)?
+
+A. SNMP architecture forces you to distinguish communicating entities only
+ on the basis of their community names (SNMPv1/v2c) or
+ ContextEngineId/ContextName pair (SNMPv3).
+
+ In other words, if one SNMP Manager should anyhow differ from another,
+ then they should use distinct community names or SNMP contexts.
+ Transport information should never be used for the identification purposes,
+ as in some cases it proves to be unreliable (cases include NAT device or
+ a proxy in the middle, not to mention address spoofing).
+
+ As practice reveals, even perfect design does not always cope well with
+ the imperfect world. So we had to pinch a logic hole from the scope of an
+ SNMP app down to transport layer. Now with the
+ getTransportInfo(stateReference) method call you could get peer transport
+ information upon receiving its SNMP message.
+
+.. code-block:: python
+
+ # Callback function for receiving notifications
+ def cbFun(snmpEngine,
+ stateReference,
+ contextEngineId, contextName,
+ varBinds,
+ cbCtx):
+ transportDomain, transportAddress = snmpEngine.msgAndPduDsp.getTransportInfo(stateReference)
diff --git a/docs/source/faq/how-to-implement-agent-mib.rst b/docs/source/faq/how-to-implement-agent-mib.rst
new file mode 100644
index 0000000..6d2bbb9
--- /dev/null
+++ b/docs/source/faq/how-to-implement-agent-mib.rst
@@ -0,0 +1,120 @@
+
+How to implement MIB at the Agent
+---------------------------------
+
+Q. How to instantiate static MIB table at my SNMP Agent?
+
+A. You need to create MibScalarInstance class instances and register
+ them with your Agent's SNMP engine (mibBuilder, more specifically).
+ Here's an example code for a IP-MIB table:
+
+.. code-block:: python
+
+ # SNMP Agent (AKA CommandResponder) is built around SNMP engine object
+ snmpEngine = engine.SnmpEngine()
+
+ # Import table columns
+ ( ipAddressAddrType,
+ ipAddressAddr,
+ ipAddressIfIndex,
+ ipAddressType,
+ ipAddressPrefix,
+ ipAddressOrigin,
+ ipAddressStatus,
+ ipAddressCreated,
+ ipAddressLastChanged,
+ ipAddressRowStatus,
+ ipAddressStorageType ) = snmpEngine.msgAndPduDsp.mibInstrumController
+ .mibBuilder.importSymbols(
+ 'IP-MIB',
+ 'ipAddressAddrType',
+ 'ipAddressAddr',
+ 'ipAddressIfIndex',
+ 'ipAddressType',
+ 'ipAddressPrefix',
+ 'ipAddressOrigin',
+ 'ipAddressStatus',
+ 'ipAddressCreated',
+ 'ipAddressLastChanged',
+ 'ipAddressRowStatus',
+ 'ipAddressStorageType'
+ )
+
+ # Import MibScalarInstance
+
+ MibScalarInstance, = snmpEngine.msgAndPduDsp.mibInstrumController.
+ mibBuilder.importSymbols('SNMPv2-SMI', 'MibScalarInstance')
+
+ # Create table columns instances
+
+ _ipAddressAddrType = MibScalarInstance(
+ ipAddressAddrType.name, (1, 4, 1, 2, 3, 4),
+ ipAddressAddrType.syntax.clone(1)
+ )
+ _ipAddressAddr = MibScalarInstance(
+ ipAddressAddr.name, (1, 4, 1, 2, 3, 4),
+ ipAddressAddr.syntax.clone('1.2.3.4')
+ )
+ _ipAddressIfIndex = MibScalarInstance(
+ ipAddressIfIndex.name, (1, 4, 1, 2, 3, 4),
+ ipAddressIfIndex.syntax.clone(1)
+ )
+ _ipAddressType = MibScalarInstance(
+ ipAddressType.name, (1, 4, 1, 2, 3, 4),
+ ipAddressType.syntax.clone(1)
+ )
+ _ipAddressPrefix = MibScalarInstance(
+ ipAddressPrefix.name, (1, 4, 1, 2, 3, 4),
+ ipAddressPrefix.syntax.clone((0,0))
+ )
+ _ipAddressOrigin = MibScalarInstance(
+ ipAddressOrigin.name, (1, 4, 1, 2, 3, 4),
+ ipAddressOrigin.syntax.clone(1)
+ )
+ _ipAddressStatus = MibScalarInstance(
+ ipAddressStatus.name, (1, 4, 1, 2, 3, 4),
+ ipAddressStatus.syntax.clone(1)
+ )
+ _ipAddressCreated = MibScalarInstance(
+ ipAddressCreated.name, (1, 4, 1, 2, 3, 4),
+ ipAddressCreated.syntax.clone(800)
+ )
+ _ipAddressLastChanged = MibScalarInstance(
+ ipAddressLastChanged.name, (1, 4, 1, 2, 3, 4),
+ ipAddressLastChanged.syntax.clone(600)
+ )
+ _ipAddressRowStatus = MibScalarInstance(
+ ipAddressRowStatus.name, (1, 4, 1, 2, 3, 4),
+ ipAddressRowStatus.syntax.clone(1)
+ )
+ _ipAddressStorageType = MibScalarInstance(
+ ipAddressStorageType.name, (1, 4, 1, 2, 3, 4),
+ ipAddressStorageType.syntax
+ )
+
+ # add anonymous column instances
+ snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.exportSymbols(
+ '_IP-MIB',
+ _ipAddressAddrType,
+ _ipAddressAddr,
+ _ipAddressIfIndex,
+ _ipAddressType,
+ _ipAddressPrefix,
+ _ipAddressOrigin,
+ _ipAddressStatus,
+ _ipAddressCreated,
+ _ipAddressLastChanged,
+ _ipAddressRowStatus,
+ _ipAddressStorageType
+ )
+
+ # Command responder code would follow...
+
+ Keep in mind that the values of this table row will not change by
+ themselves. They basically hold a snapshot of a data set so your
+ application may have to update them somehow. For example, an app could
+ periodically lookup particular MibScalarInstance by OID at mibBuilder and
+ update its "syntax" attribute with a new value.
+
+ There are other ways for building MIB tables that represent dynamic
+ Managed Objects.
diff --git a/docs/source/faq/ignored-snmp-packets.rst b/docs/source/faq/ignored-snmp-packets.rst
new file mode 100644
index 0000000..d8eca45
--- /dev/null
+++ b/docs/source/faq/ignored-snmp-packets.rst
@@ -0,0 +1,89 @@
+
+Ignored SNMP packets
+--------------------
+
+Q. Some network devices do not respond to PySNMP-based management
+ requests for particular OIDs.
+
+.. code-block:: bash
+
+ $ pysnmpget -v2c -c public 10.0.0.33 1.3.6.1.2.1.2.2.1.10.3
+ SNMPv2-SMI::mib-2.2.2.1.10.3 = Counter32: 1519568842
+ $ snmpget.py -v2c -c public 10.0.0.33 1.3.6.1.2.1.2.2.1.10.4
+ requestTimedOut
+
+ Meanwhile, tcpcump shows request-response sequence:
+
+.. code-block:: bash
+
+ 13:33:30.161843 IP 10.0.0.33.snmp > 10.0.0.1.51094:
+ GetResponse(31) interfaces.ifTable.ifEntry.ifInOctets.3=1532504859
+ 13:33:30.161881 IP 10.0.0.33.snmp > 10.0.0.1.51094:
+ GetResponse(31) interfaces.ifTable.ifEntry.ifInOctets.3=1532504859
+
+ In some cases, particularily when running v1arch PySNMP code, the
+ following exception may be thrown on response processing:
+
+.. code-block:: python
+
+ Traceback (most recent call last):
+ ....
+ File "build/bdist.linux-i686/egg/pyasn1/type/base.py", line 64, in
+ __init__
+ File "build/bdist.linux-i686/egg/pyasn1/type/base.py", line 32, in _verifySubtypeSpec
+ File "build/bdist.linux-i686/egg/pyasn1/type/constraint.py", line 33, in __call__
+ pyasn1.type.error.ValueConstraintError: ConstraintsIntersection(ConstraintsIntersection(), ValueRangeConstraint(0, 4294967295)) failed at: ValueRangeConstraint(0, 4294967295) failed at: -1413698940
+
+A. This appears to be a [widespread] bug in BER integer encoders. It usually
+ gets noticed on Counter values as they are constrained to be positive while
+ wrong encoding yelds them negative.
+
+ Here's broken encoding:
+
+.. code-block:: python
+
+ >>> decoder.decode('A\x04\xab\xbc\xaa\x84', asn1Spec=rfc1155.Counter())
+ Traceback (most recent call last):
+ ...
+ pyasn1.type.error.ValueConstraintError: ConstraintsIntersection(ConstraintsIntersection(), ValueRangeConstraint(0, 4294967295)) failed at: ValueRangeConstraint(0, 4294967295) failed at: -1413698940
+
+And here's a good one:
+
+.. code-block:: python
+
+ >>> decoder.decode('A\x05\x00\xab\xbc\xaa\x84',
+ >>> asn1Spec=rfc1155.Counter())
+ (Counter('2881268356'), '')
+
+ Notice the third octet -- positive values must have its highest bit set
+ to zero.
+
+ Here's an example hack that converts negated values into their positive
+ complimentaries for Counter type.
+
+.. code-block:: python
+
+ from pysnmp.proto import rfc1155, rfc1902, api
+ from pyasn1.codec.ber import encoder, decoder
+
+ # --- hack Counter type
+
+ def counterCloneHack(self, *args):
+ if args and args[0] < 0:
+ args = (0xffffffff+args[0]-1,) + args[1:]
+
+ return self.__class__(*args)
+
+ rfc1155.Counter.clone = counterCloneHack
+ rfc1902.Counter32.clone = counterCloneHack
+
+ Execute this hack before any SNMP message processing occures in your app.
+
+ The bad news is that if this BER encoding bug also affects Integer values,
+ in that case it is theoretically impossible to fix because, unlike Counter,
+ Integer values may legally be negative so they could not unconditionally be
+ converted into positives.
+
+ Therefore the best solutoin would be to get vendors fixing their
+ BER encoders.
+
diff --git a/docs/source/faq/listening-on-multiple-interfaces.rst b/docs/source/faq/listening-on-multiple-interfaces.rst
new file mode 100644
index 0000000..71cc644
--- /dev/null
+++ b/docs/source/faq/listening-on-multiple-interfaces.rst
@@ -0,0 +1,36 @@
+
+Listening on multiple network interfaces
+----------------------------------------
+
+Q. I need my receiving entity (CommandResponder or Notification Receiver)
+ to listen for SNMP messages on multiple network interfaces. How do
+ I do that with pysnmp?
+
+A. Simply register multiple network transports with your SNMP engine.
+ Each transport would be bound to an individual local transport
+ endpoint (for instance, IP address & UDP port pair).
+
+.. code-block:: python
+
+ # Security setup would follow
+ ...
+ # Setup first transport endpoint
+ config.addSocketTransport(
+ snmpEngine,
+ udp.domainName + (1,),
+ udp.UdpSocketTransport().openServerMode(('127.0.0.1', 162))
+ )
+
+ # Setup second transport endpoint
+ config.addSocketTransport(
+ snmpEngine,
+ udp.domainName + (2,),
+ udp.UdpSocketTransport().openServerMode(('192.168.1.1', 162))
+ )
+ # Receiver callback function implementation and Dispatcher invocation
+ # would follow
+ ...
+
+ Notice extended transport domain specification (udp.domainName) in
+ the code above. There we register each transport endpoint under distinct
+ OID, however always within the canonical transport domain OID.
diff --git a/docs/source/faq/non-printable-snmp-values-apps.rst b/docs/source/faq/non-printable-snmp-values-apps.rst
new file mode 100644
index 0000000..cee5166
--- /dev/null
+++ b/docs/source/faq/non-printable-snmp-values-apps.rst
@@ -0,0 +1,40 @@
+
+Garbaged SNMP values (apps)
+---------------------------
+
+Q. When my PySNMP application prints out fetched values, some of them
+ come out as a garbage on my screan. Here's my code:
+
+.. code-block:: python
+
+ for varBind in varBinds:
+ print(' = '.join([ str(x) for x in varBind ])
+
+ and the result is:
+
+.. code-block:: python
+
+ 1.3.6.1.4.1.161.19.3.2.1.63.0 = 50000
+ 1.3.6.1.4.1.161.19.3.2.1.4.0 = '\x01\x02\x03\x04'
+
+ The IpAddress type seems to be the only one with this problem.
+
+A. Always use prettyPrint() method for all pyasn1-based objects -- it
+ automatically converts ASN1 types to human-friendly form.
+
+.. code-block:: python
+
+ > > > from pysnmp.proto import rfc1902
+ > > > a = rfc1902.IpAddress('1.2.3.4')
+ > > > str(a)
+ '\x01\x02\x03\x04'
+ > > > a
+ IpAddress('1.2.3.4')
+ > > > a.prettyPrint()
+ '1.2.3.4'
+ > > > rfc1902.IpAddress.prettyPrint(a)
+ '1.2.3.4'
+
+ See `pyasn1 tutorial <http://pyasn1.sourceforge.net/>`_ for more information
+ on pyasn1 data model.
+
diff --git a/docs/source/faq/non-printable-snmp-values-tools.rst b/docs/source/faq/non-printable-snmp-values-tools.rst
new file mode 100644
index 0000000..89671e2
--- /dev/null
+++ b/docs/source/faq/non-printable-snmp-values-tools.rst
@@ -0,0 +1,44 @@
+
+Garbaged SNMP values (tools)
+----------------------------
+
+Q. When fetching data with snmp*.py command-line tools, some values
+ do not print out nicely:
+
+.. code-block:: bash
+
+ $ snmpget.py -v2c -c public 127.0.0.1 .1.3.6.1.4.1.14988.1.1.1.2.1.1.0.23.183.34.8.200.3
+ SNMPv2-SMI::enterprises.14988.1.1.1.2.1.1.0.23.183.34.8.200.3 =
+ OctetString: ˇČ
+
+ where Net-SNMP gives nicely formatted human-readable string:
+
+.. code-block:: bash
+
+ $ snmpget -v2c -c public 127.0.0.1 .1.3.6.1.4.1.14988.1.1.1.2.1.1.0.23.183.34.8.200.3
+ SNMPv2-SMI::enterprises.14988.1.1.1.2.1.1.0.23.183.34.8.200.3 =
+ Hex-STRING: 00 17 B7 22 08 C8
+
+ What can be done to PySNMP to make it returning HEX data in human-readable?
+
+A. The difference is that Net-SNMP prints values into hex by-default,
+ whereas pysnmp does not do that. You can force snmpget.py to work
+ similarily with the -OT command line parameter.
+
+.. code-block:: bash
+
+ $ snmpget.py -OT -v2c -c public 127.0.0.1 .1.3.6.1.4.1.14988.1.1.1.2.1.1.0.23.
+ 183.34.8.200.3
+ SNMPv2-SMI::enterprises.14988.1.1.1.2.1.1.0.23.183.34.8.200.3 =
+ OctetString: 00 17 b7 22 08 c8
+
+ Another matter is MIB lookup - when snmp*.py tool can use a MIB to figure
+ out what are the display conventions for particular value type, it will
+ reformat the value in a human-readable form.
+
+ To let MIB lookup work, please pass appropriate MIB name to snmp*.py
+ tool through command line:
+
+.. code-block:: bash
+
+ $ snmpwalk.py -m IP-MIB,IF-MIB -v2c -c public 127.0.0.1 .1.3.6.1.4.1
diff --git a/docs/source/faq/oids-not-increasing.rst b/docs/source/faq/oids-not-increasing.rst
new file mode 100644
index 0000000..681fd05
--- /dev/null
+++ b/docs/source/faq/oids-not-increasing.rst
@@ -0,0 +1,29 @@
+
+Dealing with OIDs not increasing error
+--------------------------------------
+
+Q. I'm walking a particular Agent with the CommandGenerator.nextCmd()
+ and CommandGenerator.bulkCmd() methods. It works for some OIDs, but
+ invariably fails at certain OID with the 'OIDs are not increasing'
+ diagnostics. What does it mean and how do I fix that?
+
+A. The Agent you are talking to seems to be broken. The 'OIDs are not
+ increasing' message means that in the course of fetching OIDs from Agent,
+ Manager receives an OID that is not greater than those used in request.
+ Due to the nature of GETNEXT/GETBULK algorithm, passing the same or
+ lesser OID to Manager would result in fetching the same set of OIDs over
+ and over again effectively creating an infinite loop between Manager
+ and Agent so they may never reach the end of MIB. So Manager tries
+ to intervene and prevent loop from happenning.
+
+ If have to work with a broken Agent and prepared some other mean
+ for stopping GETNEXT/GETBULK app at some point, you could set the
+ ignoreNonIncreasingOid option at CommandGenerator class instance
+ to disable OID verification on Manager side.
+
+.. code-block:: python
+
+ cmdGen = cmdgen.CommandGenerator()
+ cmdGen.ignoreNonIncreasingOid = True
+ errorIndication, errorStatus, errorIndex, varBindTable = cmdGen.bulkCmd(...)
+
diff --git a/docs/source/faq/pass-custom-mib-to-manager.rst b/docs/source/faq/pass-custom-mib-to-manager.rst
new file mode 100644
index 0000000..af2d5c0
--- /dev/null
+++ b/docs/source/faq/pass-custom-mib-to-manager.rst
@@ -0,0 +1,70 @@
+
+How to pass custom MIB to the Manager
+-------------------------------------
+
+Q. How to make use of my own MIBs at my Manager application?
+
+A. First you have to convert your plain-text MIB files into
+ pysnmp-compliant Python modules using libsmi2pysnmp tool.
+
+ Once you have your own pysnmp MIB files at hand, you'd have to put them
+ somewhere on the filesystem (possibly bundling them with your application).
+ In order to let pysnmp engine locating and using these modules, pysnmp
+ MIB search path has to be modified.
+
+.. code-block:: python
+
+ from pysnmp.entity.rfc3413.oneliner import cmdgen
+ from pysnmp.smi import builder
+
+ cmdGen = cmdgen.CommandGenerator()
+
+ mibBuilder = cmdGen.snmpEngine.msgAndPduDsp.mibInstrumController
+ .mibBuilder
+
+ mibSources = mibBuilder.getMibSources() + (
+ builder.DirMibSource('/opt/my_pysnmp_mibs'),
+ )
+
+ mibBuilder.setMibSources(*mibSources)
+
+ # Rest of CommandGenerator app would follow
+
+ The same effect could be achieved by exporting the PYSNMP_MIB_DIRS variable
+ to process environment. Individual directories should be separated with
+ semicolons.
+
+ In case you'd like to .egg your application or just the pysnmp MIB
+ modules, the following code would work.
+
+.. code-block:: python
+
+ from pysnmp.entity.rfc3413.oneliner import cmdgen
+ from pysnmp.smi import builder
+
+ cmdGen = cmdgen.CommandGenerator()
+
+ mibBuilder = cmdGen.snmpEngine.msgAndPduDsp.mibInstrumController
+ .mibBuilder
+
+ mibSources = mibBuilder.getMibSources() + (
+ builder.ZipMibSource('my_pysnmp_mibs_pkg.mibs'),
+ )
+
+ mibBuilder.setMibSources(*mibSources)
+
+ # Rest of CommandGenerator app would follow
+
+ The PYSNMP_MIB_PKGS environment variable holding semicolon-separated
+ list of modules could also be used for the same purpose.
+
+ Please, note, that Python should be able to import the [.egg] package
+ holding your MIB modules (my_pysnmp_mibs_pkg in the example above).
+ That requires either putting your module into site-packages or modifying
+ Python search math (PYTHONPATH variable).
+
+ Then in your application you could refer to your MIB by its name (when
+ resolving symbolic names to OIDs) or import MIB explicitly (with
+ mibBuilder.loadModules()) so that you could resolve OIDs to symbolic
+ names (as well as other MIB information).
+
diff --git a/docs/source/faq/py2exe-throws-error.rst b/docs/source/faq/py2exe-throws-error.rst
new file mode 100644
index 0000000..7f65620
--- /dev/null
+++ b/docs/source/faq/py2exe-throws-error.rst
@@ -0,0 +1,45 @@
+
+My py2exe app can't find MIBs
+-----------------------------
+
+Q. I packed my pysnmp-based application with py2exe. When I run my app,
+ it throws a traceback like this:
+
+.. code-block:: bash
+
+File "pysnmp\entity\rfc3413\oneliner\cmdgen.pyc", line 116, in __init__
+File "pysnmp\entity\engine.pyc", line 16, in __init__
+File "pysnmp\proto\rfc3412.pyc", line 16, in __init__
+File "pysnmp\smi\builder.pyc", line 143, in __init__
+File "pysnmp\smi\builder.pyc", line 35, in init
+File "pysnmp\smi\builder.pyc", line 80, in _init
+ImportError: No module named mibs.instances
+
+ PySNMP claims itself to be py2exe-friendly. How to make it working?
+
+A. You have to list pysnmp MIB directories explicitly at your app's
+ setup.py so that py2exe would include them into the binary.
+
+.. code-block:: python
+
+ from distutils.core import setup
+ import sys
+
+ options = {}
+
+ if "py2exe" in sys.argv:
+ import py2exe
+ # fix executables
+ options['console'] = ['myapp.py']
+ # add files not found my modulefinder
+ options['options'] = {
+ 'py2exe': {
+ 'includes': [
+ 'pysnmp.smi.mibs.*',
+ 'pysnmp.smi.mibs.instances.*'
+ ]
+ }
+ }
+
+ setup(**options)
+
diff --git a/docs/source/faq/response-values-mib-resolution.rst b/docs/source/faq/response-values-mib-resolution.rst
new file mode 100644
index 0000000..6863319
--- /dev/null
+++ b/docs/source/faq/response-values-mib-resolution.rst
@@ -0,0 +1,50 @@
+
+Resolve response values at MIB
+------------------------------
+
+Q. My CommandGenerator app reports OIDs and values in form of PyASN1
+ objects. How do I convert them into human-readable, symbolic names
+ and values?
+
+A. The most easy to use interface to MIB lookup feature is supported by
+ PySNMP 4.2.3 and later. Just pass the
+
+.. code-block:: python
+
+ lookupNames=True, lookupValues=True
+
+ parameters to getCmd(), setCmd(), nextCmd(), bulkCmd() methods of
+ oneliner CommandGenerator. Then the OIDs in response variable-binding
+ list will get replaced by similarily looking MibVariable instances,
+ their prettyPrint() methods return MIB symbols instead of OIDs.
+
+ Response values will still be PyASN1 objects but some may be replaced
+ by TEXTUAL-CONVENTION decorators what make their prettyPrint() methods
+ returning even more human-friendly output.
+
+.. code-block:: python
+
+ >>> from pysnmp.entity.rfc3413.oneliner import cmdgen
+ >>>
+ >>> cmdGen = cmdgen.CommandGenerator()
+ >>>
+ >>> errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd(
+ ... cmdgen.CommunityData('public'),
+ ... cmdgen.UdpTransportTarget(('localhost', 161)),
+ ... '1.3.6.1.2.1.1.1.0',
+ ... lookupNames=True, lookupValues=True
+ ... )
+ >>>
+ >>> name, value = varBinds[0]
+ >>> name
+ MibVariable(ObjectName(1.3.6.1.2.1.1.1.0))
+ >>> value
+ DisplayString('Linux saturn 2.6.38.1 Sat Apr 9 23:39:07 CDT 2012 i686')
+ >>> name.prettyPrint()
+ 'SNMPv2-MIB::sysDescr."0"'
+ >>> value.prettyPrint()
+ 'Linux cray 2.6.37.6-smp #2 SMP Sat Apr 9 23:39:07 CDT 2011 i686'
+ >>>
+
+ If you are using older PySNMP versions it's strongly recommended to
+ upgrade to the latest one.
diff --git a/docs/source/faq/snmp-data-constraints-verification-failure.rst b/docs/source/faq/snmp-data-constraints-verification-failure.rst
new file mode 100644
index 0000000..f489b40
--- /dev/null
+++ b/docs/source/faq/snmp-data-constraints-verification-failure.rst
@@ -0,0 +1,40 @@
+
+SNMP data constraints verification error
+----------------------------------------
+
+Q. Will PySNMP Manager verify the values it sends to and receives from
+ a distant Agent against local MIB constraints?
+
+A. Yes, it can do that. The Manager will verify the values you pass to SET
+ request against a MIB if:
+
+ The values are not already PyASN1 objects but some basic Python types
+ (like integer or string). You tell PySNMP engine to load appropriate
+ MIB where it could lookup the constraints (via the use of MibVariable)
+ So, the following code fragment makes PySNMP engine loading SNMPv2-MIB
+ and verifying that the 'new system name' value satisfies sysName
+ constraints (if any).
+
+.. code-block:: python
+
+ errorIndication, errorStatus, errorIndex, varBinds = cmdGen.setCmd(
+ cmdgen.CommunityData('public'),
+ cmdgen.UdpTransportTarget(('localhost', 161)),
+ ( cmdgen.MibVariable('SNMPv2-MIB', 'sysName', 0), 'new system name' )
+ )
+
+ To verify the response values, you should pass at least lookupValues flag
+ to CommandGenerator *cmd() method you use. In the following example
+ PySNMP will make sure that Agent-supplied value for SNMPv2-MIB::sysName
+ Managed Object satisfies MIB constraints (if any).
+
+.. code-block:: python
+
+ errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd(
+ cmdgen.CommunityData('public'),
+ cmdgen.UdpTransportTarget(('localhost', 161)),
+ cmdgen.MibVariable('SNMPv2-MIB', 'sysName', 0),
+ lookupValues=True
+ )
+
+ In case of constraint violation, a PySNMP exception will be raised.
diff --git a/docs/source/faq/walk-whole-mib.rst b/docs/source/faq/walk-whole-mib.rst
new file mode 100644
index 0000000..5682746
--- /dev/null
+++ b/docs/source/faq/walk-whole-mib.rst
@@ -0,0 +1,26 @@
+
+Walking whole MIB
+-----------------
+
+Q. The nextCmd() and bulkCmd() methods of CommandGenerator app
+ (oneliner version) stop working once returned OIDs went out of scope of
+ request OIDs.
+
+ In other words, if I request 1.3.6.1, I would get everything under
+ the 1.3.6.1 prefix, but not 1.3.6.2. Is there any way to make it walking
+ the whole MIB?
+
+A. Yes, just pass the lexicographicMode=True parameter to CommandGenerator
+ nextCmd() and bulkCmd() methods (introduced in PySNMP 4.2.3+) or set
+ CommandGenerator.lexicographicMode=True option before calling nextCmd()
+ and bulkCmd() methods.
+
+.. code-block:: python
+
+ cmdGen = cmdgen.CommandGenerator()
+ errorIndication, errorStatus, errorIndex, varBindTable = cmdGen.bulkCmd(
+ ....,
+ ....,
+ ....,
+ lexicographicMode=True
+ )
diff --git a/examples/v1arch/asyncore/agent/ntforg/inform-v2c.py b/examples/v1arch/asyncore/agent/ntforg/inform-v2c.py
new file mode 100644
index 0000000..4fd7aea
--- /dev/null
+++ b/examples/v1arch/asyncore/agent/ntforg/inform-v2c.py
@@ -0,0 +1,83 @@
+"""
+INFORM over multiple transports
++++++++++++++++++++++++++++++++
+
+The following script sends SNMP INFORM notification using the following options:
+
+* with SNMPv2c
+* with community name 'public'
+* over IPv4/UDP and IPv6/UDP
+* send INFORM notification
+* to a Manager at 127.0.0.1:162 and [::1]:162
+* with TRAP ID 'coldStart' specified as an OID
+
+The following Net-SNMP command will produce similar SNMP notification:
+
+| $ snmpinform -v2c -c public udp:127.0.0.1 0 1.3.6.1.6.3.1.1.5.1
+| $ snmpinform -v2c -c public udp6:[::1] 0 1.3.6.1.6.3.1.1.5.1
+
+"""#
+from pysnmp.carrier.asynsock.dispatch import AsynsockDispatcher
+from pysnmp.carrier.asynsock.dgram import udp, udp6
+from pyasn1.codec.ber import encoder
+from pysnmp.proto.api import v2c as pMod
+
+# Build PDU
+reqPDU = pMod.InformRequestPDU()
+pMod.apiTrapPDU.setDefaults(reqPDU)
+
+# Build message
+trapMsg = pMod.Message()
+pMod.apiMessage.setDefaults(trapMsg)
+pMod.apiMessage.setCommunity(trapMsg, 'public')
+pMod.apiMessage.setPDU(trapMsg, 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:
+ print('INFORM message delivered, response var-binds follow')
+ for oid, val in pMod.apiPDU.getVarBinds(rspPDU):
+ print('%s = %s' % (oid.prettyPrint(), val.prettyPrint()))
+ transportDispatcher.jobFinished(1)
+ return wholeMsg
+
+transportDispatcher = AsynsockDispatcher()
+
+transportDispatcher.registerRecvCbFun(cbRecvFun)
+transportDispatcher.registerTimerCbFun(cbTimerFun)
+
+# 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)
+)
+
+# Dispatcher will finish as all scheduled messages are sent
+transportDispatcher.runDispatcher()
+
+transportDispatcher.closeDispatcher()