/**
 * Function called to validate a reply or a request.  For
 * request evaluation, simply pass "NULL" for the reply_block.
 *
 * @param cls closure
 * @param type block type
 * @param query original query (hash)
 * @param bf pointer to bloom filter associated with query; possibly updated (!)
 * @param bf_mutator mutation value for bf
 * @param xquery extrended query data (can be NULL, depending on type)
 * @param xquery_size number of bytes in xquery
 * @param reply_block response to validate
 * @param reply_block_size number of bytes in reply block
 * @return characterization of result
 */
static enum GNUNET_BLOCK_EvaluationResult
block_plugin_template_evaluate (void *cls, enum GNUNET_BLOCK_Type type,
                                const struct GNUNET_HashCode * query,
                                struct GNUNET_CONTAINER_BloomFilter **bf,
                                int32_t bf_mutator, const void *xquery,
                                size_t xquery_size, const void *reply_block,
                                size_t reply_block_size)
{
  struct GNUNET_HashCode chash;
  struct GNUNET_HashCode mhash;
  /* FIXME: check validity first... */
     
  /* mandatory duplicate-detection code... */
  if (NULL != bf)
  {
    GNUNET_CRYPTO_hash (reply_block, reply_block_size, &chash);
    GNUNET_BLOCK_mingle_hash (&chash, bf_mutator, &mhash);
    if (NULL != *bf)
    {
      if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (*bf, &mhash))
        return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
    }
    else
    {
      *bf = GNUNET_CONTAINER_bloomfilter_init (NULL, 8, 64 /* BLOOMFILTER_K */);
    }
    GNUNET_CONTAINER_bloomfilter_add (*bf, &mhash);
  }
  /* FIXME: other stuff here... */
  return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
}
/**
 * Calculate when we would like to send the next HELLO to this
 * peer and ask for it.
 *
 * @param cls for which peer to schedule the HELLO
 */
static void
schedule_next_hello (void *cls)
{
  struct Peer *pl = cls;
  struct FindAdvHelloContext fah;
  struct GNUNET_MQ_Envelope *env;
  size_t want;
  struct GNUNET_TIME_Relative delay;
  struct GNUNET_HashCode hc;

  pl->hello_delay_task = NULL;
  GNUNET_assert (NULL != pl->mq);
  /* find applicable HELLOs */
  fah.peer = pl;
  fah.result = NULL;
  fah.max_size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1;
  fah.next_adv = GNUNET_TIME_UNIT_FOREVER_REL;
  GNUNET_CONTAINER_multipeermap_iterate (peers,
                                         &find_advertisable_hello,
                                         &fah);
  pl->hello_delay_task =
      GNUNET_SCHEDULER_add_delayed (fah.next_adv,
                                    &schedule_next_hello,
                                    pl);
  if (NULL == fah.result)
    return;
  delay = GNUNET_TIME_absolute_get_remaining (pl->next_hello_allowed);
  if (0 != delay.rel_value_us)
    return;

  want = GNUNET_HELLO_size (fah.result->hello);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
	      "Sending HELLO with %u bytes",
	      (unsigned int) want);
  env = GNUNET_MQ_msg_copy (&fah.result->hello->header);
  GNUNET_MQ_send (pl->mq,
		  env);

  /* avoid sending this one again soon */
  GNUNET_CRYPTO_hash (&pl->pid,
		      sizeof (struct GNUNET_PeerIdentity),
		      &hc);
  GNUNET_CONTAINER_bloomfilter_add (fah.result->filter,
				    &hc);

  GNUNET_STATISTICS_update (stats,
			    gettext_noop ("# HELLO messages gossipped"),
			    1,
			    GNUNET_NO);
  /* prepare to send the next one */
  if (NULL != pl->hello_delay_task)
    GNUNET_SCHEDULER_cancel (pl->hello_delay_task);
  pl->next_hello_allowed
    = GNUNET_TIME_relative_to_absolute (HELLO_ADVERTISEMENT_MIN_FREQUENCY);
  pl->hello_delay_task
    = GNUNET_SCHEDULER_add_now (&schedule_next_hello,
				pl);
}
/**
 * Setup bloom filter for the given peer entry.
 *
 * @param peer entry to initialize
 */
