Parsing ERF capture files in python

What is the best way to parse ERF (endace) capture files in python? I found libpcap shell for python, but I don't think lipcap supports ERF format.

Thank!

+3
source share
2 answers

Here is a simple ERF record parser that returns a dict on a package (I just cracked it together, so it's not very well tested. Not all flag fields are decoded, but those that are not are widely used):

Note:

  • ERF record types: 1 = HDLC, 2 = Ethernet, 3 = ATM, 4 = AAL5 reassembled, 5-7 multi-channel options with additional headers that are not processed here.
  • rlenmay be shorter wlen+len(header)if the snap length is too short.
  • - , , Dag .
  • scapy , scapy.

:

import scapy.layers.all as sl

def erf_records( f ):
    """
    Generator which parses ERF records from file-like ``f``
    """
    while True:
        # The ERF header is fixed length 16 bytes
        hdr = f.read( 16 )
        if hdr:
            rec = {}
            # The timestamp is in Intel byte-order
            rec['ts'] = struct.unpack( '<Q', hdr[:8] )[0]
            # The rest is in network byte-order
            rec.update( zip( ('type',  # ERF record type
                              'flags', # Raw flags bit field
                              'rlen',  # Length of entire record
                              'lctr',  # Interstitial loss counter
                              'wlen'), # Length of packet on wire
                             struct.unpack( '>BBHHH', hdr[8:] ) ) )
            rec['iface']  = rec['flags'] & 0x03
            rec['rx_err'] = rec['flags'] & 0x10 != 0
            rec['pkt'] = f.read( rec['rlen'] - 16 )
            if rec['type'] == 2:
                # ERF Ethernet has an extra two bytes of pad between ERF header
                # and beginning of MAC header so that IP-layer data are DWORD
                # aligned.  From memory, none of the other types have pad.
                rec['pkt'] = rec['pkt'][2:]
                rec['pkt'] = sl.Ether( rec['pkt'] )
            yield rec
        else:
            return
+3

ERF , 16- ERF. "type" . strix . , Ethernet , .

. , ERF , , . , , , .

import struct
import scapy.layers.all as sl

def erf_records( f ):
    """
    Generator which parses ERF records from file-like ``f``
    """
    while True:
        # The ERF header is fixed length 16 bytes
        hdr = f.read( 16 )
        if hdr:
            rec = {}
            # The timestamp is in Intel byte-order
            rec['ts'] = struct.unpack( '<Q', hdr[:8] )[0]
            # The rest is in network byte-order
            rec.update( zip( ('type',  # ERF record type
                              'flags', # Raw flags bit field
                              'rlen',  # Length of entire record
                              'lctr',  # Interstitial loss counter
                              'wlen'), # Length of packet on wire
                             struct.unpack( '>BBHHH', hdr[8:] ) ) )
            rec['iface']  = rec['flags'] & 0x03
            rec['rx_err'] = rec['flags'] & 0x10 != 0

            #- Check if ERF Extension Header present.  
            #  Each Extension Header is 8 bytes.
            if rec['type'] & 0x80:
                ext_hdr = f.read( 8 )
                rec.update( zip( (
                        'ext_hdr_signature',     # 1 byte
                        'ext_hdr_payload_hash',  # 3 bytes
                        'ext_hdr_filter_color',  # 1 bye
                        'ext_hdr_flow_hash'),    # 3 bytes
                        struct.unpack( '>B3sB3s', ext_hdr ) ) )
                #- get remaining payload, less ext_hdr
                rec['pkt'] = f.read( rec['rlen'] - 24 )
            else:
                rec['pkt'] = f.read( rec['rlen'] - 16 )
            if rec['type'] & 0x02:
                # ERF Ethernet has an extra two bytes of pad between ERF header
                # and beginning of MAC header so that IP-layer data are DWORD
                # aligned.  From memory, none of the other types have pad.
                rec['pkt'] = rec['pkt'][2:]
                rec['pkt'] = sl.Ether( rec['pkt'] )
            yield rec
        else:
            return
+2

All Articles