1# $Id: ip.py,v 1.1.1.1 2005/10/29 18:20:48 provos Exp $
2
3from dpkt import Packet, in_cksum as _ip_cksum, \
4     in_cksum_add as _ip_cksum_add, in_cksum_done as _ip_cksum_done
5
6class IP(Packet):
7    """Internet Protocol."""
8    __hdr__ = (
9        ('v_hl', 'B', (4 << 4) | (20 >> 2)),
10        ('tos', 'B', 0),
11        ('len', 'H', 20),
12        ('id', 'H', 0),
13        ('off', 'H', 0),
14        ('ttl', 'B', 64),
15        ('p', 'B', 0),
16        ('sum', 'H', 0),
17        ('src', '4s', ''),
18        ('dst', '4s', '')
19        )
20    _protosw = {}
21    opts = ''
22
23    def _get_v(self): return self.v_hl >> 4
24    def _set_v(self, v): self.v_hl = (v << 4) | (self.v_hl & 0xf)
25    v = property(_get_v, _set_v)
26
27    def _get_hl(self): return self.v_hl & 0xf
28    def _set_hl(self, hl): self.v_hl = (self.v_hl & 0xf0) | hl
29    hl = property(_get_hl, _set_hl)
30
31    def __len__(self):
32        return self.__hdr_len__ + len(self.opts) + len(self.data)
33
34    def __str__(self):
35        if not self.sum:
36            if self.p == 6 or self.p == 17 and self.data.sum == 0 and \
37               self.off & (IP_MF|IP_OFFMASK) == 0:
38                try:
39                    # Set zeroed TCP and UDP checksums for non-fragments.
40                    s = _ip_cksum_add(self.data.sum, self.src + self.dst)
41                    p = str(self.data)
42                    s = _ip_cksum_add(s, p)
43                    self.data.sum = _ip_cksum_done(s + self.p + len(p))
44                    if self.p == 17 and not self.data.sum:
45                        self.data.sum = 0xffff	# RFC 768
46                except AttributeError:
47                    pass
48            self.sum = _ip_cksum(self.pack_hdr())
49        return self.pack_hdr() + self.opts + str(self.data)
50
51    def unpack(self, buf):
52        Packet.unpack(self, buf)
53        ol = ((self.v_hl & 0xf) << 2) - self.__hdr_len__
54        self.opts = buf[self.__hdr_len__:self.__hdr_len__ + ol]
55        buf = buf[self.__hdr_len__ + ol:self.len]
56        try:
57            self.data = self._protosw[self.p](buf)
58            setattr(self, self.data.__class__.__name__.lower(), self.data)
59        except:
60            self.data = buf
61
62import ah, esp, gre, icmp, icmp6, igmp, pim, tcp, udp
63
64# XXX - prevent import cycle
65IP._protosw.update({
66    1:icmp.ICMP, 2:igmp.IGMP, 4:IP, 6:tcp.TCP, 17:udp.UDP, 47:gre.GRE,
67    50:esp.ESP, 51:ah.AH, 58:icmp6.ICMP6, 103:pim.PIM
68    })
69
70# Type of service (ip_tos), RFC 1349 ("obsoleted by RFC 2474")
71IP_TOS_DEFAULT		= 0x00	# default
72IP_TOS_LOWDELAY		= 0x10	# low delay
73IP_TOS_THROUGHPUT	= 0x08	# high throughput
74IP_TOS_RELIABILITY	= 0x04	# high reliability
75IP_TOS_LOWCOST		= 0x02	# low monetary cost - XXX
76IP_TOS_ECT		= 0x02	# ECN-capable transport
77IP_TOS_CE		= 0x01	# congestion experienced
78
79# IP precedence (high 3 bits of ip_tos), hopefully unused
80IP_TOS_PREC_ROUTINE		= 0x00
81IP_TOS_PREC_PRIORITY		= 0x20
82IP_TOS_PREC_IMMEDIATE		= 0x40
83IP_TOS_PREC_FLASH		= 0x60
84IP_TOS_PREC_FLASHOVERRIDE	= 0x80
85IP_TOS_PREC_CRITIC_ECP		= 0xa0
86IP_TOS_PREC_INTERNETCONTROL	= 0xc0
87IP_TOS_PREC_NETCONTROL		= 0xe0
88
89# Fragmentation flags (ip_off)
90IP_RF		= 0x8000	# reserved
91IP_DF		= 0x4000	# don't fragment
92IP_MF		= 0x2000	# more fragments (not last frag)
93IP_OFFMASK	= 0x1fff	# mask for fragment offset
94
95# Time-to-live (ip_ttl), seconds
96IP_TTL_DEFAULT	= 64		# default ttl, RFC 1122, RFC 1340
97IP_TTL_MAX	= 255		# maximum ttl
98
99# Protocol (ip_p) - http://www.iana.org/assignments/protocol-numbers
100IP_PROTO_IP		= 0		# dummy for IP
101IP_PROTO_HOPOPTS	= IP_PROTO_IP	# IPv6 hop-by-hop options
102IP_PROTO_ICMP		= 1		# ICMP
103IP_PROTO_IGMP		= 2		# IGMP
104IP_PROTO_GGP		= 3		# gateway-gateway protocol
105IP_PROTO_IPIP		= 4		# IP in IP
106IP_PROTO_ST		= 5		# ST datagram mode
107IP_PROTO_TCP		= 6		# TCP
108IP_PROTO_CBT		= 7		# CBT
109IP_PROTO_EGP		= 8		# exterior gateway protocol
110IP_PROTO_IGP		= 9		# interior gateway protocol
111IP_PROTO_BBNRCC		= 10		# BBN RCC monitoring
112IP_PROTO_NVP		= 11		# Network Voice Protocol
113IP_PROTO_PUP		= 12		# PARC universal packet
114IP_PROTO_ARGUS		= 13		# ARGUS
115IP_PROTO_EMCON		= 14		# EMCON
116IP_PROTO_XNET		= 15		# Cross Net Debugger
117IP_PROTO_CHAOS		= 16		# Chaos
118IP_PROTO_UDP		= 17		# UDP
119IP_PROTO_MUX		= 18		# multiplexing
120IP_PROTO_DCNMEAS	= 19		# DCN measurement
121IP_PROTO_HMP		= 20		# Host Monitoring Protocol
122IP_PROTO_PRM		= 21		# Packet Radio Measurement
123IP_PROTO_IDP		= 22		# Xerox NS IDP
124IP_PROTO_TRUNK1		= 23		# Trunk-1
125IP_PROTO_TRUNK2		= 24		# Trunk-2
126IP_PROTO_LEAF1		= 25		# Leaf-1
127IP_PROTO_LEAF2		= 26		# Leaf-2
128IP_PROTO_RDP		= 27		# "Reliable Datagram" proto
129IP_PROTO_IRTP		= 28		# Inet Reliable Transaction
130IP_PROTO_TP		= 29 		# ISO TP class 4
131IP_PROTO_NETBLT		= 30		# Bulk Data Transfer
132IP_PROTO_MFPNSP		= 31		# MFE Network Services
133IP_PROTO_MERITINP	= 32		# Merit Internodal Protocol
134IP_PROTO_SEP		= 33		# Sequential Exchange proto
135IP_PROTO_3PC		= 34		# Third Party Connect proto
136IP_PROTO_IDPR		= 35		# Interdomain Policy Route
137IP_PROTO_XTP		= 36		# Xpress Transfer Protocol
138IP_PROTO_DDP		= 37		# Datagram Delivery Proto
139IP_PROTO_CMTP		= 38		# IDPR Ctrl Message Trans
140IP_PROTO_TPPP		= 39		# TP++ Transport Protocol
141IP_PROTO_IL		= 40		# IL Transport Protocol
142IP_PROTO_IP6		= 41		# IPv6
143IP_PROTO_SDRP		= 42		# Source Demand Routing
144IP_PROTO_ROUTING	= 43		# IPv6 routing header
145IP_PROTO_FRAGMENT	= 44		# IPv6 fragmentation header
146IP_PROTO_RSVP		= 46		# Reservation protocol
147IP_PROTO_GRE		= 47		# General Routing Encap
148IP_PROTO_MHRP		= 48		# Mobile Host Routing
149IP_PROTO_ENA		= 49		# ENA
150IP_PROTO_ESP		= 50		# Encap Security Payload
151IP_PROTO_AH		= 51		# Authentication Header
152IP_PROTO_INLSP		= 52		# Integated Net Layer Sec
153IP_PROTO_SWIPE		= 53		# SWIPE
154IP_PROTO_NARP		= 54		# NBMA Address Resolution
155IP_PROTO_MOBILE		= 55		# Mobile IP, RFC 2004
156IP_PROTO_TLSP		= 56		# Transport Layer Security
157IP_PROTO_SKIP		= 57		# SKIP
158IP_PROTO_ICMP6		= 58		# ICMP for IPv6
159IP_PROTO_NONE		= 59		# IPv6 no next header
160IP_PROTO_DSTOPTS	= 60		# IPv6 destination options
161IP_PROTO_ANYHOST	= 61		# any host internal proto
162IP_PROTO_CFTP		= 62		# CFTP
163IP_PROTO_ANYNET		= 63		# any local network
164IP_PROTO_EXPAK		= 64		# SATNET and Backroom EXPAK
165IP_PROTO_KRYPTOLAN	= 65		# Kryptolan
166IP_PROTO_RVD		= 66		# MIT Remote Virtual Disk
167IP_PROTO_IPPC		= 67		# Inet Pluribus Packet Core
168IP_PROTO_DISTFS		= 68		# any distributed fs
169IP_PROTO_SATMON		= 69		# SATNET Monitoring
170IP_PROTO_VISA		= 70		# VISA Protocol
171IP_PROTO_IPCV		= 71		# Inet Packet Core Utility
172IP_PROTO_CPNX		= 72		# Comp Proto Net Executive
173IP_PROTO_CPHB		= 73		# Comp Protocol Heart Beat
174IP_PROTO_WSN		= 74		# Wang Span Network
175IP_PROTO_PVP		= 75		# Packet Video Protocol
176IP_PROTO_BRSATMON	= 76		# Backroom SATNET Monitor
177IP_PROTO_SUNND		= 77		# SUN ND Protocol
178IP_PROTO_WBMON		= 78		# WIDEBAND Monitoring
179IP_PROTO_WBEXPAK	= 79		# WIDEBAND EXPAK
180IP_PROTO_EON		= 80		# ISO CNLP
181IP_PROTO_VMTP		= 81		# Versatile Msg Transport
182IP_PROTO_SVMTP		= 82		# Secure VMTP
183IP_PROTO_VINES		= 83		# VINES
184IP_PROTO_TTP		= 84		# TTP
185IP_PROTO_NSFIGP		= 85		# NSFNET-IGP
186IP_PROTO_DGP		= 86		# Dissimilar Gateway Proto
187IP_PROTO_TCF		= 87		# TCF
188IP_PROTO_EIGRP		= 88		# EIGRP
189IP_PROTO_OSPF		= 89		# Open Shortest Path First
190IP_PROTO_SPRITERPC	= 90		# Sprite RPC Protocol
191IP_PROTO_LARP		= 91		# Locus Address Resolution
192IP_PROTO_MTP		= 92		# Multicast Transport Proto
193IP_PROTO_AX25		= 93		# AX.25 Frames
194IP_PROTO_IPIPENCAP	= 94		# yet-another IP encap
195IP_PROTO_MICP		= 95		# Mobile Internet Ctrl
196IP_PROTO_SCCSP		= 96		# Semaphore Comm Sec Proto
197IP_PROTO_ETHERIP	= 97		# Ethernet in IPv4
198IP_PROTO_ENCAP		= 98		# encapsulation header
199IP_PROTO_ANYENC		= 99		# private encryption scheme
200IP_PROTO_GMTP		= 100		# GMTP
201IP_PROTO_IFMP		= 101		# Ipsilon Flow Mgmt Proto
202IP_PROTO_PNNI		= 102		# PNNI over IP
203IP_PROTO_PIM		= 103		# Protocol Indep Multicast
204IP_PROTO_ARIS		= 104		# ARIS
205IP_PROTO_SCPS		= 105		# SCPS
206IP_PROTO_QNX		= 106		# QNX
207IP_PROTO_AN		= 107		# Active Networks
208IP_PROTO_IPCOMP		= 108		# IP Payload Compression
209IP_PROTO_SNP		= 109		# Sitara Networks Protocol
210IP_PROTO_COMPAQPEER	= 110		# Compaq Peer Protocol
211IP_PROTO_IPXIP		= 111		# IPX in IP
212IP_PROTO_VRRP		= 112		# Virtual Router Redundancy
213IP_PROTO_PGM		= 113		# PGM Reliable Transport
214IP_PROTO_ANY0HOP	= 114		# 0-hop protocol
215IP_PROTO_L2TP		= 115		# Layer 2 Tunneling Proto
216IP_PROTO_DDX		= 116		# D-II Data Exchange (DDX)
217IP_PROTO_IATP		= 117		# Interactive Agent Xfer
218IP_PROTO_STP		= 118		# Schedule Transfer Proto
219IP_PROTO_SRP		= 119		# SpectraLink Radio Proto
220IP_PROTO_UTI		= 120		# UTI
221IP_PROTO_SMP		= 121		# Simple Message Protocol
222IP_PROTO_SM		= 122		# SM
223IP_PROTO_PTP		= 123		# Performance Transparency
224IP_PROTO_ISIS		= 124		# ISIS over IPv4
225IP_PROTO_FIRE		= 125		# FIRE
226IP_PROTO_CRTP		= 126		# Combat Radio Transport
227IP_PROTO_CRUDP		= 127		# Combat Radio UDP
228IP_PROTO_SSCOPMCE	= 128		# SSCOPMCE
229IP_PROTO_IPLT		= 129		# IPLT
230IP_PROTO_SPS		= 130		# Secure Packet Shield
231IP_PROTO_PIPE		= 131		# Private IP Encap in IP
232IP_PROTO_SCTP		= 132		# Stream Ctrl Transmission
233IP_PROTO_FC		= 133		# Fibre Channel
234IP_PROTO_RSVPIGN	= 134		# RSVP-E2E-IGNORE
235IP_PROTO_RAW		= 255		# Raw IP packets
236IP_PROTO_RESERVED	= IP_PROTO_RAW	# Reserved
237IP_PROTO_MAX		= 255
238
239if __name__ == '__main__':
240    import unittest
241
242    class IPTestCase(unittest.TestCase):
243        def test_IP(self):
244            #pcap = dpkt.pcap.PcapDumper('/tmp/foo.pcap', linktype=14)
245            s = 'E\x00\x00"\x00\x00\x00\x00@\x11r\xc0\x01\x02\x03\x04\x01\x02\x03\x04\x00o\x00\xde\x00\x0e\xbf5foobar'
246            ip = IP(id=0, src='\x01\x02\x03\x04', dst='\x01\x02\x03\x04', p=17)
247            u = udp.UDP(sport=111, dport=222)
248            u.data = 'foobar'
249            u.ulen += len(u.data)
250            ip.data = u
251            ip.len += len(u)
252            self.failUnless(str(ip) == s)
253            #pcap.append(s)
254
255            ip = IP(s)
256            self.failUnless(str(ip) == s)
257            self.failUnless(ip.udp.sport == 111)
258            self.failUnless(ip.udp.data == 'foobar')
259
260    unittest.main()
261