diff --git a/CMakeLists.txt b/CMakeLists.txt index 41817d8c..b4213178 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -164,6 +164,8 @@ option(BUILD_LIBEV "Build libev support library if available." ON) option(BUILD_LIBEVENT2 "Build libevent2 support library if available." ON) option(BUILD_LIBUV "Build libuv support library available." ON) +option(BUILD_DOH "Build DNS-over-HTTPS support if libnghttp2 library is available." ON) + option(USE_LIBIDN2 "Use libidn2 if available." ON) option(USE_GNUTLS "Use GnuTLS for TLS connections." OFF) @@ -193,6 +195,7 @@ set(STUB_NATIVE_DNSSEC ${ENABLE_NATIVE_STUB_DNSSEC}) set(USE_LIBEV ${BUILD_LIBEV}) set(USE_LIBEVENT2 ${BUILD_LIBEVENT2}) set(USE_LIBUV ${BUILD_LIBUV}) +set(USE_DOH ${BUILD_DOH}) option(ENABLE_DEBUG_KEEP_CONNECTIONS_OPEN "Disable connection idle timeout. Do not enable.") mark_as_advanced(ENABLE_DEBUG_KEEP_CONNECTIONS_OPEN) @@ -409,6 +412,17 @@ if (USE_LIBIDN2) endif() endif() +# DNS-over-HTTPS support +if (USE_DOH) + find_package(Libnghttp2) + if (Libnghttp2_FOUND) + set(HAVE_LIBNGHTTP2 1) + else() + message(WARNING "DNS-over-HTTPS support build requested, but libnghttp2 not found. Disabled.") + unset(USE_DOH) + endif() +endif () + # GnuTLS and Nettle. If using GnuTLS, we need the Nettle dev stuff to # handle digital signature algorithms. GnuTLS uses Nettle internally. if (USE_GNUTLS) @@ -697,6 +711,9 @@ endif () if (GnuTLS_FOUND) target_include_directories(getdns_objects PRIVATE ${GNUTLS_INCLUDE_DIR}) endif () +if (Libnghttp2_FOUND) + target_include_directories(getdns_objects PRIVATE ${LIBNGHTTP2_INCLUDE_DIR}) +endif () # Don't compile separate objects for shared and static libraries. # Yes, -fPIC is slightly suboptimal for static libraries, but it looks @@ -730,6 +747,9 @@ if (ENABLE_STATIC) if (Nettle_FOUND) target_link_libraries(getdns PUBLIC Nettle::Nettle Nettle::Hogweed) endif () + if (Libnghttp2_FOUND) + target_link_libraries(getdns PUBLIC Libnghttp2::Libnghttp2) + endif () set_target_properties(getdns PROPERTIES OUTPUT_NAME getdns${static_lib_suffix}) endif () @@ -759,6 +779,9 @@ if (ENABLE_SHARED) if (Nettle_FOUND) target_link_libraries(getdns_shared PUBLIC Nettle::Nettle Nettle::Hogweed) endif () + if (Libnghttp2_FOUND) + target_link_libraries(getdns_shared PUBLIC Libnghttp2::Libnghttp2) + endif () set_target_properties(getdns_shared PROPERTIES OUTPUT_NAME getdns) target_shared_library_version(getdns_shared ${GETDNS_VERSION_CURRENT} ${GETDNS_VERSION_REVISION} ${GETDNS_VERSION_AGE}) diff --git a/cmake/include/cmakeconfig.h.in b/cmake/include/cmakeconfig.h.in index 4d5e259b..569c4172 100644 --- a/cmake/include/cmakeconfig.h.in +++ b/cmake/include/cmakeconfig.h.in @@ -188,6 +188,8 @@ #cmakedefine HAVE_NETTLE_DSA_COMPAT_H 1 #cmakedefine HAVE_NETTLE_EDDSA_H 1 +#cmakedefine HAVE_LIBNGHTTP2 1 + #cmakedefine HAVE_EVENT2_EVENT_H 1 #cmakedefine HAVE_EVENT_BASE_NEW 1 #cmakedefine HAVE_EVENT_BASE_FREE 1 diff --git a/cmake/modules/FindLibnghttp2.cmake b/cmake/modules/FindLibnghttp2.cmake new file mode 100644 index 00000000..c24ebfce --- /dev/null +++ b/cmake/modules/FindLibnghttp2.cmake @@ -0,0 +1,86 @@ +#[=======================================================================[.rst: +FindLibnghttp2 +----------- + +Find the Libnghttp2 library + +Imported targets +^^^^^^^^^^^^^^^^ + +This module defines the following :prop_tgt:`IMPORTED` targets: + +``Libnghttp2::Libnghttp2`` + The Libnghttp2 library, if found. + +Result variables +^^^^^^^^^^^^^^^^ + +This module will set the following variables in your project: + +``Libnghttp2_FOUND`` + If false, do not try to use Libnghttp2. +``LIBNGHTTP2_INCLUDE_DIR`` + where to find libnghttp2 headers. +``LIBNGHTTP2_LIBRARIES`` + the libraries needed to use Libnghttp2. +``LIBNGHTTP2_VERSION`` + the version of the Libnghttp2 library found + +#]=======================================================================] + +find_package(PkgConfig QUIET) +if (PKG_CONFIG_FOUND) + pkg_check_modules(PkgLibNghttp2 IMPORTED_TARGET GLOBAL libnghttp2) +endif () + +if (PkgLibNghttp2_FOUND) + set(LIBNGHTTP2_INCLUDE_DIR ${PkgLibNghttp2_INCLUDE_DIRS} CACHE FILEPATH "libnghttp2 include path") + set(LIBNGHTTP2_LIBRARIES ${PkgLibNghttp2_LIBRARIES} CACHE STRING "libnghttp2 libraries") + set(LIBNGHTTP2_VERSION ${PkgLibNghttp2_VERSION}) + add_library(Libnghttp2::Libnghttp2 ALIAS PkgConfig::PkgLibNghttp2) + if (NOT TARGET Libnghttp2::Libnghttp2) + message(STATUS "No Libnghttp2::Libnghttp2 target") + add_library(Libnghttp2::Libnghttp2 UNKNOWN IMPORTED) + set_target_properties(Libnghttp2::Libnghttp2 PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${LIBNGHTTP2_INCLUDE_DIR}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${LIBNGHTTP2_LIBRARIES}" + ) + endif () + set(Libnghttp2_FOUND ON) +else () + find_path(LIBNGHTTP2_INCLUDE_DIR nghttp2/nghttp2.h + HINTS + "${LIBNGHTTP2_DIR}" + "${LIBNGHTTP2_DIR}/include" + ) + + find_library(LIBNGHTTP2_LIBRARIES NAMES nghttp2 libnghttp2 + HINTS + "${LIBNGHTTP2_DIR}" + "${LIBNGHTTP2_DIR}/lib" + ) + + if (LIBNGHTTP2_INCLUDE_DIR AND LIBNGHTTP2_LIBRARIES) + if (NOT TARGET Libnghttp2::Libnghttp2) + add_library(Libnghttp2::Libnghttp2 UNKNOWN IMPORTED) + set_target_properties(Libnghttp2::Libnghttp2 PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${LIBNGHTTP2_INCLUDE_DIR}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${LIBNGHTTP2_LIBRARIES}" + ) + endif () + + if (NOT LIBNGHTTP2_VERSION AND LIBNGHTTP2_INCLUDE_DIR AND EXISTS "${LIBNGHTTP2_INCLUDE_DIR}/nghttp2/nghttp2.h") + file(STRINGS "${LIBNGHTTP2_INCLUDE_DIR}/nghttp2/nghttp2.h" LIBNGHTTP2_H REGEX "^[ \t]*#[ \t]*define[ \t]+NGHTTP2_VERSION[ \t]") + string(REGEX REPLACE "^.*NGHTTP2_VERSION[ \t]+\"([0-9.]+)\".*$" "\\1" LIBNGHTTP2_VERSION "${LIBNGHTTP2_H}") + endif () + endif () + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(Libnghttp2 + REQUIRED_VARS LIBNGHTTP2_LIBRARIES LIBNGHTTP2_INCLUDE_DIR + VERSION_VAR LIBNGHTTP2_VERSION + ) +endif () + +mark_as_advanced(LIBNGHTTP2_INCLUDE_DIR LIBNGHTTP2_LIBRARIES) diff --git a/src/context.c b/src/context.c index ef8b26dc..ee65bbe8 100644 --- a/src/context.c +++ b/src/context.c @@ -70,6 +70,9 @@ typedef unsigned short in_port_t; #ifdef HAVE_LIBUNBOUND #include #endif +#ifdef HAVE_LIBNGHTTP2 +#include +#endif #include "debug.h" #include "gldns/str2wire.h" #include "gldns/wire2str.h" @@ -4993,6 +4996,17 @@ getdns_context_get_api_information(const getdns_context* context) && ! _getdns_tls_get_api_information(result) +#ifdef HAVE_LIBNGHTTP2 + && ! getdns_dict_set_int( + result, "nghttp2_version_number", nghttp2_version(0)->version_num) + + && ! getdns_dict_util_set_string( + result, "nghttp2_version_string", nghttp2_version(0)->version_str) + + && ! getdns_dict_util_set_string( + result, "nghttp2_protocol_string", nghttp2_version(0)->proto_str) +#endif + && ! getdns_dict_set_int( result, "resolution_type", context->resolution_type) @@ -5689,6 +5703,9 @@ _getdns_context_config_setting(getdns_context *context, && !_streq(setting, "openssl_platform") && !_streq(setting, "openssl_dir") && !_streq(setting, "openssl_engines_dir") + && !_streq(setting, "nghttp2_version_number") + && !_streq(setting, "nghttp2_version_string") + && !_streq(setting, "nghttp2_protocol_string") ) { r = GETDNS_RETURN_NOT_IMPLEMENTED; }