DNS Poisoning

cache.c
/* Search the cache for a matching entry and return it when found.  If
   this fails search the negative cache and return (void *) -1 if this
   search was successful.  Otherwise return NULL.

   This function must be called with the read-lock held.  */
struct datahead *
cache_search (request_type type, const void *key, size_t len,
          struct database_dyn *table, uid_t owner)
{
  unsigned long int hash = __nss_hash (key, len) % table->head->module;

  unsigned long int nsearched = 0;
  struct datahead *result = NULL;

  ref_t work = table->head->array[hash];
  while (work != ENDREF)
    {
      ++nsearched;

      struct hashentry *here = (struct hashentry *) (table->data + work);

      if (type == here->type && len == here->len
      && memcmp (key, table->data + here->key, len) == 0
      && here->owner == owner)
    {
      /* We found the entry.  Increment the appropriate counter.  */
      struct datahead *dh
        = (struct datahead *) (table->data + here->packet);

      /* See whether we must ignore the entry.  */
      if (dh->usable)
        {
          /* We do not synchronize the memory here.  The statistics
         data is not crucial, we synchronize only once in a while
         in the cleanup threads.  */
          if (dh->notfound)
        ++table->head->neghit;
          else
        {
          ++table->head->poshit;

          if (dh->nreloads != 0)
            dh->nreloads = 0;
        }

          result = dh;
          break;
        }
    }

      work = here->next;
    }

  if (nsearched > table->head->maxnsearched)
    table->head->maxnsearched = nsearched;

  return result;
}