1 # -*- test-case-name: twisted.pair.test.test_ip -*-
2 # Copyright (c) Twisted Matrix Laboratories.
3 # See LICENSE for details.
8 """Support for working directly with IP packets"""
13 from twisted.internet import protocol
14 from twisted.pair import raw
15 from zope.interface import implements
19 def __init__(self, data):
21 (ihlversion, self.tos, self.tot_len, self.fragment_id, frag_off,
22 self.ttl, self.protocol, self.check, saddr, daddr) \
23 = struct.unpack("!BBHHHBBH4s4s", data[:20])
24 self.saddr = socket.inet_ntoa(saddr)
25 self.daddr = socket.inet_ntoa(daddr)
26 self.version = ihlversion & 0x0F
27 self.ihl = ((ihlversion & 0xF0) >> 4) << 2
28 self.fragment_offset = frag_off & 0x1FFF
29 self.dont_fragment = (frag_off & 0x4000 != 0)
30 self.more_fragments = (frag_off & 0x2000 != 0)
34 class IPProtocol(protocol.AbstractDatagramProtocol):
35 implements(raw.IRawPacketProtocol)
40 def addProto(self, num, proto):
41 proto = raw.IRawDatagramProtocol(proto)
43 raise TypeError, 'Added protocol must be positive or zero'
45 raise TypeError, 'Added protocol must fit in 32 bits'
46 if num not in self.ipProtos:
47 self.ipProtos[num] = []
48 self.ipProtos[num].append(proto)
50 def datagramReceived(self,
56 header = IPHeader(data)
57 for proto in self.ipProtos.get(header.protocol, ()):
58 proto.datagramReceived(data=data[20:],
62 protocol=header.protocol,
63 version=header.version,
66 tot_len=header.tot_len,
67 fragment_id=header.fragment_id,
68 fragment_offset=header.fragment_offset,
69 dont_fragment=header.dont_fragment,
70 more_fragments=header.more_fragments,