[Twisted-Python] New user, help needed with raw UDP packets
Richard Taylor
r.taylor at eris.qinetiq.com
Mon Apr 19 01:56:46 MDT 2004
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Many thanks to everyone that responded to my appeal for help with raw UDP
sockets. Following up on the useful pointers I have come up with an initial
proof of concept. The code below does appear to do what I need, although it
needs lots of tiding up. If anyone can see anything wrong with what I am
doing I would value the criticism.
import socket, fcntl
from twisted.internet import protocol
from twisted.internet import udp
from twisted.internet import reactor
import impacket # library from
http://oss.coresecurity.com/projects/impacket.html
from impacket import ImpactDecoder,ImpactPacket
from twisted.python.runtime import platformType
if platformType == 'win32':
from errno import WSAEWOULDBLOCK as EWOULDBLOCK
from errno import WSAEINTR as EINTR
from errno import WSAEMSGSIZE as EMSGSIZE
from errno import WSAECONNREFUSED as ECONNREFUSED
from errno import WSAECONNRESET
from errno import EAGAIN
elif platformType != 'java':
from errno import EWOULDBLOCK, EINTR, EMSGSIZE, ECONNREFUSED, EAGAIN
class Echo(protocol.DatagramProtocol):
def __init__(self):
self.fake_addr = None
self.dest = "127.0.0.1"
self.port = 9999
def setFakeSrc(self, addr):
"""Set the fake address from which packets should appear to come."""
self.fake_addr = addr
def startProtocol(self):
print "starting Echo"
def datagramReceived(self, data, (host, port)):
"""data is a IP packet object from Impacket."""
ip = data
udp = ip.child()
if udp.get_uh_dport() == 9999:
src = ip.get_ip_src()
print "host = %s" % (host,)
print "udp src = %s" % (src,)
print "received: %s" % (udp,)
if self.fake_addr and src == "128.98.3.63":
# Fake the src address and resend the packet
ip.set_ip_src(self.fake_addr)
print "resending with src = %s\n" % (ip.get_ip_src(),)
self.transport.write(ip.get_packet(), (self.dest,self.port))
class RawUDPPort(udp.Port):
"""Raw udp port."""
__implements__ = udp.Port.__implements__
socketType = socket.SOCK_RAW # Overide socket type.
addressFamily = socket.AF_INET
def __init__(self, *args, **kw):
udp.Port.__init__(self,*args,**kw)
self.protocolNum = socket.getprotobyname('udp')
self.decoder = ImpactDecoder.IPDecoder()
def createInternetSocket(self):
s = socket.socket(self.addressFamily, self.socketType,
self.protocolNum)
s.setblocking(0)
# enable the sending of udp headers.
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
if fcntl and hasattr(fcntl, 'FD_CLOEXEC'):
old = fcntl.fcntl(s.fileno(), fcntl.F_GETFD)
fcntl.fcntl(s.fileno(), fcntl.F_SETFD, old | fcntl.FD_CLOEXEC)
return s
def doRead(self):
"""Called when my socket is ready for reading."""
read = 0
while read < self.maxThroughput:
try:
data, addr = self.socket.recvfrom(self.maxPacketSize)
read += len(data)
ip = self.decoder.decode(data)
if isinstance(ip.child(),ImpactPacket.UDP) and \
ip.child().get_uh_dport() == self.port:
self.protocol.datagramReceived(ip, addr)
except socket.error, se:
no = se.args[0]
if no in (EAGAIN, EINTR, EWOULDBLOCK):
return
if (no == ECONNREFUSED) or (platformType == "win32" and no ==
WSAECONNRESET):
# XXX for the moment we don't deal with connection
refused
# in non-connected UDP sockets.
pass
else:
raise
## except:
## log.deferr()
echo = Echo()
echo.setFakeSrc("127.0.0.1")
reactor.listenWith(RawUDPPort,
proto=echo, port=9999, interface="localhost",
reactor=reactor)
reactor.run()
Thanks again to everyone that helped. Once I have tidied things up I will send
the finished bits to the appropriate people (who are they?) in case they want
to include them as an example.
Regards
Richard
- --
QinetiQ
B009 Woodward Building
St. Andrews Road
Malvern
Worcs WR14 3PS
Jabber: RichardTaylor at jabber.org
PGPKey: http://search.keyserver.net:11371/pks/lookup?op=get&search=0xA7DA9FD9
Key fingerprint = D051 A121 E7C3 485F 3C0E 1593 ED9E D868 A7DA 9FD9
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)
iD8DBQFAg4ZE7Z7YaKfan9kRAqPIAKDOmCMLn7zEXKbr7i3kmkw7ofibFwCcCvZt
CqkSAsP397lFCqKFeke0J6s=
=DN4i
-----END PGP SIGNATURE-----
More information about the Twisted-Python
mailing list