Skip to content

Commit ec7e7eb

Browse files
committed
feat: implement pcap global header parsing
1 parent 4b6af1e commit ec7e7eb

2 files changed

Lines changed: 87 additions & 5 deletions

File tree

src/main.py

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,46 @@
11
import sys
2+
import click
23
from rich.console import Console
34
from rich.panel import Panel
5+
from rich.table import Table
6+
from pcap_reader import PcapReader
47

58
console = Console()
69

7-
def main():
10+
@click.command()
11+
@click.argument('filepath', required=False)
12+
def main(filepath):
813
welcome_message = Panel.fit(
914
"[bold blue]WireSpectra DPI Engine[/bold blue]\n"
1015
"[white]System Initialized[/white]",
1116
border_style="bright_magenta"
1217
)
1318
console.print(welcome_message)
14-
15-
console.print(f"[green]✔[/green] Python {sys.version.split()[0]} detected.")
16-
console.print("[yellow]![/yellow] Initializing project modules...")
17-
console.print("[green]✔[/green] Project structure ready.")
19+
20+
if not filepath:
21+
console.print("[yellow]Usage: python src/main.py <path_to_pcap>[/yellow]")
22+
return
23+
24+
reader = PcapReader()
25+
try:
26+
console.print(f"[*] Opening file: [cyan]{filepath}[/cyan]...")
27+
reader.open(filepath)
28+
29+
# Display Header Information in a nice table
30+
table = Table(title="PCAP Global Header")
31+
table.add_column("Field", style="cyan")
32+
table.add_column("Value", style="green")
33+
34+
table.add_row("Magic Number", hex(reader.magic_number))
35+
table.add_row("Version", f"{reader.version_major}.{reader.version_minor}")
36+
table.add_row("Snap Length", str(reader.snaplen))
37+
table.add_row("Network Type", "Ethernet (1)" if reader.network == 1 else str(reader.network))
38+
39+
console.print(table)
40+
reader.close()
41+
42+
except Exception as e:
43+
console.print(f"[bold red]Error:[/bold red] {str(e)}")
1844

1945
if __name__ == "__main__":
2046
main()

src/pcap_reader.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import struct
2+
import os
3+
4+
class PcapReader:
5+
def __init__(self):
6+
self.file = None
7+
self.magic_number = None
8+
self.version_major = None
9+
self.version_minor = None
10+
self.snaplen = None
11+
self.network = None
12+
13+
def open(self, filepath: str):
14+
"""
15+
Opens a PCAP file and parses the 24-byte global header.
16+
"""
17+
if not os.path.exists(filepath):
18+
raise FileNotFoundError(f"File not found: {filepath}")
19+
20+
self.file = open(filepath, 'rb')
21+
22+
# PCAP Global Header is exactly 24 bytes
23+
header_data = self.file.read(24)
24+
if len(header_data) < 24:
25+
self.file.close()
26+
raise ValueError("Invalid PCAP file: Global header too short")
27+
28+
# Unpack the 24 bytes using struct
29+
# I: uint32, H: uint16
30+
# < for little-endian (standard PCAP)
31+
(
32+
self.magic_number,
33+
self.version_major,
34+
self.version_minor,
35+
self.thiszone, # GMT to local correction (ignored)
36+
self.sigfigs, # Accuracy of timestamps (ignored)
37+
self.snaplen, # Max length of captured packets
38+
self.network # Data link type (1 = Ethernet)
39+
) = struct.unpack('<IHHIIII', header_data)
40+
41+
# Verify magic number (0xa1b2c3d4 is standard PCAP)
42+
if self.magic_number != 0xa1b2c3d4:
43+
# Check for big-endian version
44+
if self.magic_number == 0xd4c3b2a1:
45+
raise ValueError("Big-endian PCAP files not supported yet")
46+
raise ValueError(f"Not a valid PCAP file. Magic: {hex(self.magic_number)}")
47+
48+
return True
49+
50+
def close(self):
51+
if self.file:
52+
self.file.close()
53+
54+
def __repr__(self):
55+
return (f"PcapReader(Version={self.version_major}.{self.version_minor}, "
56+
f"Snaplen={self.snaplen}, Network={self.network})")

0 commit comments

Comments
 (0)