Unexport almost all of LHASH. The one place where LHASH_OF(T) appears in public APIs is X509V3_EXT_conf_nid. This is only ever called with conf = NULL, but cryptography.io needs to utter the type name as part of bindings. Thus this CL keeps DECLARE_LHASH_OF and LHASH_OF macros public and the others private. Update-Note: BoringSSL no longer provides a general-purpose hash table to callers. Use the language's standard library, or another implementation. Change-Id: Ibfc65c4b4bf35abf5b1919658d0c52e4004e6629 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48205 Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/conf/conf.c b/crypto/conf/conf.c index 7070ca8..3e6388a 100644 --- a/crypto/conf/conf.c +++ b/crypto/conf/conf.c
@@ -68,6 +68,7 @@ #include "conf_def.h" #include "internal.h" #include "../internal.h" +#include "../lhash/internal.h" DEFINE_LHASH_OF(CONF_VALUE)
diff --git a/crypto/lhash/internal.h b/crypto/lhash/internal.h new file mode 100644 index 0000000..e11a15e --- /dev/null +++ b/crypto/lhash/internal.h
@@ -0,0 +1,266 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_LHASH_INTERNAL_H +#define OPENSSL_HEADER_LHASH_INTERNAL_H + +#include <openssl/lhash.h> + +#if defined(__cplusplus) +extern "C" { +#endif + + +// lhash is a traditional, chaining hash table that automatically expands and +// contracts as needed. One should not use the lh_* functions directly, rather +// use the type-safe macro wrappers: +// +// A hash table of a specific type of object has type |LHASH_OF(type)|. This +// can be defined (once) with |DEFINE_LHASH_OF(type)| and declared where needed +// with |DECLARE_LHASH_OF(type)|. For example: +// +// struct foo { +// int bar; +// }; +// +// DEFINE_LHASH_OF(struct foo) +// +// Although note that the hash table will contain /pointers/ to |foo|. +// +// A macro will be defined for each of the lh_* functions below. For +// LHASH_OF(foo), the macros would be lh_foo_new, lh_foo_num_items etc. + + +// lhash_cmp_func is a comparison function that returns a value equal, or not +// equal, to zero depending on whether |*a| is equal, or not equal to |*b|, +// respectively. Note the difference between this and |stack_cmp_func| in that +// this takes pointers to the objects directly. +// +// This function's actual type signature is int (*)(const T*, const T*). The +// low-level |lh_*| functions will be passed a type-specific wrapper to call it +// correctly. +typedef int (*lhash_cmp_func)(const void *a, const void *b); +typedef int (*lhash_cmp_func_helper)(lhash_cmp_func func, const void *a, + const void *b); + +// lhash_hash_func is a function that maps an object to a uniformly distributed +// uint32_t. +// +// This function's actual type signature is uint32_t (*)(const T*). The +// low-level |lh_*| functions will be passed a type-specific wrapper to call it +// correctly. +typedef uint32_t (*lhash_hash_func)(const void *a); +typedef uint32_t (*lhash_hash_func_helper)(lhash_hash_func func, const void *a); + +typedef struct lhash_st _LHASH; + +// lh_new returns a new, empty hash table or NULL on error. +OPENSSL_EXPORT _LHASH *lh_new(lhash_hash_func hash, lhash_cmp_func comp); + +// lh_free frees the hash table itself but none of the elements. See +// |lh_doall|. +OPENSSL_EXPORT void lh_free(_LHASH *lh); + +// lh_num_items returns the number of items in |lh|. +OPENSSL_EXPORT size_t lh_num_items(const _LHASH *lh); + +// lh_retrieve finds an element equal to |data| in the hash table and returns +// it. If no such element exists, it returns NULL. +OPENSSL_EXPORT void *lh_retrieve(const _LHASH *lh, const void *data, + lhash_hash_func_helper call_hash_func, + lhash_cmp_func_helper call_cmp_func); + +// lh_retrieve_key finds an element matching |key|, given the specified hash and +// comparison function. This differs from |lh_retrieve| in that the key may be a +// different type than the values stored in |lh|. |key_hash| and |cmp_key| must +// be compatible with the functions passed into |lh_new|. +OPENSSL_EXPORT void *lh_retrieve_key(const _LHASH *lh, const void *key, + uint32_t key_hash, + int (*cmp_key)(const void *key, + const void *value)); + +// lh_insert inserts |data| into the hash table. If an existing element is +// equal to |data| (with respect to the comparison function) then |*old_data| +// will be set to that value and it will be replaced. Otherwise, or in the +// event of an error, |*old_data| will be set to NULL. It returns one on +// success or zero in the case of an allocation error. +OPENSSL_EXPORT int lh_insert(_LHASH *lh, void **old_data, void *data, + lhash_hash_func_helper call_hash_func, + lhash_cmp_func_helper call_cmp_func); + +// lh_delete removes an element equal to |data| from the hash table and returns +// it. If no such element is found, it returns NULL. +OPENSSL_EXPORT void *lh_delete(_LHASH *lh, const void *data, + lhash_hash_func_helper call_hash_func, + lhash_cmp_func_helper call_cmp_func); + +// lh_doall_arg calls |func| on each element of the hash table and also passes +// |arg| as the second argument. +// TODO(fork): rename this +OPENSSL_EXPORT void lh_doall_arg(_LHASH *lh, void (*func)(void *, void *), + void *arg); + +// lh_strhash is the default hash function which processes NUL-terminated +// strings. +OPENSSL_EXPORT uint32_t lh_strhash(const char *c); + +#define DEFINE_LHASH_OF(type) \ + DECLARE_LHASH_OF(type) \ + \ + typedef int (*lhash_##type##_cmp_func)(const type *, const type *); \ + typedef uint32_t (*lhash_##type##_hash_func)(const type *); \ + \ + OPENSSL_INLINE int lh_##type##_call_cmp_func(lhash_cmp_func func, \ + const void *a, const void *b) { \ + return ((lhash_##type##_cmp_func)func)((const type *)a, (const type *)b); \ + } \ + \ + OPENSSL_INLINE uint32_t lh_##type##_call_hash_func(lhash_hash_func func, \ + const void *a) { \ + return ((lhash_##type##_hash_func)func)((const type *)a); \ + } \ + \ + OPENSSL_INLINE LHASH_OF(type) * \ + lh_##type##_new(lhash_##type##_hash_func hash, \ + lhash_##type##_cmp_func comp) { \ + return (LHASH_OF(type) *)lh_new((lhash_hash_func)hash, \ + (lhash_cmp_func)comp); \ + } \ + \ + OPENSSL_INLINE void lh_##type##_free(LHASH_OF(type) *lh) { \ + lh_free((_LHASH *)lh); \ + } \ + \ + OPENSSL_INLINE size_t lh_##type##_num_items(const LHASH_OF(type) *lh) { \ + return lh_num_items((const _LHASH *)lh); \ + } \ + \ + OPENSSL_INLINE type *lh_##type##_retrieve(const LHASH_OF(type) *lh, \ + const type *data) { \ + return (type *)lh_retrieve((const _LHASH *)lh, data, \ + lh_##type##_call_hash_func, \ + lh_##type##_call_cmp_func); \ + } \ + \ + typedef struct { \ + int (*cmp_key)(const void *key, const type *value); \ + const void *key; \ + } LHASH_CMP_KEY_##type; \ + \ + OPENSSL_INLINE int lh_##type##_call_cmp_key(const void *key, \ + const void *value) { \ + const LHASH_CMP_KEY_##type *cb = (const LHASH_CMP_KEY_##type *)key; \ + return cb->cmp_key(cb->key, (const type *)value); \ + } \ + \ + OPENSSL_INLINE type *lh_##type##_retrieve_key( \ + const LHASH_OF(type) *lh, const void *key, uint32_t key_hash, \ + int (*cmp_key)(const void *key, const type *value)) { \ + LHASH_CMP_KEY_##type cb = {cmp_key, key}; \ + return (type *)lh_retrieve_key((const _LHASH *)lh, &cb, key_hash, \ + lh_##type##_call_cmp_key); \ + } \ + \ + OPENSSL_INLINE int lh_##type##_insert(LHASH_OF(type) *lh, type **old_data, \ + type *data) { \ + void *old_data_void = NULL; \ + int ret = \ + lh_insert((_LHASH *)lh, &old_data_void, data, \ + lh_##type##_call_hash_func, lh_##type##_call_cmp_func); \ + *old_data = (type *)old_data_void; \ + return ret; \ + } \ + \ + OPENSSL_INLINE type *lh_##type##_delete(LHASH_OF(type) *lh, \ + const type *data) { \ + return (type *)lh_delete((_LHASH *)lh, data, lh_##type##_call_hash_func, \ + lh_##type##_call_cmp_func); \ + } \ + \ + typedef struct { \ + void (*doall)(type *); \ + void (*doall_arg)(type *, void *); \ + void *arg; \ + } LHASH_DOALL_##type; \ + \ + OPENSSL_INLINE void lh_##type##_call_doall(void *value, void *arg) { \ + const LHASH_DOALL_##type *cb = (const LHASH_DOALL_##type *)arg; \ + cb->doall((type *)value); \ + } \ + \ + OPENSSL_INLINE void lh_##type##_call_doall_arg(void *value, void *arg) { \ + const LHASH_DOALL_##type *cb = (const LHASH_DOALL_##type *)arg; \ + cb->doall_arg((type *)value, cb->arg); \ + } \ + \ + OPENSSL_INLINE void lh_##type##_doall(LHASH_OF(type) *lh, \ + void (*func)(type *)) { \ + LHASH_DOALL_##type cb = {func, NULL, NULL}; \ + lh_doall_arg((_LHASH *)lh, lh_##type##_call_doall, &cb); \ + } \ + \ + OPENSSL_INLINE void lh_##type##_doall_arg( \ + LHASH_OF(type) *lh, void (*func)(type *, void *), void *arg) { \ + LHASH_DOALL_##type cb = {NULL, func, arg}; \ + lh_doall_arg((_LHASH *)lh, lh_##type##_call_doall_arg, &cb); \ + } + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_LHASH_INTERNAL_H
diff --git a/crypto/lhash/lhash.c b/crypto/lhash/lhash.c index 98ee60a..946ea84 100644 --- a/crypto/lhash/lhash.c +++ b/crypto/lhash/lhash.c
@@ -62,6 +62,7 @@ #include <openssl/mem.h> +#include "internal.h" #include "../internal.h" @@ -73,6 +74,16 @@ static const size_t kMaxAverageChainLength = 2; static const size_t kMinAverageChainLength = 1; +// lhash_item_st is an element of a hash chain. It points to the opaque data +// for this element and to the next item in the chain. The linked-list is NULL +// terminated. +typedef struct lhash_item_st { + void *data; + struct lhash_item_st *next; + // hash contains the cached, hash value of |data|. + uint32_t hash; +} LHASH_ITEM; + struct lhash_st { // num_items contains the total number of items in the hash table. size_t num_items;
diff --git a/crypto/lhash/lhash_test.cc b/crypto/lhash/lhash_test.cc index 885d3c7..f2b8169 100644 --- a/crypto/lhash/lhash_test.cc +++ b/crypto/lhash/lhash_test.cc
@@ -27,6 +27,8 @@ #include <gtest/gtest.h> +#include "internal.h" + DEFINE_LHASH_OF(char)
diff --git a/crypto/obj/obj.c b/crypto/obj/obj.c index 3053132..a85979f 100644 --- a/crypto/obj/obj.c +++ b/crypto/obj/obj.c
@@ -69,6 +69,7 @@ #include "obj_dat.h" #include "../internal.h" +#include "../lhash/internal.h" DEFINE_LHASH_OF(ASN1_OBJECT)
diff --git a/crypto/pool/pool.c b/crypto/pool/pool.c index 917e43c..88bf8af 100644 --- a/crypto/pool/pool.c +++ b/crypto/pool/pool.c
@@ -22,6 +22,7 @@ #include <openssl/thread.h> #include "../internal.h" +#include "../lhash/internal.h" #include "internal.h"
diff --git a/include/openssl/lhash.h b/include/openssl/lhash.h index 29e09c8..1297541 100644 --- a/include/openssl/lhash.h +++ b/include/openssl/lhash.h
@@ -58,223 +58,22 @@ #define OPENSSL_HEADER_LHASH_H #include <openssl/base.h> -#include <openssl/type_check.h> #if defined(__cplusplus) extern "C" { #endif -// lhash is a traditional, chaining hash table that automatically expands and -// contracts as needed. One should not use the lh_* functions directly, rather -// use the type-safe macro wrappers: -// -// A hash table of a specific type of object has type |LHASH_OF(type)|. This -// can be defined (once) with |DEFINE_LHASH_OF(type)| and declared where needed -// with |DECLARE_LHASH_OF(type)|. For example: -// -// struct foo { -// int bar; -// }; -// -// DEFINE_LHASH_OF(struct foo) -// -// Although note that the hash table will contain /pointers/ to |foo|. -// -// A macro will be defined for each of the lh_* functions below. For -// LHASH_OF(foo), the macros would be lh_foo_new, lh_foo_num_items etc. +// lhash is an internal library and not exported for use outside BoringSSL. This +// header is provided for compatibility with code that expects OpenSSL. +// These two macros are exported for compatibility with existing callers of +// |X509V3_EXT_conf_nid|. Do not use these symbols outside BoringSSL. #define LHASH_OF(type) struct lhash_st_##type - #define DECLARE_LHASH_OF(type) LHASH_OF(type); -// lhash_item_st is an element of a hash chain. It points to the opaque data -// for this element and to the next item in the chain. The linked-list is NULL -// terminated. -typedef struct lhash_item_st { - void *data; - struct lhash_item_st *next; - // hash contains the cached, hash value of |data|. - uint32_t hash; -} LHASH_ITEM; - -// lhash_cmp_func is a comparison function that returns a value equal, or not -// equal, to zero depending on whether |*a| is equal, or not equal to |*b|, -// respectively. Note the difference between this and |stack_cmp_func| in that -// this takes pointers to the objects directly. -// -// This function's actual type signature is int (*)(const T*, const T*). The -// low-level |lh_*| functions will be passed a type-specific wrapper to call it -// correctly. -typedef int (*lhash_cmp_func)(const void *a, const void *b); -typedef int (*lhash_cmp_func_helper)(lhash_cmp_func func, const void *a, - const void *b); - -// lhash_hash_func is a function that maps an object to a uniformly distributed -// uint32_t. -// -// This function's actual type signature is uint32_t (*)(const T*). The -// low-level |lh_*| functions will be passed a type-specific wrapper to call it -// correctly. -typedef uint32_t (*lhash_hash_func)(const void *a); -typedef uint32_t (*lhash_hash_func_helper)(lhash_hash_func func, const void *a); - -typedef struct lhash_st _LHASH; - -// lh_new returns a new, empty hash table or NULL on error. -OPENSSL_EXPORT _LHASH *lh_new(lhash_hash_func hash, lhash_cmp_func comp); - -// lh_free frees the hash table itself but none of the elements. See -// |lh_doall|. -OPENSSL_EXPORT void lh_free(_LHASH *lh); - -// lh_num_items returns the number of items in |lh|. -OPENSSL_EXPORT size_t lh_num_items(const _LHASH *lh); - -// lh_retrieve finds an element equal to |data| in the hash table and returns -// it. If no such element exists, it returns NULL. -OPENSSL_EXPORT void *lh_retrieve(const _LHASH *lh, const void *data, - lhash_hash_func_helper call_hash_func, - lhash_cmp_func_helper call_cmp_func); - -// lh_retrieve_key finds an element matching |key|, given the specified hash and -// comparison function. This differs from |lh_retrieve| in that the key may be a -// different type than the values stored in |lh|. |key_hash| and |cmp_key| must -// be compatible with the functions passed into |lh_new|. -OPENSSL_EXPORT void *lh_retrieve_key(const _LHASH *lh, const void *key, - uint32_t key_hash, - int (*cmp_key)(const void *key, - const void *value)); - -// lh_insert inserts |data| into the hash table. If an existing element is -// equal to |data| (with respect to the comparison function) then |*old_data| -// will be set to that value and it will be replaced. Otherwise, or in the -// event of an error, |*old_data| will be set to NULL. It returns one on -// success or zero in the case of an allocation error. -OPENSSL_EXPORT int lh_insert(_LHASH *lh, void **old_data, void *data, - lhash_hash_func_helper call_hash_func, - lhash_cmp_func_helper call_cmp_func); - -// lh_delete removes an element equal to |data| from the hash table and returns -// it. If no such element is found, it returns NULL. -OPENSSL_EXPORT void *lh_delete(_LHASH *lh, const void *data, - lhash_hash_func_helper call_hash_func, - lhash_cmp_func_helper call_cmp_func); - -// lh_doall_arg calls |func| on each element of the hash table and also passes -// |arg| as the second argument. -// TODO(fork): rename this -OPENSSL_EXPORT void lh_doall_arg(_LHASH *lh, void (*func)(void *, void *), - void *arg); - -// lh_strhash is the default hash function which processes NUL-terminated -// strings. -OPENSSL_EXPORT uint32_t lh_strhash(const char *c); - -#define DEFINE_LHASH_OF(type) \ - DECLARE_LHASH_OF(type) \ - \ - typedef int (*lhash_##type##_cmp_func)(const type *, const type *); \ - typedef uint32_t (*lhash_##type##_hash_func)(const type *); \ - \ - OPENSSL_INLINE int lh_##type##_call_cmp_func(lhash_cmp_func func, \ - const void *a, const void *b) { \ - return ((lhash_##type##_cmp_func)func)((const type *)a, (const type *)b); \ - } \ - \ - OPENSSL_INLINE uint32_t lh_##type##_call_hash_func(lhash_hash_func func, \ - const void *a) { \ - return ((lhash_##type##_hash_func)func)((const type *)a); \ - } \ - \ - OPENSSL_INLINE LHASH_OF(type) * \ - lh_##type##_new(lhash_##type##_hash_func hash, \ - lhash_##type##_cmp_func comp) { \ - return (LHASH_OF(type) *)lh_new((lhash_hash_func)hash, \ - (lhash_cmp_func)comp); \ - } \ - \ - OPENSSL_INLINE void lh_##type##_free(LHASH_OF(type) *lh) { \ - lh_free((_LHASH *)lh); \ - } \ - \ - OPENSSL_INLINE size_t lh_##type##_num_items(const LHASH_OF(type) *lh) { \ - return lh_num_items((const _LHASH *)lh); \ - } \ - \ - OPENSSL_INLINE type *lh_##type##_retrieve(const LHASH_OF(type) *lh, \ - const type *data) { \ - return (type *)lh_retrieve((const _LHASH *)lh, data, \ - lh_##type##_call_hash_func, \ - lh_##type##_call_cmp_func); \ - } \ - \ - typedef struct { \ - int (*cmp_key)(const void *key, const type *value); \ - const void *key; \ - } LHASH_CMP_KEY_##type; \ - \ - OPENSSL_INLINE int lh_##type##_call_cmp_key(const void *key, \ - const void *value) { \ - const LHASH_CMP_KEY_##type *cb = (const LHASH_CMP_KEY_##type *)key; \ - return cb->cmp_key(cb->key, (const type *)value); \ - } \ - \ - OPENSSL_INLINE type *lh_##type##_retrieve_key( \ - const LHASH_OF(type) *lh, const void *key, uint32_t key_hash, \ - int (*cmp_key)(const void *key, const type *value)) { \ - LHASH_CMP_KEY_##type cb = {cmp_key, key}; \ - return (type *)lh_retrieve_key((const _LHASH *)lh, &cb, key_hash, \ - lh_##type##_call_cmp_key); \ - } \ - \ - OPENSSL_INLINE int lh_##type##_insert(LHASH_OF(type) *lh, type **old_data, \ - type *data) { \ - void *old_data_void = NULL; \ - int ret = \ - lh_insert((_LHASH *)lh, &old_data_void, data, \ - lh_##type##_call_hash_func, lh_##type##_call_cmp_func); \ - *old_data = (type *)old_data_void; \ - return ret; \ - } \ - \ - OPENSSL_INLINE type *lh_##type##_delete(LHASH_OF(type) *lh, \ - const type *data) { \ - return (type *)lh_delete((_LHASH *)lh, data, lh_##type##_call_hash_func, \ - lh_##type##_call_cmp_func); \ - } \ - \ - typedef struct { \ - void (*doall)(type *); \ - void (*doall_arg)(type *, void *); \ - void *arg; \ - } LHASH_DOALL_##type; \ - \ - OPENSSL_INLINE void lh_##type##_call_doall(void *value, void *arg) { \ - const LHASH_DOALL_##type *cb = (const LHASH_DOALL_##type *)arg; \ - cb->doall((type *)value); \ - } \ - \ - OPENSSL_INLINE void lh_##type##_call_doall_arg(void *value, void *arg) { \ - const LHASH_DOALL_##type *cb = (const LHASH_DOALL_##type *)arg; \ - cb->doall_arg((type *)value, cb->arg); \ - } \ - \ - OPENSSL_INLINE void lh_##type##_doall(LHASH_OF(type) *lh, \ - void (*func)(type *)) { \ - LHASH_DOALL_##type cb = {func, NULL, NULL}; \ - lh_doall_arg((_LHASH *)lh, lh_##type##_call_doall, &cb); \ - } \ - \ - OPENSSL_INLINE void lh_##type##_doall_arg( \ - LHASH_OF(type) *lh, void (*func)(type *, void *), void *arg) { \ - LHASH_DOALL_##type cb = {NULL, func, arg}; \ - lh_doall_arg((_LHASH *)lh, lh_##type##_call_doall_arg, &cb); \ - } - - #if defined(__cplusplus) } // extern C #endif
diff --git a/ssl/internal.h b/ssl/internal.h index 5b17a95..ad199aa 100644 --- a/ssl/internal.h +++ b/ssl/internal.h
@@ -163,6 +163,7 @@ #include "../crypto/err/internal.h" #include "../crypto/internal.h" +#include "../crypto/lhash/internal.h" #if defined(OPENSSL_WINDOWS)