def run(self):
     """
         Run forever grabbing data from the VM and forwarding it to listening
         clients 
     """
     # Get our meta data which is always the first packet sent
     meta = MetaHeader()
     meta_data = self._conn.recv(len(meta))
     if len(meta_data) == 0:
         logger.debug("VM Disconnected.")
         self._conn.close()
         return
     
     meta._unpack(meta_data)
     
     #logger.debug("Got meta data")
     #logger.debug(meta)
     
     # Store our filename for this VM
     # NOTE: We must strip the null chars off or comparisons will fail!
     filename = meta.filename.strip("\x00")
     
     # Create our sensor packet, and save its default size
     sensor_packet = DiskSensorPacket()
     sensor_header_size = len(sensor_packet)
     
     # Read packets forever
     while True:
         
         # Read and unpack our header
         header_data = self._conn.recv(sensor_header_size)
         if len(header_data) == 0:
             #logger.debug("VM Disconnected.")
             break
         
         sensor_packet._unpack(header_data)
         
         # Get the accompanying data
         try:
             sensor_packet.data = self._conn.recv(sensor_packet.size)
         except:
             print sensor_packet
             G.print_traceback()
             
         if len(sensor_packet.data) == 0:
             logger.debug("VM Disconnected.")
             self._conn.close()
             return
         
         if filename in disk_stream_dict:
             #logger.debug("Found %s in dict."%filename)
             for queue in disk_stream_dict[filename]:
                 queue.put(`sensor_packet`)
Example #2
0
    def get_disk_packet(self):
        """
            Get the next packet header/data
        """
        
        if self.SOCK is None:
            self._connect()
        
        access_packet = DiskSensorPacket()

        # Try forever to get a packet
        while 1:
            # Receive our header
            header = self._read_raw_packet(len(access_packet))

            # Did our socket get closed?
            if len(header) < len(access_packet):
                logger.warn("Introspection server disconnected.")
                # reconnect and try again
                self._connect()
                continue
            
            access_packet = DiskSensorPacket(header)

            # Read for as long as the header tells us to to get the content
            data = ""
            recvd = 0
            while len(data) < access_packet.size:
                logger.debug("Read data.")
                tmp = self.SOCK.recv(access_packet.size - recvd);
                data += tmp
                recvd = len(data)
                if len(tmp) == 0:
                    logger.warn("Introspection server disconnected.")
                    break

            # Did our socket get closed?
            if recvd < access_packet.size:
                logger.warn("Introspection server disconnected.")
                # reconnect and try again
                self._connect()
                continue

            logger.debug("Read %d bytes of data."%len(data))
            
            # Return our data
            access_packet.data = data
            
            return access_packet
Example #3
0
    def handle_register_HTD(self, register_packet):
        """
            Handle a Register HTD

            Always returns None
        """

        sata_header = register_packet.sata_header

        # Check if C bit is set to 0 -- see 11.2 Dl1 Note 1 -- no FIS is sent
        # I think we can ignore if C bit is set to 0 and go back to IDLE state
        # software reset could still happen -- not sure which bit is the SRST bit in the control register?
        if sata_header['C'] == 0:
            logger.debug("Got HTD Register Packet but C bit is set to 0.  Ignoring.")
            return None

        # check if this is an NCQ command
        if sata_header['command'] == NCQCommandType.ReadFPDMAQueued or sata_header['command'] == NCQCommandType.WriteFPDMAQueued:

            cmd = "READ"
            direction = G.SATA_OP.DIRECTION.READ
            if sata_header['command'] == NCQCommandType.WriteFPDMAQueued:
                cmd = "WRITE"
                direction = G.SATA_OP.DIRECTION.WRITE

            # NCQ uses features field for sector count
            logger.debug("Got HTD Register Packet for NCQ %s -- TAG %d expecting %d bytes." % (cmd, sata_header['tag'], sata_header['features']*self.sector_size))

            #            if len(self.ncq_register_stack) > 0:
            #                logger.error("Our NCQ register stack will be greater than 1, so we have at least one outstanding NCQ register packet with NO Register ACK.  Stack size is %d" % len(self.ncq_register_stack))

            #            # add to our stack
            #            self.ncq_register_stack.append(register_packet)

            #No ACKS
            #            # change state to waiting for Register DTH
            #            self.STATE = self.WAIT_FOR_REGISTER_ACK
            #
            #            # deal with error checking when we get the Register DTH ACK back
            #            return None

            # check if the spot belonging to the associated TAG is empty
            if (not self.ncq_transactions_outstanding[sata_header['tag']]):
                # This TAG is not taken, so we just add
                self.ncq_transactions_outstanding[sata_header['tag']] = register_packet

            else:
                logger.error("Received HTD NCQ Register Packet for TAG %d but it is already in use.  Using it anyway." % sata_header['tag'])
                # still put it in there for now
                self.ncq_transactions_outstanding[sata_header['tag']] = register_packet

                #don't need this if we accept the register packet anyway
                #return None


            # Associate this DTH Register packet
            # with the tag and prepare the disk sensor packet for aggregating data
            lba = sata_header['lba']

            # NOTE: NCQ uses features field instead of count for sector count
            sector_count = sata_header['features']


            disk_sensor_packet = DiskSensorPacket()
            disk_sensor_packet.sector = lba
            disk_sensor_packet.num_sectors =  sector_count
            disk_sensor_packet.disk_operation = direction
            disk_sensor_packet.size = sector_count*self.sector_size
            disk_sensor_packet.data = ""

            self.ncq_data_outstanding[sata_header['tag']] = disk_sensor_packet

            # DO NOT set state to IDLE
            # Because now it looks like Register packets can come during other times
            # so we want to maintain the current state
            #            # set state to IDLE
            #
            #            self.STATE = self.DEVICE_IDLE

            return None



        # NCQ Management stuff
        elif sata_header['command'] == NCQCommandType.NCQQueueManagement:
            logger.debug("Got Register Packet for NCQ Queue Management.  Ignoring for now.")
            # Don't need to change state
            return None

        # NON NCQ Register Packet
        else:
            logger.debug("Got Non-NCQ HTD Register Packet, expected %d bytes." % (sata_header['count']*self.sector_size))
            logger.debug("Command field is %d" % sata_header['command'])

            #            if len(self.ncq_register_stack) > 0:
            #                logger.error("Have more than 0 outstanding NCQ HTD Register Packets.  Non NCQ Register packets are not supposed to be sent while NCQ Register packets are still outstanding.  Size of stack is %d" % len(self.regular_register_stack))


            #            if len(self.regular_register_stack) > 0:
            #                logger.error("Will have more than one outstanding regular (non NCQ) HTD Register Packets.  Size of stack is %d" % len(self.regular_register_stack))

            # push this normal Register HTD packet on the stack
            self.regular_register_stack.append(register_packet)


            # prepare the disk sensor packet for aggregating data
            lba = sata_header['lba']
            sector_count = sata_header['count']
            direction = sata_header['direction']

            #             self.regular_disk_sensor_packet = DiskSensorPacket(lba,
            #                                          sector_count,
            #                                          direction,
            #                                          sector_count*self.sector_size,
            #                                          "")
            self.regular_disk_sensor_packet = DiskSensorPacket()
            self.regular_disk_sensor_packet.sector = lba
            self.regular_disk_sensor_packet.num_sectors = sector_count
            self.regular_disk_sensor_packet.disk_operation = direction
            self.regular_disk_sensor_packet.size = sector_count*self.sector_size
            self.regular_disk_sensor_packet.data = ""

            # Transition state now that we are waiting for data
            self.STATE = self.WAIT_FOR_NON_NCQ_DATA

            return None