PcapFileEx (pcap_file_ex v0.5.5)

View Source

Elixir wrapper for parsing PCAP and PCAPNG network capture files.

This library provides functionality to read packet capture files commonly used with tools like Wireshark, tcpdump, and dumpcap.

Modules

Examples

# Open and read a PCAP file (format auto-detected)
{:ok, reader} = PcapFileEx.open("capture.pcap")

# Read all packets at once
{:ok, packets} = PcapFileEx.read_all("capture.pcap")

# Stream packets lazily (memory efficient for large files)
PcapFileEx.stream("capture.pcap")
|> Stream.filter(fn packet -> byte_size(packet.data) > 1000 end)
|> Enum.take(10)

# Compute statistics
{:ok, stats} = PcapFileEx.Stats.compute("capture.pcap")
IO.inspect(stats.packet_count)

# Filter packets
PcapFileEx.stream("capture.pcap")
|> PcapFileEx.Filter.by_size(100..1500)
|> PcapFileEx.Filter.larger_than(500)
|> Enum.to_list()

# Validate file
{:ok, :pcap} = PcapFileEx.Validator.validate("capture.pcap")

Summary

Functions

Copies a PCAP/PCAPNG file to a new location, optionally converting format.

Exports filtered packets to a new file.

Exports filtered packets to a new file, raising on error.

Opens a PCAP or PCAPNG file for reading with automatic format detection.

Reads all packets from a PCAP or PCAPNG file with automatic format detection.

Creates a lazy stream of packets from a PCAP or PCAPNG file with automatic format detection.

Creates a lazy stream of packets, raising on errors.

Writes packets to a PCAP or PCAPNG file.

Writes packets to a file, raising on error.

Functions

copy(source_path, dest_path, opts \\ [])

@spec copy(Path.t(), Path.t(), keyword()) ::
  {:ok, non_neg_integer()} | {:error, String.t()}

Copies a PCAP/PCAPNG file to a new location, optionally converting format.

Parameters

  • source_path - Input file path
  • dest_path - Output file path

Options

  • :format - Output format (:pcap or :pcapng, default: auto-detect from extension)
  • :on_error - How to handle read errors (:halt or :skip, default: :halt)

Returns

  • {:ok, count} - Number of packets copied
  • {:error, reason} - Copy failed

Examples

# Simple copy
{:ok, 1000} = PcapFileEx.copy("input.pcap", "output.pcap")

# Convert PCAP to PCAPNG
{:ok, 1000} = PcapFileEx.copy("input.pcap", "output.pcapng")

# Skip corrupt packets
{:ok, 995} = PcapFileEx.copy("input.pcap", "output.pcap", on_error: :skip)

export_filtered(source_path, dest_path, filter_fun, opts \\ [])

@spec export_filtered(
  Path.t(),
  Path.t(),
  (PcapFileEx.Packet.t() -> boolean()),
  keyword()
) ::
  {:ok, non_neg_integer()} | {:error, String.t()}

Exports filtered packets to a new file.

Convenience function that combines filtering and writing.

Parameters

  • source_path - Input file path
  • dest_path - Output file path
  • filter_fun - Function to filter packets (packet -> boolean)

Options

  • :format - Output format (:pcap or :pcapng, default: auto-detect)
  • :on_error - How to handle read errors (:halt or :skip, default: :halt)

Returns

  • {:ok, count} - Number of packets exported
  • {:error, reason} - Export failed

Examples

# Export only large packets
filter = fn packet -> byte_size(packet.data) > 1000 end
{:ok, 50} = PcapFileEx.export_filtered("input.pcap", "large.pcap", filter)

# Export HTTP traffic
filter = fn packet -> packet.protocol == :http end
{:ok, 100} = PcapFileEx.export_filtered("input.pcap", "http.pcap", filter)

export_filtered!(source_path, dest_path, filter_fun, opts \\ [])

@spec export_filtered!(
  Path.t(),
  Path.t(),
  (PcapFileEx.Packet.t() -> boolean()),
  keyword()
) ::
  non_neg_integer()

Exports filtered packets to a new file, raising on error.

See export_filtered/4 for details.

open(path)

@spec open(Path.t()) ::
  {:ok, PcapFileEx.Pcap.t() | PcapFileEx.PcapNg.t()} | {:error, String.t()}

Opens a PCAP or PCAPNG file for reading with automatic format detection.

This function reads the file's magic number to determine whether it's a PCAP or PCAPNG file and opens it with the appropriate reader.

Examples

