def next(self): """Get the next packet from the trace file or raise StopIteration. The packet is also stored in the object attribute pkt. Examples: # Iterate over all packets found in the trace file using # the iterable properties of the object for pkt in x: print pkt # Iterate over all packets found in the trace file using it # as a method and using the object variable as the packet # Must use the try statement to catch StopIteration exception try: while (x.next()): print x.pkt except StopIteration: pass # Iterate over all packets found in the trace file using it # as a method and using the return value as the packet # Must use the try statement to catch StopIteration exception while True: try: print x.next() except StopIteration: break NOTE: Supports only single active iteration """ self.dprint('PKT4', ">>> %d: next()" % self.index) # Initialize next packet self.pkt = Pkt() if len(self.pktt_list) > 1: # Dealing with multiple trace files minsecs = None pktt_obj = None for obj in self.pktt_list: if obj.pkt is None: # Get first packet for this packet trace object try: obj.next() except StopIteration: obj.mindex = self.index if obj.eof: continue if minsecs is None or obj.pkt.record.secs < minsecs: minsecs = obj.pkt.record.secs pktt_obj = obj if self.filesize == 0: # Calculate total bytes to process for obj in self.pktt_list: self.filesize += obj.filesize if pktt_obj is None: # All packet trace files have been processed self.offset = self.filesize self.show_progress(True) raise StopIteration elif len(self._tcp_stream_map): # This packet trace file should be processed serially # Have all state transferred to next packet object pktt_obj.rewind() pktt_obj._tcp_stream_map = self._tcp_stream_map pktt_obj._rpc_xid_map = self._rpc_xid_map self._tcp_stream_map = {} self._rpc_xid_map = {} pktt_obj.next() # Overwrite attributes seen by the caller with the attributes # from the current packet trace object self.pkt = pktt_obj.pkt self.pkt_call = pktt_obj.pkt_call self.tfile = pktt_obj.tfile self.pkt.record.index = self.index # Use a cumulative index self.offset += pktt_obj.offset - pktt_obj.boffset try: # Get next packet for this packet trace object pktt_obj.next() except StopIteration: # Set maximum packet index for this packet trace object to # be used by rewind to select the proper packet trace object pktt_obj.mindex = self.index # Check if objects should be serially processed pktt_obj.serial = False for obj in self.pktt_list: if not obj.eof: if obj.index > 1: pktt_obj.serial = False break elif obj.index == 1: pktt_obj.serial = True if pktt_obj.serial: # Save current state self._tcp_stream_map = pktt_obj._tcp_stream_map self._rpc_xid_map = pktt_obj._rpc_xid_map self.show_progress() # Increment cumulative packet index self.index += 1 return self.pkt if self.boffset != self.offset: # Frame number is one for every record header on the pcap trace # On the other hand self.index is the packet number. Since there # could be multiple packets on a single frame self.index could # be larger the self.frame except that self.index start at 0 # while self.frame starts at 1. # The frame number can be used to match packets with other tools # like wireshark self.frame += 1 # Save file offset for this packet self.boffset = self.offset # Get record header data = self._read(16) if len(data) < 16: self.eof = True self.offset = self.filesize self.show_progress(True) raise StopIteration # Decode record header record = Record(self, data) # Get record data and create Unpack object self.unpack = Unpack(self._read(record.length_inc)) if self.unpack.size() < record.length_inc: # Record has been truncated, stop iteration self.eof = True self.offset = self.filesize self.show_progress(True) raise StopIteration if self.header.link_type == 1: # Decode ethernet layer ETHERNET(self) else: # Unknown link layer record.data = self.unpack.getbytes() self.show_progress() # Increment packet index self.index += 1 return self.pkt
def __init__(self, pktt): """Constructor Initialize object's private data. pktt: Packet trace object (packet.pktt.Pktt) so this layer has access to the parent layers. """ # Decode the TCP layer header unpack = pktt.unpack ulist = unpack.unpack(20, "!HHIIHHHH") self.src_port = ulist[0] self.dst_port = ulist[1] self.seq_number = ulist[2] self.ack_number = ulist[3] self.hl = ulist[4] >> 12 self.header_size = 4 * self.hl self.flags = Flags(ulist[4] & 0x1FF) self.window_size = ulist[5] self.checksum = ShortHex(ulist[6]) self.urgent_ptr = ulist[7] pktt.pkt.tcp = self # Stream identifier ip = pktt.pkt.ip streamid = "%s:%d-%s:%d" % (ip.src, self.src_port, ip.dst, self.dst_port) if streamid not in pktt._tcp_stream_map: # Create TCP stream object pktt._tcp_stream_map[streamid] = Stream(self.seq_number) # De-reference stream map stream = pktt._tcp_stream_map[streamid] if self.flags.SYN: # Reset seq_base on SYN stream.seq_base = self.seq_number stream.last_seq = stream.seq_wrap # Convert sequence numbers to relative numbers seq = self.seq_number - stream.seq_base + stream.seq_wrap if seq < stream.seq_wrap: # Sequence number has reached the maximum and wrapped around stream.seq_wrap += 4294967296 seq += 4294967296 self.seq = seq if self.header_size > 20: self.options = [] osize = self.header_size - 20 optunpack = Unpack(unpack.read(osize)) while optunpack.size(): optobj = Option(optunpack) if optobj.kind == 0: # End of option list break elif optobj.kind > 0: # Valid option self.options.append(optobj) # Save length of TCP segment self.length = unpack.size() if seq < stream.last_seq and not stream.missing_fragment(seq): # This is a re-transmission, do not process return self._decode_payload(pktt, stream) if self.length > 0: stream.last_seq = seq stream.next_seq = seq + self.length