""" Packet read and write routines for pcap format. See http://wiki.wireshark.org/Development/LibpcapFileFormat """ import sys import logging import struct from pypacker import pypacker # avoid unneeded references for performance reasons unpack = struct.unpack logger = logging.getLogger("pypacker") # File magic numbers # pcap using microseconds resolution TCPDUMP_MAGIC = 0xa1b2c3d4 TCPDUMP_MAGIC_SWAPPED = 0xd4c3b2a1 # pcap using nanoseconds resolution TCPDUMP_MAGIC_NANO = 0xa1b23c4d TCPDUMP_MAGIC_NANO_SWAPPED = 0x4d3cb2a1 PCAP_VERSION_MAJOR = 2 PCAP_VERSION_MINOR = 4 DLT_NULL = 0 DLT_EN10MB = 1 DLT_EN3MB = 2 DLT_AX25 = 3 DLT_PRONET = 4 DLT_CHAOS = 5 DLT_IEEE802 = 6 DLT_ARCNET = 7 DLT_SLIP = 8 DLT_PPP = 9 DLT_FDDI = 10 DLT_PFSYNC = 18 DLT_IEEE802_11 = 105 DLT_LINUX_SLL = 113 DLT_PFLOG = 117 DLT_IEEE802_11_RADIO = 127 _MODE_BYTES = 0 _MODE_PACKETS = 1 if sys.platform.find("openbsd") != -1: DLT_LOOP = 12 DLT_RAW = 14 else: DLT_LOOP = 108 DLT_RAW = 12 # retrieve via: FileHdr.linktype dltoff = { DLT_NULL : 4, DLT_EN10MB : 14, DLT_IEEE802 : 22, DLT_ARCNET : 6, DLT_SLIP : 16, DLT_PPP : 4, DLT_FDDI : 21, DLT_PFLOG : 48, DLT_PFSYNC : 4, DLT_LOOP : 4, DLT_LINUX_SLL : 16 } class FileHdr(pypacker.Packet): """pcap file header.""" # header length = 24 __hdr__ = ( ("magic", "I", TCPDUMP_MAGIC), ("v_major", "H", PCAP_VERSION_MAJOR), ("v_minor", "H", PCAP_VERSION_MINOR), ("thiszone", "I", 0), ("sigfigs", "I", 0), ("snaplen", "I", 1500), ("linktype", "I", 1), ) class LEFileHdr(pypacker.Packet): """pcap file header.""" # header length = 24 __hdr__ = ( ("magic", "I", TCPDUMP_MAGIC), ("v_major", "H", PCAP_VERSION_MAJOR), ("v_minor", "H", PCAP_VERSION_MINOR), ("thiszone", "I", 0), ("sigfigs", "I", 0), ("snaplen", "I", 1500), ("linktype", "I", 1), ) __byte_order__ = "<" class PktHdr(pypacker.Packet): """pcap packet header.""" # header length: 16 __hdr__ = ( ("tv_sec", "I", 0), # this can be either microseconds or nanoseconds: check magic number ("tv_usec", "I", 0), ("caplen", "I", 0), ("len", "I", 0), ) class LEPktHdr(pypacker.Packet): """pcap packet header.""" # header length: 16 __hdr__ = ( ("tv_sec", "I", 0), # this can be either microseconds or nanoseconds: check magic number ("tv_usec", "I", 0), ("caplen", "I", 0), ("len", "I", 0), ) __byte_order__ = "<" class Writer(object): """ Simple pcap writer supporting pcap format. Note: this will use nanosecond timestamp resolution. """ def __init__(self, fileobj=None, filename=None, snaplen=1500, linktype=DLT_EN10MB): """ fileobj -- create a pcap-writer giving a file object retrieved by open(..., "wb") filename -- create a pcap-writer giving a file pcap filename """ # handle source modes if fileobj is not None: self.__fh = fileobj elif filename is not None: self.__fh = open(filename, "wb") else: raise Exception("No fileobject and no filename given..nothing to read!!!") fh = FileHdr(magic=TCPDUMP_MAGIC_NANO, snaplen=snaplen, linktype=linktype) logger.debug("writing fileheader %r" % fh) self.__fh.write(fh.bin()) self._timestamp = 0 def write(self, bts, ts=None): """ Write the given packet's bytes to file. bts -- bytes to be written ts -- timestamp in Nanoseconds """ # split timestamp into seconds, nanoseconds if ts is None: sec = self._timestamp // 1000000000 nsec = int(self._timestamp - (sec * 1000000000)) self._timestamp += 1000000 else: sec = int(ts / 1000000000) nsec = ts - (sec * 1000000000) # logger.debug("paket time sec/nsec: %d/%d" % (sec, nsec)) n = len(bts) ph = PktHdr(tv_sec=sec, tv_usec=nsec, caplen=n, len=n) # logger.debug("writing packet header + packet data") self.__fh.write(ph.bin()) self.__fh.write(bts) def close(self): self.__fh.close() _struct_preheader_be = struct.Struct(">IIII") _struct_preheader_le = struct.Struct("