{:ok, reader} = PcapFileEx.open("capture.pcap")
{:ok, reader} = PcapFileEx.open("capture.pcapng")

Returns

  • {:ok, reader} - A reader struct (either Pcap.t() or PcapNg.t())
  • {:error, reason} - If the file cannot be opened or has an unknown format

read_all(path, opts \\ [])

@spec read_all(
  Path.t(),
  keyword()
) :: {:ok, [PcapFileEx.Packet.t()]} | {:error, String.t()}

Reads all packets from a PCAP or PCAPNG file with automatic format detection.

Warning: This loads all packets into memory. For large files, use stream/1 instead.

Options

  • :decode - If true (default), attaches decoded protocol information to each packet
  • :hosts_map - Map of IP address strings to hostname strings for endpoint resolution

Examples

{:ok, packets} = PcapFileEx.read_all("capture.pcap")
{:ok, packets} = PcapFileEx.read_all("capture.pcapng")

# With hosts mapping
hosts = %{"192.168.1.1" => "gateway", "10.0.0.1" => "server"}
{:ok, packets} = PcapFileEx.read_all("capture.pcap", hosts_map: hosts)

stream(path, opts \\ [])

@spec stream(
  Path.t(),
  keyword()
) :: {:ok, Enumerable.t()} | {:error, String.t()}

Creates a lazy stream of packets from a PCAP or PCAPNG file with automatic format detection.

This is memory efficient for large files as packets are read on demand. The file is automatically opened and closed.

Returns {:ok, stream} on success or {:error, reason} if the file format cannot be detected or the file cannot be opened.

Options

  • :decode - If true (default), attaches decoded protocol information to each packet
  • :hosts_map - Map of IP address strings to hostname strings for endpoint resolution

Examples

{:ok, stream} = PcapFileEx.stream("capture.pcap")
stream
|> Stream.filter(fn packet -> byte_size(packet.data) > 100 end)
|> Enum.count()

# Handle errors
case PcapFileEx.stream("capture.pcapng") do
  {:ok, stream} -> stream |> Enum.take(10)
  {:error, msg} -> IO.puts("Error: #{msg}")
end

# With hosts mapping
hosts = %{"192.168.1.1" => "gateway", "10.0.0.1" => "server"}
{:ok, stream} = PcapFileEx.stream("capture.pcap", hosts_map: hosts)

Migration from 0.1.x

In version 0.1.x, this function raised on errors. Use stream!/2 for the old behavior:

# Old (0.1.x)
stream = PcapFileEx.stream("capture.pcap")

# New (0.2.0) - option 1: handle errors
{:ok, stream} = PcapFileEx.stream("capture.pcap")

# New (0.2.0) - option 2: use bang variant
stream = PcapFileEx.stream!("capture.pcap")

stream!(path, opts \\ [])

@spec stream!(
  Path.t(),
  keyword()
) :: Enumerable.t()

Creates a lazy stream of packets, raising on errors.

This is the old behavior from version 0.1.x.

The returned stream emits bare packets (not tagged tuples) and raises on mid-stream errors.

Examples

PcapFileEx.stream!("capture.pcap")
|> Stream.filter(fn packet -> byte_size(packet.data) > 100 end)
|> Enum.count()

write(path, header_or_nil, packets, opts \\ [])

@spec write(Path.t(), PcapFileEx.Header.t() | nil, Enumerable.t(), keyword()) ::
  {:ok, non_neg_integer()} | {:error, String.t()}

Writes packets to a PCAP or PCAPNG file.

Format is determined by file extension (.pcap or .pcapng).

Parameters

  • path - Output file path
  • header - PCAP header (for .pcap files)
  • packets - Enumerable of packets

Options

  • :format - Override format detection (:pcap or :pcapng)
  • :interfaces - Required for PCAPNG format (list of Interface structs)
  • :endianness - For PCAPNG files ("big" or "little", default: "little")

Returns

  • {:ok, count} - Number of packets written
  • {:error, reason} - Write failed

Examples

# Write PCAP file
header = %PcapFileEx.Header{...}
{:ok, 100} = PcapFileEx.write("output.pcap", header, packets)

# Write PCAPNG file
interfaces = [%PcapFileEx.Interface{...}]
{:ok, 100} = PcapFileEx.write("output.pcapng", nil, packets, interfaces: interfaces)

write!(path, header_or_nil, packets, opts \\ [])

@spec write!(Path.t(), PcapFileEx.Header.t() | nil, Enumerable.t(), keyword()) ::
  non_neg_integer()

Writes packets to a file, raising on error.

See write/4 for details.