1#
2# This file is part of pysnmp software.
3#
4# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
5# License: http://snmplabs.com/pysnmp/license.html
6#
7from pysnmp.entity.rfc3413 import cmdgen
8from pysnmp.smi.rfc1902 import *
9from pysnmp.hlapi.auth import *
10from pysnmp.hlapi.context import *
11from pysnmp.hlapi.lcd import *
12from pysnmp.hlapi.varbinds import *
13from pysnmp.hlapi.asyncore.transport import *
14
15__all__ = ['getCmd', 'nextCmd', 'setCmd', 'bulkCmd', 'isEndOfMib']
16
17vbProcessor = CommandGeneratorVarBinds()
18lcd = CommandGeneratorLcdConfigurator()
19
20isEndOfMib = lambda x: not cmdgen.getNextVarBinds(x)[1]
21
22
23def getCmd(snmpEngine, authData, transportTarget, contextData,
24           *varBinds, **options):
25    """Performs SNMP GET query.
26
27    Based on passed parameters, prepares SNMP GET packet
28    (:RFC:`1905#section-4.2.1`) and schedules its transmission by
29    I/O framework at a later point of time.
30
31    Parameters
32    ----------
33    snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine`
34        Class instance representing SNMP engine.
35
36    authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData`
37        Class instance representing SNMP credentials.
38
39    transportTarget : :py:class:`~pysnmp.hlapi.asyncore.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncore.Udp6TransportTarget`
40        Class instance representing transport type along with SNMP peer
41        address.
42
43    contextData : :py:class:`~pysnmp.hlapi.ContextData`
44        Class instance representing SNMP ContextEngineId and ContextName
45        values.
46
47    \*varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType`
48        One or more class instances representing MIB variables to place
49        into SNMP request.
50
51    Other Parameters
52    ----------------
53    \*\*options :
54        Request options:
55
56            * `lookupMib` - load MIB and resolve response MIB variables at
57              the cost of slightly reduced performance. Default is `True`.
58            * `cbFun` (callable) - user-supplied callable that is invoked
59               to pass SNMP response data or error to user at a later point
60               of time. Default is `None`.
61            * `cbCtx` (object) - user-supplied object passing additional
62               parameters to/from `cbFun`. Default is `None`.
63
64    Notes
65    -----
66    User-supplied `cbFun` callable must have the following call
67    signature:
68
69    * snmpEngine (:py:class:`~pysnmp.hlapi.SnmpEngine`):
70      Class instance representing SNMP engine.
71    * sendRequestHandle (int): Unique request identifier. Can be used
72      for matching multiple ongoing requests with received responses.
73    * errorIndication (str): True value indicates SNMP engine error.
74    * errorStatus (str): True value indicates SNMP PDU error.
75    * errorIndex (int): Non-zero value refers to `varBinds[errorIndex-1]`
76    * varBinds (tuple): A sequence of
77      :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances
78      representing MIB variables returned in SNMP response in exactly
79      the same order as `varBinds` in request.
80    * `cbCtx` : Original user-supplied object.
81
82    Returns
83    -------
84    sendRequestHandle : int
85        Unique request identifier. Can be used for matching received
86        responses with ongoing requests.
87
88    Raises
89    ------
90    PySnmpError
91        Or its derivative indicating that an error occurred while
92        performing SNMP operation.
93
94    Examples
95    --------
96    >>> from pysnmp.hlapi.asyncore import *
97    >>> def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx):
98    ...     print(errorIndication, errorStatus, errorIndex, varBinds)
99    >>>
100    >>> snmpEngine = SnmpEngine()
101    >>> getCmd(snmpEngine,
102    ...        CommunityData('public'),
103    ...        UdpTransportTarget(('demo.snmplabs.com', 161)),
104    ...        ContextData(),
105    ...        ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)),
106    ...        cbFun=cbFun)
107    >>> snmpEngine.transportDispatcher.runDispatcher()
108    (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))])
109    >>>
110
111    """
112
113    def __cbFun(snmpEngine, sendRequestHandle,
114                errorIndication, errorStatus, errorIndex,
115                varBinds, cbCtx):
116        lookupMib, cbFun, cbCtx = cbCtx
117        if cbFun:
118            return cbFun(snmpEngine, sendRequestHandle, errorIndication,
119                         errorStatus, errorIndex,
120                         vbProcessor.unmakeVarBinds(
121                             snmpEngine, varBinds, lookupMib
122                         ), cbCtx)
123
124    addrName, paramsName = lcd.configure(
125        snmpEngine, authData, transportTarget, contextData.contextName)
126
127    return cmdgen.GetCommandGenerator().sendVarBinds(
128        snmpEngine, addrName, contextData.contextEngineId,
129        contextData.contextName,
130        vbProcessor.makeVarBinds(snmpEngine, varBinds), __cbFun,
131        (options.get('lookupMib', True),
132         options.get('cbFun'), options.get('cbCtx'))
133    )
134
135
136def setCmd(snmpEngine, authData, transportTarget, contextData,
137           *varBinds, **options):
138    """Performs SNMP SET query.
139
140    Based on passed parameters, prepares SNMP SET packet
141    (:RFC:`1905#section-4.2.5`) and schedules its transmission by
142    I/O framework at a later point of time.
143
144    Parameters
145    ----------
146    snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine`
147        Class instance representing SNMP engine.
148
149    authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData`
150        Class instance representing SNMP credentials.
151
152    transportTarget : :py:class:`~pysnmp.hlapi.asyncore.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncore.Udp6TransportTarget`
153        Class instance representing transport type along with SNMP peer
154        address.
155
156    contextData : :py:class:`~pysnmp.hlapi.ContextData`
157        Class instance representing SNMP ContextEngineId and ContextName
158        values.
159
160    \*varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType`
161        One or more class instances representing MIB variables to place
162        into SNMP request.
163
164    Other Parameters
165    ----------------
166    \*\*options :
167        Request options:
168
169            * `lookupMib` - load MIB and resolve response MIB variables at
170              the cost of slightly reduced performance. Default is `True`.
171            * `cbFun` (callable) - user-supplied callable that is invoked
172               to pass SNMP response data or error to user at a later point
173               of time. Default is `None`.
174            * `cbCtx` (object) - user-supplied object passing additional
175               parameters to/from `cbFun`. Default is `None`.
176
177    Notes
178    -----
179    User-supplied `cbFun` callable must have the following call
180    signature:
181
182    * snmpEngine (:py:class:`~pysnmp.hlapi.SnmpEngine`):
183      Class instance representing SNMP engine.
184    * sendRequestHandle (int): Unique request identifier. Can be used
185      for matching multiple ongoing requests with received responses.
186    * errorIndication (str): True value indicates SNMP engine error.
187    * errorStatus (str): True value indicates SNMP PDU error.
188    * errorIndex (int): Non-zero value refers to `varBinds[errorIndex-1]`
189    * varBinds (tuple): A sequence of
190      :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances
191      representing MIB variables returned in SNMP response in exactly
192      the same order as `varBinds` in request.
193    * `cbCtx` : Original user-supplied object.
194
195    Returns
196    -------
197    sendRequestHandle : int
198        Unique request identifier. Can be used for matching received
199        responses with ongoing requests.
200
201    Raises
202    ------
203    PySnmpError
204        Or its derivative indicating that an error occurred while
205        performing SNMP operation.
206
207    Examples
208    --------
209    >>> from pysnmp.hlapi.asyncore import *
210    >>> def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx):
211    ...     print(errorIndication, errorStatus, errorIndex, varBinds)
212    >>>
213    >>> snmpEngine = SnmpEngine()
214    >>> setCmd(snmpEngine,
215    ...        CommunityData('public'),
216    ...        UdpTransportTarget(('demo.snmplabs.com', 161)),
217    ...        ContextData(),
218    ...        ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysContact', 0), 'info@snmplabs.com'),
219    ...        cbFun=cbFun)
220    >>> snmpEngine.transportDispatcher.runDispatcher()
221    (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.4.0')), DisplayString('info@snmplabs.com'))])
222    >>>
223
224    """
225
226    def __cbFun(snmpEngine, sendRequestHandle,
227                errorIndication, errorStatus, errorIndex,
228                varBinds, cbCtx):
229        lookupMib, cbFun, cbCtx = cbCtx
230        return cbFun(snmpEngine, sendRequestHandle, errorIndication,
231                     errorStatus, errorIndex,
232                     vbProcessor.unmakeVarBinds(
233                         snmpEngine, varBinds, lookupMib
234                     ), cbCtx)
235
236    addrName, paramsName = lcd.configure(
237        snmpEngine, authData, transportTarget, contextData.contextName)
238
239    return cmdgen.SetCommandGenerator().sendVarBinds(
240        snmpEngine, addrName, contextData.contextEngineId,
241        contextData.contextName, vbProcessor.makeVarBinds(snmpEngine, varBinds),
242        __cbFun, (options.get('lookupMib', True),
243                  options.get('cbFun'), options.get('cbCtx'))
244    )
245
246
247def nextCmd(snmpEngine, authData, transportTarget, contextData,
248            *varBinds, **options):
249    """Performs SNMP GETNEXT query.
250
251    Based on passed parameters, prepares SNMP GETNEXT packet
252    (:RFC:`1905#section-4.2.2`) and schedules its transmission by
253    I/O framework at a later point of time.
254
255    Parameters
256    ----------
257    snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine`
258        Class instance representing SNMP engine.
259
260    authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData`
261        Class instance representing SNMP credentials.
262
263    transportTarget : :py:class:`~pysnmp.hlapi.asyncore.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncore.Udp6TransportTarget`
264        Class instance representing transport type along with SNMP peer
265        address.
266
267    contextData : :py:class:`~pysnmp.hlapi.ContextData`
268        Class instance representing SNMP ContextEngineId and ContextName
269        values.
270
271    \*varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType`
272        One or more class instances representing MIB variables to place
273        into SNMP request.
274
275    Other Parameters
276    ----------------
277    \*\*options :
278        Request options:
279
280            * `lookupMib` - load MIB and resolve response MIB variables at
281              the cost of slightly reduced performance. Default is `True`.
282            * `cbFun` (callable) - user-supplied callable that is invoked
283               to pass SNMP response data or error to user at a later point
284               of time. Default is `None`.
285            * `cbCtx` (object) - user-supplied object passing additional
286               parameters to/from `cbFun`. Default is `None`.
287
288    Notes
289    -----
290    User-supplied `cbFun` callable must have the following call
291    signature:
292
293    * snmpEngine (:py:class:`~pysnmp.hlapi.SnmpEngine`):
294      Class instance representing SNMP engine.
295    * sendRequestHandle (int): Unique request identifier. Can be used
296      for matching multiple ongoing requests with received responses.
297    * errorIndication (str): True value indicates SNMP engine error.
298    * errorStatus (str): True value indicates SNMP PDU error.
299    * errorIndex (int): Non-zero value refers to `varBinds[errorIndex-1]`
300    * varBinds (tuple): A sequence of sequences (e.g. 2-D array) of
301      :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances
302      representing a table of MIB variables returned in SNMP response.
303      Inner sequences represent table rows and ordered exactly the same
304      as `varBinds` in request. Response to GETNEXT always contain a
305      single row.
306    * `cbCtx` : Original user-supplied object.
307
308    Returns
309    -------
310    sendRequestHandle : int
311        Unique request identifier. Can be used for matching received
312        responses with ongoing requests.
313
314    Raises
315    ------
316    PySnmpError
317        Or its derivative indicating that an error occurred while
318        performing SNMP operation.
319
320    Examples
321    --------
322    >>> from pysnmp.hlapi.asyncore import *
323    >>> def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx):
324    ...     print(errorIndication, errorStatus, errorIndex, varBinds)
325    >>>
326    >>> snmpEngine = SnmpEngine()
327    >>> nextCmd(snmpEngine,
328    ...         CommunityData('public'),
329    ...         UdpTransportTarget(('demo.snmplabs.com', 161)),
330    ...         ContextData(),
331    ...         ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')),
332    ...         cbFun=cbFun)
333    >>> snmpEngine.transportDispatcher.runDispatcher()
334    (None, 0, 0, [ [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))] ])
335    >>>
336
337    """
338
339    def __cbFun(snmpEngine, sendRequestHandle, errorIndication,
340                errorStatus, errorIndex, varBindTable, cbCtx):
341        lookupMib, cbFun, cbCtx = cbCtx
342        return cbFun(snmpEngine, sendRequestHandle, errorIndication,
343                     errorStatus, errorIndex,
344                     [vbProcessor.unmakeVarBinds(snmpEngine, varBindTableRow, lookupMib) for varBindTableRow in
345                      varBindTable],
346                     cbCtx)
347
348    addrName, paramsName = lcd.configure(
349        snmpEngine, authData, transportTarget, contextData.contextName)
350
351    return cmdgen.NextCommandGenerator().sendVarBinds(
352        snmpEngine, addrName,
353        contextData.contextEngineId, contextData.contextName,
354        vbProcessor.makeVarBinds(snmpEngine, varBinds),
355        __cbFun, (options.get('lookupMib', True),
356                  options.get('cbFun'), options.get('cbCtx'))
357    )
358
359
360def bulkCmd(snmpEngine, authData, transportTarget, contextData,
361            nonRepeaters, maxRepetitions, *varBinds, **options):
362    """Performs SNMP GETBULK query.
363
364    Based on passed parameters, prepares SNMP GETBULK packet
365    (:RFC:`1905#section-4.2.3`) and schedules its transmission by
366    I/O framework at a later point of time.
367
368    Parameters
369    ----------
370    snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine`
371        Class instance representing SNMP engine.
372
373    authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData`
374        Class instance representing SNMP credentials.
375
376    transportTarget : :py:class:`~pysnmp.hlapi.asyncore.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncore.Udp6TransportTarget`
377        Class instance representing transport type along with SNMP peer
378        address.
379
380    contextData : :py:class:`~pysnmp.hlapi.ContextData`
381        Class instance representing SNMP ContextEngineId and ContextName
382        values.
383
384    nonRepeaters : int
385        One MIB variable is requested in response for the first
386        `nonRepeaters` MIB variables in request.
387
388    maxRepetitions : int
389        `maxRepetitions` MIB variables are requested in response for each
390        of the remaining MIB variables in the request (e.g. excluding
391        `nonRepeaters`). Remote SNMP engine may choose lesser value than
392        requested.
393
394    \*varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType`
395        One or more class instances representing MIB variables to place
396        into SNMP request.
397
398    Other Parameters
399    ----------------
400    \*\*options :
401        Request options:
402
403            * `lookupMib` - load MIB and resolve response MIB variables at
404              the cost of slightly reduced performance. Default is `True`.
405            * `cbFun` (callable) - user-supplied callable that is invoked
406               to pass SNMP response data or error to user at a later point
407               of time. Default is `None`.
408            * `cbCtx` (object) - user-supplied object passing additional
409               parameters to/from `cbFun`. Default is `None`.
410
411    Notes
412    -----
413    User-supplied `cbFun` callable must have the following call
414    signature:
415
416    * snmpEngine (:py:class:`~pysnmp.hlapi.SnmpEngine`):
417      Class instance representing SNMP engine.
418    * sendRequestHandle (int): Unique request identifier. Can be used
419      for matching multiple ongoing requests with received responses.
420    * errorIndication (str): True value indicates SNMP engine error.
421    * errorStatus (str): True value indicates SNMP PDU error.
422    * errorIndex (int): Non-zero value refers to `varBinds[errorIndex-1]`
423    * varBindTable (tuple):
424      A sequence of sequences (e.g. 2-D array) of
425      :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances representing a
426      table of MIB variables returned in SNMP response, with up to
427      ``maxRepetitions`` rows, i.e. ``len(varBindTable) <= maxRepetitions``.
428
429      For ``0 <= i < len(varBindTable)`` and ``0 <= j < len(varBinds)``,
430      ``varBindTable[i][j]`` represents:
431
432      - For non-repeaters (``j < nonRepeaters``), the first lexicographic
433        successor of ``varBinds[j]``, regardless the value of ``i``, or an
434        :py:class:`~pysnmp.smi.rfc1902.ObjectType` instance with the
435        :py:obj:`~pysnmp.proto.rfc1905.endOfMibView` value if no such successor
436        exists;
437      - For repeaters (``j >= nonRepeaters``), the ``i``-th lexicographic
438        successor of ``varBinds[j]``, or an
439        :py:class:`~pysnmp.smi.rfc1902.ObjectType` instance with the
440        :py:obj:`~pysnmp.proto.rfc1905.endOfMibView` value if no such successor
441        exists.
442
443      See :rfc:`3416#section-4.2.3` for details on the underlying
444      ``GetBulkRequest-PDU`` and the associated ``GetResponse-PDU``, such as
445      specific conditions under which the server may truncate the response,
446      causing ``varBindTable`` to have less than ``maxRepetitions`` rows.
447    * `cbCtx` : Original user-supplied object.
448
449    Returns
450    -------
451    sendRequestHandle : int
452        Unique request identifier. Can be used for matching received
453        responses with ongoing requests.
454
455    Raises
456    ------
457    PySnmpError
458        Or its derivative indicating that an error occurred while
459        performing SNMP operation.
460
461    Examples
462    --------
463    >>> from pysnmp.hlapi.asyncore import *
464    >>> def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx):
465    ...     print(errorIndication, errorStatus, errorIndex, varBinds)
466    >>>
467    >>> snmpEngine = SnmpEngine()
468    >>> bulkCmd(snmpEngine,
469    ...         CommunityData('public'),
470    ...         UdpTransportTarget(('demo.snmplabs.com', 161)),
471    ...         ContextData(),
472    ...         0, 2,
473    ...         ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')),
474    ...         cbFun=cbFun)
475    >>> snmpEngine.transportDispatcher.runDispatcher()
476    (None, 0, 0, [[ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))], [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.2.0')), ObjectIdentifier('1.3.6.1.4.1.424242.1.1'))]])
477    >>>
478
479    """
480
481    def __cbFun(snmpEngine, sendRequestHandle,
482                errorIndication, errorStatus, errorIndex,
483                varBindTable, cbCtx):
484        lookupMib, cbFun, cbCtx = cbCtx
485        return cbFun(snmpEngine, sendRequestHandle, errorIndication,
486                     errorStatus, errorIndex,
487                     [vbProcessor.unmakeVarBinds(snmpEngine, varBindTableRow, lookupMib) for varBindTableRow in
488                      varBindTable], cbCtx)
489
490    addrName, paramsName = lcd.configure(
491        snmpEngine, authData, transportTarget, contextData.contextName)
492
493    return cmdgen.BulkCommandGenerator().sendVarBinds(
494        snmpEngine, addrName, contextData.contextEngineId,
495        contextData.contextName, nonRepeaters, maxRepetitions,
496        vbProcessor.makeVarBinds(snmpEngine, varBinds), __cbFun,
497        (options.get('lookupMib', True),
498         options.get('cbFun'), options.get('cbCtx'))
499    )
500