示例#1
0
文件: bro_sobject.c 项目: ewust/telex
void *
__bro_sobject_data_get(BroSObject *obj, const char *key)
{
  void *result;

  if (! obj || ! key || ! *key)
    return NULL;

  result = __bro_ht_get(obj->data, (void *) key);
  /* D(("Retrieving data item '%s' from object %p yields %p\n", key, obj, result)); */
  return result;
}
示例#2
0
文件: bro_io.c 项目: bro/broccoli
int
__bro_io_process_input(BroConn *bc)
{
  uint32          buf_off, chunk_size;
  BroMsgHeader    msg_hdr;
  int             result = FALSE;
  
  D_ENTER;
  
  /* Read all available data into receive buffer. Our socket is
   * nonblocking so if nothing's available we'll be back right
   * away. If nothing was read, the subsequent for loop will exit
   * right away, so the io_msg_fill_rx() return code need not be
   * checked here.
   */
  io_msg_fill_rx(bc);

  /* Try to process as much in the input buffer as we can */
  for ( ; ; )
    {  
      D(("----- Attempting to extract a message\n"));

      /* Get the current offset of the buffer pointer to make
       * sure we can reset to it if things go wrong.
       */
      buf_off = __bro_buf_ptr_tell(bc->rx_buf);
      
      /* Now check the buffer contents and see if there's enough
       * for us to analyze it. Start with a uint32 for the size
       * of the first chunk, and then the chunk itself.
       */
      if (! io_read_chunk_size(bc, &chunk_size))
	goto reset_return;
      
      if (chunk_size != sizeof(BroMsgHeader))
	{
	  D(("Received chunk should be %i bytes, but is %i\n",
	     sizeof(BroMsgHeader), chunk_size));
	  io_skip_chunk(bc->rx_buf, buf_off, chunk_size);
	  result = TRUE;
	  continue;
	}
      
      if (! io_read_msg_hdr(bc, &msg_hdr))
	goto reset_return;
      
      switch (msg_hdr.hdr_type)
	{
	case BRO_MSG_REQUEST:
	  {
	    char *tmp = NULL, *tmp2 = NULL;
	        
	    D(("Received MSQ_REQUEST\n"));
	        
	    /* We need to read another chunk, whose data will contain
	     * a sequence of 0-terminated strings, each one being the
	     * name of an event that the peering Bro is interested in.
	     */
	    if (! io_read_chunk_size(bc, &chunk_size))
	      goto reset_return;
	        
	    if (! (tmp = (char *) malloc(chunk_size * sizeof(char))))
	      goto reset_return;
	        
	    if (! __bro_buf_read_data(bc->rx_buf, tmp, chunk_size))
	      {
		free(tmp);
		goto reset_return;
	      }
	        
	    for (tmp2 = tmp; tmp2 < tmp + chunk_size; tmp2 = tmp2 + strlen(tmp2) + 1)
	      {
		char *key;

		if (__bro_ht_get(bc->ev_mask, tmp2))
		  continue;
		
		key = strdup(tmp2);
		__bro_ht_add(bc->ev_mask, key, key);
		D(("Will report event '%s'\n", tmp2));
	      }

	    D(("Now reporting %i event(s).\n", __bro_ht_get_size(bc->ev_mask)));
	    free(tmp);
	  }
	  break;
	    
	case BRO_MSG_VERSION:
	  {
	    uchar *data;
	    uint32 proto_version;
	    uint32 cache_size;
	    uint32 data_version;
	    uint32 runtime; /* unused */

	    D(("Received MSG_VERSION\n"));

	    /* We need to read another chunk for the raw data.
	     */
	    if (! io_read_chunk_size(bc, &chunk_size))
	      goto reset_return;

	    if (! (data = malloc(sizeof(uchar) * chunk_size)))
	      goto reset_return;

	    if (! __bro_buf_read_data(bc->rx_buf, data, chunk_size))
	      {
		free(data);
		goto reset_return;
	      }
	        
	    proto_version = ntohl(((uint32 *) data)[0]);
	    cache_size    = ntohl(((uint32 *) data)[1]);
	    data_version  = ntohl(((uint32 *) data)[2]);
	    runtime       = ntohl(((uint32 *) data)[3]);

	    /* If there are more bytes than required for the 4 uint32s
	     * used above, it means that the peer has sent a connection class
	     * identifier. Extract and register in the handle.
	     */
	    if (chunk_size > 4 * sizeof(uint32))
	      {
		if (bc->peer_class)
		  free(bc->peer_class);
		
		bc->peer_class = strdup((char *) (data + 4 * sizeof(uint32)));
	      }

	    if (proto_version != BRO_PROTOCOL_VERSION)
	      {
		D(("EEEK -- we speak protocol version %i, peer speeks %i. Aborting.\n",
		   BRO_PROTOCOL_VERSION, proto_version));		
		__bro_openssl_shutdown(bc);
		free(data);
		goto reset_return;
	      } else {
		D(("Protocols compatible, we speak version %i\n", BRO_PROTOCOL_VERSION));
	      }
	    
	    if (data_version != 0 && data_version != BRO_DATA_FORMAT_VERSION)
	      {
		D(("EEEK -- we speak data format version %i, peer speeks %i. Aborting.\n",
		   BRO_DATA_FORMAT_VERSION, data_version));		
		__bro_openssl_shutdown(bc);
		free(data);
		goto reset_return;
	      } else {
		D(("Data formats compatible, we speak version %i\n", BRO_DATA_FORMAT_VERSION));
	      }
	    
	    bc->io_cache_maxsize = cache_size;
	    D(("Receiver cache size set to %i entries.\n", cache_size));
	    free(data);

	    bc->state->conn_state_peer = BRO_CONNSTATE_HANDSHAKE;
	    D(("VERSION received, on %p, peer now in HANDSHAKE stage.\n"));
	  }
	  break;
	    
	case BRO_MSG_SERIAL:
	  {
	    uint32 pre_serial;
	        
	    D(("Received MSQ_SERIAL\n"));
	    pre_serial = __bro_buf_ptr_tell(bc->rx_buf);

	    if (! io_read_chunk_size(bc, &chunk_size))
	      goto reset_return;
	        
	    if (! io_process_serialization(bc))
	      io_skip_chunk(bc->rx_buf, pre_serial, chunk_size);
	  }
	  break;
	    
	case BRO_MSG_CAPTURE_FILTER:
	  {
	    uint32 pre_capture;

	    D(("Received MSQ_CAPTURE_FILTER\n"));
	    pre_capture = __bro_buf_ptr_tell(bc->rx_buf);
	        
	    if (! io_read_chunk_size(bc, &chunk_size))
	      goto reset_return;
	        
	    io_skip_chunk(bc->rx_buf, pre_capture, chunk_size);
	  }
	  break;

	case BRO_MSG_PHASE_DONE:
	  /* No additional content for this one. */
	  switch (bc->state->conn_state_peer)
	    {
	    case BRO_CONNSTATE_HANDSHAKE:
	      /* When we complete the handshake phase, it depends
	       * on whether or not the peer has requested synced
	       * state. If so, enter the sync phase, otherwise
	       * we're up and running.
	       */
	      if (bc->state->sync_state_requested)
		{
		  bc->state->conn_state_peer = BRO_CONNSTATE_SYNC;
		  D(("Phase done from peer on %p, sync requested, peer now in SYNC stage.\n", bc));
		}
	      else
		{
		  bc->state->conn_state_peer = BRO_CONNSTATE_RUNNING;
		  D(("Phase done from peer on %p, no sync requested, peer now in RUNNING stage.\n", bc));
		}
	      break;

	    case BRO_CONNSTATE_SYNC:
	      bc->state->conn_state_peer = BRO_CONNSTATE_RUNNING;
	      D(("Phase done from peer on %p, peer now in RUNNING stage.\n", bc));
	      break;
	      
	    default:
	      D(("Ignoring PHASE_DONE in conn state %i/%i on conn %p\n",
		 bc->state->conn_state_self, bc->state->conn_state_peer, bc));
	    }
	  break;
	  
	case BRO_MSG_REQUEST_SYNC:
		{   	  
	    uchar *data;
		
	    D(("Received MSQ_REQUEST_SYNC, peer now in SYNC stage.\n"));
		
	    bc->state->sync_state_requested = 1;
	    bc->state->conn_state_peer = BRO_CONNSTATE_SYNC;

	    /* We need to read another chunk for the raw data.
	     */
	    if (! io_read_chunk_size(bc, &chunk_size))
	      goto reset_return;

	    if (! (data = malloc(sizeof(uchar) * chunk_size)))
	      goto reset_return;

	    if (! __bro_buf_read_data(bc->rx_buf, data, chunk_size))
	      {
		free(data);
		goto reset_return;
	      }
	    D(("Skipping sync interpretation\n"));
	    free(data);
	    break;
	  }
	
	
	case BRO_MSG_CAPS:
	  {
	    uchar *data;

	    D(("Received MSG_CAPS\n"));

	    /* We need to read another chunk for the raw data.
	     */
	    if (! io_read_chunk_size(bc, &chunk_size))
	      goto reset_return;

	    if (! (data = malloc(sizeof(uchar) * chunk_size)))
	      goto reset_return;

	    if (! __bro_buf_read_data(bc->rx_buf, data, chunk_size))
	      {
		free(data);
		goto reset_return;
	      }
	    D(("Skipping capabilities interpretation\n"));
	    free(data);
	    break;
	  }

	default:
	  D(("Skipping unknown message type %i\n", msg_hdr.hdr_type));
	  break;
	}
      
      __bro_buf_consume(bc->rx_buf);
      result = TRUE;

      if ((bc->conn_flags & BRO_CFLAG_YIELD) &&
	  bc->state->conn_state_self == BRO_CONNSTATE_RUNNING &&
	  bc->state->conn_state_peer == BRO_CONNSTATE_RUNNING)	  
	break;
    }
  
 reset_return:
  __bro_buf_ptr_seek(bc->rx_buf, buf_off, SEEK_SET);
  D_RETURN_(result);
}
示例#3
0
文件: bro_io.c 项目: bro/broccoli
static int      
io_msg_fill_tx(BroConn *bc, BroMsg *msg)
{
  int result = TRUE;

  D_ENTER;

  if (!bc || !msg)
    {
      D(("Input error.\n"));
      D_RETURN_(FALSE);
    }

  /* Check if anything is still left in the input buffer. In that case,
   * we don't fill anything in but return right away, so the message
   * gets queued.
   */
  if (__bro_buf_get_used_size(bc->tx_buf) > 0)
    {
      D(("Buffer not empty; not filling!\n"));
      D_RETURN_(FALSE);
    }
  
  D((">>> Attempting write of %s\n", msg_type_2_str(msg->msg_header.hdr_type)));

  /* We will collect the message chunk in the connection's tx buffer.
   * We append stuff to it as we go along and at the end write it out.
   * When being sent, he buffer has the amount of octets to send at
   * the beginning, so the reader knows how much is coming.
   */
  __bro_buf_reset(bc->tx_buf);

  msg->msg_header_size = sizeof(BroMsgHeader);
  
  if (! __bro_buf_write_int(bc->tx_buf, msg->msg_header_size))
    {
      __bro_buf_reset(bc->tx_buf);
      D_RETURN_(FALSE);
    }
  
  /* Hook in the Bro message header */
  if (! io_fill_msg_header(bc->tx_buf, &msg->msg_header))
    {
      __bro_buf_reset(bc->tx_buf);
      D_RETURN_(FALSE);
    }
  
  if (msg->msg_cont_type != BRO_MSG_CONT_NONE)
    {
      uint32 msg_size_pos, msg_size_end;

      /* This starts another chunk of data (in Bro protocol speak),
       * but here we cannot yet know how big the chunk will be.
       * We save the offset in the buffer and return to it later,
       * overwriting the value with the then correct one.
       */
      msg_size_pos = __bro_buf_get_used_size(bc->tx_buf);
      if (! __bro_buf_write_int(bc->tx_buf, msg->msg_size))
	{
	  __bro_buf_reset(bc->tx_buf);
	  D_RETURN_(FALSE);
	}
      
      /* Gather the payload of the message we are about
       * to send into the buffer BUF.
       */
      switch (msg->msg_cont_type)
	{
	case BRO_MSG_CONT_RAW:
	  D(("Filling raw data into buffer\n"));
	  if (! io_fill_raw(bc->tx_buf, msg->msg_cont_raw))
	    {
	      __bro_buf_reset(bc->tx_buf);
	      D_RETURN_(FALSE);
	    }
	  break;
	  
	case BRO_MSG_CONT_EVENT:
	  /* Check if the peer actually requested the event, and if not,
	   * drop it silently (i.e., still return success).
	   */
	  if (! __bro_ht_get(bc->ev_mask, msg->msg_cont_ev->name.str_val))
	    {
	      D(("Event '%s' not requested by peer -- dropping.\n",
		 msg->msg_cont_ev->name.str_val));
	      __bro_buf_reset(bc->tx_buf);

	      /* This is not an error but a silent drop, so we
	       * return success.
	       */
	      D_RETURN_(TRUE);
	    }
	  
	  D(("Filling event into buffer\n"));
	  
	  if (! __bro_event_serialize(msg->msg_cont_ev, bc))
	    {
	      D(("Error during serialization.\n"));
	      __bro_buf_reset(bc->tx_buf);
	      D_RETURN_(FALSE);	
	    }
	  break;
	  
	case BRO_MSG_CONT_REQUEST:
	  D(("Filling request into buffer\n"));
	  if (! io_fill_request(bc->tx_buf, msg->msg_cont_req))
	    {
	      __bro_buf_reset(bc->tx_buf);
	      D_RETURN_(FALSE);	
	    }
	  break;

#ifdef BRO_PCAP_SUPPORT	  
	case BRO_MSG_CONT_PACKET:
	  if (! __bro_packet_serialize(msg->msg_cont_packet, bc))
	    {
	      __bro_buf_reset(bc->tx_buf);	      
	      D_RETURN_(FALSE);
	    }
	  break;
#endif
	default:
	  D(("ERROR -- invalid message content code %i\n", msg->msg_cont_type));
	  break;
	}
      
      /* Now calculate length of entire transmission --
       * we know where we wrote the uint32 containing the
       * size of the chunk, and we know where we are now,
       * so the length is their difference, minus the uint32
       * itself.
       */
      msg_size_end = __bro_buf_get_used_size(bc->tx_buf);
      msg->msg_size = msg_size_end - msg_size_pos - sizeof(uint32);
      D(("Serialized message sized %i bytes.\n", msg->msg_size));
      
      if (! __bro_buf_ptr_seek(bc->tx_buf, msg_size_pos, SEEK_SET))
	{
	  D(("Cannot seek to position %u -- we're screwed.\n", msg_size_pos));
	  __bro_buf_reset(bc->tx_buf);
	  D_RETURN_(FALSE);
	}
      
      if (! __bro_buf_write_int(bc->tx_buf, msg->msg_size))
	{
	  __bro_buf_reset(bc->tx_buf);
	  D_RETURN_(FALSE);
	}
    }
  
  D_RETURN_(result);
}
示例#4
0
文件: bro_sobject.c 项目: ewust/telex
BroSObject      *
__bro_sobject_unserialize(uint16 type_id_wanted, BroConn *bc)
{
  BroSObject *obj;
  char full_obj;
  uint32 perm_id;
  uint16 type_id;

  D_ENTER;

  if (! bc)
    D_RETURN_(NULL);
  
  /* Same special case for types as in __bro_sobject_serialize().
   */
  if ( (type_id_wanted & SER_TYPE_MASK) == SER_IS_TYPE)
    {
      D(("Unserializing a type, checking for name-only format.\n"));

      if (! __bro_buf_read_char(bc->rx_buf, &full_obj))
	D_RETURN_(NULL);

      if (! full_obj)
	{
	  BroString tmp;
	  bro_string_init(&tmp);
	  
	  /* We only get the name. */
	  if (! __bro_buf_read_string(bc->rx_buf, &tmp))
	    D_RETURN_(FALSE);
	  
	  /* We don't really have a namespace in which we can now
	   * look up the type, so there's not much we can do!
	   */
	  D(("Received name-only type '%s', reporting failure.\n",
	     bro_string_get_data(&tmp)));
	  D_RETURN_(FALSE);
	}
    }
  
  if (! __bro_buf_read_char(bc->rx_buf, &full_obj))
    D_RETURN_(NULL);
  
  if (! __bro_buf_read_int(bc->rx_buf, &perm_id))
    D_RETURN_(NULL);

  if (! full_obj)
    {
#ifdef BRO_DEBUG
      if (! (bc->conn_flags & BRO_CFLAG_CACHE))
	D(("WARNING: no caching requested, yet peer sends cached data.\n"));
#endif
      if (! (obj = __bro_ht_get(bc->io_cache, (void *) perm_id)))
	{
	  D(("Cache inconsistency: cache should contain object %i\n", perm_id));
	  D_RETURN_(NULL);
	}
      
      __bro_sobject_ref(obj);

      D(("Returning object %i/%p from cache.\n", perm_id, obj));
      D_RETURN_(obj);
    }
 
  if (! __bro_buf_read_short(bc->rx_buf, &type_id))
    D_RETURN_(NULL);
  
  /* Now check if the stuff that's arriving is actually an
   * instance of the type we'd like to see -- we can only do
   * primitive checking for inherited types (when we want to
   * know that it's a type, say, but we cannot know what exact
   * kind of type) -- so we just check whether all the bits set
   * in both type id's match:
   */
  if ((type_id_wanted & SER_TYPE_MASK) != (type_id & SER_TYPE_MASK))
    {
      D(("Type mismatch in serialization: wanted %04x, got %04x.\n",
	 type_id_wanted, type_id));
      D_RETURN_(NULL);
    }
  
  if (! (obj = __bro_sobject_create(type_id)))
    D_RETURN_(NULL);
  
  /* Polymorphism: depending on the constructor of the object,
   * this call will start from the bottom of the hierarchy and
   * read members in step by step, so by the time we return
   * from this function the object is fully unserialized.
   */
  if (! obj->read(obj, bc))
    {
      D(("Reading object %i of type 0x%04x FAILED.\n", perm_id, type_id));
      __bro_sobject_release(obj);
      D_RETURN_(NULL);
    }

  /* If we have asked the peer to use caching,
   * make sure the object is in the cache:
   */
  if ( (bc->conn_flags & BRO_CFLAG_CACHE) &&
      ! __bro_ht_get(bc->io_cache, (void *) perm_id))
    {
      D(("Storing object %i in cache.\n", perm_id));
      __bro_ht_add(bc->io_cache, (void *) perm_id, obj);
      obj->perm_id = perm_id;
      __bro_sobject_ref(obj);
    }

  D(("Object %i of type 0x%04x unserialized successfully.\n", perm_id, type_id));
  D_RETURN_(obj);
}