1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
|
# Copyright (c) 2005, Neville-Neil Consulting
#
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# Neither the name of Neville-Neil Consulting nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# File: $Id: ipv4.py,v 1.6 2006/09/05 07:30:56 gnn Exp $
#
# Author: George V. Neville-Neil
#
# Description: A class which implements an IPv4 packet
import pcs
from socket import AF_INET, IPPROTO_UDP, IPPROTO_TCP, IPPROTO_AH, IPPROTO_ESP, IPPROTO_ICMP, inet_ntop
import udp, tcp, icmpv4
import struct
class ipv4(pcs.Packet):
layout = pcs.Layout()
def __init__(self, bytes = None):
""" define the fields of an IPv4 packet, from RFC 791
This version does not include options."""
version = pcs.Field("version", 4, default = 4)
hlen = pcs.Field("hlen", 4)
tos = pcs.Field("tos", 8)
length = pcs.Field("length", 16)
id = pcs.Field("id", 16)
flags = pcs.Field("flags", 3)
offset = pcs.Field("offset", 13)
ttl = pcs.Field("ttl", 8, default = 64)
protocol = pcs.Field("protocol", 8)
checksum = pcs.Field("checksum", 16)
src = pcs.Field("src", 32)
dst = pcs.Field("dst", 32)
pcs.Packet.__init__(self,
[version, hlen, tos, length, id, flags, offset,
ttl, protocol, checksum, src, dst],
bytes = bytes)
# Description MUST be set after the PCS layer init
self.description = "IPv4"
if (bytes != None):
offset = self.hlen << 2
self.data = self.next(bytes[offset:len(bytes)])
else:
self.data = None
def __str__(self):
"""Walk the entire packet and pretty print the values of the fields."""
retval = "IPv4\n"
for field in self.layout:
if (field.name == "src" or field.name == "dst"):
value = inet_ntop(AF_INET,
struct.pack('!L', self.__dict__[field.name]))
retval += "%s %s\n" % (field.name, value)
else:
retval += "%s %s\n" % (field.name, self.__dict__[field.name])
return retval
def next(self, bytes):
"""Decode the type of a packet and return the correct higher
level protocol object"""
## the protocol above IP, such as ICMP, UDP, TCP, AH, ESP etc.
if self.protocol == IPPROTO_UDP:
return udp.udp(bytes)
elif self.protocol == IPPROTO_TCP:
return tcp.tcp(bytes)
elif self.protocol == IPPROTO_AH:
return ipsec.ah(bytes)
elif self.protocol == IPPROTO_ESP:
return ipsec.esp(bytes)
elif self.protocol == IPPROTO_ICMP:
return icmpv4.icmpv4(bytes)
# Fall through
return None
def calc_checksum(self):
"""calculate the IPv4 checksum over a packet
returns the calculated checksum
"""
total = 0
packet = ipv4(self.bytes)
packet.checksum = 0
bytes = packet.bytes
if len(bytes) % 2 == 1:
bytes += "\0"
for i in range(len(bytes)/2):
total += (struct.unpack("!H", bytes[2*i:2*i+2])[0])
total = (total >> 16) + (total & 0xffff)
total += total >> 16
return ~total
|