summaryrefslogtreecommitdiff
path: root/pysnmp/entity/rfc3413/ntfrcv.py
blob: 53cc7ac35aed6cd6e2626817483644e999da6e1d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#
# This file is part of pysnmp software.
#
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pysnmp/license.html
#
from pyasn1.compat.octets import null

from pysnmp import debug
from pysnmp.proto import error
from pysnmp.proto import rfc3411
from pysnmp.proto.api import v1
from pysnmp.proto.api import v2c  # backend is always SMIv2 compliant
from pysnmp.proto.proxy import rfc2576


# 3.4
class NotificationReceiver(object):
    SUPPORTED_PDU_TYPES = (v1.TrapPDU.tagSet, v2c.SNMPv2TrapPDU.tagSet,
                           v2c.InformRequestPDU.tagSet)

    def __init__(self, snmpEngine, cbFun, cbCtx=None):
        snmpEngine.msgAndPduDsp.registerContextEngineId(
            null, self.SUPPORTED_PDU_TYPES, self.processPdu  # '' is a wildcard
        )

        self.__snmpTrapCommunity = ''
        self.__cbFun = cbFun
        self.__cbCtx = cbCtx

        def storeSnmpTrapCommunity(snmpEngine, execpoint, variables, cbCtx):
            self.__snmpTrapCommunity = variables.get('communityName', '')

        snmpEngine.observer.registerObserver(
            storeSnmpTrapCommunity, 'rfc2576.processIncomingMsg')

    def close(self, snmpEngine):
        snmpEngine.msgAndPduDsp.unregisterContextEngineId(
            null, self.SUPPORTED_PDU_TYPES
        )
        self.__cbFun = self.__cbCtx = None

    def processPdu(self, snmpEngine, messageProcessingModel,
                   securityModel, securityName, securityLevel,
                   contextEngineId, contextName, pduVersion, PDU,
                   maxSizeResponseScopedPDU, stateReference):

        # Agent-side API complies with SMIv2
        if messageProcessingModel == 0:
            origPdu = PDU
            PDU = rfc2576.v1ToV2(PDU, snmpTrapCommunity=self.__snmpTrapCommunity)

        else:
            origPdu = None

        errorStatus = 'noError'
        errorIndex = 0
        varBinds = v2c.apiPDU.getVarBinds(PDU)

        debug.logger & debug.FLAG_APP and debug.logger(
            'processPdu: stateReference %s, varBinds %s' % (stateReference, varBinds))

        # 3.4
        if PDU.tagSet in rfc3411.CONFIRMED_CLASS_PDUS:
            # 3.4.1 --> no-op

            rspPDU = v2c.apiPDU.getResponse(PDU)

            # 3.4.2
            v2c.apiPDU.setErrorStatus(rspPDU, errorStatus)
            v2c.apiPDU.setErrorIndex(rspPDU, errorIndex)
            v2c.apiPDU.setVarBinds(rspPDU, varBinds)

            debug.logger & debug.FLAG_APP and debug.logger(
                'processPdu: stateReference %s, confirm PDU %s' % (stateReference, rspPDU.prettyPrint()))

            # Agent-side API complies with SMIv2
            if messageProcessingModel == 0:
                rspPDU = rfc2576.v2ToV1(rspPDU, origPdu)

            statusInformation = {}

            # 3.4.3
            try:
                snmpEngine.msgAndPduDsp.returnResponsePdu(
                    snmpEngine, messageProcessingModel, securityModel,
                    securityName, securityLevel, contextEngineId,
                    contextName, pduVersion, rspPDU, maxSizeResponseScopedPDU,
                    stateReference, statusInformation)

            except error.StatusInformation as exc:
                debug.logger & debug.FLAG_APP and debug.logger(
                    'processPdu: stateReference %s, statusInformation %s' % (stateReference, exc))

                mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder

                snmpSilentDrops, = mibBuilder.importSymbols(
                    '__SNMPv2-MIB', 'snmpSilentDrops')

                snmpSilentDrops.syntax += 1

        elif PDU.tagSet in rfc3411.UNCONFIRMED_CLASS_PDUS:
            pass

        else:
            raise error.ProtocolError('Unexpected PDU class %s' % PDU.tagSet)

        debug.logger & debug.FLAG_APP and debug.logger(
            'processPdu: stateReference %s, user cbFun %s, cbCtx %s, varBinds %s' % (
                stateReference, self.__cbFun, self.__cbCtx, varBinds))

        self.__cbFun(snmpEngine, stateReference, contextEngineId,
                     contextName, varBinds, self.__cbCtx)