Protocol conversion
*******************


SNMPv2c-to-SNMPv1 conversion
============================

Act as a local SNMPv2c Agent, relay messages to distant SNMPv1 Agent:

* over IPv4/UDP

* with local SNMPv2c community public

* local Agent listening at 127.0.0.1:161

* remote SNMPv1, community public

* remote Agent listening at 104.236.166.95:161

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

   $ snmpbulkwalk -v2c -c public -ObentU 127.0.0.1:161 system

due to proxy, it is equivalent to

   $ snmpwalk -v1 -c public 104.236.166.95:161 system

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
   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 IPv4
   config.addTransport(
       snmpEngine,
       udp.domainName + (1,),
       udp.UdpTransport().openServerMode(('127.0.0.1', 161))
   )

   # Manager section

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

   #
   # SNMPv2c setup (Agent role)
   #

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

   #
   # SNMPv1 setup (Manager role)
   #

   # SecurityName <-> CommunityName <-> Transport mapping
   config.addV1System(snmpEngine, 'distant-area', 'public', transportTag='distant')

   #
   # Transport target used by Manager
   #

   # Specify security settings per SecurityName (SNMPv1 - 0, SNMPv2c - 1)
   config.addTargetParams(snmpEngine, 'distant-agent-auth', 'distant-area',
                          'noAuthNoPriv', 0)

   config.addTargetAddr(
       snmpEngine, 'distant-agent',
       udp.domainName + (2,), ('104.236.166.95', 161),
       'distant-agent-auth', retryCount=0, tagList='distant'
   )

   # 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(
                   snmpEngine, stateReference, 'error', None, cbCtx
               )

       # SNMP response relay
       # noinspection PyUnusedLocal
       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

"Download" script.


SNMPv2c-to-SNMPv3 conversion
============================

Act as a local SNMPv1/v2c Agent, relay messages to distant SNMPv3
Agent: * over IPv4/UDP * with local SNMPv2c community 'public' * local
Agent listening at 127.0.0.1:161 * remote SNMPv3 user usr-md5-none,
MD5 auth and no privacy protocols * remote Agent listening at
104.236.166.95:161

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

   $ snmpget -v2c -c public 127.0.0.1:161 1.3.6.1.2.1.1.1.0

due to proxy, it is equivalent to

   $ snmpget -v3 -l authNoPriv -u usr-md5-none -A authkey1 -ObentU 104.236.166.95:161  1.3.6.1.2.1.1.1.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
   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 IPv4
   config.addTransport(
       snmpEngine,
       udp.domainName + (1,),
       udp.UdpTransport().openServerMode(('127.0.0.1', 161))
   )

   # Manager section

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

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

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

   #
   # SNMPv3/USM setup (Manager role)
   #

   # user: usr-md5-none, auth: MD5, priv NONE
   config.addV3User(
       snmpEngine, 'usr-md5-none', config.usmHMACMD5AuthProtocol, 'authkey1'
   )

   #
   # Transport target used by Manager
   #

   config.addTargetParams(
       snmpEngine, 'distant-agent-auth', 'usr-md5-none', 'authNoPriv'
   )
   config.addTargetAddr(
       snmpEngine, 'distant-agent',
       udp.domainName + (2,), ('104.236.166.95', 161),
       'distant-agent-auth', retryCount=0
   )

   # 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(
                   snmpEngine, stateReference, 'error', None, cbCtx
               )

       # SNMP response relay
       # noinspection PyUnusedLocal
       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

"Download" script.


SNMPv3-to-SNMPv2c conversion
============================

Act as a local SNMPv3 Agent, relay messages to distant SNMPv1/v2c
Agent: * over IPv4/UDP * with local SNMPv3 user usr-md5-des, MD5 auth
and DES privacy protocols * local Agent listening at 127.0.0.1:161 *
remote SNMPv1, community public * remote Agent listening at
104.236.166.95:161

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

   $ snmpget -v3 -l authPriv -u usr-md5-des -A authkey1 -X privkey1 -ObentU 127.0.0.1:161 1.3.6.1.2.1.1.1.0

due to proxy, it is equivalent to

   $ snmpget -v2c -c public 104.236.166.95:161 1.3.6.1.2.1.1.1.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
   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 IPv4
   config.addTransport(
       snmpEngine,
       udp.domainName + (1,),
       udp.UdpTransport().openServerMode(('127.0.0.1', 161))
   )

   # Manager section

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

   #
   # SNMPv3/USM setup (Agent role)
   #

   # user: usr-md5-des, auth: MD5, priv DES
   config.addV3User(
       snmpEngine, 'usr-md5-des',
       config.usmHMACMD5AuthProtocol, 'authkey1',
       config.usmDESPrivProtocol, 'privkey1'
   )

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

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

   #
   # Transport target used by Manager
   #

   # Specify security settings per SecurityName (SNMPv1 - 0, SNMPv2c - 1)
   config.addTargetParams(snmpEngine, 'distant-agent-auth', 'my-area',
                          'noAuthNoPriv', 0)

   config.addTargetAddr(
       snmpEngine, 'distant-agent',
       udp.domainName + (2,), ('104.236.166.95', 161),
       'distant-agent-auth', retryCount=0
   )

   # 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(
                   snmpEngine, stateReference, 'error', None, cbCtx
               )

       # SNMP response relay
       # noinspection PyUnusedLocal
       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

"Download" script.

See also: library-reference.