static void
setup_filter (struct Peer *peer)
{
  /* 2^{-5} chance of not sending a HELLO to a peer is
   * acceptably small (if the filter is 50% full);
   * 64 bytes of memory are small compared to the rest
   * of the data structure and would only really become
   * "useless" once a HELLO has been passed on to ~100
   * other peers, which is likely more than enough in
   * any case; hence 64, 5 as bloomfilter parameters. */
  peer->filter = GNUNET_CONTAINER_bloomfilter_init (NULL, 64, 5);
  peer->filter_expiration =
      GNUNET_TIME_relative_to_absolute
      (HELLO_ADVERTISEMENT_MIN_REPEAT_FREQUENCY);
  /* never send a peer its own HELLO */
  GNUNET_CONTAINER_bloomfilter_add (peer->filter, &peer->pid.hashPubKey);
}
/**
 * Resize a bloom filter.  Note that this operation
 * is pretty costly.  Essentially, the bloom filter
 * needs to be completely re-build.
 *
 * @param bf the filter
 * @param iterator an iterator over all elements stored in the BF
 * @param iterator_cls argument to the iterator function
 * @param size the new size for the filter
 * @param k the new number of GNUNET_CRYPTO_hash-function to apply per element
 */
void
GNUNET_CONTAINER_bloomfilter_resize (struct GNUNET_CONTAINER_BloomFilter *bf,
                                     GNUNET_HashCodeIterator iterator,
                                     void *iterator_cls, size_t size,
                                     unsigned int k)
{
  GNUNET_HashCode hc;
  unsigned int i;

  GNUNET_free (bf->bitArray);
  i = 1;
  while (i < size)
    i *= 2;
  size = i;                     /* make sure it's a power of 2 */

  bf->bitArraySize = size;
  bf->bitArray = GNUNET_malloc (size);
  if (bf->filename != NULL)
    make_empty_file (bf->fh, bf->bitArraySize * 4LL);
  while (GNUNET_YES == iterator (iterator_cls, &hc))
    GNUNET_CONTAINER_bloomfilter_add (bf, &hc);
}
Exemple #5
0
/**
 * Store an item in the datastore.
 *
 * @param h handle to the datacache
 * @param key key to store data under
 * @param size number of bytes in data
 * @param data data to store
 * @param type type of the value
 * @param discard_time when to discard the value in any case
 * @param path_info_len number of entries in 'path_info'
 * @param path_info a path through the network
 * @return GNUNET_OK on success, GNUNET_SYSERR on error, GNUNET_NO if duplicate
 */
int
GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h,
                      const struct GNUNET_HashCode * key, size_t size,
                      const char *data, enum GNUNET_BLOCK_Type type,
                      struct GNUNET_TIME_Absolute discard_time,
		      unsigned int path_info_len,
		      const struct GNUNET_PeerIdentity *path_info)
{
  ssize_t used;

  used = h->api->put (h->api->cls, key, 
		      size, data, 
		      type, discard_time,
		      path_info_len, path_info);
  if (-1 == used)
  {
    GNUNET_break (0);
    return GNUNET_SYSERR;
  }
  if (0 == used)
  {
    /* duplicate */
    return GNUNET_NO;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG, "Stored data under key `%s' in cache\n",
       GNUNET_h2s (key));
  GNUNET_STATISTICS_update (h->stats, gettext_noop ("# bytes stored"), size,
                            GNUNET_NO);
  GNUNET_STATISTICS_update (h->stats, gettext_noop ("# items stored"), 1,
                            GNUNET_NO);
  if (NULL != h->filter)
    GNUNET_CONTAINER_bloomfilter_add (h->filter, key);
  while (h->utilization + used > h->env.quota)
    GNUNET_assert (GNUNET_OK == h->api->del (h->api->cls));
  h->utilization += used;
  return GNUNET_OK;
}
/**
 * Function to fill send buffer with HELLO.
 *
 * @param cls 'struct Peer' of the target peer
 * @param size number of bytes available in buf
 * @param buf where the callee should write the message
 * @return number of bytes written to buf
 */
