summaryrefslogtreecommitdiff
path: root/examples/v1arch
diff options
context:
space:
mode:
authorelie <elie>2015-01-20 16:57:59 +0000
committerelie <elie>2015-01-20 16:57:59 +0000
commitc317a137113d4f39a60052c0ae59a9c48b0dd334 (patch)
tree19fbd1d94927e20894d140fd1a77ac439462167e /examples/v1arch
parent48fa5f20c6a341708db517dc6a78dbd84d057192 (diff)
downloadpysnmp-git-c317a137113d4f39a60052c0ae59a9c48b0dd334.tar.gz
- The asyncore-based transport subsystem extended to support POSIX
sendmsg()/recvmsg() based socket communication what could be used, among other things, in the context of a transparent SNMP proxy application. Technically, the following features were brought into pysnmp with this update: * Sending SNMP packets from a non-local IP address * Receiving IP packets for non-local IP addresses * Responding to SNMP requests from exactly the same IP address the query was sent to. This proves to be useful when listening on both primary and secondary IP interfaces.
Diffstat (limited to 'examples/v1arch')
-rw-r--r--examples/v1arch/asyncore/manager/cmdgen/spoof-source-address.py87
1 files changed, 87 insertions, 0 deletions
diff --git a/examples/v1arch/asyncore/manager/cmdgen/spoof-source-address.py b/examples/v1arch/asyncore/manager/cmdgen/spoof-source-address.py
new file mode 100644
index 00000000..28f2190e
--- /dev/null
+++ b/examples/v1arch/asyncore/manager/cmdgen/spoof-source-address.py
@@ -0,0 +1,87 @@
+from pysnmp.carrier.asynsock.dispatch import AsynsockDispatcher
+from pysnmp.carrier.asynsock.dgram import udp
+from pysnmp.proto import api
+from pyasn1.codec.ber import encoder, decoder
+from time import time
+
+# Send request message to this address
+transportAddress = udp.UdpTransportAddress(('195.218.195.228', 161))
+
+# Send request message from this non-local (!) IP address
+transportAddress.setLocalAddress(('1.2.3.4', 0))
+
+# Protocol version to use
+#pMod = api.protoModules[api.protoVersion1]
+pMod = api.protoModules[api.protoVersion2c]
+
+# Build PDU
+reqPDU = pMod.GetRequestPDU()
+pMod.apiPDU.setDefaults(reqPDU)
+pMod.apiPDU.setVarBinds(
+ reqPDU, ( ('1.3.6.1.2.1.1.1.0', pMod.Null('')),
+ ('1.3.6.1.2.1.1.3.0', pMod.Null('')) )
+ )
+
+# Build message
+reqMsg = pMod.Message()
+pMod.apiMessage.setDefaults(reqMsg)
+pMod.apiMessage.setCommunity(reqMsg, 'public')
+pMod.apiMessage.setPDU(reqMsg, reqPDU)
+
+startedAt = time()
+
+class StopWaiting(Exception): pass
+
+def cbTimerFun(timeNow):
+ if timeNow - startedAt > 3:
+ raise StopWaiting()
+
+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:
+ 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)
+
+# Initialize UDP/IPv4 transport
+udpSocketTransport = udp.UdpSocketTransport().openClientMode()
+
+# Use sendmsg()/recvmsg() for socket communication (required for
+# IP source spoofing functionality)
+udpSocketTransport.enablePktInfo()
+
+# Enable IP source spoofing (requires root privileges)
+udpSocketTransport.enableTransparent()
+
+transportDispatcher.registerTransport(udp.domainName, udpSocketTransport)
+
+# Pass message to dispatcher
+transportDispatcher.sendMessage(
+ encoder.encode(reqMsg), udp.domainName, transportAddress
+)
+
+# We might never receive any response as we sent request with fake source IP
+transportDispatcher.jobStarted(1)
+
+# Dispatcher will finish as all jobs counter reaches zero
+try:
+ transportDispatcher.runDispatcher()
+except StopWaiting:
+ transportDispatcher.closeDispatcher()
+else:
+ raise