2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 05:57:52 +00:00

Merge branch '178-cleanup-isc_hash-functions' into 'master'

Clean up the isc_hash_* family of functions

See merge request isc-projects/bind9!160
This commit is contained in:
Ondřej Surý 2018-04-04 17:19:41 -04:00
commit ab992d40b0
35 changed files with 37 additions and 813 deletions

View File

@ -1,3 +1,6 @@
4919. [cleanup] Clean up the isc_hash_* namespace and leave only
the FNV-1a hash implementation. [GL #188]
4918. [bug] Fix double free after keygen error in dnssec-keygen
when OpenSSL >= 1.1.0 is used and RSA_generate_key_ex
fails. [GL #109]

View File

@ -656,9 +656,6 @@ main(int argc, char **argv) {
RUNTIME_CHECK(setup_logging(mctx, stdout, &logc) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
== ISC_R_SUCCESS);
dns_result_register();
RUNTIME_CHECK(cfg_parser_create(mctx, logc, &parser) == ISC_R_SUCCESS);
@ -689,7 +686,6 @@ main(int argc, char **argv) {
isc_log_destroy(&logc);
isc_hash_destroy();
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);

View File

@ -523,8 +523,6 @@ main(int argc, char **argv) {
RUNTIME_CHECK(setup_logging(mctx, errout, &lctx)
== ISC_R_SUCCESS);
RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
== ISC_R_SUCCESS);
dns_result_register();
@ -556,7 +554,6 @@ main(int argc, char **argv) {
destroy();
if (lctx != NULL)
isc_log_destroy(&lctx);
isc_hash_destroy();
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
#ifdef _WIN32

View File

@ -1234,10 +1234,6 @@ main(int argc, char *argv[]) {
if (ectx == NULL) {
setup_entropy(mctx, NULL, &ectx);
}
result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
if (result != ISC_R_SUCCESS) {
fatal("could not initialize hash");
}
result = dst_lib_init(mctx, ectx,
ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY);
if (result != ISC_R_SUCCESS) {
@ -1394,7 +1390,6 @@ main(int argc, char *argv[]) {
free_all_sets();
cleanup_logging(&lctx);
dst_lib_destroy();
isc_hash_destroy();
cleanup_entropy(&ectx);
if (verbose > 10) {
isc_mem_stats(mctx, stdout);

View File

@ -484,9 +484,6 @@ main(int argc, char **argv) {
if (result != ISC_R_SUCCESS)
fatal("could not initialize dst: %s",
isc_result_totext(result));
result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
if (result != ISC_R_SUCCESS)
fatal("could not initialize hash");
isc_entropy_stopcallbacksources(ectx);
setup_logging(mctx, &log);
@ -548,7 +545,6 @@ main(int argc, char **argv) {
if (dns_rdataset_isassociated(&rdataset))
dns_rdataset_disassociate(&rdataset);
cleanup_logging(&log);
isc_hash_destroy();
dst_lib_destroy();
cleanup_entropy(&ectx);
dns_name_destroy();

View File

@ -413,9 +413,6 @@ main(int argc, char **argv) {
if (result != ISC_R_SUCCESS)
fatal("could not initialize dst: %s",
isc_result_totext(result));
result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
if (result != ISC_R_SUCCESS)
fatal("could not initialize hash");
isc_entropy_stopcallbacksources(ectx);
setup_logging(mctx, &log);
@ -459,7 +456,6 @@ main(int argc, char **argv) {
if (dns_rdataset_isassociated(&rdataset))
dns_rdataset_disassociate(&rdataset);
cleanup_logging(&log);
isc_hash_destroy();
dst_lib_destroy();
cleanup_entropy(&ectx);
dns_name_destroy();

View File

@ -187,9 +187,6 @@ main(int argc, char **argv) {
if (result != ISC_R_SUCCESS)
fatal("Could not initialize dst: %s",
isc_result_totext(result));
result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
if (result != ISC_R_SUCCESS)
fatal("Could not initialize hash");
isc_entropy_stopcallbacksources(ectx);
result = dst_key_fromnamedfile(filename, dir,
@ -271,7 +268,6 @@ main(int argc, char **argv) {
cleanup:
dst_key_free(&key);
isc_hash_destroy();
dst_lib_destroy();
cleanup_entropy(&ectx);
if (verbose > 10)

View File

@ -385,9 +385,6 @@ main(int argc, char **argv) {
if (result != ISC_R_SUCCESS)
fatal("Could not initialize dst: %s",
isc_result_totext(result));
result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
if (result != ISC_R_SUCCESS)
fatal("Could not initialize hash");
isc_entropy_stopcallbacksources(ectx);
if (predecessor != NULL) {
@ -672,7 +669,6 @@ main(int argc, char **argv) {
if (prevkey != NULL)
dst_key_free(&prevkey);
dst_key_free(&key);
isc_hash_destroy();
dst_lib_destroy();
cleanup_entropy(&ectx);
if (verbose > 10)

View File

@ -3508,10 +3508,6 @@ main(int argc, char *argv[]) {
fatal("could not initialize dst: %s",
isc_result_totext(result));
result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
if (result != ISC_R_SUCCESS)
fatal("could not create hash context");
isc_stdtime_get(&now);
if (startstr != NULL) {
@ -3925,7 +3921,6 @@ main(int argc, char *argv[]) {
dns_master_styledestroy(&dsstyle, mctx);
cleanup_logging(&log);
isc_hash_destroy();
dst_lib_destroy();
cleanup_entropy(&ectx);
dns_name_destroy();

View File

@ -286,10 +286,6 @@ main(int argc, char *argv[]) {
fatal("could not initialize dst: %s",
isc_result_totext(result));
result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
if (result != ISC_R_SUCCESS)
fatal("could not create hash context");
isc_stdtime_get(&now);
rdclass = strtoclass(classname);
@ -340,7 +336,6 @@ main(int argc, char *argv[]) {
cleanup_logging(&log);
dst_lib_destroy();
isc_hash_destroy();
cleanup_entropy(&ectx);
dns_name_destroy();
if (verbose > 10)

View File

@ -852,15 +852,6 @@ create_managers(void) {
return (ISC_R_UNEXPECTED);
}
result = isc_hash_create(named_g_mctx, named_g_entropy,
DNS_NAME_MAXWIRE);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_hash_create() failed: %s",
isc_result_totext(result));
return (ISC_R_UNEXPECTED);
}
return (ISC_R_SUCCESS);
}
@ -872,13 +863,6 @@ destroy_managers(void) {
isc_taskmgr_destroy(&named_g_taskmgr);
isc_timermgr_destroy(&named_g_timermgr);
isc_socketmgr_destroy(&named_g_socketmgr);
/*
* isc_hash_destroy() cannot be called as long as a resolver may be
* running. Calling this after isc_taskmgr_destroy() ensures the
* call is safe.
*/
isc_hash_destroy();
}
static void

View File

@ -9247,8 +9247,6 @@ run_server(isc_task_t *task, isc_event_t *event) {
CHECKFATAL(load_configuration(named_g_conffile, server, ISC_TRUE),
"loading configuration");
isc_hash_init();
CHECKFATAL(load_zones(server, ISC_TRUE, ISC_FALSE), "loading zones");
#ifdef ENABLE_AFL
named_g_run_done = ISC_TRUE;

View File

@ -971,9 +971,6 @@ setup_system(void) {
if (entropy == NULL)
setup_entropy(gmctx, NULL, &entropy);
result = isc_hash_create(gmctx, entropy, DNS_NAME_MAXWIRE);
check_result(result, "isc_hash_create");
result = dns_dispatchmgr_create(gmctx, entropy, &dispatchmgr);
check_result(result, "dns_dispatchmgr_create");
@ -996,9 +993,6 @@ setup_system(void) {
check_result(result, "dst_lib_init");
is_dst_up = ISC_TRUE;
/* moved after dst_lib_init() */
isc_hash_init();
attrmask = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
@ -3305,9 +3299,6 @@ cleanup(void) {
ddebug("Shutting down timer manager");
isc_timermgr_destroy(&timermgr);
ddebug("Destroying hash context");
isc_hash_destroy();
ddebug("Destroying name state");
dns_name_destroy();

View File

@ -40,7 +40,7 @@ isc_mem_t *mctx = NULL;
isc_log_t *lctx = NULL;
isc_entropy_t *ectx = NULL;
static isc_boolean_t hash_active = ISC_FALSE, dst_active = ISC_FALSE;
static isc_boolean_t dst_active = ISC_FALSE;
/*
* Logging categories: this needs to match the list in bin/named/log.c.
@ -104,9 +104,6 @@ main(int argc, char **argv) {
CHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING));
dst_active = ISC_TRUE;
CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE));
hash_active = ISC_TRUE;
CHECK(isc_log_create(mctx, &lctx, &logconfig));
isc_log_registercategories(lctx, categories);
isc_log_setcontext(lctx);
@ -153,10 +150,6 @@ main(int argc, char **argv) {
dst_lib_destroy();
dst_active = ISC_FALSE;
}
if (hash_active) {
isc_hash_destroy();
hash_active = ISC_FALSE;
}
if (ectx != NULL)
isc_entropy_detach(&ectx);
if (mctx != NULL)

View File

@ -306,9 +306,6 @@ main(int argc, char **argv) {
result = isc_entropy_create(mctx, &ectx);
check_result(result, "isc_entropy_create()");
result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
check_result(result, "isc_hash_create()");
result = isc_log_create(mctx, &lctx, &lcfg);
check_result(result, "isc_log_create()");
isc_log_setcontext(lctx);
@ -418,7 +415,6 @@ main(int argc, char **argv) {
isc_log_destroy(&lctx);
isc_hash_destroy();
isc_entropy_detach(&ectx);
isc_mempool_destroy(&cmp);

View File

@ -209,8 +209,6 @@ main(int argc, char *argv[]) {
RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
== ISC_R_SUCCESS);
while ((ch = isc_commandline_parse(argc, argv, "d:vw:")) != -1) {
switch (ch) {
@ -356,7 +354,6 @@ main(int argc, char *argv[]) {
isc_log_destroy(&lctx);
isc_hash_destroy();
isc_entropy_detach(&ectx);
if (verbose)

View File

@ -285,7 +285,6 @@ main(int argc, char *argv[]) {
RUNCHECK(isc_entropy_createfilesource(ectx, randomfile));
RUNCHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_GOODONLY));
RUNCHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE));
taskmgr = NULL;
RUNCHECK(isc_taskmgr_create(mctx, 1, 0, &taskmgr));
@ -338,7 +337,6 @@ main(int argc, char *argv[]) {
isc_task_detach(&task);
isc_taskmgr_destroy(&taskmgr);
isc_hash_destroy();
dst_lib_destroy();
isc_entropy_detach(&ectx);

View File

@ -265,7 +265,6 @@ main(int argc, char *argv[]) {
RUNCHECK(isc_log_create(mctx, &log, &logconfig));
RUNCHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_GOODONLY));
RUNCHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE));
taskmgr = NULL;
RUNCHECK(isc_taskmgr_create(mctx, 1, 0, &taskmgr));
@ -344,7 +343,6 @@ main(int argc, char *argv[]) {
isc_log_destroy(&log);
isc_hash_destroy();
dst_lib_destroy();
isc_entropy_detach(&ectx);

View File

@ -196,7 +196,6 @@ main(int argc, char **argv) {
RUNCHECK(isc_log_create(mctx, &log, &logconfig));
RUNCHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_GOODONLY));
RUNCHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE));
taskmgr = NULL;
RUNCHECK(isc_taskmgr_create(mctx, 1, 0, &taskmgr));
@ -279,7 +278,6 @@ main(int argc, char **argv) {
isc_log_destroy(&log);
isc_hash_destroy();
dst_lib_destroy();
isc_entropy_detach(&ectx);

View File

@ -1935,7 +1935,6 @@ main(int argc, char *argv[]) {
ectx = NULL;
RUNCHECK(isc_entropy_create(mctx, &ectx));
RUNCHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_GOODONLY));
RUNCHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE));
RUNCHECK(isc_entropy_getdata(ectx, cookie_secret,
sizeof(cookie_secret), NULL, 0));
@ -2037,7 +2036,6 @@ main(int argc, char *argv[]) {
isc_taskmgr_destroy(&taskmgr);
dst_lib_destroy();
isc_hash_destroy();
isc_entropy_detach(&ectx);
isc_log_destroy(&lctx);

View File

@ -217,9 +217,6 @@ main (int argc, char **argv)
result = isc_entropy_create(mctx, &ectx);
isc_result_check (result, "isc_entropy_create");
result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
isc_result_check (result, "isc_hash_create");
isc_buffer_init (&buff, argzone, strlen (argzone));
isc_buffer_add (&buff, strlen (argzone));
dns_fixedname_init (&fixedzone);
@ -348,7 +345,6 @@ main (int argc, char **argv)
printf("Operation Complete.\n");
/* Cleanup */
isc_hash_destroy();
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
if (zonefile)

View File

@ -161,9 +161,6 @@ main(int argc, char **argv) {
result = isc_entropy_create(mctx, &ectx);
check_result(result, "isc_entropy_create");
result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
check_result(result, "isc_hash_create");
isc_buffer_init(&b, porigin, strlen(porigin));
isc_buffer_add(&b, strlen(porigin));
dns_fixedname_init(&forigin);
@ -278,7 +275,6 @@ main(int argc, char **argv) {
PQclear(res);
dns_dbiterator_destroy(&dbiter);
dns_db_detach(&db);
isc_hash_destroy();
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
closeandexit(0);

View File

@ -169,8 +169,6 @@ main(int argc, char *argv[])
check_result(result, "isc_mem_create");
result = isc_entropy_create(mctx, &ectx);
check_result(result, "isc_entropy_create");
result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
check_result(result, "isc_hash_create");
isc_buffer_init(&b, porigin, strlen(porigin));
isc_buffer_add(&b, strlen(porigin));
@ -288,7 +286,6 @@ main(int argc, char *argv[])
dns_dbiterator_destroy(&dbiter);
dns_db_detach(&db);
isc_hash_destroy();
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);

View File

@ -372,26 +372,6 @@ dns_name_fullhash(const dns_name_t *name, isc_boolean_t case_sensitive);
*\li A hash value
*/
unsigned int
dns_name_hashbylabel(const dns_name_t *name, isc_boolean_t case_sensitive);
/*%<
* Provide a hash value for 'name', where the hash value is the sum
* of the hash values of each label. This function should only be used
* when incremental hashing is necessary, for example, during RBT
* traversal. It is not currently used in BIND. Generally,
* dns_name_fullhash() is the correct function to use for name
* hashing.
*
* Note: if 'case_sensitive' is ISC_FALSE, then names which differ only in
* case will have the same hash value.
*
* Requires:
*\li 'name' is a valid name
*
* Returns:
*\li A hash value
*/
/*
*** Comparisons
***/

View File

@ -90,19 +90,15 @@ initialize(void) {
result = isc_entropy_create(dns_g_mctx, &ectx);
if (result != ISC_R_SUCCESS)
goto cleanup_db;
result = isc_hash_create(dns_g_mctx, NULL, DNS_NAME_MAXWIRE);
if (result != ISC_R_SUCCESS)
goto cleanup_ectx;
result = dst_lib_init(dns_g_mctx, ectx, 0);
if (result != ISC_R_SUCCESS)
goto cleanup_hash;
goto cleanup_ectx;
result = isc_mutex_init(&reflock);
if (result != ISC_R_SUCCESS)
goto cleanup_dst;
isc_hash_init();
isc_entropy_detach(&ectx);
initialize_done = ISC_TRUE;
@ -113,8 +109,6 @@ initialize(void) {
cleanup_ectx:
if (ectx != NULL)
isc_entropy_detach(&ectx);
cleanup_hash:
isc_hash_destroy();
cleanup_db:
if (dbimp != NULL)
dns_ecdb_unregister(&dbimp);
@ -160,8 +154,6 @@ dns_lib_shutdown(void) {
dst_lib_destroy();
if (isc_hashctx != NULL)
isc_hash_destroy();
if (dbimp != NULL)
dns_ecdb_unregister(&dbimp);
if (dns_g_mctx != NULL)

View File

@ -161,9 +161,6 @@ static dns_name_t const wild =
LIBDNS_EXTERNAL_DATA const dns_name_t *dns_wildcardname = &wild;
unsigned int
dns_fullname_hash(const dns_name_t *name, isc_boolean_t case_sensitive);
/*
* dns_name_t to text post-conversion procedure.
*/
@ -489,52 +486,6 @@ dns_name_fullhash(const dns_name_t *name, isc_boolean_t case_sensitive) {
case_sensitive, NULL));
}
unsigned int
dns_fullname_hash(const dns_name_t *name, isc_boolean_t case_sensitive) {
/*
* This function was deprecated due to the breakage of the name space
* convention. We only keep this internally to provide binary backward
* compatibility.
*/
return (dns_name_fullhash(name, case_sensitive));
}
unsigned int
dns_name_hashbylabel(const dns_name_t *name, isc_boolean_t case_sensitive) {
unsigned char *offsets;
dns_offsets_t odata;
dns_name_t tname;
unsigned int h = 0;
unsigned int i;
/*
* Provide a hash value for 'name'.
*/
REQUIRE(VALID_NAME(name));
if (name->labels == 0)
return (0);
else if (name->labels == 1)
return (isc_hash_function_reverse(name->ndata, name->length,
case_sensitive, NULL));
SETUP_OFFSETS(name, offsets, odata);
DNS_NAME_INIT(&tname, NULL);
tname.labels = 1;
h = 0;
for (i = 0; i < name->labels; i++) {
tname.ndata = name->ndata + offsets[i];
if (i == name->labels - 1)
tname.length = name->length - offsets[i];
else
tname.length = offsets[i + 1] - offsets[i];
h += isc_hash_function_reverse(tname.ndata, tname.length,
case_sensitive, NULL);
}
return (h);
}
dns_namereln_t
dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
int *orderp, unsigned int *nlabelsp)

View File

@ -52,9 +52,6 @@ ATF_TC_BODY(getoriginnode, tc) {
result = isc_mem_create(0, 0, &mymctx);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
result = isc_hash_create(mymctx, NULL, 256);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
result = dns_db_create(mymctx, "rbt", dns_rootname, dns_dbtype_zone,
dns_rdataclass_in, 0, NULL, &db);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
@ -85,9 +82,6 @@ ATF_TC_BODY(getsetservestalettl, tc) {
result = isc_mem_create(0, 0, &mymctx);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
result = isc_hash_create(mymctx, NULL, 256);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
result = dns_db_create(mymctx, "rbt", dns_rootname, dns_dbtype_cache,
dns_rdataclass_in, 0, NULL, &db);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
@ -133,9 +127,6 @@ ATF_TC_BODY(dns_dbfind_staleok, tc) {
result = isc_mem_create(0, 0, &mymctx);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
result = isc_hash_create(mymctx, NULL, 256);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
result = dns_db_create(mymctx, "rbt", dns_rootname, dns_dbtype_cache,
dns_rdataclass_in, 0, NULL, &db);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

View File

@ -58,7 +58,7 @@ isc_boolean_t app_running = ISC_FALSE;
int ncpus;
isc_boolean_t debug_mem_record = ISC_TRUE;
static isc_boolean_t hash_active = ISC_FALSE, dst_active = ISC_FALSE;
static isc_boolean_t dst_active = ISC_FALSE;
/*
* Logging categories: this needs to match the list in bin/named/log.c.
@ -123,9 +123,6 @@ dns_test_begin(FILE *logfile, isc_boolean_t start_managers) {
CHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING));
dst_active = ISC_TRUE;
CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE));
hash_active = ISC_TRUE;
if (logfile != NULL) {
isc_logdestination_t destination;
isc_logconfig_t *logconfig = NULL;
@ -169,10 +166,6 @@ dns_test_begin(FILE *logfile, isc_boolean_t start_managers) {
void
dns_test_end(void) {
if (hash_active) {
isc_hash_destroy();
hash_active = ISC_FALSE;
}
if (dst_active) {
dst_lib_destroy();
dst_active = ISC_FALSE;

View File

@ -594,7 +594,6 @@ dns_name_getlabel
dns_name_getlabelsequence
dns_name_hasbuffer
dns_name_hash
dns_name_hashbylabel
dns_name_init
dns_name_internalwildcard
dns_name_invalidate

View File

@ -9,92 +9,23 @@
* information regarding copyright ownership.
*/
/*! \file
* Some portion of this code was derived from universal hash function
* libraries of Rice University.
\section license UH Universal Hashing Library
Copyright ((c)) 2002, Rice University
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Rice University (RICE) nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
This software is provided by RICE and the contributors on an "as is"
basis, without any representations or warranties of any kind, express
or implied including, but not limited to, representations or
warranties of non-infringement, merchantability or fitness for a
particular purpose. In no event shall RICE or contributors be liable
for any direct, indirect, incidental, special, exemplary, or
consequential damages (including, but not limited to, procurement of
substitute goods or services; loss of use, data, or profits; or
business interruption) however caused and on any theory of liability,
whether in contract, strict liability, or tort (including negligence
or otherwise) arising in any way out of the use of this software, even
if advised of the possibility of such damage.
*/
#include <config.h>
#include <isc/entropy.h>
#include <isc/hash.h>
#include <isc/mem.h>
#include <isc/magic.h>
#include <isc/mutex.h>
#include <isc/once.h>
#include <isc/random.h>
#include <isc/refcount.h>
#include <isc/string.h>
#include <isc/util.h>
#define HASH_MAGIC ISC_MAGIC('H', 'a', 's', 'h')
#define VALID_HASH(h) ISC_MAGIC_VALID((h), HASH_MAGIC)
/*%
* A large 32-bit prime number that specifies the range of the hash output.
/*
* 32 bit Fowler/Noll/Vo FNV-1a hash code with modification for BIND
*/
#define PRIME32 0xFFFFFFFB /* 2^32 - 5 */
/*@{*/
/*%
* Types of random seed and hash accumulator. Perhaps they can be system
* dependent.
*/
typedef isc_uint32_t hash_accum_t;
typedef isc_uint16_t hash_random_t;
/*@}*/
#include <config.h> // IWYU pragma: keep
#include <stddef.h>
#include "isc/once.h"
#include "isc/random.h"
#include "isc/util.h"
#include "isc/types.h"
#include "isc/likely.h"
#include "isc/result.h"
#include "isc/hash.h" // IWYU pragma: keep
/*% isc hash structure */
struct isc_hash {
unsigned int magic;
isc_mem_t *mctx;
isc_mutex_t lock;
isc_boolean_t initialized;
isc_refcount_t refcnt;
isc_entropy_t *entropy; /*%< entropy source */
size_t limit; /*%< upper limit of key length */
size_t vectorlen; /*%< size of the vector below */
hash_random_t *rndvector; /*%< random vector for universal hashing */
};
static isc_mutex_t createlock;
static isc_once_t once = ISC_ONCE_INIT;
LIBISC_EXTERNAL_DATA isc_hash_t *isc_hashctx = NULL;
static isc_uint32_t fnv_offset_basis;
static isc_once_t fnv_once = ISC_ONCE_INIT;
static isc_boolean_t fnv_initialized = ISC_FALSE;
static unsigned char maptolower[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
@ -131,277 +62,6 @@ static unsigned char maptolower[] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
isc_result_t
isc_hash_ctxcreate(isc_mem_t *mctx, isc_entropy_t *entropy,
size_t limit, isc_hash_t **hctxp)
{
isc_result_t result;
isc_hash_t *hctx;
size_t vlen;
hash_random_t *rv;
hash_accum_t overflow_limit;
REQUIRE(mctx != NULL);
REQUIRE(hctxp != NULL && *hctxp == NULL);
/*
* Overflow check. Since our implementation only does a modulo
* operation at the last stage of hash calculation, the accumulator
* must not overflow.
*/
overflow_limit =
1 << (((sizeof(hash_accum_t) - sizeof(hash_random_t))) * 8);
if (overflow_limit < (limit + 1) * 0xff)
return (ISC_R_RANGE);
hctx = isc_mem_get(mctx, sizeof(isc_hash_t));
if (hctx == NULL)
return (ISC_R_NOMEMORY);
vlen = sizeof(hash_random_t) * (limit + 1);
rv = isc_mem_get(mctx, vlen);
if (rv == NULL) {
result = ISC_R_NOMEMORY;
goto errout;
}
/*
* We need a lock.
*/
result = isc_mutex_init(&hctx->lock);
if (result != ISC_R_SUCCESS)
goto errout;
/*
* From here down, no failures will/can occur.
*/
hctx->magic = HASH_MAGIC;
hctx->mctx = NULL;
isc_mem_attach(mctx, &hctx->mctx);
hctx->initialized = ISC_FALSE;
result = isc_refcount_init(&hctx->refcnt, 1);
if (result != ISC_R_SUCCESS)
goto cleanup_lock;
hctx->entropy = NULL;
hctx->limit = limit;
hctx->vectorlen = vlen;
hctx->rndvector = rv;
if (entropy != NULL)
isc_entropy_attach(entropy, &hctx->entropy);
*hctxp = hctx;
return (ISC_R_SUCCESS);
cleanup_lock:
DESTROYLOCK(&hctx->lock);
errout:
isc_mem_put(mctx, hctx, sizeof(isc_hash_t));
if (rv != NULL)
isc_mem_put(mctx, rv, vlen);
return (result);
}
static void
initialize_lock(void) {
RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
}
isc_result_t
isc_hash_create(isc_mem_t *mctx, isc_entropy_t *entropy, size_t limit) {
isc_result_t result = ISC_R_SUCCESS;
REQUIRE(mctx != NULL);
INSIST(isc_hashctx == NULL);
RUNTIME_CHECK(isc_once_do(&once, initialize_lock) == ISC_R_SUCCESS);
LOCK(&createlock);
if (isc_hashctx == NULL)
result = isc_hash_ctxcreate(mctx, entropy, limit,
&isc_hashctx);
UNLOCK(&createlock);
return (result);
}
void
isc_hash_ctxinit(isc_hash_t *hctx) {
LOCK(&hctx->lock);
if (hctx->initialized == ISC_TRUE)
goto out;
if (hctx->entropy != NULL) {
isc_result_t result;
result = isc_entropy_getdata(hctx->entropy,
hctx->rndvector,
(unsigned int)hctx->vectorlen,
NULL, 0);
INSIST(result == ISC_R_SUCCESS);
} else {
isc_uint32_t pr;
size_t i, copylen;
unsigned char *p;
p = (unsigned char *)hctx->rndvector;
for (i = 0; i < hctx->vectorlen; i += copylen, p += copylen) {
isc_random_get(&pr);
if (i + sizeof(pr) <= hctx->vectorlen)
copylen = sizeof(pr);
else
copylen = hctx->vectorlen - i;
memmove(p, &pr, copylen);
}
INSIST(p == (unsigned char *)hctx->rndvector +
hctx->vectorlen);
}
hctx->initialized = ISC_TRUE;
out:
UNLOCK(&hctx->lock);
}
void
isc_hash_init(void) {
INSIST(isc_hashctx != NULL && VALID_HASH(isc_hashctx));
isc_hash_ctxinit(isc_hashctx);
}
void
isc_hash_ctxattach(isc_hash_t *hctx, isc_hash_t **hctxp) {
REQUIRE(VALID_HASH(hctx));
REQUIRE(hctxp != NULL && *hctxp == NULL);
isc_refcount_increment(&hctx->refcnt, NULL);
*hctxp = hctx;
}
static void
destroy(isc_hash_t **hctxp) {
isc_hash_t *hctx;
isc_mem_t *mctx;
REQUIRE(hctxp != NULL && *hctxp != NULL);
hctx = *hctxp;
*hctxp = NULL;
LOCK(&hctx->lock);
isc_refcount_destroy(&hctx->refcnt);
mctx = hctx->mctx;
if (hctx->entropy != NULL)
isc_entropy_detach(&hctx->entropy);
if (hctx->rndvector != NULL)
isc_mem_put(mctx, hctx->rndvector, hctx->vectorlen);
UNLOCK(&hctx->lock);
DESTROYLOCK(&hctx->lock);
memset(hctx, 0, sizeof(isc_hash_t));
isc_mem_put(mctx, hctx, sizeof(isc_hash_t));
isc_mem_detach(&mctx);
}
void
isc_hash_ctxdetach(isc_hash_t **hctxp) {
isc_hash_t *hctx;
unsigned int refs;
REQUIRE(hctxp != NULL && VALID_HASH(*hctxp));
hctx = *hctxp;
isc_refcount_decrement(&hctx->refcnt, &refs);
if (refs == 0)
destroy(&hctx);
*hctxp = NULL;
}
void
isc_hash_destroy(void) {
unsigned int refs;
INSIST(isc_hashctx != NULL && VALID_HASH(isc_hashctx));
isc_refcount_decrement(&isc_hashctx->refcnt, &refs);
INSIST(refs == 0);
destroy(&isc_hashctx);
}
static inline unsigned int
hash_calc(isc_hash_t *hctx, const unsigned char *key, unsigned int keylen,
isc_boolean_t case_sensitive)
{
hash_accum_t partial_sum = 0;
hash_random_t *p = hctx->rndvector;
unsigned int i = 0;
/* Make it sure that the hash context is initialized. */
if (hctx->initialized == ISC_FALSE)
isc_hash_ctxinit(hctx);
if (case_sensitive) {
for (i = 0; i < keylen; i++)
partial_sum += key[i] * (hash_accum_t)p[i];
} else {
for (i = 0; i < keylen; i++)
partial_sum += maptolower[key[i]] * (hash_accum_t)p[i];
}
partial_sum += p[i];
return ((unsigned int)(partial_sum % PRIME32));
}
unsigned int
isc_hash_ctxcalc(isc_hash_t *hctx, const unsigned char *key,
unsigned int keylen, isc_boolean_t case_sensitive)
{
REQUIRE(hctx != NULL && VALID_HASH(hctx));
REQUIRE(keylen <= hctx->limit);
return (hash_calc(hctx, key, keylen, case_sensitive));
}
unsigned int
isc_hash_calc(const unsigned char *key, unsigned int keylen,
isc_boolean_t case_sensitive)
{
INSIST(isc_hashctx != NULL && VALID_HASH(isc_hashctx));
REQUIRE(keylen <= isc_hashctx->limit);
return (hash_calc(isc_hashctx, key, keylen, case_sensitive));
}
void
isc__hash_setvec(const isc_uint16_t *vec) {
int i;
hash_random_t *p;
if (isc_hashctx == NULL)
return;
p = isc_hashctx->rndvector;
for (i = 0; i < 256; i++) {
p[i] = vec[i];
}
}
static isc_uint32_t fnv_offset_basis;
static isc_once_t fnv_once = ISC_ONCE_INIT;
static isc_boolean_t fnv_initialized = ISC_FALSE;
static void
fnv_initialize(void) {
/*
@ -438,6 +98,8 @@ isc_hash_set_initializer(const void *initializer) {
fnv_offset_basis = *((const unsigned int *) initializer);
}
#define FNV_32_PRIME ((isc_uint32_t)0x01000193)
isc_uint32_t
isc_hash_function(const void *data, size_t length,
isc_boolean_t case_sensitive,
@ -449,14 +111,16 @@ isc_hash_function(const void *data, size_t length,
REQUIRE(length == 0 || data != NULL);
if (ISC_UNLIKELY(!fnv_initialized))
if (ISC_UNLIKELY(!fnv_initialized)) {
RUNTIME_CHECK(isc_once_do(&fnv_once, fnv_initialize) == ISC_R_SUCCESS);
}
hval = ISC_UNLIKELY(previous_hashp != NULL) ?
*previous_hashp : fnv_offset_basis;
if (length == 0)
if (length == 0) {
return (hval);
}
bp = (const unsigned char *) data;
be = bp + length;
@ -471,36 +135,14 @@ isc_hash_function(const void *data, size_t length,
*/
if (case_sensitive) {
while (bp <= be - 4) {
hval ^= bp[0];
hval *= 16777619;
hval ^= bp[1];
hval *= 16777619;
hval ^= bp[2];
hval *= 16777619;
hval ^= bp[3];
hval *= 16777619;
bp += 4;
}
while (bp < be) {
hval ^= *bp++;
hval *= 16777619;
hval *= FNV_32_PRIME;
}
} else {
while (bp <= be - 4) {
hval ^= maptolower[bp[0]];
hval *= 16777619;
hval ^= maptolower[bp[1]];
hval *= 16777619;
hval ^= maptolower[bp[2]];
hval *= 16777619;
hval ^= maptolower[bp[3]];
hval *= 16777619;
bp += 4;
}
while (bp < be) {
hval ^= maptolower[*bp++];
hval *= 16777619;
hval *= FNV_32_PRIME;
}
}
@ -518,14 +160,16 @@ isc_hash_function_reverse(const void *data, size_t length,
REQUIRE(length == 0 || data != NULL);
if (ISC_UNLIKELY(!fnv_initialized))
if (ISC_UNLIKELY(!fnv_initialized)) {
RUNTIME_CHECK(isc_once_do(&fnv_once, fnv_initialize) == ISC_R_SUCCESS);
}
hval = ISC_UNLIKELY(previous_hashp != NULL) ?
*previous_hashp : fnv_offset_basis;
if (length == 0)
if (length == 0) {
return (hval);
}
bp = (const unsigned char *) data;
be = bp + length;
@ -540,36 +184,14 @@ isc_hash_function_reverse(const void *data, size_t length,
*/
if (case_sensitive) {
while (be >= bp + 4) {
be -= 4;
hval ^= be[3];
hval *= 16777619;
hval ^= be[2];
hval *= 16777619;
hval ^= be[1];
hval *= 16777619;
hval ^= be[0];
hval *= 16777619;
}
while (--be >= bp) {
hval ^= *be;
hval *= 16777619;
hval *= FNV_32_PRIME;
}
} else {
while (be >= bp + 4) {
be -= 4;
hval ^= maptolower[be[3]];
hval *= 16777619;
hval ^= maptolower[be[2]];
hval *= 16777619;
hval ^= maptolower[be[1]];
hval *= 16777619;
hval ^= maptolower[be[0]];
hval *= 16777619;
}
while (--be >= bp) {
hval ^= maptolower[*be];
hval *= 16777619;
hval *= FNV_32_PRIME;
}
}

View File

@ -12,192 +12,14 @@
#ifndef ISC_HASH_H
#define ISC_HASH_H 1
#include <isc/deprecated.h>
#include <isc/types.h>
/*****
***** Module Info
*****/
/*! \file isc/hash.h
*
* \brief The hash API
* provides an unpredictable hash value for variable length data.
* A hash object contains a random vector (which is hidden from clients
* of this API) to make the actual hash value unpredictable.
*
* The algorithm used in the API guarantees the probability of hash
* collision; in the current implementation, as long as the values stored
* in the random vector are unpredictable, the probability of hash
* collision between arbitrary two different values is at most 1/2^16.
*
* Although the API is generic about the hash keys, it mainly expects
* DNS names (and sometimes IPv4/v6 addresses) as inputs. It has an
* upper limit of the input length, and may run slow to calculate the
* hash values for large inputs.
*
* This API is designed to be general so that it can provide multiple
* different hash contexts that have different random vectors. However,
* it should be typical to have a single context for an entire system.
* To support such cases, the API also provides a single-context mode.
*
* \li MP:
* The hash object is almost read-only. Once the internal random vector
* is initialized, no write operation will occur, and there will be no
* need to lock the object to calculate actual hash values.
*
* \li Reliability:
* In some cases this module uses low-level data copy to initialize the
* random vector. Errors in this part are likely to crash the server or
* corrupt memory.
*
* \li Resources:
* A buffer, used as a random vector for calculating hash values.
*
* \li Security:
* This module intends to provide unpredictable hash values in
* adversarial environments in order to avoid denial of service attacks
* to hash buckets.
* Its unpredictability relies on the quality of entropy to build the
* random vector.
*
* \li Standards:
* None.
*/
/***
*** Imports
***/
#include <isc/types.h>
#include "isc/lang.h"
#include "isc/types.h"
/***
*** Functions
***/
ISC_LANG_BEGINDECLS
LIBISC_EXTERNAL_DATA extern isc_hash_t *isc_hashctx;
isc_result_t
isc_hash_ctxcreate(isc_mem_t *mctx, isc_entropy_t *entropy, size_t limit,
isc_hash_t **hctx);
isc_result_t
isc_hash_create(isc_mem_t *mctx, isc_entropy_t *entropy, size_t limit);
/*!<
* \brief Create a new hash object.
*
* isc_hash_ctxcreate() creates a different object.
*
* isc_hash_create() creates a module-internal object to support the
* single-context mode. It should be called only once.
*
* 'entropy' must be NULL or a valid entropy object. If 'entropy' is NULL,
* pseudo random values will be used to build the random vector, which may
* weaken security.
*
* 'limit' specifies the maximum number of hash keys. If it is too large,
* these functions may fail.
*/
void
isc_hash_ctxattach(isc_hash_t *hctx, isc_hash_t **hctxp)
ISC_DEPRECATED;
/*!<
* \brief Attach to a hash object.
*
* This function is only necessary for the multiple-context mode.
*/
void
isc_hash_ctxdetach(isc_hash_t **hctxp)
ISC_DEPRECATED;
/*!<
* \brief Detach from a hash object.
*
* This function is for the multiple-context mode, and takes a valid
* hash object as an argument.
*/
void
isc_hash_destroy(void);
/*!<
* \brief This function is for the single-context mode, and is expected to be used
* as a counterpart of isc_hash_create().
*
* A valid module-internal hash object must have been created, and this
* function should be called only once.
*/
/*@{*/
void
isc_hash_ctxinit(isc_hash_t *hctx);
void
isc_hash_init(void);
/*!<
* \brief Initialize a hash object.
*
* It fills in the random vector with a proper
* source of entropy, which is typically from the entropy object specified
* at the creation. Thus, it is desirable to call these functions after
* initializing the entropy object with some good entropy sources.
*
* These functions should be called before the first hash calculation.
*
* isc_hash_ctxinit() is for the multiple-context mode, and takes a valid hash
* object as an argument.
*
* isc_hash_init() is for the single-context mode. A valid module-internal
* hash object must have been created, and this function should be called only
* once.
*/
/*@}*/
/*@{*/
unsigned int
isc_hash_ctxcalc(isc_hash_t *hctx, const unsigned char *key,
unsigned int keylen, isc_boolean_t case_sensitive)
ISC_DEPRECATED;
unsigned int
isc_hash_calc(const unsigned char *key, unsigned int keylen,
isc_boolean_t case_sensitive)
ISC_DEPRECATED;
/*!<
* \brief Calculate a hash value.
*
* isc_hash_ctxinit() is for the multiple-context mode, and takes a valid hash
* object as an argument.
*
* isc_hash_init() is for the single-context mode. A valid module-internal
* hash object must have been created.
*
* 'key' is the hash key, which is a variable length buffer.
*
* 'keylen' specifies the key length, which must not be larger than the limit
* specified for the corresponding hash object.
*
* 'case_sensitive' specifies whether the hash key should be treated as
* case_sensitive values. It should typically be ISC_FALSE if the hash key
* is a DNS name.
*/
/*@}*/
void
isc__hash_setvec(const isc_uint16_t *vec)
ISC_DEPRECATED;
/*!<
* \brief Set the contents of the random vector used in hashing.
*
* WARNING: This function is meant to be used only in testing code. It
* must not be used anywhere in normally running code.
*
* The hash context must have been created beforehand, otherwise this
* function is a nop.
*
* 'vec' is not documented here on purpose. You should know what you are
* doing before using this function.
*/
const void *
isc_hash_get_initializer(void);
@ -227,9 +49,6 @@ isc_hash_function_reverse(const void *data, size_t length,
* useful in incremental hashing; for example, a previously hashed
* value for 'com' can be used as input when hashing 'example.com'.
*
* This is a new variant of isc_hash_calc() and will supercede
* isc_hash_calc() eventually.
*
* 'data' is the data to be hashed.
*
* 'length' is the size of the data to be hashed.

View File

@ -39,8 +39,6 @@ isc_socketmgr_t *socketmgr = NULL;
isc_task_t *maintask = NULL;
int ncpus;
static isc_boolean_t hash_active = ISC_FALSE;
/*
* Logging categories: this needs to match the list in bin/named/log.c.
*/
@ -109,9 +107,6 @@ isc_test_begin(FILE *logfile, isc_boolean_t start_managers,
CHECK(isc_mem_create(0, 0, &mctx));
CHECK(isc_entropy_create(mctx, &ectx));
CHECK(isc_hash_create(mctx, ectx, 255));
hash_active = ISC_TRUE;
if (logfile != NULL) {
isc_logdestination_t destination;
isc_logconfig_t *logconfig = NULL;
@ -154,10 +149,6 @@ isc_test_end(void) {
isc_task_detach(&maintask);
if (taskmgr != NULL)
isc_taskmgr_destroy(&taskmgr);
if (hash_active) {
isc_hash_destroy();
hash_active = ISC_FALSE;
}
if (ectx != NULL)
isc_entropy_detach(&ectx);

View File

@ -1,6 +1,5 @@
; These symbols are not needed by the WIN32 build, but build-tarballs
; will complain if they aren't present here.
isc__hash_setvec
isc_socket_accept
isc_socket_attach
isc_socket_bind

View File

@ -51,7 +51,6 @@ isc__buffer_remainingregion
isc__buffer_setactive
isc__buffer_subtract
isc__buffer_usedregion
isc__hash_setvec
isc__mem_allocate
isc__mem_free
isc__mem_get
@ -262,18 +261,9 @@ isc_fsaccess_add
isc_fsaccess_changeowner
isc_fsaccess_remove
isc_fsaccess_set
isc_hash_calc
isc_hash_create
isc_hash_ctxattach
isc_hash_ctxcalc
isc_hash_ctxcreate
isc_hash_ctxdetach
isc_hash_ctxinit
isc_hash_destroy
isc_hash_function
isc_hash_function_reverse
isc_hash_get_initializer
isc_hash_init
isc_hash_set_initializer
isc_heap_create
isc_heap_decreased

View File

@ -68,7 +68,7 @@ int ncpus;
isc_boolean_t debug_mem_record = ISC_TRUE;
isc_boolean_t run_managers = ISC_FALSE;
static isc_boolean_t hash_active = ISC_FALSE, dst_active = ISC_FALSE;
static isc_boolean_t dst_active = ISC_FALSE;
static dns_zone_t *served_zone = NULL;
@ -248,9 +248,6 @@ ns_test_begin(FILE *logfile, isc_boolean_t start_managers) {
CHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING));
dst_active = ISC_TRUE;
CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE));
hash_active = ISC_TRUE;
if (logfile != NULL) {
isc_logdestination_t destination;
isc_logconfig_t *logconfig = NULL;
@ -303,11 +300,6 @@ ns_test_end(void) {
cleanup_managers();
if (hash_active) {
isc_hash_destroy();
hash_active = ISC_FALSE;
}
if (ectx != NULL)
isc_entropy_detach(&ectx);