static size_t
hello_advertising_ready (void *cls, size_t size, void *buf)
{
  struct Peer *pl = cls;
  struct FindAdvHelloContext fah;
  size_t want;

  pl->hello_req = NULL;
  GNUNET_assert (GNUNET_YES == pl->is_connected);
  /* find applicable HELLOs */
  fah.peer = pl;
  fah.result = NULL;
  fah.max_size = size;
  fah.next_adv = GNUNET_TIME_UNIT_FOREVER_REL;
  GNUNET_CONTAINER_multihashmap_iterate (peers, &find_advertisable_hello, &fah);
  want = 0;
  if (fah.result != NULL)
  {
    want = GNUNET_HELLO_size (fah.result->hello);
    GNUNET_assert (want <= size);
    memcpy (buf, fah.result->hello, want);
    GNUNET_CONTAINER_bloomfilter_add (fah.result->filter, &pl->pid.hashPubKey);
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' with %u bytes", "HELLO",
                (unsigned int) want);
    GNUNET_STATISTICS_update (stats,
                              gettext_noop ("# HELLO messages gossipped"), 1,
                              GNUNET_NO);
  }

  if (pl->hello_delay_task != GNUNET_SCHEDULER_NO_TASK)
    GNUNET_SCHEDULER_cancel (pl->hello_delay_task);
  pl->next_hello_allowed =
      GNUNET_TIME_relative_to_absolute (HELLO_ADVERTISEMENT_MIN_FREQUENCY);
  pl->hello_delay_task = GNUNET_SCHEDULER_add_now (&schedule_next_hello, pl);
  return want;
}
Exemple #7
0
/**
 * Store an item in the datastore.
 *
 * @param h handle to the datacache
 * @param key key to store data under
 * @param size number of bytes in data
 * @param data data to store
 * @param type type of the value
 * @param discard_time when to discard the value in any case
 * @return GNUNET_OK on success, GNUNET_SYSERR on error (full, etc.)
 */
int
GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h,
                      const GNUNET_HashCode * key, size_t size,
                      const char *data, enum GNUNET_BLOCK_Type type,
                      struct GNUNET_TIME_Absolute discard_time)
{
  uint32_t used;

