Changeset 872:fa66f778ed74

Show
Ignore:
Timestamp:
08/16/08 14:37:28 (5 months ago)
Author:
Phil <phil@secdev.org>
Message:

Extracted raw pcap file reader/writer from PcapReader/PcapWriter?

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • scapy/utils.py

    r866 r872  
    1111from arch import * 
    1212from error import log_runtime 
     13from base_classes import BasePacketList 
    1314 
    1415 
     
    454455    return PcapReader(filename).read_all(count=count) 
    455456 
    456 class PcapReader: 
    457     """A stateful pcap reader 
    458      
    459     Based entirely on scapy.rdpcap(), this class allows for packets 
    460     to be dispatched without having to be loaded into memory all at 
    461     once 
    462     """ 
     457 
     458 
     459class RawPcapReader: 
     460    """A stateful pcap reader. Each packet is returned as a string""" 
    463461 
    464462    def __init__(self, filename): 
     
    480478            raise RuntimeWarning, "Invalid pcap file (too short)" 
    481479        vermaj,vermin,tz,sig,snaplen,linktype = struct.unpack(self.endian+"HHIIII",hdr) 
    482         self.LLcls = conf.l2types.get(linktype, Raw) 
    483         if self.LLcls == Raw: 
    484             warning("PcapReader: unkonwon LL type [%i]/[%#x]. Using Raw packets" % (linktype,linktype)) 
     480 
     481        self.linktype = linktype 
     482 
     483 
    485484 
    486485    def __iter__(self): 
     
    488487 
    489488    def next(self): 
    490         """impliment the iterator protocol on a set of packets in a 
    491         pcap file 
    492         """ 
     489        """impliment the iterator protocol on a set of packets in a pcap file""" 
    493490        pkt = self.read_packet() 
    494491        if pkt == None: 
     
    505502        if len(hdr) < 16: 
    506503            return None 
    507         sec,usec,caplen,olen = struct.unpack(self.endian+"IIII", hdr) 
     504        sec,usec,caplen,wirelen = struct.unpack(self.endian+"IIII", hdr) 
    508505        s = self.f.read(caplen) 
     506        return s,(sec,usec,wirelen) # caplen = len(s) 
     507 
     508 
     509    def dispatch(self, callback): 
     510        """call the specified callback routine for each packet read 
     511         
     512        This is just a convienience function for the main loop 
     513        that allows for easy launching of packet processing in a  
     514        thread. 
     515        """ 
     516        for p in self: 
     517            callback(p) 
     518 
     519    def read_all(self,count=-1): 
     520        """return a list of all packets in the pcap file 
     521        """ 
     522        res=[] 
     523        while count != 0: 
     524            count -= 1 
     525            p = self.read_packet() 
     526            if p is None: 
     527                break 
     528            res.append(p) 
     529        return res 
     530 
     531    def recv(self, size): 
     532        """ Emulate a socket 
     533        """ 
     534        return self.read_packet()[0] 
     535 
     536    def fileno(self): 
     537        return self.f.fileno() 
     538 
     539    def close(self): 
     540        return self.f.close() 
     541 
     542     
     543 
     544class PcapReader(RawPcapReader): 
     545    def __init__(self, filename): 
     546        RawPcapReader.__init__(self, filename) 
     547        try: 
     548            self.LLcls = conf.l2types[self.linktype] 
     549        except KeyError: 
     550            warning("PcapReader: unknown LL type [%i]/[%#x]. Using Raw packets" % (self.linktype,self.linktype)) 
     551            self.LLcls = Raw 
     552    def read_packet(self): 
     553        rp = RawPcapReader.read_packet(self) 
     554        if rp is None: 
     555            return None 
     556        s,(sec,usec,wirelen) = rp 
     557         
    509558        try: 
    510559            p = self.LLcls(s) 
     
    517566        p.time = sec+0.000001*usec 
    518567        return p 
    519  
    520     def dispatch(self, callback): 
    521         """call the specified callback routine for each packet read 
    522          
    523         This is just a convienience function for the main loop 
    524         that allows for easy launching of packet processing in a  
    525         thread. 
    526         """ 
    527         p = self.read_packet() 
    528         while p != None: 
    529             callback(p) 
    530             p = self.read_packet() 
    531  
    532568    def read_all(self,count=-1): 
    533         """return a list of all packets in the pcap file 
    534         """ 
    535         res=[] 
    536         while count != 0: 
    537             count -= 1 
    538             p = self.read_packet() 
    539             if p is None: 
    540                 break 
    541             res.append(p) 
     569        res = RawPcapReader.read_all(self, count) 
    542570        return PacketList(res,name = os.path.basename(self.filename)) 
    543  
    544571    def recv(self, size): 
    545         """ Emulate a socket 
    546         """ 
    547572        return self.read_packet() 
    548  
    549     def fileno(self): 
    550         return self.f.fileno() 
    551  
    552     def close(self): 
    553         return self.f.close() 
    554          
    555  
    556  
    557 class PcapWriter: 
     573         
     574 
     575 
     576class RawPcapWriter: 
    558577    """A stream PCAP writer with more control than wrpcap()""" 
    559578    def __init__(self, filename, linktype=None, gz=False, endianness="", append=False, sync=False): 
     
    580599        self.f = [open,gzip.open][gz](filename,append and "ab" or "wb", gz and 9 or bufsz) 
    581600         
    582              
    583  
    584601    def fileno(self): 
    585602        return self.f.fileno() 
     
    587604    def _write_header(self, pkt): 
    588605        self.header_present=1 
    589  
    590         if self.linktype == None: 
    591             if type(pkt) is list or type(pkt) is tuple: 
    592                 pkt = pkt[0] 
    593             self.linktype = conf.l2types.get(pkt.__class__,1) 
    594606 
    595607        if self.append: 
     
    613625        if not self.header_present: 
    614626            self._write_header(pkt) 
    615         for p in pkt: 
    616             self._write_packet(p) 
    617  
    618     def _write_packet(self, packet): 
     627        if type(pkt) is str: 
     628            self._write_packet(pkt) 
     629        else: 
     630            for p in pkt: 
     631                self._write_packet(p) 
     632 
     633    def _write_packet(self, packet, sec=None, usec=None, caplen=None, wirelen=None): 
    619634        """writes a single packet to the pcap file 
    620635        """ 
    621         s = str(packet) 
    622         l = len(s) 
    623         sec = int(packet.time) 
    624         usec = int((packet.time-sec)*1000000) 
    625         self.f.write(struct.pack(self.endian+"IIII", sec, usec, l, l)) 
    626         self.f.write(s) 
     636        if caplen is None: 
     637            caplen = len(packet) 
     638        if wirelen is None: 
     639            wirelen = caplen 
     640        if sec is None or usec is None: 
     641            t=time.time() 
     642            it = int(t) 
     643            if sec is None: 
     644                sec = it 
     645            if usec is None: 
     646                usec = int((t-it)*1000000) 
     647        self.f.write(struct.pack(self.endian+"IIII", sec, usec, caplen, wirelen)) 
     648        self.f.write(packet) 
    627649        if self.gz and self.sync: 
    628650            self.f.flush() 
     
    633655        return self.f.close() 
    634656                 
     657class PcapWriter(RawPcapWriter): 
     658    def _write_header(self, pkt): 
     659        if self.linktype == None: 
     660            if type(pkt) is list or type(pkt) is tuple or isinstance(pkt,BasePacketList): 
     661                pkt = pkt[0] 
     662            try: 
     663                self.linktype = conf.l2types[pkt.__class__] 
     664            except KeyError: 
     665                warning("PcapWriter: unknown LL type for %s. Using type 1 (Ethernet)" % pkt.__class__.__name__) 
     666                self.linktype = 1 
     667        RawPcapWriter._write_header(self, pkt) 
     668 
     669    def _write_packet(self, packet):         
     670        sec = int(packet.time) 
     671        usec = int((packet.time-sec)*1000000) 
     672        s = str(packet) 
     673        caplen = len(s) 
     674        RawPcapWriter._write_packet(self, s, sec, usec, caplen, caplen) 
     675 
    635676 
    636677re_extract_hexcap = re.compile("^(0x[0-9a-fA-F]{2,}[ :\t]|(0x)?[0-9a-fA-F]{2,}:|(0x)?[0-9a-fA-F]{3,}[: \t]|) *(([0-9a-fA-F]{2} {,2}){,16})")