mirror of https://github.com/dirtbags/netarch.git
Now handling ARP
This commit is contained in:
parent
297598b7de
commit
79daacd3ce
57
ip.py
57
ip.py
|
@ -11,13 +11,7 @@ import heapq
|
||||||
import gapstr
|
import gapstr
|
||||||
import time
|
import time
|
||||||
import UserDict
|
import UserDict
|
||||||
|
from __init__ import *
|
||||||
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:],)
|
|
||||||
|
|
||||||
def unpack_nybbles(byte):
|
def unpack_nybbles(byte):
|
||||||
return (byte >> 4, byte & 0x0F)
|
return (byte >> 4, byte & 0x0F)
|
||||||
|
@ -28,7 +22,7 @@ TCP = 6
|
||||||
UDP = 17
|
UDP = 17
|
||||||
|
|
||||||
class Frame:
|
class Frame:
|
||||||
"""Turn an ethernet frame into relevant TCP parts"""
|
"""Turn an ethernet frame into relevant parts"""
|
||||||
|
|
||||||
def __init__(self, pkt):
|
def __init__(self, pkt):
|
||||||
((self.time, _, _), frame) = pkt
|
((self.time, _, _), frame) = pkt
|
||||||
|
@ -38,9 +32,23 @@ class Frame:
|
||||||
self.eth_shost,
|
self.eth_shost,
|
||||||
self.eth_type,
|
self.eth_type,
|
||||||
p) = unpack('!6s6sH', frame)
|
p) = unpack('!6s6sH', frame)
|
||||||
if self.eth_type != 0x0800:
|
if self.eth_type == 0x0806:
|
||||||
raise ValueError('Not IP %04x' % self.eth_type)
|
# 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
|
# IP
|
||||||
(self.ihlvers,
|
(self.ihlvers,
|
||||||
self.tos,
|
self.tos,
|
||||||
|
@ -55,7 +63,7 @@ class Frame:
|
||||||
p) = unpack("!BBHHHBBHii", p)
|
p) = unpack("!BBHHHBBHii", p)
|
||||||
|
|
||||||
if self.protocol == TCP:
|
if self.protocol == TCP:
|
||||||
self.name = 'TCP'
|
self.name = 'TCP/IP'
|
||||||
(self.sport,
|
(self.sport,
|
||||||
self.dport,
|
self.dport,
|
||||||
self.seq,
|
self.seq,
|
||||||
|
@ -71,7 +79,7 @@ class Frame:
|
||||||
self.options, p = p[:opt_length - 20], p[opt_length - 20:]
|
self.options, p = p[:opt_length - 20], p[opt_length - 20:]
|
||||||
self.payload = p[:self.tot_len - opt_length - 20]
|
self.payload = p[:self.tot_len - opt_length - 20]
|
||||||
elif self.protocol == UDP:
|
elif self.protocol == UDP:
|
||||||
self.name = 'UDP'
|
self.name = 'UDP/IP'
|
||||||
(self.sport,
|
(self.sport,
|
||||||
self.dport,
|
self.dport,
|
||||||
self.ulen,
|
self.ulen,
|
||||||
|
@ -79,8 +87,8 @@ class Frame:
|
||||||
p) = unpack("!HHHH", p)
|
p) = unpack("!HHHH", p)
|
||||||
self.payload = p[:self.ulen - 8]
|
self.payload = p[:self.ulen - 8]
|
||||||
elif self.protocol == ICMP:
|
elif self.protocol == ICMP:
|
||||||
self.name = 'ICMP'
|
self.name = 'ICMP/IP'
|
||||||
self.sport = self.dport = -1
|
self.sport = self.dport = None
|
||||||
(self.type,
|
(self.type,
|
||||||
self.code,
|
self.code,
|
||||||
self.cheksum,
|
self.cheksum,
|
||||||
|
@ -89,14 +97,20 @@ class Frame:
|
||||||
p) = unpack('!BBHHH', p)
|
p) = unpack('!BBHHH', p)
|
||||||
self.payload = p[:self.tot_len - 8]
|
self.payload = p[:self.tot_len - 8]
|
||||||
else:
|
else:
|
||||||
raise ValueError('Unknown protocol')
|
self.name = 'IP Protocol %d' % self.protocol
|
||||||
|
self.sport = self.dport = None
|
||||||
|
self.payload = p
|
||||||
|
|
||||||
# Nice formatting
|
# Nice formatting
|
||||||
self.src = (self.saddr, self.sport)
|
self.src = (self.saddr, self.sport)
|
||||||
self.dst = (self.daddr, self.dport)
|
self.dst = (self.daddr, self.dport)
|
||||||
|
|
||||||
# This hash is the same for both sides of the transaction
|
# This hash is the same for both sides of the transaction
|
||||||
self.hash = (self.saddr ^ self.sport ^ self.daddr ^ self.dport)
|
self.hash = (self.saddr ^ (self.sport or 0)
|
||||||
|
^ self.daddr ^ (self.dport or 0))
|
||||||
|
else:
|
||||||
|
self.name = 'Ethernet type %d' % self.eth_type
|
||||||
|
|
||||||
|
|
||||||
def get_src_addr(self):
|
def get_src_addr(self):
|
||||||
saddr = struct.pack('!i', self.saddr)
|
saddr = struct.pack('!i', self.saddr)
|
||||||
|
@ -111,11 +125,18 @@ class Frame:
|
||||||
dst_addr = property(get_dst_addr)
|
dst_addr = property(get_dst_addr)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<Frame %s %s:%d -> %s:%d length %d>' % (self.name,
|
return '<Frame %s %s:%r -> %s:%r length %d>' % (self.name,
|
||||||
self.src_addr, self.sport,
|
self.src_addr, self.sport,
|
||||||
self.dst_addr, self.dport,
|
self.dst_addr, self.dport,
|
||||||
len(self.payload))
|
len(self.payload))
|
||||||
|
|
||||||
|
def __arp_repr__(self):
|
||||||
|
return '<Frame %s %s(%s) -> %s(%s)>' % (self.name,
|
||||||
|
self.ar_sha.encode('hex'),
|
||||||
|
self.src_addr,
|
||||||
|
self.ar_tha.encode('hex'),
|
||||||
|
self.dst_addr)
|
||||||
|
|
||||||
|
|
||||||
class Chunk:
|
class Chunk:
|
||||||
"""Chunk of frames, possibly with gaps.
|
"""Chunk of frames, possibly with gaps.
|
||||||
|
|
Loading…
Reference in New Issue