  used = h->api->put (h->api->cls, key, size, data, type, discard_time);
  if (used == 0)
  {
    GNUNET_break (0);
    return GNUNET_SYSERR;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG, "Stored data under key `%s' in cache\n",
       GNUNET_h2s (key));
  GNUNET_STATISTICS_update (h->stats, gettext_noop ("# bytes stored"), size,
                            GNUNET_NO);
  GNUNET_CONTAINER_bloomfilter_add (h->filter, key);
  while (h->utilization + used > h->env.quota)
    GNUNET_assert (GNUNET_OK == h->api->del (h->api->cls));
  h->utilization += used;
  return GNUNET_OK;
}
int
main (int argc, char *argv[])
{
  struct GNUNET_CONTAINER_BloomFilter *bf;
  struct GNUNET_CONTAINER_BloomFilter *bfi;
  GNUNET_HashCode tmp;
  int i;
  int ok1;
  int ok2;
  int falseok;
  char buf[SIZE];
  struct stat sbuf;

  GNUNET_log_setup ("test-container-bloomfilter", "WARNING", NULL);
  GNUNET_CRYPTO_seed_weak_random (1);
  if (0 == STAT (TESTFILE, &sbuf))
    if (0 != UNLINK (TESTFILE))
      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "unlink", TESTFILE);
  bf = GNUNET_CONTAINER_bloomfilter_load (TESTFILE, SIZE, K);

  for (i = 0; i < 200; i++)
  {
    nextHC (&tmp);
    GNUNET_CONTAINER_bloomfilter_add (bf, &tmp);
  }
  GNUNET_CRYPTO_seed_weak_random (1);
  ok1 = 0;
  for (i = 0; i < 200; i++)
  {
    nextHC (&tmp);
    if (GNUNET_CONTAINER_bloomfilter_test (bf, &tmp) == GNUNET_YES)
      ok1++;
  }
  if (ok1 != 200)
  {
    printf ("Got %d elements out of" "200 expected after insertion.\n", ok1);
    GNUNET_CONTAINER_bloomfilter_free (bf);
    return -1;
  }
  if (GNUNET_OK != GNUNET_CONTAINER_bloomfilter_get_raw_data (bf, buf, SIZE))
  {
    GNUNET_CONTAINER_bloomfilter_free (bf);
    return -1;
  }

  GNUNET_CONTAINER_bloomfilter_free (bf);

  bf = GNUNET_CONTAINER_bloomfilter_load (TESTFILE, SIZE, K);
  GNUNET_assert (bf != NULL);
  bfi = GNUNET_CONTAINER_bloomfilter_init (buf, SIZE, K);
  GNUNET_assert (bfi != NULL);

  GNUNET_CRYPTO_seed_weak_random (1);
  ok1 = 0;
  ok2 = 0;
  for (i = 0; i < 200; i++)
  {
    nextHC (&tmp);
    if (GNUNET_CONTAINER_bloomfilter_test (bf, &tmp) == GNUNET_YES)
      ok1++;
    if (GNUNET_CONTAINER_bloomfilter_test (bfi, &tmp) == GNUNET_YES)
      ok2++;
  }
  if (ok1 != 200)
  {
    printf ("Got %d elements out of 200 " "expected after reloading.\n", ok1);
    GNUNET_CONTAINER_bloomfilter_free (bf);
    GNUNET_CONTAINER_bloomfilter_free (bfi);
    return -1;
  }

  if (ok2 != 200)
  {
    printf ("Got %d elements out of 200 " "expected after initialization.\n",
            ok2);
    GNUNET_CONTAINER_bloomfilter_free (bf);
    GNUNET_CONTAINER_bloomfilter_free (bfi);
    return -1;
  }

  GNUNET_CRYPTO_seed_weak_random (1);
  for (i = 0; i < 100; i++)
  {
    nextHC (&tmp);
    GNUNET_CONTAINER_bloomfilter_remove (bf, &tmp);
    GNUNET_CONTAINER_bloomfilter_remove (bfi, &tmp);
  }

  GNUNET_CRYPTO_seed_weak_random (1);

  ok1 = 0;
  ok2 = 0;
  for (i = 0; i < 200; i++)
  {
    nextHC (&tmp);
    if (GNUNET_CONTAINER_bloomfilter_test (bf, &tmp) == GNUNET_YES)
      ok1++;
    if (GNUNET_CONTAINER_bloomfilter_test (bfi, &tmp) == GNUNET_YES)
      ok2++;
  }

  if (ok1 != 100)
  {
    printf ("Expected 100 elements in loaded filter"
            " after adding 200 and deleting 100, got %d\n", ok1);
    GNUNET_CONTAINER_bloomfilter_free (bf);
    GNUNET_CONTAINER_bloomfilter_free (bfi);
    return -1;
  }
  if (ok2 != 200)
  {
    printf ("Expected 200 elements in initialized filter"
            " after adding 200 and deleting 100 "
            "(which should do nothing for a filter not backed by a file), got %d\n",
            ok2);
    GNUNET_CONTAINER_bloomfilter_free (bf);
    GNUNET_CONTAINER_bloomfilter_free (bfi);
    return -1;
  }

  GNUNET_CRYPTO_seed_weak_random (3);

  GNUNET_CONTAINER_bloomfilter_clear (bf);
  falseok = 0;
  for (i = 0; i < 1000; i++)
  {
    nextHC (&tmp);
    if (GNUNET_CONTAINER_bloomfilter_test (bf, &tmp) == GNUNET_YES)
      falseok++;
  }
  if (falseok > 0)
  {
    GNUNET_CONTAINER_bloomfilter_free (bf);
    GNUNET_CONTAINER_bloomfilter_free (bfi);
    return -1;
  }

  if (GNUNET_OK != GNUNET_CONTAINER_bloomfilter_or (bf, buf, SIZE))
  {
    GNUNET_CONTAINER_bloomfilter_free (bf);
    GNUNET_CONTAINER_bloomfilter_free (bfi);
    return -1;
  }

  GNUNET_CRYPTO_seed_weak_random (2);
  i = 20;
  GNUNET_CONTAINER_bloomfilter_resize (bfi, &add_iterator, &i, SIZE * 2, K);

  GNUNET_CRYPTO_seed_weak_random (2);
  i = 20;
  GNUNET_CONTAINER_bloomfilter_resize (bf, &add_iterator, &i, SIZE * 2, K);
  GNUNET_CRYPTO_seed_weak_random (2);

  ok1 = 0;
  ok2 = 0;
  for (i = 0; i < 20; i++)
  {
    nextHC (&tmp);
    if (GNUNET_CONTAINER_bloomfilter_test (bf, &tmp) == GNUNET_YES)
      ok1++;
    if (GNUNET_CONTAINER_bloomfilter_test (bfi, &tmp) == GNUNET_YES)
      ok2++;
  }

  if (ok1 != 20)
  {
    printf ("Expected 20 elements in resized file-backed filter"
            " after adding 20, got %d\n", ok1);
    GNUNET_CONTAINER_bloomfilter_free (bf);
    GNUNET_CONTAINER_bloomfilter_free (bfi);
    return -1;
  }
  if (ok2 != 20)
  {
    printf ("Expected 20 elements in resized filter"
            " after adding 20, got %d\n", ok2);
    GNUNET_CONTAINER_bloomfilter_free (bf);
    GNUNET_CONTAINER_bloomfilter_free (bfi);
    return -1;
  }


  GNUNET_CONTAINER_bloomfilter_free (bf);
  GNUNET_CONTAINER_bloomfilter_free (bfi);

  GNUNET_break (0 == UNLINK (TESTFILE));
  return 0;
}
Exemple #9
0
/**
 * Function called to validate a reply or a request of type
 * #GNUNET_BLOCK_TYPE_REGEX.
 * For request evaluation, pass "NULL" for the reply_block.
 * Note that it is assumed that the reply has already been
 * matched to the key (and signatures checked) as it would
 * be done with the #GNUNET_BLOCK_get_key() function.
 *
 * @param cls closure
 * @param type block type
 * @param eo control flags
 * @param query original query (hash)
 * @param bf pointer to bloom filter associated with query; possibly updated (!)
 * @param bf_mutator mutation value for bf
 * @param xquery extrended query data (can be NULL, depending on type)
 * @param xquery_size number of bytes in @a xquery
 * @param reply_block response to validate
 * @param reply_block_size number of bytes in @a reply_block
 * @return characterization of result
 */
