diff --git a/ip.py b/ip.py
index 6641a23..da608da 100755
--- a/ip.py
+++ b/ip.py
@@ -11,13 +11,7 @@ import heapq
import gapstr
import time
import UserDict
-
-def unpack(fmt, buf):
- """Unpack buf based on fmt, assuming the rest is a string."""
-
- size = struct.calcsize(fmt)
- vals = struct.unpack(fmt, buf[:size])
- return vals + (buf[size:],)
+from __init__ import *
def unpack_nybbles(byte):
return (byte >> 4, byte & 0x0F)
@@ -28,7 +22,7 @@ TCP = 6
UDP = 17
class Frame:
- """Turn an ethernet frame into relevant TCP parts"""
+ """Turn an ethernet frame into relevant parts"""
def __init__(self, pkt):
((self.time, _, _), frame) = pkt
@@ -38,65 +32,85 @@ class Frame:
self.eth_shost,
self.eth_type,
p) = unpack('!6s6sH', frame)
- if self.eth_type != 0x0800:
- raise ValueError('Not IP %04x' % self.eth_type)
-
- # IP
- (self.ihlvers,
- self.tos,
- self.tot_len,
- self.id,
- self.frag_off,
- self.ttl,
- self.protocol,
- self.check,
- self.saddr,
- self.daddr,
- p) = unpack("!BBHHHBBHii", p)
-
- if self.protocol == TCP:
- self.name = 'TCP'
- (self.sport,
- self.dport,
- self.seq,
- self.ack,
- x2off,
- self.flags,
- self.win,
- self.sum,
- self.urp,
- p) = unpack("!HHLLBBHHH", p)
- (self.off, th_x2) = unpack_nybbles(x2off)
- opt_length = self.off * 4
- self.options, p = p[:opt_length - 20], p[opt_length - 20:]
- self.payload = p[:self.tot_len - opt_length - 20]
- elif self.protocol == UDP:
- self.name = 'UDP'
- (self.sport,
- self.dport,
- self.ulen,
- self.sum,
- p) = unpack("!HHHH", p)
- self.payload = p[:self.ulen - 8]
- elif self.protocol == ICMP:
- self.name = 'ICMP'
- self.sport = self.dport = -1
- (self.type,
- self.code,
- self.cheksum,
+ if self.eth_type == 0x0806:
+ # ARP
+ self.name = 'ARP'
+ (self.ar_hrd,
+ self.ar_pro,
+ self.ar_hln,
+ self.ar_pln,
+ self.ar_op,
+ self.ar_sha,
+ self.ar_sip,
+ self.ar_tha,
+ self.ar_tip,
+ p) = unpack('!HHBBH6si6si', p)
+ self.saddr = self.ar_sip
+ self.daddr = self.ar_tip
+ self.__repr__ = self.__arp_repr__
+ elif self.eth_type == 0x0800:
+ # IP
+ (self.ihlvers,
+ self.tos,
+ self.tot_len,
self.id,
- self.seq,
- p) = unpack('!BBHHH', p)
- self.payload = p[:self.tot_len - 8]
+ self.frag_off,
+ self.ttl,
+ self.protocol,
+ self.check,
+ self.saddr,
+ self.daddr,
+ p) = unpack("!BBHHHBBHii", p)
+
+ if self.protocol == TCP:
+ self.name = 'TCP/IP'
+ (self.sport,
+ self.dport,
+ self.seq,
+ self.ack,
+ x2off,
+ self.flags,
+ self.win,
+ self.sum,
+ self.urp,
+ p) = unpack("!HHLLBBHHH", p)
+ (self.off, th_x2) = unpack_nybbles(x2off)
+ opt_length = self.off * 4
+ self.options, p = p[:opt_length - 20], p[opt_length - 20:]
+ self.payload = p[:self.tot_len - opt_length - 20]
+ elif self.protocol == UDP:
+ self.name = 'UDP/IP'
+ (self.sport,
+ self.dport,
+ self.ulen,
+ self.sum,
+ p) = unpack("!HHHH", p)
+ self.payload = p[:self.ulen - 8]
+ elif self.protocol == ICMP:
+ self.name = 'ICMP/IP'
+ self.sport = self.dport = None
+ (self.type,
+ self.code,
+ self.cheksum,
+ self.id,
+ self.seq,
+ p) = unpack('!BBHHH', p)
+ self.payload = p[:self.tot_len - 8]
+ else:
+ self.name = 'IP Protocol %d' % self.protocol
+ self.sport = self.dport = None
+ self.payload = p
+
+ # Nice formatting
+ self.src = (self.saddr, self.sport)
+ self.dst = (self.daddr, self.dport)
+
+ # This hash is the same for both sides of the transaction
+ self.hash = (self.saddr ^ (self.sport or 0)
+ ^ self.daddr ^ (self.dport or 0))
else:
- raise ValueError('Unknown protocol')
+ self.name = 'Ethernet type %d' % self.eth_type
- # Nice formatting
- self.src = (self.saddr, self.sport)
- self.dst = (self.daddr, self.dport)
-
- # This hash is the same for both sides of the transaction
- self.hash = (self.saddr ^ self.sport ^ self.daddr ^ self.dport)
def get_src_addr(self):
saddr = struct.pack('!i', self.saddr)
@@ -111,11 +125,18 @@ class Frame:
dst_addr = property(get_dst_addr)
def __repr__(self):
- return ' %s:%d length %d>' % (self.name,
+ return ' %s:%r length %d>' % (self.name,
self.src_addr, self.sport,
self.dst_addr, self.dport,
len(self.payload))
+ def __arp_repr__(self):
+ return ' %s(%s)>' % (self.name,
+ self.ar_sha.encode('hex'),
+ self.src_addr,
+ self.ar_tha.encode('hex'),
+ self.dst_addr)
+
class Chunk:
"""Chunk of frames, possibly with gaps.