Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pcapfile/protocols/ethernet/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

51 changes: 51 additions & 0 deletions pcapfile/protocols/ethernet/dot1q.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""
802.1Q (dot1Q) encapsulation
"""

import ctypes
import struct
from pcapfile.protocols.linklayer import ethernet

class Dot1q(ctypes.Structure):
_fields_ = [('priority', ctypes.c_ubyte), # Priority
('cfi', ctypes.c_ubyte), # CFI
('id', ctypes.c_ushort), # VLAN ID
('etype', ctypes.c_ushort)] # Ethertype

def __init__(self, packet, layers=0):

fields = struct.unpack('!HH', packet[:4])

self.priority = fields[0] >> 13
self.cfi = (fields[0] >> 12) & 0b0001
self.id = fields[0] & 0b0000111111111111
self.type = fields[1]
self.payload = packet[4:]

if layers:
self.load_network(layers)

def load_network(self, layers=1):
"""
Given an Ethernet frame, determine the appropriate sub-protocol;
If layers is greater than zerol determine the type of the payload
and load the appropriate type of network packet. It is expected
that the payload be a hexified string. The layers argument determines
how many layers to descend while parsing the packet.
"""
if layers:
ctor = ethernet.payload_type(self.type)[0]
if ctor:
ctor = ctor
# payload = binascii.unhexlify(self.payload)
self.payload = ctor(self.payload, layers - 1)
else:
# if no type is found, do not touch the packet.
pass

def __str__(self):
packet = '802.1Q packet VLAN %d PRI %d CFI %d' % (self.id, self.priority, self.cfi)
return packet

def __call__(packet):
return Dot1q(packet)
22 changes: 13 additions & 9 deletions pcapfile/protocols/linklayer/ethernet.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
IP protocol definitions.
Ethernet protocol definitions.
"""

import binascii
Expand All @@ -26,8 +26,9 @@ def __init__(self, packet, layers=0):
self.dst = b':'.join([('%02x' % o).encode('ascii') for o in dst])
self.src = b':'.join([('%02x' % o).encode('ascii') for o in src])

payload = binascii.hexlify(packet[14:])
self.payload = payload
# payload = binascii.hexlify(packet[14:])
# self.payload = payload
self.payload = packet[14:]

if layers:
self.load_network(layers)
Expand All @@ -44,8 +45,8 @@ def load_network(self, layers=1):
ctor = payload_type(self.type)[0]
if ctor:
ctor = ctor
payload = binascii.unhexlify(self.payload)
self.payload = ctor(payload, layers - 1)
# payload = binascii.unhexlify(self.payload)
self.payload = ctor(self.payload, layers - 1)
else:
# if no type is found, do not touch the packet.
pass
Expand Down Expand Up @@ -77,14 +78,17 @@ def payload_type(ethertype):
if ethertype == 0x0800:
from pcapfile.protocols.network.ip import IP
return (IP, 'IPv4')
# elif ethertype == 0x0806:
# from pcapfile.protocols.network.arp import ARP
# return (ARP, 'ARP')
elif ethertype == 0x8100:
from pcapfile.protocols.ethernet.dot1q import Dot1q
return (Dot1q, '802.1Q')
elif ethertype == 0x0806:
from pcapfile.protocols.network.arp import ARP
return (ARP, 'ARP')
# elif ethertype == 0x0835:
# from pcapfile.protocols.network.rarp import RARP
# return (RARP, 'RARP')
# elif ethertype == 0x08DD:
# from pcapfile.protocols.network.ipv6 import IPv6
# return (IPv6, 'IPv6')
else:
return (None, 'unknown')
return (None, "0x%04x" % (ethertype))
44 changes: 44 additions & 0 deletions pcapfile/protocols/network/arp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""
IPv4 Address Resultion Protocol (ARP)
"""

import ctypes
import struct

class ARP(ctypes.Structure):
_fields_ = [('hw_type', ctypes.c_ushort), # Hardware Type
('proto', ctypes.c_ushort), # Protocol Type
('hw_size', ctypes.c_ubyte), # Hardware size
('proto_size', ctypes.c_ubyte), # Protocol size
('opcode', ctypes.c_ushort), # Opcode
('src_mac', ctypes.c_char_p), # Source MAC address
('src_ip', ctypes.c_char_p), # Source IP address
('dst_mac', ctypes.c_char_p), # Target MAC address
('dst_ip', ctypes.c_char_p)] # Target IP address

def __init__(self, packet, layers=0):

fields = struct.unpack('!HHBBH6s4s6s4s', packet[:28])

self.hw_type = fields[0]
self.proto = fields[1]
self.hw_size = fields[2]
self.proto_size = fields[3]
self.opcode = fields[4]
self.src_mac = ctypes.c_char_p(parse_mac(fields[5]))
self.src_ip = ctypes.c_char_p(parse_ip(fields[6]))
self.dst_mac = ctypes.c_char_p(parse_mac(fields[7]))
self.dst_ip = ctypes.c_char_p(parse_ip(fields[8]))

def parse_mac(mac):
mac = bytearray(mac)
mac = b':'.join([('%02x' % o).encode('ascii') for o in mac])
return mac

def parse_ip(octets):
ipv4 = b'.'.join([('%d' % o).encode('ascii') for o in bytearray(octets)])
return ipv4

def __call__(packet):
return ARP(packet)