static enum GNUNET_BLOCK_EvaluationResult
evaluate_block_regex (void *cls,
                      enum GNUNET_BLOCK_Type type,
                      enum GNUNET_BLOCK_EvaluationOptions eo,
                      const struct GNUNET_HashCode *query,
                      struct GNUNET_CONTAINER_BloomFilter **bf,
                      int32_t bf_mutator,
                      const void *xquery,
                      size_t xquery_size,
                      const void *reply_block,
                      size_t reply_block_size)
{
  if (NULL == reply_block)
  {
    if (0 != xquery_size)
      {
        const char *s;

        s = (const char *) xquery;
        if ('\0' != s[xquery_size - 1]) /* must be valid 0-terminated string */
          {
            GNUNET_break_op (0);
            return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
          }
      }
    return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
  }
  if (0 != xquery_size)
  {
    const char *s;

    s = (const char *) xquery;
    if ('\0' != s[xquery_size - 1]) /* must be valid 0-terminated string */
    {
      GNUNET_break_op (0);
      return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
    }
  }
  else if (NULL != query)
  {
    /* xquery is required for regex GETs, at least an empty string */
    GNUNET_break_op (0);
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "type %d, query %p, xquery %p\n",
                type, query, xquery);
    return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
  }
  switch (REGEX_BLOCK_check (reply_block,
			     reply_block_size,
			     query,
			     xquery))
  {
    case GNUNET_SYSERR:
      GNUNET_break_op(0);
      return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
    case GNUNET_NO:
      /* xquery missmatch, can happen */
      return GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT;
    default:
      break;
  }
  if (NULL != bf)
  {
    struct GNUNET_HashCode chash;
    struct GNUNET_HashCode mhash;

    GNUNET_CRYPTO_hash (reply_block, reply_block_size, &chash);
    GNUNET_BLOCK_mingle_hash (&chash, bf_mutator, &mhash);
    if (NULL != *bf)
    {
      if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (*bf, &mhash))
        return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
    }
    else
    {
      *bf = GNUNET_CONTAINER_bloomfilter_init (NULL, 8, GNUNET_CONSTANTS_BLOOMFILTER_K);
    }
    GNUNET_CONTAINER_bloomfilter_add (*bf, &mhash);
  }
  return GNUNET_BLOCK_EVALUATION_OK_MORE;
}
Exemple #10
0
/**
 * Function called to validate a reply or a request of type
 * #GNUNET_BLOCK_TYPE_REGEX_ACCEPT.
 * For request evaluation, pass "NULL" for the reply_block.
 * Note that it is assumed that the reply has already been
 * matched to the key (and signatures checked) as it would
 * be done with the #GNUNET_BLOCK_get_key() function.
 *
 * @param cls closure
 * @param type block type
 * @param eo control flags
 * @param query original query (hash)
 * @param bf pointer to bloom filter associated with query; possibly updated (!)
 * @param bf_mutator mutation value for bf
 * @param xquery extrended query data (can be NULL, depending on type)
 * @param xquery_size number of bytes in @a xquery
 * @param reply_block response to validate
 * @param reply_block_size number of bytes in @a reply_block
 * @return characterization of result
 */
