capfile 0.1.2

Pure Rust crate for reading/writing pcap/pcapng files with zero-copy parsing
Documentation

Capfile

Rust crates.io docs.rs License: Apache-2.0

A pure Rust crate for reading and writing pcap/pcapng capture files with zero-copy parsing and built-in packet dissection.

Features

  • Zero-copy parsing: Efficiently parse large capture files without unnecessary memory allocation
  • Both formats: Full support for legacy PCAP and modern PCAPNG formats
  • Packet dissection: Built-in dissection for Ethernet, IPv4, IPv6, TCP, UDP, ICMP, and DNS
  • Write support: Create new PCAP and PCAPNG capture files
  • Memory-mapped I/O: Fast reading using memory mapping

Quick Start

Reading a PCAP file

use capfile::PcapReader;

let mut reader = PcapReader::open("capture.pcap")?;

while let Some(pkt) = reader.next_packet()? {
    println!("{} bytes at {}", pkt.len(), pkt.timestamp_ns());
}

Reading from bytes

use capfile::PcapReader;
use std::io::Cursor;

let data = include_bytes!("capture.pcap");
let mut reader = PcapReader::from_reader(Cursor::new(data))?;

while let Some(pkt) = reader.next_packet()? {
    // Process packet
}

Reading a PCAPNG file

use capfile::PcapngReader;
use capfile::format::pcapng::Block;

let mut reader = PcapngReader::open("capture.pcapng")?;

// Get interface information
for (i, iface) in reader.interfaces().iter().enumerate() {
    println!("Interface {}: link_type={}, snap_len={}", i, iface.link_type, iface.snap_len);
}

// Iterate over blocks
while let Some(block) = reader.next_block()? {
    match block {
        Block::EnhancedPacket(epb) => {
            println!("Packet: {} bytes on interface {}", epb.captured_length, epb.interface_id);
        }
        Block::InterfaceStatistics(stats) => {
            println!("Stats: {} packets received", stats.packets_received);
        }
        _ => {}
    }
}

Packet Dissection

use capfile::{PcapReader, dissect::{Ethernet, Ipv4, Tcp}};

let mut reader = PcapReader::open("capture.pcap")?;

if let Some(pkt) = reader.next_packet()? {
    // Dissect Ethernet
    let eth = Ethernet::new(pkt.data())?;
    println!("{} -> {}", eth.src(), eth.dst());

    // Dissect IPv4
    let ip = Ipv4::new(eth.payload())?;
    println!("{} -> {}", ip.src_str(), ip.dst_str());

    // Dissect TCP
    if let Ok(tcp) = Tcp::new(ip.payload()) {
        println!("{} -> {}", tcp.src_port(), tcp.dst_port());
    }
}

Writing a PCAP file

use capfile::PcapWriter;

let mut writer = PcapWriter::create("output.pcap", 1)?; // Ethernet (link_type = 1)

// Write a packet (data, timestamp in ns, captured length)
writer.write_packet(b"packet data", 1_000_000_000, 14)?;

Writing a PCAPNG file

use capfile::PcapngWriter;

let mut writer = PcapngWriter::create("output.pcapng")?;

// Add an interface (returns interface ID)
let iface_id = writer.write_interface(1, 65535)?; // Ethernet, snap_len = 65535

// Write a packet
writer.write_packet(iface_id, b"packet data", 1_000_000_000, 14, 14)?;

Requirements

  • Rust 1.85 or later

License

Apache License 2.0 - see LICENSE for details.