Пример #1
0
packet_t *packet_parse(uint8_t *data, size_t length, options_t options)
{
  packet_t *packet = (packet_t*) safe_malloc(sizeof(packet_t));
  buffer_t *buffer = buffer_create_with_data(BO_BIG_ENDIAN, data, length);

  /* Validate the size */
  if(buffer_get_length(buffer) > MAX_PACKET_SIZE)
  {
    LOG_FATAL("Packet is too long: %zu bytes\n", buffer_get_length(buffer));
    exit(1);
  }

  packet->packet_id    = buffer_read_next_int16(buffer);
  packet->packet_type  = (packet_type_t) buffer_read_next_int8(buffer);
  packet->session_id   = buffer_read_next_int16(buffer);

  switch(packet->packet_type)
  {
    case PACKET_TYPE_SYN:
      packet->body.syn.seq     = buffer_read_next_int16(buffer);
      packet->body.syn.options = buffer_read_next_int16(buffer);
      break;

    case PACKET_TYPE_MSG:
      if(options & OPT_CHUNKED_DOWNLOAD)
      {
        packet->body.msg.options.chunked.chunk = buffer_read_next_int32(buffer);
      }
      else
      {
        packet->body.msg.options.normal.seq     = buffer_read_next_int16(buffer);
        packet->body.msg.options.normal.ack     = buffer_read_next_int16(buffer);
      }
      packet->body.msg.data    = buffer_read_remaining_bytes(buffer, &packet->body.msg.data_length, -1, FALSE);
      break;

    case PACKET_TYPE_FIN:
      packet->body.fin.reason = buffer_alloc_next_ntstring(buffer);

      break;

    case PACKET_TYPE_PING:
      packet->body.ping.data = buffer_alloc_next_ntstring(buffer);

      break;

    default:
      LOG_FATAL("Error: unknown message type (0x%02x)\n", packet->packet_type);
      exit(0);
  }

  buffer_destroy(buffer);

  return packet;
}
Пример #2
0
/* Read data from the session that will be sent out across the network. This
 * will return up to read_length bytes (and will return the number of bytes
 * read in read_length as well). The memory returned has to be freed. 
 *
 * If the session isn't found, NULL is returned. If no data is waiting, the
 * empty string is returned and read_length is set to 0. 
 */