static enum GNUNET_BLOCK_EvaluationResult
evaluate_block_regex_accept (void *cls,
                             enum GNUNET_BLOCK_Type type,
                             enum GNUNET_BLOCK_EvaluationOptions eo,
                             const struct GNUNET_HashCode * query,
                             struct GNUNET_CONTAINER_BloomFilter **bf,
                             int32_t bf_mutator, const void *xquery,
                             size_t xquery_size, const void *reply_block,
                             size_t reply_block_size)
{
  const struct RegexAcceptBlock *rba;

  if (0 != xquery_size)
  {
    GNUNET_break_op (0);
    return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
  }
  if (NULL == reply_block)
    return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
  if (sizeof (struct RegexAcceptBlock) != reply_block_size)
  {
    GNUNET_break_op(0);
    return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
  }
  rba = reply_block;
  if (ntohl (rba->purpose.size) !=
      sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
      sizeof (struct GNUNET_TIME_AbsoluteNBO) +
      sizeof (struct GNUNET_HashCode))
  {
    GNUNET_break_op(0);
    return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
  }
  if (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (rba->expiration_time)).rel_value_us)
  {
    /* technically invalid, but can happen without an error, so
       we're nice by reporting it as a 'duplicate' */
    return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
  }
  if (GNUNET_OK !=
      GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_REGEX_ACCEPT,
				&rba->purpose,
				&rba->signature,
				&rba->peer.public_key))
  {
    GNUNET_break_op(0);
    return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
  }
  if (NULL != bf)
  {
    struct GNUNET_HashCode chash;
    struct GNUNET_HashCode mhash;

    GNUNET_CRYPTO_hash (reply_block, reply_block_size, &chash);
    GNUNET_BLOCK_mingle_hash (&chash, bf_mutator, &mhash);
    if (NULL != *bf)
    {
      if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (*bf, &mhash))
        return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
    }
    else
    {
      *bf = GNUNET_CONTAINER_bloomfilter_init (NULL, 8, GNUNET_CONSTANTS_BLOOMFILTER_K);
    }
    GNUNET_CONTAINER_bloomfilter_add (*bf, &mhash);
  }
  return GNUNET_BLOCK_EVALUATION_OK_MORE;
}
Exemple #11
0
/**
 * Function called to validate a reply or a request.  For
 * request evaluation, simply pass "NULL" for the @a reply_block.
 *
 * @param cls closure
 * @param type block type
 * @param eo control flags
 * @param query original query (hash)
 * @param bf pointer to bloom filter associated with query; possibly updated (!)
 * @param bf_mutator mutation value for @a bf
 * @param xquery extended query data (can be NULL, depending on type)
 * @param xquery_size number of bytes in @a xquery
 * @param reply_block response to validate
 * @param reply_block_size number of bytes in @a reply_block
 * @return characterization of result
 */
