gnutls/gnutls-3.8.6-compression-dlwrap.patch
Daiki Ueno 9f3cab5d41 Switch to using dlwrap for loading compression libraries
Related: RHEL-50011
Signed-off-by: Daiki Ueno <dueno@redhat.com>
2024-07-28 08:17:10 +09:00

2132 lines
63 KiB
Diff

From dd7f8c30ca44695992bbb92146e385b4b700f285 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Sat, 29 Jun 2024 09:52:55 +0900
Subject: [PATCH 1/4] m4: factor out soname check into a separate macro
This moves the SONAME detection from configure.ac to m4/hooks.m4 as
the LIBGNUTLS_CHECK_SONAME macro. The new macro doesn't implicitly
set *_LIBRARY_SONAME to "none", so the callers need to adjust
themselves depending on whether the macro is defined.
Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
configure.ac | 50 ++++++++++++--------------------------------------
lib/fips.c | 26 ++++++++++++++------------
lib/fipshmac.c | 14 ++++++++++++++
lib/global.c | 6 ++++++
m4/hooks.m4 | 20 ++++++++++++++++++++
5 files changed, 66 insertions(+), 50 deletions(-)
diff --git a/configure.ac b/configure.ac
index 1744813b79..3f001998b4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -810,61 +810,35 @@ save_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS $GMP_CFLAGS"
save_LIBS=$LIBS
LIBS="$LIBS $GMP_LIBS"
-AC_MSG_CHECKING([gmp soname])
-AC_LINK_IFELSE([AC_LANG_PROGRAM([
+LIBGNUTLS_CHECK_SONAME([gmp], [AC_LANG_PROGRAM([
#include <gmp.h>],[
mpz_t n;
- mpz_init(n);])],
- [gmp_so=`(eval "$LDDPROG conftest$EXEEXT $LDDPOSTPROC") | grep '^libgmp\.so'`],
- [gmp_so=none])
-if test -z "$gmp_so"; then
- gmp_so=none
-fi
-AC_MSG_RESULT($gmp_so)
-if test "$gmp_so" != none; then
- AC_DEFINE_UNQUOTED([GMP_LIBRARY_SONAME], ["$gmp_so"], [The soname of gmp library])
-fi
-LIBS=$save_LIBS
-CFLAGS=$save_CFLAGS
+ mpz_init(n);])])
+LIBS="$save_LIBS"
+CFLAGS="$save_CFLAGS"
save_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS $NETTLE_CFLAGS"
save_LIBS=$LIBS
LIBS="$LIBS $NETTLE_LIBS"
-AC_MSG_CHECKING([nettle soname])
-AC_LINK_IFELSE([AC_LANG_PROGRAM([
+LIBGNUTLS_CHECK_SONAME([nettle], [AC_LANG_PROGRAM([
#include <nettle/sha2.h>],[
struct sha256_ctx ctx;
- sha256_init(&ctx);])],
- [nettle_so=`(eval "$LDDPROG conftest$EXEEXT $LDDPOSTPROC") | grep '^libnettle\.so'`],
- [nettle_so=none])
-if test -z "$nettle_so"; then
- nettle_so=none
-fi
-AC_MSG_RESULT($nettle_so)
-AC_DEFINE_UNQUOTED([NETTLE_LIBRARY_SONAME], ["$nettle_so"], [The soname of nettle library])
-LIBS=$save_LIBS
-CFLAGS=$save_CFLAGS
+ sha256_init(&ctx);])])
+LIBS="$save_LIBS"
+CFLAGS="$save_CFLAGS"
save_CFLAGS=$CFLAGS
# <nettle/bignum.h> includes <gmp.h>
CFLAGS="$CFLAGS $HOGWEED_CFLAGS $GMP_CFLAGS"
save_LIBS=$LIBS
LIBS="$LIBS $HOGWEED_LIBS"
-AC_MSG_CHECKING([hogweed soname])
-AC_LINK_IFELSE([AC_LANG_PROGRAM([
+LIBGNUTLS_CHECK_SONAME([hogweed], [AC_LANG_PROGRAM([
#include <nettle/rsa.h>],[
struct rsa_private_key priv;
- nettle_rsa_private_key_init(&priv);])],
- [hogweed_so=`(eval "$LDDPROG conftest$EXEEXT $LDDPOSTPROC") | grep '^libhogweed\.so'`],
- [hogweed_so=none])
-if test -z "$hogweed_so"; then
- hogweed_so=none
-fi
-AC_MSG_RESULT($hogweed_so)
-AC_DEFINE_UNQUOTED([HOGWEED_LIBRARY_SONAME], ["$hogweed_so"], [The soname of hogweed library])
-LIBS=$save_LIBS
-CFLAGS=$save_CFLAGS
+ nettle_rsa_private_key_init(&priv);])])
+LIBS="$save_LIBS"
+CFLAGS="$save_CFLAGS"
gnutls_so=libgnutls.so.`expr "$LT_CURRENT" - "$LT_AGE"`
AC_DEFINE_UNQUOTED([GNUTLS_LIBRARY_SONAME], ["$gnutls_so"], [The soname of gnutls library])
diff --git a/lib/fips.c b/lib/fips.c
index 1611200be8..e5fce6b1b9 100644
--- a/lib/fips.c
+++ b/lib/fips.c
@@ -152,15 +152,17 @@ void _gnutls_fips_mode_reset_zombie(void)
}
}
-/* These only works with the platform where SONAME is part of the ABI.
- * For example, *_SONAME will be set to "none" on Windows platforms. */
-#define GNUTLS_LIBRARY_NAME GNUTLS_LIBRARY_SONAME
-#define NETTLE_LIBRARY_NAME NETTLE_LIBRARY_SONAME
-#define HOGWEED_LIBRARY_NAME HOGWEED_LIBRARY_SONAME
+/* These only works with the platform where SONAME is part of the ABI. */
+#ifndef GNUTLS_LIBRARY_SONAME
+#define GNUTLS_LIBRARY_SONAME "none"
+#endif
-/* GMP can be statically linked. */
-#ifdef GMP_LIBRARY_SONAME
-#define GMP_LIBRARY_NAME GMP_LIBRARY_SONAME
+#ifndef NETTLE_LIBRARY_SONAME
+#define NETTLE_LIBRARY_SONAME "none"
+#endif
+
+#ifndef HOGWEED_LIBRARY_SONAME
+#define HOGWEED_LIBRARY_SONAME "none"
#endif
#define HMAC_SIZE 32
@@ -246,14 +248,14 @@ static int handler(void *user, const char *section, const char *name,
} else {
return 0;
}
- } else if (!strcmp(section, GNUTLS_LIBRARY_NAME)) {
+ } else if (!strcmp(section, GNUTLS_LIBRARY_SONAME)) {
return lib_handler(&p->gnutls, section, name, value);
- } else if (!strcmp(section, NETTLE_LIBRARY_NAME)) {
+ } else if (!strcmp(section, NETTLE_LIBRARY_SONAME)) {
return lib_handler(&p->nettle, section, name, value);
- } else if (!strcmp(section, HOGWEED_LIBRARY_NAME)) {
+ } else if (!strcmp(section, HOGWEED_LIBRARY_SONAME)) {
return lib_handler(&p->hogweed, section, name, value);
#ifdef GMP_LIBRARY_SONAME
- } else if (!strcmp(section, GMP_LIBRARY_NAME)) {
+ } else if (!strcmp(section, GMP_LIBRARY_SONAME)) {
return lib_handler(&p->gmp, section, name, value);
#endif
} else {
diff --git a/lib/fipshmac.c b/lib/fipshmac.c
index 6a4883a131..d3561b4c47 100644
--- a/lib/fipshmac.c
+++ b/lib/fipshmac.c
@@ -34,6 +34,20 @@
#include "errors.h"
#define FORMAT_VERSION 1
+
+/* These only works with the platform where SONAME is part of the ABI. */
+#ifndef GNUTLS_LIBRARY_SONAME
+#define GNUTLS_LIBRARY_SONAME "none"
+#endif
+
+#ifndef NETTLE_LIBRARY_SONAME
+#define NETTLE_LIBRARY_SONAME "none"
+#endif
+
+#ifndef HOGWEED_LIBRARY_SONAME
+#define HOGWEED_LIBRARY_SONAME "none"
+#endif
+
#define HMAC_SIZE 32
#define HMAC_ALGO GNUTLS_MAC_SHA256
#define HMAC_STR_SIZE (2 * HMAC_SIZE + 1)
diff --git a/lib/global.c b/lib/global.c
index 718740c103..b434140bbf 100644
--- a/lib/global.c
+++ b/lib/global.c
@@ -563,9 +563,15 @@ static const struct gnutls_library_config_st _gnutls_library_config[] = {
#ifdef FIPS_MODULE_VERSION
{ "fips-module-version", FIPS_MODULE_VERSION },
#endif
+#ifdef GNUTLS_LIBRARY_SONAME
{ "libgnutls-soname", GNUTLS_LIBRARY_SONAME },
+#endif
+#ifdef NETTLE_LIBRARY_SONAME
{ "libnettle-soname", NETTLE_LIBRARY_SONAME },
+#endif
+#ifdef HOGWEED_LIBRARY_SONAME
{ "libhogweed-soname", HOGWEED_LIBRARY_SONAME },
+#endif
#ifdef GMP_LIBRARY_SONAME
{ "libgmp-soname", GMP_LIBRARY_SONAME },
#endif
diff --git a/m4/hooks.m4 b/m4/hooks.m4
index cf6064ca1d..a786d35150 100644
--- a/m4/hooks.m4
+++ b/m4/hooks.m4
@@ -421,3 +421,23 @@ dnl #AM_ICONV
dnl m4_ifdef([gl_ICONV_MODULE_INDICATOR],
dnl [gl_ICONV_MODULE_INDICATOR([iconv])])
])
+
+AC_DEFUN([LIBGNUTLS_CHECK_SONAME],
+[
+ m4_pushdef([soname], AS_TR_SH([$1]))
+ m4_pushdef([SONAME], AS_TR_CPP([$1]))
+ AC_MSG_CHECKING([$1 [soname]])
+ AC_LINK_IFELSE([$2],
+ [soname[]_so=`(eval "$LDDPROG conftest$EXEEXT $LDDPOSTPROC") | grep '^lib[]$1\.so'`],
+ [soname[]_so=none])
+ if test -z "$soname[]_so"; then
+ soname[]_so=none
+ fi
+ AC_MSG_RESULT($soname[]_so)
+ if test "$soname[]_so" != none; then
+ SONAME[]_LIBRARY_SONAME="$soname[]_so"
+ AC_DEFINE_UNQUOTED([SONAME[]_LIBRARY_SONAME], ["$soname[]_so"], [The soname of $1 library])
+ fi
+ m4_popdef([soname])
+ m4_popdef([SONAME])
+])
--
2.45.2
From 0647139f50b6c14f2f2d22d40a42a8fdfaead5d5 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Sat, 6 Jul 2024 11:59:08 +0900
Subject: [PATCH 2/4] build: check if dlopen(SONAME) works in configure
Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
configure.ac | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/configure.ac b/configure.ac
index 3f001998b4..8d8c4038b6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -946,6 +946,27 @@ AM_CONDITIONAL(P11KIT_0_23_11_API, $PKG_CONFIG --atleast-version=0.23.11 p11-kit
AM_CONDITIONAL(ENABLE_PKCS11, test "$with_p11_kit" != "no")
+save_LIBS=$LIBS
+LIBS="$LIBS -lm"
+LIBGNUTLS_CHECK_SONAME([m], [AC_LANG_PROGRAM([
+ #include <math.h>],[
+ trunc (0);])])
+LIBS="$save_LIBS"
+CFLAGS="$save_CFLAGS"
+
+AC_RUN_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <dlfcn.h>
+ #include <stdlib.h>
+ ]],
+ [[void *handle = dlopen("$M_LIBRARY_SONAME", RTLD_LAZY | RTLD_GLOBAL);
+ return handle != NULL ? 0 : 1;
+ ]])],
+ [ac_cv_dlopen_soname_works=yes],
+ [ac_cv_dlopen_soname_works=no],
+ [ac_cv_dlopen_soname_works=cross-compiling])
+
+AM_CONDITIONAL([ENABLE_DLOPEN], [test "$ac_cv_dlopen_soname_works" = yes])
need_ltlibdl=no
AC_ARG_WITH(tpm2,
--
2.45.2
From 297c83d2830e44a675e8e52d65a66e0ba327f788 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Sat, 29 Jun 2024 13:34:36 +0900
Subject: [PATCH 3/4] build: detect SONAME for compression libraries at
configure
Instead of hard-coding the SONAMEs for zlib, libzstd, libbrotlienc,
and libbrotlidec, this checks the actual SONAMEs at configure time, so
the first argument of dlopen is more acurate when a SONAME is bumped.
Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
configure.ac | 82 +++++++++++++++++++++++++++++++++++++++-----------
lib/compress.c | 8 ++---
2 files changed, 68 insertions(+), 22 deletions(-)
diff --git a/configure.ac b/configure.ac
index 8d8c4038b6..28d6895efb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1048,8 +1048,6 @@ AC_DEFINE_UNQUOTED([TROUSERS_LIB], ["$ac_trousers_lib"], [the location of the tr
AC_SUBST(TROUSERS_LIB)
-AM_CONDITIONAL(NEED_LTLIBDL, test "$need_ltlibdl" = yes)
-
# For minitasn1.
AC_CHECK_SIZEOF(unsigned long int, 4)
AC_CHECK_SIZEOF(unsigned int, 4)
@@ -1058,35 +1056,45 @@ AC_CHECK_SIZEOF(time_t, 4)
AC_ARG_WITH(zlib, AS_HELP_STRING([--without-zlib],
[disable zlib compression support]),
ac_zlib=$withval, ac_zlib=yes)
-AC_MSG_CHECKING([whether to include zlib compression support])
-if test x$ac_zlib != xno; then
- AC_MSG_RESULT(yes)
- AC_LIB_HAVE_LINKFLAGS(z,, [#include <zlib.h>], [compress (0, 0, 0, 0);])
- if test x$ac_cv_libz != xyes; then
- AC_MSG_WARN(
- ***
- *** ZLIB was not found. You will not be able to use ZLIB compression.)
-fi
-else
- AC_MSG_RESULT(no)
-fi
-
-PKG_CHECK_EXISTS(zlib, ZLIB_HAS_PKGCONFIG=y, ZLIB_HAS_PKGCONFIG=n)
-
if test x$ac_zlib != xno; then
+ PKG_CHECK_EXISTS(zlib, ZLIB_HAS_PKGCONFIG=y, ZLIB_HAS_PKGCONFIG=n)
if test "$ZLIB_HAS_PKGCONFIG" = "y" ; then
+ PKG_CHECK_MODULES(ZLIB, [zlib])
if test "x$GNUTLS_REQUIRES_PRIVATE" = x; then
GNUTLS_REQUIRES_PRIVATE="Requires.private: zlib"
else
GNUTLS_REQUIRES_PRIVATE="$GNUTLS_REQUIRES_PRIVATE, zlib"
fi
- LIBZ_PC=""
+ ac_zlib=yes
else
+ AC_LIB_HAVE_LINKFLAGS(z,, [#include <zlib.h>], [compress (0, 0, 0, 0);])
+ if test x$ac_cv_libz != xyes; then
+ AC_MSG_WARN([[
+***
+*** ZLIB was not found. You will not be able to use ZLIB compression.
+*** ]])
+ fi
+ ac_zlib=$ac_cv_libz
+ ZLIB_LIBS=$LIBZ
LIBZ_PC=$LIBZ
fi
fi
+if test x$ac_zlib != xno; then
+ AC_DEFINE([HAVE_LIBZ], 1, [Define if ZLIB compression is enabled.])
+ need_ltlibdl=yes
+fi
AC_SUBST(LIBZ_PC)
+AS_IF([test "$ac_cv_dlopen_soname_works" = yes], [
+ save_LIBS=$LIBS
+ LIBS="$LIBS $ZLIB_LIBS"
+ LIBGNUTLS_CHECK_SONAME([z], [AC_LANG_PROGRAM([
+ #include <zlib.h>],[
+ compress (0, 0, 0, 0);])])
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+])
+
AC_ARG_WITH(brotli,
AS_HELP_STRING([--without-brotli], [disable brotli compression support]),
ac_brotli=$withval, ac_brotli=yes)
@@ -1102,6 +1110,7 @@ if test x$ac_brotli != xno; then
else
GNUTLS_REQUIRES_PRIVATE="${GNUTLS_REQUIRES_PRIVATE}, libbrotlienc, libbrotlidec"
fi
+ need_ltlibdl=yes
else
AC_MSG_WARN(*** LIBBROTLI was not found. You will not be able to use BROTLI compression.)
fi
@@ -1110,6 +1119,28 @@ else
fi
AM_CONDITIONAL(HAVE_LIBBROTLI, test "$with_libbrotlienc" != "no" && test "$with_libbrotlidec" != "no")
+AS_IF([test "$ac_cv_dlopen_soname_works" = yes], [
+ save_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS $LIBBROTLIENC_CFLAGS"
+ save_LIBS=$LIBS
+ LIBS="$LIBS $LIBBROTLIENC_LIBS"
+ LIBGNUTLS_CHECK_SONAME([brotlienc], [AC_LANG_PROGRAM([
+ #include <brotli/encode.h>],[
+ BrotliEncoderVersion();])])
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ save_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS $LIBBROTLIDEC_CFLAGS"
+ save_LIBS=$LIBS
+ LIBS="$LIBS $LIBBROTLIDEC_LIBS"
+ LIBGNUTLS_CHECK_SONAME([brotlidec], [AC_LANG_PROGRAM([
+ #include <brotli/decode.h>],[
+ BrotliDecoderVersion();])])
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+])
+
AC_ARG_WITH(zstd,
AS_HELP_STRING([--without-zstd], [disable zstd compression support]),
ac_zstd=$withval, ac_zstd=yes)
@@ -1124,6 +1155,7 @@ if test x$ac_zstd != xno; then
else
GNUTLS_REQUIRES_PRIVATE="${GNUTLS_REQUIRES_PRIVATE}, libzstd"
fi
+ need_ltlibdl=yes
else
AC_MSG_WARN(*** LIBZSTD was not found. You will not be able to use ZSTD compression.)
fi
@@ -1132,6 +1164,20 @@ else
fi
AM_CONDITIONAL(HAVE_LIBZSTD, test "$with_libzstd" != "no")
+AS_IF([test "$ac_cv_dlopen_soname_works" = yes], [
+ save_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS $LIBZSTD_CFLAGS"
+ save_LIBS=$LIBS
+ LIBS="$LIBS $LIBZSTD_LIBS"
+ LIBGNUTLS_CHECK_SONAME([zstd], [AC_LANG_PROGRAM([
+ #include <zstd.h>],[
+ ZSTD_versionNumber();])])
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+])
+
+AM_CONDITIONAL(NEED_LTLIBDL, test "$need_ltlibdl" = yes)
+
# export for use in scripts
AC_SUBST(ac_cv_sizeof_time_t)
diff --git a/lib/compress.c b/lib/compress.c
index a0a7c699c3..26ea2912c2 100644
--- a/lib/compress.c
+++ b/lib/compress.c
@@ -72,7 +72,7 @@ static int zlib_init(void)
#ifndef _WIN32
if (_zlib_handle != NULL)
return 0;
- if ((_zlib_handle = dlopen("libz.so.1", RTLD_NOW | RTLD_GLOBAL)) ==
+ if ((_zlib_handle = dlopen(Z_LIBRARY_SONAME, RTLD_NOW | RTLD_GLOBAL)) ==
NULL)
goto error;
if ((_gnutls_zlib_compressBound =
@@ -135,10 +135,10 @@ static int brotli_init(void)
#ifndef _WIN32
if (_brotlienc_handle != NULL || _brotlidec_handle != NULL)
return 0;
- if ((_brotlienc_handle = dlopen("libbrotlienc.so.1",
+ if ((_brotlienc_handle = dlopen(BROTLIENC_LIBRARY_SONAME,
RTLD_NOW | RTLD_GLOBAL)) == NULL)
goto error;
- if ((_brotlidec_handle = dlopen("libbrotlidec.so.1",
+ if ((_brotlidec_handle = dlopen(BROTLIDEC_LIBRARY_SONAME,
RTLD_NOW | RTLD_GLOBAL)) == NULL)
goto error;
if ((_gnutls_BrotliEncoderMaxCompressedSize =
@@ -195,7 +195,7 @@ static int zstd_init(void)
#ifndef _WIN32
if (_zstd_handle != NULL)
return 0;
- if ((_zstd_handle = dlopen("libzstd.so.1", RTLD_NOW | RTLD_GLOBAL)) ==
+ if ((_zstd_handle = dlopen(ZSTD_LIBRARY_SONAME, RTLD_NOW | RTLD_GLOBAL)) ==
NULL)
goto error;
if ((_gnutls_ZSTD_isError = dlsym(_zstd_handle, "ZSTD_isError")) ==
--
2.45.2
From 3e5be1315a15ac6e1e33e08f28030b8215b6d234 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Sat, 29 Jun 2024 13:36:58 +0900
Subject: [PATCH 4/4] build: switch to using dlwrap for loading compression
libraries
This switches the logic to load compression libraries from the
hand-written code to the automatically generated code by the dlwrap
tool[1], which enables to select whether to use dlopen or link to the
library at build time.
1. https://crates.io/crates/dlwrap
Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
cfg.mk | 2 +-
configure.ac | 1 +
devel/check-headers.sh | 4 +-
devel/dlwrap/brotli.license | 4 +
devel/dlwrap/brotlidec.syms | 1 +
devel/dlwrap/brotlienc.syms | 2 +
devel/dlwrap/z.license | 20 ++++
devel/dlwrap/z.syms | 3 +
devel/dlwrap/zstd.license | 7 ++
devel/dlwrap/zstd.syms | 4 +
devel/generate-dlwrap.sh | 37 ++++++
devel/indent-gnutls | 2 +-
lib/Makefile.am | 40 ++++++-
lib/compress.c | 218 ++++++++++--------------------------
lib/dlwrap/brotlidec.c | 182 ++++++++++++++++++++++++++++++
lib/dlwrap/brotlidec.h | 47 ++++++++
lib/dlwrap/brotlidecfuncs.h | 9 ++
lib/dlwrap/brotlienc.c | 182 ++++++++++++++++++++++++++++++
lib/dlwrap/brotlienc.h | 47 ++++++++
lib/dlwrap/brotliencfuncs.h | 10 ++
lib/dlwrap/zlib.c | 182 ++++++++++++++++++++++++++++++
lib/dlwrap/zlib.h | 47 ++++++++
lib/dlwrap/zlibfuncs.h | 27 +++++
lib/dlwrap/zstd.c | 182 ++++++++++++++++++++++++++++++
lib/dlwrap/zstd.h | 47 ++++++++
lib/dlwrap/zstdfuncs.h | 15 +++
26 files changed, 1154 insertions(+), 168 deletions(-)
create mode 100644 devel/dlwrap/brotli.license
create mode 100644 devel/dlwrap/brotlidec.syms
create mode 100644 devel/dlwrap/brotlienc.syms
create mode 100644 devel/dlwrap/z.license
create mode 100644 devel/dlwrap/z.syms
create mode 100644 devel/dlwrap/zstd.license
create mode 100644 devel/dlwrap/zstd.syms
create mode 100755 devel/generate-dlwrap.sh
create mode 100644 lib/dlwrap/brotlidec.c
create mode 100644 lib/dlwrap/brotlidec.h
create mode 100644 lib/dlwrap/brotlidecfuncs.h
create mode 100644 lib/dlwrap/brotlienc.c
create mode 100644 lib/dlwrap/brotlienc.h
create mode 100644 lib/dlwrap/brotliencfuncs.h
create mode 100644 lib/dlwrap/zlib.c
create mode 100644 lib/dlwrap/zlib.h
create mode 100644 lib/dlwrap/zlibfuncs.h
create mode 100644 lib/dlwrap/zstd.c
create mode 100644 lib/dlwrap/zstd.h
create mode 100644 lib/dlwrap/zstdfuncs.h
diff --git a/cfg.mk b/cfg.mk
index 5ef839a2c1..1b94279633 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -24,7 +24,7 @@ PACKAGE ?= gnutls
.PHONY: config glimport
-INDENT_SOURCES = `find . -name \*.[ch] -o -name gnutls.h.in | grep -v -e ^./build-aux/ -e ^./config.h -e ^./devel/ -e ^./gnulib -e ^./lib/minitasn1/ -e ^./lib/includes/gnutls/gnutls.h -e ^./lib/nettle/backport/ -e ^./lib/priority_options.h -e ^./lib/unistring/ -e ^./lib/x509/supported_exts.h -e ^./lib/build-aux/ -e ^./gl/ -e ^./src/gl/ -e ^./src/.*-options.[ch] -e -args.[ch] -e asn1_tab.c -e ^./tests/suite/`
+INDENT_SOURCES = `find . -name \*.[ch] -o -name gnutls.h.in | grep -v -e ^./build-aux/ -e ^./config.h -e ^./devel/ -e ^./gnulib -e ^./lib/minitasn1/ -e ^./lib/includes/gnutls/gnutls.h -e ^./lib/nettle/backport/ -e ^./lib/priority_options.h -e ^./lib/unistring/ -e ^./lib/x509/supported_exts.h -e ^./lib/build-aux/ -e ^./lib/dlwrap/ -e ^./gl/ -e ^./src/gl/ -e ^./src/.*-options.[ch] -e -args.[ch] -e asn1_tab.c -e ^./tests/suite/`
ifeq ($(.DEFAULT_GOAL),abort-due-to-no-makefile)
.DEFAULT_GOAL := bootstrap
diff --git a/configure.ac b/configure.ac
index 28d6895efb..62a7fbdf66 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1083,6 +1083,7 @@ if test x$ac_zlib != xno; then
AC_DEFINE([HAVE_LIBZ], 1, [Define if ZLIB compression is enabled.])
need_ltlibdl=yes
fi
+AM_CONDITIONAL(HAVE_ZLIB, test "$ac_zlib" = "yes")
AC_SUBST(LIBZ_PC)
AS_IF([test "$ac_cv_dlopen_soname_works" = yes], [
diff --git a/devel/dlwrap/brotli.license b/devel/dlwrap/brotli.license
new file mode 100644
index 0000000000..d65b39b1ac
--- /dev/null
+++ b/devel/dlwrap/brotli.license
@@ -0,0 +1,4 @@
+Copyright 2013 Google Inc. All Rights Reserved.
+
+Distributed under MIT license.
+See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
diff --git a/devel/dlwrap/brotlidec.syms b/devel/dlwrap/brotlidec.syms
new file mode 100644
index 0000000000..97edbad15e
--- /dev/null
+++ b/devel/dlwrap/brotlidec.syms
@@ -0,0 +1 @@
+BrotliDecoderDecompress
diff --git a/devel/dlwrap/brotlienc.syms b/devel/dlwrap/brotlienc.syms
new file mode 100644
index 0000000000..d618292047
--- /dev/null
+++ b/devel/dlwrap/brotlienc.syms
@@ -0,0 +1,2 @@
+BrotliEncoderMaxCompressedSize
+BrotliEncoderCompress
diff --git a/devel/dlwrap/z.license b/devel/dlwrap/z.license
new file mode 100644
index 0000000000..94ce4ae9c9
--- /dev/null
+++ b/devel/dlwrap/z.license
@@ -0,0 +1,20 @@
+Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+Jean-loup Gailly Mark Adler
+jloup@gzip.org madler@alumni.caltech.edu
diff --git a/devel/dlwrap/z.syms b/devel/dlwrap/z.syms
new file mode 100644
index 0000000000..e3ed6c13f2
--- /dev/null
+++ b/devel/dlwrap/z.syms
@@ -0,0 +1,3 @@
+compressBound
+compress
+uncompress
diff --git a/devel/dlwrap/zstd.license b/devel/dlwrap/zstd.license
new file mode 100644
index 0000000000..4b585386bf
--- /dev/null
+++ b/devel/dlwrap/zstd.license
@@ -0,0 +1,7 @@
+Copyright (c) Meta Platforms, Inc. and affiliates.
+All rights reserved.
+
+This source code is licensed under both the BSD-style license (found in the
+LICENSE file in the root directory of this source tree) and the GPLv2 (found
+in the COPYING file in the root directory of this source tree).
+You may select, at your option, one of the above-listed licenses.
diff --git a/devel/dlwrap/zstd.syms b/devel/dlwrap/zstd.syms
new file mode 100644
index 0000000000..881bdc8135
--- /dev/null
+++ b/devel/dlwrap/zstd.syms
@@ -0,0 +1,4 @@
+ZSTD_isError
+ZSTD_compressBound
+ZSTD_compress
+ZSTD_decompress
diff --git a/devel/generate-dlwrap.sh b/devel/generate-dlwrap.sh
new file mode 100755
index 0000000000..dbcf870612
--- /dev/null
+++ b/devel/generate-dlwrap.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+# This script generates dlopen stubs for optional libraries using dlwrap tool:
+# https://crates.io/crates/dlwrap
+
+# Copyright (c) 2023 Daiki Ueno
+# License: GPLv3+ <http://gnu.org/licenses/gpl.html>
+
+set +e
+
+: ${srcdir=.}
+: ${DLWRAP=dlwrap}
+
+if ! "$DLWRAP" -V >& /dev/null; then
+ echo 1>&2 "$0: "$DLWRAP" is missing"
+ exit 77
+fi
+
+SRC="$srcdir/devel/$DLWRAP"
+DST="$srcdir/lib/$DLWRAP"
+
+echo "Generating $DST/zlib.h"
+
+"$DLWRAP" --input /usr/include/zlib.h -o "$DST" --clang-resource-dir $(clang -print-resource-dir) --symbol-file "$SRC/z.syms" --license-file "$SRC/z.license" --soname Z_LIBRARY_SONAME --prefix gnutls_zlib --header-guard GNUTLS_LIB_DLWRAP_ZLIB_H_ --include "<zlib.h>"
+
+echo "Generating $DST/zstd.h"
+
+"$DLWRAP" --input /usr/include/zstd.h -o "$DST" --clang-resource-dir $(clang -print-resource-dir) --symbol-file "$SRC/zstd.syms" --license-file "$SRC/zstd.license" --soname ZSTD_LIBRARY_SONAME --prefix gnutls_zstd --header-guard GNUTLS_LIB_DLWRAP_ZSTD_H_ --include "<zstd.h>"
+
+echo "Generating $DST/brotlienc.h"
+
+"$DLWRAP" --input /usr/include/brotli/encode.h -o "$DST" --clang-resource-dir $(clang -print-resource-dir) --symbol-file "$SRC/brotlienc.syms" --license-file "$SRC/brotli.license" --soname BROTLIENC_LIBRARY_SONAME --prefix gnutls_brotlienc --loader-basename brotlienc --header-guard GNUTLS_LIB_DLWRAP_BROTLIENC_H_ --include "<brotli/encode.h>"
+
+echo "Generating $DST/brotlidec.h"
+
+"$DLWRAP" --input /usr/include/brotli/decode.h -o "$DST" --clang-resource-dir $(clang -print-resource-dir) --symbol-file "$SRC/brotlidec.syms" --license-file "$SRC/brotli.license" --soname BROTLIDEC_LIBRARY_SONAME --prefix gnutls_brotlidec --loader-basename brotlidec --header-guard GNUTLS_LIB_DLWRAP_BROTLIDEC_H_ --include "<brotli/decode.h>"
+
diff --git a/lib/Makefile.am b/lib/Makefile.am
index a50d3114ea..d1bd07248e 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -33,7 +33,7 @@ localedir = $(datadir)/locale
include $(top_srcdir)/lib/common.mk
-AM_CPPFLAGS = \
+AM_CPPFLAGS = \
-DLOCALEDIR=\"$(localedir)\" \
-I$(srcdir)/../gl \
-I$(builddir)/../gl \
@@ -45,7 +45,8 @@ AM_CPPFLAGS = \
$(LIBTASN1_CFLAGS) \
$(P11_KIT_CFLAGS) \
$(TSS2_CFLAGS)
- $(LIBZSTD_CFLAGS)
+
+thirdparty_libadd =
if !HAVE_LIBUNISTRING
SUBDIRS += unistring
@@ -85,6 +86,39 @@ COBJECTS = range.c record.c compress.c debug.c cipher.c gthreads.h handshake-tls
hello_ext_lib.c hello_ext_lib.h ocsp-api.c stek.c cert-cred-rawpk.c \
iov.c iov.h system/ktls.c system/ktls.h pathbuf.c pathbuf.h
+if HAVE_ZLIB
+COBJECTS += dlwrap/zlib.c dlwrap/zlibfuncs.h dlwrap/zlib.h
+
+if ENABLE_DLOPEN
+AM_CPPFLAGS += $(ZLIB_CFLAGS) -DGNUTLS_ZLIB_ENABLE_DLOPEN=1
+else
+thirdparty_libadd += $(ZLIB_LIBS)
+endif
+endif
+
+if HAVE_LIBZSTD
+COBJECTS += dlwrap/zstd.c dlwrap/zstdfuncs.h dlwrap/zstd.h
+
+if ENABLE_DLOPEN
+AM_CPPFLAGS += $(LIBZSTD_CFLAGS) -DGNUTLS_ZSTD_ENABLE_DLOPEN=1
+else
+thirdparty_libadd += $(LIBZSTD_LIBS)
+endif
+endif
+
+if HAVE_LIBBROTLI
+COBJECTS += dlwrap/brotlienc.c dlwrap/brotliencfuncs.h dlwrap/brotlienc.h
+COBJECTS += dlwrap/brotlidec.c dlwrap/brotlidecfuncs.h dlwrap/brotlidec.h
+
+if ENABLE_DLOPEN
+AM_CPPFLAGS += $(LIBBROTLIENC_CFLAGS) -DGNUTLS_BROTLIENC_ENABLE_DLOPEN=1
+AM_CPPFLAGS += $(LIBBROTLIDEC_CFLAGS) -DGNUTLS_BROTLIDEC_ENABLE_DLOPEN=1
+else
+thirdparty_libadd += $(LIBBROTLIENC_LIBS)
+thirdparty_libadd += $(LIBBROTLIDEC_LIBS)
+endif
+endif
+
if ENABLE_GOST
COBJECTS += vko.c
endif
@@ -156,7 +190,7 @@ libgnutls_la_LIBADD = ../gl/libgnu.la x509/libgnutls_x509.la \
ext/libgnutls_ext.la \
auth/libgnutls_auth.la algorithms/libgnutls_alg.la \
extras/libgnutls_extras.la
-thirdparty_libadd = $(LTLIBINTL) $(LIBSOCKET) $(LTLIBNSL) \
+thirdparty_libadd += $(LTLIBINTL) $(LIBSOCKET) $(LTLIBNSL) \
$(P11_KIT_LIBS) $(LIB_SELECT) $(GNUTLS_LIBS_PRIVATE)
if HAVE_LIBIDN2
diff --git a/lib/compress.c b/lib/compress.c
index 26ea2912c2..936a459532 100644
--- a/lib/compress.c
+++ b/lib/compress.c
@@ -25,198 +25,91 @@
#include "compress.h"
-#ifndef _WIN32
+#ifdef _WIN32
+#define RTLD_NOW 0
+#define RTLD_GLOBAL 0
+#else
#include <dlfcn.h>
#endif
+#ifndef Z_LIBRARY_SONAME
+#define Z_LIBRARY_SONAME "none"
+#endif
+
+#ifndef BROTLIENC_LIBRARY_SONAME
+#define BROTLIENC_LIBRARY_SONAME "none"
+#endif
+
+#ifndef BROTLIDEC_LIBRARY_SONAME
+#define BROTLIDEC_LIBRARY_SONAME "none"
+#endif
+
+#ifndef ZSTD_LIBRARY_SONAME
+#define ZSTD_LIBRARY_SONAME "none"
+#endif
+
#ifdef HAVE_LIBZ
-#include <zlib.h>
+#include "dlwrap/zlib.h"
#endif
#ifdef HAVE_LIBBROTLI
-#include <brotli/decode.h>
-#include <brotli/encode.h>
+#include "dlwrap/brotlienc.h"
+#include "dlwrap/brotlidec.h"
#endif
#ifdef HAVE_LIBZSTD
-#include <zstd.h>
+#include "dlwrap/zstd.h"
#endif
#ifdef HAVE_LIBZ
-static void *_zlib_handle;
-
-#if HAVE___TYPEOF__
-static __typeof__(compressBound)(*_gnutls_zlib_compressBound);
-static __typeof__(compress)(*_gnutls_zlib_compress);
-static __typeof__(uncompress)(*_gnutls_zlib_uncompress);
-#else
-static uLong (*_gnutls_zlib_compressBound)(uLong sourceLen);
-static int (*_gnutls_zlib_compress)(Bytef *dest, uLongf *destLen,
- const Bytef *source, uLong sourceLen);
-static int (*_gnutls_zlib_uncompress)(Bytef *dest, uLongf *destLen,
- const Bytef *source, uLong sourceLen);
-#endif /* HAVE___TYPEOF__ */
-
static void zlib_deinit(void)
{
-#ifndef _WIN32
- if (_zlib_handle != NULL) {
- dlclose(_zlib_handle);
- _zlib_handle = NULL;
- }
-#endif /* _WIN32 */
+ gnutls_zlib_unload_library();
}
static int zlib_init(void)
{
-#ifndef _WIN32
- if (_zlib_handle != NULL)
- return 0;
- if ((_zlib_handle = dlopen(Z_LIBRARY_SONAME, RTLD_NOW | RTLD_GLOBAL)) ==
- NULL)
- goto error;
- if ((_gnutls_zlib_compressBound =
- dlsym(_zlib_handle, "compressBound")) == NULL)
- goto error;
- if ((_gnutls_zlib_compress = dlsym(_zlib_handle, "compress")) == NULL)
- goto error;
- if ((_gnutls_zlib_uncompress = dlsym(_zlib_handle, "uncompress")) ==
- NULL)
- goto error;
+ if (gnutls_zlib_ensure_library(Z_LIBRARY_SONAME,
+ RTLD_NOW | RTLD_GLOBAL) < 0)
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
return 0;
-error:
- zlib_deinit();
- return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
-#else
- return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
-#endif /* _WIN32 */
}
#endif /* HAVE_LIBZ */
#ifdef HAVE_LIBBROTLI
-static void *_brotlienc_handle;
-static void *_brotlidec_handle;
-
-#if HAVE___TYPEOF__
-static __typeof__(BrotliEncoderMaxCompressedSize)(
- *_gnutls_BrotliEncoderMaxCompressedSize);
-static __typeof__(BrotliEncoderCompress)(*_gnutls_BrotliEncoderCompress);
-static __typeof__(BrotliDecoderDecompress)(*_gnutls_BrotliDecoderDecompress);
-#else
-static size_t (*_gnutls_BrotliEncoderMaxCompressedSize)(size_t input_size);
-static BROTLI_BOOL (*_gnutls_BrotliEncoderCompress)(
- int quality, int lgwin, BrotliEncoderMode mode, size_t input_size,
- const uint8_t input_buffer[BROTLI_ARRAY_PARAM(input_size)],
- size_t *encoded_size,
- uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(*encoded_size)]);
-static BrotliDecoderResult (*_gnutls_BrotliDecoderDecompress)(
- size_t encoded_size,
- const uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(encoded_size)],
- size_t *decoded_size,
- uint8_t decoded_buffer[BROTLI_ARRAY_PARAM(*decoded_size)]);
-#endif /* HAVE___TYPEOF__ */
static void brotli_deinit(void)
{
-#ifndef _WIN32
- if (_brotlienc_handle != NULL) {
- dlclose(_brotlienc_handle);
- _brotlienc_handle = NULL;
- }
- if (_brotlidec_handle != NULL) {
- dlclose(_brotlidec_handle);
- _brotlidec_handle = NULL;
- }
-#endif /* _WIN32 */
+ gnutls_brotlienc_unload_library();
+ gnutls_brotlidec_unload_library();
}
static int brotli_init(void)
{
-#ifndef _WIN32
- if (_brotlienc_handle != NULL || _brotlidec_handle != NULL)
- return 0;
- if ((_brotlienc_handle = dlopen(BROTLIENC_LIBRARY_SONAME,
- RTLD_NOW | RTLD_GLOBAL)) == NULL)
- goto error;
- if ((_brotlidec_handle = dlopen(BROTLIDEC_LIBRARY_SONAME,
- RTLD_NOW | RTLD_GLOBAL)) == NULL)
- goto error;
- if ((_gnutls_BrotliEncoderMaxCompressedSize =
- dlsym(_brotlienc_handle,
- "BrotliEncoderMaxCompressedSize")) == NULL)
- goto error;
- if ((_gnutls_BrotliEncoderCompress =
- dlsym(_brotlienc_handle, "BrotliEncoderCompress")) == NULL)
- goto error;
- if ((_gnutls_BrotliDecoderDecompress = dlsym(
- _brotlidec_handle, "BrotliDecoderDecompress")) == NULL)
- goto error;
+ if (gnutls_brotlienc_ensure_library(BROTLIENC_LIBRARY_SONAME,
+ RTLD_NOW | RTLD_GLOBAL) < 0)
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+
+ if (gnutls_brotlidec_ensure_library(BROTLIDEC_LIBRARY_SONAME,
+ RTLD_NOW | RTLD_GLOBAL) < 0)
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
return 0;
-error:
- brotli_deinit();
- return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
-#else
- return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
-#endif /* _WIN32 */
}
#endif /* HAVE_LIBBROTLI */
#ifdef HAVE_LIBZSTD
-static void *_zstd_handle;
-
-#if HAVE___TYPEOF__
-static __typeof__(ZSTD_isError)(*_gnutls_ZSTD_isError);
-static __typeof__(ZSTD_compressBound)(*_gnutls_ZSTD_compressBound);
-static __typeof__(ZSTD_compress)(*_gnutls_ZSTD_compress);
-static __typeof__(ZSTD_decompress)(*_gnutls_ZSTD_decompress);
-#else
-static unsigned (*_gnutls_ZSTD_isError)(size_t code);
-static size_t (*_gnutls_ZSTD_compressBound)(size_t srcSize);
-static size_t (*_gnutls_ZSTD_compress)(void *dst, size_t dstCapacity,
- const void *src, size_t srcSize,
- int compressionLevel);
-static size_t (*_gnutls_ZSTD_decompress)(void *dst, size_t dstCapacity,
- const void *src,
- size_t compressedSize);
-#endif /* HAVE___TYPEOF__ */
static void zstd_deinit(void)
{
-#ifndef _WIN32
- if (_zstd_handle != NULL) {
- dlclose(_zstd_handle);
- _zstd_handle = NULL;
- }
-#endif /* _WIN32 */
+ gnutls_zstd_unload_library();
}
static int zstd_init(void)
{
-#ifndef _WIN32
- if (_zstd_handle != NULL)
- return 0;
- if ((_zstd_handle = dlopen(ZSTD_LIBRARY_SONAME, RTLD_NOW | RTLD_GLOBAL)) ==
- NULL)
- goto error;
- if ((_gnutls_ZSTD_isError = dlsym(_zstd_handle, "ZSTD_isError")) ==
- NULL)
- goto error;
- if ((_gnutls_ZSTD_compressBound =
- dlsym(_zstd_handle, "ZSTD_compressBound")) == NULL)
- goto error;
- if ((_gnutls_ZSTD_compress = dlsym(_zstd_handle, "ZSTD_compress")) ==
- NULL)
- goto error;
- if ((_gnutls_ZSTD_decompress =
- dlsym(_zstd_handle, "ZSTD_decompress")) == NULL)
- goto error;
+ if (gnutls_zstd_ensure_library(ZSTD_LIBRARY_SONAME,
+ RTLD_NOW | RTLD_GLOBAL) < 0)
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
return 0;
-error:
- zstd_deinit();
- return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
-#else
- return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
-#endif /* _WIN32 */
}
#endif /* HAVE_LIBZSTD */
@@ -345,15 +238,16 @@ size_t _gnutls_compress_bound(gnutls_compression_method_t alg, size_t src_len)
switch (alg) {
#ifdef HAVE_LIBZ
case GNUTLS_COMP_ZLIB:
- return _gnutls_zlib_compressBound(src_len);
+ return GNUTLS_ZLIB_FUNC(compressBound)(src_len);
#endif
#ifdef HAVE_LIBBROTLI
case GNUTLS_COMP_BROTLI:
- return _gnutls_BrotliEncoderMaxCompressedSize(src_len);
+ return GNUTLS_BROTLIENC_FUNC(BrotliEncoderMaxCompressedSize)(
+ src_len);
#endif
#ifdef HAVE_LIBZSTD
case GNUTLS_COMP_ZSTD:
- return _gnutls_ZSTD_compressBound(src_len);
+ return GNUTLS_ZSTD_FUNC(ZSTD_compressBound)(src_len);
#endif
default:
return 0;
@@ -372,7 +266,7 @@ int _gnutls_compress(gnutls_compression_method_t alg, uint8_t *dst,
int err;
uLongf comp_len = dst_len;
- err = _gnutls_zlib_compress(dst, &comp_len, src, src_len);
+ err = GNUTLS_ZLIB_FUNC(compress)(dst, &comp_len, src, src_len);
if (err != Z_OK)
return gnutls_assert_val(GNUTLS_E_COMPRESSION_FAILED);
ret = comp_len;
@@ -383,7 +277,7 @@ int _gnutls_compress(gnutls_compression_method_t alg, uint8_t *dst,
BROTLI_BOOL err;
size_t comp_len = dst_len;
- err = _gnutls_BrotliEncoderCompress(
+ err = GNUTLS_BROTLIENC_FUNC(BrotliEncoderCompress)(
BROTLI_DEFAULT_QUALITY, BROTLI_DEFAULT_WINDOW,
BROTLI_DEFAULT_MODE, src_len, src, &comp_len, dst);
if (!err)
@@ -395,9 +289,9 @@ int _gnutls_compress(gnutls_compression_method_t alg, uint8_t *dst,
case GNUTLS_COMP_ZSTD: {
size_t comp_len;
- comp_len = _gnutls_ZSTD_compress(dst, dst_len, src, src_len,
- ZSTD_CLEVEL_DEFAULT);
- if (_gnutls_ZSTD_isError(comp_len))
+ comp_len = GNUTLS_ZSTD_FUNC(ZSTD_compress)(
+ dst, dst_len, src, src_len, ZSTD_CLEVEL_DEFAULT);
+ if (GNUTLS_ZSTD_FUNC(ZSTD_isError)(comp_len))
return gnutls_assert_val(GNUTLS_E_COMPRESSION_FAILED);
ret = comp_len;
} break;
@@ -425,7 +319,8 @@ int _gnutls_decompress(gnutls_compression_method_t alg, uint8_t *dst,
int err;
uLongf plain_len = dst_len;
- err = _gnutls_zlib_uncompress(dst, &plain_len, src, src_len);
+ err = GNUTLS_ZLIB_FUNC(uncompress)(dst, &plain_len, src,
+ src_len);
if (err != Z_OK)
return gnutls_assert_val(GNUTLS_E_DECOMPRESSION_FAILED);
ret = plain_len;
@@ -436,8 +331,8 @@ int _gnutls_decompress(gnutls_compression_method_t alg, uint8_t *dst,
BrotliDecoderResult err;
size_t plain_len = dst_len;
- err = _gnutls_BrotliDecoderDecompress(src_len, src, &plain_len,
- dst);
+ err = GNUTLS_BROTLIDEC_FUNC(
+ BrotliDecoderDecompress)(src_len, src, &plain_len, dst);
if (err != BROTLI_DECODER_RESULT_SUCCESS)
return gnutls_assert_val(GNUTLS_E_DECOMPRESSION_FAILED);
ret = plain_len;
@@ -447,8 +342,9 @@ int _gnutls_decompress(gnutls_compression_method_t alg, uint8_t *dst,
case GNUTLS_COMP_ZSTD: {
size_t plain_len;
- plain_len = _gnutls_ZSTD_decompress(dst, dst_len, src, src_len);
- if (_gnutls_ZSTD_isError(plain_len))
+ plain_len = GNUTLS_ZSTD_FUNC(ZSTD_decompress)(dst, dst_len, src,
+ src_len);
+ if (GNUTLS_ZSTD_FUNC(ZSTD_isError)(plain_len))
return gnutls_assert_val(GNUTLS_E_DECOMPRESSION_FAILED);
ret = plain_len;
} break;
diff --git a/lib/dlwrap/brotlidec.c b/lib/dlwrap/brotlidec.c
new file mode 100644
index 0000000000..45c9b4b259
--- /dev/null
+++ b/lib/dlwrap/brotlidec.c
@@ -0,0 +1,182 @@
+/*
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved. This file is offered as-is,
+ * without any warranty.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "brotlidec.h"
+
+#if defined(GNUTLS_BROTLIDEC_ENABLE_DLOPEN) && GNUTLS_BROTLIDEC_ENABLE_DLOPEN
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* If BROTLIDEC_LIBRARY_SONAME is defined, dlopen handle can be automatically
+ * set; otherwise, the caller needs to call
+ * gnutls_brotlidec_ensure_library with soname determined at run time.
+ */
+#ifdef BROTLIDEC_LIBRARY_SONAME
+
+static void
+ensure_library (void)
+{
+ if (gnutls_brotlidec_ensure_library (BROTLIDEC_LIBRARY_SONAME, RTLD_LAZY | RTLD_LOCAL) < 0)
+ abort ();
+}
+
+#if defined(GNUTLS_BROTLIDEC_ENABLE_PTHREAD) && GNUTLS_BROTLIDEC_ENABLE_PTHREAD
+#include <pthread.h>
+
+static pthread_once_t dlopen_once = PTHREAD_ONCE_INIT;
+
+#define ENSURE_LIBRARY pthread_once(&dlopen_once, ensure_library)
+
+#else /* GNUTLS_BROTLIDEC_ENABLE_PTHREAD */
+
+#define ENSURE_LIBRARY do { \
+ if (!gnutls_brotlidec_dlhandle) \
+ ensure_library(); \
+ } while (0)
+
+#endif /* !GNUTLS_BROTLIDEC_ENABLE_PTHREAD */
+
+#else /* BROTLIDEC_LIBRARY_SONAME */
+
+#define ENSURE_LIBRARY do {} while (0)
+
+#endif /* !BROTLIDEC_LIBRARY_SONAME */
+
+static void *gnutls_brotlidec_dlhandle;
+
+/* Define redirection symbols */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+
+#if (2 <= __GNUC__ || (4 <= __clang_major__))
+#define FUNC(ret, name, args, cargs) \
+ static __typeof__(name)(*gnutls_brotlidec_sym_##name);
+#else
+#define FUNC(ret, name, args, cargs) \
+ static ret(*gnutls_brotlidec_sym_##name)args;
+#endif
+#define VOID_FUNC FUNC
+#include "brotlidecfuncs.h"
+#undef VOID_FUNC
+#undef FUNC
+
+#pragma GCC diagnostic pop
+
+/* Define redirection wrapper functions */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+
+#define FUNC(ret, name, args, cargs) \
+ret gnutls_brotlidec_func_##name args \
+{ \
+ ENSURE_LIBRARY; \
+ assert (gnutls_brotlidec_sym_##name); \
+ return gnutls_brotlidec_sym_##name cargs; \
+}
+#define VOID_FUNC(ret, name, args, cargs) \
+ret gnutls_brotlidec_func_##name args \
+{ \
+ ENSURE_LIBRARY; \
+ assert (gnutls_brotlidec_sym_##name); \
+ gnutls_brotlidec_sym_##name cargs; \
+}
+#include "brotlidecfuncs.h"
+#undef VOID_FUNC
+#undef FUNC
+
+#pragma GCC diagnostic pop
+
+static int
+ensure_symbol (const char *name, void **symp)
+{
+ if (!*symp)
+ {
+ void *sym = dlsym (gnutls_brotlidec_dlhandle, name);
+ if (!sym)
+ return -errno;
+ *symp = sym;
+ }
+ return 0;
+}
+
+int
+gnutls_brotlidec_ensure_library (const char *soname, int flags)
+{
+ int err;
+
+ if (!gnutls_brotlidec_dlhandle)
+ {
+ gnutls_brotlidec_dlhandle = dlopen (soname, flags);
+ if (!gnutls_brotlidec_dlhandle)
+ return -errno;
+ }
+
+#define ENSURE_SYMBOL(name) \
+ ensure_symbol(#name, (void **)&gnutls_brotlidec_sym_##name)
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+
+#define FUNC(ret, name, args, cargs) \
+ err = ENSURE_SYMBOL(name); \
+ if (err < 0) \
+ return err;
+#define VOID_FUNC FUNC
+#include "brotlidecfuncs.h"
+#undef VOID_FUNC
+#undef FUNC
+
+#pragma GCC diagnostic pop
+
+#undef ENSURE_SYMBOL
+ return 0;
+}
+
+void
+gnutls_brotlidec_unload_library (void)
+{
+ if (gnutls_brotlidec_dlhandle)
+ dlclose (gnutls_brotlidec_dlhandle);
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+
+#define FUNC(ret, name, args, cargs) \
+ gnutls_brotlidec_sym_##name = NULL;
+#define VOID_FUNC FUNC
+#include "brotlidecfuncs.h"
+#undef VOID_FUNC
+#undef FUNC
+
+#pragma GCC diagnostic pop
+
+#undef RESET_SYMBOL
+}
+
+#else /* GNUTLS_BROTLIDEC_ENABLE_DLOPEN */
+
+int
+gnutls_brotlidec_ensure_library (const char *soname, int flags)
+{
+ (void) soname;
+ (void) flags;
+ return 0;
+}
+
+void
+gnutls_brotlidec_unload_library (void)
+{
+}
+
+#endif /* !GNUTLS_BROTLIDEC_ENABLE_DLOPEN */
diff --git a/lib/dlwrap/brotlidec.h b/lib/dlwrap/brotlidec.h
new file mode 100644
index 0000000000..31397f24cf
--- /dev/null
+++ b/lib/dlwrap/brotlidec.h
@@ -0,0 +1,47 @@
+/*
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved. This file is offered as-is,
+ * without any warranty.
+ */
+
+#ifndef GNUTLS_LIB_DLWRAP_BROTLIDEC_H_
+#define GNUTLS_LIB_DLWRAP_BROTLIDEC_H_
+
+#include <brotli/decode.h>
+
+#if defined(GNUTLS_BROTLIDEC_ENABLE_DLOPEN) && GNUTLS_BROTLIDEC_ENABLE_DLOPEN
+
+#define FUNC(ret, name, args, cargs) \
+ ret gnutls_brotlidec_func_##name args;
+#define VOID_FUNC FUNC
+#include "brotlidecfuncs.h"
+#undef VOID_FUNC
+#undef FUNC
+
+#define GNUTLS_BROTLIDEC_FUNC(name) gnutls_brotlidec_func_##name
+
+#else
+
+#define GNUTLS_BROTLIDEC_FUNC(name) name
+
+#endif /* GNUTLS_BROTLIDEC_ENABLE_DLOPEN */
+
+/* Ensure SONAME to be loaded with dlopen FLAGS, and all the necessary
+ * symbols are resolved.
+ *
+ * Returns 0 on success; negative error code otherwise.
+ *
+ * Note that this function is NOT thread-safe; when calling it from
+ * multi-threaded programs, protect it with a locking mechanism.
+ */
+int gnutls_brotlidec_ensure_library (const char *soname, int flags);
+
+/* Unload library and reset symbols.
+ *
+ * Note that this function is NOT thread-safe; when calling it from
+ * multi-threaded programs, protect it with a locking mechanism.
+ */
+void gnutls_brotlidec_unload_library (void);
+
+#endif /* GNUTLS_LIB_DLWRAP_BROTLIDEC_H_ */
diff --git a/lib/dlwrap/brotlidecfuncs.h b/lib/dlwrap/brotlidecfuncs.h
new file mode 100644
index 0000000000..aa033e3a8b
--- /dev/null
+++ b/lib/dlwrap/brotlidecfuncs.h
@@ -0,0 +1,9 @@
+/*
+ * This file was automatically generated from decode.h,
+ * which is covered by the following license:
+ * Copyright 2013 Google Inc. All Rights Reserved.
+ *
+ * Distributed under MIT license.
+ * See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+ */
+FUNC(BrotliDecoderResult, BrotliDecoderDecompress, (size_t encoded_size, const uint8_t encoded_buffer[], size_t *decoded_size, uint8_t decoded_buffer[]), (encoded_size, encoded_buffer, decoded_size, decoded_buffer))
diff --git a/lib/dlwrap/brotlienc.c b/lib/dlwrap/brotlienc.c
new file mode 100644
index 0000000000..9dd8ff37c6
--- /dev/null
+++ b/lib/dlwrap/brotlienc.c
@@ -0,0 +1,182 @@
+/*
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved. This file is offered as-is,
+ * without any warranty.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "brotlienc.h"
+
+#if defined(GNUTLS_BROTLIENC_ENABLE_DLOPEN) && GNUTLS_BROTLIENC_ENABLE_DLOPEN
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* If BROTLIENC_LIBRARY_SONAME is defined, dlopen handle can be automatically
+ * set; otherwise, the caller needs to call
+ * gnutls_brotlienc_ensure_library with soname determined at run time.
+ */
+#ifdef BROTLIENC_LIBRARY_SONAME
+
+static void
+ensure_library (void)
+{
+ if (gnutls_brotlienc_ensure_library (BROTLIENC_LIBRARY_SONAME, RTLD_LAZY | RTLD_LOCAL) < 0)
+ abort ();
+}
+
+#if defined(GNUTLS_BROTLIENC_ENABLE_PTHREAD) && GNUTLS_BROTLIENC_ENABLE_PTHREAD
+#include <pthread.h>
+
+static pthread_once_t dlopen_once = PTHREAD_ONCE_INIT;
+
+#define ENSURE_LIBRARY pthread_once(&dlopen_once, ensure_library)
+
+#else /* GNUTLS_BROTLIENC_ENABLE_PTHREAD */
+
+#define ENSURE_LIBRARY do { \
+ if (!gnutls_brotlienc_dlhandle) \
+ ensure_library(); \
+ } while (0)
+
+#endif /* !GNUTLS_BROTLIENC_ENABLE_PTHREAD */
+
+#else /* BROTLIENC_LIBRARY_SONAME */
+
+#define ENSURE_LIBRARY do {} while (0)
+
+#endif /* !BROTLIENC_LIBRARY_SONAME */
+
+static void *gnutls_brotlienc_dlhandle;
+
+/* Define redirection symbols */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+
+#if (2 <= __GNUC__ || (4 <= __clang_major__))
+#define FUNC(ret, name, args, cargs) \
+ static __typeof__(name)(*gnutls_brotlienc_sym_##name);
+#else
+#define FUNC(ret, name, args, cargs) \
+ static ret(*gnutls_brotlienc_sym_##name)args;
+#endif
+#define VOID_FUNC FUNC
+#include "brotliencfuncs.h"
+#undef VOID_FUNC
+#undef FUNC
+
+#pragma GCC diagnostic pop
+
+/* Define redirection wrapper functions */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+
+#define FUNC(ret, name, args, cargs) \
+ret gnutls_brotlienc_func_##name args \
+{ \
+ ENSURE_LIBRARY; \
+ assert (gnutls_brotlienc_sym_##name); \
+ return gnutls_brotlienc_sym_##name cargs; \
+}
+#define VOID_FUNC(ret, name, args, cargs) \
+ret gnutls_brotlienc_func_##name args \
+{ \
+ ENSURE_LIBRARY; \
+ assert (gnutls_brotlienc_sym_##name); \
+ gnutls_brotlienc_sym_##name cargs; \
+}
+#include "brotliencfuncs.h"
+#undef VOID_FUNC
+#undef FUNC
+
+#pragma GCC diagnostic pop
+
+static int
+ensure_symbol (const char *name, void **symp)
+{
+ if (!*symp)
+ {
+ void *sym = dlsym (gnutls_brotlienc_dlhandle, name);
+ if (!sym)
+ return -errno;
+ *symp = sym;
+ }
+ return 0;
+}
+
+int
+gnutls_brotlienc_ensure_library (const char *soname, int flags)
+{
+ int err;
+
+ if (!gnutls_brotlienc_dlhandle)
+ {
+ gnutls_brotlienc_dlhandle = dlopen (soname, flags);
+ if (!gnutls_brotlienc_dlhandle)
+ return -errno;
+ }
+
+#define ENSURE_SYMBOL(name) \
+ ensure_symbol(#name, (void **)&gnutls_brotlienc_sym_##name)
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+
+#define FUNC(ret, name, args, cargs) \
+ err = ENSURE_SYMBOL(name); \
+ if (err < 0) \
+ return err;
+#define VOID_FUNC FUNC
+#include "brotliencfuncs.h"
+#undef VOID_FUNC
+#undef FUNC
+
+#pragma GCC diagnostic pop
+
+#undef ENSURE_SYMBOL
+ return 0;
+}
+
+void
+gnutls_brotlienc_unload_library (void)
+{
+ if (gnutls_brotlienc_dlhandle)
+ dlclose (gnutls_brotlienc_dlhandle);
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+
+#define FUNC(ret, name, args, cargs) \
+ gnutls_brotlienc_sym_##name = NULL;
+#define VOID_FUNC FUNC
+#include "brotliencfuncs.h"
+#undef VOID_FUNC
+#undef FUNC
+
+#pragma GCC diagnostic pop
+
+#undef RESET_SYMBOL
+}
+
+#else /* GNUTLS_BROTLIENC_ENABLE_DLOPEN */
+
+int
+gnutls_brotlienc_ensure_library (const char *soname, int flags)
+{
+ (void) soname;
+ (void) flags;
+ return 0;
+}
+
+void
+gnutls_brotlienc_unload_library (void)
+{
+}
+
+#endif /* !GNUTLS_BROTLIENC_ENABLE_DLOPEN */
diff --git a/lib/dlwrap/brotlienc.h b/lib/dlwrap/brotlienc.h
new file mode 100644
index 0000000000..ed1af45e04
--- /dev/null
+++ b/lib/dlwrap/brotlienc.h
@@ -0,0 +1,47 @@
+/*
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved. This file is offered as-is,
+ * without any warranty.
+ */
+
+#ifndef GNUTLS_LIB_DLWRAP_BROTLIENC_H_
+#define GNUTLS_LIB_DLWRAP_BROTLIENC_H_
+
+#include <brotli/encode.h>
+
+#if defined(GNUTLS_BROTLIENC_ENABLE_DLOPEN) && GNUTLS_BROTLIENC_ENABLE_DLOPEN
+
+#define FUNC(ret, name, args, cargs) \
+ ret gnutls_brotlienc_func_##name args;
+#define VOID_FUNC FUNC
+#include "brotliencfuncs.h"
+#undef VOID_FUNC
+#undef FUNC
+
+#define GNUTLS_BROTLIENC_FUNC(name) gnutls_brotlienc_func_##name
+
+#else
+
+#define GNUTLS_BROTLIENC_FUNC(name) name
+
+#endif /* GNUTLS_BROTLIENC_ENABLE_DLOPEN */
+
+/* Ensure SONAME to be loaded with dlopen FLAGS, and all the necessary
+ * symbols are resolved.
+ *
+ * Returns 0 on success; negative error code otherwise.
+ *
+ * Note that this function is NOT thread-safe; when calling it from
+ * multi-threaded programs, protect it with a locking mechanism.
+ */
+int gnutls_brotlienc_ensure_library (const char *soname, int flags);
+
+/* Unload library and reset symbols.
+ *
+ * Note that this function is NOT thread-safe; when calling it from
+ * multi-threaded programs, protect it with a locking mechanism.
+ */
+void gnutls_brotlienc_unload_library (void);
+
+#endif /* GNUTLS_LIB_DLWRAP_BROTLIENC_H_ */
diff --git a/lib/dlwrap/brotliencfuncs.h b/lib/dlwrap/brotliencfuncs.h
new file mode 100644
index 0000000000..1a4f884d35
--- /dev/null
+++ b/lib/dlwrap/brotliencfuncs.h
@@ -0,0 +1,10 @@
+/*
+ * This file was automatically generated from encode.h,
+ * which is covered by the following license:
+ * Copyright 2013 Google Inc. All Rights Reserved.
+ *
+ * Distributed under MIT license.
+ * See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+ */
+FUNC(size_t, BrotliEncoderMaxCompressedSize, (size_t input_size), (input_size))
+FUNC(int, BrotliEncoderCompress, (int quality, int lgwin, BrotliEncoderMode mode, size_t input_size, const uint8_t input_buffer[], size_t *encoded_size, uint8_t encoded_buffer[]), (quality, lgwin, mode, input_size, input_buffer, encoded_size, encoded_buffer))
diff --git a/lib/dlwrap/zlib.c b/lib/dlwrap/zlib.c
new file mode 100644
index 0000000000..455485c63f
--- /dev/null
+++ b/lib/dlwrap/zlib.c
@@ -0,0 +1,182 @@
+/*
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved. This file is offered as-is,
+ * without any warranty.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "zlib.h"
+
+#if defined(GNUTLS_ZLIB_ENABLE_DLOPEN) && GNUTLS_ZLIB_ENABLE_DLOPEN
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* If Z_LIBRARY_SONAME is defined, dlopen handle can be automatically
+ * set; otherwise, the caller needs to call
+ * gnutls_zlib_ensure_library with soname determined at run time.
+ */
+#ifdef Z_LIBRARY_SONAME
+
+static void
+ensure_library (void)
+{
+ if (gnutls_zlib_ensure_library (Z_LIBRARY_SONAME, RTLD_LAZY | RTLD_LOCAL) < 0)
+ abort ();
+}
+
+#if defined(GNUTLS_ZLIB_ENABLE_PTHREAD) && GNUTLS_ZLIB_ENABLE_PTHREAD
+#include <pthread.h>
+
+static pthread_once_t dlopen_once = PTHREAD_ONCE_INIT;
+
+#define ENSURE_LIBRARY pthread_once(&dlopen_once, ensure_library)
+
+#else /* GNUTLS_ZLIB_ENABLE_PTHREAD */
+
+#define ENSURE_LIBRARY do { \
+ if (!gnutls_zlib_dlhandle) \
+ ensure_library(); \
+ } while (0)
+
+#endif /* !GNUTLS_ZLIB_ENABLE_PTHREAD */
+
+#else /* Z_LIBRARY_SONAME */
+
+#define ENSURE_LIBRARY do {} while (0)
+
+#endif /* !Z_LIBRARY_SONAME */
+
+static void *gnutls_zlib_dlhandle;
+
+/* Define redirection symbols */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+
+#if (2 <= __GNUC__ || (4 <= __clang_major__))
+#define FUNC(ret, name, args, cargs) \
+ static __typeof__(name)(*gnutls_zlib_sym_##name);
+#else
+#define FUNC(ret, name, args, cargs) \
+ static ret(*gnutls_zlib_sym_##name)args;
+#endif
+#define VOID_FUNC FUNC
+#include "zlibfuncs.h"
+#undef VOID_FUNC
+#undef FUNC
+
+#pragma GCC diagnostic pop
+
+/* Define redirection wrapper functions */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+
+#define FUNC(ret, name, args, cargs) \
+ret gnutls_zlib_func_##name args \
+{ \
+ ENSURE_LIBRARY; \
+ assert (gnutls_zlib_sym_##name); \
+ return gnutls_zlib_sym_##name cargs; \
+}
+#define VOID_FUNC(ret, name, args, cargs) \
+ret gnutls_zlib_func_##name args \
+{ \
+ ENSURE_LIBRARY; \
+ assert (gnutls_zlib_sym_##name); \
+ gnutls_zlib_sym_##name cargs; \
+}
+#include "zlibfuncs.h"
+#undef VOID_FUNC
+#undef FUNC
+
+#pragma GCC diagnostic pop
+
+static int
+ensure_symbol (const char *name, void **symp)
+{
+ if (!*symp)
+ {
+ void *sym = dlsym (gnutls_zlib_dlhandle, name);
+ if (!sym)
+ return -errno;
+ *symp = sym;
+ }
+ return 0;
+}
+
+int
+gnutls_zlib_ensure_library (const char *soname, int flags)
+{
+ int err;
+
+ if (!gnutls_zlib_dlhandle)
+ {
+ gnutls_zlib_dlhandle = dlopen (soname, flags);
+ if (!gnutls_zlib_dlhandle)
+ return -errno;
+ }
+
+#define ENSURE_SYMBOL(name) \
+ ensure_symbol(#name, (void **)&gnutls_zlib_sym_##name)
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+
+#define FUNC(ret, name, args, cargs) \
+ err = ENSURE_SYMBOL(name); \
+ if (err < 0) \
+ return err;
+#define VOID_FUNC FUNC
+#include "zlibfuncs.h"
+#undef VOID_FUNC
+#undef FUNC
+
+#pragma GCC diagnostic pop
+
+#undef ENSURE_SYMBOL
+ return 0;
+}
+
+void
+gnutls_zlib_unload_library (void)
+{
+ if (gnutls_zlib_dlhandle)
+ dlclose (gnutls_zlib_dlhandle);
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+
+#define FUNC(ret, name, args, cargs) \
+ gnutls_zlib_sym_##name = NULL;
+#define VOID_FUNC FUNC
+#include "zlibfuncs.h"
+#undef VOID_FUNC
+#undef FUNC
+
+#pragma GCC diagnostic pop
+
+#undef RESET_SYMBOL
+}
+
+#else /* GNUTLS_ZLIB_ENABLE_DLOPEN */
+
+int
+gnutls_zlib_ensure_library (const char *soname, int flags)
+{
+ (void) soname;
+ (void) flags;
+ return 0;
+}
+
+void
+gnutls_zlib_unload_library (void)
+{
+}
+
+#endif /* !GNUTLS_ZLIB_ENABLE_DLOPEN */
diff --git a/lib/dlwrap/zlib.h b/lib/dlwrap/zlib.h
new file mode 100644
index 0000000000..a9666d27f5
--- /dev/null
+++ b/lib/dlwrap/zlib.h
@@ -0,0 +1,47 @@
+/*
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved. This file is offered as-is,
+ * without any warranty.
+ */
+
+#ifndef GNUTLS_LIB_DLWRAP_ZLIB_H_
+#define GNUTLS_LIB_DLWRAP_ZLIB_H_
+
+#include <zlib.h>
+
+#if defined(GNUTLS_ZLIB_ENABLE_DLOPEN) && GNUTLS_ZLIB_ENABLE_DLOPEN
+
+#define FUNC(ret, name, args, cargs) \
+ ret gnutls_zlib_func_##name args;
+#define VOID_FUNC FUNC
+#include "zlibfuncs.h"
+#undef VOID_FUNC
+#undef FUNC
+
+#define GNUTLS_ZLIB_FUNC(name) gnutls_zlib_func_##name
+
+#else
+
+#define GNUTLS_ZLIB_FUNC(name) name
+
+#endif /* GNUTLS_ZLIB_ENABLE_DLOPEN */
+
+/* Ensure SONAME to be loaded with dlopen FLAGS, and all the necessary
+ * symbols are resolved.
+ *
+ * Returns 0 on success; negative error code otherwise.
+ *
+ * Note that this function is NOT thread-safe; when calling it from
+ * multi-threaded programs, protect it with a locking mechanism.
+ */
+int gnutls_zlib_ensure_library (const char *soname, int flags);
+
+/* Unload library and reset symbols.
+ *
+ * Note that this function is NOT thread-safe; when calling it from
+ * multi-threaded programs, protect it with a locking mechanism.
+ */
+void gnutls_zlib_unload_library (void);
+
+#endif /* GNUTLS_LIB_DLWRAP_ZLIB_H_ */
diff --git a/lib/dlwrap/zlibfuncs.h b/lib/dlwrap/zlibfuncs.h
new file mode 100644
index 0000000000..efe01455d2
--- /dev/null
+++ b/lib/dlwrap/zlibfuncs.h
@@ -0,0 +1,27 @@
+/*
+ * This file was automatically generated from zlib.h,
+ * which is covered by the following license:
+ * Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * Jean-loup Gailly Mark Adler
+ * jloup@gzip.org madler@alumni.caltech.edu
+ */
+FUNC(int, compress, (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen), (dest, destLen, source, sourceLen))
+FUNC(uLong, compressBound, (uLong sourceLen), (sourceLen))
+FUNC(int, uncompress, (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen), (dest, destLen, source, sourceLen))
diff --git a/lib/dlwrap/zstd.c b/lib/dlwrap/zstd.c
new file mode 100644
index 0000000000..2ea7252975
--- /dev/null
+++ b/lib/dlwrap/zstd.c
@@ -0,0 +1,182 @@
+/*
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved. This file is offered as-is,
+ * without any warranty.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "zstd.h"
+
+#if defined(GNUTLS_ZSTD_ENABLE_DLOPEN) && GNUTLS_ZSTD_ENABLE_DLOPEN
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* If ZSTD_LIBRARY_SONAME is defined, dlopen handle can be automatically
+ * set; otherwise, the caller needs to call
+ * gnutls_zstd_ensure_library with soname determined at run time.
+ */
+#ifdef ZSTD_LIBRARY_SONAME
+
+static void
+ensure_library (void)
+{
+ if (gnutls_zstd_ensure_library (ZSTD_LIBRARY_SONAME, RTLD_LAZY | RTLD_LOCAL) < 0)
+ abort ();
+}
+
+#if defined(GNUTLS_ZSTD_ENABLE_PTHREAD) && GNUTLS_ZSTD_ENABLE_PTHREAD
+#include <pthread.h>
+
+static pthread_once_t dlopen_once = PTHREAD_ONCE_INIT;
+
+#define ENSURE_LIBRARY pthread_once(&dlopen_once, ensure_library)
+
+#else /* GNUTLS_ZSTD_ENABLE_PTHREAD */
+
+#define ENSURE_LIBRARY do { \
+ if (!gnutls_zstd_dlhandle) \
+ ensure_library(); \
+ } while (0)
+
+#endif /* !GNUTLS_ZSTD_ENABLE_PTHREAD */
+
+#else /* ZSTD_LIBRARY_SONAME */
+
+#define ENSURE_LIBRARY do {} while (0)
+
+#endif /* !ZSTD_LIBRARY_SONAME */
+
+static void *gnutls_zstd_dlhandle;
+
+/* Define redirection symbols */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+
+#if (2 <= __GNUC__ || (4 <= __clang_major__))
+#define FUNC(ret, name, args, cargs) \
+ static __typeof__(name)(*gnutls_zstd_sym_##name);
+#else
+#define FUNC(ret, name, args, cargs) \
+ static ret(*gnutls_zstd_sym_##name)args;
+#endif
+#define VOID_FUNC FUNC
+#include "zstdfuncs.h"
+#undef VOID_FUNC
+#undef FUNC
+
+#pragma GCC diagnostic pop
+
+/* Define redirection wrapper functions */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+
+#define FUNC(ret, name, args, cargs) \
+ret gnutls_zstd_func_##name args \
+{ \
+ ENSURE_LIBRARY; \
+ assert (gnutls_zstd_sym_##name); \
+ return gnutls_zstd_sym_##name cargs; \
+}
+#define VOID_FUNC(ret, name, args, cargs) \
+ret gnutls_zstd_func_##name args \
+{ \
+ ENSURE_LIBRARY; \
+ assert (gnutls_zstd_sym_##name); \
+ gnutls_zstd_sym_##name cargs; \
+}
+#include "zstdfuncs.h"
+#undef VOID_FUNC
+#undef FUNC
+
+#pragma GCC diagnostic pop
+
+static int
+ensure_symbol (const char *name, void **symp)
+{
+ if (!*symp)
+ {
+ void *sym = dlsym (gnutls_zstd_dlhandle, name);
+ if (!sym)
+ return -errno;
+ *symp = sym;
+ }
+ return 0;
+}
+
+int
+gnutls_zstd_ensure_library (const char *soname, int flags)
+{
+ int err;
+
+ if (!gnutls_zstd_dlhandle)
+ {
+ gnutls_zstd_dlhandle = dlopen (soname, flags);
+ if (!gnutls_zstd_dlhandle)
+ return -errno;
+ }
+
+#define ENSURE_SYMBOL(name) \
+ ensure_symbol(#name, (void **)&gnutls_zstd_sym_##name)
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+
+#define FUNC(ret, name, args, cargs) \
+ err = ENSURE_SYMBOL(name); \
+ if (err < 0) \
+ return err;
+#define VOID_FUNC FUNC
+#include "zstdfuncs.h"
+#undef VOID_FUNC
+#undef FUNC
+
+#pragma GCC diagnostic pop
+
+#undef ENSURE_SYMBOL
+ return 0;
+}
+
+void
+gnutls_zstd_unload_library (void)
+{
+ if (gnutls_zstd_dlhandle)
+ dlclose (gnutls_zstd_dlhandle);
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+
+#define FUNC(ret, name, args, cargs) \
+ gnutls_zstd_sym_##name = NULL;
+#define VOID_FUNC FUNC
+#include "zstdfuncs.h"
+#undef VOID_FUNC
+#undef FUNC
+
+#pragma GCC diagnostic pop
+
+#undef RESET_SYMBOL
+}
+
+#else /* GNUTLS_ZSTD_ENABLE_DLOPEN */
+
+int
+gnutls_zstd_ensure_library (const char *soname, int flags)
+{
+ (void) soname;
+ (void) flags;
+ return 0;
+}
+
+void
+gnutls_zstd_unload_library (void)
+{
+}
+
+#endif /* !GNUTLS_ZSTD_ENABLE_DLOPEN */
diff --git a/lib/dlwrap/zstd.h b/lib/dlwrap/zstd.h
new file mode 100644
index 0000000000..80ac2fbd46
--- /dev/null
+++ b/lib/dlwrap/zstd.h
@@ -0,0 +1,47 @@
+/*
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved. This file is offered as-is,
+ * without any warranty.
+ */
+
+#ifndef GNUTLS_LIB_DLWRAP_ZSTD_H_
+#define GNUTLS_LIB_DLWRAP_ZSTD_H_
+
+#include <zstd.h>
+
+#if defined(GNUTLS_ZSTD_ENABLE_DLOPEN) && GNUTLS_ZSTD_ENABLE_DLOPEN
+
+#define FUNC(ret, name, args, cargs) \
+ ret gnutls_zstd_func_##name args;
+#define VOID_FUNC FUNC
+#include "zstdfuncs.h"
+#undef VOID_FUNC
+#undef FUNC
+
+#define GNUTLS_ZSTD_FUNC(name) gnutls_zstd_func_##name
+
+#else
+
+#define GNUTLS_ZSTD_FUNC(name) name
+
+#endif /* GNUTLS_ZSTD_ENABLE_DLOPEN */
+
+/* Ensure SONAME to be loaded with dlopen FLAGS, and all the necessary
+ * symbols are resolved.
+ *
+ * Returns 0 on success; negative error code otherwise.
+ *
+ * Note that this function is NOT thread-safe; when calling it from
+ * multi-threaded programs, protect it with a locking mechanism.
+ */
+int gnutls_zstd_ensure_library (const char *soname, int flags);
+
+/* Unload library and reset symbols.
+ *
+ * Note that this function is NOT thread-safe; when calling it from
+ * multi-threaded programs, protect it with a locking mechanism.
+ */
+void gnutls_zstd_unload_library (void);
+
+#endif /* GNUTLS_LIB_DLWRAP_ZSTD_H_ */
diff --git a/lib/dlwrap/zstdfuncs.h b/lib/dlwrap/zstdfuncs.h
new file mode 100644
index 0000000000..8e3eb9ff59
--- /dev/null
+++ b/lib/dlwrap/zstdfuncs.h
@@ -0,0 +1,15 @@
+/*
+ * This file was automatically generated from zstd.h,
+ * which is covered by the following license:
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+FUNC(size_t, ZSTD_compress, (void *dst, size_t dstCapacity, const void *src, size_t srcSize, int compressionLevel), (dst, dstCapacity, src, srcSize, compressionLevel))
+FUNC(size_t, ZSTD_decompress, (void *dst, size_t dstCapacity, const void *src, size_t compressedSize), (dst, dstCapacity, src, compressedSize))
+FUNC(size_t, ZSTD_compressBound, (size_t srcSize), (srcSize))
+FUNC(unsigned int, ZSTD_isError, (size_t code), (code))
--
2.45.2