uint8_t *session_read(sessions_t *sessions, char *session_name, uint32_t *read_length)
{
	uint32_t i = 0;

	buffer_t *incoming;
	buffer_t *response;
	session_t *session;

	session = session_get(sessions, session_name);
	if(!session)
		return NULL;

	if(session_is_closed(sessions, session_name))
		return NULL;

	if(buffer_can_read_int8(sessions->buffer_data))
	{
		incoming = sessions->buffer_data;
	}
	else
	{
		if(!session)
			return NULL;
		incoming = session->buffer;
	}

	response = buffer_create(BO_NETWORK);
	while(buffer_can_read_int8(incoming) && i < *read_length)
	{
		if(sessions->log)
			fputc(buffer_peek_next_int8(incoming), sessions->log);
		buffer_add_int8(response, buffer_read_next_int8(incoming));
		i++;
	}

	/* Clear whichever buffer we're using if we're at the end. */
	if(!buffer_can_read_int8(incoming))
		buffer_clear(incoming);

	return buffer_create_string_and_destroy(response, read_length);
}
Пример #3
0
static SELECT_RESPONSE_t recv_socket_callback(void *group, int s, uint8_t *data, size_t length, char *addr, uint16_t port, void *param)
{
  /*driver_dns_t *driver_dns = param;*/
  dns_t        *dns    = dns_create_from_packet(data, length);
  driver_dns_t *driver = (driver_dns_t*) param;

  LOG_INFO("DNS response received (%d bytes)", length);

  /* TODO */
  if(dns->rcode != _DNS_RCODE_SUCCESS)
  {
    /* TODO: Handle errors more gracefully */
    switch(dns->rcode)
    {
      case _DNS_RCODE_FORMAT_ERROR:
        LOG_ERROR("DNS: RCODE_FORMAT_ERROR");
        break;
      case _DNS_RCODE_SERVER_FAILURE:
        LOG_ERROR("DNS: RCODE_SERVER_FAILURE");
        break;
      case _DNS_RCODE_NAME_ERROR:
        LOG_ERROR("DNS: RCODE_NAME_ERROR");
        break;
      case _DNS_RCODE_NOT_IMPLEMENTED:
        LOG_ERROR("DNS: RCODE_NOT_IMPLEMENTED");
        break;
      case _DNS_RCODE_REFUSED:
        LOG_ERROR("DNS: RCODE_REFUSED");
        break;
      default:
        LOG_ERROR("DNS: Unknown error code (0x%04x)", dns->rcode);
        break;
    }
  }
  else if(dns->question_count != 1)
  {
    LOG_ERROR("DNS returned the wrong number of response fields (question_count should be 1, was instead %d).", dns->question_count);
    LOG_ERROR("This is probably due to a DNS error");
  }
  else if(dns->answer_count < 1)
  {
    LOG_ERROR("DNS didn't return an answer");
    LOG_ERROR("This is probably due to a DNS error");
  }
  else
  {
    size_t    i;

    uint8_t   *answer = NULL;
    size_t     answer_length = 0;
    dns_type_t type = dns->answers[0].type;

    if(type == _DNS_TYPE_TEXT)
    {
      /* Get the answer. */
      answer        = dns->answers[0].answer->TEXT.text;
      answer_length = dns->answers[0].answer->TEXT.length;
      LOG_INFO("Received a TXT response (%zu bytes)", answer_length);

      /* Decode it. */
      answer = buffer_decode_hex(answer, &answer_length);
    }
    else if(type == _DNS_TYPE_CNAME)
    {
      /* Get the answer. */
      answer = remove_domain((char*)dns->answers[0].answer->CNAME.name, driver->domain);
      answer_length = strlen((char*)answer);
      LOG_INFO("Received a CNAME response (%zu bytes)", answer_length);

      /* Decode it. */
      answer = buffer_decode_hex(answer, &answer_length);
    }
    else if(type == _DNS_TYPE_MX)
    {
      /* Get the answer. */
      answer = remove_domain((char*)dns->answers[0].answer->MX.name, driver->domain);
      answer_length = strlen((char*)answer);
      LOG_INFO("Received a MX response (%zu bytes)", answer_length);

      /* Decode it. */
      answer = buffer_decode_hex(answer, &answer_length);
    }
    else if(type == _DNS_TYPE_A)
    {
      buffer_t *buf = buffer_create(BO_BIG_ENDIAN);

      qsort(dns->answers, dns->answer_count, sizeof(answer_t), cmpfunc_a);

      for(i = 0; i < dns->answer_count; i++)
        buffer_add_bytes(buf, dns->answers[i].answer->A.bytes + 1, 3);

      answer_length = buffer_read_next_int8(buf);
      LOG_INFO("Received an A response (%zu bytes)", answer_length);

      answer = safe_malloc(answer_length);
      buffer_read_bytes_at(buf, 1, answer, answer_length);
    }
#ifndef WIN32
    else if(type == _DNS_TYPE_AAAA)
    {
      buffer_t *buf = buffer_create(BO_BIG_ENDIAN);

      qsort(dns->answers, dns->answer_count, sizeof(answer_t), cmpfunc_aaaa);

      for(i = 0; i < dns->answer_count; i++)
        buffer_add_bytes(buf, dns->answers[i].answer->AAAA.bytes + 1, 15);

      answer_length = buffer_read_next_int8(buf);
      LOG_INFO("Received an AAAA response (%zu bytes)", answer_length);

      answer = safe_malloc(answer_length);
      buffer_read_bytes_at(buf, 1, answer, answer_length);
    }
#endif
    else
    {
      LOG_ERROR("Unknown DNS type returned: %d", type);
      answer = NULL;
    }

    if(answer)
    {
      /*LOG_WARNING("Received a %zu-byte DNS response: %s [0x%04x]", answer_length, answer, type);*/

      /* Pass the buffer to the caller */
      if(answer_length > 0)
      {
        /* Pass the data elsewhere. */
        message_post_packet_in(answer, answer_length);
      }

      safe_free(answer);
    }
  }

  dns_destroy(dns);

  return SELECT_OK;
}