static enum GNUNET_BLOCK_EvaluationResult
block_plugin_dht_evaluate (void *cls,
                           enum GNUNET_BLOCK_Type type,
                           enum GNUNET_BLOCK_EvaluationOptions eo,
                           const struct GNUNET_HashCode *query,
                           struct GNUNET_CONTAINER_BloomFilter **bf,
                           int32_t bf_mutator,
                           const void *xquery,
                           size_t xquery_size,
                           const void *reply_block,
                           size_t reply_block_size)
{
  struct GNUNET_HashCode mhash;
  const struct GNUNET_HELLO_Message *hello;
  struct GNUNET_PeerIdentity pid;
  const struct GNUNET_MessageHeader *msg;
  struct GNUNET_HashCode phash;

  if (type != GNUNET_BLOCK_TYPE_DHT_HELLO)
    return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
  if (xquery_size != 0)
  {
    GNUNET_break_op (0);
    return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
  }
  if (NULL == reply_block)
    return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
  if (reply_block_size < sizeof (struct GNUNET_MessageHeader))
  {
    GNUNET_break_op (0);
    return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
  }
  msg = reply_block;
  if (reply_block_size != ntohs (msg->size))
  {
    GNUNET_break_op (0);
    return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
  }
  hello = reply_block;
  if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid))
  {
    GNUNET_break_op (0);
    return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
  }
  if (NULL != bf)
  {
    GNUNET_CRYPTO_hash (&pid, sizeof (pid), &phash);
    GNUNET_BLOCK_mingle_hash (&phash, bf_mutator, &mhash);
    if (NULL != *bf)
    {
      if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (*bf, &mhash))
        return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
    }
    else
    {
      *bf = GNUNET_CONTAINER_bloomfilter_init (NULL, 8,
                                               GNUNET_CONSTANTS_BLOOMFILTER_K);
    }
    GNUNET_CONTAINER_bloomfilter_add (*bf, &mhash);
  }
  return GNUNET_BLOCK_EVALUATION_OK_MORE;
}
/**
 * Function called to validate a reply or a request.  For
 * request evaluation, simply pass "NULL" for the reply_block.
 * Note that it is assumed that the reply has already been
 * matched to the key (and signatures checked) as it would
 * be done with the "get_key" function.
 *
 * @param cls closure
 * @param type block type
 * @param query original query (hash)
 * @param bf pointer to bloom filter associated with @a query; possibly updated (!)
 * @param bf_mutator mutation value for @a bf
 * @param xquery extrended query data (can be NULL, depending on @a type)
 * @param xquery_size number of bytes in @a xquery
 * @param reply_block response to validate
 * @param reply_block_size number of bytes in @a reply_block
 * @return characterization of result
 */
static enum GNUNET_BLOCK_EvaluationResult
block_plugin_gns_evaluate (void *cls, enum GNUNET_BLOCK_Type type,
                          const struct GNUNET_HashCode *query,
                          struct GNUNET_CONTAINER_BloomFilter **bf,
                          int32_t bf_mutator, const void *xquery,
                          size_t xquery_size, const void *reply_block,
                          size_t reply_block_size)
{
  const struct GNUNET_GNSRECORD_Block *block;
  struct GNUNET_HashCode h;
  struct GNUNET_HashCode chash;
  struct GNUNET_HashCode mhash;

  if (type != GNUNET_BLOCK_TYPE_GNS_NAMERECORD)
    return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
  if (NULL == reply_block)
  {
    if (0 != xquery_size)
    {
      GNUNET_break_op (0);
      return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
    }
    return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
  }

  /* this is a reply */
  if (reply_block_size < sizeof (struct GNUNET_GNSRECORD_Block))
    {
      GNUNET_break_op (0);
      return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
    }
  block = reply_block;
  if (ntohl (block->purpose.size) + sizeof (struct GNUNET_CRYPTO_EcdsaSignature) + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) !=
      reply_block_size)
    {
      GNUNET_break_op (0);
      return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
    }
  GNUNET_CRYPTO_hash (&block->derived_key,
		      sizeof (block->derived_key),
		      &h);
  if (0 != memcmp (&h, query, sizeof (struct GNUNET_HashCode)))
    {
      GNUNET_break_op (0);
      return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
    }
  if (GNUNET_OK !=
      GNUNET_GNSRECORD_block_verify (block))
    {
      GNUNET_break_op (0);
      return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
    }
  if (NULL != bf)
    {
      GNUNET_CRYPTO_hash (reply_block, reply_block_size, &chash);
      GNUNET_BLOCK_mingle_hash (&chash, bf_mutator, &mhash);
      if (NULL != *bf)
	{
	  if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test(*bf, &mhash))
	    return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
	}
      else
	{
	  *bf = GNUNET_CONTAINER_bloomfilter_init(NULL, 8, BLOOMFILTER_K);
	}
      GNUNET_CONTAINER_bloomfilter_add(*bf, &mhash);
    }
  return GNUNET_BLOCK_EVALUATION_OK_MORE;
}