- Add DNS-over-HTTPS support

This commit is contained in:
Ralph Dolmans 2020-05-07 16:36:26 +02:00
parent ce7fd591c6
commit 8dae5d9f81
26 changed files with 6188 additions and 4564 deletions

View file

@ -663,7 +663,7 @@ dns.lo dns.o: $(srcdir)/services/cache/dns.c config.h $(srcdir)/iterator/iter_de
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
$(srcdir)/validator/val_utils.h $(srcdir)/sldns/pkthdr.h $(srcdir)/services/cache/dns.h \
$(srcdir)/util/data/msgreply.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
$(srcdir)/util/data/dname.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/rrdef.h \
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/dname.h $(srcdir)/util/module.h \
$(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h
infra.lo infra.o: $(srcdir)/services/cache/infra.c config.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h \
$(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/services/cache/infra.h \
@ -704,10 +704,11 @@ msgreply.lo msgreply.o: $(srcdir)/util/data/msgreply.c config.h $(srcdir)/util/d
$(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/util/config_file.h \
$(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \
$(srcdir)/respip/respip.h
packed_rrset.lo packed_rrset.o: $(srcdir)/util/data/packed_rrset.c config.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/alloc.h $(srcdir)/util/regional.h \
$(srcdir)/util/net_help.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h
packed_rrset.lo packed_rrset.o: $(srcdir)/util/data/packed_rrset.c config.h $(srcdir)/util/data/msgparse.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/sldns/pkthdr.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/dname.h \
$(srcdir)/util/storage/lookup3.h $(srcdir)/util/alloc.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h \
$(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h
iterator.lo iterator.o: $(srcdir)/iterator/iterator.c config.h $(srcdir)/iterator/iterator.h \
$(srcdir)/services/outbound_list.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/module.h \
@ -776,7 +777,7 @@ listen_dnsport.lo listen_dnsport.o: $(srcdir)/services/listen_dnsport.c config.h
$(srcdir)/services/listen_dnsport.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
$(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/log.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \
$(srcdir)/sldns/sbuffer.h $(srcdir)/services/mesh.h $(srcdir)/util/data/msgparse.h \
$(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/parseutil.h $(srcdir)/services/mesh.h $(srcdir)/util/data/msgparse.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
$(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
@ -799,10 +800,10 @@ mesh.lo mesh.o: $(srcdir)/services/mesh.c config.h $(srcdir)/services/mesh.h $(s
$(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h \
$(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h \
$(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h \
$(srcdir)/services/outbound_list.h $(srcdir)/services/cache/dns.h $(srcdir)/util/net_help.h \
$(srcdir)/util/regional.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h \
$(srcdir)/util/alloc.h $(srcdir)/util/edns.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/data/dname.h \
$(srcdir)/services/listen_dnsport.h
$(srcdir)/services/outbound_list.h $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/rrset.h \
$(srcdir)/util/storage/slabhash.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h \
$(srcdir)/util/data/msgencode.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/alloc.h \
$(srcdir)/util/edns.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/data/dname.h $(srcdir)/services/listen_dnsport.h
modstack.lo modstack.o: $(srcdir)/services/modstack.c config.h $(srcdir)/services/modstack.h \
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
@ -903,7 +904,7 @@ fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/
$(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
$(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \
$(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
$(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
$(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/mini_event.h \
$(srcdir)/services/outside_network.h $(srcdir)/services/cache/infra.h \
$(srcdir)/util/rtt.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/dns64/dns64.h \
$(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h \
@ -914,15 +915,7 @@ fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/
$(srcdir)/libunbound/worker.h
locks.lo locks.o: $(srcdir)/util/locks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h
log.lo log.o: $(srcdir)/util/log.c config.h $(srcdir)/util/log.h $(srcdir)/util/locks.h $(srcdir)/sldns/sbuffer.h
mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
$(srcdir)/util/log.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
$(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h \
$(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h \
$(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h \
$(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h
mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h
module.lo module.o: $(srcdir)/util/module.c config.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h \
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h
@ -994,7 +987,7 @@ tube.lo tube.o: $(srcdir)/util/tube.c config.h $(srcdir)/util/tube.h $(srcdir)/u
$(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/ub_event.h
ub_event.lo ub_event.o: $(srcdir)/util/ub_event.c config.h $(srcdir)/util/ub_event.h $(srcdir)/util/log.h \
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
$(srcdir)/util/tube.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
$(srcdir)/util/tube.h
ub_event_pluggable.lo ub_event_pluggable.o: $(srcdir)/util/ub_event_pluggable.c config.h $(srcdir)/util/ub_event.h \
$(srcdir)/libunbound/unbound-event.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
$(srcdir)/util/log.h $(srcdir)/util/fptr_wlist.h \
@ -1004,7 +997,7 @@ ub_event_pluggable.lo ub_event_pluggable.o: $(srcdir)/util/ub_event_pluggable.c
$(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
$(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \
$(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
$(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
$(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h
winsock_event.lo winsock_event.o: $(srcdir)/util/winsock_event.c config.h
autotrust.lo autotrust.o: $(srcdir)/validator/autotrust.c config.h $(srcdir)/validator/autotrust.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
@ -1273,7 +1266,8 @@ worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(sr
$(srcdir)/util/data/dname.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/edns.h \
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/validator/autotrust.h \
$(srcdir)/validator/val_anchor.h $(srcdir)/libunbound/context.h $(srcdir)/libunbound/unbound-event.h \
$(srcdir)/libunbound/libworker.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/shm_side/shm_main.h
$(srcdir)/libunbound/libworker.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/shm_side/shm_main.h \
$(srcdir)/dnstap/dtstream.h
testbound.lo testbound.o: $(srcdir)/testcode/testbound.c config.h $(srcdir)/testcode/testpkts.h \
$(srcdir)/testcode/replay.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
$(srcdir)/util/rbtree.h $(srcdir)/testcode/fake_event.h \
@ -1307,7 +1301,8 @@ worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(sr
$(srcdir)/util/data/dname.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/edns.h \
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/validator/autotrust.h \
$(srcdir)/validator/val_anchor.h $(srcdir)/libunbound/context.h $(srcdir)/libunbound/unbound-event.h \
$(srcdir)/libunbound/libworker.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/shm_side/shm_main.h
$(srcdir)/libunbound/libworker.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/shm_side/shm_main.h \
$(srcdir)/dnstap/dtstream.h
acl_list.lo acl_list.o: $(srcdir)/daemon/acl_list.c config.h $(srcdir)/daemon/acl_list.h \
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/locks.h \
$(srcdir)/util/log.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \
@ -1470,6 +1465,12 @@ unbound-control.lo unbound-control.o: $(srcdir)/smallapp/unbound-control.c confi
unbound-anchor.lo unbound-anchor.o: $(srcdir)/smallapp/unbound-anchor.c config.h $(srcdir)/libunbound/unbound.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/parseutil.h
petal.lo petal.o: $(srcdir)/testcode/petal.c config.h
unbound-dnstap-socket.lo unbound-dnstap-socket.o: $(srcdir)/dnstap/unbound-dnstap-socket.c config.h \
$(srcdir)/dnstap/dtstream.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/dnstap/dnstap_fstrm.h \
$(srcdir)/util/ub_event.h $(srcdir)/util/net_help.h $(srcdir)/services/listen_dnsport.h \
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
$(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/config_file.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h
pythonmod_utils.lo pythonmod_utils.o: $(srcdir)/pythonmod/pythonmod_utils.c config.h $(srcdir)/util/module.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \

View file

@ -28,6 +28,9 @@
/* Whether daemon is deprecated */
#undef DEPRECATED_DAEMON
/* Define this to enable kernel based UDP source port randomization. */
#undef DISABLE_EXPLICIT_PORT_RANDOMISATION
/* default dnstap socket path */
#undef DNSTAP_SOCKET_PATH
@ -110,6 +113,10 @@
don't. */
#undef HAVE_DECL_INET_PTON
/* Define to 1 if you have the declaration of `nghttp2_session_server_new',
and to 0 if you don't. */
#undef HAVE_DECL_NGHTTP2_SESSION_SERVER_NEW
/* Define to 1 if you have the declaration of `NID_ED25519', and to 0 if you
don't. */
#undef HAVE_DECL_NID_ED25519
@ -368,6 +375,12 @@
/* Define to 1 if you have the <nettle/eddsa.h> header file. */
#undef HAVE_NETTLE_EDDSA_H
/* Define this to use nghttp2 client. */
#undef HAVE_NGHTTP2
/* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */
#undef HAVE_NGHTTP2_NGHTTP2_H
/* Use libnss for crypto */
#undef HAVE_NSS
@ -491,6 +504,9 @@
/* Define if you have the SSL libraries installed. */
#undef HAVE_SSL
/* Define to 1 if you have the `SSL_CTX_set_alpn_select_cb' function. */
#undef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
/* Define to 1 if you have the `SSL_CTX_set_ciphersuites' function. */
#undef HAVE_SSL_CTX_SET_CIPHERSUITES
@ -811,9 +827,8 @@
/* Define to 1 to use ipset support */
#undef USE_IPSET
/* Define to 1 to disable explict UDP source port randomisation and rely on the
kernel to provide random source ports */
#undef DISABLE_EXPLICIT_PORT_RANDOMISATION
/* Define if you enable libevent */
#undef USE_LIBEVENT
/* Define if you want to use internal select based events */
#undef USE_MINI_EVENT
@ -1349,6 +1364,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
#define UNBOUND_DNS_PORT 53
/** default port for DNS over TLS traffic. */
#define UNBOUND_DNS_OVER_TLS_PORT 853
/** default port for DNS over HTTPS traffic. */
#define UNBOUND_DNS_OVER_HTTPS_PORT 443
/** default port for unbound control traffic, registered port with IANA,
ub-dns-control 8953/tcp unbound dns nameserver control */
#define UNBOUND_CONTROL_PORT 8953

123
configure vendored
View file

@ -804,6 +804,7 @@ infodir
docdir
oldincludedir
includedir
runstatedir
localstatedir
sharedstatedir
sysconfdir
@ -877,6 +878,7 @@ enable_tfo_server
with_libevent
with_libexpat
with_libhiredis
with_libnghttp2
enable_static_exe
enable_fully_static
enable_lock_checks
@ -951,6 +953,7 @@ datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@ -1203,6 +1206,15 @@ do
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
-runstatedir | --runstatedir | --runstatedi | --runstated \
| --runstate | --runstat | --runsta | --runst | --runs \
| --run | --ru | --r)
ac_prev=runstatedir ;;
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
| --run=* | --ru=* | --r=*)
runstatedir=$ac_optarg ;;
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@ -1340,7 +1352,7 @@ fi
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
libdir localedir mandir
libdir localedir mandir runstatedir
do
eval ac_val=\$$ac_var
# Remove trailing slashes.
@ -1493,6 +1505,7 @@ Fine tuning of the installation directories:
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
@ -1635,6 +1648,7 @@ Optional Packages:
outgoing port ranges.
--with-libexpat=path specify explicit path for libexpat.
--with-libhiredis=path specify explicit path for libhiredis.
--with-libnghttp2=path specify explicit path for libnghttp2.
--with-dnstap-socket-path=pathname
set default dnstap socket path
--with-protobuf-c=path Path where protobuf-c is installed, for dnstap
@ -15666,7 +15680,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
@ -15712,7 +15726,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
@ -15736,7 +15750,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
@ -15781,7 +15795,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
@ -15805,7 +15819,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
@ -18306,7 +18320,7 @@ done
# these check_funcs need -lssl
BAKLIBS="$LIBS"
LIBS="-lssl $LIBS"
for ac_func in OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername X509_VERIFY_PARAM_set1_host SSL_CTX_set_ciphersuites
for ac_func in OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername X509_VERIFY_PARAM_set1_host SSL_CTX_set_ciphersuites SSL_CTX_set_alpn_select_cb
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@ -19124,31 +19138,34 @@ esac
if test "${with_libevent+set}" = set; then :
withval=$with_libevent;
else
withval="no"
with_libevent="no"
fi
if test x_$withval = x_yes -o x_$withval != x_no; then
if test "x_$with_libevent" != x_no; then
$as_echo "#define USE_LIBEVENT 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libevent" >&5
$as_echo_n "checking for libevent... " >&6; }
if test x_$withval = x_ -o x_$withval = x_yes; then
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
if test "x_$with_libevent" = x_ -o "x_$with_libevent" = x_yes; then
with_libevent="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
fi
for dir in $withval; do
for dir in $with_libevent; do
thedir="$dir"
if test -f "$dir/include/event.h" -o -f "$dir/include/event2/event.h"; then
found_libevent="yes"
if test "$thedir" != "/usr"; then
CPPFLAGS="$CPPFLAGS -I$thedir/include"
fi
break;
fi
if test "$thedir" != "/usr"; then
CPPFLAGS="$CPPFLAGS -I$thedir/include"
fi
break;
fi
done
if test x_$found_libevent != x_yes; then
if test -f "$dir/event.h" -a \( -f "$dir/libevent.la" -o -f "$dir/libev.la" \) ; then
# libevent source directory
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $thedir" >&5
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $thedir" >&5
$as_echo "found in $thedir" >&6; }
CPPFLAGS="$CPPFLAGS -I$thedir -I$thedir/include"
CPPFLAGS="$CPPFLAGS -I$thedir -I$thedir/include"
BAK_LDFLAGS_SET="1"
BAK_LDFLAGS="$LDFLAGS"
# remove evdns from linking
@ -19161,10 +19178,10 @@ $as_echo "found in $thedir" >&6; }
cp $ev_files_o build/libevent
cp $ev_files_lo build/libevent
cp $ev_files_libso build/libevent/.libs
LATE_LDFLAGS="build/libevent/*.lo -lm"
LATE_LDFLAGS="build/libevent/*.lo -lm"
LDFLAGS="build/libevent/*.o $LDFLAGS -lm"
else
as_fn_error $? "Cannot find the libevent library in $withval
as_fn_error $? "Cannot find the libevent library in $with_libevent
You can restart ./configure --with-libevent=no to use a builtin alternative.
Please note that this alternative is not as capable as libevent when using
large outgoing port ranges. " "$LINENO" 5
@ -19615,6 +19632,70 @@ _ACEOF
fi
# nghttp2
# Check whether --with-libnghttp2 was given.
if test "${with_libnghttp2+set}" = set; then :
withval=$with_libnghttp2;
else
withval="no"
fi
found_libnghttp2="no"
if test x_$withval = x_yes -o x_$withval != x_no; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libnghttp2" >&5
$as_echo_n "checking for libnghttp2... " >&6; }
if test x_$withval = x_ -o x_$withval = x_yes; then
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
fi
for dir in $withval ; do
if test -f "$dir/include/nghttp2/nghttp2.h"; then
found_libnghttp2="yes"
if test "$dir" != "/usr"; then
CPPFLAGS="$CPPFLAGS -I$dir/include"
LDFLAGS="$LDFLAGS -L$dir/lib"
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $dir" >&5
$as_echo "found in $dir" >&6; }
$as_echo "#define HAVE_NGHTTP2 1" >>confdefs.h
LIBS="$LIBS -lnghttp2"
break;
fi
done
if test x_$found_libnghttp2 != x_yes; then
as_fn_error $? "Could not find libnghttp2, nghttp2.h" "$LINENO" 5
fi
for ac_header in nghttp2/nghttp2.h
do :
ac_fn_c_check_header_compile "$LINENO" "nghttp2/nghttp2.h" "ac_cv_header_nghttp2_nghttp2_h" "$ac_includes_default
"
if test "x$ac_cv_header_nghttp2_nghttp2_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_NGHTTP2_NGHTTP2_H 1
_ACEOF
fi
done
ac_fn_c_check_decl "$LINENO" "nghttp2_session_server_new" "ac_cv_have_decl_nghttp2_session_server_new" "$ac_includes_default
#include <nghttp2/nghttp2.h>
"
if test "x$ac_cv_have_decl_nghttp2_session_server_new" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_NGHTTP2_SESSION_SERVER_NEW $ac_have_decl
_ACEOF
fi
# set static linking for uninstalled libraries if requested
staticexe=""

View file

@ -830,7 +830,7 @@ AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_C
# these check_funcs need -lssl
BAKLIBS="$LIBS"
LIBS="-lssl $LIBS"
AC_CHECK_FUNCS([OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername X509_VERIFY_PARAM_set1_host SSL_CTX_set_ciphersuites])
AC_CHECK_FUNCS([OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername X509_VERIFY_PARAM_set1_host SSL_CTX_set_ciphersuites SSL_CTX_set_alpn_select_cb])
LIBS="$BAKLIBS"
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [
@ -1369,6 +1369,39 @@ if test x_$withval = x_yes -o x_$withval != x_no; then
])
fi
# nghttp2
AC_ARG_WITH(libnghttp2, AC_HELP_STRING([--with-libnghttp2=path],
[specify explicit path for libnghttp2.]),
[ ],[ withval="no" ])
found_libnghttp2="no"
if test x_$withval = x_yes -o x_$withval != x_no; then
AC_MSG_CHECKING(for libnghttp2)
if test x_$withval = x_ -o x_$withval = x_yes; then
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
fi
for dir in $withval ; do
if test -f "$dir/include/nghttp2/nghttp2.h"; then
found_libnghttp2="yes"
dnl assume /usr is in default path.
if test "$dir" != "/usr"; then
CPPFLAGS="$CPPFLAGS -I$dir/include"
LDFLAGS="$LDFLAGS -L$dir/lib"
fi
AC_MSG_RESULT(found in $dir)
AC_DEFINE([HAVE_NGHTTP2], [1], [Define this to use nghttp2 client.])
LIBS="$LIBS -lnghttp2"
break;
fi
done
if test x_$found_libnghttp2 != x_yes; then
AC_ERROR([Could not find libnghttp2, nghttp2.h])
fi
AC_CHECK_HEADERS([nghttp2/nghttp2.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_DECLS([nghttp2_session_server_new], [], [], [AC_INCLUDES_DEFAULT
#include <nghttp2/nghttp2.h>
])
fi
# set static linking for uninstalled libraries if requested
AC_SUBST(staticexe)
staticexe=""
@ -2105,6 +2138,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
#define UNBOUND_DNS_PORT 53
/** default port for DNS over TLS traffic. */
#define UNBOUND_DNS_OVER_TLS_PORT 853
/** default port for DNS over HTTPS traffic. */
#define UNBOUND_DNS_OVER_HTTPS_PORT 443
/** default port for unbound control traffic, registered port with IANA,
ub-dns-control 8953/tcp unbound dns nameserver control */
#define UNBOUND_CONTROL_PORT 8953

View file

@ -329,7 +329,7 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
/* open fd */
fd = create_tcp_accept_sock(res, 1, &noproto, 0,
cfg->ip_transparent, 0, cfg->ip_freebind, cfg->use_systemd);
cfg->ip_transparent, 0, 0, cfg->ip_freebind, cfg->use_systemd);
freeaddrinfo(res);
}

View file

@ -1109,7 +1109,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
struct respip_client_info* cinfo = NULL, cinfo_tmp;
memset(&qinfo, 0, sizeof(qinfo));
if(error != NETEVENT_NOERROR || !repinfo) {
if((error != NETEVENT_NOERROR && error != NETEVENT_DONE)|| !repinfo) {
/* some bad tcp query DNS formats give these error calls */
verbose(VERB_ALGO, "handle request called with err=%d", error);
return 0;
@ -1797,7 +1797,8 @@ worker_init(struct worker* worker, struct config_file *cfg,
cfg->do_tcp_keepalive
? cfg->tcp_keepalive_timeout
: cfg->tcp_idle_timeout,
worker->daemon->tcl,
cfg->harden_large_queries,
worker->daemon->tcl,
worker->daemon->listen_sslctx,
dtenv, worker_handle_request, worker);
if(!worker->front) {

View file

@ -729,12 +729,14 @@ server:
# add a netblock specific override to a localzone, with zone type
# local-zone-override: "example.com" 192.0.2.0/24 refuse
# service clients over TLS (on the TCP sockets), with plain DNS inside
# the TLS stream. Give the certificate to use and private key.
# service clients over TLS (on the TCP sockets) with plain DNS inside
# the TLS stream, and over HTTPS using HTTP/2 as specified in RFC8484.
# Give the certificate to use and private key.
# default is "" (disabled). requires restart to take effect.
# tls-service-key: "path/to/privatekeyfile.key"
# tls-service-pem: "path/to/publiccertfile.pem"
# tls-port: 853
# https-port: 443
# cipher setting for TLSv1.2
# tls-ciphers: "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256"

View file

@ -469,15 +469,16 @@ Alternate syntax for \fBtls\-upstream\fR. If both are present in the config
file the last is used.
.TP
.B tls\-service\-key: \fI<file>
If enabled, the server provides TLS service on the TCP ports marked
implicitly or explicitly for TLS service with tls\-port. The file must
contain the private key for the TLS session, the public certificate is in
the tls\-service\-pem file and it must also be specified if tls\-service\-key
is specified. The default is "", turned off. Enabling or disabling
this service requires a restart (a reload is not enough), because the
key is read while root permissions are held and before chroot (if any).
The ports enabled implicitly or explicitly via \fBtls\-port:\fR do not provide
normal DNS TCP service.
If enabled, the server provides DNS-over-TLS or DNS-over-HTTPS service on the
TCP ports marked implicitly or explicitly for these services with tls\-port or
https\-port. The file must contain the private key for the TLS session, the
public certificate is in the tls\-service\-pem file and it must also be
specified if tls\-service\-key is specified. The default is "", turned off.
Enabling or disabling this service requires a restart (a reload is not enough),
because the key is read while root permissions are held and before chroot (if any).
The ports enabled implicitly or explicitly via \fBtls\-port:\fR and
\fBhttps\-port:\fR do not provide normal DNS TCP service. Unbound needs to be
compiled with libnghttp2 in order to provide DNS-over-HTTPS.
.TP
.B ssl\-service\-key: \fI<file>
Alternate syntax for \fBtls\-service\-key\fR.
@ -493,6 +494,10 @@ Alternate syntax for \fBtls\-service\-pem\fR.
The port number on which to provide TCP TLS service, default 853, only
interfaces configured with that port number as @number get the TLS service.
.TP
.B https\-port: \fI<number>
The port number on which to provide DNS-over-HTTPS service, default 443, only
interfaces configured with that port number as @number get the HTTPS service.
.TP
.B ssl\-port: \fI<number>
Alternate syntax for \fBtls\-port\fR.
.TP

View file

@ -53,6 +53,7 @@
#include "util/config_file.h"
#include "util/net_help.h"
#include "sldns/sbuffer.h"
#include "sldns/parseutil.h"
#include "services/mesh.h"
#include "util/fptr_wlist.h"
#include "util/locks.h"
@ -638,7 +639,8 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
int
create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
int* reuseport, int transparent, int mss, int freebind, int use_systemd)
int* reuseport, int transparent, int mss, int nodelay, int freebind,
int use_systemd)
{
int s;
#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND) || defined(SO_BINDANY)
@ -685,6 +687,36 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
#endif
return -1;
}
if(nodelay) {
#if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
if(setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void*)&on,
(socklen_t)sizeof(on)) < 0) {
#ifndef USE_WINSOCK
log_err(" setsockopt(.. TCP_NODELAY ..) failed: %s",
strerror(errno));
#else
log_err(" setsockopt(.. TCP_NODELAY ..) failed: %s",
wsa_strerror(WSAGetLastError()));
#endif
}
#else
log_warn(" setsockopt(TCP_NODELAY) unsupported");
#endif /* defined(IPPROTO_TCP) && defined(TCP_NODELAY) */
#if defined(IPPROTO_TCP) && defined(TCP_QUICKACK)
if(setsockopt(s, IPPROTO_TCP, TCP_QUICKACK, (void*)&on,
(socklen_t)sizeof(on)) < 0) {
#ifndef USE_WINSOCK
log_err(" setsockopt(.. TCP_QUICKACK ..) failed: %s",
strerror(errno));
#else
log_err(" setsockopt(.. TCP_QUICKACK ..) failed: %s",
wsa_strerror(WSAGetLastError()));
#endif
}
#else
log_warn(" setsockopt(TCP_QUICKACK) unsupported");
#endif /* defined(IPPROTO_TCP) && defined(TCP_QUICKACK) */
}
if (mss > 0) {
#if defined(IPPROTO_TCP) && defined(TCP_MAXSEG)
if(setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, (void*)&mss,
@ -952,7 +984,8 @@ err:
static int
make_sock(int stype, const char* ifname, const char* port,
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
int* reuseport, int transparent, int tcp_mss, int freebind, int use_systemd)
int* reuseport, int transparent, int tcp_mss, int nodelay, int freebind,
int use_systemd)
{
struct addrinfo *res = NULL;
int r, s, inuse, noproto;
@ -988,7 +1021,7 @@ make_sock(int stype, const char* ifname, const char* port,
}
} else {
s = create_tcp_accept_sock(res, v6only, &noproto, reuseport,
transparent, tcp_mss, freebind, use_systemd);
transparent, tcp_mss, nodelay, freebind, use_systemd);
if(s == -1 && noproto && hints->ai_family == AF_INET6){
*noip6 = 1;
}
@ -1001,7 +1034,8 @@ make_sock(int stype, const char* ifname, const char* port,
static int
make_sock_port(int stype, const char* ifname, const char* port,
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
int* reuseport, int transparent, int tcp_mss, int freebind, int use_systemd)
int* reuseport, int transparent, int tcp_mss, int nodelay, int freebind,
int use_systemd)
{
char* s = strchr(ifname, '@');
if(s) {
@ -1023,10 +1057,11 @@ make_sock_port(int stype, const char* ifname, const char* port,
(void)strlcpy(p, s+1, sizeof(p));
p[strlen(s+1)]=0;
return make_sock(stype, newif, p, hints, v6only, noip6,
rcv, snd, reuseport, transparent, tcp_mss, freebind, use_systemd);
rcv, snd, reuseport, transparent, tcp_mss, nodelay,
freebind, use_systemd);
}
return make_sock(stype, ifname, port, hints, v6only, noip6, rcv, snd,
reuseport, transparent, tcp_mss, freebind, use_systemd);
reuseport, transparent, tcp_mss, nodelay, freebind, use_systemd);
}
/**
@ -1125,6 +1160,18 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
return 0;
}
/** see if interface is https, its port number == the https port number */
static int
if_is_https(const char* ifname, const char* port, int https_port)
{
char* p = strchr(ifname, '@');
if(!p && atoi(port) == https_port)
return 1;
if(p && atoi(p+1) == https_port)
return 1;
return 0;
}
/**
* Helper for ports_open. Creates one interface (or NULL for default).
* @param ifname: The interface ip address.
@ -1139,6 +1186,7 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
* @param snd: send buffer size for UDP
* @param ssl_port: ssl service port number
* @param tls_additional_port: list of additional ssl service port numbers.
* @param https_port: DoH service port number
* @param reuseport: try to set SO_REUSEPORT if nonNULL and true.
* set to false on exit if reuseport failed due to no kernel support.
* @param transparent: set IP_TRANSPARENT socket option.
@ -1152,11 +1200,13 @@ static int
ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
struct addrinfo *hints, const char* port, struct listen_port** list,
size_t rcv, size_t snd, int ssl_port,
struct config_strlist* tls_additional_port, int* reuseport,
int transparent, int tcp_mss, int freebind, int use_systemd,
int dnscrypt_port)
struct config_strlist* tls_additional_port, int https_port,
int* reuseport, int transparent, int tcp_mss, int freebind,
int use_systemd, int dnscrypt_port)
{
int s, noip6=0;
int is_https = if_is_https(ifname, port, https_port);
int nodelay = is_https; /* TODO make config option */
#ifdef USE_DNSCRYPT
int is_dnscrypt = ((strchr(ifname, '@') &&
atoi(strchr(ifname, '@')+1) == dnscrypt_port) ||
@ -1171,7 +1221,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
if(do_auto) {
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
&noip6, rcv, snd, reuseport, transparent,
tcp_mss, freebind, use_systemd)) == -1) {
tcp_mss, nodelay, freebind, use_systemd)) == -1) {
if(noip6) {
log_warn("IPv6 protocol not available");
return 1;
@ -1200,7 +1250,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
/* regular udp socket */
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
&noip6, rcv, snd, reuseport, transparent,
tcp_mss, freebind, use_systemd)) == -1) {
tcp_mss, nodelay, freebind, use_systemd)) == -1) {
if(noip6) {
log_warn("IPv6 protocol not available");
return 1;
@ -1220,8 +1270,17 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
if(do_tcp) {
int is_ssl = if_is_ssl(ifname, port, ssl_port,
tls_additional_port);
enum listen_type port_type;
if(is_ssl)
port_type = listen_type_ssl;
else if(is_https)
port_type = listen_type_http;
else if(is_dnscrypt)
port_type = listen_type_tcp_dnscrypt;
else
port_type = listen_type_tcp;
if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
&noip6, 0, 0, reuseport, transparent, tcp_mss,
&noip6, 0, 0, reuseport, transparent, tcp_mss, nodelay,
freebind, use_systemd)) == -1) {
if(noip6) {
/*log_warn("IPv6 protocol not available");*/
@ -1231,8 +1290,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
}
if(is_ssl)
verbose(VERB_ALGO, "setup TCP for SSL service");
if(!port_insert(list, s, is_ssl?listen_type_ssl:
(is_dnscrypt?listen_type_tcp_dnscrypt:listen_type_tcp))) {
if(!port_insert(list, s, port_type)) {
#ifndef USE_WINSOCK
close(s);
#else
@ -1266,7 +1324,7 @@ listen_cp_insert(struct comm_point* c, struct listen_dnsport* front)
struct listen_dnsport*
listen_create(struct comm_base* base, struct listen_port* ports,
size_t bufsize, int tcp_accept_count, int tcp_idle_timeout,
struct tcl_list* tcp_conn_limit, void* sslctx,
int harden_large_queries, struct tcl_list* tcp_conn_limit, void* sslctx,
struct dt_env* dtenv, comm_point_callback_type* cb, void *cb_arg)
{
struct listen_dnsport* front = (struct listen_dnsport*)
@ -1298,14 +1356,35 @@ listen_create(struct comm_base* base, struct listen_port* ports,
ports->ftype == listen_type_tcp_dnscrypt)
cp = comm_point_create_tcp(base, ports->fd,
tcp_accept_count, tcp_idle_timeout,
harden_large_queries,
tcp_conn_limit, bufsize, front->udp_buff,
cb, cb_arg);
else if(ports->ftype == listen_type_ssl) {
ports->ftype, cb, cb_arg);
else if(ports->ftype == listen_type_ssl ||
ports->ftype == listen_type_http) {
cp = comm_point_create_tcp(base, ports->fd,
tcp_accept_count, tcp_idle_timeout,
harden_large_queries,
tcp_conn_limit, bufsize, front->udp_buff,
cb, cb_arg);
ports->ftype, cb, cb_arg);
cp->ssl = sslctx;
if(ports->ftype == listen_type_http) {
if(!sslctx) {
log_warn("HTTPS port configured, but no TLS "
"tls-service-key or tls-service-pem "
"set");
}
#ifndef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
log_warn("Unbound is not compiled with an "
"OpenSSL version supporting ALPN "
" (OpenSSL >= 1.0.2). This is required "
"to use DNS-over-HTTPS");
#endif
#ifndef HAVE_NGHTTP2_NGHTTP2_H
log_warn("Unbound is not compiled with "
"nghttp2. This is required to use "
"DNS-over-HTTPS.");
#endif
}
} else if(ports->ftype == listen_type_udpancil ||
ports->ftype == listen_type_udpancil_dnscrypt)
cp = comm_point_create_udp_ancil(base, ports->fd,
@ -1419,6 +1498,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
cfg->dnscrypt_port)) {
@ -1433,6 +1513,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
cfg->dnscrypt_port)) {
@ -1449,6 +1530,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
do_tcp, &hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
cfg->dnscrypt_port)) {
@ -1463,6 +1545,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
do_tcp, &hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
cfg->dnscrypt_port)) {
@ -1906,3 +1989,624 @@ size_t tcp_req_info_get_stream_buffer_size(void)
lock_basic_unlock(&stream_wait_count_lock);
return s;
}
#ifdef HAVE_NGHTTP2
/** nghttp2 callback. Used to copy response from rbuffer to nghttp2 session */
static ssize_t http2_submit_response_read_callback(
nghttp2_session* ATTR_UNUSED(session),
int32_t stream_id, uint8_t* buf, size_t length, uint32_t* data_flags,
nghttp2_data_source* source, void* ATTR_UNUSED(cb_arg))
{
struct http2_stream* h2_stream;
struct http2_session* h2_session = source->ptr;
size_t copylen = length;
if(!(h2_stream = nghttp2_session_get_stream_user_data(
h2_session->session, stream_id))) {
verbose(VERB_QUERY, "http2: cannot get stream data, closing "
"stream");
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
if(!h2_stream->rbuffer ||
sldns_buffer_remaining(h2_stream->rbuffer) == 0) {
verbose(VERB_QUERY, "http2: cannot submit buffer. No data "
"available in rbuffer");
sldns_buffer_free(h2_stream->rbuffer);
h2_stream->rbuffer = NULL;
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
if(copylen > sldns_buffer_remaining(h2_stream->rbuffer))
copylen = sldns_buffer_remaining(h2_stream->rbuffer);
if(copylen > SSIZE_MAX)
copylen = SSIZE_MAX; /* will probably never happen */
memcpy(buf, sldns_buffer_current(h2_stream->rbuffer), copylen);
sldns_buffer_skip(h2_stream->rbuffer, copylen);
if(sldns_buffer_remaining(h2_stream->rbuffer) == 0) {
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
sldns_buffer_free(h2_stream->rbuffer);
h2_stream->rbuffer = NULL;
}
return copylen;
}
/**
* DNS response ready to be submitted to nghttp2, to be prepared for sending
* out. Response is stored in c->buffer. Copy to rbuffer because the c->buffer
* might be used before this will bne send out.
* @param h2_session: http2 session, containing c->buffer which contains answer
* @return 0 on error, 1 otherwise
*/
int http2_submit_dns_response(struct http2_session* h2_session)
{
int ret;
nghttp2_data_provider data_prd;
char status[4];
nghttp2_nv headers[2];
struct http2_stream* h2_stream = h2_session->c->h2_stream;
if(h2_stream->rbuffer) {
log_err("http2 submit response error: rbuffer already "
"exists");
return 0;
}
if(sldns_buffer_remaining(h2_session->c->buffer) == 0) {
log_err("http2 submit response error: c->buffer not complete");
return 0;
}
if(!(h2_stream->rbuffer = sldns_buffer_new(
sldns_buffer_remaining(h2_session->c->buffer)))) {
log_err("http2 submit response error: malloc failure");
return 0;
}
if(snprintf(status, 4, "%d", h2_stream->status) != 3) {
verbose(VERB_QUERY, "http2: submit response error: "
"invalid status");
return 0;
}
headers[0].name = (uint8_t*)":status";
headers[0].namelen = 7;
headers[0].value = (uint8_t*)status;
headers[0].valuelen = 3;
headers[0].flags = NGHTTP2_NV_FLAG_NONE;
headers[1].name = (uint8_t*)"content-type";
headers[1].namelen = 12;
headers[1].value = (uint8_t*)"application/dns-message";
headers[1].valuelen = 23;
headers[1].flags = NGHTTP2_NV_FLAG_NONE;
/*TODO be nice and add the content-length header
headers[2].name = (uint8_t*)"content-length";
headers[2].namelen = 14;
headers[2].value =
headers[2].valuelen =
headers[2].flags = NGHTTP2_NV_FLAG_NONE;
*/
sldns_buffer_write(h2_stream->rbuffer,
sldns_buffer_current(h2_session->c->buffer),
sldns_buffer_remaining(h2_stream->rbuffer));
sldns_buffer_flip(h2_stream->rbuffer);
data_prd.source.ptr = h2_session;
data_prd.read_callback = http2_submit_response_read_callback;
ret = nghttp2_submit_response(h2_session->session, h2_stream->stream_id,
headers, 2, &data_prd);
if(ret) {
verbose(VERB_QUERY, "http2: set_stream_user_data failed, "
"error: %s", nghttp2_strerror(ret));
return 0;
}
return 1;
}
#else
int http2_submit_dns_response(void* ATTR_UNUSED(v))
{
return 0;
}
#endif
#ifdef HAVE_NGHTTP2
/** HTTP status to descriptive string */
static char* http_status_to_str(enum http_status s)
{
switch(s) {
case HTTP_STATUS_OK:
return "OK";
case HTTP_STATUS_BAD_REQUEST:
return "Bad Request";
case HTTP_STATUS_NOT_FOUND:
return "Not Found";
case HTTP_STATUS_PAYLOAD_TOO_LARGE:
return "Payload Too Large";
case HTTP_STATUS_URI_TOO_LONG:
return "URI Too Long";
case HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE:
return "Unsupported Media Type";
case HTTP_STATUS_NOT_IMPLEMENTED:
return "Not Implemented";
}
return "Status Unknown";
}
/** nghttp2 callback. Used to copy error message to nghttp2 session */
static ssize_t http2_submit_error_read_callback(
nghttp2_session* ATTR_UNUSED(session),
int32_t stream_id, uint8_t* buf, size_t length, uint32_t* data_flags,
nghttp2_data_source* source, void* ATTR_UNUSED(cb_arg))
{
struct http2_stream* h2_stream;
struct http2_session* h2_session = source->ptr;
char* msg;
if(!(h2_stream = nghttp2_session_get_stream_user_data(
h2_session->session, stream_id))) {
verbose(VERB_QUERY, "http2: cannot get stream data, closing "
"stream");
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
msg = http_status_to_str(h2_stream->status);
if(length < strlen(msg))
return 0; /* not worth trying over multiple frames */
memcpy(buf, msg, strlen(msg));
return strlen(msg);
}
/**
* HTTP error response ready to be submitted to nghttp2, to be prepared for
* sending out. Message body will contain descriptive string for HTTP status.
* @param h2_session: http2 session to submit to
* @param h2_stream: http2 stream containing HTTP status to use for error
* @return 0 on error, 1 otherwise
*/
static int http2_submit_error(struct http2_session* h2_session,
struct http2_stream* h2_stream)
{
int ret;
char status[4];
nghttp2_data_provider data_prd;
nghttp2_nv headers[1]; /* will be copied by nghttp */
if(snprintf(status, 4, "%d", h2_stream->status) != 3) {
verbose(VERB_QUERY, "http2: submit error failed, "
"invalid status");
return 0;
}
headers[0].name = (uint8_t*)":status";
headers[0].namelen = 7;
headers[0].value = (uint8_t*)status;
headers[0].valuelen = 3;
headers[0].flags = NGHTTP2_NV_FLAG_NONE;
data_prd.source.ptr = h2_session;
data_prd.read_callback = http2_submit_error_read_callback;
ret = nghttp2_submit_response(h2_session->session, h2_stream->stream_id,
headers, 1, &data_prd);
if(ret) {
verbose(VERB_QUERY, "http2: submit error failed, "
"error: %s", nghttp2_strerror(ret));
return 0;
}
return 1;
}
/**
* Start query handling. Query is stored in the stream, and will be free'd here.
* @param h2_session: http2 session, containing comm point
* @param h2_stream: stream containing buffered query
* @return: -1 on error, 1 if answer is stored in c->buffer, 0 if there is no
* reply available (yet).
*/
static int http2_query_read_done(struct http2_session* h2_session,
struct http2_stream* h2_stream)
{
log_assert(h2_stream->qbuffer);
if(h2_session->c->h2_stream) {
verbose(VERB_ALGO, "http2_query_read_done failure: shared "
"buffer already assigned to stream");
return -1;
}
if(sldns_buffer_remaining(h2_session->c->buffer) <
sldns_buffer_remaining(h2_stream->qbuffer)) {
sldns_buffer_free(h2_stream->qbuffer);
h2_stream->qbuffer = NULL;
sldns_buffer_clear(h2_session->c->buffer);
verbose(VERB_ALGO, "http2_query_read_done failure: can't fit "
"qbuffer in c->buffer");
return -1;
}
sldns_buffer_write(h2_session->c->buffer,
sldns_buffer_current(h2_stream->qbuffer),
sldns_buffer_remaining(h2_stream->qbuffer));
sldns_buffer_free(h2_stream->qbuffer);
h2_stream->qbuffer = NULL;
sldns_buffer_flip(h2_session->c->buffer);
h2_session->c->h2_stream = h2_stream;
fptr_ok(fptr_whitelist_comm_point(h2_session->c->callback));
if((*h2_session->c->callback)(h2_session->c, h2_session->c->cb_arg,
NETEVENT_NOERROR, &h2_session->c->repinfo)) {
return 1; /* answer in c->buffer */
}
sldns_buffer_clear(h2_session->c->buffer);
h2_session->c->h2_stream = NULL;
return 0; /* mesh state added, or dropped */
}
/** nghttp2 callback. Used to check if the received frame indicates the end of a
* stream. Gather collected request data and start query handling. */
static int http2_req_frame_recv_cb(nghttp2_session* session,
const nghttp2_frame* frame, void* cb_arg)
{
struct http2_session* h2_session = (struct http2_session*)cb_arg;
struct http2_stream* h2_stream;
int query_read_done;
if((frame->hd.type != NGHTTP2_DATA &&
frame->hd.type != NGHTTP2_HEADERS) ||
!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) {
return 0;
}
if(!(h2_stream = nghttp2_session_get_stream_user_data(
session, frame->hd.stream_id)))
return 0;
if(h2_stream->invalid_endpoint) {
h2_stream->status = HTTP_STATUS_NOT_FOUND;
goto submit_http_error;
}
if(h2_stream->invalid_content_type) {
h2_stream->status = HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE;
goto submit_http_error;
}
if(h2_stream->http_method != HTTP_METHOD_GET &&
h2_stream->http_method != HTTP_METHOD_POST) {
h2_stream->status = HTTP_STATUS_NOT_IMPLEMENTED;
goto submit_http_error;
}
if(h2_stream->query_too_large) {
if(h2_stream->http_method == HTTP_METHOD_POST)
h2_stream->status = HTTP_STATUS_PAYLOAD_TOO_LARGE;
else
h2_stream->status = HTTP_STATUS_URI_TOO_LONG;
goto submit_http_error;
}
if(!h2_stream->qbuffer) {
h2_stream->status = HTTP_STATUS_BAD_REQUEST;
goto submit_http_error;
}
if(h2_stream->status) {
submit_http_error:
verbose(VERB_QUERY, "http2 request invalid, returning :status="
"%d", h2_stream->status);
if(!http2_submit_error(h2_session, h2_stream)) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
return 0;
}
h2_stream->status = HTTP_STATUS_OK;
sldns_buffer_flip(h2_stream->qbuffer);
h2_session->postpone_drop = 1;
query_read_done = http2_query_read_done(h2_session, h2_stream);
if(query_read_done < 0)
return NGHTTP2_ERR_CALLBACK_FAILURE;
else if(!query_read_done) {
if(h2_session->is_drop) {
/* connection needs to be closed. Return failure to make
* sure no other action are taken anymore on comm point.
* failure will result in reclaiming (and closing)
* of comm point. */
verbose(VERB_QUERY, "http2 query dropped in worker cb");
h2_session->postpone_drop = 0;
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
/* nothing to submit right now, query added to mesh. */
h2_session->postpone_drop = 0;
return 0;
}
if(!http2_submit_dns_response(h2_session)) {
sldns_buffer_clear(h2_session->c->buffer);
h2_session->c->h2_stream = NULL;
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
verbose(VERB_QUERY, "http2 query submitted to session");
sldns_buffer_clear(h2_session->c->buffer);
h2_session->c->h2_stream = NULL;
return 0;
}
/** nghttp2 callback. Used to detect start of new streams. */
static int http2_req_begin_headers_cb(nghttp2_session* session,
const nghttp2_frame* frame, void* cb_arg)
{
struct http2_session* h2_session = (struct http2_session*)cb_arg;
struct http2_stream* h2_stream;
int ret;
if(frame->hd.type != NGHTTP2_HEADERS ||
frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
/* only interrested in request headers */
return 0;
}
if(!(h2_stream = http2_stream_create(frame->hd.stream_id))) {
log_err("malloc failure while creating http2 stream");
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
http2_session_add_stream(h2_session, h2_stream);
ret = nghttp2_session_set_stream_user_data(session,
frame->hd.stream_id, h2_stream);
if(ret) {
/* stream does not exist */
verbose(VERB_QUERY, "http2: set_stream_user_data failed, "
"error: %s", nghttp2_strerror(ret));
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
return 0;
}
/**
* base64url decode, store in qbuffer
* @param h2_session: http2 session
* @param h2_stream: http2 stream
* @param start: start of the base64 string
* @param length: length of the base64 string
* @return: 0 on error, 1 otherwise. query will be stored in h2_stram->qbuffer,
* buffer will be NULL is unparseble.
*/
static int http2_buffer_uri_query(struct http2_session* h2_session,
struct http2_stream* h2_stream, const uint8_t* start, size_t length)
{
size_t expectb64len;
int b64len;
if(h2_stream->http_method == HTTP_METHOD_POST)
return 1;
if(length == 0)
return 1;
if(h2_stream->qbuffer) {
verbose(VERB_ALGO, "http2_req_header fail, "
"qbuffer already set");
return 0;
}
/* calculate size, might be a bit bigger than the real
* decoded buffer size */
expectb64len = sldns_b64_pton_calculate_size(length);
log_assert(expectb64len > 0);
if(expectb64len >
h2_session->c->http2_max_qbuffer_size) {
h2_stream->query_too_large = 1;
return 1;
}
if(!(h2_stream->qbuffer = sldns_buffer_new(expectb64len))) {
log_err("http2_req_header fail, qbuffer "
"malloc failure");
return 0;
}
if(!(b64len = sldns_b64url_pton(
(char const *)start, length,
sldns_buffer_current(h2_stream->qbuffer),
expectb64len)) || b64len < 0) {
sldns_buffer_free(h2_stream->qbuffer);
h2_stream->qbuffer = NULL;
/* return without error, method can be an
* unknown POST */
return 1;
}
sldns_buffer_skip(h2_stream->qbuffer, (size_t)b64len);
return 1;
}
/** nghttp2 callback. Used to parse headers from HEADER frames. */
static int http2_req_header_cb(nghttp2_session* session,
const nghttp2_frame* frame, const uint8_t* name, size_t namelen,
const uint8_t* value, size_t valuelen, uint8_t ATTR_UNUSED(flags),
void* cb_arg)
{
struct http2_stream* h2_stream = NULL;
struct http2_session* h2_session = (struct http2_session*)cb_arg;
/* nghttp2 deals with CONTINUATION frames and provides them as part of
* the HEADER */
if(frame->hd.type != NGHTTP2_HEADERS ||
frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
/* only interrested in request headers */
return 0;
}
if(!(h2_stream = nghttp2_session_get_stream_user_data(session,
frame->hd.stream_id)))
return 0;
/* earlier checks already indicate we can stop handling this query */
if(h2_stream->http_method == HTTP_METHOD_UNSUPPORTED ||
h2_stream->invalid_content_type ||
h2_stream->invalid_endpoint)
return 0;
/* nghttp2 performs some sanity checks in the headers, including:
* name and value are guaranteed to be null terminated
* name is guaranteed to be lowercase
* content-length value is guaranteed to contain digits
*/
if(!h2_stream->http_method && namelen == 7 &&
memcmp(":method", name, namelen) == 0) {
/* Case insensitive check on :method value to be on the safe
* side. I failed to find text about case sentitivity in specs.
*/
if(valuelen == 3 && strcasecmp("GET", (const char*)value) == 0)
h2_stream->http_method = HTTP_METHOD_GET;
else if(valuelen == 4 &&
strcasecmp("POST", (const char*)value) == 0) {
h2_stream->http_method = HTTP_METHOD_POST;
if(h2_stream->qbuffer) {
/* POST method uses query from DATA frames */
sldns_buffer_free(h2_stream->qbuffer);
h2_stream->qbuffer = NULL;
}
} else
h2_stream->http_method = HTTP_METHOD_UNSUPPORTED;
return 0;
}
if(namelen == 5 && memcmp(":path", name, namelen) == 0) {
/* Hard coded /dns-query endpoint, might be nice to make
* configurable.
* :path may contain DNS query, depending on method. Method might
* not be known yet here, so check after finishing receiving
* stream. */
#define HTTP_ENDPOINT "/dns-query"
#define HTTP_QUERY_PARAM "?dns="
size_t el = sizeof(HTTP_ENDPOINT) - 1;
size_t qpl = sizeof(HTTP_QUERY_PARAM) - 1;
if(valuelen < el || memcmp(HTTP_ENDPOINT, value, el) != 0) {
h2_stream->invalid_endpoint = 1;
return 0;
}
/* larger than endpoint only allowed if it is for the query
* parameter */
if(valuelen <= el+qpl ||
memcmp(HTTP_QUERY_PARAM, value+el, qpl) != 0) {
if(valuelen != el)
h2_stream->invalid_endpoint = 1;
return 0;
}
if(!http2_buffer_uri_query(h2_session, h2_stream,
value+(el+qpl), valuelen-(el+qpl))) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
return 0;
}
/* Content type is a SHOULD (rfc7231#section-3.1.1.5) when using POST,
* and not needed when using GET. Don't enfore.
* If set only allow lowercase "application/dns-message".
*
* Clients SHOULD (rfc8484#section-4.1) set an accept header, but MUST
* be able to handle "application/dns-message". Since that is the only
* content-type supported we can ignore the accept header.
*/
if((namelen == 12 && memcmp("content-type", name, namelen) == 0)) {
if(valuelen != 23 || memcmp("application/dns-message", value,
valuelen) != 0) {
h2_stream->invalid_content_type = 1;
}
}
/* Only interested in content-lentg for POST (on not yet known) method.
*/
if((!h2_stream->http_method ||
h2_stream->http_method == HTTP_METHOD_POST) &&
!h2_stream->content_length && namelen == 14 &&
memcmp("content-length", name, namelen) == 0) {
if(valuelen > 5) {
h2_stream->query_too_large = 1;
return 0;
}
/* guaranteed to only contian digits and be null terminated */
h2_stream->content_length = atoi((const char*)value);
if(h2_stream->content_length >
h2_session->c->http2_max_qbuffer_size) {
h2_stream->query_too_large = 1;
return 0;
}
}
return 0;
}
/** nghttp2 callback. Used to get data from DATA frames, which can contain
* queries in POST requests. */
static int http2_req_data_chunk_recv_cb(nghttp2_session* ATTR_UNUSED(session),
uint8_t ATTR_UNUSED(flags), int32_t stream_id, const uint8_t* data,
size_t len, void* cb_arg)
{
struct http2_session* h2_session = (struct http2_session*)cb_arg;
struct http2_stream* h2_stream;
if(!(h2_stream = nghttp2_session_get_stream_user_data(
h2_session->session, stream_id))) {
return 0;
}
if(h2_stream->query_too_large)
return 0;
if(!h2_stream->qbuffer) {
if(h2_stream->content_length) {
if(h2_stream->content_length < len)
/* getting more data in DATA frame than
* advertised in content-length header. */
return NGHTTP2_ERR_CALLBACK_FAILURE;
h2_stream->qbuffer = sldns_buffer_new(
h2_stream->content_length);
} else if(len <= h2_session->c->http2_max_qbuffer_size) {
/* setting this to msg-buffer-size can result in a lot
* of memory consuption. Most queries should fit in a
* single DATA frame, and most POST queries will
* containt content-length which does not impose this
* limit. */
h2_stream->qbuffer = sldns_buffer_new(len);
}
}
if(!h2_stream->qbuffer ||
sldns_buffer_remaining(h2_stream->qbuffer) < len) {
verbose(VERB_ALGO, "http2 data_chunck_recv failed. Not enough "
"buffer space for POST query. Can happen on multi "
"frame requests without content-length header");
h2_stream->query_too_large = 1;
return 0;
}
sldns_buffer_write(h2_stream->qbuffer, data, len);
return 0;
}
nghttp2_session_callbacks* http2_req_callbacks_create()
{
nghttp2_session_callbacks *callbacks;
if(nghttp2_session_callbacks_new(&callbacks) == NGHTTP2_ERR_NOMEM) {
log_err("failed to initialize nghttp2 callback");
return NULL;
}
/* reception of header block started, used to create h2_stream */
nghttp2_session_callbacks_set_on_begin_headers_callback(callbacks,
http2_req_begin_headers_cb);
/* complete frame received, used to get data from stream if frame
* has end stream flag, and start processing query */
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
http2_req_frame_recv_cb);
/* get request info from headers */
nghttp2_session_callbacks_set_on_header_callback(callbacks,
http2_req_header_cb);
/* get data from DATA frames, containing POST query */
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(callbacks,
http2_req_data_chunk_recv_cb);
/* generic HTTP2 callbacks */
nghttp2_session_callbacks_set_recv_callback(callbacks, http2_recv_cb);
nghttp2_session_callbacks_set_send_callback(callbacks, http2_send_cb);
nghttp2_session_callbacks_set_on_stream_close_callback(callbacks,
http2_stream_close_cb);
return callbacks;
}
#endif /* HAVE_NGHTTP2 */

View file

@ -43,6 +43,9 @@
#define LISTEN_DNSPORT_H
#include "util/netevent.h"
#ifdef HAVE_NGHTTP2_NGHTTP2_H
#include <nghttp2/nghttp2.h>
#endif
struct listen_list;
struct config_file;
struct addrinfo;
@ -94,8 +97,9 @@ enum listen_type {
/** tcp type + dnscrypt */
listen_type_tcp_dnscrypt,
/** udp ipv6 (v4mapped) for use with ancillary data + dnscrypt*/
listen_type_udpancil_dnscrypt
listen_type_udpancil_dnscrypt,
/** HTTP(2) over TLS over TCP */
listen_type_http
};
/**
@ -139,6 +143,7 @@ void listening_ports_free(struct listen_port* list);
* @param tcp_accept_count: max number of simultaneous TCP connections
* from clients.
* @param tcp_idle_timeout: idle timeout for TCP connections in msec.
* @param harden_large_queries: whether query size should be limited.
* @param tcp_conn_limit: TCP connection limit info.
* @param sslctx: nonNULL if ssl context.
* @param dtenv: nonNULL if dnstap enabled.
@ -149,7 +154,7 @@ void listening_ports_free(struct listen_port* list);
*/
struct listen_dnsport* listen_create(struct comm_base* base,
struct listen_port* ports, size_t bufsize,
int tcp_accept_count, int tcp_idle_timeout,
int tcp_accept_count, int tcp_idle_timeout, int harden_large_queries,
struct tcl_list* tcp_conn_limit, void* sslctx,
struct dt_env *dtenv, comm_point_callback_type* cb, void* cb_arg);
@ -220,12 +225,14 @@ int create_udp_sock(int family, int socktype, struct sockaddr* addr,
* listening UDP port. Set to false on return if it failed to do so.
* @param transparent: set IP_TRANSPARENT socket option.
* @param mss: maximum segment size of the socket. if zero, leaves the default.
* @param nodelay: if true set TCP_NODELAY and TCP_QUICKACK socket options.
* @param freebind: set IP_FREEBIND socket option.
* @param use_systemd: if true, fetch sockets from systemd.
* @return: the socket. -1 on error.
*/
int create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
int* reuseport, int transparent, int mss, int freebind, int use_systemd);
int* reuseport, int transparent, int mss, int nodelay, int freebind,
int use_systemd);
/**
* Create and bind local listening socket
@ -367,4 +374,24 @@ int tcp_req_info_handle_read_close(struct tcp_req_info* req);
/** get the size of currently used tcp stream wait buffers (in bytes) */
size_t tcp_req_info_get_stream_buffer_size(void);
#ifdef HAVE_NGHTTP2
/**
* Create nghttp2 callbacks to handle HTTP2 requests.
* @return malloc'ed struct, NULL on failure
*/
nghttp2_session_callbacks* http2_req_callbacks_create();
/**
* DNS response ready to be submitted to nghttp2, to be prepared for sending
* out. Response is stored in c->buffer. Copy to rbuffer because the c->buffer
* might be used before this will be send out.
* @param h2_session: http2 session, containing c->buffer which contains answer
* @param h2_stream: http2 stream, containing buffer to store answer in
* @return 0 on error, 1 otherwise
*/
int http2_submit_dns_response(struct http2_session* h2_session);
#else
int http2_submit_dns_response(void* v);
#endif /* HAVE_NGHTTP2 */
#endif /* LISTEN_DNSPORT_H */

View file

@ -551,6 +551,9 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
goto servfail_mem;
}
}
if(rep->c->alpn_h2) {
http2_stream_add_meshstate(rep->c->h2_stream, mesh, s);
}
/* add serve expired timer if required and not already there */
if(timeout && !mesh_serve_expired_init(s, timeout)) {
log_err("mesh_new_client: out of memory initializing serve expired");
@ -1207,6 +1210,9 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
else secure = 0;
if(!rep && rcode == LDNS_RCODE_NOERROR)
rcode = LDNS_RCODE_SERVFAIL;
if(r->query_reply.c->alpn_h2) {
r->query_reply.c->h2_stream = r->h2_stream;
}
/* send the reply */
/* We don't reuse the encoded answer if either the previous or current
* response has a local alias. We could compare the alias records
@ -1488,6 +1494,8 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
s->s.qinfo.qname_len);
if(!r->qname)
return 0;
if(rep->c->alpn_h2)
r->h2_stream = rep->c->h2_stream;
/* Data related to local alias stored in 'qinfo' (if any) is ephemeral
* and can be different for different original queries (even if the

View file

@ -230,6 +230,8 @@ struct mesh_reply {
uint8_t* qname;
/** same as that in query_info. */
struct local_rrset* local_alias;
/** send query to this http2 stream, if set */
struct http2_stream* h2_stream;
};
/**

View file

@ -674,14 +674,17 @@ size_t sldns_b64_pton_calculate_size(size_t srcsize)
return (((((srcsize + 3) / 4) * 3)) + 1);
}
int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize)
/* padding not required if srcsize is set */
static int sldns_b64_pton_base(char const *src, size_t srcsize, uint8_t *target,
size_t targsize, int base64url)
{
const uint8_t pad64 = 64; /* is 64th in the b64 array */
const char* s = src;
uint8_t in[4];
size_t o = 0, incount = 0;
int check_padding = (srcsize) ? 0 : 1;
while(*s) {
while(*s && (check_padding || srcsize)) {
/* skip any character that is not base64 */
/* conceptually we do:
const char* b64 = pad'=' is appended to array
@ -690,30 +693,40 @@ int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize)
and use d-b64;
*/
char d = *s++;
srcsize--;
if(d <= 'Z' && d >= 'A')
d -= 'A';
else if(d <= 'z' && d >= 'a')
d = d - 'a' + 26;
else if(d <= '9' && d >= '0')
d = d - '0' + 52;
else if(d == '+')
else if(!base64url && d == '+')
d = 62;
else if(d == '/')
else if(base64url && d == '-')
d = 62;
else if(!base64url && d == '/')
d = 63;
else if(d == '=')
else if(base64url && d == '_')
d = 63;
else if(!base64url && d == '=')
d = 64;
else continue;
in[incount++] = (uint8_t)d;
if(incount != 4)
/* work on block of 4, unless padding is not used and there are
* less than 4 chars left */
if(incount != 4 && (check_padding || srcsize))
continue;
assert(!check_padding || incount==4);
/* process whole block of 4 characters into 3 output bytes */
if(in[3] == pad64 && in[2] == pad64) { /* A B = = */
if((incount == 2 ||
(incount == 4 && in[3] == pad64 && in[2] == pad64))) { /* A B = = */
if(o+1 > targsize)
return -1;
target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
o += 1;
break; /* we are done */
} else if(in[3] == pad64) { /* A B C = */
} else if(incount == 3 ||
(incount == 4 && in[3] == pad64)) { /* A B C = */
if(o+2 > targsize)
return -1;
target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
@ -721,7 +734,7 @@ int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize)
o += 2;
break; /* we are done */
} else {
if(o+3 > targsize)
if(incount != 4 || o+3 > targsize)
return -1;
/* write xxxxxxyy yyyyzzzz zzwwwwww */
target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
@ -733,3 +746,17 @@ int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize)
}
return (int)o;
}
int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize)
{
return sldns_b64_pton_base(src, 0, target, targsize, 0);
}
int sldns_b64url_pton(char const *src, size_t srcsize, uint8_t *target,
size_t targsize)
{
if(!srcsize) {
return 0;
}
return sldns_b64_pton_base(src, srcsize, target, targsize, 1);
}

View file

@ -97,8 +97,9 @@ int sldns_b64_ntop(uint8_t const *src, size_t srclength,
* calculates the size needed to store the result of sldns_b64_pton
*/
size_t sldns_b64_pton_calculate_size(size_t srcsize);
int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize);
int sldns_b64url_pton(char const *src, size_t srcsize, uint8_t *target,
size_t targsize);
/**
* calculates the size needed to store the result of b32_ntop

View file

@ -868,6 +868,7 @@ struct listen_dnsport*
listen_create(struct comm_base* base, struct listen_port* ATTR_UNUSED(ports),
size_t bufsize, int ATTR_UNUSED(tcp_accept_count),
int ATTR_UNUSED(tcp_idle_timeout),
int ATTR_UNUSED(harden_large_queries),
struct tcl_list* ATTR_UNUSED(tcp_conn_limit),
void* ATTR_UNUSED(sslctx), struct dt_env* ATTR_UNUSED(dtenv),
comm_point_callback_type* cb, void* cb_arg)
@ -1823,4 +1824,9 @@ tcp_req_info_get_stream_buffer_size(void)
return 0;
}
void http2_stream_add_meshstate(struct http2_stream* ATTR_UNUSED(h2_stream),
struct mesh_area* ATTR_UNUSED(mesh), struct mesh_state* ATTR_UNUSED(m))
{
}
/*********** End of Dummy routines ***********/

View file

@ -116,6 +116,7 @@ config_create(void)
cfg->ssl_upstream = 0;
cfg->tls_cert_bundle = NULL;
cfg->tls_win_cert = 0;
cfg->https_port = UNBOUND_DNS_OVER_HTTPS_PORT;
cfg->use_syslog = 1;
cfg->log_identity = NULL; /* changed later with argv[0] */
cfg->log_time_ascii = 0;
@ -505,6 +506,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_STRLIST_APPEND("tls-session-ticket-keys:", tls_session_ticket_keys)
else S_STR("tls-ciphers:", tls_ciphers)
else S_STR("tls-ciphersuites:", tls_ciphersuites)
else S_NUMBER_NONZERO("https-port:", https_port)
else S_YNO("interface-automatic:", if_automatic)
else S_YNO("use-systemd:", use_systemd)
else S_YNO("do-daemonize:", do_daemonize)
@ -957,6 +959,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_LST(opt, "tls-session-ticket-keys", tls_session_ticket_keys.first)
else O_STR(opt, "tls-ciphers", tls_ciphers)
else O_STR(opt, "tls-ciphersuites", tls_ciphersuites)
else O_DEC(opt, "https-port", https_port)
else O_YNO(opt, "use-systemd", use_systemd)
else O_YNO(opt, "do-daemonize", do_daemonize)
else O_STR(opt, "chroot", chrootdir)

View file

@ -128,6 +128,8 @@ struct config_file {
char* tls_ciphers;
/** TLS chiphersuites (TLSv1.3) */
char* tls_ciphersuites;
/** port on which to provide DNS over HTTPS service */
int https_port;
/** outgoing port range number of ports (per thread) */
int outgoing_num_ports;

File diff suppressed because it is too large Load diff

View file

@ -248,6 +248,7 @@ tls-additional-port{COLON} { YDVAR(1, VAR_TLS_ADDITIONAL_PORT) }
tls-session-ticket-keys{COLON} { YDVAR(1, VAR_TLS_SESSION_TICKET_KEYS) }
tls-ciphers{COLON} { YDVAR(1, VAR_TLS_CIPHERS) }
tls-ciphersuites{COLON} { YDVAR(1, VAR_TLS_CIPHERSUITES) }
https-port{COLON} { YDVAR(1, VAR_HTTPS_PORT) }
use-systemd{COLON} { YDVAR(1, VAR_USE_SYSTEMD) }
do-daemonize{COLON} { YDVAR(1, VAR_DO_DAEMONIZE) }
interface{COLON} { YDVAR(1, VAR_INTERFACE) }

File diff suppressed because it is too large Load diff

View file

@ -1,9 +1,8 @@
/* A Bison parser, made by GNU Bison 3.4.1. */
/* A Bison parser, made by GNU Bison 3.0.4. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
Inc.
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -31,9 +30,6 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* Undocumented macros, especially those whose name start with YY_,
are private implementation details. Do not rely on them. */
#ifndef YY_YY_UTIL_CONFIGPARSER_H_INCLUDED
# define YY_YY_UTIL_CONFIGPARSER_H_INCLUDED
/* Debug traces. */
@ -187,150 +183,151 @@ extern int yydebug;
VAR_STUB_SSL_UPSTREAM = 393,
VAR_FORWARD_SSL_UPSTREAM = 394,
VAR_TLS_CERT_BUNDLE = 395,
VAR_STUB_FIRST = 396,
VAR_MINIMAL_RESPONSES = 397,
VAR_RRSET_ROUNDROBIN = 398,
VAR_MAX_UDP_SIZE = 399,
VAR_DELAY_CLOSE = 400,
VAR_UNBLOCK_LAN_ZONES = 401,
VAR_INSECURE_LAN_ZONES = 402,
VAR_INFRA_CACHE_MIN_RTT = 403,
VAR_DNS64_PREFIX = 404,
VAR_DNS64_SYNTHALL = 405,
VAR_DNS64_IGNORE_AAAA = 406,
VAR_DNSTAP = 407,
VAR_DNSTAP_ENABLE = 408,
VAR_DNSTAP_SOCKET_PATH = 409,
VAR_DNSTAP_IP = 410,
VAR_DNSTAP_TLS = 411,
VAR_DNSTAP_TLS_SERVER_NAME = 412,
VAR_DNSTAP_TLS_CERT_BUNDLE = 413,
VAR_DNSTAP_TLS_CLIENT_KEY_FILE = 414,
VAR_DNSTAP_TLS_CLIENT_CERT_FILE = 415,
VAR_DNSTAP_SEND_IDENTITY = 416,
VAR_DNSTAP_SEND_VERSION = 417,
VAR_DNSTAP_IDENTITY = 418,
VAR_DNSTAP_VERSION = 419,
VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES = 420,
VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES = 421,
VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES = 422,
VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES = 423,
VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES = 424,
VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES = 425,
VAR_RESPONSE_IP_TAG = 426,
VAR_RESPONSE_IP = 427,
VAR_RESPONSE_IP_DATA = 428,
VAR_HARDEN_ALGO_DOWNGRADE = 429,
VAR_IP_TRANSPARENT = 430,
VAR_DISABLE_DNSSEC_LAME_CHECK = 431,
VAR_IP_RATELIMIT = 432,
VAR_IP_RATELIMIT_SLABS = 433,
VAR_IP_RATELIMIT_SIZE = 434,
VAR_RATELIMIT = 435,
VAR_RATELIMIT_SLABS = 436,
VAR_RATELIMIT_SIZE = 437,
VAR_RATELIMIT_FOR_DOMAIN = 438,
VAR_RATELIMIT_BELOW_DOMAIN = 439,
VAR_IP_RATELIMIT_FACTOR = 440,
VAR_RATELIMIT_FACTOR = 441,
VAR_SEND_CLIENT_SUBNET = 442,
VAR_CLIENT_SUBNET_ZONE = 443,
VAR_CLIENT_SUBNET_ALWAYS_FORWARD = 444,
VAR_CLIENT_SUBNET_OPCODE = 445,
VAR_MAX_CLIENT_SUBNET_IPV4 = 446,
VAR_MAX_CLIENT_SUBNET_IPV6 = 447,
VAR_MIN_CLIENT_SUBNET_IPV4 = 448,
VAR_MIN_CLIENT_SUBNET_IPV6 = 449,
VAR_MAX_ECS_TREE_SIZE_IPV4 = 450,
VAR_MAX_ECS_TREE_SIZE_IPV6 = 451,
VAR_CAPS_WHITELIST = 452,
VAR_CACHE_MAX_NEGATIVE_TTL = 453,
VAR_PERMIT_SMALL_HOLDDOWN = 454,
VAR_QNAME_MINIMISATION = 455,
VAR_QNAME_MINIMISATION_STRICT = 456,
VAR_IP_FREEBIND = 457,
VAR_DEFINE_TAG = 458,
VAR_LOCAL_ZONE_TAG = 459,
VAR_ACCESS_CONTROL_TAG = 460,
VAR_LOCAL_ZONE_OVERRIDE = 461,
VAR_ACCESS_CONTROL_TAG_ACTION = 462,
VAR_ACCESS_CONTROL_TAG_DATA = 463,
VAR_VIEW = 464,
VAR_ACCESS_CONTROL_VIEW = 465,
VAR_VIEW_FIRST = 466,
VAR_SERVE_EXPIRED = 467,
VAR_SERVE_EXPIRED_TTL = 468,
VAR_SERVE_EXPIRED_TTL_RESET = 469,
VAR_SERVE_EXPIRED_REPLY_TTL = 470,
VAR_SERVE_EXPIRED_CLIENT_TIMEOUT = 471,
VAR_FAKE_DSA = 472,
VAR_FAKE_SHA1 = 473,
VAR_LOG_IDENTITY = 474,
VAR_HIDE_TRUSTANCHOR = 475,
VAR_TRUST_ANCHOR_SIGNALING = 476,
VAR_AGGRESSIVE_NSEC = 477,
VAR_USE_SYSTEMD = 478,
VAR_SHM_ENABLE = 479,
VAR_SHM_KEY = 480,
VAR_ROOT_KEY_SENTINEL = 481,
VAR_DNSCRYPT = 482,
VAR_DNSCRYPT_ENABLE = 483,
VAR_DNSCRYPT_PORT = 484,
VAR_DNSCRYPT_PROVIDER = 485,
VAR_DNSCRYPT_SECRET_KEY = 486,
VAR_DNSCRYPT_PROVIDER_CERT = 487,
VAR_DNSCRYPT_PROVIDER_CERT_ROTATED = 488,
VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE = 489,
VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS = 490,
VAR_DNSCRYPT_NONCE_CACHE_SIZE = 491,
VAR_DNSCRYPT_NONCE_CACHE_SLABS = 492,
VAR_IPSECMOD_ENABLED = 493,
VAR_IPSECMOD_HOOK = 494,
VAR_IPSECMOD_IGNORE_BOGUS = 495,
VAR_IPSECMOD_MAX_TTL = 496,
VAR_IPSECMOD_WHITELIST = 497,
VAR_IPSECMOD_STRICT = 498,
VAR_CACHEDB = 499,
VAR_CACHEDB_BACKEND = 500,
VAR_CACHEDB_SECRETSEED = 501,
VAR_CACHEDB_REDISHOST = 502,
VAR_CACHEDB_REDISPORT = 503,
VAR_CACHEDB_REDISTIMEOUT = 504,
VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM = 505,
VAR_FOR_UPSTREAM = 506,
VAR_AUTH_ZONE = 507,
VAR_ZONEFILE = 508,
VAR_MASTER = 509,
VAR_URL = 510,
VAR_FOR_DOWNSTREAM = 511,
VAR_FALLBACK_ENABLED = 512,
VAR_TLS_ADDITIONAL_PORT = 513,
VAR_LOW_RTT = 514,
VAR_LOW_RTT_PERMIL = 515,
VAR_FAST_SERVER_PERMIL = 516,
VAR_FAST_SERVER_NUM = 517,
VAR_ALLOW_NOTIFY = 518,
VAR_TLS_WIN_CERT = 519,
VAR_TCP_CONNECTION_LIMIT = 520,
VAR_FORWARD_NO_CACHE = 521,
VAR_STUB_NO_CACHE = 522,
VAR_LOG_SERVFAIL = 523,
VAR_DENY_ANY = 524,
VAR_UNKNOWN_SERVER_TIME_LIMIT = 525,
VAR_LOG_TAG_QUERYREPLY = 526,
VAR_STREAM_WAIT_SIZE = 527,
VAR_TLS_CIPHERS = 528,
VAR_TLS_CIPHERSUITES = 529,
VAR_IPSET = 530,
VAR_IPSET_NAME_V4 = 531,
VAR_IPSET_NAME_V6 = 532,
VAR_TLS_SESSION_TICKET_KEYS = 533,
VAR_RPZ = 534,
VAR_TAGS = 535,
VAR_RPZ_ACTION_OVERRIDE = 536,
VAR_RPZ_CNAME_OVERRIDE = 537,
VAR_RPZ_LOG = 538,
VAR_RPZ_LOG_NAME = 539
VAR_HTTPS_PORT = 396,
VAR_STUB_FIRST = 397,
VAR_MINIMAL_RESPONSES = 398,
VAR_RRSET_ROUNDROBIN = 399,
VAR_MAX_UDP_SIZE = 400,
VAR_DELAY_CLOSE = 401,
VAR_UNBLOCK_LAN_ZONES = 402,
VAR_INSECURE_LAN_ZONES = 403,
VAR_INFRA_CACHE_MIN_RTT = 404,
VAR_DNS64_PREFIX = 405,
VAR_DNS64_SYNTHALL = 406,
VAR_DNS64_IGNORE_AAAA = 407,
VAR_DNSTAP = 408,
VAR_DNSTAP_ENABLE = 409,
VAR_DNSTAP_SOCKET_PATH = 410,
VAR_DNSTAP_IP = 411,
VAR_DNSTAP_TLS = 412,
VAR_DNSTAP_TLS_SERVER_NAME = 413,
VAR_DNSTAP_TLS_CERT_BUNDLE = 414,
VAR_DNSTAP_TLS_CLIENT_KEY_FILE = 415,
VAR_DNSTAP_TLS_CLIENT_CERT_FILE = 416,
VAR_DNSTAP_SEND_IDENTITY = 417,
VAR_DNSTAP_SEND_VERSION = 418,
VAR_DNSTAP_IDENTITY = 419,
VAR_DNSTAP_VERSION = 420,
VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES = 421,
VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES = 422,
VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES = 423,
VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES = 424,
VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES = 425,
VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES = 426,
VAR_RESPONSE_IP_TAG = 427,
VAR_RESPONSE_IP = 428,
VAR_RESPONSE_IP_DATA = 429,
VAR_HARDEN_ALGO_DOWNGRADE = 430,
VAR_IP_TRANSPARENT = 431,
VAR_DISABLE_DNSSEC_LAME_CHECK = 432,
VAR_IP_RATELIMIT = 433,
VAR_IP_RATELIMIT_SLABS = 434,
VAR_IP_RATELIMIT_SIZE = 435,
VAR_RATELIMIT = 436,
VAR_RATELIMIT_SLABS = 437,
VAR_RATELIMIT_SIZE = 438,
VAR_RATELIMIT_FOR_DOMAIN = 439,
VAR_RATELIMIT_BELOW_DOMAIN = 440,
VAR_IP_RATELIMIT_FACTOR = 441,
VAR_RATELIMIT_FACTOR = 442,
VAR_SEND_CLIENT_SUBNET = 443,
VAR_CLIENT_SUBNET_ZONE = 444,
VAR_CLIENT_SUBNET_ALWAYS_FORWARD = 445,
VAR_CLIENT_SUBNET_OPCODE = 446,
VAR_MAX_CLIENT_SUBNET_IPV4 = 447,
VAR_MAX_CLIENT_SUBNET_IPV6 = 448,
VAR_MIN_CLIENT_SUBNET_IPV4 = 449,
VAR_MIN_CLIENT_SUBNET_IPV6 = 450,
VAR_MAX_ECS_TREE_SIZE_IPV4 = 451,
VAR_MAX_ECS_TREE_SIZE_IPV6 = 452,
VAR_CAPS_WHITELIST = 453,
VAR_CACHE_MAX_NEGATIVE_TTL = 454,
VAR_PERMIT_SMALL_HOLDDOWN = 455,
VAR_QNAME_MINIMISATION = 456,
VAR_QNAME_MINIMISATION_STRICT = 457,
VAR_IP_FREEBIND = 458,
VAR_DEFINE_TAG = 459,
VAR_LOCAL_ZONE_TAG = 460,
VAR_ACCESS_CONTROL_TAG = 461,
VAR_LOCAL_ZONE_OVERRIDE = 462,
VAR_ACCESS_CONTROL_TAG_ACTION = 463,
VAR_ACCESS_CONTROL_TAG_DATA = 464,
VAR_VIEW = 465,
VAR_ACCESS_CONTROL_VIEW = 466,
VAR_VIEW_FIRST = 467,
VAR_SERVE_EXPIRED = 468,
VAR_SERVE_EXPIRED_TTL = 469,
VAR_SERVE_EXPIRED_TTL_RESET = 470,
VAR_SERVE_EXPIRED_REPLY_TTL = 471,
VAR_SERVE_EXPIRED_CLIENT_TIMEOUT = 472,
VAR_FAKE_DSA = 473,
VAR_FAKE_SHA1 = 474,
VAR_LOG_IDENTITY = 475,
VAR_HIDE_TRUSTANCHOR = 476,
VAR_TRUST_ANCHOR_SIGNALING = 477,
VAR_AGGRESSIVE_NSEC = 478,
VAR_USE_SYSTEMD = 479,
VAR_SHM_ENABLE = 480,
VAR_SHM_KEY = 481,
VAR_ROOT_KEY_SENTINEL = 482,
VAR_DNSCRYPT = 483,
VAR_DNSCRYPT_ENABLE = 484,
VAR_DNSCRYPT_PORT = 485,
VAR_DNSCRYPT_PROVIDER = 486,
VAR_DNSCRYPT_SECRET_KEY = 487,
VAR_DNSCRYPT_PROVIDER_CERT = 488,
VAR_DNSCRYPT_PROVIDER_CERT_ROTATED = 489,
VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE = 490,
VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS = 491,
VAR_DNSCRYPT_NONCE_CACHE_SIZE = 492,
VAR_DNSCRYPT_NONCE_CACHE_SLABS = 493,
VAR_IPSECMOD_ENABLED = 494,
VAR_IPSECMOD_HOOK = 495,
VAR_IPSECMOD_IGNORE_BOGUS = 496,
VAR_IPSECMOD_MAX_TTL = 497,
VAR_IPSECMOD_WHITELIST = 498,
VAR_IPSECMOD_STRICT = 499,
VAR_CACHEDB = 500,
VAR_CACHEDB_BACKEND = 501,
VAR_CACHEDB_SECRETSEED = 502,
VAR_CACHEDB_REDISHOST = 503,
VAR_CACHEDB_REDISPORT = 504,
VAR_CACHEDB_REDISTIMEOUT = 505,
VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM = 506,
VAR_FOR_UPSTREAM = 507,
VAR_AUTH_ZONE = 508,
VAR_ZONEFILE = 509,
VAR_MASTER = 510,
VAR_URL = 511,
VAR_FOR_DOWNSTREAM = 512,
VAR_FALLBACK_ENABLED = 513,
VAR_TLS_ADDITIONAL_PORT = 514,
VAR_LOW_RTT = 515,
VAR_LOW_RTT_PERMIL = 516,
VAR_FAST_SERVER_PERMIL = 517,
VAR_FAST_SERVER_NUM = 518,
VAR_ALLOW_NOTIFY = 519,
VAR_TLS_WIN_CERT = 520,
VAR_TCP_CONNECTION_LIMIT = 521,
VAR_FORWARD_NO_CACHE = 522,
VAR_STUB_NO_CACHE = 523,
VAR_LOG_SERVFAIL = 524,
VAR_DENY_ANY = 525,
VAR_UNKNOWN_SERVER_TIME_LIMIT = 526,
VAR_LOG_TAG_QUERYREPLY = 527,
VAR_STREAM_WAIT_SIZE = 528,
VAR_TLS_CIPHERS = 529,
VAR_TLS_CIPHERSUITES = 530,
VAR_IPSET = 531,
VAR_IPSET_NAME_V4 = 532,
VAR_IPSET_NAME_V6 = 533,
VAR_TLS_SESSION_TICKET_KEYS = 534,
VAR_RPZ = 535,
VAR_TAGS = 536,
VAR_RPZ_ACTION_OVERRIDE = 537,
VAR_RPZ_CNAME_OVERRIDE = 538,
VAR_RPZ_LOG = 539,
VAR_RPZ_LOG_NAME = 540
};
#endif
/* Tokens. */
@ -472,162 +469,164 @@ extern int yydebug;
#define VAR_STUB_SSL_UPSTREAM 393
#define VAR_FORWARD_SSL_UPSTREAM 394
#define VAR_TLS_CERT_BUNDLE 395
#define VAR_STUB_FIRST 396
#define VAR_MINIMAL_RESPONSES 397
#define VAR_RRSET_ROUNDROBIN 398
#define VAR_MAX_UDP_SIZE 399
#define VAR_DELAY_CLOSE 400
#define VAR_UNBLOCK_LAN_ZONES 401
#define VAR_INSECURE_LAN_ZONES 402
#define VAR_INFRA_CACHE_MIN_RTT 403
#define VAR_DNS64_PREFIX 404
#define VAR_DNS64_SYNTHALL 405
#define VAR_DNS64_IGNORE_AAAA 406
#define VAR_DNSTAP 407
#define VAR_DNSTAP_ENABLE 408
#define VAR_DNSTAP_SOCKET_PATH 409
#define VAR_DNSTAP_IP 410
#define VAR_DNSTAP_TLS 411
#define VAR_DNSTAP_TLS_SERVER_NAME 412
#define VAR_DNSTAP_TLS_CERT_BUNDLE 413
#define VAR_DNSTAP_TLS_CLIENT_KEY_FILE 414
#define VAR_DNSTAP_TLS_CLIENT_CERT_FILE 415
#define VAR_DNSTAP_SEND_IDENTITY 416
#define VAR_DNSTAP_SEND_VERSION 417
#define VAR_DNSTAP_IDENTITY 418
#define VAR_DNSTAP_VERSION 419
#define VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES 420
#define VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES 421
#define VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES 422
#define VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES 423
#define VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES 424
#define VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES 425
#define VAR_RESPONSE_IP_TAG 426
#define VAR_RESPONSE_IP 427
#define VAR_RESPONSE_IP_DATA 428
#define VAR_HARDEN_ALGO_DOWNGRADE 429
#define VAR_IP_TRANSPARENT 430
#define VAR_DISABLE_DNSSEC_LAME_CHECK 431
#define VAR_IP_RATELIMIT 432
#define VAR_IP_RATELIMIT_SLABS 433
#define VAR_IP_RATELIMIT_SIZE 434
#define VAR_RATELIMIT 435
#define VAR_RATELIMIT_SLABS 436
#define VAR_RATELIMIT_SIZE 437
#define VAR_RATELIMIT_FOR_DOMAIN 438
#define VAR_RATELIMIT_BELOW_DOMAIN 439
#define VAR_IP_RATELIMIT_FACTOR 440
#define VAR_RATELIMIT_FACTOR 441
#define VAR_SEND_CLIENT_SUBNET 442
#define VAR_CLIENT_SUBNET_ZONE 443
#define VAR_CLIENT_SUBNET_ALWAYS_FORWARD 444
#define VAR_CLIENT_SUBNET_OPCODE 445
#define VAR_MAX_CLIENT_SUBNET_IPV4 446
#define VAR_MAX_CLIENT_SUBNET_IPV6 447
#define VAR_MIN_CLIENT_SUBNET_IPV4 448
#define VAR_MIN_CLIENT_SUBNET_IPV6 449
#define VAR_MAX_ECS_TREE_SIZE_IPV4 450
#define VAR_MAX_ECS_TREE_SIZE_IPV6 451
#define VAR_CAPS_WHITELIST 452
#define VAR_CACHE_MAX_NEGATIVE_TTL 453
#define VAR_PERMIT_SMALL_HOLDDOWN 454
#define VAR_QNAME_MINIMISATION 455
#define VAR_QNAME_MINIMISATION_STRICT 456
#define VAR_IP_FREEBIND 457
#define VAR_DEFINE_TAG 458
#define VAR_LOCAL_ZONE_TAG 459
#define VAR_ACCESS_CONTROL_TAG 460
#define VAR_LOCAL_ZONE_OVERRIDE 461
#define VAR_ACCESS_CONTROL_TAG_ACTION 462
#define VAR_ACCESS_CONTROL_TAG_DATA 463
#define VAR_VIEW 464
#define VAR_ACCESS_CONTROL_VIEW 465
#define VAR_VIEW_FIRST 466
#define VAR_SERVE_EXPIRED 467
#define VAR_SERVE_EXPIRED_TTL 468
#define VAR_SERVE_EXPIRED_TTL_RESET 469
#define VAR_SERVE_EXPIRED_REPLY_TTL 470
#define VAR_SERVE_EXPIRED_CLIENT_TIMEOUT 471
#define VAR_FAKE_DSA 472
#define VAR_FAKE_SHA1 473
#define VAR_LOG_IDENTITY 474
#define VAR_HIDE_TRUSTANCHOR 475
#define VAR_TRUST_ANCHOR_SIGNALING 476
#define VAR_AGGRESSIVE_NSEC 477
#define VAR_USE_SYSTEMD 478
#define VAR_SHM_ENABLE 479
#define VAR_SHM_KEY 480
#define VAR_ROOT_KEY_SENTINEL 481
#define VAR_DNSCRYPT 482
#define VAR_DNSCRYPT_ENABLE 483
#define VAR_DNSCRYPT_PORT 484
#define VAR_DNSCRYPT_PROVIDER 485
#define VAR_DNSCRYPT_SECRET_KEY 486
#define VAR_DNSCRYPT_PROVIDER_CERT 487
#define VAR_DNSCRYPT_PROVIDER_CERT_ROTATED 488
#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE 489
#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS 490
#define VAR_DNSCRYPT_NONCE_CACHE_SIZE 491
#define VAR_DNSCRYPT_NONCE_CACHE_SLABS 492
#define VAR_IPSECMOD_ENABLED 493
#define VAR_IPSECMOD_HOOK 494
#define VAR_IPSECMOD_IGNORE_BOGUS 495
#define VAR_IPSECMOD_MAX_TTL 496
#define VAR_IPSECMOD_WHITELIST 497
#define VAR_IPSECMOD_STRICT 498
#define VAR_CACHEDB 499
#define VAR_CACHEDB_BACKEND 500
#define VAR_CACHEDB_SECRETSEED 501
#define VAR_CACHEDB_REDISHOST 502
#define VAR_CACHEDB_REDISPORT 503
#define VAR_CACHEDB_REDISTIMEOUT 504
#define VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM 505
#define VAR_FOR_UPSTREAM 506
#define VAR_AUTH_ZONE 507
#define VAR_ZONEFILE 508
#define VAR_MASTER 509
#define VAR_URL 510
#define VAR_FOR_DOWNSTREAM 511
#define VAR_FALLBACK_ENABLED 512
#define VAR_TLS_ADDITIONAL_PORT 513
#define VAR_LOW_RTT 514
#define VAR_LOW_RTT_PERMIL 515
#define VAR_FAST_SERVER_PERMIL 516
#define VAR_FAST_SERVER_NUM 517
#define VAR_ALLOW_NOTIFY 518
#define VAR_TLS_WIN_CERT 519
#define VAR_TCP_CONNECTION_LIMIT 520
#define VAR_FORWARD_NO_CACHE 521
#define VAR_STUB_NO_CACHE 522
#define VAR_LOG_SERVFAIL 523
#define VAR_DENY_ANY 524
#define VAR_UNKNOWN_SERVER_TIME_LIMIT 525
#define VAR_LOG_TAG_QUERYREPLY 526
#define VAR_STREAM_WAIT_SIZE 527
#define VAR_TLS_CIPHERS 528
#define VAR_TLS_CIPHERSUITES 529
#define VAR_IPSET 530
#define VAR_IPSET_NAME_V4 531
#define VAR_IPSET_NAME_V6 532
#define VAR_TLS_SESSION_TICKET_KEYS 533
#define VAR_RPZ 534
#define VAR_TAGS 535
#define VAR_RPZ_ACTION_OVERRIDE 536
#define VAR_RPZ_CNAME_OVERRIDE 537
#define VAR_RPZ_LOG 538
#define VAR_RPZ_LOG_NAME 539
#define VAR_HTTPS_PORT 396
#define VAR_STUB_FIRST 397
#define VAR_MINIMAL_RESPONSES 398
#define VAR_RRSET_ROUNDROBIN 399
#define VAR_MAX_UDP_SIZE 400
#define VAR_DELAY_CLOSE 401
#define VAR_UNBLOCK_LAN_ZONES 402
#define VAR_INSECURE_LAN_ZONES 403
#define VAR_INFRA_CACHE_MIN_RTT 404
#define VAR_DNS64_PREFIX 405
#define VAR_DNS64_SYNTHALL 406
#define VAR_DNS64_IGNORE_AAAA 407
#define VAR_DNSTAP 408
#define VAR_DNSTAP_ENABLE 409
#define VAR_DNSTAP_SOCKET_PATH 410
#define VAR_DNSTAP_IP 411
#define VAR_DNSTAP_TLS 412
#define VAR_DNSTAP_TLS_SERVER_NAME 413
#define VAR_DNSTAP_TLS_CERT_BUNDLE 414
#define VAR_DNSTAP_TLS_CLIENT_KEY_FILE 415
#define VAR_DNSTAP_TLS_CLIENT_CERT_FILE 416
#define VAR_DNSTAP_SEND_IDENTITY 417
#define VAR_DNSTAP_SEND_VERSION 418
#define VAR_DNSTAP_IDENTITY 419
#define VAR_DNSTAP_VERSION 420
#define VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES 421
#define VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES 422
#define VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES 423
#define VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES 424
#define VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES 425
#define VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES 426
#define VAR_RESPONSE_IP_TAG 427
#define VAR_RESPONSE_IP 428
#define VAR_RESPONSE_IP_DATA 429
#define VAR_HARDEN_ALGO_DOWNGRADE 430
#define VAR_IP_TRANSPARENT 431
#define VAR_DISABLE_DNSSEC_LAME_CHECK 432
#define VAR_IP_RATELIMIT 433
#define VAR_IP_RATELIMIT_SLABS 434
#define VAR_IP_RATELIMIT_SIZE 435
#define VAR_RATELIMIT 436
#define VAR_RATELIMIT_SLABS 437
#define VAR_RATELIMIT_SIZE 438
#define VAR_RATELIMIT_FOR_DOMAIN 439
#define VAR_RATELIMIT_BELOW_DOMAIN 440
#define VAR_IP_RATELIMIT_FACTOR 441
#define VAR_RATELIMIT_FACTOR 442
#define VAR_SEND_CLIENT_SUBNET 443
#define VAR_CLIENT_SUBNET_ZONE 444
#define VAR_CLIENT_SUBNET_ALWAYS_FORWARD 445
#define VAR_CLIENT_SUBNET_OPCODE 446
#define VAR_MAX_CLIENT_SUBNET_IPV4 447
#define VAR_MAX_CLIENT_SUBNET_IPV6 448
#define VAR_MIN_CLIENT_SUBNET_IPV4 449
#define VAR_MIN_CLIENT_SUBNET_IPV6 450
#define VAR_MAX_ECS_TREE_SIZE_IPV4 451
#define VAR_MAX_ECS_TREE_SIZE_IPV6 452
#define VAR_CAPS_WHITELIST 453
#define VAR_CACHE_MAX_NEGATIVE_TTL 454
#define VAR_PERMIT_SMALL_HOLDDOWN 455
#define VAR_QNAME_MINIMISATION 456
#define VAR_QNAME_MINIMISATION_STRICT 457
#define VAR_IP_FREEBIND 458
#define VAR_DEFINE_TAG 459
#define VAR_LOCAL_ZONE_TAG 460
#define VAR_ACCESS_CONTROL_TAG 461
#define VAR_LOCAL_ZONE_OVERRIDE 462
#define VAR_ACCESS_CONTROL_TAG_ACTION 463
#define VAR_ACCESS_CONTROL_TAG_DATA 464
#define VAR_VIEW 465
#define VAR_ACCESS_CONTROL_VIEW 466
#define VAR_VIEW_FIRST 467
#define VAR_SERVE_EXPIRED 468
#define VAR_SERVE_EXPIRED_TTL 469
#define VAR_SERVE_EXPIRED_TTL_RESET 470
#define VAR_SERVE_EXPIRED_REPLY_TTL 471
#define VAR_SERVE_EXPIRED_CLIENT_TIMEOUT 472
#define VAR_FAKE_DSA 473
#define VAR_FAKE_SHA1 474
#define VAR_LOG_IDENTITY 475
#define VAR_HIDE_TRUSTANCHOR 476
#define VAR_TRUST_ANCHOR_SIGNALING 477
#define VAR_AGGRESSIVE_NSEC 478
#define VAR_USE_SYSTEMD 479
#define VAR_SHM_ENABLE 480
#define VAR_SHM_KEY 481
#define VAR_ROOT_KEY_SENTINEL 482
#define VAR_DNSCRYPT 483
#define VAR_DNSCRYPT_ENABLE 484
#define VAR_DNSCRYPT_PORT 485
#define VAR_DNSCRYPT_PROVIDER 486
#define VAR_DNSCRYPT_SECRET_KEY 487
#define VAR_DNSCRYPT_PROVIDER_CERT 488
#define VAR_DNSCRYPT_PROVIDER_CERT_ROTATED 489
#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE 490
#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS 491
#define VAR_DNSCRYPT_NONCE_CACHE_SIZE 492
#define VAR_DNSCRYPT_NONCE_CACHE_SLABS 493
#define VAR_IPSECMOD_ENABLED 494
#define VAR_IPSECMOD_HOOK 495
#define VAR_IPSECMOD_IGNORE_BOGUS 496
#define VAR_IPSECMOD_MAX_TTL 497
#define VAR_IPSECMOD_WHITELIST 498
#define VAR_IPSECMOD_STRICT 499
#define VAR_CACHEDB 500
#define VAR_CACHEDB_BACKEND 501
#define VAR_CACHEDB_SECRETSEED 502
#define VAR_CACHEDB_REDISHOST 503
#define VAR_CACHEDB_REDISPORT 504
#define VAR_CACHEDB_REDISTIMEOUT 505
#define VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM 506
#define VAR_FOR_UPSTREAM 507
#define VAR_AUTH_ZONE 508
#define VAR_ZONEFILE 509
#define VAR_MASTER 510
#define VAR_URL 511
#define VAR_FOR_DOWNSTREAM 512
#define VAR_FALLBACK_ENABLED 513
#define VAR_TLS_ADDITIONAL_PORT 514
#define VAR_LOW_RTT 515
#define VAR_LOW_RTT_PERMIL 516
#define VAR_FAST_SERVER_PERMIL 517
#define VAR_FAST_SERVER_NUM 518
#define VAR_ALLOW_NOTIFY 519
#define VAR_TLS_WIN_CERT 520
#define VAR_TCP_CONNECTION_LIMIT 521
#define VAR_FORWARD_NO_CACHE 522
#define VAR_STUB_NO_CACHE 523
#define VAR_LOG_SERVFAIL 524
#define VAR_DENY_ANY 525
#define VAR_UNKNOWN_SERVER_TIME_LIMIT 526
#define VAR_LOG_TAG_QUERYREPLY 527
#define VAR_STREAM_WAIT_SIZE 528
#define VAR_TLS_CIPHERS 529
#define VAR_TLS_CIPHERSUITES 530
#define VAR_IPSET 531
#define VAR_IPSET_NAME_V4 532
#define VAR_IPSET_NAME_V6 533
#define VAR_TLS_SESSION_TICKET_KEYS 534
#define VAR_RPZ 535
#define VAR_TAGS 536
#define VAR_RPZ_ACTION_OVERRIDE 537
#define VAR_RPZ_CNAME_OVERRIDE 538
#define VAR_RPZ_LOG 539
#define VAR_RPZ_LOG_NAME 540
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
union YYSTYPE
{
#line 66 "./util/configparser.y"
#line 66 "./util/configparser.y" /* yacc.c:1909 */
char* str;
#line 629 "util/configparser.h"
#line 628 "util/configparser.h" /* yacc.c:1909 */
};
typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1

View file

@ -111,6 +111,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_TCP_UPSTREAM VAR_SSL_UPSTREAM
%token VAR_SSL_SERVICE_KEY VAR_SSL_SERVICE_PEM VAR_SSL_PORT VAR_FORWARD_FIRST
%token VAR_STUB_SSL_UPSTREAM VAR_FORWARD_SSL_UPSTREAM VAR_TLS_CERT_BUNDLE
%token VAR_HTTPS_PORT
%token VAR_STUB_FIRST VAR_MINIMAL_RESPONSES VAR_RRSET_ROUNDROBIN
%token VAR_MAX_UDP_SIZE VAR_DELAY_CLOSE
%token VAR_UNBLOCK_LAN_ZONES VAR_INSECURE_LAN_ZONES
@ -235,6 +236,7 @@ content_server: server_num_threads | server_verbosity | server_port |
server_log_queries | server_log_replies | server_tcp_upstream | server_ssl_upstream |
server_log_local_actions |
server_ssl_service_key | server_ssl_service_pem | server_ssl_port |
server_https_port |
server_minimal_responses | server_rrset_roundrobin | server_max_udp_size |
server_so_reuseport | server_delay_close |
server_unblock_lan_zones | server_insecure_lan_zones |
@ -949,6 +951,15 @@ server_tls_session_ticket_keys: VAR_TLS_SESSION_TICKET_KEYS STRING_ARG
yyerror("out of memory");
}
;
server_https_port: VAR_HTTPS_PORT STRING_ARG
{
OUTYY(("P(server_https_port:%s)\n", $2));
if(atoi($2) == 0)
yyerror("port number expected");
else cfg_parser->cfg->https_port = atoi($2);
free($2);
}
;
server_use_systemd: VAR_USE_SYSTEMD STRING_ARG
{
OUTYY(("P(server_use_systemd:%s)\n", $2));

View file

@ -3771,6 +3771,7 @@
4188,
4191,
4192,
4195,
4197,
4199,
4300,

View file

@ -58,6 +58,9 @@
#ifdef USE_WINSOCK
#include <wincrypt.h>
#endif
#ifdef HAVE_NGHTTP2_NGHTTP2_H
#include <nghttp2/nghttp2.h>
#endif
/** max length of an IP address (the address portion) that we allow */
#define MAX_ADDR_STRLEN 128 /* characters */
@ -855,6 +858,21 @@ log_cert(unsigned level, const char* str, void* cert)
}
#endif /* HAVE_SSL */
#if defined(HAVE_SSL) && defined(HAVE_NGHTTP2)
static int alpn_select_cb(SSL* ATTR_UNUSED(ssl), const unsigned char** out,
unsigned char* outlen, const unsigned char* in, unsigned int inlen,
void* ATTR_UNUSED(arg))
{
int rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in,
inlen);
if(rv == -1) {
return SSL_TLSEXT_ERR_NOACK;
}
/* either http/1.1 or h2 selected */
return SSL_TLSEXT_ERR_OK;
}
#endif
int
listen_sslctx_setup(void* ctxt)
{
@ -913,6 +931,9 @@ listen_sslctx_setup(void* ctxt)
#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
SSL_CTX_set_security_level(ctx, 0);
#endif
#if defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB) && defined(HAVE_NGHTTP2)
SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb, NULL);
#endif
#else
(void)ctxt;
#endif /* HAVE_SSL */

View file

@ -733,7 +733,7 @@ static void
setup_tcp_handler(struct comm_point* c, int fd, int cur, int max)
{
int handler_usage;
log_assert(c->type == comm_tcp);
log_assert(c->type == comm_tcp || c->type == comm_http);
log_assert(c->fd == -1);
sldns_buffer_clear(c->buffer);
#ifdef USE_DNSCRYPT
@ -908,6 +908,41 @@ comm_point_tcp_win_bio_cb(struct comm_point* c, void* thessl)
}
#endif
#ifdef HAVE_NGHTTP2
/** Create http2 session server. Per connection, after TCP accepted.*/
static int http2_session_server_create(struct http2_session* h2_session)
{
log_assert(h2_session->callbacks);
h2_session->is_drop = 0;
if(nghttp2_session_server_new(&h2_session->session,
h2_session->callbacks,
h2_session) == NGHTTP2_ERR_NOMEM) {
log_err("failed to create nghttp2 session server");
return 0;
}
return 1;
}
/** Submit http2 setting to session. Once per session. */
static int http2_submit_settings(struct http2_session* h2_session)
{
int ret;
nghttp2_settings_entry settings[1] = {
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
ret = nghttp2_submit_settings(h2_session->session, NGHTTP2_FLAG_NONE,
settings, 1);
if(ret) {
verbose(VERB_QUERY, "http2: submit_settings failed, "
"error: %s", nghttp2_strerror(ret));
return 0;
}
return 1;
}
#endif /* HAVE_NGHTTP2 */
void
comm_point_tcp_accept_callback(int fd, short event, void* arg)
{
@ -929,7 +964,28 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg)
/* clear leftover flags from previous use, and then set the
* correct event base for the event structure for libevent */
ub_event_free(c_hdl->ev->ev);
c_hdl->ev->ev = ub_event_new(c_hdl->ev->base->eb->base, -1, UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT, comm_point_tcp_handle_callback, c_hdl);
#ifdef HAVE_NGHTTP2
if(c_hdl->type == comm_http && c_hdl->h2_session) {
if(!http2_session_server_create(c_hdl->h2_session)) {
log_warn("failed to create nghttp2");
return;
}
if(!http2_submit_settings(c_hdl->h2_session)) {
log_warn("failed to submit http2 settings");
return;
}
c_hdl->ev->ev = ub_event_new(c_hdl->ev->base->eb->base, -1,
UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT,
comm_point_http_handle_callback, c_hdl);
} else {
#endif
c_hdl->ev->ev = ub_event_new(c_hdl->ev->base->eb->base, -1,
UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT,
comm_point_tcp_handle_callback, c_hdl);
#ifdef HAVE_NGHTTP2
}
#endif
if(!c_hdl->ev->ev) {
log_warn("could not ub_event_new, dropped tcp");
return;
@ -1163,6 +1219,18 @@ ssl_handshake(struct comm_point* c)
c->repinfo.addrlen);
}
/* check if http2 use is negotiated */
if(c->type == comm_http && c->h2_session) {
const unsigned char *alpn;
unsigned int alpnlen = 0;
SSL_get0_alpn_selected(c->ssl, &alpn, &alpnlen);
if(alpnlen == 2 && memcmp("h2", alpn, 2) == 0) {
/* connection upgraded to HTTP2 */
c->tcp_do_toggle_rw = 0;
c->alpn_h2 = 1;
}
}
/* setup listen rw correctly */
if(c->tcp_is_reading) {
if(c->ssl_shake_state != comm_ssl_shake_read)
@ -2180,11 +2248,210 @@ http_chunked_segment(struct comm_point* c)
return 1;
}
#ifdef HAVE_NGHTTP2
/** Create new http2 session. Called when creating handling comm point. */
struct http2_session* http2_session_create(struct comm_point* c)
{
struct http2_session* session = calloc(1, sizeof(*session));
if(!session) {
log_err("malloc failure while creating http2 session");
return NULL;
}
session->c = c;
return session;
}
#endif
/** Delete http2 session. After closing connection or on error */
void http2_session_delete(struct http2_session* h2_session)
{
#ifdef HAVE_NGHTTP2
if(h2_session->callbacks)
nghttp2_session_callbacks_del(h2_session->callbacks);
free(h2_session);
#else
(void)h2_session;
#endif
}
#ifdef HAVE_NGHTTP2
struct http2_stream* http2_stream_create(int32_t stream_id)
{
struct http2_stream* h2_stream = calloc(1, sizeof(*h2_stream));
if(!h2_stream) {
log_err("malloc failure while creating http2 stream");
return NULL;
}
h2_stream->stream_id = stream_id;
return h2_stream;
}
/** Delete http2 stream. After session delete or stream close callback */
void http2_stream_delete(struct http2_session* h2_session,
struct http2_stream* h2_stream)
{
if(h2_stream->mesh_state) {
mesh_state_remove_reply(h2_stream->mesh, h2_stream->mesh_state,
h2_session->c);
}
if(h2_stream->qbuffer)
sldns_buffer_free(h2_stream->qbuffer);
if(h2_stream->rbuffer)
sldns_buffer_free(h2_stream->rbuffer);
free(h2_stream);
}
#endif
void http2_stream_add_meshstate(struct http2_stream* h2_stream,
struct mesh_area* mesh, struct mesh_state* m)
{
h2_stream->mesh = mesh;
h2_stream->mesh_state = m;
}
/** delete http2 session server. After closing connection. */
static void http2_session_server_delete(struct http2_session* h2_session)
{
#ifdef HAVE_NGHTTP2
struct http2_stream* h2_stream, *next;
nghttp2_session_del(h2_session->session); /* NULL input is fine */
h2_session->session = NULL;
for(h2_stream = h2_session->first_stream; h2_stream;) {
next = h2_stream->next;
http2_stream_delete(h2_session, h2_stream);
h2_stream = next;
}
h2_session->first_stream = NULL;
h2_session->is_drop = 0;
h2_session->postpone_drop = 0;
h2_session->c->h2_stream = NULL;
#endif
(void)h2_session;
}
#ifdef HAVE_NGHTTP2
void http2_session_add_stream(struct http2_session* h2_session,
struct http2_stream* h2_stream)
{
if(h2_session->first_stream)
h2_session->first_stream->prev = h2_stream;
h2_stream->next = h2_session->first_stream;
h2_session->first_stream = h2_stream;
}
/** remove stream from session linked list. After stream close callback or
* closing connection */
void http2_session_remove_stream(struct http2_session* h2_session,
struct http2_stream* h2_stream)
{
if(h2_stream->prev)
h2_stream->prev->next = h2_stream->next;
else
h2_session->first_stream = h2_stream->next;
if(h2_stream->next)
h2_stream->next->prev = h2_stream->prev;
}
int http2_stream_close_cb(nghttp2_session* ATTR_UNUSED(session),
int32_t stream_id, uint32_t ATTR_UNUSED(error_code), void* cb_arg)
{
struct http2_stream* h2_stream;
struct http2_session* h2_session = (struct http2_session*)cb_arg;
if(!(h2_stream = nghttp2_session_get_stream_user_data(
h2_session->session, stream_id))) {
return 0;
}
http2_session_remove_stream(h2_session, h2_stream);
http2_stream_delete(h2_session, h2_stream);
return 0;
}
ssize_t http2_recv_cb(nghttp2_session* ATTR_UNUSED(session), uint8_t* buf,
size_t len, int ATTR_UNUSED(flags), void* cb_arg)
{
#ifdef HAVE_SSL
struct http2_session* h2_session = (struct http2_session*)cb_arg;
int r;
log_assert(h2_session->c->type == comm_http);
log_assert(h2_session->c->h2_session);
if(!h2_session->c->ssl)
return 0;
ERR_clear_error();
r = SSL_read(h2_session->c->ssl, buf, len);
if(r <= 0) {
int want = SSL_get_error(h2_session->c->ssl, r);
if(want == SSL_ERROR_ZERO_RETURN) {
return NGHTTP2_ERR_EOF;
} else if(want == SSL_ERROR_WANT_READ) {
return NGHTTP2_ERR_WOULDBLOCK;
} else if(want == SSL_ERROR_WANT_WRITE) {
h2_session->c->ssl_shake_state = comm_ssl_shake_hs_write;
comm_point_listen_for_rw(h2_session->c, 0, 1);
return NGHTTP2_ERR_WOULDBLOCK;
} else if(want == SSL_ERROR_SYSCALL) {
#ifdef ECONNRESET
if(errno == ECONNRESET && verbosity < 2)
return NGHTTP2_ERR_CALLBACK_FAILURE;
#endif
if(errno != 0)
log_err("SSL_read syscall: %s",
strerror(errno));
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
log_crypto_err("could not SSL_read");
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
return r;
#else
(void)buf;
(void)len;
(void)cb_arg;
return -1;
#endif
}
#endif /* HAVE_NGHTTP2 */
/** Handle http2 read */
static int
comm_point_http2_handle_read(int ATTR_UNUSED(fd), struct comm_point* c)
{
#ifdef HAVE_NGHTTP2
int ret;
log_assert(c->h2_session);
log_assert(c->ssl);
/* reading until recv cb returns NGHTTP2_ERR_WOULDBLOCK */
ret = nghttp2_session_recv(c->h2_session->session);
if(ret) {
if(ret != NGHTTP2_ERR_EOF) {
verbose(VERB_QUERY, "http2: session_recv failed, "
"error: %s", nghttp2_strerror(ret));
}
return 0;
}
if(nghttp2_session_want_write(c->h2_session->session)) {
c->tcp_is_reading = 0;
comm_point_stop_listening(c);
comm_point_start_listening(c, -1, c->tcp_timeout_msec);
} else if(!nghttp2_session_want_read(c->h2_session->session))
return 0; /* connection can be closed */
return 1;
#else
(void)c;
return 0;
#endif
}
/**
* Handle http reading callback.
* Handle http reading callback.
* @param fd: file descriptor of socket.
* @param c: comm point to read from into buffer.
* @return: 0 on error
* @return: 0 on error
*/
static int
comm_point_http_handle_read(int fd, struct comm_point* c)
@ -2204,6 +2471,18 @@ comm_point_http_handle_read(int fd, struct comm_point* c)
if(!c->tcp_is_reading)
return 1;
if(c->alpn_h2) {
return comm_point_http2_handle_read(fd, c);
}
/* http version is <= http/1.1 */
if(c->http_min_version >= http_version_2) {
/* HTTP/2 failed, not allowed to use lower version. */
return 0;
}
/* read more data */
if(c->ssl) {
if(!ssl_http_read_more(c))
@ -2214,7 +2493,9 @@ comm_point_http_handle_read(int fd, struct comm_point* c)
}
sldns_buffer_flip(c->buffer);
while(sldns_buffer_remaining(c->buffer) > 0) {
/* Handle HTTP/1.x data */
/* if we are reading headers, read more headers */
if(c->http_in_headers || c->http_in_chunk_headers) {
/* if header is done, process the header */
@ -2376,6 +2657,83 @@ http_write_more(int fd, struct comm_point* c)
return 1;
}
#ifdef HAVE_NGHTTP2
ssize_t http2_send_cb(nghttp2_session* ATTR_UNUSED(session), const uint8_t* buf,
size_t len, int ATTR_UNUSED(flags), void* cb_arg)
{
#ifdef HAVE_SSL
int r;
struct http2_session* h2_session = (struct http2_session*)cb_arg;
log_assert(h2_session->c->type == comm_http);
log_assert(h2_session->c->h2_session);
if(!h2_session->c->ssl)
return 0;
ERR_clear_error();
r = SSL_write(h2_session->c->ssl, buf, len);
if(r <= 0) {
int want = SSL_get_error(h2_session->c->ssl, r);
if(want == SSL_ERROR_ZERO_RETURN) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
} else if(want == SSL_ERROR_WANT_READ) {
h2_session->c->ssl_shake_state = comm_ssl_shake_hs_read;
comm_point_listen_for_rw(h2_session->c, 1, 0);
return NGHTTP2_ERR_WOULDBLOCK;
} else if(want == SSL_ERROR_WANT_WRITE) {
return NGHTTP2_ERR_WOULDBLOCK;
} else if(want == SSL_ERROR_SYSCALL) {
#ifdef EPIPE
if(errno == EPIPE && verbosity < 2)
return NGHTTP2_ERR_CALLBACK_FAILURE;
#endif
if(errno != 0)
log_err("SSL_write syscall: %s",
strerror(errno));
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
log_crypto_err("could not SSL_write");
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
return r;
#else
(void)buf;
(void)len;
(void)cb_arg;
return -1;
#endif
}
#endif /* HAVE_NGHTTP2 */
/** Handle http2 writing */
static int
comm_point_http2_handle_write(int ATTR_UNUSED(fd), struct comm_point* c)
{
#ifdef HAVE_NGHTTP2
int ret;
log_assert(c->h2_session);
log_assert(c->ssl);
ret = nghttp2_session_send(c->h2_session->session);
if(ret) {
verbose(VERB_QUERY, "http2: session_send failed, "
"error: %s", nghttp2_strerror(ret));
return 0;
}
if(nghttp2_session_want_read(c->h2_session->session)) {
c->tcp_is_reading = 1;
comm_point_stop_listening(c);
comm_point_start_listening(c, -1, c->tcp_timeout_msec);
} else if(!nghttp2_session_want_write(c->h2_session->session))
return 0; /* connection can be closed */
return 1;
#else
(void)c;
return 0;
#endif
}
/**
* Handle http writing callback.
* @param fd: file descriptor of socket.
@ -2407,6 +2765,18 @@ comm_point_http_handle_write(int fd, struct comm_point* c)
#endif /* HAVE_SSL */
if(c->tcp_is_reading)
return 1;
if(c->alpn_h2) {
return comm_point_http2_handle_write(fd, c);
}
/* http version is <= http/1.1 */
if(c->http_min_version >= http_version_2) {
/* HTTP/2 failed, not allowed to use lower version. */
return 0;
}
/* if we are writing, write more */
if(c->ssl) {
if(!ssl_http_write_more(c))
@ -2718,11 +3088,116 @@ comm_point_create_tcp_handler(struct comm_base *base,
return c;
}
static struct comm_point*
comm_point_create_http_handler(struct comm_base *base,
struct comm_point* parent, size_t bufsize, int harden_large_queries,
comm_point_callback_type* callback, void* callback_arg)
{
struct comm_point* c = (struct comm_point*)calloc(1,
sizeof(struct comm_point));
short evbits;
if(!c)
return NULL;
c->ev = (struct internal_event*)calloc(1,
sizeof(struct internal_event));
if(!c->ev) {
free(c);
return NULL;
}
c->ev->base = base;
c->fd = -1;
c->buffer = sldns_buffer_new(bufsize);
if(!c->buffer) {
free(c->ev);
free(c);
return NULL;
}
c->timeout = (struct timeval*)malloc(sizeof(struct timeval));
if(!c->timeout) {
sldns_buffer_free(c->buffer);
free(c->ev);
free(c);
return NULL;
}
c->tcp_is_reading = 0;
c->tcp_byte_count = 0;
c->tcp_parent = parent;
c->tcp_timeout_msec = parent->tcp_timeout_msec;
c->tcp_conn_limit = parent->tcp_conn_limit;
c->tcl_addr = NULL;
c->tcp_keepalive = 0;
c->max_tcp_count = 0;
c->cur_tcp_count = 0;
c->tcp_handlers = NULL;
c->tcp_free = NULL;
c->type = comm_http;
c->tcp_do_close = 1;
c->do_not_close = 0;
c->tcp_do_toggle_rw = 1; /* will be set to 0 after http2 upgrade */
c->tcp_check_nb_connect = 0;
#ifdef USE_MSG_FASTOPEN
c->tcp_do_fastopen = 0;
#endif
#ifdef USE_DNSCRYPT
c->dnscrypt = 0;
c->dnscrypt_buffer = NULL;
#endif
c->repinfo.c = c;
c->callback = callback;
c->cb_arg = callback_arg;
c->http_min_version = http_version_2;
c->http2_max_qbuffer_size = bufsize;
if(harden_large_queries && bufsize > 512)
c->http2_max_qbuffer_size = 512;
c->alpn_h2 = 0;
#ifdef HAVE_NGHTTP2
if(!(c->h2_session = http2_session_create(c))) {
log_err("could not create http2 session");
sldns_buffer_free(c->buffer);
free(c->timeout);
free(c->ev);
free(c);
return NULL;
}
if(!(c->h2_session->callbacks = http2_req_callbacks_create())) {
log_err("could not create http2 callbacks");
http2_session_delete(c->h2_session);
sldns_buffer_free(c->buffer);
free(c->timeout);
free(c->ev);
free(c);
return NULL;
}
#endif
/* add to parent free list */
c->tcp_free = parent->tcp_free;
parent->tcp_free = c;
/* ub_event stuff */
evbits = UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT;
c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
comm_point_http_handle_callback, c);
if(c->ev->ev == NULL)
{
log_err("could not set http handler event");
parent->tcp_free = c->tcp_free;
http2_session_delete(c->h2_session);
sldns_buffer_free(c->buffer);
free(c->timeout);
free(c->ev);
free(c);
return NULL;
}
return c;
}
struct comm_point*
comm_point_create_tcp(struct comm_base *base, int fd, int num,
int idle_timeout, struct tcl_list* tcp_conn_limit, size_t bufsize,
struct sldns_buffer* spoolbuf, comm_point_callback_type* callback,
void* callback_arg)
int idle_timeout, int harden_large_queries,
struct tcl_list* tcp_conn_limit, size_t bufsize,
struct sldns_buffer* spoolbuf, enum listen_type port_type,
comm_point_callback_type* callback, void* callback_arg)
{
struct comm_point* c = (struct comm_point*)calloc(1,
sizeof(struct comm_point));
@ -2786,10 +3261,23 @@ comm_point_create_tcp(struct comm_base *base, int fd, int num,
comm_point_delete(c);
return NULL;
}
/* now prealloc the tcp handlers */
/* now prealloc the handlers */
for(i=0; i<num; i++) {
c->tcp_handlers[i] = comm_point_create_tcp_handler(base,
c, bufsize, spoolbuf, callback, callback_arg);
if(port_type == listen_type_tcp ||
port_type == listen_type_ssl ||
port_type == listen_type_tcp_dnscrypt) {
c->tcp_handlers[i] = comm_point_create_tcp_handler(base,
c, bufsize, spoolbuf, callback, callback_arg);
} else if(port_type == listen_type_http) {
c->tcp_handlers[i] = comm_point_create_http_handler(
base, c, bufsize, harden_large_queries,
callback, callback_arg);
}
else {
log_err("could not create tcp handler, unknown listen "
"type");
return NULL;
}
if(!c->tcp_handlers[i]) {
comm_point_delete(c);
return NULL;
@ -3073,6 +3561,9 @@ comm_point_close(struct comm_point* c)
tcl_close_connection(c->tcl_addr);
if(c->tcp_req_info)
tcp_req_info_clear(c->tcp_req_info);
if(c->h2_session)
http2_session_server_delete(c->h2_session);
/* close fd after removing from event lists, or epoll.. is messed up */
if(c->fd != -1 && !c->do_not_close) {
if(c->type == comm_tcp || c->type == comm_http) {
@ -3119,6 +3610,9 @@ comm_point_delete(struct comm_point* c)
if(c->tcp_req_info) {
tcp_req_info_delete(c->tcp_req_info);
}
if(c->h2_session) {
http2_session_delete(c->h2_session);
}
}
ub_event_free(c->ev->ev);
free(c->ev);
@ -3161,6 +3655,17 @@ comm_point_send_reply(struct comm_reply *repinfo)
#endif
if(repinfo->c->tcp_req_info) {
tcp_req_info_send_reply(repinfo->c->tcp_req_info);
} else if(repinfo->c->alpn_h2) {
if(!http2_submit_dns_response(repinfo->c->h2_session)) {
comm_point_drop_reply(repinfo);
return;
}
repinfo->c->h2_stream = NULL;
repinfo->c->tcp_is_reading = 0;
comm_point_stop_listening(repinfo->c);
comm_point_start_listening(repinfo->c, -1,
repinfo->c->tcp_timeout_msec);
return;
} else {
comm_point_start_listening(repinfo->c, -1,
repinfo->c->tcp_timeout_msec);
@ -3179,6 +3684,16 @@ comm_point_drop_reply(struct comm_reply* repinfo)
return;
if(repinfo->c->tcp_req_info)
repinfo->c->tcp_req_info->is_drop = 1;
if(repinfo->c->type == comm_http) {
if(repinfo->c->h2_session) {
repinfo->c->h2_session->is_drop = 1;
if(!repinfo->c->h2_session->postpone_drop)
reclaim_http_handler(repinfo->c);
return;
}
reclaim_http_handler(repinfo->c);
return;
}
reclaim_tcp_handler(repinfo->c);
}

View file

@ -61,6 +61,9 @@
#define NET_EVENT_H
#include "dnscrypt/dnscrypt.h"
#ifdef HAVE_NGHTTP2_NGHTTP2_H
#include <nghttp2/nghttp2.h>
#endif
struct sldns_buffer;
struct comm_point;
@ -68,11 +71,16 @@ struct comm_reply;
struct tcl_list;
struct ub_event_base;
struct mesh_state;
struct mesh_area;
/* internal event notification data storage structure. */
struct internal_event;
struct internal_base;
struct internal_timer; /* A sub struct of the comm_timer super struct */
enum listen_type;
/** callback from communication point function type */
typedef int comm_point_callback_type(struct comm_point*, void*, int,
struct comm_reply*);
@ -205,6 +213,13 @@ struct comm_point {
} ssl_shake_state;
/* -------- HTTP ------- */
/** Do not allow connection to use HTTP version lower than this. 0=no
* minimum. */
enum {
http_version_none = 0,
http_version_2 = 2
} http_min_version;
/* -------- HTTP/1.1 ------- */
/** Currently reading in http headers */
int http_in_headers;
/** Currently reading in chunk headers, 0=not, 1=firstline, 2=unused
@ -216,6 +231,15 @@ struct comm_point {
struct sldns_buffer* http_temp;
/** http stored content in buffer */
size_t http_stored;
/* -------- HTTP/2 ------- */
/** http2 session */
struct http2_session* h2_session;
/** set to 1 if h2 is negatiated using alpn */
int alpn_h2;
/** maximum allowed query buffer size */
size_t http2_max_qbuffer_size;
/** stream currently being handled */
struct http2_stream* h2_stream;
/* -------- dnstap ------- */
/** the dnstap environment */
@ -456,10 +480,13 @@ struct comm_point* comm_point_create_udp_ancil(struct comm_base* base,
* @param num: becomes max_tcp_count, the routine allocates that
* many tcp handler commpoints.
* @param idle_timeout: TCP idle timeout in ms.
* @param harden_large_queries: whether query size should be limited.
* @param tcp_conn_limit: TCP connection limit info.
* @param bufsize: size of buffer to create for handlers.
* @param spoolbuf: shared spool buffer for tcp_req_info structures.
* or NULL to not create those structures in the tcp handlers.
* @param port_type: the type of port we are creating a TCP listener for. Used
* to select handler type to use.
* @param callback: callback function pointer for TCP handlers.
* @param callback_arg: will be passed to your callback function.
* @return: returns the TCP listener commpoint. You can find the
@ -468,8 +495,10 @@ struct comm_point* comm_point_create_udp_ancil(struct comm_base* base,
* Inits timeout to NULL. All handlers are on the free list.
*/
struct comm_point* comm_point_create_tcp(struct comm_base* base,
int fd, int num, int idle_timeout, struct tcl_list* tcp_conn_limit,
int fd, int num, int idle_timeout, int harden_large_queries,
struct tcl_list* tcp_conn_limit,
size_t bufsize, struct sldns_buffer* spoolbuf,
enum listen_type port_type,
comm_point_callback_type* callback, void* callback_arg);
/**
@ -723,6 +752,110 @@ void comm_point_tcp_handle_callback(int fd, short event, void* arg);
*/
void comm_point_http_handle_callback(int fd, short event, void* arg);
/**
* HTTP2 session. HTTP2 related info per comm point.
*/
struct http2_session {
/** first item in list of streams */
struct http2_stream* first_stream;
#ifdef HAVE_NGHTTP2
/** nghttp2 session */
nghttp2_session *session;
/** store nghttp2 callbacks for easy reuse */
nghttp2_session_callbacks* callbacks;
#endif
/** comm point containing buffer used to build answer in worker or
* module */
struct comm_point* c;
/** session is instructed to get dropped (comm port will be closed) */
int is_drop;
/** postpone dropping the session, can be used to prevent dropping
* while being in a callback */
int postpone_drop;
};
/** enum of HTTP status */
enum http_status {
HTTP_STATUS_OK = 200,
HTTP_STATUS_BAD_REQUEST = 400,
HTTP_STATUS_NOT_FOUND = 404,
HTTP_STATUS_PAYLOAD_TOO_LARGE = 413,
HTTP_STATUS_URI_TOO_LONG = 414,
HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE = 415,
HTTP_STATUS_NOT_IMPLEMENTED = 501
};
/**
* HTTP stream. Part of list of HTTP2 streams per session.
*/
struct http2_stream {
/** next stream in list per session */
struct http2_stream* next;
/** previous stream in list per session */
struct http2_stream* prev;
/** HTTP2 stream ID is an unsigned 31-bit integer */
int32_t stream_id;
/** HTTP method used for this stream */
enum {
HTTP_METHOD_POST = 1,
HTTP_METHOD_GET,
HTTP_METHOD_UNSUPPORTED
} http_method;
/** message contains invalid content type */
int invalid_content_type;
/** message body content type */
size_t content_length;
/** HTTP response status */
enum http_status status;
/** request for non existing endpoint */
int invalid_endpoint;
/** query in request is too large */
int query_too_large;
/** buffer to store query into. Can't use session shared buffer as query
* can arrive in parts, intertwined with frames for other queries. */
struct sldns_buffer* qbuffer;
/** buffer to store response into. Can't use shared buffer as a next
* query read callback can overwrite it before it is send out. */
struct sldns_buffer* rbuffer;
/** mesh area containing mesh state */
struct mesh_area* mesh;
/** mesh state for query. Used to remove mesh reply before closing
* stream. */
struct mesh_state* mesh_state;
};
#ifdef HAVE_NGHTTP2
/** nghttp2 receive cb. Read from SSL connection into nghttp2 buffer */
ssize_t http2_recv_cb(nghttp2_session* session, uint8_t* buf,
size_t len, int flags, void* cb_arg);
/** nghttp2 send callback. Send from nghttp2 buffer to ssl socket */
ssize_t http2_send_cb(nghttp2_session* session, const uint8_t* buf,
size_t len, int flags, void* cb_arg);
/** nghttp2 callback on closing stream */
int http2_stream_close_cb(nghttp2_session* session, int32_t stream_id,
uint32_t error_code, void* cb_arg);
#endif
/**
* Create new http2 stream
* @param stream_id: ID for stream to create.
* @return malloc'ed stream, NULL on error
*/
struct http2_stream* http2_stream_create(int32_t stream_id);
/**
* Add new stream to session linked list
* @param h2_session: http2 session to add stream to
* @param h2_stream: stream to add to session list
*/
void http2_session_add_stream(struct http2_session* h2_session,
struct http2_stream* h2_stream);
/** Add mesh state to stream. To be able to remove mesh reply on stream closure
*/
void http2_stream_add_meshstate(struct http2_stream* h2_stream,
struct mesh_area* mesh, struct mesh_state* m);
/**
* This routine is published for checks and tests, and is only used internally.
* handle libevent callback for timer comm.