Example #1
0
    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
Example #2
0
    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