|
| 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