struct outbound_entry*
worker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec,
int want_dnssec, int nocaps, struct sockaddr_storage* addr,
- socklen_t addrlen, uint8_t* zone, size_t zonelen, int ssl_upstream,
- char* tls_auth_name, struct module_qstate* q)
+ socklen_t addrlen, uint8_t* zone, size_t zonelen, int tcp_upstream,
+ int ssl_upstream, char* tls_auth_name, struct module_qstate* q)
{
struct worker* worker = q->env->worker;
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
return NULL;
e->qstate = q;
e->qsent = outnet_serviced_query(worker->back, qinfo, flags, dnssec,
- want_dnssec, nocaps, q->env->cfg->tcp_upstream,
+ want_dnssec, nocaps, tcp_upstream,
ssl_upstream, tls_auth_name, addr, addrlen, zone, zonelen, q,
worker_handle_service_reply, e, worker->back->udp_buff, q->env);
if(!e->qsent) {
uint16_t ATTR_UNUSED(flags), int ATTR_UNUSED(dnssec),
int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps),
struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen),
- uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen),
+ uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
struct module_qstate* ATTR_UNUSED(q))
{
.TP
.B tcp\-upstream: \fI<yes or no>
Enable or disable whether the upstream queries use TCP only for transport.
-Default is no. Useful in tunneling scenarios.
+Default is no. Useful in tunneling scenarios. If set to no you can specify
+TCP transport only for selected forward or stub zones using forward-tcp-upstream
+or stub-tcp-upstream respectively.
.TP
.B udp\-upstream\-without\-downstream: \fI<yes or no>
Enable udp upstream even if do-udp is no. Default is no, and this does not
.B stub\-ssl\-upstream: \fI<yes or no>
Alternate syntax for \fBstub\-tls\-upstream\fR.
.TP
+.B stub\-tcp\-upstream: \fI<yes or no>
+If it is set to "yes" then upstream queries use TCP only for transport regardless of global flag tcp-upstream.
+Default is no.
+.TP
.B stub\-no\-cache: \fI<yes or no>
Default is no. If enabled, data inside the stub is not cached. This is
useful when you want immediate changes to be visible.
.B forward\-ssl\-upstream: \fI<yes or no>
Alternate syntax for \fBforward\-tls\-upstream\fR.
.TP
+.B forward\-tcp\-upstream: \fI<yes or no>
+If it is set to "yes" then upstream queries use TCP only for transport regardless of global flag tcp-upstream.
+Default is no.
+.TP
.B forward\-no\-cache: \fI<yes or no>
Default is no. If enabled, data inside the forward is not cached. This is
useful when you want immediate changes to be visible.
copy->bogus = dp->bogus;
copy->has_parent_side_NS = dp->has_parent_side_NS;
copy->ssl_upstream = dp->ssl_upstream;
+ copy->tcp_upstream = dp->tcp_upstream;
for(ns = dp->nslist; ns; ns = ns->next) {
if(!delegpt_add_ns(copy, region, ns->name, ns->lame))
return NULL;
uint8_t dp_type_mlc;
/** use SSL for upstream query */
uint8_t ssl_upstream;
+ /** use TCP for upstream query */
+ uint8_t tcp_upstream;
/** delegpt from authoritative zone that is locally hosted */
uint8_t auth_dp;
/*** no cache */
dp->no_cache = s->no_cache;
/* use SSL for queries to this forwarder */
dp->ssl_upstream = (uint8_t)s->ssl_upstream;
+ /* use TCP for queries to this forwarder */
+ dp->tcp_upstream = (uint8_t)s->tcp_upstream;
verbose(VERB_QUERY, "Forward zone server list:");
delegpt_log(VERB_QUERY, dp);
if(!forwards_insert(fwd, LDNS_RR_CLASS_IN, dp))
dp->no_cache = s->no_cache;
/* ssl_upstream */
dp->ssl_upstream = (uint8_t)s->ssl_upstream;
+ /* tcp_upstream */
+ dp->tcp_upstream = (uint8_t)s->tcp_upstream;
delegpt_log(VERB_QUERY, dp);
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, !s->isprime))
return 0;
iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted(
ie, iq), &target->addr, target->addrlen,
iq->dp->name, iq->dp->namelen,
+ (iq->dp->tcp_upstream || qstate->env->cfg->tcp_upstream),
(iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream),
target->tls_auth_name, qstate);
if(!outq) {
struct outbound_entry* libworker_send_query(struct query_info* qinfo,
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
- size_t zonelen, int ssl_upstream, char* tls_auth_name,
+ size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
struct module_qstate* q)
{
struct libworker* w = (struct libworker*)q->env->worker;
return NULL;
e->qstate = q;
e->qsent = outnet_serviced_query(w->back, qinfo, flags, dnssec,
- want_dnssec, nocaps, q->env->cfg->tcp_upstream, ssl_upstream,
+ want_dnssec, nocaps, tcp_upstream, ssl_upstream,
tls_auth_name, addr, addrlen, zone, zonelen, q,
libworker_handle_service_reply, e, w->back->udp_buff, q->env);
if(!e->qsent) {
uint16_t ATTR_UNUSED(flags), int ATTR_UNUSED(dnssec),
int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps),
struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen),
- uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen),
+ uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
struct module_qstate* ATTR_UNUSED(q))
{
struct outbound_entry* libworker_send_query(struct query_info* qinfo,
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
- size_t zonelen, int ssl_upstream, char* tls_auth_name,
+ size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
struct module_qstate* q);
/** process incoming serviced query replies from the network */
struct outbound_entry* worker_send_query(struct query_info* qinfo,
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
- size_t zonelen, int ssl_upstream, char* tls_auth_name,
+ size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
struct module_qstate* q);
/**
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
- size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(ssl_upstream),
+ size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream),
char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q))
{
log_assert(0);
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
- size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(ssl_upstream),
+ size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream),
char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q))
{
log_assert(0);
--- /dev/null
+server:
+ verbosity: 5
+ # num-threads: 1
+ interface: 127.0.0.1
+ port: @PORT@
+ use-syslog: no
+ directory: ""
+ pidfile: "unbound.pid"
+ chroot: ""
+ username: ""
+ do-not-query-localhost: no
+forward-zone:
+ name: "tcp.example.com"
+ forward-addr: "127.0.0.1@@TOPORT@"
+ forward-tcp-upstream: "yes"
+forward-zone:
+ name: "udp.example.com"
+ forward-addr: "127.0.0.1@@TOPORT@"
+ forward-tcp-upstream: "no"
+
--- /dev/null
+BaseName: fwd_udp_with_tcp_upstream
+Version: 1.0
+Description: Forward an UDP packet to upstream via TCP and return reply.
+CreationDate: Thu Aug 5 07:44:41 CEST 2021
+Maintainer: ziollek
+Category:
+Component:
+CmdDepends:
+Depends:
+Help:
+Pre: fwd_udp_with_tcp_upstream.pre
+Post: fwd_udp_with_tcp_upstream.post
+Test: fwd_udp_with_tcp_upstream.test
+AuxFiles:
+Passed:
+Failure:
--- /dev/null
+# #-- fwd_udp_with_tcp_upstream.post --#
+# source the master var file when it's there
+[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
+# source the test var file when it's there
+[ -f .tpkg.var.test ] && source .tpkg.var.test
+#
+# do your teardown here
+. ../common.sh
+kill_pid $FWD_PID
+kill_pid $UNBOUND_PID
--- /dev/null
+# #-- fwd_udp_with_tcp_upstream.pre--#
+# source the master var file when it's there
+[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
+# use .tpkg.var.test for in test variable passing
+[ -f .tpkg.var.test ] && source .tpkg.var.test
+
+. ../common.sh
+get_random_port 2
+UNBOUND_PORT=$RND_PORT
+FWD_PORT=$(($RND_PORT + 1))
+echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test
+echo "FWD_PORT=$FWD_PORT" >> .tpkg.var.test
+
+# start forwarder
+get_ldns_testns
+$LDNS_TESTNS -p $FWD_PORT fwd_udp_with_tcp_upstream.testns >fwd.log 2>&1 &
+FWD_PID=$!
+echo "FWD_PID=$FWD_PID" >> .tpkg.var.test
+
+# make config file
+sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$FWD_PORT'/' < fwd_udp_with_tcp_upstream.conf > ub.conf
+# start unbound in the background
+PRE="../.."
+$PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
+UNBOUND_PID=$!
+echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
+
+cat .tpkg.var.test
+wait_ldns_testns_up fwd.log
+wait_unbound_up unbound.log
+
--- /dev/null
+# #-- fwd_udp_with_tcp_upstream.test --#
+# source the master var file when it's there
+[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
+# use .tpkg.var.test for in test variable passing
+[ -f .tpkg.var.test ] && source .tpkg.var.test
+
+PRE="../.."
+# do the test
+echo "> dig tcp.example.com."
+dig @localhost -p $UNBOUND_PORT tcp.example.com. | tee outfile
+echo "> cat logfiles"
+cat fwd.log
+cat unbound.log
+echo "> check answer"
+if grep "10.20.30.40" outfile; then
+ echo "OK"
+else
+ echo "Not OK"
+ exit 1
+fi
+
+echo "> dig udp.example.com."
+dig @localhost -p $UNBOUND_PORT udp.example.com. | tee outfile
+echo "> cat logfiles"
+cat fwd.log
+cat unbound.log
+echo "> check answer"
+if grep "10.20.30.80" outfile; then
+ echo "OK"
+else
+ echo "Not OK"
+ exit 1
+fi
+
+exit 0
--- /dev/null
+; nameserver test file
+$ORIGIN example.com.
+$TTL 3600
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+MATCH TCP
+REPLY QR AA NOERROR
+ADJUST copy_id
+SECTION QUESTION
+tcp IN A
+SECTION ANSWER
+tcp IN A 10.20.30.40
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+MATCH UDP
+REPLY QR AA NOERROR
+ADJUST copy_id
+SECTION QUESTION
+udp IN A
+SECTION ANSWER
+udp IN A 10.20.30.80
+ENTRY_END
--- /dev/null
+server:
+ verbosity: 2
+ # num-threads: 1
+ interface: 127.0.0.1
+ port: @PORT@
+ use-syslog: no
+ directory: ""
+ pidfile: "unbound.pid"
+ chroot: ""
+ username: ""
+ do-not-query-localhost: no
+stub-zone:
+ name: "tcp.example.com"
+ stub-addr: "127.0.0.1@@TOPORT@"
+ stub-tcp-upstream: "yes"
+stub-zone:
+ name: "udp.example.com"
+ stub-addr: "127.0.0.1@@TOPORT@"
+ stub-tcp-upstream: "no"
\ No newline at end of file
--- /dev/null
+BaseName: stub_udp_with_tcp_upstream
+Version: 1.0
+Description: Stub server contacted via UDP with tcp upstream.
+CreationDate: Thu Aug 5 07:44:41 CEST 2021
+Maintainer: ziollek
+Category:
+Component:
+CmdDepends:
+Depends:
+Help:
+Pre: stub_udp_with_tcp_upstream.pre
+Post: stub_udp_with_tcp_upstream.post
+Test: stub_udp_with_tcp_upstream.test
+AuxFiles:
+Passed:
+Failure:
--- /dev/null
+# #-- stub_udp_with_tcp_upstream.post --#
+# source the master var file when it's there
+[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
+# source the test var file when it's there
+[ -f .tpkg.var.test ] && source .tpkg.var.test
+#
+# do your teardown here
+. ../common.sh
+kill_pid $FWD_PID
+kill_pid $UNBOUND_PID
--- /dev/null
+# #-- stub_udp_with_tcp_upstream.pre--#
+# source the master var file when it's there
+[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
+# use .tpkg.var.test for in test variable passing
+[ -f .tpkg.var.test ] && source .tpkg.var.test
+. ../common.sh
+
+get_random_port 2
+UNBOUND_PORT=$RND_PORT
+FWD_PORT=$(($RND_PORT + 1))
+echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test
+echo "FWD_PORT=$FWD_PORT" >> .tpkg.var.test
+
+# start forwarder
+get_ldns_testns
+$LDNS_TESTNS -p $FWD_PORT stub_udp_with_tcp_upstream.testns >fwd.log 2>&1 &
+FWD_PID=$!
+echo "FWD_PID=$FWD_PID" >> .tpkg.var.test
+
+# make config file
+sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$FWD_PORT'/' < stub_udp_with_tcp_upstream.conf > ub.conf
+# start unbound in the background
+PRE="../.."
+$PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
+UNBOUND_PID=$!
+echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
+
+cat .tpkg.var.test
+
+# wait for forwarder to come up
+wait_ldns_testns_up fwd.log
+
+# wait for unbound to come up
+wait_unbound_up unbound.log
+
--- /dev/null
+# #-- stub_udp_with_tcp_upstream.test --#
+# source the master var file when it's there
+[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
+# use .tpkg.var.test for in test variable passing
+[ -f .tpkg.var.test ] && source .tpkg.var.test
+
+PRE="../.."
+# do the test
+echo "> dig tcp.example.com."
+dig @127.0.0.1 -p $UNBOUND_PORT tcp.example.com. | tee outfile
+echo "> cat logfiles"
+cat fwd.log
+cat unbound.log
+echo "> check answer"
+if grep "10.20.30.40" outfile; then
+ echo "OK"
+else
+ echo "Not OK"
+ exit 1
+fi
+
+
+# check if second stub is requested via udp
+echo "> dig udp.example.com."
+dig @127.0.0.1 -p $UNBOUND_PORT udp.example.com. | tee outfile
+echo "> cat logfiles"
+cat fwd.log
+cat unbound.log
+echo "> check answer"
+if grep "10.20.30.80" outfile; then
+ echo "OK"
+else
+ echo "Not OK"
+ exit 1
+fi
+
+exit 0
--- /dev/null
+; nameserver test file
+$ORIGIN example.com.
+$TTL 3600
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+MATCH TCP
+REPLY QR AA NOERROR
+ADJUST copy_id
+SECTION QUESTION
+tcp IN A
+SECTION ANSWER
+tcp IN A 10.20.30.40
+SECTION AUTHORITY
+@ IN NS ns.example.com.
+SECTION ADDITIONAL
+ns IN A 127.0.0.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+MATCH UDP
+REPLY QR AA NOERROR
+ADJUST copy_id
+SECTION QUESTION
+udp IN A
+SECTION ANSWER
+udp IN A 10.20.30.80
+SECTION AUTHORITY
+@ IN NS ns.example.com.
+SECTION ADDITIONAL
+ns IN A 127.0.0.1
+ENTRY_END
+
+; root prime
+ENTRY_BEGIN
+MATCH opcode qtype qname
+REPLY QR AA NOERROR
+ADJUST copy_id
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS root.server.
+SECTION AUTHORITY
+SECTION ADDITIONAL
+root.server. IN A 127.0.0.1
+ENTRY_END
+
int isprime;
/** if forward-first is set (failover to without if fails) */
int isfirst;
+ /** use tcp for queries to this stub */
+ int tcp_upstream;
/** use SSL for queries to this stub */
int ssl_upstream;
/*** no cache */
stub-no-cache{COLON} { YDVAR(1, VAR_STUB_NO_CACHE) }
stub-ssl-upstream{COLON} { YDVAR(1, VAR_STUB_SSL_UPSTREAM) }
stub-tls-upstream{COLON} { YDVAR(1, VAR_STUB_SSL_UPSTREAM) }
+stub-tcp-upstream{COLON} { YDVAR(1, VAR_STUB_TCP_UPSTREAM) }
forward-zone{COLON} { YDVAR(0, VAR_FORWARD_ZONE) }
forward-addr{COLON} { YDVAR(1, VAR_FORWARD_ADDR) }
forward-host{COLON} { YDVAR(1, VAR_FORWARD_HOST) }
forward-no-cache{COLON} { YDVAR(1, VAR_FORWARD_NO_CACHE) }
forward-ssl-upstream{COLON} { YDVAR(1, VAR_FORWARD_SSL_UPSTREAM) }
forward-tls-upstream{COLON} { YDVAR(1, VAR_FORWARD_SSL_UPSTREAM) }
+forward-tcp-upstream{COLON} { YDVAR(1, VAR_FORWARD_TCP_UPSTREAM) }
auth-zone{COLON} { YDVAR(0, VAR_AUTH_ZONE) }
rpz{COLON} { YDVAR(0, VAR_RPZ) }
tags{COLON} { YDVAR(1, VAR_TAGS) }
%token VAR_SSL_UPSTREAM VAR_TCP_AUTH_QUERY_TIMEOUT VAR_SSL_SERVICE_KEY
%token 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_STUB_TCP_UPSTREAM VAR_FORWARD_TCP_UPSTREAM
%token VAR_HTTPS_PORT VAR_HTTP_ENDPOINT VAR_HTTP_MAX_STREAMS
%token VAR_HTTP_QUERY_BUFFER_SIZE VAR_HTTP_RESPONSE_BUFFER_SIZE
%token VAR_HTTP_NODELAY VAR_HTTP_NOTLS_DOWNSTREAM
contents_stub: contents_stub content_stub
| ;
content_stub: stub_name | stub_host | stub_addr | stub_prime | stub_first |
- stub_no_cache | stub_ssl_upstream
+ stub_no_cache | stub_ssl_upstream | stub_tcp_upstream
;
forwardstart: VAR_FORWARD_ZONE
{
contents_forward: contents_forward content_forward
| ;
content_forward: forward_name | forward_host | forward_addr | forward_first |
- forward_no_cache | forward_ssl_upstream
+ forward_no_cache | forward_ssl_upstream | forward_tcp_upstream
;
viewstart: VAR_VIEW
{
free($2);
}
;
+stub_tcp_upstream: VAR_STUB_TCP_UPSTREAM STRING_ARG
+ {
+ OUTYY(("P(stub-tcp-upstream:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->stubs->tcp_upstream =
+ (strcmp($2, "yes")==0);
+ free($2);
+ }
+ ;
stub_prime: VAR_STUB_PRIME STRING_ARG
{
OUTYY(("P(stub-prime:%s)\n", $2));
free($2);
}
;
+forward_tcp_upstream: VAR_FORWARD_TCP_UPSTREAM STRING_ARG
+ {
+ OUTYY(("P(forward-tcp-upstream:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->forwards->tcp_upstream =
+ (strcmp($2, "yes")==0);
+ free($2);
+ }
+ ;
auth_name: VAR_NAME STRING_ARG
{
OUTYY(("P(name:%s)\n", $2));
fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
int nocaps, struct sockaddr_storage* addr, socklen_t addrlen,
- uint8_t* zone, size_t zonelen, int ssl_upstream, char* tls_auth_name,
+ uint8_t* zone, size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
struct module_qstate* q))
{
if(fptr == &worker_send_query) return 1;
int fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
int nocaps, struct sockaddr_storage* addr, socklen_t addrlen,
- uint8_t* zone, size_t zonelen, int ssl_upstream, char* tls_auth_name,
+ uint8_t* zone, size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
struct module_qstate* q));
/**
* @param addrlen: length of addr.
* @param zone: delegation point name.
* @param zonelen: length of zone name.
+ * @param tcp_upstream: use TCP for upstream queries.
* @param ssl_upstream: use SSL for upstream queries.
* @param tls_auth_name: if ssl_upstream, use this name with TLS
* authentication.
struct outbound_entry* (*send_query)(struct query_info* qinfo,
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
struct sockaddr_storage* addr, socklen_t addrlen,
- uint8_t* zone, size_t zonelen, int ssl_upstream,
+ uint8_t* zone, size_t zonelen, int tcp_upstream, int ssl_upstream,
char* tls_auth_name, struct module_qstate* q);
/**