Skip to content
SeparateWings edited this page Jul 8, 2023 · 2 revisions

Introduction

I am going to show a small example how to parse PCAP files produced by Wireshark. The Format description I have found in the Wireshark wiki.

Source code

I have written a small class which takes a link to a PCAP file defined as the first command line argument and prints its inside content to console. The PCAP file can be saved in different byte orders so that I am made to check that outside of the parsing process and make selection of the right parsers based on the magic number byte order.

package com.igormaznitsa.parsepcap;

import com.igormaznitsa.jbbp.JBBPParser;
import com.igormaznitsa.jbbp.io.JBBPBitInputStream;
import com.igormaznitsa.jbbp.io.JBBPByteOrder;
import com.igormaznitsa.jbbp.mapper.Bin;
import com.igormaznitsa.jbbp.utils.JBBPUtils;
import java.io.FileInputStream;

public class PCAPParser {
  private static final JBBPParser PCAP_HEADER_LITTLE_ENDIAN = JBBPParser.prepare(
          "<short version_major;"
          + "<short version_minor;"
          + "<int thiszone;"
          + "<int sigfigs;"
          + "<int snaplen;"
          + "<int network;"
  );

  private static final JBBPParser PCAP_HEADER_BIG_ENDIAN = JBBPParser.prepare(
          "short version_major;"
          + "short version_minor;"
          + "int thiszone;"
          + "int sigfigs;"
          + "int snaplen;"
          + "int network;"
  );

  private static final JBBPParser PCAP_PACKET_LITTLE_ENDIAN = JBBPParser.prepare(
          "<int ts_sec;"
          + "<int ts_usec;"
          + "<int incl_len;"
          + "<int orig_len;"
          + "byte [incl_len] data;"
  );

  private static final JBBPParser PCAP_PACKET_BIG_ENDIAN = JBBPParser.prepare(
          "int ts_sec;"
          + "int ts_usec;"
          + "int incl_len;"
          + "int orig_len;"
          + "byte [incl_len] data;"
  );

  public static void main(final String ... args) throws Exception {
    @Bin class PcapHeader {
      short version_major;
      short version_minor;
      int thiszone;
      int sigfigs;
      int snaplen;
      int network;

      @Override
      public String toString() {
        return "Version "+version_major+'.'+version_minor+
                "\nGMT to local correction: "+thiszone+
                "\nAccuracy of timestamps: "+sigfigs+
                "\nMax length of captured packets, in octets: "+snaplen+
                "\nData link type: "+network;
      }
    }
    
    @Bin class PcapPacket {
      int ts_sec;
      int ts_usec;
      int incl_len;
      int orig_len;
      byte [] data;

      @Override
      public String toString() {
        return "Timestamp (s): "+Long.toString((long)ts_sec & 0xFFFFFFFFL)+", "+
               "Timestamp (us): " + Long.toString((long) ts_usec & 0xFFFFFFFFL) + ", " +
               "Length : " + incl_len + ", " +
               "Orig.Length : " + orig_len + ", "+JBBPUtils.array2hex(data);
      }
    }

    JBBPBitInputStream inStream = null;
    try{
      inStream = new JBBPBitInputStream(new FileInputStream(args[0]));
      final int magic = inStream.readInt(JBBPByteOrder.BIG_ENDIAN);
      
      final JBBPParser headerParser;
      final JBBPParser packetParser;
      switch(magic){
        case 0xA1B2C3D4:{
          // BIG ENDIAN ORDER
          headerParser = PCAP_HEADER_BIG_ENDIAN;
          packetParser = PCAP_PACKET_BIG_ENDIAN;
        }break;
        case 0xD4C3B2A1:{
          // LITTLE ENDIAN ORDER
          headerParser = PCAP_HEADER_LITTLE_ENDIAN;
          packetParser = PCAP_PACKET_LITTLE_ENDIAN;
        }break;
        default: throw new Exception("It is not a PCAP file");
      }
      
      final PcapHeader header = headerParser.parse(inStream).mapTo(PcapHeader.class);

      System.out.println("PCAP File\n----------------------\n"+header+"\n----------------------");
      
      int packetCounter = 0;
      
      while(inStream.hasAvailableData()){
        final PcapPacket packet = packetParser.parse(inStream).mapTo(PcapPacket.class);
        System.out.println(packet);
        packetCounter ++;
      }
      System.out.println("-------------------\nParsed "+packetCounter+" packet(s)");
      
    }finally{
      JBBPUtils.closeQuietly(inStream);
    }
  }
}
Clone this wiki locally