summaryrefslogtreecommitdiff
path: root/examples/v3arch/asyncore/proxy/command/udp6-to-udp4-conversion.py
blob: a13df6b628e7c26ca2bb6ca41c5ced8f72192f5d (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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
"""
IPv6-to-IPv4 conversion
+++++++++++++++++++++++

Act as a local SNMPv1/v2c Agent listening on a UDP/IPv6 transport, relay
messages to distant SNMPv1/2c Agent over UDP/IPv4 transport:

* with local SNMPv2c community 'public'
* local Agent listening at [::1]:161
* remote SNMPv2c community 'public'
* remote Agent listening at 195.218.195.228:161

This script can be queried with the following Net-SNMP command:

| $ snmpget -v2c -c public udp6:[::1]:161 sysDescr.0

due to proxy, it is equivalent to

| $ snmpget -v2c -c public 195.218.195.228:161 sysDescr.0

Warning: for production operation you would need to modify this script
so that it will re-map possible duplicate request-ID values, coming in
initial request PDUs from different Managers, into unique values to
avoid sending duplicate request-IDs to Agents.

"""#
from pysnmp.carrier.asyncore.dgram import udp, udp6
from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413 import cmdrsp, cmdgen, context
from pysnmp.proto.api import v2c
from pysnmp import error

# Create SNMP engine with autogenernated engineID and pre-bound
# to socket transport dispatcher
snmpEngine = engine.SnmpEngine()

#
# Transport setup
#

# Agent section

# UDP over IPv6
config.addTransport(
    snmpEngine,
    udp6.domainName,
    udp6.Udp6Transport().openServerMode(('::1', 161))
)

# Manager section

# UDP over IPv4
config.addTransport(
    snmpEngine,
    udp.domainName,
    udp.UdpTransport().openClientMode()
)

#
# SNMPv1/2c setup (Agent role)
#

# SecurityName <-> CommunityName mapping
config.addV1System(snmpEngine, '1-my-area', 'public')

#
# SNMPv1/v2c setup (Manager role)
#
# Here we configure securityName lexicographically lesser than '1-my-area'
# to let it match first in snmpCommunityTable on response processing.
#

config.addV1System(snmpEngine, '0-distant-area', 'public',
                   transportTag='remote')

#
# Transport target used by Manager
#

config.addTargetParams(
    snmpEngine, 'distant-agent-auth', '0-distant-area', 'noAuthNoPriv', 1
)
config.addTargetAddr(
        snmpEngine, 'distant-agent', 
        udp.domainName, ('195.218.195.228', 161),
        'distant-agent-auth', retryCount=0, tagList='remote'
)

# Default SNMP context
config.addContext(snmpEngine, '')

class CommandResponder(cmdrsp.CommandResponderBase):
    cmdGenMap = { 
        v2c.GetRequestPDU.tagSet: cmdgen.GetCommandGenerator(),
        v2c.SetRequestPDU.tagSet: cmdgen.SetCommandGenerator(),
        v2c.GetNextRequestPDU.tagSet: cmdgen.NextCommandGeneratorSingleRun(),
        v2c.GetBulkRequestPDU.tagSet: cmdgen.BulkCommandGeneratorSingleRun() 
    }
    pduTypes = cmdGenMap.keys()  # This app will handle these PDUs

    # SNMP request relay
    def handleMgmtOperation(self, snmpEngine, stateReference, contextName,
                            PDU, acInfo):
        cbCtx = stateReference, PDU
        contextEngineId = None  # address authoritative SNMP Engine
        try:
            self.cmdGenMap[PDU.tagSet].sendPdu(
                snmpEngine, 'distant-agent', 
                contextEngineId, contextName,
                PDU,
                self.handleResponsePdu, cbCtx
            )
        except error.PySnmpError:
            self.handleResponsePdu(
                stateReference,  'error', None, cbCtx
            )

    # SNMP response relay
    def handleResponsePdu(self, snmpEngine, sendRequestHandle,
                          errorIndication, PDU, cbCtx):
        stateReference, reqPDU = cbCtx

        if errorIndication:
            PDU = v2c.apiPDU.getResponse(reqPDU)
            PDU.setErrorStatus(PDU, 5)

        self.sendPdu(
            snmpEngine, stateReference, PDU
        )

        self.releaseStateInformation(stateReference)

CommandResponder(snmpEngine, context.SnmpContext(snmpEngine))

snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish

# Run I/O dispatcher which would receive queries and send responses
try:
    snmpEngine.transportDispatcher.runDispatcher()
except:
    snmpEngine.transportDispatcher.closeDispatcher()
    raise